⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parse_entry.c

📁 ncurses-5.4
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************** * Copyright (c) 1998-2002,2003 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-2003               * ****************************************************************************//* *	parse_entry.c -- compile one terminfo or termcap entry * *	Get an exact in-core representation of an entry.  Don't *	try to resolve use or tc capabilities, that is someone *	else's job.  Depends on the lexical analyzer to get tokens *	from the input stream. */#define __INTERNAL_CAPS_VISIBLE#include <curses.priv.h>#include <ctype.h>#include <tic.h>#include <term_entry.h>MODULE_ID("$Id: parse_entry.c,v 1.60 2003/11/08 21:57:09 tom Exp $")#ifdef LINTstatic short const parametrized[] ={0};#else#include <parametrized.h>#endifstatic void postprocess_termcap(TERMTYPE *, bool);static void postprocess_terminfo(TERMTYPE *);static struct name_table_entry const *lookup_fullname(const char *name);#if NCURSES_XNAMESstatic struct name_table_entry const *_nc_extend_names(ENTRY * entryp, char *name, int token_type){    static struct name_table_entry temp;    TERMTYPE *tp = &(entryp->tterm);    unsigned offset = 0;    unsigned actual;    unsigned tindex;    unsigned first, last, n;    bool found;    switch (token_type) {    case BOOLEAN:	first = 0;	last = tp->ext_Booleans;	offset = tp->ext_Booleans;	tindex = tp->num_Booleans;	break;    case NUMBER:	first = tp->ext_Booleans;	last = tp->ext_Numbers + first;	offset = tp->ext_Booleans + tp->ext_Numbers;	tindex = tp->num_Numbers;	break;    case STRING:	first = tp->ext_Booleans + tp->ext_Numbers;	last = tp->ext_Strings + first;	offset = tp->ext_Booleans + tp->ext_Numbers + tp->ext_Strings;	tindex = tp->num_Strings;	break;    case CANCEL:	actual = NUM_EXT_NAMES(tp);	for (n = 0; n < actual; n++) {	    if (!strcmp(name, tp->ext_Names[n])) {		if (n > (unsigned) (tp->ext_Booleans + tp->ext_Numbers)) {		    token_type = STRING;		} else if (n > tp->ext_Booleans) {		    token_type = NUMBER;		} else {		    token_type = BOOLEAN;		}		return _nc_extend_names(entryp, name, token_type);	    }	}	/* Well, we are given a cancel for a name that we don't recognize */	return _nc_extend_names(entryp, name, STRING);    default:	return 0;    }    /* Adjust the 'offset' (insertion-point) to keep the lists of extended     * names sorted.     */    for (n = first, found = FALSE; n < last; n++) {	int cmp = strcmp(tp->ext_Names[n], name);	if (cmp == 0)	    found = TRUE;	if (cmp >= 0) {	    offset = n;	    tindex = n - first;	    switch (token_type) {	    case BOOLEAN:		tindex += BOOLCOUNT;		break;	    case NUMBER:		tindex += NUMCOUNT;		break;	    case STRING:		tindex += STRCOUNT;		break;	    }	    break;	}    }    if (!found) {	switch (token_type) {	case BOOLEAN:	    tp->ext_Booleans += 1;	    tp->num_Booleans += 1;	    tp->Booleans = typeRealloc(char, tp->num_Booleans, tp->Booleans);	    for (last = tp->num_Booleans - 1; last > tindex; last--)		tp->Booleans[last] = tp->Booleans[last - 1];	    break;	case NUMBER:	    tp->ext_Numbers += 1;	    tp->num_Numbers += 1;	    tp->Numbers = typeRealloc(short, tp->num_Numbers, tp->Numbers);	    for (last = tp->num_Numbers - 1; last > tindex; last--)		tp->Numbers[last] = tp->Numbers[last - 1];	    break;	case STRING:	    tp->ext_Strings += 1;	    tp->num_Strings += 1;	    tp->Strings = typeRealloc(char *, tp->num_Strings, tp->Strings);	    for (last = tp->num_Strings - 1; last > tindex; last--)		tp->Strings[last] = tp->Strings[last - 1];	    break;	}	actual = NUM_EXT_NAMES(tp);	tp->ext_Names = typeRealloc(char *, actual, tp->ext_Names);	while (--actual > offset)	    tp->ext_Names[actual] = tp->ext_Names[actual - 1];	tp->ext_Names[offset] = _nc_save_str(name);    }    temp.nte_name = tp->ext_Names[offset];    temp.nte_type = token_type;    temp.nte_index = tindex;    temp.nte_link = -1;    return &temp;}#endif /* NCURSES_XNAMES *//* *	int *	_nc_parse_entry(entry, literal, silent) * *	Compile one entry.  Doesn't try to resolve use or tc capabilities. * *	found-forward-use = FALSE *	re-initialise internal arrays *	get_token(); *	if the token was not a name in column 1, complain and die *	save names in entry's string table *	while (get_token() is not EOF and not NAMES) *	        check for existence and type-correctness *	        enter cap into structure *	        if STRING *	            save string in entry's string table *	push back token */#define BAD_TC_USAGE if (!bad_tc_usage) \ 	{ bad_tc_usage = TRUE; \	 _nc_warning("Legacy termcap allows only a trailing tc= clause"); }NCURSES_EXPORT(int)_nc_parse_entry(struct entry *entryp, int literal, bool silent){    int token_type;    struct name_table_entry const *entry_ptr;    char *ptr, *base;    bool bad_tc_usage = FALSE;    token_type = _nc_get_token(silent);    if (token_type == EOF)	return (EOF);    if (token_type != NAMES)	_nc_err_abort("Entry does not start with terminal names in column one");    _nc_init_entry(&entryp->tterm);    entryp->cstart = _nc_comment_start;    entryp->cend = _nc_comment_end;    entryp->startline = _nc_start_line;    DEBUG(2, ("Comment range is %ld to %ld", entryp->cstart, entryp->cend));    /*     * Strip off the 2-character termcap name, if present.  Originally termcap     * used that as an indexing aid.  We can retain 2-character terminfo names,     * but note that they would be lost if we translate to/from termcap.  This     * feature is supposedly obsolete since "newer" BSD implementations do not     * use it; however our reference for this feature is SunOS 4.x, which     * implemented it.  Note that the resulting terminal type was never the     * 2-character name, but was instead the first alias after that.     */    ptr = _nc_curr_token.tk_name;    if (_nc_syntax == SYN_TERMCAP) {	if (ptr[2] == '|') {	    ptr += 3;	    _nc_curr_token.tk_name[2] = '\0';	}    }    entryp->tterm.str_table = entryp->tterm.term_names = _nc_save_str(ptr);    DEBUG(1, ("Starting '%s'", ptr));    /*     * We do this because the one-token lookahead in the parse loop     * results in the terminal type getting prematurely set to correspond     * to that of the next entry.     */    _nc_set_type(_nc_first_name(entryp->tterm.term_names));    /* check for overly-long names and aliases */    for (base = entryp->tterm.term_names; (ptr = strchr(base, '|')) != 0;	 base = ptr + 1) {	if (ptr - base > MAX_ALIAS) {	    _nc_warning("%s `%.*s' may be too long",			(base == entryp->tterm.term_names)			? "primary name"			: "alias",			(int) (ptr - base), base);	}    }    entryp->nuses = 0;    for (token_type = _nc_get_token(silent);	 token_type != EOF && token_type != NAMES;	 token_type = _nc_get_token(silent)) {	bool is_use = (strcmp(_nc_curr_token.tk_name, "use") == 0);	bool is_tc = !is_use && (strcmp(_nc_curr_token.tk_name, "tc") == 0);	if (is_use || is_tc) {	    entryp->uses[entryp->nuses].name = _nc_save_str(_nc_curr_token.tk_valstring);	    entryp->uses[entryp->nuses].line = _nc_curr_line;	    entryp->nuses++;	    if (entryp->nuses > 1 && is_tc) {		BAD_TC_USAGE	    }	} else {	    /* normal token lookup */	    entry_ptr = _nc_find_entry(_nc_curr_token.tk_name,				       _nc_syntax ? _nc_cap_hash_table : _nc_info_hash_table);	    /*	     * Our kluge to handle aliasing.  The reason it's done	     * this ugly way, with a linear search, is so the hashing	     * machinery doesn't have to be made really complicated	     * (also we get better warnings this way).  No point in	     * making this case fast, aliased caps aren't common now	     * and will get rarer.	     */	    if (entry_ptr == NOTFOUND) {		const struct alias *ap;		if (_nc_syntax == SYN_TERMCAP) {		    if (entryp->nuses != 0) {			BAD_TC_USAGE		    }		    for (ap = _nc_capalias_table; ap->from; ap++)			if (strcmp(ap->from, _nc_curr_token.tk_name) == 0) {			    if (ap->to == (char *) 0) {				_nc_warning("%s (%s termcap extension) ignored",					    ap->from, ap->source);				goto nexttok;			    }			    entry_ptr = _nc_find_entry(ap->to, _nc_cap_hash_table);			    if (entry_ptr && !silent)				_nc_warning("%s (%s termcap extension) aliased to %s",					    ap->from, ap->source, ap->to);			    break;			}		} else {	/* if (_nc_syntax == SYN_TERMINFO) */		    for (ap = _nc_infoalias_table; ap->from; ap++)			if (strcmp(ap->from, _nc_curr_token.tk_name) == 0) {			    if (ap->to == (char *) 0) {				_nc_warning("%s (%s terminfo extension) ignored",					    ap->from, ap->source);				goto nexttok;			    }			    entry_ptr = _nc_find_entry(ap->to, _nc_info_hash_table);			    if (entry_ptr && !silent)				_nc_warning("%s (%s terminfo extension) aliased to %s",					    ap->from, ap->source, ap->to);			    break;			}		    if (entry_ptr == NOTFOUND) {			entry_ptr = lookup_fullname(_nc_curr_token.tk_name);		    }		}	    }#if NCURSES_XNAMES	    /*	     * If we have extended-names active, we will automatically	     * define a name based on its context.	     */	    if (entry_ptr == NOTFOUND		&& _nc_user_definable		&& (entry_ptr = _nc_extend_names(entryp,						 _nc_curr_token.tk_name,						 token_type)) != 0) {		if (_nc_tracing >= DEBUG_LEVEL(1))		    _nc_warning("extended capability '%s'", _nc_curr_token.tk_name);	    }#endif /* NCURSES_XNAMES */	    /* can't find this cap name, not even as an alias */	    if (entry_ptr == NOTFOUND) {		if (!silent)		    _nc_warning("unknown capability '%s'",				_nc_curr_token.tk_name);		continue;	    }	    /* deal with bad type/value combinations. */	    if (token_type != CANCEL && entry_ptr->nte_type != token_type) {		/*		 * Nasty special cases here handle situations in which type		 * information can resolve name clashes.  Normal lookup		 * finds the last instance in the capability table of a		 * given name, regardless of type.  find_type_entry looks		 * for a first matching instance with given type.  So as		 * long as all ambiguous names occur in pairs of distinct		 * type, this will do the job.		 */		/* tell max_attributes from arrow_key_map */		if (token_type == NUMBER && !strcmp("ma", _nc_curr_token.tk_name))		    entry_ptr = _nc_find_type_entry("ma", NUMBER,						    _nc_get_table(_nc_syntax								  != 0));		/* map terminfo's string MT to MT */		else if (token_type == STRING && !strcmp("MT", _nc_curr_token.tk_name))		    entry_ptr = _nc_find_type_entry("MT", STRING,						    _nc_get_table(_nc_syntax								  != 0));		/* treat strings without following "=" as empty strings */		else if (token_type == BOOLEAN && entry_ptr->nte_type == STRING)		    token_type = STRING;		/* we couldn't recover; skip this token */		else {		    if (!silent) {			const char *type_name;			switch (entry_ptr->nte_type) {			case BOOLEAN:			    type_name = "boolean";			    break;			case STRING:			    type_name = "string";			    break;			case NUMBER:			    type_name = "numeric";			    break;			default:			    type_name = "unknown";			    break;			}			_nc_warning("wrong type used for %s capability '%s'",				    type_name, _nc_curr_token.tk_name);		    }		    continue;		}	    }	    /* now we know that the type/value combination is OK */	    switch (token_type) {	    case CANCEL:		switch (entry_ptr->nte_type) {		case BOOLEAN:		    entryp->tterm.Booleans[entry_ptr->nte_index] = CANCELLED_BOOLEAN;		    break;		case NUMBER:		    entryp->tterm.Numbers[entry_ptr->nte_index] = CANCELLED_NUMERIC;		    break;		case STRING:		    entryp->tterm.Strings[entry_ptr->nte_index] = CANCELLED_STRING;		    break;		}		break;	    case BOOLEAN:		entryp->tterm.Booleans[entry_ptr->nte_index] = TRUE;		break;	    case NUMBER:		entryp->tterm.Numbers[entry_ptr->nte_index] =		    _nc_curr_token.tk_valnumber;		break;	    case STRING:		ptr = _nc_curr_token.tk_valstring;		if (_nc_syntax == SYN_TERMCAP)		    ptr = _nc_captoinfo(_nc_curr_token.tk_name,					ptr,					parametrized[entry_ptr->nte_index]);		entryp->tterm.Strings[entry_ptr->nte_index] = _nc_save_str(ptr);		break;	    default:		if (!silent)		    _nc_warning("unknown token type");		_nc_panic_mode((_nc_syntax == SYN_TERMCAP) ? ':' : ',');		continue;	    }	}			/* end else cur_token.name != "use" */      nexttok:	continue;		/* cannot have a label w/o statement */    }				/* endwhile (not EOF and not NAMES) */    _nc_push_token(token_type);    _nc_set_type(_nc_first_name(entryp->tterm.term_names));    /*     * Try to deduce as much as possible from extension capabilities     * (this includes obsolete BSD capabilities).  Sigh...it would be more     * space-efficient to call this after use resolution, but it has     * to be done before entry allocation is wrapped up.     */    if (!literal) {	if (_nc_syntax == SYN_TERMCAP) {	    bool has_base_entry = FALSE;	    int i;	    /*	     * Don't insert defaults if this is a `+' entry meant only	     * for inclusion in other entries (not sure termcap ever	     * had these, actually).	     */	    if (strchr(entryp->tterm.term_names, '+'))		has_base_entry = TRUE;	    else		/*		 * Otherwise, look for a base entry that will already		 * have picked up defaults via translation.		 */		for (i = 0; i < entryp->nuses; i++)		    if (!strchr((char *) entryp->uses[i].name, '+'))			has_base_entry = TRUE;	    postprocess_termcap(&entryp->tterm, has_base_entry);	} else	    postprocess_terminfo(&entryp->tterm);    }    _nc_wrap_entry(entryp, FALSE);    return (OK);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -