📄 comp_parse.c
字号:
/**************************************************************************** * Copyright (c) 1998-2004,2005 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 * * "Software"), to deal in the Software without restriction, including * * without limitation the rights to use, copy, modify, merge, publish, * * distribute, distribute with modifications, sublicense, and/or sell * * copies of the Software, and to permit persons to whom the Software is * * furnished to do so, subject to the following conditions: * * * * The above copyright notice and this permission notice shall be included * * in all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * * * Except as contained in this notice, the name(s) of the above copyright * * holders shall not be used in advertising or otherwise to promote the * * sale, use or other dealings in this Software without prior written * * authorization. * ****************************************************************************//**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * * and: Thomas E. Dickey 1996-on * ****************************************************************************//* * 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 <curses.priv.h>#include <ctype.h>#include <tic.h>#include <term_entry.h>MODULE_ID("$Id: comp_parse.c,v 1.60 2005/06/04 21:42:44 tom Exp $")static void sanity_check2(TERMTYPE *, bool);NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype2) (TERMTYPE *, bool) = sanity_check2;/* obsolete: 20040705 */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 voidenqueue(ENTRY * ep)/* add an entry to the in-core list */{ ENTRY *newp = _nc_copy_entry(ep); if (newp == 0) _nc_err_abort(MSG_NO_MEMORY); newp->last = _nc_tail; _nc_tail = newp; newp->next = 0; if (newp->last) newp->last->next = newp;}NCURSES_EXPORT(void)_nc_free_entries(ENTRY * headp)/* free the allocated storage consumed by list entries */{ while (_nc_head != 0) { _nc_free_entry(headp, &(headp->tterm)); }}NCURSES_EXPORT(ENTRY *)_nc_delink_entry(ENTRY * headp, TERMTYPE *tterm)/* delink the allocated storage for the given list entry */{ ENTRY *ep, *last; for (last = 0, ep = headp; ep != 0; last = ep, ep = ep->next) { if (&(ep->tterm) == tterm) { if (last != 0) last->next = ep->next; else headp = ep->next; if (ep == _nc_head) _nc_head = 0; if (ep == _nc_tail) _nc_tail = 0; break; } } return ep;}NCURSES_EXPORT(void)_nc_free_entry(ENTRY * headp, TERMTYPE *tterm)/* free the allocated storage consumed by the given list entry */{ ENTRY *ep; if ((ep = _nc_delink_entry(headp, tterm)) != 0) { _nc_free_termtype(&(ep->tterm)); free(ep); }}static char *force_bar(char *dst, char *src){ 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;}NCURSES_EXPORT(bool)_nc_entry_match(char *n1, char *n2)/* do any of the aliases in a pair of terminal names match? */{ char *pstart, *qstart, *pend, *qend; char nc1[MAX_NAME_SIZE + 2], nc2[MAX_NAME_SIZE + 2]; n1 = force_bar(nc1, n1); n2 = force_bar(nc2, n2); 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) return (TRUE); return (FALSE);}/**************************************************************************** * * Entry compiler and resolution logic * ****************************************************************************/NCURSES_EXPORT(void)_nc_read_entry_source(FILE *fp, char *buf, int literal, bool silent, bool(*hook) (ENTRY *))/* slurp all entries in the given file into core */{ ENTRY thisentry; bool oldsuppress = _nc_suppress_warnings; int immediate = 0; if (silent) _nc_suppress_warnings = TRUE; /* shut the lexer up, too */ _nc_reset_input(fp, buf); for (;;) { memset(&thisentry, 0, sizeof(thisentry)); if (_nc_parse_entry(&thisentry, literal, silent) == ERR) break; if (!isalnum(UChar(thisentry.tterm.term_names[0]))) _nc_err_abort("terminal names must start with letter or digit"); /* * This can be used for immediate compilation of entries with no * use references to disk, so as to avoid chewing up a lot of * core when the resolution code could fetch entries off disk. */ if (hook != NULLHOOK && (*hook) (&thisentry)) { immediate++; } else { enqueue(&thisentry); FreeIfNeeded(thisentry.tterm.Booleans); FreeIfNeeded(thisentry.tterm.Numbers); FreeIfNeeded(thisentry.tterm.Strings); } } if (_nc_tail) { /* set up the head pointer */ 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)); }#ifdef TRACE else if (!immediate) DEBUG(1, ("no entries parsed"));#endif _nc_suppress_warnings = oldsuppress;}NCURSES_EXPORT(int)_nc_resolve_uses2(bool fullresolve, bool literal)/* try to resolve all use capabilities */{ ENTRY *qp, *rp, *lastread = 0; bool keepgoing; int i, unresolved, total_unresolved, multiples; DEBUG(2, ("RESOLUTION BEGINNING")); /* * Check for multiple occurrences of the same name. */ multiples = 0; for_entry_list(qp) { int matchcount = 0; 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));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -