X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Fcomp_scan.c;h=e1118f6f9ea927188f41e6c1c468c4723b9c89eb;hp=152930885ab75ffa9dc459205fd85ad44dec7ac9;hb=c633e5103a29a38532cf1925257b91cea33fd090;hpb=0eb88fc5281804773e2a0c7a488a4452463535ce;ds=sidebyside diff --git a/ncurses/tinfo/comp_scan.c b/ncurses/tinfo/comp_scan.c index 15293088..e1118f6f 100644 --- a/ncurses/tinfo/comp_scan.c +++ b/ncurses/tinfo/comp_scan.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998 Free Software Foundation, Inc. * + * Copyright (c) 1998,1999,2000 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 * @@ -47,9 +47,10 @@ #include #include +#include #include -MODULE_ID("$Id: comp_scan.c,v 1.34 1998/11/01 00:56:39 tom Exp $") +MODULE_ID("$Id: comp_scan.c,v 1.47 2000/09/24 01:15:17 tom Exp $") /* * Maximum length of string capability we'll accept before raising an error. @@ -59,11 +60,14 @@ MODULE_ID("$Id: comp_scan.c,v 1.34 1998/11/01 00:56:39 tom Exp $") #define iswhite(ch) (ch == ' ' || ch == '\t') -int _nc_syntax; /* termcap or terminfo? */ -long _nc_curr_file_pos; /* file offset of current line */ -long _nc_comment_start; /* start of comment range before name */ -long _nc_comment_end; /* end of comment range before name */ -long _nc_start_line; /* start line of current entry */ +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 */ + +struct token _nc_curr_token = +{0, 0, 0}; /***************************************************************************** * @@ -74,21 +78,26 @@ long _nc_start_line; /* start line of current entry */ static bool first_column; /* See 'next_char()' below */ static char separator; /* capability separator */ static int pushtype; /* type of pushback token */ -static char pushname[MAX_NAME_SIZE+1]; +static char pushname[MAX_NAME_SIZE + 1]; + +#if NCURSES_EXT_FUNCS +bool _nc_disable_period = FALSE; /* used by tic -a option */ +#endif -static int last_char(void); -static int next_char(void); +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); /* Assume we may be looking at a termcap-style continuation */ -static inline int eat_escaped_newline(int ch) +static inline int +eat_escaped_newline(int ch) { - if (ch == '\\') - while ((ch = next_char()) == '\n' || iswhite(ch)) - continue; - return ch; + if (ch == '\\') + while ((ch = next_char()) == '\n' || iswhite(ch)) + continue; + return ch; } /* @@ -124,316 +133,306 @@ static inline int eat_escaped_newline(int ch) * */ -int _nc_get_token(void) +int +_nc_get_token(void) { -static const char terminfo_punct[] = "@%&*!#"; -long number; -int type; -int ch; -char * numchk; -char numbuf[80]; -unsigned found; -static char buffer[MAX_ENTRY_SIZE]; -char *ptr; -int dot_flag = FALSE; -long token_start; - - if (pushtype != NO_PUSHBACK) - { - int retval = pushtype; - - _nc_set_type(pushname); - DEBUG(3, ("pushed-back token: `%s', class %d", - _nc_curr_token.tk_name, pushtype)); - - pushtype = NO_PUSHBACK; - pushname[0] = '\0'; - - /* currtok wasn't altered by _nc_push_token() */ - return(retval); - } + static const char terminfo_punct[] = "@%&*!#"; + long number; + int type; + int ch; + char *numchk; + char numbuf[80]; + unsigned found; + static char buffer[MAX_ENTRY_SIZE]; + char *ptr; + int dot_flag = FALSE; + long token_start; + + if (pushtype != NO_PUSHBACK) { + int retval = pushtype; + + _nc_set_type(pushname); + DEBUG(3, ("pushed-back token: `%s', class %d", + _nc_curr_token.tk_name, pushtype)); - if (end_of_stream()) - return(EOF); + pushtype = NO_PUSHBACK; + pushname[0] = '\0'; -start_token: - token_start = stream_pos(); - while ((ch = next_char()) == '\n' || iswhite(ch)) - continue; + /* currtok wasn't altered by _nc_push_token() */ + return (retval); + } - ch = eat_escaped_newline(ch); + if (end_of_stream()) + return (EOF); - if (ch == EOF) - type = EOF; - else { - /* if this is a termcap entry, skip a leading separator */ - if (separator == ':' && ch == ':') - ch = next_char(); + start_token: + token_start = stream_pos(); + while ((ch = next_char()) == '\n' || iswhite(ch)) + continue; - if (ch == '.') { - dot_flag = TRUE; - DEBUG(8, ("dot-flag set")); + ch = eat_escaped_newline(ch); - while ((ch = next_char())=='.' || iswhite(ch)) - continue; - } + if (ch == EOF) + type = EOF; + else { + /* if this is a termcap entry, skip a leading separator */ + if (separator == ':' && ch == ':') + ch = next_char(); - if (ch == EOF) { - type = EOF; - goto end_of_token; - } - - /* have to make some punctuation chars legal for terminfo */ - if (!isalnum(ch) && !strchr(terminfo_punct, (char)ch)) { - _nc_warning("Illegal character (expected alphanumeric or %s) - %s", - terminfo_punct, _tracechar((chtype)ch)); - _nc_panic_mode(separator); - goto start_token; - } + if (ch == '.' +#if NCURSES_EXT_FUNCS + && !_nc_disable_period +#endif + ) { + dot_flag = TRUE; + DEBUG(8, ("dot-flag set")); - ptr = buffer; - *(ptr++) = ch; - - if (first_column) { - char *desc; - - _nc_comment_start = token_start; - _nc_comment_end = _nc_curr_file_pos; - _nc_start_line = _nc_curr_line; - - _nc_syntax = ERR; - while ((ch = next_char()) != '\n') - { - if (ch == EOF) - _nc_err_abort("premature EOF"); - else if (ch == ':' && last_char() != ',') - { - _nc_syntax = SYN_TERMCAP; - separator = ':'; - break; - } - else if (ch == ',') - { - _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 - * either syntax. - */ - /* FALLTHRU */ - } - else - ch = eat_escaped_newline(ch); - - *ptr++ = ch; - } - ptr[0] = '\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. - */ - _nc_syntax = SYN_TERMCAP; - separator = ':'; - } - else if (_nc_syntax == SYN_TERMINFO) - { - /* throw away trailing /, *$/ */ - for (--ptr; iswhite(*ptr) || *ptr == ','; ptr--) - continue; - ptr[1] = '\0'; - } + while ((ch = next_char()) == '.' || iswhite(ch)) + continue; + } - /* - * This is the soonest we have the terminal name - * fetched. Set up for following warning messages. - */ - ptr = strchr(buffer, '|'); - if (ptr == (char *)NULL) - ptr = buffer + strlen(buffer); - ch = *ptr; - *ptr = '\0'; - _nc_set_type(buffer); - *ptr = ch; - - /* - * 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 (!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. - */ - for (ptr = buffer; ptr < desc; ptr++) - { - if (isspace(*ptr)) - { - _nc_warning("whitespace in name or alias field"); - break; - } - else if (*ptr == '/') - { - _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); - break; - } - } + if (ch == EOF) { + type = EOF; + goto end_of_token; + } - ptr = buffer; + /* have to make some punctuation chars legal for terminfo */ + if (!isalnum(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)); + _nc_panic_mode(separator); + goto start_token; + } - _nc_curr_token.tk_name = buffer; - type = NAMES; - } else { - while ((ch = next_char()) != EOF) { - if (!isalnum(ch)) { - if (_nc_syntax == SYN_TERMINFO) { - if (ch != '_') - break; - } else { /* allow ';' for "k;" */ - if (ch != ';') - break; - } - } - *(ptr++) = ch; - } + ptr = buffer; + *(ptr++) = ch; - *ptr++ = '\0'; - switch (ch) { - case ',': - case ':': - if (ch != separator) - _nc_err_abort("Separator inconsistent with syntax"); - _nc_curr_token.tk_name = buffer; - type = BOOLEAN; - break; - case '@': - if ((ch = next_char()) != separator) - _nc_warning("Missing separator after `%s', have %s", - buffer, _tracechar((chtype)ch)); - _nc_curr_token.tk_name = buffer; - type = CANCEL; - break; - - case '#': - found = 0; - while (isalnum(ch = next_char())) { - numbuf[found++] = 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; - type = NUMBER; - break; - - case '=': - ch = _nc_trans_string(ptr); - if (ch != separator) - _nc_warning("Missing separator"); - _nc_curr_token.tk_name = buffer; - _nc_curr_token.tk_valstring = ptr; - type = STRING; - break; - - case EOF: - type = EOF; - break; - default: - /* just to get rid of the compiler warning */ - type = UNDEF; - _nc_warning("Illegal character - %s", - _tracechar((chtype)ch)); - } - } /* end else (first_column == FALSE) */ - } /* end else (ch != EOF) */ + if (first_column) { + char *desc; -end_of_token: + _nc_comment_start = token_start; + _nc_comment_end = _nc_curr_file_pos; + _nc_start_line = _nc_curr_line; -#ifdef TRACE - if (dot_flag == TRUE) - DEBUG(8, ("Commented out ")); - - if (_nc_tracing & TRACE_IEVENT) - { - fprintf(stderr, "Token: "); - switch (type) - { - case BOOLEAN: - fprintf(stderr, "Boolean; name='%s'\n", - _nc_curr_token.tk_name); + _nc_syntax = ERR; + while ((ch = next_char()) != '\n') { + if (ch == EOF) + _nc_err_abort("premature EOF"); + else if (ch == ':' && last_char() != ',') { + _nc_syntax = SYN_TERMCAP; + separator = ':'; break; + } else if (ch == ',') { + _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 + * either syntax. + */ + /* FALLTHRU */ + } else + ch = eat_escaped_newline(ch); + + *ptr++ = ch; + } + ptr[0] = '\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. + */ + _nc_syntax = SYN_TERMCAP; + separator = ':'; + } else if (_nc_syntax == SYN_TERMINFO) { + /* throw away trailing /, *$/ */ + for (--ptr; iswhite(*ptr) || *ptr == ','; ptr--) + continue; + ptr[1] = '\0'; + } - case NUMBER: - fprintf(stderr, "Number; name='%s', value=%d\n", - _nc_curr_token.tk_name, - _nc_curr_token.tk_valnumber); + /* + * This is the soonest we have the terminal name + * fetched. Set up for following warning messages. + */ + ptr = strchr(buffer, '|'); + if (ptr == (char *) NULL) + ptr = buffer + strlen(buffer); + ch = *ptr; + *ptr = '\0'; + _nc_set_type(buffer); + *ptr = ch; + + /* + * 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 (!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. + */ + for (ptr = buffer; ptr < desc; ptr++) { + if (isspace(*ptr)) { + _nc_warning("whitespace in name or alias field"); break; - - case STRING: - fprintf(stderr, "String; name='%s', value=%s\n", - _nc_curr_token.tk_name, - _nc_visbuf(_nc_curr_token.tk_valstring)); + } else if (*ptr == '/') { + _nc_warning("slashes aren't allowed in names or aliases"); break; - - case CANCEL: - fprintf(stderr, "Cancel; name='%s'\n", - _nc_curr_token.tk_name); + } else if (strchr("$[]!*?", *ptr)) { + _nc_warning("dubious character `%c' in name or alias field", *ptr); break; + } + } - case NAMES: + ptr = buffer; - fprintf(stderr, "Names; value='%s'\n", - _nc_curr_token.tk_name); - break; + _nc_curr_token.tk_name = buffer; + type = NAMES; + } else { + while ((ch = next_char()) != EOF) { + if (!isalnum(ch)) { + if (_nc_syntax == SYN_TERMINFO) { + if (ch != '_') + break; + } else { /* allow ';' for "k;" */ + if (ch != ';') + break; + } + } + *(ptr++) = ch; + } - case EOF: - fprintf(stderr, "End of file\n"); - break; + *ptr++ = '\0'; + switch (ch) { + case ',': + case ':': + if (ch != separator) + _nc_err_abort("Separator inconsistent with syntax"); + _nc_curr_token.tk_name = buffer; + type = BOOLEAN; + break; + case '@': + if ((ch = next_char()) != separator) + _nc_warning("Missing separator after `%s', have %s", + buffer, unctrl(ch)); + _nc_curr_token.tk_name = buffer; + type = CANCEL; + break; - default: - _nc_warning("Bad token type"); + case '#': + found = 0; + while (isalnum(ch = next_char())) { + numbuf[found++] = 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; + type = NUMBER; + break; + + case '=': + ch = _nc_trans_string(ptr, buffer + sizeof(buffer)); + if (ch != separator) + _nc_warning("Missing separator"); + _nc_curr_token.tk_name = buffer; + _nc_curr_token.tk_valstring = ptr; + type = STRING; + break; + + case EOF: + type = EOF; + break; + default: + /* just to get rid of the compiler warning */ + type = UNDEF; + _nc_warning("Illegal character - %s", unctrl(ch)); } + } /* end else (first_column == FALSE) */ + } /* end else (ch != EOF) */ + + end_of_token: + +#ifdef TRACE + if (dot_flag == TRUE) + DEBUG(8, ("Commented out ")); + + if (_nc_tracing >= DEBUG_LEVEL(7)) { + switch (type) { + case BOOLEAN: + _tracef("Token: Boolean; name='%s'", + _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); + break; + + case STRING: + _tracef("Token: String; name='%s', value=%s", + _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); + break; + + case NAMES: + + _tracef("Token: Names; value='%s'", + _nc_curr_token.tk_name); + break; + + case EOF: + _tracef("Token: End of file"); + break; + + default: + _nc_warning("Bad token type"); } + } #endif - if (dot_flag == TRUE) /* if commented out, use the next one */ - type = _nc_get_token(); + if (dot_flag == TRUE) /* if commented out, use the next one */ + type = _nc_get_token(); - DEBUG(3, ("token: `%s', class %d", _nc_curr_token.tk_name, type)); + DEBUG(3, ("token: `%s', class %d", _nc_curr_token.tk_name, type)); - return(type); + return (type); } /* @@ -456,120 +455,150 @@ end_of_token: */ char -_nc_trans_string(char *ptr) +_nc_trans_string(char *ptr, char *last) { -int count = 0; -int number; -int i, c; -chtype ch, last_ch = '\0'; -bool ignored = FALSE; - - while ((ch = c = next_char()) != (chtype)separator && c != EOF) { - if ((_nc_syntax == SYN_TERMCAP) && c == '\n') - break; - if (ch == '^' && last_ch != '%') { - ch = c = next_char(); - if (c == EOF) - _nc_err_abort("Premature EOF"); - - if (! (is7bits(ch) && isprint(ch))) { - _nc_warning("Illegal ^ character - %s", - _tracechar((unsigned char)ch)); - } - if (ch == '?') { - *(ptr++) = '\177'; - } else { - if ((ch &= 037) == 0) - ch = 128; - *(ptr++) = (char)(ch); - } + int count = 0; + int number; + int i, c; + chtype ch, last_ch = '\0'; + bool ignored = FALSE; + bool long_warning = FALSE; + + while ((ch = c = next_char()) != (chtype) separator && c != EOF) { + if (ptr == (last - 1)) + break; + if ((_nc_syntax == SYN_TERMCAP) && c == '\n') + break; + if (ch == '^' && last_ch != '%') { + ch = c = next_char(); + if (c == EOF) + _nc_err_abort("Premature EOF"); + + if (!(is7bits(ch) && isprint(ch))) { + _nc_warning("Illegal ^ character - %s", unctrl(ch)); + } + if (ch == '?') { + *(ptr++) = '\177'; + if (_nc_tracing) + _nc_warning("Allow ^? as synonym for \\177"); + } else { + if ((ch &= 037) == 0) + ch = 128; + *(ptr++) = (char) (ch); } - else if (ch == '\\') { - ch = c = next_char(); - if (c == EOF) - _nc_err_abort("Premature EOF"); - - if (ch >= '0' && ch <= '7') { - number = ch - '0'; - for (i=0; i < 2; i++) { - ch = c = next_char(); - if (c == EOF) - _nc_err_abort("Premature EOF"); - - if (c < '0' || c > '7') { - if (isdigit(c)) { - _nc_warning("Non-octal digit `%c' in \\ sequence", c); - /* allow the digit; it'll do less harm */ - } else { - push_back((char)c); - break; - } + } else if (ch == '\\') { + ch = c = next_char(); + if (c == EOF) + _nc_err_abort("Premature EOF"); + + if (ch >= '0' && ch <= '7') { + number = ch - '0'; + for (i = 0; i < 2; i++) { + ch = c = next_char(); + if (c == EOF) + _nc_err_abort("Premature EOF"); + + if (c < '0' || c > '7') { + if (isdigit(c)) { + _nc_warning("Non-octal digit `%c' in \\ sequence", c); + /* allow the digit; it'll do less harm */ + } else { + push_back((char) c); + break; } - - number = number * 8 + c - '0'; } - if (number == 0) - number = 0200; - *(ptr++) = (char) number; - } else { - switch (c) { - case 'E': - case 'e': *(ptr++) = '\033'; break; + number = number * 8 + c - '0'; + } + + if (number == 0) + number = 0200; + *(ptr++) = (char) number; + } else { + switch (c) { + case 'E': + case 'e': + *(ptr++) = '\033'; + break; - case 'a': *(ptr++) = '\007'; break; + case 'a': + *(ptr++) = '\007'; + break; - case 'l': - case 'n': *(ptr++) = '\n'; break; + case 'l': + case 'n': + *(ptr++) = '\n'; + break; - case 'r': *(ptr++) = '\r'; break; + case 'r': + *(ptr++) = '\r'; + break; - case 'b': *(ptr++) = '\010'; break; + case 'b': + *(ptr++) = '\010'; + break; - case 's': *(ptr++) = ' '; break; + case 's': + *(ptr++) = ' '; + break; - case 'f': *(ptr++) = '\014'; break; + case 'f': + *(ptr++) = '\014'; + break; - case 't': *(ptr++) = '\t'; break; + case 't': + *(ptr++) = '\t'; + break; - case '\\': *(ptr++) = '\\'; break; + case '\\': + *(ptr++) = '\\'; + break; - case '^': *(ptr++) = '^'; break; + case '^': + *(ptr++) = '^'; + break; - case ',': *(ptr++) = ','; break; + case ',': + *(ptr++) = ','; + break; - case ':': *(ptr++) = ':'; break; + case ':': + *(ptr++) = ':'; + break; - case '\n': - continue; + case '\n': + continue; - default: - _nc_warning("Illegal character %s in \\ sequence", - _tracechar((unsigned char)ch)); - *(ptr++) = (char)ch; - } /* endswitch (ch) */ - } /* endelse (ch < '0' || ch > '7') */ - } /* end else if (ch == '\\') */ - else if (ch == '\n' && (_nc_syntax == SYN_TERMINFO)) { - /* newlines embedded in a terminfo string are ignored */ - ignored = TRUE; - } else { - *(ptr++) = (char)ch; - } + default: + _nc_warning("Illegal character %s in \\ sequence", + unctrl(ch)); + *(ptr++) = (char) ch; + } /* endswitch (ch) */ + } /* endelse (ch < '0' || ch > '7') */ + } + /* end else if (ch == '\\') */ + else if (ch == '\n' && (_nc_syntax == SYN_TERMINFO)) { + /* newlines embedded in a terminfo string are ignored */ + ignored = TRUE; + } else { + *(ptr++) = (char) ch; + } - if (!ignored) { - last_ch = ch; - count ++; - } - ignored = FALSE; + if (!ignored) { + last_ch = ch; + count++; + } + ignored = FALSE; - if (count > MAXCAPLEN) - _nc_warning("Very long string found. Missing separator?"); - } /* end while */ + if (count > MAXCAPLEN && !long_warning) { + _nc_warning("Very long string found. Missing separator?"); + long_warning = TRUE; + } + } /* end while */ - *ptr = '\0'; + *ptr = '\0'; - return(ch); + return (ch); } /* @@ -579,7 +608,8 @@ bool ignored = FALSE; * get_token() call. */ -void _nc_push_token(int tokclass) +void +_nc_push_token(int tokclass) { /* * This implementation is kind of bogus, it will fail if we ever do @@ -597,17 +627,18 @@ void _nc_push_token(int tokclass) /* * Panic mode error recovery - skip everything until a "ch" is found. */ -void _nc_panic_mode(char ch) +void +_nc_panic_mode(char ch) { - int c; - - for (;;) { - c = next_char(); - if (c == ch) - return; - if (c == EOF) - return; - } + int c; + + for (;;) { + c = next_char(); + if (c == ch) + return; + if (c == EOF) + return; + } } /***************************************************************************** @@ -630,16 +661,17 @@ static FILE *yyin; /* scanner's input file descriptor */ * non-null. */ -void _nc_reset_input(FILE *fp, char *buf) +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; + 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; } /* @@ -650,12 +682,12 @@ void _nc_reset_input(FILE *fp, char *buf) static int last_char(void) { - size_t len = strlen(bufptr); - while (len--) { - if (!isspace(bufptr[len])) - return bufptr[len]; - } - return 0; + size_t len = strlen(bufptr); + while (len--) { + if (!isspace(bufptr[len])) + return bufptr[len]; + } + return 0; } /* @@ -675,17 +707,14 @@ last_char(void) static int next_char(void) { - if (!yyin) - { + if (!yyin) { if (*bufptr == '\0') - return(EOF); + return (EOF); if (*bufptr == '\n') { _nc_curr_line++; _nc_curr_col = 0; } - } - else if (!bufptr || !*bufptr) - { + } 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 @@ -697,17 +726,17 @@ next_char(void) size_t len; do { - _nc_curr_file_pos = ftell(yyin); + _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 = fgets(line, LEXBUFSIZ, yyin)) != NULL) { + _nc_curr_line++; + _nc_curr_col = 0; + } + bufptr = bufstart; + } while + (bufstart != NULL && line[0] == '#'); - if (bufstart == NULL) + if (bufstart == NULL || *bufstart == 0) return (EOF); while (iswhite(*bufptr)) @@ -718,35 +747,47 @@ next_char(void) * 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 (bufptr[len - 1] == '\n' + && bufptr[len - 2] == '\r') { + len--; + bufptr[len - 1] = '\n'; + bufptr[len] = '\0'; } } + + /* + * If we don't have a trailing newline, it's because the line is simply + * too long. Give up. (FIXME: We could instead reallocate the line + * buffer and allow arbitrary-length lines). + */ + if (len == 0 || (bufptr[len - 1] != '\n')) + return (EOF); } first_column = (bufptr == bufstart); _nc_curr_col++; - return(*bufptr++); + return (*bufptr++); } -static void push_back(char c) +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"); + _nc_syserr_abort("Can't backspace off beginning of line"); *--bufptr = c; } -static long stream_pos(void) +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) +static bool +end_of_stream(void) /* are we at end of input? */ { return ((yyin ? feof(yyin) : (bufptr && *bufptr == '\0'))