/****************************************************************************
- * Copyright (c) 1998-2017,2018 Free Software Foundation, Inc. *
+ * Copyright 2018-2021,2022 Thomas E. Dickey *
+ * Copyright 1998-2016,2017 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 *
#include <tic.h>
-MODULE_ID("$Id: comp_parse.c,v 1.101 2018/02/24 22:33:40 tom Exp $")
+MODULE_ID("$Id: comp_parse.c,v 1.122 2022/05/08 00:11:44 tom Exp $")
static void sanity_check2(TERMTYPE2 *, bool);
-NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype2) (TERMTYPE2 *, bool) = sanity_check2;
+NCURSES_IMPEXP void (NCURSES_API *_nc_check_termtype2) (TERMTYPE2 *, bool) = sanity_check2;
static void fixup_acsc(TERMTYPE2 *, int);
enqueue(ENTRY * ep)
/* add an entry to the in-core list */
{
- ENTRY *newp = _nc_copy_entry(ep);
+ ENTRY *newp;
+ DEBUG(1, (T_CALLED("enqueue(ep=%p)"), (void *) ep));
+
+ newp = _nc_copy_entry(ep);
if (newp == 0)
_nc_err_abort(MSG_NO_MEMORY);
newp->next = 0;
if (newp->last)
newp->last->next = newp;
+ DEBUG(1, (T_RETURN("")));
}
#define NAMEBUFFER_SIZE (MAX_NAME_SIZE + 2)
size_t len = strlen(src);
if (len > MAX_NAME_SIZE)
len = MAX_NAME_SIZE;
- _nc_STRNCPY(dst, src, len);
+ _nc_STRNCPY(dst, src, MAX_NAME_SIZE);
_nc_STRCPY(dst + len, "|", NAMEBUFFER_SIZE - len);
src = dst;
}
++qend;
while ((*qstart++ = *qend++) != '\0') ;
fprintf(stderr, "...now\t%s\n", p2);
+ removed = TRUE;
} else {
fprintf(stderr, "Cannot remove alias '%.*s'\n",
(int) (qend - qstart), qstart);
}
- removed = TRUE;
break;
}
}
bool oldsuppress = _nc_suppress_warnings;
int immediate = 0;
+ DEBUG(1,
+ (T_CALLED("_nc_read_entry_source(file=%p, buf=%p, literal=%d, silent=%d, hook=%p)"),
+ (void *) fp, buf, literal, silent, (void *) hook));
+
if (silent)
_nc_suppress_warnings = TRUE; /* shut the lexer up, too */
FreeIfNeeded(thisentry.tterm.Strings);
#if NCURSES_XNAMES
FreeIfNeeded(thisentry.tterm.ext_Names);
+ FreeIfNeeded(thisentry.tterm.ext_str_table);
#endif
}
}
for (_nc_head = _nc_tail; _nc_head->last; _nc_head = _nc_head->last)
continue;
- DEBUG(1, ("head = %s", _nc_head->tterm.term_names));
- DEBUG(1, ("tail = %s", _nc_tail->tterm.term_names));
+ DEBUG(2, ("head = %s", _nc_head->tterm.term_names));
+ DEBUG(2, ("tail = %s", _nc_tail->tterm.term_names));
}
#ifdef TRACE
else if (!immediate)
- DEBUG(1, ("no entries parsed"));
+ DEBUG(2, ("no entries parsed"));
#endif
_nc_suppress_warnings = oldsuppress;
}
-#if NCURSES_XNAMES
+#if 0 && NCURSES_XNAMES
static unsigned
find_capname(TERMTYPE2 *p, const char *name)
{
unsigned num_names = NUM_EXT_NAMES(p);
unsigned n;
- for (n = 0; n < num_names; ++n) {
- if (!strcmp(p->ext_Names[n], name))
- break;
+ 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;
}
} else {
limit += p->ext_Strings;
if (limit != 0 && which < limit) {
- result = STRING;
+ result = ((p->Strings[STRCOUNT + which] != CANCELLED_STRING)
+ ? STRING
+ : CANCEL);
} else if (which >= limit) {
result = CANCEL;
}
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.
invalid_merge(TERMTYPE2 *to, TERMTYPE2 *from)
{
int rc = FALSE;
- 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)));
+ 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)) {
+ _nc_warning("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 {
+ _nc_warning("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));
+ }
+ rc = TRUE;
}
- _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);
}
- free(from_name);
return rc;
}
#define validate_merge(p, q) \
{
ENTRY *qp, *rp, *lastread = 0;
bool keepgoing;
- unsigned i;
+ unsigned i, j;
int unresolved, total_unresolved, multiples;
- DEBUG(2, ("RESOLUTION BEGINNING"));
+ DEBUG(2, (T_CALLED("_nc_resolve_uses2")));
/*
* Check for multiple occurrences of the same name.
}
}
}
- if (multiples > 0)
+ if (multiples > 0) {
+ DEBUG(2, (T_RETURN("false")));
return (FALSE);
+ }
DEBUG(2, ("NO MULTIPLE NAME OCCURRENCES"));
char *lookfor = qp->uses[i].name;
long lookline = qp->uses[i].line;
+ if (lookfor == 0)
+ continue;
+
foundit = FALSE;
_nc_set_type(child);
qp->uses[i].link = rp;
foundit = TRUE;
+
+ /* verify that there are no earlier uses */
+ for (j = 0; j < i; ++j) {
+ if (qp->uses[j].link != NULL
+ && !strcmp(qp->uses[j].link->tterm.term_names,
+ rp->tterm.term_names)) {
+ _nc_warning("duplicate use=%s", lookfor);
+ break;
+ }
+ }
}
}
qp->uses[i].link = rp;
foundit = TRUE;
+
+ /* verify that there are no earlier uses */
+ for (j = 0; j < i; ++j) {
+ if (qp->uses[j].link != NULL
+ && !strcmp(qp->uses[j].link->tterm.term_names,
+ rp->tterm.term_names)) {
+ _nc_warning("duplicate use=%s", lookfor);
+ break;
+ }
+ }
}
}
if (total_unresolved) {
/* free entries read in off disk */
_nc_free_entries(lastread);
+ DEBUG(2, (T_RETURN("false")));
return (FALSE);
}
* 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;
FreeIfNeeded(qp->tterm.Booleans);
FreeIfNeeded(qp->tterm.Numbers);
FreeIfNeeded(qp->tterm.Strings);
+ FreeIfNeeded(qp->tterm.str_table);
#if NCURSES_XNAMES
FreeIfNeeded(qp->tterm.ext_Names);
+ FreeIfNeeded(qp->tterm.ext_str_table);
#endif
qp->tterm = merged.tterm;
_nc_wrap_entry(qp, TRUE);
_nc_check_termtype2(&qp->tterm, literal);
+ /*
+ * Checking calls tparm, which can allocate memory. Fix leaks.
+ */
+#define TPS(name) fake_tm.tparm_state.name
+ FreeAndNull(TPS(out_buff));
+ FreeAndNull(TPS(fmt_buff));
+#undef TPS
+
_nc_set_screen(save_SP);
set_curterm(save_tm);
} else {
DEBUG(2, ("SANITY CHECK FINISHED"));
}
+ DEBUG(2, (T_RETURN("true")));
return (TRUE);
}
NCURSES_EXPORT(void)
_nc_leaks_tic(void)
{
- T((T_CALLED("_nc_free_tic()")));
+ T((T_CALLED("_nc_leaks_tic()")));
_nc_globals.leak_checking = TRUE;
_nc_alloc_entry_leaks();
_nc_captoinfo_leaks();
_nc_codes_leaks();
#endif
_nc_tic_expand(0, FALSE, 0);
+ T((T_RETURN("")));
}
NCURSES_EXPORT(void)
_nc_free_tic(int code)
{
+ T((T_CALLED("_nc_free_tic(%d)"), code));
_nc_leaks_tic();
- _nc_free_tinfo(code);
+ exit_terminfo(code);
}
#endif