X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Fcomp_scan.c;h=ef604026a151c8173d2c1cd99b59273822df447a;hp=56ba1d1a5a59e3b4b3dcb5ae54f5927e71e0d215;hb=b9cd971c38eeeb2394d3da08edfd3c5dfc71694e;hpb=b1f61d9f3aa244512045a6b02e759825d7049d34 diff --git a/ncurses/tinfo/comp_scan.c b/ncurses/tinfo/comp_scan.c index 56ba1d1a..ef604026 100644 --- a/ncurses/tinfo/comp_scan.c +++ b/ncurses/tinfo/comp_scan.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2010,2011 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 * ****************************************************************************/ /* @@ -47,10 +48,9 @@ #include #include -#include #include -MODULE_ID("$Id: comp_scan.c,v 1.45 2000/07/08 00:43:55 tom Exp $") +MODULE_ID("$Id: comp_scan.c,v 1.93 2011/08/20 21:19:40 tom Exp $") /* * Maximum length of string capability we'll accept before raising an error. @@ -60,14 +60,17 @@ MODULE_ID("$Id: comp_scan.c,v 1.45 2000/07/08 00:43:55 tom Exp $") #define iswhite(ch) (ch == ' ' || ch == '\t') -int _nc_syntax = 0; /* termcap or terminfo? */ -long _nc_curr_file_pos = 0; /* file offset of current line */ -long _nc_comment_start = 0; /* start of comment range before name */ -long _nc_comment_end = 0; /* end of comment range before name */ -long _nc_start_line = 0; /* start line of current entry */ +NCURSES_EXPORT_VAR (int) _nc_syntax = 0; /* termcap or terminfo? */ +NCURSES_EXPORT_VAR (int) _nc_strict_bsd = 1; /* ncurses extended termcap? */ +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 */ -struct token _nc_curr_token = -{0, 0, 0}; +NCURSES_EXPORT_VAR (struct token) _nc_curr_token = +{ + 0, 0, 0 +}; /***************************************************************************** * @@ -76,22 +79,210 @@ struct token _nc_curr_token = *****************************************************************************/ 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[MAX_NAME_SIZE + 1]; +static char *pushname; -#ifdef NCURSES_EXT_FUNCS -bool _nc_disable_period = FALSE; /* used by tic -a option */ +#if NCURSES_EXT_FUNCS +NCURSES_EXPORT_VAR (bool) _nc_disable_period = FALSE; /* used by tic -a option */ #endif -static int last_char(void); -static int next_char(void); -static long stream_pos(void); -static bool end_of_stream(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); + bufstart = result; + } + if (used == 0) + _nc_curr_file_pos = ftell(yyin); + + if (fgets(result + used, (int) (allocated - used), yyin) != 0) { + bufstart = result; + if (used == 0) { + if (_nc_curr_line == 0 + && IS_TIC_MAGIC(result)) { + _nc_err_abort("This is a compiled terminal description, not a source"); + } + _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 == '\\') @@ -100,6 +291,17 @@ eat_escaped_newline(int ch) return ch; } +#define TOK_BUF_SIZE MAX_ENTRY_SIZE + +#define OkToAdd() \ + ((tok_ptr - tok_buf) < (TOK_BUF_SIZE - 2)) + +#define AddCh(ch) \ + *tok_ptr++ = (char) ch; \ + *tok_ptr = '\0' + +static char *tok_buf; + /* * int * get_token() @@ -133,45 +335,68 @@ eat_escaped_newline(int ch) * */ -int -_nc_get_token(void) +NCURSES_EXPORT(int) +_nc_get_token(bool silent) { static const char terminfo_punct[] = "@%&*!#"; - long number; - int type; - int ch; + + char *after_list; + char *after_name; char *numchk; + char *tok_ptr; + char *s; char numbuf[80]; - unsigned found; - static char buffer[MAX_ENTRY_SIZE]; - char *ptr; + 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); + _nc_set_type(pushname != 0 ? pushname : ""); DEBUG(3, ("pushed-back token: `%s', class %d", - _nc_curr_token.tk_name, pushtype)); + _nc_curr_token.tk_name, pushtype)); pushtype = NO_PUSHBACK; - pushname[0] = '\0'; + if (pushname != 0) + pushname[0] = '\0'; /* currtok wasn't altered by _nc_push_token() */ return (retval); } - if (end_of_stream()) + if (end_of_stream()) { + yyin = 0; + next_char(); /* frees its allocated memory */ + if (tok_buf != 0) { + if (_nc_curr_token.tk_name == tok_buf) + _nc_curr_token.tk_name = 0; + } return (EOF); + } start_token: token_start = stream_pos(); - while ((ch = next_char()) == '\n' || iswhite(ch)) + while ((ch = next_char()) == '\n' || iswhite(ch)) { + if (ch == '\n') + had_newline = TRUE; continue; + } ch = eat_escaped_newline(ch); + _nc_curr_token.tk_valstring = 0; +#ifdef TRACE + old_line = _nc_curr_line; + old_col = _nc_curr_col; +#endif if (ch == EOF) type = EOF; else { @@ -180,10 +405,10 @@ _nc_get_token(void) ch = next_char(); if (ch == '.' -#ifdef NCURSES_EXT_FUNCS - && !_nc_disable_period +#if NCURSES_EXT_FUNCS + && !_nc_disable_period #endif - ) { + ) { dot_flag = TRUE; DEBUG(8, ("dot-flag set")); @@ -197,32 +422,44 @@ _nc_get_token(void) } /* have to make some punctuation chars legal for terminfo */ - if (!isalnum(ch) -#ifdef NCURSES_EXT_FUNCS - && !(ch == '.' && _nc_disable_period) + if (!isalnum(UChar(ch)) +#if NCURSES_EXT_FUNCS + && !(ch == '.' && _nc_disable_period) #endif - && !strchr(terminfo_punct, (char) ch)) { - _nc_warning("Illegal character (expected alphanumeric or %s) - %s", - terminfo_punct, unctrl(ch)); + && !strchr(terminfo_punct, (char) ch)) { + if (!silent) + _nc_warning("Illegal character (expected alphanumeric or %s) - '%s'", + terminfo_punct, unctrl(UChar(ch))); _nc_panic_mode(separator); goto start_token; } - ptr = buffer; - *(ptr++) = ch; + if (tok_buf == 0) + tok_buf = typeMalloc(char, TOK_BUF_SIZE); - if (first_column) { - char *desc; +#ifdef TRACE + old_line = _nc_curr_line; + old_col = _nc_curr_col; +#endif + tok_ptr = tok_buf; + AddCh(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("premature EOF"); - else if (ch == ':' && last_char() != ',') { + if (ch == EOF) { + _nc_err_abort(MSG_NO_INPUTS); + } else if (ch == '|') { + after_list = tok_ptr; + if (after_name == 0) + after_name = tok_ptr; + } else if (ch == ':' && last_char() != ',') { _nc_syntax = SYN_TERMCAP; separator = ':'; break; @@ -230,91 +467,104 @@ _nc_get_token(void) _nc_syntax = SYN_TERMINFO; separator = ','; /* - * Fall-through here is not an accident. - * The idea is that if we see a comma, we - * figure this is terminfo unless we - * subsequently run into a colon -- but - * we don't stop looking for that colon until - * hitting a newline. This allows commas to - * be embedded in description fields of + * If we did not see a '|', then we found a name with no + * aliases or description. + */ + if (after_name == 0) + break; + /* + * If we see a comma, we assume this is terminfo unless we + * subsequently run into a colon. But we don't stop + * looking for a colon until hitting a newline. This + * allows commas to be embedded in description fields of * either syntax. */ - /* FALLTHRU */ } else ch = eat_escaped_newline(ch); - *ptr++ = ch; + if (OkToAdd()) { + AddCh(ch); + } else { + break; + } } - ptr[0] = '\0'; + *tok_ptr = '\0'; if (_nc_syntax == ERR) { /* - * Grrr...what we ought to do here is barf, - * complaining that the entry is malformed. - * But because a couple of name fields in the - * 8.2 termcap file end with |\, we just have - * to assume it's termcap syntax. + * Grrr...what we ought to do here is barf, complaining that + * the entry is malformed. But because a couple of name fields + * in the 8.2 termcap file end with |\, we just have to assume + * it's termcap syntax. */ _nc_syntax = SYN_TERMCAP; separator = ':'; } else if (_nc_syntax == SYN_TERMINFO) { /* throw away trailing /, *$/ */ - for (--ptr; iswhite(*ptr) || *ptr == ','; ptr--) + for (--tok_ptr; + iswhite(*tok_ptr) || *tok_ptr == ','; + tok_ptr--) continue; - ptr[1] = '\0'; + tok_ptr[1] = '\0'; } /* - * This is the soonest we have the terminal name - * fetched. Set up for following warning messages. + * This is the soonest we have the terminal name fetched. Set up + * for following warning messages. If there's no '|', then there + * is no description. */ - ptr = strchr(buffer, '|'); - if (ptr == (char *) NULL) - ptr = buffer + strlen(buffer); - ch = *ptr; - *ptr = '\0'; - _nc_set_type(buffer); - *ptr = ch; + if (after_name != 0) { + ch = *after_name; + *after_name = '\0'; + _nc_set_type(tok_buf); + *after_name = (char) ch; + } /* - * Compute the boundary between the aliases and the - * description field for syntax-checking purposes. + * Compute the boundary between the aliases and the description + * field for syntax-checking purposes. */ - desc = strrchr(buffer, '|'); - if (desc) { - if (*desc == '\0') - _nc_warning("empty longname field"); - else if (strchr(desc, ' ') == (char *) NULL) - _nc_warning("older tic versions may treat the description field as an alias"); + if (after_list != 0) { + if (!silent) { + if (*after_list == '\0') + _nc_warning("empty longname field"); + else if (strchr(after_list, ' ') == 0) + _nc_warning("older tic versions may treat the description field as an alias"); + } + } else { + after_list = tok_buf + strlen(tok_buf); + DEBUG(1, ("missing description")); } - if (!desc) - desc = buffer + strlen(buffer); /* - * Whitespace in a name field other than the long name - * can confuse rdist and some termcap tools. Slashes - * are a no-no. Other special characters can be - * dangerous due to shell expansion. + * Whitespace in a name field other than the long name can confuse + * rdist and some termcap tools. Slashes are a no-no. Other + * special characters can be dangerous due to shell expansion. */ - for (ptr = buffer; ptr < desc; ptr++) { - if (isspace(*ptr)) { - _nc_warning("whitespace in name or alias field"); + for (s = tok_buf; s < after_list; ++s) { + if (isspace(UChar(*s))) { + if (!silent) + _nc_warning("whitespace in name or alias field"); break; - } else if (*ptr == '/') { - _nc_warning("slashes aren't allowed in names or aliases"); + } else if (*s == '/') { + if (!silent) + _nc_warning("slashes aren't allowed in names or aliases"); break; - } else if (strchr("$[]!*?", *ptr)) { - _nc_warning("dubious character `%c' in name or alias field", *ptr); + } else if (strchr("$[]!*?", *s)) { + if (!silent) + _nc_warning("dubious character `%c' in name or alias field", *s); break; } } - ptr = buffer; - - _nc_curr_token.tk_name = buffer; + _nc_curr_token.tk_name = tok_buf; type = NAMES; } else { + if (had_newline && _nc_syntax == SYN_TERMCAP) { + _nc_warning("Missing backslash before newline"); + had_newline = FALSE; + } while ((ch = next_char()) != EOF) { - if (!isalnum(ch)) { + if (!isalnum(UChar(ch))) { if (_nc_syntax == SYN_TERMINFO) { if (ch != '_') break; @@ -323,50 +573,57 @@ _nc_get_token(void) break; } } - *(ptr++) = ch; + if (OkToAdd()) { + AddCh(ch); + } else { + ch = EOF; + break; + } } - *ptr++ = '\0'; + *tok_ptr++ = '\0'; /* separate name/value in buffer */ switch (ch) { case ',': case ':': if (ch != separator) _nc_err_abort("Separator inconsistent with syntax"); - _nc_curr_token.tk_name = buffer; + _nc_curr_token.tk_name = tok_buf; type = BOOLEAN; break; case '@': - if ((ch = next_char()) != separator) + if ((ch = next_char()) != separator && !silent) _nc_warning("Missing separator after `%s', have %s", - buffer, unctrl(ch)); - _nc_curr_token.tk_name = buffer; + tok_buf, unctrl(UChar(ch))); + _nc_curr_token.tk_name = tok_buf; type = CANCEL; break; case '#': found = 0; while (isalnum(ch = next_char())) { - numbuf[found++] = ch; + numbuf[found++] = (char) ch; if (found >= sizeof(numbuf) - 1) break; } numbuf[found] = '\0'; number = strtol(numbuf, &numchk, 0); - if (numchk == numbuf) - _nc_warning("no value given for `%s'", buffer); - if ((*numchk != '\0') || (ch != separator)) - _nc_warning("Missing separator"); - _nc_curr_token.tk_name = buffer; - _nc_curr_token.tk_valnumber = number; + if (!silent) { + if (numchk == numbuf) + _nc_warning("no value given for `%s'", tok_buf); + if ((*numchk != '\0') || (ch != separator)) + _nc_warning("Missing separator"); + } + _nc_curr_token.tk_name = tok_buf; + _nc_curr_token.tk_valnumber = (int) number; type = NUMBER; break; case '=': - ch = _nc_trans_string(ptr, buffer + sizeof(buffer)); - if (ch != separator) + ch = _nc_trans_string(tok_ptr, tok_buf + TOK_BUF_SIZE); + if (!silent && ch != separator) _nc_warning("Missing separator"); - _nc_curr_token.tk_name = buffer; - _nc_curr_token.tk_valstring = ptr; + _nc_curr_token.tk_name = tok_buf; + _nc_curr_token.tk_valstring = tok_ptr; type = STRING; break; @@ -376,7 +633,8 @@ _nc_get_token(void) default: /* just to get rid of the compiler warning */ type = UNDEF; - _nc_warning("Illegal character - %s", unctrl(ch)); + if (!silent) + _nc_warning("Illegal character - '%s'", unctrl(UChar(ch))); } } /* end else (first_column == FALSE) */ } /* end else (ch != EOF) */ @@ -387,34 +645,39 @@ _nc_get_token(void) 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: _tracef("Token: Boolean; name='%s'", - _nc_curr_token.tk_name); + _nc_curr_token.tk_name); break; case NUMBER: _tracef("Token: Number; name='%s', value=%d", - _nc_curr_token.tk_name, - _nc_curr_token.tk_valnumber); + _nc_curr_token.tk_name, + _nc_curr_token.tk_valnumber); break; case STRING: _tracef("Token: String; name='%s', value=%s", - _nc_curr_token.tk_name, - _nc_visbuf(_nc_curr_token.tk_valstring)); + _nc_curr_token.tk_name, + _nc_visbuf(_nc_curr_token.tk_valstring)); break; case CANCEL: _tracef("Token: Cancel; name='%s'", - _nc_curr_token.tk_name); + _nc_curr_token.tk_name); break; case NAMES: _tracef("Token: Names; value='%s'", - _nc_curr_token.tk_name); + _nc_curr_token.tk_name); break; case EOF: @@ -428,9 +691,13 @@ _nc_get_token(void) #endif if (dot_flag == TRUE) /* if commented out, use the next one */ - type = _nc_get_token(); + type = _nc_get_token(silent); - DEBUG(3, ("token: `%s', class %d", _nc_curr_token.tk_name, type)); + DEBUG(3, ("token: `%s', class %d", + ((_nc_curr_token.tk_name != 0) + ? _nc_curr_token.tk_name + : ""), + type)); return (type); } @@ -454,54 +721,66 @@ _nc_get_token(void) * */ -char +NCURSES_EXPORT(int) _nc_trans_string(char *ptr, char *last) { int count = 0; - int number; + int number = 0; int i, c; - chtype ch, last_ch = '\0'; + int last_ch = '\0'; bool ignored = FALSE; bool long_warning = FALSE; - while ((ch = c = next_char()) != (chtype) separator && c != EOF) { - if (ptr == (last - 1)) + while ((c = next_char()) != separator && c != EOF) { + if (ptr >= (last - 1)) { + if (c != EOF) { + while ((c = next_char()) != separator && c != EOF) { + ; + } + } break; + } if ((_nc_syntax == SYN_TERMCAP) && c == '\n') break; - if (ch == '^' && last_ch != '%') { - ch = c = next_char(); + if (c == '^' && last_ch != '%') { + c = next_char(); if (c == EOF) - _nc_err_abort("Premature EOF"); + _nc_err_abort(MSG_NO_INPUTS); - if (!(is7bits(ch) && isprint(ch))) { - _nc_warning("Illegal ^ character - %s", unctrl(ch)); + if (!(is7bits(c) && isprint(c))) { + _nc_warning("Illegal ^ character - '%s'", unctrl(UChar(c))); } - if (ch == '?') { + if (c == '?' && (_nc_syntax != SYN_TERMCAP)) { *(ptr++) = '\177'; if (_nc_tracing) _nc_warning("Allow ^? as synonym for \\177"); } else { - if ((ch &= 037) == 0) - ch = 128; - *(ptr++) = (char) (ch); + if ((c &= 037) == 0) + c = 128; + *(ptr++) = (char) (c); } - } else if (ch == '\\') { - ch = c = next_char(); + } else if (c == '\\') { + bool strict_bsd = ((_nc_syntax == SYN_TERMCAP) && _nc_strict_bsd); + + c = next_char(); if (c == EOF) - _nc_err_abort("Premature EOF"); + _nc_err_abort(MSG_NO_INPUTS); + +#define isoctal(c) ((c) >= '0' && (c) <= '7') - if (ch >= '0' && ch <= '7') { - number = ch - '0'; + if (isoctal(c) || (strict_bsd && isdigit(c))) { + number = c - '0'; for (i = 0; i < 2; i++) { - ch = c = next_char(); + c = next_char(); if (c == EOF) - _nc_err_abort("Premature EOF"); + _nc_err_abort(MSG_NO_INPUTS); - if (c < '0' || c > '7') { + if (!isoctal(c)) { if (isdigit(c)) { - _nc_warning("Non-octal digit `%c' in \\ sequence", c); - /* allow the digit; it'll do less harm */ + if (!strict_bsd) { + _nc_warning("Non-octal digit `%c' in \\ sequence", c); + /* allow the digit; it'll do less harm */ + } } else { push_back((char) c); break; @@ -511,21 +790,16 @@ _nc_trans_string(char *ptr, char *last) number = number * 8 + c - '0'; } - if (number == 0) + number = UChar(number); + if (number == 0 && !strict_bsd) number = 0200; *(ptr++) = (char) number; } else { switch (c) { case 'E': - case 'e': *(ptr++) = '\033'; break; - case 'a': - *(ptr++) = '\007'; - break; - - case 'l': case 'n': *(ptr++) = '\n'; break; @@ -538,10 +812,6 @@ _nc_trans_string(char *ptr, char *last) *(ptr++) = '\010'; break; - case 's': - *(ptr++) = ' '; - break; - case 'f': *(ptr++) = '\014'; break; @@ -562,30 +832,57 @@ _nc_trans_string(char *ptr, char *last) *(ptr++) = ','; break; - case ':': - *(ptr++) = ':'; - break; - case '\n': continue; default: - _nc_warning("Illegal character %s in \\ sequence", - unctrl(ch)); - *(ptr++) = (char) ch; - } /* endswitch (ch) */ - } /* endelse (ch < '0' || ch > '7') */ + if ((_nc_syntax == SYN_TERMINFO) || !_nc_strict_bsd) { + switch (c) { + case 'a': + c = '\007'; + break; + case 'e': + c = '\033'; + break; + case 'l': + c = '\n'; + break; + case 's': + c = ' '; + break; + case ':': + c = ':'; + break; + default: + _nc_warning("Illegal character '%s' in \\ sequence", + unctrl(UChar(c))); + break; + } + } + /* FALLTHRU */ + case '|': + *(ptr++) = (char) c; + } /* endswitch (c) */ + } /* endelse (c < '0' || c > '7') */ } - /* end else if (ch == '\\') */ - else if (ch == '\n' && (_nc_syntax == SYN_TERMINFO)) { - /* newlines embedded in a terminfo string are ignored */ + /* end else if (c == '\\') */ + else if (c == '\n' && (_nc_syntax == SYN_TERMINFO)) { + /* + * Newlines embedded in a terminfo string are ignored, provided + * that the next line begins with whitespace. + */ ignored = TRUE; } else { - *(ptr++) = (char) ch; + *(ptr++) = (char) c; } if (!ignored) { - last_ch = ch; + if (_nc_curr_col <= 1) { + push_back((char) c); + c = '\n'; + break; + } + last_ch = c; count++; } ignored = FALSE; @@ -598,7 +895,7 @@ _nc_trans_string(char *ptr, char *last) *ptr = '\0'; - return (ch); + return (c); } /* @@ -608,26 +905,31 @@ _nc_trans_string(char *ptr, char *last) * get_token() call. */ -void +NCURSES_EXPORT(void) _nc_push_token(int tokclass) { /* - * This implementation is kind of bogus, it will fail if we ever do - * more than one pushback at a time between get_token() calls. It - * relies on the fact that curr_tok is static storage that nothing - * but get_token() touches. + * This implementation is kind of bogus, it will fail if we ever do more + * than one pushback at a time between get_token() calls. It relies on the + * fact that _nc_curr_token is static storage that nothing but + * _nc_get_token() touches. */ pushtype = tokclass; + if (pushname == 0) + pushname = typeMalloc(char, MAX_NAME_SIZE + 1); _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)); } /* * Panic mode error recovery - skip everything until a "ch" is found. */ -void +NCURSES_EXPORT(void) _nc_panic_mode(char ch) { int c; @@ -641,148 +943,15 @@ _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. - */ - -void -_nc_reset_input(FILE * fp, char *buf) -{ - pushtype = NO_PUSHBACK; - 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) +#if NO_LEAKS +NCURSES_EXPORT(void) +_nc_comp_scan_leaks(void) { - size_t len = strlen(bufptr); - while (len--) { - if (!isspace(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) { - 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 line[LEXBUFSIZ]; - size_t len; - - do { - _nc_curr_file_pos = ftell(yyin); - - if ((bufstart = fgets(line, LEXBUFSIZ, yyin)) != NULL) { - _nc_curr_line++; - _nc_curr_col = 0; - } - bufptr = bufstart; - } while - (bufstart != NULL && line[0] == '#'); - - if (bufstart == NULL) - return (EOF); - - 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') { - bufptr[len - 2] = '\n'; - bufptr[len - 1] = '\0'; - } - } + if (tok_buf != 0) { + FreeAndNull(tok_buf); } - - first_column = (bufptr == bufstart); - - _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); -} - -/* comp_scan.c ends here */ +#endif