X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Fcomp_scan.c;h=e937f7eb5adac719db9787a2b771260d098d5838;hp=c819edcaaf3f5755e9e2b89cbe9320874e2cdbed;hb=1051e5f924808ea27fcf8f5b624e63d07788b86e;hpb=a8987e73ec254703634802b4f7ee30d3a485524d diff --git a/ncurses/tinfo/comp_scan.c b/ncurses/tinfo/comp_scan.c index c819edca..e937f7eb 100644 --- a/ncurses/tinfo/comp_scan.c +++ b/ncurses/tinfo/comp_scan.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2002,2003 Free Software Foundation, Inc. * + * Copyright (c) 1998-2005,2006 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 * @@ -29,6 +29,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996 on * ****************************************************************************/ /* @@ -50,7 +51,7 @@ #include #include -MODULE_ID("$Id: comp_scan.c,v 1.66 2003/12/14 00:32:40 tom Exp $") +MODULE_ID("$Id: comp_scan.c,v 1.78 2006/12/16 19:17:01 tom Exp $") /* * Maximum length of string capability we'll accept before raising an error. @@ -94,14 +95,196 @@ NCURSES_EXPORT_VAR(bool) _nc_disable_period = FALSE; /* used by tic -a option */ #endif -static bool end_of_stream(void); -static int last_char(void); -static int next_char(void); -static long stream_pos(void); -static void push_back(char c); +/***************************************************************************** + * + * Character-stream handling + * + *****************************************************************************/ + +#define LEXBUFSIZ 1024 + +static 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 int +last_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 int +next_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 the same as a 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 void +push_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 long +stream_pos(void) +/* return our current character position in the input stream */ +{ + return (yyin ? ftell(yyin) : (bufptr ? bufptr - bufstart : 0)); +} + +static bool +end_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 int +static NCURSES_INLINE int eat_escaped_newline(int ch) { if (ch == '\\') @@ -161,6 +344,10 @@ _nc_get_token(bool silent) long number; long token_start; unsigned found; +#ifdef TRACE + int old_line; + int old_col; +#endif if (pushtype != NO_PUSHBACK) { int retval = pushtype; @@ -178,7 +365,11 @@ _nc_get_token(bool silent) } 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); @@ -194,6 +385,10 @@ _nc_get_token(bool silent) ch = eat_escaped_newline(ch); +#ifdef TRACE + old_line = _nc_curr_line; + old_col = _nc_curr_col; +#endif if (ch == EOF) type = EOF; else { @@ -219,13 +414,13 @@ _nc_get_token(bool silent) } /* have to make some punctuation chars legal for terminfo */ - if (!isalnum(ch) + 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", + _nc_warning("Illegal character (expected alphanumeric or %s) - '%s'", terminfo_punct, unctrl((chtype) ch)); _nc_panic_mode(separator); goto start_token; @@ -234,6 +429,10 @@ _nc_get_token(bool silent) 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; @@ -247,7 +446,7 @@ _nc_get_token(bool silent) after_list = 0; while ((ch = next_char()) != '\n') { if (ch == EOF) { - _nc_err_abort(MSG_NO_MEMORY); + _nc_err_abort(MSG_NO_INPUTS); } else if (ch == '|') { after_list = ptr; if (after_name == 0) @@ -351,7 +550,7 @@ _nc_get_token(bool silent) had_newline = FALSE; } while ((ch = next_char()) != EOF) { - if (!isalnum(ch)) { + if (!isalnum(UChar(ch))) { if (_nc_syntax == SYN_TERMINFO) { if (ch != '_') break; @@ -416,7 +615,7 @@ _nc_get_token(bool silent) /* just to get rid of the compiler warning */ type = UNDEF; if (!silent) - _nc_warning("Illegal character - %s", unctrl((chtype) ch)); + _nc_warning("Illegal character - '%s'", unctrl((chtype) ch)); } } /* end else (first_column == FALSE) */ } /* end else (ch != EOF) */ @@ -427,6 +626,11 @@ _nc_get_token(bool silent) if (dot_flag == TRUE) DEBUG(8, ("Commented out ")); + if (_nc_tracing >= DEBUG_LEVEL(8)) { + _tracef("parsed %d.%d to %d.%d", + old_line, old_col, + _nc_curr_line, _nc_curr_col); + } if (_nc_tracing >= DEBUG_LEVEL(7)) { switch (type) { case BOOLEAN: @@ -471,8 +675,9 @@ _nc_get_token(bool silent) type = _nc_get_token(silent); DEBUG(3, ("token: `%s', class %d", - _nc_curr_token.tk_name != 0 ? _nc_curr_token.tk_name : - "", + ((_nc_curr_token.tk_name != 0) + ? _nc_curr_token.tk_name + : ""), type)); return (type); @@ -497,7 +702,7 @@ _nc_get_token(bool silent) * */ -NCURSES_EXPORT(char) +NCURSES_EXPORT(int) _nc_trans_string(char *ptr, char *last) { int count = 0; @@ -518,7 +723,7 @@ _nc_trans_string(char *ptr, char *last) _nc_err_abort(MSG_NO_INPUTS); if (!(is7bits(ch) && isprint(ch))) { - _nc_warning("Illegal ^ character - %s", unctrl(ch)); + _nc_warning("Illegal ^ character - '%s'", unctrl(ch)); } if (ch == '?') { *(ptr++) = '\177'; @@ -613,7 +818,7 @@ _nc_trans_string(char *ptr, char *last) continue; default: - _nc_warning("Illegal character %s in \\ sequence", + _nc_warning("Illegal character '%s' in \\ sequence", unctrl(ch)); /* FALLTHRU */ case '|': @@ -623,13 +828,21 @@ _nc_trans_string(char *ptr, char *last) } /* end else if (ch == '\\') */ else if (ch == '\n' && (_nc_syntax == SYN_TERMINFO)) { - /* newlines embedded in a terminfo string are ignored */ + /* + * Newlines embedded in a terminfo string are ignored, provided + * that the next line begins with whitespace. + */ ignored = TRUE; } else { *(ptr++) = (char) ch; } if (!ignored) { + if (_nc_curr_col <= 1) { + push_back(ch); + ch = '\n'; + break; + } last_ch = ch; count++; } @@ -668,7 +881,10 @@ _nc_push_token(int tokclass) _nc_get_type(pushname); DEBUG(3, ("pushing token: `%s', class %d", - _nc_curr_token.tk_name, pushtype)); + ((_nc_curr_token.tk_name != 0) + ? _nc_curr_token.tk_name + : ""), + pushtype)); } /* @@ -688,171 +904,12 @@ _nc_panic_mode(char ch) } } -/***************************************************************************** - * - * Character-stream handling - * - *****************************************************************************/ - -#define LEXBUFSIZ 1024 - -static 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. - */ - +#if NO_LEAKS NCURSES_EXPORT(void) -_nc_reset_input(FILE *fp, char *buf) +_nc_comp_scan_leaks(void) { - 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 int -last_char(void) -{ - size_t len = strlen(bufptr); - while (len--) { - if (!isspace(UChar(bufptr[len]))) - return bufptr[len]; + if (pushname != 0) { + FreeAndNull(pushname); } - 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 int -next_char(void) -{ - if (!yyin) { - /* - * An string with an embedded null will truncate the input. This is - * intentional (we don't read binary files here). - */ - if (*bufptr == '\0') - return (EOF); - if (*bufptr == '\n') { - _nc_curr_line++; - _nc_curr_col = 0; - } - } 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. - */ - static char *result; - static size_t allocated; - 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, 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)) - bufptr++; - - /* - * Treat a trailing the same as a 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 */ - } - - first_column = (bufptr == bufstart); - if (first_column) - had_newline = FALSE; - - _nc_curr_col++; - return (*bufptr++); -} - -static void -push_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; -} - -static long -stream_pos(void) -/* return our current character position in the input stream */ -{ - return (yyin ? ftell(yyin) : (bufptr ? bufptr - bufstart : 0)); -} - -static bool -end_of_stream(void) -/* are we at end of input? */ -{ - return ((yyin ? feof(yyin) : (bufptr && *bufptr == '\0')) - ? TRUE : FALSE); } +#endif