1 |
|
|
/* $OpenBSD: comp_parse.c,v 1.12 2010/01/12 23:22:06 nicm Exp $ */ |
2 |
|
|
|
3 |
|
|
/**************************************************************************** |
4 |
|
|
* Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * |
5 |
|
|
* * |
6 |
|
|
* Permission is hereby granted, free of charge, to any person obtaining a * |
7 |
|
|
* copy of this software and associated documentation files (the * |
8 |
|
|
* "Software"), to deal in the Software without restriction, including * |
9 |
|
|
* without limitation the rights to use, copy, modify, merge, publish, * |
10 |
|
|
* distribute, distribute with modifications, sublicense, and/or sell * |
11 |
|
|
* copies of the Software, and to permit persons to whom the Software is * |
12 |
|
|
* furnished to do so, subject to the following conditions: * |
13 |
|
|
* * |
14 |
|
|
* The above copyright notice and this permission notice shall be included * |
15 |
|
|
* in all copies or substantial portions of the Software. * |
16 |
|
|
* * |
17 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * |
18 |
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * |
19 |
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * |
20 |
|
|
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * |
21 |
|
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * |
22 |
|
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * |
23 |
|
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. * |
24 |
|
|
* * |
25 |
|
|
* Except as contained in this notice, the name(s) of the above copyright * |
26 |
|
|
* holders shall not be used in advertising or otherwise to promote the * |
27 |
|
|
* sale, use or other dealings in this Software without prior written * |
28 |
|
|
* authorization. * |
29 |
|
|
****************************************************************************/ |
30 |
|
|
|
31 |
|
|
/**************************************************************************** |
32 |
|
|
* Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * |
33 |
|
|
* and: Eric S. Raymond <esr@snark.thyrsus.com> * |
34 |
|
|
* and: Thomas E. Dickey 1996-on * |
35 |
|
|
****************************************************************************/ |
36 |
|
|
|
37 |
|
|
/* |
38 |
|
|
* comp_parse.c -- parser driver loop and use handling. |
39 |
|
|
* |
40 |
|
|
* _nc_read_entry_source(FILE *, literal, bool, bool (*hook)()) |
41 |
|
|
* _nc_resolve_uses2(void) |
42 |
|
|
* _nc_free_entries(void) |
43 |
|
|
* |
44 |
|
|
* Use this code by calling _nc_read_entry_source() on as many source |
45 |
|
|
* files as you like (either terminfo or termcap syntax). If you |
46 |
|
|
* want use-resolution, call _nc_resolve_uses2(). To free the list |
47 |
|
|
* storage, do _nc_free_entries(). |
48 |
|
|
* |
49 |
|
|
*/ |
50 |
|
|
|
51 |
|
|
#include <curses.priv.h> |
52 |
|
|
|
53 |
|
|
#include <ctype.h> |
54 |
|
|
|
55 |
|
|
#include <tic.h> |
56 |
|
|
#include <term_entry.h> |
57 |
|
|
|
58 |
|
|
MODULE_ID("$Id: comp_parse.c,v 1.12 2010/01/12 23:22:06 nicm Exp $") |
59 |
|
|
|
60 |
|
|
static void sanity_check2(TERMTYPE *, bool); |
61 |
|
|
NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype2) (TERMTYPE *, bool) = sanity_check2; |
62 |
|
|
|
63 |
|
|
/* obsolete: 20040705 */ |
64 |
|
|
static void sanity_check(TERMTYPE *); |
65 |
|
|
NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype) (TERMTYPE *) = sanity_check; |
66 |
|
|
|
67 |
|
|
static void |
68 |
|
|
enqueue(ENTRY * ep) |
69 |
|
|
/* add an entry to the in-core list */ |
70 |
|
|
{ |
71 |
|
|
ENTRY *newp = _nc_copy_entry(ep); |
72 |
|
|
|
73 |
|
|
if (newp == 0) |
74 |
|
|
_nc_err_abort(MSG_NO_MEMORY); |
75 |
|
|
|
76 |
|
|
newp->last = _nc_tail; |
77 |
|
|
_nc_tail = newp; |
78 |
|
|
|
79 |
|
|
newp->next = 0; |
80 |
|
|
if (newp->last) |
81 |
|
|
newp->last->next = newp; |
82 |
|
|
} |
83 |
|
|
|
84 |
|
|
static char * |
85 |
|
|
force_bar(char *dst, char *src, size_t siz) |
86 |
|
|
{ |
87 |
|
|
if (strchr(src, '|') == 0) { |
88 |
|
|
size_t len; |
89 |
|
|
|
90 |
|
|
len = strlcpy(dst, src, siz); |
91 |
|
|
if (len > siz - 2) |
92 |
|
|
len = siz - 2; |
93 |
|
|
dst[len++] = '|'; |
94 |
|
|
dst[len] = '\0'; |
95 |
|
|
src = dst; |
96 |
|
|
} |
97 |
|
|
return src; |
98 |
|
|
} |
99 |
|
|
|
100 |
|
|
NCURSES_EXPORT(bool) |
101 |
|
|
_nc_entry_match(char *n1, char *n2) |
102 |
|
|
/* do any of the aliases in a pair of terminal names match? */ |
103 |
|
|
{ |
104 |
|
|
char *pstart, *qstart, *pend, *qend; |
105 |
|
|
char nc1[MAX_NAME_SIZE + 2], nc2[MAX_NAME_SIZE + 2]; |
106 |
|
|
|
107 |
|
|
n1 = force_bar(nc1, n1, sizeof(nc1)); |
108 |
|
|
n2 = force_bar(nc2, n2, sizeof(nc2)); |
109 |
|
|
|
110 |
|
|
for (pstart = n1; (pend = strchr(pstart, '|')); pstart = pend + 1) |
111 |
|
|
for (qstart = n2; (qend = strchr(qstart, '|')); qstart = qend + 1) |
112 |
|
|
if ((pend - pstart == qend - qstart) |
113 |
|
|
&& memcmp(pstart, qstart, (size_t) (pend - pstart)) == 0) |
114 |
|
|
return (TRUE); |
115 |
|
|
|
116 |
|
|
return (FALSE); |
117 |
|
|
} |
118 |
|
|
|
119 |
|
|
/**************************************************************************** |
120 |
|
|
* |
121 |
|
|
* Entry compiler and resolution logic |
122 |
|
|
* |
123 |
|
|
****************************************************************************/ |
124 |
|
|
|
125 |
|
|
NCURSES_EXPORT(void) |
126 |
|
|
_nc_read_entry_source(FILE *fp, char *buf, |
127 |
|
|
int literal, bool silent, |
128 |
|
|
bool(*hook) (ENTRY *)) |
129 |
|
|
/* slurp all entries in the given file into core */ |
130 |
|
|
{ |
131 |
|
|
ENTRY thisentry; |
132 |
|
|
bool oldsuppress = _nc_suppress_warnings; |
133 |
|
|
int immediate = 0; |
134 |
|
|
|
135 |
|
|
if (silent) |
136 |
|
|
_nc_suppress_warnings = TRUE; /* shut the lexer up, too */ |
137 |
|
|
|
138 |
|
|
_nc_reset_input(fp, buf); |
139 |
|
|
for (;;) { |
140 |
|
|
memset(&thisentry, 0, sizeof(thisentry)); |
141 |
|
|
if (_nc_parse_entry(&thisentry, literal, silent) == ERR) |
142 |
|
|
break; |
143 |
|
|
if (!isalnum(UChar(thisentry.tterm.term_names[0]))) |
144 |
|
|
_nc_err_abort("terminal names must start with letter or digit"); |
145 |
|
|
|
146 |
|
|
/* |
147 |
|
|
* This can be used for immediate compilation of entries with no "use=" |
148 |
|
|
* references to disk. That avoids consuming a lot of memory when the |
149 |
|
|
* resolution code could fetch entries off disk. |
150 |
|
|
*/ |
151 |
|
|
if (hook != NULLHOOK && (*hook) (&thisentry)) { |
152 |
|
|
immediate++; |
153 |
|
|
} else { |
154 |
|
|
enqueue(&thisentry); |
155 |
|
|
/* |
156 |
|
|
* The enqueued entry is copied with _nc_copy_termtype(), so we can |
157 |
|
|
* free some of the data from thisentry, i.e., the arrays. |
158 |
|
|
*/ |
159 |
|
|
FreeIfNeeded(thisentry.tterm.Booleans); |
160 |
|
|
FreeIfNeeded(thisentry.tterm.Numbers); |
161 |
|
|
FreeIfNeeded(thisentry.tterm.Strings); |
162 |
|
|
#if NCURSES_XNAMES |
163 |
|
|
FreeIfNeeded(thisentry.tterm.ext_Names); |
164 |
|
|
#endif |
165 |
|
|
} |
166 |
|
|
} |
167 |
|
|
|
168 |
|
|
if (_nc_tail) { |
169 |
|
|
/* set up the head pointer */ |
170 |
|
|
for (_nc_head = _nc_tail; _nc_head->last; _nc_head = _nc_head->last) |
171 |
|
|
continue; |
172 |
|
|
|
173 |
|
|
DEBUG(1, ("head = %s", _nc_head->tterm.term_names)); |
174 |
|
|
DEBUG(1, ("tail = %s", _nc_tail->tterm.term_names)); |
175 |
|
|
} |
176 |
|
|
#ifdef TRACE |
177 |
|
|
else if (!immediate) |
178 |
|
|
DEBUG(1, ("no entries parsed")); |
179 |
|
|
#endif |
180 |
|
|
|
181 |
|
|
_nc_suppress_warnings = oldsuppress; |
182 |
|
|
} |
183 |
|
|
|
184 |
|
|
NCURSES_EXPORT(int) |
185 |
|
|
_nc_resolve_uses2(bool fullresolve, bool literal) |
186 |
|
|
/* try to resolve all use capabilities */ |
187 |
|
|
{ |
188 |
|
|
ENTRY *qp, *rp, *lastread = 0; |
189 |
|
|
bool keepgoing; |
190 |
|
|
unsigned i; |
191 |
|
|
int unresolved, total_unresolved, multiples; |
192 |
|
|
|
193 |
|
|
DEBUG(2, ("RESOLUTION BEGINNING")); |
194 |
|
|
|
195 |
|
|
/* |
196 |
|
|
* Check for multiple occurrences of the same name. |
197 |
|
|
*/ |
198 |
|
|
multiples = 0; |
199 |
|
|
for_entry_list(qp) { |
200 |
|
|
int matchcount = 0; |
201 |
|
|
|
202 |
|
|
for_entry_list(rp) { |
203 |
|
|
if (qp > rp |
204 |
|
|
&& _nc_entry_match(qp->tterm.term_names, rp->tterm.term_names)) { |
205 |
|
|
matchcount++; |
206 |
|
|
if (matchcount == 1) { |
207 |
|
|
(void) fprintf(stderr, "Name collision between %s", |
208 |
|
|
_nc_first_name(qp->tterm.term_names)); |
209 |
|
|
multiples++; |
210 |
|
|
} |
211 |
|
|
if (matchcount >= 1) |
212 |
|
|
(void) fprintf(stderr, " %s", _nc_first_name(rp->tterm.term_names)); |
213 |
|
|
} |
214 |
|
|
} |
215 |
|
|
if (matchcount >= 1) |
216 |
|
|
(void) putc('\n', stderr); |
217 |
|
|
} |
218 |
|
|
if (multiples > 0) |
219 |
|
|
return (FALSE); |
220 |
|
|
|
221 |
|
|
DEBUG(2, ("NO MULTIPLE NAME OCCURRENCES")); |
222 |
|
|
|
223 |
|
|
/* |
224 |
|
|
* First resolution stage: compute link pointers corresponding to names. |
225 |
|
|
*/ |
226 |
|
|
total_unresolved = 0; |
227 |
|
|
_nc_curr_col = -1; |
228 |
|
|
for_entry_list(qp) { |
229 |
|
|
unresolved = 0; |
230 |
|
|
for (i = 0; i < qp->nuses; i++) { |
231 |
|
|
bool foundit; |
232 |
|
|
char *child = _nc_first_name(qp->tterm.term_names); |
233 |
|
|
char *lookfor = qp->uses[i].name; |
234 |
|
|
long lookline = qp->uses[i].line; |
235 |
|
|
|
236 |
|
|
foundit = FALSE; |
237 |
|
|
|
238 |
|
|
_nc_set_type(child); |
239 |
|
|
|
240 |
|
|
/* first, try to resolve from in-core records */ |
241 |
|
|
for_entry_list(rp) { |
242 |
|
|
if (rp != qp |
243 |
|
|
&& _nc_name_match(rp->tterm.term_names, lookfor, "|")) { |
244 |
|
|
DEBUG(2, ("%s: resolving use=%s (in core)", |
245 |
|
|
child, lookfor)); |
246 |
|
|
|
247 |
|
|
qp->uses[i].link = rp; |
248 |
|
|
foundit = TRUE; |
249 |
|
|
} |
250 |
|
|
} |
251 |
|
|
|
252 |
|
|
/* if that didn't work, try to merge in a compiled entry */ |
253 |
|
|
if (!foundit) { |
254 |
|
|
TERMTYPE thisterm; |
255 |
|
|
char filename[PATH_MAX]; |
256 |
|
|
|
257 |
|
|
memset(&thisterm, 0, sizeof(thisterm)); |
258 |
|
|
if (_nc_read_entry(lookfor, filename, &thisterm) == 1) { |
259 |
|
|
DEBUG(2, ("%s: resolving use=%s (compiled)", |
260 |
|
|
child, lookfor)); |
261 |
|
|
|
262 |
|
|
rp = typeMalloc(ENTRY, 1); |
263 |
|
|
if (rp == 0) |
264 |
|
|
_nc_err_abort(MSG_NO_MEMORY); |
265 |
|
|
rp->tterm = thisterm; |
266 |
|
|
rp->nuses = 0; |
267 |
|
|
rp->next = lastread; |
268 |
|
|
lastread = rp; |
269 |
|
|
|
270 |
|
|
qp->uses[i].link = rp; |
271 |
|
|
foundit = TRUE; |
272 |
|
|
} |
273 |
|
|
} |
274 |
|
|
|
275 |
|
|
/* no good, mark this one unresolvable and complain */ |
276 |
|
|
if (!foundit) { |
277 |
|
|
unresolved++; |
278 |
|
|
total_unresolved++; |
279 |
|
|
|
280 |
|
|
_nc_curr_line = lookline; |
281 |
|
|
_nc_warning("resolution of use=%s failed", lookfor); |
282 |
|
|
qp->uses[i].link = 0; |
283 |
|
|
} |
284 |
|
|
} |
285 |
|
|
} |
286 |
|
|
if (total_unresolved) { |
287 |
|
|
/* free entries read in off disk */ |
288 |
|
|
_nc_free_entries(lastread); |
289 |
|
|
return (FALSE); |
290 |
|
|
} |
291 |
|
|
|
292 |
|
|
DEBUG(2, ("NAME RESOLUTION COMPLETED OK")); |
293 |
|
|
|
294 |
|
|
/* |
295 |
|
|
* OK, at this point all (char *) references in `name' members |
296 |
|
|
* have been successfully converted to (ENTRY *) pointers in |
297 |
|
|
* `link' members. Time to do the actual merges. |
298 |
|
|
*/ |
299 |
|
|
if (fullresolve) { |
300 |
|
|
do { |
301 |
|
|
TERMTYPE merged; |
302 |
|
|
|
303 |
|
|
keepgoing = FALSE; |
304 |
|
|
|
305 |
|
|
for_entry_list(qp) { |
306 |
|
|
if (qp->nuses > 0) { |
307 |
|
|
DEBUG(2, ("%s: attempting merge", |
308 |
|
|
_nc_first_name(qp->tterm.term_names))); |
309 |
|
|
/* |
310 |
|
|
* If any of the use entries we're looking for is |
311 |
|
|
* incomplete, punt. We'll catch this entry on a |
312 |
|
|
* subsequent pass. |
313 |
|
|
*/ |
314 |
|
|
for (i = 0; i < qp->nuses; i++) |
315 |
|
|
if (qp->uses[i].link->nuses) { |
316 |
|
|
DEBUG(2, ("%s: use entry %d unresolved", |
317 |
|
|
_nc_first_name(qp->tterm.term_names), i)); |
318 |
|
|
goto incomplete; |
319 |
|
|
} |
320 |
|
|
|
321 |
|
|
/* |
322 |
|
|
* First, make sure there is no garbage in the |
323 |
|
|
* merge block. As a side effect, copy into |
324 |
|
|
* the merged entry the name field and string |
325 |
|
|
* table pointer. |
326 |
|
|
*/ |
327 |
|
|
_nc_copy_termtype(&merged, &(qp->tterm)); |
328 |
|
|
|
329 |
|
|
/* |
330 |
|
|
* Now merge in each use entry in the proper |
331 |
|
|
* (reverse) order. |
332 |
|
|
*/ |
333 |
|
|
for (; qp->nuses; qp->nuses--) |
334 |
|
|
_nc_merge_entry(&merged, |
335 |
|
|
&qp->uses[qp->nuses - 1].link->tterm); |
336 |
|
|
|
337 |
|
|
/* |
338 |
|
|
* Now merge in the original entry. |
339 |
|
|
*/ |
340 |
|
|
_nc_merge_entry(&merged, &qp->tterm); |
341 |
|
|
|
342 |
|
|
/* |
343 |
|
|
* Replace the original entry with the merged one. |
344 |
|
|
*/ |
345 |
|
|
FreeIfNeeded(qp->tterm.Booleans); |
346 |
|
|
FreeIfNeeded(qp->tterm.Numbers); |
347 |
|
|
FreeIfNeeded(qp->tterm.Strings); |
348 |
|
|
#if NCURSES_XNAMES |
349 |
|
|
FreeIfNeeded(qp->tterm.ext_Names); |
350 |
|
|
#endif |
351 |
|
|
qp->tterm = merged; |
352 |
|
|
_nc_wrap_entry(qp, TRUE); |
353 |
|
|
|
354 |
|
|
/* |
355 |
|
|
* We know every entry is resolvable because name resolution |
356 |
|
|
* didn't bomb. So go back for another pass. |
357 |
|
|
*/ |
358 |
|
|
/* FALLTHRU */ |
359 |
|
|
incomplete: |
360 |
|
|
keepgoing = TRUE; |
361 |
|
|
} |
362 |
|
|
} |
363 |
|
|
} while |
364 |
|
|
(keepgoing); |
365 |
|
|
|
366 |
|
|
DEBUG(2, ("MERGES COMPLETED OK")); |
367 |
|
|
} |
368 |
|
|
|
369 |
|
|
/* |
370 |
|
|
* We'd like to free entries read in off disk at this point, but can't. |
371 |
|
|
* The merge_entry() code doesn't copy the strings in the use entries, |
372 |
|
|
* it just aliases them. If this ever changes, do a |
373 |
|
|
* free_entries(lastread) here. |
374 |
|
|
*/ |
375 |
|
|
|
376 |
|
|
DEBUG(2, ("RESOLUTION FINISHED")); |
377 |
|
|
|
378 |
|
|
if (fullresolve) |
379 |
|
|
if (_nc_check_termtype != 0) { |
380 |
|
|
_nc_curr_col = -1; |
381 |
|
|
for_entry_list(qp) { |
382 |
|
|
_nc_curr_line = qp->startline; |
383 |
|
|
_nc_set_type(_nc_first_name(qp->tterm.term_names)); |
384 |
|
|
_nc_check_termtype2(&qp->tterm, literal); |
385 |
|
|
} |
386 |
|
|
DEBUG(2, ("SANITY CHECK FINISHED")); |
387 |
|
|
} |
388 |
|
|
|
389 |
|
|
return (TRUE); |
390 |
|
|
} |
391 |
|
|
|
392 |
|
|
/* obsolete: 20040705 */ |
393 |
|
|
NCURSES_EXPORT(int) |
394 |
|
|
_nc_resolve_uses(bool fullresolve) |
395 |
|
|
{ |
396 |
|
|
return _nc_resolve_uses2(fullresolve, FALSE); |
397 |
|
|
} |
398 |
|
|
|
399 |
|
|
/* |
400 |
|
|
* This bit of legerdemain turns all the terminfo variable names into |
401 |
|
|
* references to locations in the arrays Booleans, Numbers, and Strings --- |
402 |
|
|
* precisely what's needed. |
403 |
|
|
*/ |
404 |
|
|
|
405 |
|
|
#undef CUR |
406 |
|
|
#define CUR tp-> |
407 |
|
|
|
408 |
|
|
static void |
409 |
|
|
sanity_check2(TERMTYPE *tp, bool literal) |
410 |
|
|
{ |
411 |
|
|
if (!PRESENT(exit_attribute_mode)) { |
412 |
|
|
#ifdef __UNUSED__ /* this casts too wide a net */ |
413 |
|
|
bool terminal_entry = !strchr(tp->term_names, '+'); |
414 |
|
|
if (terminal_entry && |
415 |
|
|
(PRESENT(set_attributes) |
416 |
|
|
|| PRESENT(enter_standout_mode) |
417 |
|
|
|| PRESENT(enter_underline_mode) |
418 |
|
|
|| PRESENT(enter_blink_mode) |
419 |
|
|
|| PRESENT(enter_bold_mode) |
420 |
|
|
|| PRESENT(enter_dim_mode) |
421 |
|
|
|| PRESENT(enter_secure_mode) |
422 |
|
|
|| PRESENT(enter_protected_mode) |
423 |
|
|
|| PRESENT(enter_reverse_mode))) |
424 |
|
|
_nc_warning("no exit_attribute_mode"); |
425 |
|
|
#endif /* __UNUSED__ */ |
426 |
|
|
PAIRED(enter_standout_mode, exit_standout_mode); |
427 |
|
|
PAIRED(enter_underline_mode, exit_underline_mode); |
428 |
|
|
} |
429 |
|
|
|
430 |
|
|
/* we do this check/fix in postprocess_termcap(), but some packagers |
431 |
|
|
* prefer to bypass it... |
432 |
|
|
*/ |
433 |
|
|
if (!literal) { |
434 |
|
|
if (acs_chars == 0 |
435 |
|
|
&& enter_alt_charset_mode != 0 |
436 |
|
|
&& exit_alt_charset_mode != 0) |
437 |
|
|
acs_chars = strdup(VT_ACSC); |
438 |
|
|
ANDMISSING(enter_alt_charset_mode, acs_chars); |
439 |
|
|
ANDMISSING(exit_alt_charset_mode, acs_chars); |
440 |
|
|
} |
441 |
|
|
|
442 |
|
|
/* listed in structure-member order of first argument */ |
443 |
|
|
PAIRED(enter_alt_charset_mode, exit_alt_charset_mode); |
444 |
|
|
ANDMISSING(enter_blink_mode, exit_attribute_mode); |
445 |
|
|
ANDMISSING(enter_bold_mode, exit_attribute_mode); |
446 |
|
|
PAIRED(exit_ca_mode, enter_ca_mode); |
447 |
|
|
PAIRED(enter_delete_mode, exit_delete_mode); |
448 |
|
|
ANDMISSING(enter_dim_mode, exit_attribute_mode); |
449 |
|
|
PAIRED(enter_insert_mode, exit_insert_mode); |
450 |
|
|
ANDMISSING(enter_secure_mode, exit_attribute_mode); |
451 |
|
|
ANDMISSING(enter_protected_mode, exit_attribute_mode); |
452 |
|
|
ANDMISSING(enter_reverse_mode, exit_attribute_mode); |
453 |
|
|
PAIRED(from_status_line, to_status_line); |
454 |
|
|
PAIRED(meta_off, meta_on); |
455 |
|
|
|
456 |
|
|
PAIRED(prtr_on, prtr_off); |
457 |
|
|
PAIRED(save_cursor, restore_cursor); |
458 |
|
|
PAIRED(enter_xon_mode, exit_xon_mode); |
459 |
|
|
PAIRED(enter_am_mode, exit_am_mode); |
460 |
|
|
ANDMISSING(label_off, label_on); |
461 |
|
|
#ifdef remove_clock |
462 |
|
|
PAIRED(display_clock, remove_clock); |
463 |
|
|
#endif |
464 |
|
|
ANDMISSING(set_color_pair, initialize_pair); |
465 |
|
|
} |
466 |
|
|
|
467 |
|
|
/* obsolete: 20040705 */ |
468 |
|
|
static void |
469 |
|
|
sanity_check(TERMTYPE *tp) |
470 |
|
|
{ |
471 |
|
|
sanity_check2(tp, FALSE); |
472 |
|
|
} |
473 |
|
|
|
474 |
|
|
#if NO_LEAKS |
475 |
|
|
NCURSES_EXPORT(void) |
476 |
|
|
_nc_leaks_tic(void) |
477 |
|
|
{ |
478 |
|
|
_nc_alloc_entry_leaks(); |
479 |
|
|
_nc_captoinfo_leaks(); |
480 |
|
|
_nc_comp_captab_leaks(); |
481 |
|
|
_nc_comp_scan_leaks(); |
482 |
|
|
#if BROKEN_LINKER || USE_REENTRANT |
483 |
|
|
_nc_names_leaks(); |
484 |
|
|
_nc_codes_leaks(); |
485 |
|
|
#endif |
486 |
|
|
_nc_tic_expand(0, FALSE, 0); |
487 |
|
|
} |
488 |
|
|
|
489 |
|
|
NCURSES_EXPORT(void) |
490 |
|
|
_nc_free_tic(int code) |
491 |
|
|
{ |
492 |
|
|
_nc_leaks_tic(); |
493 |
|
|
_nc_free_tinfo(code); |
494 |
|
|
} |
495 |
|
|
#endif |