X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Fcomp_parse.c;h=a1f9f4a877fb634cec5bc3a04fe48a9b97e7ce43;hp=667b3257f25a4a806571263ad0c2c8a6f1c198b2;hb=af4c589f0c605e1a1dd3825678a0b1a97df02d37;hpb=027ae42953e3186daed8f3882da73de48291b606 diff --git a/ncurses/tinfo/comp_parse.c b/ncurses/tinfo/comp_parse.c index 667b3257..a1f9f4a8 100644 --- a/ncurses/tinfo/comp_parse.c +++ b/ncurses/tinfo/comp_parse.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * + * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -35,15 +35,10 @@ /* * comp_parse.c -- parser driver loop and use handling. * - * _nc_read_entry_source(FILE *, literal, bool, bool (*hook)()) - * _nc_resolve_uses2(void) - * _nc_free_entries(void) - * * Use this code by calling _nc_read_entry_source() on as many source * files as you like (either terminfo or termcap syntax). If you * want use-resolution, call _nc_resolve_uses2(). To free the list * storage, do _nc_free_entries(). - * */ #include @@ -51,9 +46,8 @@ #include #include -#include -MODULE_ID("$Id: comp_parse.c,v 1.63 2006/07/08 18:55:14 tom Exp $") +MODULE_ID("$Id: comp_parse.c,v 1.77 2011/10/01 22:43:51 tom Exp $") static void sanity_check2(TERMTYPE *, bool); NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype2) (TERMTYPE *, bool) = sanity_check2; @@ -62,29 +56,7 @@ NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype2) (TERMTYPE *, bool) = sanit static void sanity_check(TERMTYPE *); NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype) (TERMTYPE *) = sanity_check; -/**************************************************************************** - * - * Entry queue handling - * - ****************************************************************************/ -/* - * The entry list is a doubly linked list with NULLs terminating the lists: - * - * --------- --------- --------- - * | | | | | | offset - * |-------| |-------| |-------| - * | ----+-->| ----+-->| NULL | next - * |-------| |-------| |-------| - * | NULL |<--+---- |<--+---- | last - * --------- --------- --------- - * ^ ^ - * | | - * | | - * _nc_head _nc_tail - */ - -NCURSES_EXPORT_VAR(ENTRY *) _nc_head = 0; -NCURSES_EXPORT_VAR(ENTRY *) _nc_tail = 0; +static void fixup_acsc(TERMTYPE *, bool); static void enqueue(ENTRY * ep) @@ -103,82 +75,134 @@ enqueue(ENTRY * ep) newp->last->next = newp; } -NCURSES_EXPORT(void) -_nc_free_entries(ENTRY * headp) -/* free the allocated storage consumed by list entries */ +static char * +force_bar(char *dst, char *src) { - (void) headp; /* unused - _nc_head is altered here! */ - - while (_nc_head != 0) { - _nc_free_termtype(&(_nc_head->tterm)); + if (strchr(src, '|') == 0) { + size_t len = strlen(src); + if (len > MAX_NAME_SIZE) + len = MAX_NAME_SIZE; + (void) strncpy(dst, src, len); + (void) strcpy(dst + len, "|"); + src = dst; } + return src; } +#define ForceBar(dst, src) ((strchr(src, '|') == 0) ? force_bar(dst, src) : src) -NCURSES_EXPORT(ENTRY *) -_nc_delink_entry(ENTRY * headp, TERMTYPE *tterm) -/* delink the allocated storage for the given list entry */ +#if USE_TERMCAP && NCURSES_XNAMES +static char * +skip_index(char *name) { - ENTRY *ep, *last; + char *bar = strchr(name, '|'); - for (last = 0, ep = headp; ep != 0; last = ep, ep = ep->next) { - if (&(ep->tterm) == tterm) { - if (last != 0) { - last->next = ep->next; - } - if (ep == _nc_head) { - _nc_head = ep->next; - } - if (ep == _nc_tail) { - _nc_tail = last; + if (bar != 0 && (bar - name) == 2) + name = bar + 1; + + return name; +} +#endif + +static bool +check_collisions(char *n1, char *n2, int counter) +{ + char *pstart, *qstart, *pend, *qend; + char nc1[MAX_NAME_SIZE + 2]; + char nc2[MAX_NAME_SIZE + 2]; + + n1 = ForceBar(nc1, n1); + n2 = ForceBar(nc2, n2); + +#if USE_TERMCAP && NCURSES_XNAMES + if ((_nc_syntax == SYN_TERMCAP) && _nc_user_definable) { + n1 = skip_index(n1); + n2 = skip_index(n2); + } +#endif + + for (pstart = n1; (pend = strchr(pstart, '|')); pstart = pend + 1) { + for (qstart = n2; (qend = strchr(qstart, '|')); qstart = qend + 1) { + if ((pend - pstart == qend - qstart) + && memcmp(pstart, qstart, (size_t) (pend - pstart)) == 0) { + if (counter > 0) + (void) fprintf(stderr, "Name collision '%.*s' between\n", + (int) (pend - pstart), pstart); + return (TRUE); } - break; } } - return ep; + + return (FALSE); } -NCURSES_EXPORT(void) -_nc_free_entry(ENTRY * headp, TERMTYPE *tterm) -/* free the allocated storage consumed by the given list entry */ +static char * +next_name(char *name) { - ENTRY *ep; - - if ((ep = _nc_delink_entry(headp, tterm)) != 0) { - free(ep); - } + if (*name != '\0') + ++name; + return name; } static char * -force_bar(char *dst, char *src) +name_ending(char *name) { - if (strchr(src, '|') == 0) { - size_t len = strlen(src); - if (len > MAX_NAME_SIZE) - len = MAX_NAME_SIZE; - (void) strncpy(dst, src, len); - (void) strcpy(dst + len, "|"); - src = dst; + if (*name == '\0') { + name = 0; + } else { + while (*name != '\0' && *name != '|') + ++name; } - return src; + return name; } -NCURSES_EXPORT(bool) -_nc_entry_match(char *n1, char *n2) -/* do any of the aliases in a pair of terminal names match? */ +/* + * Essentially, find the conflict reported in check_collisions() and remove + * it from the second name, unless that happens to be the last alias. + */ +static bool +remove_collision(char *n1, char *n2) { + char *p1 = n1; + char *p2 = n2; char *pstart, *qstart, *pend, *qend; - char nc1[MAX_NAME_SIZE + 2], nc2[MAX_NAME_SIZE + 2]; + bool removed = FALSE; - n1 = force_bar(nc1, n1); - n2 = force_bar(nc2, n2); +#if USE_TERMCAP && NCURSES_XNAMES + if ((_nc_syntax == SYN_TERMCAP) && _nc_user_definable) { + p1 = n1 = skip_index(n1); + p2 = n2 = skip_index(n2); + } +#else + (void) p1; +#endif - for (pstart = n1; (pend = strchr(pstart, '|')); pstart = pend + 1) - for (qstart = n2; (qend = strchr(qstart, '|')); qstart = qend + 1) + for (pstart = n1; (pend = name_ending(pstart)); pstart = next_name(pend)) { + for (qstart = n2; (qend = name_ending(qstart)); qstart = next_name(qend)) { if ((pend - pstart == qend - qstart) - && memcmp(pstart, qstart, (size_t) (pend - pstart)) == 0) - return (TRUE); + && memcmp(pstart, qstart, (size_t) (pend - pstart)) == 0) { + if (qstart != p2 || *qend == '|') { + if (*qend == '|') + ++qend; + while ((*qstart++ = *qend++) != '\0') ; + fprintf(stderr, "...now\t%s\n", p2); + } else { + fprintf(stderr, "Cannot remove alias '%.*s'\n", + (int) (qend - qstart), qstart); + } + removed = TRUE; + break; + } + } + } - return (FALSE); + return removed; +} + +/* do any of the aliases in a pair of terminal names match? */ +NCURSES_EXPORT(bool) +_nc_entry_match(char *n1, char *n2) +{ + return check_collisions(n1, n2, 0); } /**************************************************************************** @@ -252,7 +276,8 @@ _nc_resolve_uses2(bool fullresolve, bool literal) { ENTRY *qp, *rp, *lastread = 0; bool keepgoing; - int i, unresolved, total_unresolved, multiples; + unsigned i; + int unresolved, total_unresolved, multiples; DEBUG(2, ("RESOLUTION BEGINNING")); @@ -265,19 +290,19 @@ _nc_resolve_uses2(bool fullresolve, bool literal) for_entry_list(rp) { if (qp > rp - && _nc_entry_match(qp->tterm.term_names, rp->tterm.term_names)) { - matchcount++; - if (matchcount == 1) { - (void) fprintf(stderr, "Name collision between %s", - _nc_first_name(qp->tterm.term_names)); - multiples++; + && check_collisions(qp->tterm.term_names, + rp->tterm.term_names, + matchcount + 1)) { + if (!matchcount++) { + (void) fprintf(stderr, "\t%s\n", rp->tterm.term_names); + } + (void) fprintf(stderr, "and\t%s\n", qp->tterm.term_names); + if (!remove_collision(rp->tterm.term_names, + qp->tterm.term_names)) { + ++multiples; } - if (matchcount >= 1) - (void) fprintf(stderr, " %s", _nc_first_name(rp->tterm.term_names)); } } - if (matchcount >= 1) - (void) putc('\n', stderr); } if (multiples > 0) return (FALSE); @@ -341,7 +366,7 @@ _nc_resolve_uses2(bool fullresolve, bool literal) unresolved++; total_unresolved++; - _nc_curr_line = lookline; + _nc_curr_line = (int) lookline; _nc_warning("resolution of use=%s failed", lookfor); qp->uses[i].link = 0; } @@ -443,9 +468,9 @@ _nc_resolve_uses2(bool fullresolve, bool literal) if (_nc_check_termtype != 0) { _nc_curr_col = -1; for_entry_list(qp) { - _nc_curr_line = qp->startline; + _nc_curr_line = (int) qp->startline; _nc_set_type(_nc_first_name(qp->tterm.term_names)); - _nc_check_termtype2(&qp->tterm, literal); + fixup_acsc(&qp->tterm, literal); } DEBUG(2, ("SANITY CHECK FINISHED")); } @@ -469,6 +494,17 @@ _nc_resolve_uses(bool fullresolve) #undef CUR #define CUR tp-> +static void +fixup_acsc(TERMTYPE *tp, bool literal) +{ + if (!literal) { + if (acs_chars == 0 + && enter_alt_charset_mode != 0 + && exit_alt_charset_mode != 0) + acs_chars = strdup(VT_ACSC); + } +} + static void sanity_check2(TERMTYPE *tp, bool literal) { @@ -495,10 +531,7 @@ sanity_check2(TERMTYPE *tp, bool literal) * prefer to bypass it... */ if (!literal) { - if (acs_chars == 0 - && enter_alt_charset_mode != 0 - && exit_alt_charset_mode != 0) - acs_chars = strdup(VT_ACSC); + fixup_acsc(tp, literal); ANDMISSING(enter_alt_charset_mode, acs_chars); ANDMISSING(exit_alt_charset_mode, acs_chars); } @@ -534,3 +567,25 @@ sanity_check(TERMTYPE *tp) { sanity_check2(tp, FALSE); } + +#if NO_LEAKS +NCURSES_EXPORT(void) +_nc_leaks_tic(void) +{ + _nc_alloc_entry_leaks(); + _nc_captoinfo_leaks(); + _nc_comp_scan_leaks(); +#if BROKEN_LINKER || USE_REENTRANT + _nc_names_leaks(); + _nc_codes_leaks(); +#endif + _nc_tic_expand(0, FALSE, 0); +} + +NCURSES_EXPORT(void) +_nc_free_tic(int code) +{ + _nc_leaks_tic(); + _nc_free_tinfo(code); +} +#endif