X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Fcomp_parse.c;h=b97332ebc990c007f33975cfdc4eca57ac1db062;hp=7284b02d51bf79bd9038d06cf5ac05a566b62505;hb=b93d96b78ac5250135975df892cee793dc3c0797;hpb=93ed44d781ca36f55021e0ad55f1ce33de62f7ba diff --git a/ncurses/tinfo/comp_parse.c b/ncurses/tinfo/comp_parse.c index 7284b02d..b97332eb 100644 --- a/ncurses/tinfo/comp_parse.c +++ b/ncurses/tinfo/comp_parse.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2016,2017 Free Software Foundation, Inc. * + * Copyright (c) 1998-2017,2018 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 * @@ -47,7 +47,7 @@ #include -MODULE_ID("$Id: comp_parse.c,v 1.100 2017/09/20 00:37:08 tom Exp $") +MODULE_ID("$Id: comp_parse.c,v 1.105 2018/04/14 20:33:44 tom Exp $") static void sanity_check2(TERMTYPE2 *, bool); NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype2) (TERMTYPE2 *, bool) = sanity_check2; @@ -265,6 +265,126 @@ _nc_read_entry_source(FILE *fp, char *buf, _nc_suppress_warnings = oldsuppress; } +#if NCURSES_XNAMES +static unsigned +find_capname(TERMTYPE2 *p, const char *name) +{ + unsigned num_names = NUM_EXT_NAMES(p); + unsigned n; + if (name != 0) { + for (n = 0; n < num_names; ++n) { + if (!strcmp(p->ext_Names[n], name)) + break; + } + } else { + n = num_names + 1; + } + return n; +} + +static int +extended_captype(TERMTYPE2 *p, unsigned which) +{ + int result = UNDEF; + unsigned limit = 0; + limit += p->ext_Booleans; + if (limit != 0 && which < limit) { + result = BOOLEAN; + } else { + limit += p->ext_Numbers; + if (limit != 0 && which < limit) { + result = NUMBER; + } else { + limit += p->ext_Strings; + if (limit != 0 && which < limit) { + result = STRING; + } else if (which >= limit) { + result = CANCEL; + } + } + } + return result; +} + +static const char * +name_of_captype(int which) +{ + const char *result = "?"; + switch (which) { + case BOOLEAN: + result = "boolean"; + break; + case NUMBER: + result = "number"; + break; + case STRING: + result = "string"; + break; + } + return result; +} + +#define valid_TERMTYPE2(p) \ + ((p) != 0 && \ + (p)->term_names != 0 && \ + (p)->ext_Names != 0) + +/* + * Disallow changing the type of an extended capability when doing a "use" + * if one or the other is a string. + */ +static int +invalid_merge(TERMTYPE2 *to, TERMTYPE2 *from) +{ + int rc = FALSE; + if (valid_TERMTYPE2(to) + && valid_TERMTYPE2(from)) { + char *to_name = _nc_first_name(to->term_names); + char *from_name = strdup(_nc_first_name(from->term_names)); + unsigned num_names = NUM_EXT_NAMES(from); + unsigned n; + + for (n = 0; n < num_names; ++n) { + const char *capname = from->ext_Names[n]; + int tt = extended_captype(to, find_capname(to, capname)); + int tf = extended_captype(from, n); + + if (tt <= STRING + && tf <= STRING + && (tt == STRING) != (tf == STRING)) { + if (from_name != 0 && strcmp(to_name, from_name)) { + DEBUG(2, + ("merge of %s to %s changes type of %s from %s to %s", + from_name, + to_name, + from->ext_Names[n], + name_of_captype(tf), + name_of_captype(tt))); + } else { + DEBUG(2, ("merge of %s changes type of %s from %s to %s", + to_name, + from->ext_Names[n], + name_of_captype(tf), + name_of_captype(tt))); + } + _nc_warning("merge changes type of %s from %s to %s", + from->ext_Names[n], + name_of_captype(tf), + name_of_captype(tt)); + rc = TRUE; + } + } + free(from_name); + } + return rc; +} +#define validate_merge(p, q) \ + if (invalid_merge(&((p)->tterm), &((q)->tterm))) \ + return FALSE +#else +#define validate_merge(p, q) /* nothing */ +#endif + NCURSES_EXPORT(int) _nc_resolve_uses2(bool fullresolve, bool literal) /* try to resolve all use capabilities */ @@ -317,6 +437,9 @@ _nc_resolve_uses2(bool fullresolve, bool literal) char *lookfor = qp->uses[i].name; long lookline = qp->uses[i].line; + if (lookfor == 0) + continue; + foundit = FALSE; _nc_set_type(child); @@ -394,7 +517,8 @@ _nc_resolve_uses2(bool fullresolve, bool literal) * subsequent pass. */ for (i = 0; i < qp->nuses; i++) - if (qp->uses[i].link->nuses) { + if (qp->uses[i].link + && qp->uses[i].link->nuses) { DEBUG(2, ("%s: use entry %d unresolved", _nc_first_name(qp->tterm.term_names), i)); goto incomplete; @@ -412,13 +536,17 @@ _nc_resolve_uses2(bool fullresolve, bool literal) * Now merge in each use entry in the proper * (reverse) order. */ - for (; qp->nuses; qp->nuses--) + for (; qp->nuses; qp->nuses--) { + validate_merge(&merged, + qp->uses[qp->nuses - 1].link); _nc_merge_entry(&merged, qp->uses[qp->nuses - 1].link); + } /* * Now merge in the original entry. */ + validate_merge(&merged, qp); _nc_merge_entry(&merged, qp); /*