📄 comp_scan.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_scan.c --- Lexical scanner for terminfo compiler. * * _nc_reset_input() * _nc_get_token() * _nc_panic_mode() * int _nc_syntax; * int _nc_curr_line; * long _nc_curr_file_pos; * long _nc_comment_start; * long _nc_comment_end; */#include <curses.priv.h>#include <ctype.h>#include <term_entry.h>#include <tic.h>MODULE_ID("$Id: comp_scan.c,v 1.76 2005/06/04 22:04:45 tom Exp $")/* * Maximum length of string capability we'll accept before raising an error. * Yes, there is a real capability in /etc/termcap this long, an "is". */#define MAXCAPLEN 600#define iswhite(ch) (ch == ' ' || ch == '\t')NCURSES_EXPORT_VAR(int)_nc_syntax = 0; /* termcap or terminfo? */NCURSES_EXPORT_VAR(long)_nc_curr_file_pos = 0; /* file offset of current line */NCURSES_EXPORT_VAR(long)_nc_comment_start = 0; /* start of comment range before name */NCURSES_EXPORT_VAR(long)_nc_comment_end = 0; /* end of comment range before name */NCURSES_EXPORT_VAR(long)_nc_start_line = 0; /* start line of current entry */NCURSES_EXPORT_VAR(struct token)_nc_curr_token ={ 0, 0, 0};/***************************************************************************** * * Token-grabbing machinery * *****************************************************************************/static bool first_column; /* See 'next_char()' below */static bool had_newline;static char separator; /* capability separator */static int pushtype; /* type of pushback token */static char *pushname;#if NCURSES_EXT_FUNCSNCURSES_EXPORT_VAR(bool)_nc_disable_period = FALSE; /* used by tic -a option */#endif/***************************************************************************** * * Character-stream handling * *****************************************************************************/#define LEXBUFSIZ 1024static char *bufptr; /* otherwise, the input buffer pointer */static char *bufstart; /* start of buffer so we can compute offsets */static FILE *yyin; /* scanner's input file descriptor *//* * _nc_reset_input() * * Resets the input-reading routines. Used on initialization, * or after a seek has been done. Exactly one argument must be * non-null. */NCURSES_EXPORT(void)_nc_reset_input(FILE *fp, char *buf){ pushtype = NO_PUSHBACK; if (pushname != 0) pushname[0] = '\0'; yyin = fp; bufstart = bufptr = buf; _nc_curr_file_pos = 0L; if (fp != 0) _nc_curr_line = 0; _nc_curr_col = 0;}/* * int last_char() * * Returns the final nonblank character on the current input buffer */static intlast_char(void){ size_t len = strlen(bufptr); while (len--) { if (!isspace(UChar(bufptr[len]))) return bufptr[len]; } return 0;}/* * int next_char() * * Returns the next character in the input stream. Comments and leading * white space are stripped. * * The global state variable 'firstcolumn' is set TRUE if the character * returned is from the first column of the input line. * * The global variable _nc_curr_line is incremented for each new line. * The global variable _nc_curr_file_pos is set to the file offset of the * beginning of each line. */static intnext_char(void){ static char *result; static size_t allocated; int the_char; if (!yyin) { if (result != 0) { FreeAndNull(result); FreeAndNull(pushname); allocated = 0; } /* * An string with an embedded null will truncate the input. This is * intentional (we don't read binary files here). */ if (bufptr == 0 || *bufptr == '\0') return (EOF); if (*bufptr == '\n') { _nc_curr_line++; _nc_curr_col = 0; } else if (*bufptr == '\t') { _nc_curr_col = (_nc_curr_col | 7); } } else if (!bufptr || !*bufptr) { /* * In theory this could be recoded to do its I/O one character at a * time, saving the buffer space. In practice, this turns out to be * quite hard to get completely right. Try it and see. If you * succeed, don't forget to hack push_back() correspondingly. */ size_t used; size_t len; do { bufstart = 0; used = 0; do { if (used + (LEXBUFSIZ / 4) >= allocated) { allocated += (allocated + LEXBUFSIZ); result = typeRealloc(char, allocated, result); if (result == 0) return (EOF); } if (used == 0) _nc_curr_file_pos = ftell(yyin); if (fgets(result + used, (int) (allocated - used), yyin) != 0) { bufstart = result; if (used == 0) { _nc_curr_line++; _nc_curr_col = 0; } } else { if (used != 0) strcat(result, "\n"); } if ((bufptr = bufstart) != 0) { used = strlen(bufptr); while (iswhite(*bufptr)) { if (*bufptr == '\t') { _nc_curr_col = (_nc_curr_col | 7) + 1; } else { _nc_curr_col++; } bufptr++; } /* * Treat a trailing <cr><lf> the same as a <newline> so we * can read files on OS/2, etc. */ if ((len = strlen(bufptr)) > 1) { if (bufptr[len - 1] == '\n' && bufptr[len - 2] == '\r') { len--; bufptr[len - 1] = '\n'; bufptr[len] = '\0'; } } } else { return (EOF); } } while (bufptr[len - 1] != '\n'); /* complete a line */ } while (result[0] == '#'); /* ignore comments */ } else if (*bufptr == '\t') { _nc_curr_col = (_nc_curr_col | 7); } first_column = (bufptr == bufstart); if (first_column) had_newline = FALSE; _nc_curr_col++; the_char = *bufptr++; return UChar(the_char);}static voidpush_back(char c)/* push a character back onto the input stream */{ if (bufptr == bufstart) _nc_syserr_abort("Can't backspace off beginning of line"); *--bufptr = c; _nc_curr_col--;}static longstream_pos(void)/* return our current character position in the input stream */{ return (yyin ? ftell(yyin) : (bufptr ? bufptr - bufstart : 0));}static boolend_of_stream(void)/* are we at end of input? */{ return ((yyin ? feof(yyin) : (bufptr && *bufptr == '\0')) ? TRUE : FALSE);}/* Assume we may be looking at a termcap-style continuation */static inline inteat_escaped_newline(int ch){ if (ch == '\\') while ((ch = next_char()) == '\n' || iswhite(ch)) continue; return ch;}/* * int * get_token() * * Scans the input for the next token, storing the specifics in the * global structure 'curr_token' and returning one of the following: * * NAMES A line beginning in column 1. 'name' * will be set to point to everything up to but * not including the first separator on the line. * BOOLEAN An entry consisting of a name followed by * a separator. 'name' will be set to point to * the name of the capability. * NUMBER An entry of the form * name#digits, * 'name' will be set to point to the capability * name and 'valnumber' to the number given. * STRING An entry of the form * name=characters, * 'name' is set to the capability name and * 'valstring' to the string of characters, with * input translations done. * CANCEL An entry of the form * name@, * 'name' is set to the capability name and * 'valnumber' to -1. * EOF The end of the file has been reached. * * A `separator' is either a comma or a semicolon, depending on whether * we are in termcap or terminfo mode. * */NCURSES_EXPORT(int)_nc_get_token(bool silent){ static const char terminfo_punct[] = "@%&*!#"; static char *buffer; char *after_list; char *after_name; char *numchk; char *ptr; char *s; char numbuf[80]; int ch; int dot_flag = FALSE; int type; long number; long token_start; unsigned found;#ifdef TRACE int old_line; int old_col;#endif if (pushtype != NO_PUSHBACK) { int retval = pushtype; _nc_set_type(pushname != 0 ? pushname : ""); DEBUG(3, ("pushed-back token: `%s', class %d", _nc_curr_token.tk_name, pushtype)); pushtype = NO_PUSHBACK; if (pushname != 0) pushname[0] = '\0'; /* currtok wasn't altered by _nc_push_token() */ return (retval); } if (end_of_stream()) { yyin = 0; next_char(); /* frees its allocated memory */ if (buffer != 0) { if (_nc_curr_token.tk_name == buffer) _nc_curr_token.tk_name = 0; FreeAndNull(buffer); } return (EOF); } start_token: token_start = stream_pos(); while ((ch = next_char()) == '\n' || iswhite(ch)) { if (ch == '\n') had_newline = TRUE; continue; } ch = eat_escaped_newline(ch);#ifdef TRACE old_line = _nc_curr_line; old_col = _nc_curr_col;#endif if (ch == EOF) type = EOF; else { /* if this is a termcap entry, skip a leading separator */ if (separator == ':' && ch == ':') ch = next_char(); if (ch == '.'#if NCURSES_EXT_FUNCS && !_nc_disable_period#endif ) { dot_flag = TRUE; DEBUG(8, ("dot-flag set")); while ((ch = next_char()) == '.' || iswhite(ch)) continue; } if (ch == EOF) { type = EOF; goto end_of_token; } /* have to make some punctuation chars legal for terminfo */ if (!isalnum(UChar(ch))#if NCURSES_EXT_FUNCS && !(ch == '.' && _nc_disable_period)#endif && !strchr(terminfo_punct, (char) ch)) { if (!silent) _nc_warning("Illegal character (expected alphanumeric or %s) - '%s'", terminfo_punct, unctrl((chtype) ch)); _nc_panic_mode(separator); goto start_token; } if (buffer == 0) buffer = typeMalloc(char, MAX_ENTRY_SIZE);#ifdef TRACE old_line = _nc_curr_line; old_col = _nc_curr_col;#endif ptr = buffer; *(ptr++) = ch; if (first_column) { _nc_comment_start = token_start; _nc_comment_end = _nc_curr_file_pos; _nc_start_line = _nc_curr_line; _nc_syntax = ERR; after_name = 0; after_list = 0; while ((ch = next_char()) != '\n') { if (ch == EOF) { _nc_err_abort(MSG_NO_INPUTS); } else if (ch == '|') { after_list = ptr; if (after_name == 0) after_name = ptr; } else if (ch == ':' && last_char() != ',') { _nc_syntax = SYN_TERMCAP; separator = ':'; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -