From: Zack Weinberg Date: Mon, 13 Mar 2000 22:01:08 +0000 (+0000) Subject: Makefile.in (LIBCPP_OBJS): Add cpplex.o. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=45b966db65e4ab054d31f01f65b7a98023dbcb54;p=platform%2Fupstream%2Fgcc.git Makefile.in (LIBCPP_OBJS): Add cpplex.o. * Makefile.in (LIBCPP_OBJS): Add cpplex.o. (cpplex.o): New target. * po/POTFILES.in: Add cpplex.c. * cpplex.c (_cpp_grow_token_buffer, null_cleanup, cpp_push_buffer, cpp_pop_buffer, cpp_scan_buffer, cpp_expand_to_buffer, cpp_buf_line_and_col, cpp_file_buffer, skip_block_comment, skip_line_comment, skip_comment, copy_comment, _cpp_skip_hspace, _cpp_skip_rest_of_line, _cpp_parse_name, skip_string, parse_string, _cpp_parse_assertion, cpp_get_token, cpp_get_non_space_token, _cpp_get_directive_token, find_position, _cpp_read_and_prescan, _cpp_init_input_buffer): Move here. (maybe_macroexpand, _cpp_lex_token): New functions. * cpplib.c (SKIP_WHITE_SPACE, eval_if_expr, parse_set_mark, parse_goto_mark): Delete. (_cpp_handle_eof): New function. (_cpp_handle_directive): Rename from handle_directive. (_cpp_output_line_command): Rename from output_line_command. (do_if, do_elif): Call _cpp_parse_expr directly. * cppfiles.c (_cpp_read_include_file): Don't call init_input_buffer here. * cpphash.c (quote_string): Move here, rename _cpp_quote_string. * cppexp.c (_cpp_parse_expr): Diddle parsing_if_directive here; pop the token_buffer and skip the rest of the line here. * cppinit.c (cpp_start_read): Call _cpp_init_input_buffer here. * cpphash.h (CPP_RESERVE, CPP_IS_MACRO_BUFFER, ACTIVE_MARK_P): Define here. (CPP_SET_BUF_MARK, CPP_GOTO_BUF_MARK, CPP_SET_MARK, CPP_GOTO_MARK): New macros. (_cpp_quote_string, _cpp_parse_name, _cpp_skip_rest_of_line, _cpp_skip_hspace, _cpp_parse_assertion, _cpp_lex_token, _cpp_read_and_prescan, _cpp_init_input_buffer, _cpp_grow_token_buffer, _cpp_get_directive_token, _cpp_handle_directive, _cpp_handle_eof, _cpp_output_line_command): Prototype them here. * cpplib.h (enum cpp_token): Add CPP_MACRO. (CPP_RESERVE, get_directive_token, cpp_grow_buffer, quote_string, output_line_command): Remove. From-SVN: r32513 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1589abd..0abf7f5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,48 @@ +2000-03-13 Zack Weinberg + + * Makefile.in (LIBCPP_OBJS): Add cpplex.o. + (cpplex.o): New target. + * po/POTFILES.in: Add cpplex.c. + + * cpplex.c (_cpp_grow_token_buffer, null_cleanup, + cpp_push_buffer, cpp_pop_buffer, cpp_scan_buffer, + cpp_expand_to_buffer, cpp_buf_line_and_col, cpp_file_buffer, + skip_block_comment, skip_line_comment, skip_comment, + copy_comment, _cpp_skip_hspace, _cpp_skip_rest_of_line, + _cpp_parse_name, skip_string, parse_string, + _cpp_parse_assertion, cpp_get_token, cpp_get_non_space_token, + _cpp_get_directive_token, find_position, + _cpp_read_and_prescan, _cpp_init_input_buffer): Move here. + (maybe_macroexpand, _cpp_lex_token): New functions. + + * cpplib.c (SKIP_WHITE_SPACE, eval_if_expr, parse_set_mark, + parse_goto_mark): Delete. + (_cpp_handle_eof): New function. + (_cpp_handle_directive): Rename from handle_directive. + (_cpp_output_line_command): Rename from output_line_command. + (do_if, do_elif): Call _cpp_parse_expr directly. + * cppfiles.c (_cpp_read_include_file): Don't call + init_input_buffer here. + * cpphash.c (quote_string): Move here, rename _cpp_quote_string. + * cppexp.c (_cpp_parse_expr): Diddle parsing_if_directive + here; pop the token_buffer and skip the rest of the line here. + * cppinit.c (cpp_start_read): Call _cpp_init_input_buffer + here. + + * cpphash.h (CPP_RESERVE, CPP_IS_MACRO_BUFFER, ACTIVE_MARK_P): + Define here. + (CPP_SET_BUF_MARK, CPP_GOTO_BUF_MARK, CPP_SET_MARK, + CPP_GOTO_MARK): New macros. + (_cpp_quote_string, _cpp_parse_name, _cpp_skip_rest_of_line, + _cpp_skip_hspace, _cpp_parse_assertion, _cpp_lex_token, + _cpp_read_and_prescan, _cpp_init_input_buffer, + _cpp_grow_token_buffer, _cpp_get_directive_token, + _cpp_handle_directive, _cpp_handle_eof, + _cpp_output_line_command): Prototype them here. + * cpplib.h (enum cpp_token): Add CPP_MACRO. + (CPP_RESERVE, get_directive_token, cpp_grow_buffer, + quote_string, output_line_command): Remove. + 2000-03-13 Bernd Schmidt * stmt.c (expand_end_case): RANGE may be signed, and when checking diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 9fff80b..3da6452 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2025,7 +2025,7 @@ cccp.o: cccp.c $(CONFIG_H) intl.h pcp.h version.c config.status system.h \ -c `echo $(srcdir)/cccp.c | sed 's,^\./,,'` LIBCPP_OBJS = cpplib.o cpphash.o cpperror.o cppexp.o cppfiles.o \ - cppinit.o cppulp.o mkdeps.o \ + cppinit.o cppulp.o cpplex.o mkdeps.o \ prefix.o version.o mbchar.o @extra_cpp_objs@ LIBCPP_DEPS = cpplib.h cpphash.h intl.h system.h @@ -2048,6 +2048,7 @@ cppmain.o: cppmain.c $(CONFIG_H) cpplib.h intl.h system.h cppulp.o: cppulp.c $(CONFIG_H) system.h output.h cpperror.o: cpperror.c $(CONFIG_H) $(LIBCPP_DEPS) cppexp.o: cppexp.c $(CONFIG_H) $(LIBCPP_DEPS) +cpplex.o: cpplex.c $(CONFIG_H) $(LIBCPP_DEPS) cppfiles.o: cppfiles.c $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H) cpphash.o: cpphash.c $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H) cpplib.o: cpplib.c $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H) mkdeps.h diff --git a/gcc/cppexp.c b/gcc/cppexp.c index bb2ae7a..4d1cf10 100644 --- a/gcc/cppexp.c +++ b/gcc/cppexp.c @@ -352,12 +352,12 @@ parse_defined (pfile) op.op = INT; pfile->no_macro_expand++; - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); if (token == CPP_LPAREN) { paren++; CPP_SET_WRITTEN (pfile, old_written); - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); } if (token != CPP_NAME) @@ -369,7 +369,7 @@ parse_defined (pfile) if (paren) { - if (get_directive_token (pfile) != CPP_RPAREN) + if (_cpp_get_directive_token (pfile) != CPP_RPAREN) goto oops; } CPP_SET_WRITTEN (pfile, old_written); @@ -419,7 +419,7 @@ lex (pfile, skip_evaluation) long old_written; old_written = CPP_WRITTEN (pfile); - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); tok_start = pfile->token_buffer + old_written; tok_end = CPP_PWRITTEN (pfile); @@ -689,7 +689,10 @@ _cpp_parse_expr (pfile) register struct operation *top = stack; unsigned int lprio, rprio = 0; int skip_evaluation = 0; + long old_written = CPP_WRITTEN (pfile); + int result; + pfile->parsing_if_directive++; top->rprio = 0; top->flags = 0; for (;;) @@ -999,9 +1002,8 @@ _cpp_parse_expr (pfile) { if (top != stack) cpp_ice (pfile, "unbalanced stack in #if expression"); - if (stack != init_stack) - free (stack); - return (top->value != 0); + result = (top->value != 0); + goto done; } top++; @@ -1041,7 +1043,12 @@ _cpp_parse_expr (pfile) } } syntax_error: + _cpp_skip_rest_of_line (pfile); + result = 0; + done: + pfile->parsing_if_directive--; + CPP_SET_WRITTEN (pfile, old_written); if (stack != init_stack) free (stack); - return 0; + return result; } diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c index 3354663..ec7529f 100644 --- a/gcc/cppfiles.c +++ b/gcc/cppfiles.c @@ -38,17 +38,13 @@ static struct file_name_map *read_name_map static char *read_filename_string PARAMS ((int, FILE *)); static char *remap_filename PARAMS ((cpp_reader *, char *, struct file_name_list *)); -static long read_and_prescan PARAMS ((cpp_reader *, cpp_buffer *, - int, size_t)); static struct file_name_list *actual_directory PARAMS ((cpp_reader *, const char *)); static unsigned int hash_IHASH PARAMS ((const void *)); static int eq_IHASH PARAMS ((const void *, const void *)); -static void init_input_buffer PARAMS ((cpp_reader *, int, struct stat *)); static int file_cleanup PARAMS ((cpp_buffer *, cpp_reader *)); -static U_CHAR *find_position PARAMS ((U_CHAR *, U_CHAR *, unsigned long *)); #if 0 static void hack_vms_include_specification PARAMS ((char *)); @@ -587,14 +583,11 @@ _cpp_read_include_file (pfile, fd, ihash) goto fail; } - if (pfile->input_buffer == NULL) - init_input_buffer (pfile, fd, &st); - /* Read the file, converting end-of-line characters and trigraphs (if enabled). */ fp->ihash = ihash; fp->nominal_fname = ihash->name; - length = read_and_prescan (pfile, fp, fd, st_size); + length = _cpp_read_and_prescan (pfile, fp, fd, st_size); if (length < 0) goto fail; if (length == 0) @@ -687,402 +680,6 @@ actual_directory (pfile, fname) return x; } -/* Determine the current line and column. Used only by read_and_prescan. */ -static U_CHAR * -find_position (start, limit, linep) - U_CHAR *start; - U_CHAR *limit; - unsigned long *linep; -{ - unsigned long line = *linep; - U_CHAR *lbase = start; - while (start < limit) - { - U_CHAR ch = *start++; - if (ch == '\n' || ch == '\r') - { - line++; - lbase = start; - } - } - *linep = line; - return lbase; -} - -/* Read the entire contents of file DESC into buffer BUF. LEN is how - much memory to allocate initially; more will be allocated if - necessary. Convert end-of-line markers (\n, \r, \r\n, \n\r) to - canonical form (\n). If enabled, convert and/or warn about - trigraphs. Convert backslash-newline to a one-character escape - (\r) and remove it from "embarrassing" places (i.e. the middle of a - token). If there is no newline at the end of the file, add one and - warn. Returns -1 on failure, or the actual length of the data to - be scanned. - - This function does a lot of work, and can be a serious performance - bottleneck. It has been tuned heavily; make sure you understand it - before hacking. The common case - no trigraphs, Unix style line - breaks, backslash-newline set off by whitespace, newline at EOF - - has been optimized at the expense of the others. The performance - penalty for DOS style line breaks (\r\n) is about 15%. - - Warnings lose particularly heavily since we have to determine the - line number, which involves scanning from the beginning of the file - or from the last warning. The penalty for the absence of a newline - at the end of reload1.c is about 60%. (reload1.c is 329k.) - - If your file has more than one kind of end-of-line marker, you - will get messed-up line numbering. */ - -/* Table of characters that can't be handled in the inner loop. - Keep these contiguous to optimize the performance of the code generated - for the switch that uses them. */ -#define SPECCASE_EMPTY 0 -#define SPECCASE_NUL 1 -#define SPECCASE_CR 2 -#define SPECCASE_BACKSLASH 3 -#define SPECCASE_QUESTION 4 - -static long -read_and_prescan (pfile, fp, desc, len) - cpp_reader *pfile; - cpp_buffer *fp; - int desc; - size_t len; -{ - U_CHAR *buf = (U_CHAR *) xmalloc (len); - U_CHAR *ip, *op, *line_base; - U_CHAR *ibase; - U_CHAR *speccase = pfile->input_speccase; - unsigned long line; - unsigned int deferred_newlines; - int count; - size_t offset; - - offset = 0; - op = buf; - line_base = buf; - line = 1; - ibase = pfile->input_buffer + 2; - deferred_newlines = 0; - - for (;;) - { - read_next: - - count = read (desc, pfile->input_buffer + 2, pfile->input_buffer_len); - if (count < 0) - goto error; - else if (count == 0) - break; - - offset += count; - ip = ibase; - ibase = pfile->input_buffer + 2; - ibase[count] = ibase[count+1] = '\0'; - - if (offset > len) - { - size_t delta_op; - size_t delta_line_base; - len *= 2; - if (offset > len) - /* len overflowed. - This could happen if the file is larger than half the - maximum address space of the machine. */ - goto too_big; - - delta_op = op - buf; - delta_line_base = line_base - buf; - buf = (U_CHAR *) xrealloc (buf, len); - op = buf + delta_op; - line_base = buf + delta_line_base; - } - - for (;;) - { - unsigned int span = 0; - - /* Deal with \-newline in the middle of a token. */ - if (deferred_newlines) - { - while (speccase[ip[span]] == SPECCASE_EMPTY - && ip[span] != '\n' - && ip[span] != '\t' - && ip[span] != ' ') - span++; - memcpy (op, ip, span); - op += span; - ip += span; - /* If ip[0] is SPECCASE_EMPTY, we have hit white space. - Dump out the remaining deferred \-newlines. */ - if (speccase[ip[0]] == SPECCASE_EMPTY) - while (deferred_newlines) - deferred_newlines--, *op++ = '\r'; - span = 0; - } - - /* Copy as much as we can without special treatment. */ - while (speccase[ip[span]] == SPECCASE_EMPTY) span++; - memcpy (op, ip, span); - op += span; - ip += span; - - switch (speccase[*ip++]) - { - case SPECCASE_NUL: /* \0 */ - ibase[-1] = op[-1]; - goto read_next; - - case SPECCASE_CR: /* \r */ - if (ip[-2] == '\n') - continue; - else if (*ip == '\n') - ip++; - else if (*ip == '\0') - { - *--ibase = '\r'; - goto read_next; - } - *op++ = '\n'; - break; - - case SPECCASE_BACKSLASH: /* \ */ - backslash: - { - /* If we're at the end of the intermediate buffer, - we have to shift the backslash down to the start - and come back next pass. */ - if (*ip == '\0') - { - *--ibase = '\\'; - goto read_next; - } - else if (*ip == '\n') - { - ip++; - if (*ip == '\r') ip++; - if (*ip == '\n' || *ip == '\t' || *ip == ' ') - *op++ = '\r'; - else if (op[-1] == '\t' || op[-1] == ' ' - || op[-1] == '\r' || op[-1] == '\n') - *op++ = '\r'; - else - deferred_newlines++; - } - else if (*ip == '\r') - { - ip++; - if (*ip == '\n') ip++; - else if (*ip == '\0') - { - *--ibase = '\r'; - *--ibase = '\\'; - goto read_next; - } - else if (*ip == '\r' || *ip == '\t' || *ip == ' ') - *op++ = '\r'; - else - deferred_newlines++; - } - else - *op++ = '\\'; - } - break; - - case SPECCASE_QUESTION: /* ? */ - { - unsigned int d, t; - /* If we're at the end of the intermediate buffer, - we have to shift the ?'s down to the start and - come back next pass. */ - d = ip[0]; - if (d == '\0') - { - *--ibase = '?'; - goto read_next; - } - if (d != '?') - { - *op++ = '?'; - break; - } - d = ip[1]; - if (d == '\0') - { - *--ibase = '?'; - *--ibase = '?'; - goto read_next; - } - - /* Trigraph map: - * from to from to from to - * ?? = # ?? ) ] ?? ! | - * ?? ( [ ?? ' ^ ?? > } - * ?? / \ ?? < { ?? - ~ - */ - if (d == '=') t = '#'; - else if (d == ')') t = ']'; - else if (d == '!') t = '|'; - else if (d == '(') t = '['; - else if (d == '\'') t = '^'; - else if (d == '>') t = '}'; - else if (d == '/') t = '\\'; - else if (d == '<') t = '{'; - else if (d == '-') t = '~'; - else - { - *op++ = '?'; - break; - } - ip += 2; - if (CPP_OPTIONS (pfile)->warn_trigraphs) - { - unsigned long col; - line_base = find_position (line_base, op, &line); - col = op - line_base + 1; - if (CPP_OPTIONS (pfile)->trigraphs) - cpp_warning_with_line (pfile, line, col, - "trigraph ??%c converted to %c", d, t); - else - cpp_warning_with_line (pfile, line, col, - "trigraph ??%c ignored", d); - } - if (CPP_OPTIONS (pfile)->trigraphs) - { - if (t == '\\') - goto backslash; - else - *op++ = t; - } - else - { - *op++ = '?'; - *op++ = '?'; - *op++ = d; - } - } - } - } - } - - if (offset == 0) - return 0; - - /* Deal with pushed-back chars at true EOF. - This may be any of: ?? ? \ \r \n \\r \\n. - \r must become \n, \\r or \\n must become \r. - We know we have space already. */ - if (ibase == pfile->input_buffer) - { - if (*ibase == '?') - { - *op++ = '?'; - *op++ = '?'; - } - else - *op++ = '\r'; - } - else if (ibase == pfile->input_buffer + 1) - { - if (*ibase == '\r') - *op++ = '\n'; - else - *op++ = *ibase; - } - - if (op[-1] != '\n') - { - unsigned long col; - line_base = find_position (line_base, op, &line); - col = op - line_base + 1; - cpp_warning_with_line (pfile, line, col, "no newline at end of file\n"); - if (offset + 1 > len) - { - len += 1; - if (offset + 1 > len) - goto too_big; - buf = (U_CHAR *) xrealloc (buf, len); - op = buf + offset; - } - *op++ = '\n'; - } - - fp->buf = ((len - offset < 20) ? buf : (U_CHAR *)xrealloc (buf, op - buf)); - return op - buf; - - too_big: - cpp_error (pfile, "file is too large (>%lu bytes)\n", (unsigned long)offset); - free (buf); - return -1; - - error: - cpp_error_from_errno (pfile, fp->ihash->name); - free (buf); - return -1; -} - -/* Initialize the `input_buffer' and `input_speccase' tables. - These are only used by read_and_prescan, but they're large and - somewhat expensive to set up, so we want them allocated once for - the duration of the cpp run. */ - -static void -init_input_buffer (pfile, fd, st) - cpp_reader *pfile; - int fd; - struct stat *st; -{ - long pipe_buf; - U_CHAR *tmp; - - /* Table of characters that cannot be handled by the - read_and_prescan inner loop. The number of non-EMPTY entries - should be as small as humanly possible. */ - - tmp = (U_CHAR *) xmalloc (1 << CHAR_BIT); - memset (tmp, SPECCASE_EMPTY, 1 << CHAR_BIT); - tmp['\0'] = SPECCASE_NUL; - tmp['\r'] = SPECCASE_CR; - tmp['\\'] = SPECCASE_BACKSLASH; - if (CPP_OPTIONS (pfile)->trigraphs || CPP_OPTIONS (pfile)->warn_trigraphs) - tmp['?'] = SPECCASE_QUESTION; - - pfile->input_speccase = tmp; - - /* Determine the appropriate size for the input buffer. Normal C - source files are smaller than eight K. If we are reading a pipe, - we want to make sure the input buffer is bigger than the kernel's - pipe buffer. */ - pipe_buf = -1; - - if (! S_ISREG (st->st_mode)) - { -#ifdef _PC_PIPE_BUF - pipe_buf = fpathconf (fd, _PC_PIPE_BUF); -#endif - if (pipe_buf == -1) - { -#ifdef PIPE_BUF - pipe_buf = PIPE_BUF; -#else - pipe_buf = 8192; -#endif - } - } - - if (pipe_buf < 8192) - pipe_buf = 8192; - /* PIPE_BUF bytes of buffer proper, 2 to detect running off the end - without address arithmetic all the time, and 2 for pushback in - the case there's a potential trigraph or end-of-line digraph at - the end of a block. */ - - tmp = (U_CHAR *) xmalloc (pipe_buf + 2 + 2); - pfile->input_buffer = tmp; - pfile->input_buffer_len = pipe_buf; -} - /* Simplify a path name in place, deleting redundant components. This reduces OS overhead and guarantees that equivalent paths compare the same (modulo symlinks). diff --git a/gcc/cpphash.c b/gcc/cpphash.c index 3d48e8c..d3dac0b 100644 --- a/gcc/cpphash.c +++ b/gcc/cpphash.c @@ -307,7 +307,7 @@ collect_expansion (pfile, arglist) last -= 2; /* two extra chars for the leading escape */ for (;;) { - /* We use cpp_get_token because get_directive_token would + /* We use cpp_get_token because _cpp_get_directive_token would discard whitespace and we can't cope with that yet. Macro expansion is off, so we are guaranteed not to see POP or EOF. */ @@ -570,7 +570,7 @@ collect_formal_parameters (pfile) long old_written; old_written = CPP_WRITTEN (pfile); - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); if (token != CPP_LPAREN) { cpp_ice (pfile, "first token = %d not %d in collect_formal_parameters", @@ -584,7 +584,7 @@ collect_formal_parameters (pfile) for (;;) { CPP_SET_WRITTEN (pfile, old_written); - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); switch (token) { case CPP_NAME: @@ -660,7 +660,7 @@ collect_formal_parameters (pfile) argv[argc].rest_arg = 1; - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); if (token != CPP_RPAREN) { cpp_error (pfile, "another parameter follows `...'"); @@ -826,6 +826,43 @@ static const char * const monthnames[] = "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }; +/* Place into PFILE a quoted string representing the string SRC. + Caller must reserve enough space in pfile->token_buffer. */ + +void +_cpp_quote_string (pfile, src) + cpp_reader *pfile; + const char *src; +{ + U_CHAR c; + + CPP_PUTC_Q (pfile, '\"'); + for (;;) + switch ((c = *src++)) + { + default: + if (ISPRINT (c)) + CPP_PUTC_Q (pfile, c); + else + { + sprintf ((char *)CPP_PWRITTEN (pfile), "\\%03o", c); + CPP_ADJUST_WRITTEN (pfile, 4); + } + break; + + case '\"': + case '\\': + CPP_PUTC_Q (pfile, '\\'); + CPP_PUTC_Q (pfile, c); + break; + + case '\0': + CPP_PUTC_Q (pfile, '\"'); + CPP_NUL_TERMINATE_Q (pfile); + return; + } +} + /* * expand things like __FILE__. Place the expansion into the output * buffer *without* rescanning. @@ -857,7 +894,7 @@ special_symbol (hp, pfile) if (!buf) buf = ""; CPP_RESERVE (pfile, 3 + 4 * strlen (buf)); - quote_string (pfile, buf); + _cpp_quote_string (pfile, buf); return; } @@ -1597,7 +1634,7 @@ _cpp_dump_definition (pfile, sym, len, defn) DEFINITION *defn; { if (pfile->lineno == 0) - output_line_command (pfile, same_file); + _cpp_output_line_command (pfile, same_file); CPP_RESERVE (pfile, len + sizeof "#define "); CPP_PUTS_Q (pfile, "#define ", sizeof "#define " -1); diff --git a/gcc/cpphash.h b/gcc/cpphash.h index c842ea6..4468d42 100644 --- a/gcc/cpphash.h +++ b/gcc/cpphash.h @@ -217,6 +217,11 @@ extern unsigned char _cpp_IStable[256]; ((BUFFER)->cur < (BUFFER)->rlimit ? *(BUFFER)->cur++ : EOF) #define CPP_FORWARD(BUFFER, N) ((BUFFER)->cur += (N)) +/* Make sure PFILE->token_buffer has space for at least N more characters. */ +#define CPP_RESERVE(PFILE, N) \ + (CPP_WRITTEN (PFILE) + (size_t)(N) > (PFILE)->token_buffer_size \ + && (_cpp_grow_token_buffer (PFILE, N), 0)) + /* Append string STR (of length N) to PFILE's output buffer. Assume there is enough space. */ #define CPP_PUTS_Q(PFILE, STR, N) \ @@ -242,6 +247,29 @@ extern unsigned char _cpp_IStable[256]; #define CPP_PEDANTIC(PFILE) \ (CPP_OPTIONS (PFILE)->pedantic && !CPP_BUFFER (pfile)->system_header_p) +/* CPP_IS_MACRO_BUFFER is true if the buffer contains macro expansion. + (Note that it is false while we're expanding macro *arguments*.) */ +#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->data != NULL) + +/* Remember the current position of PFILE so it may be returned to + after looking ahead a bit. + + Note that when you set a mark, you _must_ return to that mark. You + may not forget about it and continue parsing. You may not pop a + buffer with an active mark. You may not call CPP_BUMP_LINE while a + mark is active. */ +#define CPP_SET_BUF_MARK(IP) ((IP)->mark = (IP)->cur - (IP)->buf) +#define CPP_GOTO_BUF_MARK(IP) ((IP)->cur = (IP)->buf + (IP)->mark, \ + (IP)->mark = -1) +#define CPP_SET_MARK(PFILE) CPP_SET_BUF_MARK(CPP_BUFFER(PFILE)) +#define CPP_GOTO_MARK(PFILE) CPP_GOTO_BUF_MARK(CPP_BUFFER(PFILE)) + +/* ACTIVE_MARK_P is true if there's a live mark in the buffer. */ +#define ACTIVE_MARK_P(PFILE) (CPP_BUFFER (PFILE)->mark != -1) + +/* Last arg to output_line_command. */ +enum file_change_code {same_file, rename_file, enter_file, leave_file}; + /* In cpphash.c */ extern HASHNODE *_cpp_make_hashnode PARAMS ((const U_CHAR *, size_t, enum node_type, @@ -257,6 +285,7 @@ extern void _cpp_dump_definition PARAMS ((cpp_reader *, const U_CHAR *, long, DEFINITION *)); extern int _cpp_compare_defs PARAMS ((cpp_reader *, DEFINITION *, DEFINITION *)); +extern void _cpp_quote_string PARAMS ((cpp_reader *, const char *)); extern void _cpp_macroexpand PARAMS ((cpp_reader *, HASHNODE *)); extern void _cpp_init_macro_hash PARAMS ((cpp_reader *)); extern void _cpp_dump_macro_hash PARAMS ((cpp_reader *)); @@ -272,4 +301,24 @@ extern void _cpp_init_include_hash PARAMS ((cpp_reader *)); /* In cppexp.c */ extern int _cpp_parse_expr PARAMS ((cpp_reader *)); +/* In cpplex.c */ +extern void _cpp_parse_name PARAMS ((cpp_reader *, int)); +extern void _cpp_skip_rest_of_line PARAMS ((cpp_reader *)); +extern void _cpp_skip_hspace PARAMS ((cpp_reader *)); +extern int _cpp_parse_assertion PARAMS ((cpp_reader *)); +extern enum cpp_token _cpp_lex_token PARAMS ((cpp_reader *)); +extern long _cpp_read_and_prescan PARAMS ((cpp_reader *, cpp_buffer *, + int, size_t)); +extern void _cpp_init_input_buffer PARAMS ((cpp_reader *)); +extern void _cpp_grow_token_buffer PARAMS ((cpp_reader *, long)); +extern enum cpp_token _cpp_get_directive_token + PARAMS ((cpp_reader *)); + +/* In cpplib.c */ +extern int _cpp_handle_directive PARAMS ((cpp_reader *)); +extern void _cpp_handle_eof PARAMS ((cpp_reader *)); +extern void _cpp_output_line_command PARAMS ((cpp_reader *, + enum file_change_code)); + + #endif diff --git a/gcc/cppinit.c b/gcc/cppinit.c index 0eb2a29..674e140 100644 --- a/gcc/cppinit.c +++ b/gcc/cppinit.c @@ -519,7 +519,7 @@ dump_special_to_buffer (pfile, macro_name) { static const char define_directive[] = "#define "; int macro_name_length = strlen (macro_name); - output_line_command (pfile, same_file); + _cpp_output_line_command (pfile, same_file); CPP_RESERVE (pfile, sizeof(define_directive) + macro_name_length); CPP_PUTS_Q (pfile, define_directive, sizeof(define_directive)-1); CPP_PUTS_Q (pfile, macro_name, macro_name_length); @@ -872,6 +872,9 @@ cpp_start_read (pfile, fname) with a compiler that supports C99 designated initializers. */ init_IStable (); + /* Set up the tables used by read_and_prescan. */ + _cpp_init_input_buffer (pfile); + /* Set up the include search path now. */ if (! opts->no_standard_includes) initialize_standard_includes (pfile); @@ -933,7 +936,7 @@ cpp_start_read (pfile, fname) counter accordingly. */ pfile->lineno = CPP_BUFFER (pfile)->lineno; else - output_line_command (pfile, same_file); + _cpp_output_line_command (pfile, same_file); pfile->only_seen_white = 2; /* The -imacros files can be scanned now, but the -include files @@ -957,7 +960,7 @@ cpp_start_read (pfile, fname) while (p) { if (cpp_read_file (pfile, p->arg)) - output_line_command (pfile, enter_file); + _cpp_output_line_command (pfile, enter_file); q = p->next; free (p); diff --git a/gcc/cpplex.c b/gcc/cpplex.c new file mode 100644 index 0000000..674db90 --- /dev/null +++ b/gcc/cpplex.c @@ -0,0 +1,1620 @@ +/* CPP Library - lexical analysis. + Copyright (C) 2000 Free Software Foundation, Inc. + Contributed by Per Bothner, 1994-95. + Based on CCCP program by Paul Rubin, June 1986 + Adapted to ANSI C, Richard Stallman, Jan 1987 + Broken out to separate file, Zack Weinberg, Mar 2000 + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "config.h" +#include "system.h" +#include "intl.h" +#include "cpplib.h" +#include "cpphash.h" + +#define PEEKN(N) (CPP_BUFFER (pfile)->rlimit - CPP_BUFFER (pfile)->cur >= (N) \ + ? CPP_BUFFER (pfile)->cur[N] : EOF) +#define FORWARD(N) CPP_FORWARD (CPP_BUFFER (pfile), (N)) +#define GETC() CPP_BUF_GET (CPP_BUFFER (pfile)) +#define PEEKC() CPP_BUF_PEEK (CPP_BUFFER (pfile)) + +static void skip_block_comment PARAMS ((cpp_reader *)); +static void skip_line_comment PARAMS ((cpp_reader *)); +static int maybe_macroexpand PARAMS ((cpp_reader *, long)); +static int skip_comment PARAMS ((cpp_reader *, int)); +static int copy_comment PARAMS ((cpp_reader *, int)); +static void skip_string PARAMS ((cpp_reader *, int)); +static void parse_string PARAMS ((cpp_reader *, int)); +static U_CHAR *find_position PARAMS ((U_CHAR *, U_CHAR *, unsigned long *)); +static int null_cleanup PARAMS ((cpp_buffer *, cpp_reader *)); + +/* Re-allocates PFILE->token_buffer so it will hold at least N more chars. */ + +void +_cpp_grow_token_buffer (pfile, n) + cpp_reader *pfile; + long n; +{ + long old_written = CPP_WRITTEN (pfile); + pfile->token_buffer_size = n + 2 * pfile->token_buffer_size; + pfile->token_buffer = (U_CHAR *) + xrealloc(pfile->token_buffer, pfile->token_buffer_size); + CPP_SET_WRITTEN (pfile, old_written); +} + +static int +null_cleanup (pbuf, pfile) + cpp_buffer *pbuf ATTRIBUTE_UNUSED; + cpp_reader *pfile ATTRIBUTE_UNUSED; +{ + return 0; +} + +/* Allocate a new cpp_buffer for PFILE, and push it on the input buffer stack. + If BUFFER != NULL, then use the LENGTH characters in BUFFER + as the new input buffer. + Return the new buffer, or NULL on failure. */ + +cpp_buffer * +cpp_push_buffer (pfile, buffer, length) + cpp_reader *pfile; + const U_CHAR *buffer; + long length; +{ + cpp_buffer *buf = CPP_BUFFER (pfile); + cpp_buffer *new; + if (++pfile->buffer_stack_depth == CPP_STACK_MAX) + { + cpp_fatal (pfile, "macro or `#include' recursion too deep"); + return NULL; + } + + new = (cpp_buffer *) xcalloc (1, sizeof (cpp_buffer)); + + new->if_stack = pfile->if_stack; + new->cleanup = null_cleanup; + new->buf = new->cur = buffer; + new->alimit = new->rlimit = buffer + length; + new->prev = buf; + new->mark = -1; + new->line_base = NULL; + + CPP_BUFFER (pfile) = new; + return new; +} + +cpp_buffer * +cpp_pop_buffer (pfile) + cpp_reader *pfile; +{ + cpp_buffer *buf = CPP_BUFFER (pfile); + if (ACTIVE_MARK_P (pfile)) + cpp_ice (pfile, "mark active in cpp_pop_buffer"); + (*buf->cleanup) (buf, pfile); + CPP_BUFFER (pfile) = CPP_PREV_BUFFER (buf); + free (buf); + pfile->buffer_stack_depth--; + return CPP_BUFFER (pfile); +} + +/* Scan until CPP_BUFFER (PFILE) is exhausted into PFILE->token_buffer. + Pop the buffer when done. */ + +void +cpp_scan_buffer (pfile) + cpp_reader *pfile; +{ + cpp_buffer *buffer = CPP_BUFFER (pfile); + enum cpp_token token; + if (CPP_OPTIONS (pfile)->no_output) + { + long old_written = CPP_WRITTEN (pfile); + /* In no-output mode, we can ignore everything but directives. */ + for (;;) + { + if (! pfile->only_seen_white) + _cpp_skip_rest_of_line (pfile); + token = cpp_get_token (pfile); + if (token == CPP_EOF) /* Should not happen ... */ + break; + if (token == CPP_POP && CPP_BUFFER (pfile) == buffer) + { + if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) != NULL) + cpp_pop_buffer (pfile); + break; + } + } + CPP_SET_WRITTEN (pfile, old_written); + } + else + { + for (;;) + { + token = cpp_get_token (pfile); + if (token == CPP_EOF) /* Should not happen ... */ + break; + if (token == CPP_POP && CPP_BUFFER (pfile) == buffer) + { + if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) != NULL) + cpp_pop_buffer (pfile); + break; + } + } + } +} + +/* + * Rescan a string (which may have escape marks) into pfile's buffer. + * Place the result in pfile->token_buffer. + * + * The input is copied before it is scanned, so it is safe to pass + * it something from the token_buffer that will get overwritten + * (because it follows CPP_WRITTEN). This is used by do_include. + */ + +void +cpp_expand_to_buffer (pfile, buf, length) + cpp_reader *pfile; + const U_CHAR *buf; + int length; +{ + register cpp_buffer *ip; + U_CHAR *buf1; + int save_no_output; + + if (length < 0) + { + cpp_ice (pfile, "length < 0 in cpp_expand_to_buffer"); + return; + } + + /* Set up the input on the input stack. */ + + buf1 = (U_CHAR *) alloca (length + 1); + memcpy (buf1, buf, length); + buf1[length] = 0; + + ip = cpp_push_buffer (pfile, buf1, length); + if (ip == NULL) + return; + ip->has_escapes = 1; + + /* Scan the input, create the output. */ + save_no_output = CPP_OPTIONS (pfile)->no_output; + CPP_OPTIONS (pfile)->no_output = 0; + CPP_OPTIONS (pfile)->no_line_commands++; + cpp_scan_buffer (pfile); + CPP_OPTIONS (pfile)->no_line_commands--; + CPP_OPTIONS (pfile)->no_output = save_no_output; + + CPP_NUL_TERMINATE (pfile); +} + +void +cpp_buf_line_and_col (pbuf, linep, colp) + register cpp_buffer *pbuf; + long *linep, *colp; +{ + if (pbuf) + { + *linep = pbuf->lineno; + if (colp) + *colp = pbuf->cur - pbuf->line_base; + } + else + { + *linep = 0; + if (colp) + *colp = 0; + } +} + +/* Return the topmost cpp_buffer that corresponds to a file (not a macro). */ + +cpp_buffer * +cpp_file_buffer (pfile) + cpp_reader *pfile; +{ + cpp_buffer *ip; + + for (ip = CPP_BUFFER (pfile); ip; ip = CPP_PREV_BUFFER (ip)) + if (ip->ihash != NULL) + return ip; + return NULL; +} + +/* Skip a C-style block comment. We know it's a comment, and point is + at the second character of the starter. */ +static void +skip_block_comment (pfile) + cpp_reader *pfile; +{ + int c, prev_c = -1; + long line, col; + + FORWARD(1); + cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col); + for (;;) + { + c = GETC (); + if (c == EOF) + { + cpp_error_with_line (pfile, line, col, "unterminated comment"); + return; + } + else if (c == '\n' || c == '\r') + { + /* \r cannot be a macro escape marker here. */ + if (!ACTIVE_MARK_P (pfile)) + CPP_BUMP_LINE (pfile); + } + else if (c == '/' && prev_c == '*') + return; + else if (c == '*' && prev_c == '/' + && CPP_OPTIONS (pfile)->warn_comments) + cpp_warning (pfile, "`/*' within comment"); + + prev_c = c; + } +} + +/* Skip a C++/Chill line comment. We know it's a comment, and point + is at the second character of the initiator. */ +static void +skip_line_comment (pfile) + cpp_reader *pfile; +{ + FORWARD(1); + for (;;) + { + int c = GETC (); + + /* We don't have to worry about EOF in here. */ + if (c == '\n') + { + /* Don't consider final '\n' to be part of comment. */ + FORWARD(-1); + return; + } + else if (c == '\r') + { + /* \r cannot be a macro escape marker here. */ + if (!ACTIVE_MARK_P (pfile)) + CPP_BUMP_LINE (pfile); + if (CPP_OPTIONS (pfile)->warn_comments) + cpp_warning (pfile, "backslash-newline within line comment"); + } + } +} + +/* Skip a comment - C, C++, or Chill style. M is the first character + of the comment marker. If this really is a comment, skip to its + end and return ' '. If this is not a comment, return M (which will + be '/' or '-'). */ + +static int +skip_comment (pfile, m) + cpp_reader *pfile; + int m; +{ + if (m == '/' && PEEKC() == '*') + { + skip_block_comment (pfile); + return ' '; + } + else if (m == '/' && PEEKC() == '/') + { + if (CPP_BUFFER (pfile)->system_header_p) + { + /* We silently allow C++ comments in system headers, irrespective + of conformance mode, because lots of busted systems do that + and trying to clean it up in fixincludes is a nightmare. */ + skip_line_comment (pfile); + return ' '; + } + else if (CPP_OPTIONS (pfile)->cplusplus_comments) + { + if (CPP_OPTIONS (pfile)->c89 + && CPP_PEDANTIC (pfile) + && ! CPP_BUFFER (pfile)->warned_cplusplus_comments) + { + cpp_pedwarn (pfile, + "C++ style comments are not allowed in ISO C89"); + cpp_pedwarn (pfile, + "(this will be reported only once per input file)"); + CPP_BUFFER (pfile)->warned_cplusplus_comments = 1; + } + skip_line_comment (pfile); + return ' '; + } + else + return m; + } + else if (m == '-' && PEEKC() == '-' + && CPP_OPTIONS (pfile)->chill) + { + skip_line_comment (pfile); + return ' '; + } + else + return m; +} + +/* Identical to skip_comment except that it copies the comment into the + token_buffer. This is used if !discard_comments. */ +static int +copy_comment (pfile, m) + cpp_reader *pfile; + int m; +{ + const U_CHAR *start = CPP_BUFFER (pfile)->cur; /* XXX Layering violation */ + const U_CHAR *limit; + + if (skip_comment (pfile, m) == m) + return m; + + limit = CPP_BUFFER (pfile)->cur; + CPP_RESERVE (pfile, limit - start + 2); + CPP_PUTC_Q (pfile, m); + for (; start <= limit; start++) + if (*start != '\r') + CPP_PUTC_Q (pfile, *start); + + return ' '; +} + +/* Skip whitespace \-newline and comments. Does not macro-expand. */ + +void +_cpp_skip_hspace (pfile) + cpp_reader *pfile; +{ + int c; + while (1) + { + c = GETC(); + if (c == EOF) + return; + else if (is_hspace(c)) + { + if ((c == '\f' || c == '\v') && CPP_PEDANTIC (pfile)) + cpp_pedwarn (pfile, "%s in preprocessing directive", + c == '\f' ? "formfeed" : "vertical tab"); + } + else if (c == '\r') + { + /* \r is a backslash-newline marker if !has_escapes, and + a deletable-whitespace or no-reexpansion marker otherwise. */ + if (CPP_BUFFER (pfile)->has_escapes) + { + if (PEEKC() == ' ') + FORWARD(1); + else + break; + } + else + CPP_BUMP_LINE (pfile); + } + else if (c == '/' || c == '-') + { + c = skip_comment (pfile, c); + if (c != ' ') + break; + } + else + break; + } + FORWARD(-1); +} + +/* Read and discard the rest of the current line. */ + +void +_cpp_skip_rest_of_line (pfile) + cpp_reader *pfile; +{ + for (;;) + { + int c = GETC(); + switch (c) + { + case '\n': + FORWARD(-1); + case EOF: + return; + + case '\r': + if (! CPP_BUFFER (pfile)->has_escapes) + CPP_BUMP_LINE (pfile); + break; + + case '\'': + case '\"': + skip_string (pfile, c); + break; + + case '/': + case '-': + skip_comment (pfile, c); + break; + + case '\f': + case '\v': + if (CPP_PEDANTIC (pfile)) + cpp_pedwarn (pfile, "%s in preprocessing directive", + c == '\f' ? "formfeed" : "vertical tab"); + break; + + } + } +} + +/* Parse an identifier starting with C. */ + +void +_cpp_parse_name (pfile, c) + cpp_reader *pfile; + int c; +{ + for (;;) + { + if (! is_idchar(c)) + { + FORWARD (-1); + break; + } + + if (c == '$' && CPP_PEDANTIC (pfile)) + cpp_pedwarn (pfile, "`$' in identifier"); + + CPP_RESERVE(pfile, 2); /* One more for final NUL. */ + CPP_PUTC_Q (pfile, c); + c = GETC(); + if (c == EOF) + break; + } + CPP_NUL_TERMINATE_Q (pfile); + return; +} + +/* Parse and skip over a string starting with C. A single quoted + string is treated like a double -- some programs (e.g., troff) are + perverse this way. (However, a single quoted string is not allowed + to extend over multiple lines.) */ +static void +skip_string (pfile, c) + cpp_reader *pfile; + int c; +{ + long start_line, start_column; + cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column); + + while (1) + { + int cc = GETC(); + switch (cc) + { + case EOF: + cpp_error_with_line (pfile, start_line, start_column, + "unterminated string or character constant"); + if (pfile->multiline_string_line != start_line + && pfile->multiline_string_line != 0) + cpp_error_with_line (pfile, + pfile->multiline_string_line, -1, + "possible real start of unterminated constant"); + pfile->multiline_string_line = 0; + return; + + case '\n': + CPP_BUMP_LINE (pfile); + /* In Fortran and assembly language, silently terminate + strings of either variety at end of line. This is a + kludge around not knowing where comments are in these + languages. */ + if (CPP_OPTIONS (pfile)->lang_fortran + || CPP_OPTIONS (pfile)->lang_asm) + { + FORWARD(-1); + return; + } + /* Character constants may not extend over multiple lines. + In Standard C, neither may strings. We accept multiline + strings as an extension. */ + if (c == '\'') + { + cpp_error_with_line (pfile, start_line, start_column, + "unterminated character constant"); + FORWARD(-1); + return; + } + if (CPP_PEDANTIC (pfile) && pfile->multiline_string_line == 0) + cpp_pedwarn_with_line (pfile, start_line, start_column, + "string constant runs past end of line"); + if (pfile->multiline_string_line == 0) + pfile->multiline_string_line = start_line; + break; + + case '\r': + if (CPP_BUFFER (pfile)->has_escapes) + { + cpp_ice (pfile, "\\r escape inside string constant"); + FORWARD(1); + } + else + /* Backslash newline is replaced by nothing at all. */ + CPP_BUMP_LINE (pfile); + break; + + case '\\': + FORWARD(1); + break; + + case '\"': + case '\'': + if (cc == c) + return; + break; + } + } +} + +/* Parse a string and copy it to the output. */ + +static void +parse_string (pfile, c) + cpp_reader *pfile; + int c; +{ + const U_CHAR *start = CPP_BUFFER (pfile)->cur; /* XXX Layering violation */ + const U_CHAR *limit; + + skip_string (pfile, c); + + limit = CPP_BUFFER (pfile)->cur; + CPP_RESERVE (pfile, limit - start + 2); + CPP_PUTC_Q (pfile, c); + for (; start < limit; start++) + if (*start != '\r') + CPP_PUTC_Q (pfile, *start); +} + +/* Read an assertion into the token buffer, converting to + canonical form: `#predicate(a n swe r)' The next non-whitespace + character to read should be the first letter of the predicate. + Returns 0 for syntax error, 1 for bare predicate, 2 for predicate + with answer (see callers for why). In case of 0, an error has been + printed. */ +int +_cpp_parse_assertion (pfile) + cpp_reader *pfile; +{ + int c, dropwhite; + _cpp_skip_hspace (pfile); + c = PEEKC(); + if (! is_idstart(c)) + { + cpp_error (pfile, "assertion predicate is not an identifier"); + return 0; + } + CPP_PUTC(pfile, '#'); + FORWARD(1); + _cpp_parse_name (pfile, c); + + c = PEEKC(); + if (c != '(') + { + if (is_hspace(c) || c == '\r') + _cpp_skip_hspace (pfile); + c = PEEKC(); + } + if (c != '(') + return 1; + + CPP_PUTC(pfile, '('); + FORWARD(1); + dropwhite = 1; + while ((c = GETC()) != ')') + { + if (is_space(c)) + { + if (! dropwhite) + { + CPP_PUTC(pfile, ' '); + dropwhite = 1; + } + } + else if (c == '\n' || c == EOF) + { + if (c == '\n') FORWARD(-1); + cpp_error (pfile, "un-terminated assertion answer"); + return 0; + } + else if (c == '\r') + /* \r cannot be a macro escape here. */ + CPP_BUMP_LINE (pfile); + else + { + CPP_PUTC (pfile, c); + dropwhite = 0; + } + } + + if (pfile->limit[-1] == ' ') + pfile->limit[-1] = ')'; + else if (pfile->limit[-1] == '(') + { + cpp_error (pfile, "empty token sequence in assertion"); + return 0; + } + else + CPP_PUTC (pfile, ')'); + + CPP_NUL_TERMINATE (pfile); + return 2; +} + +/* Get the next token, and add it to the text in pfile->token_buffer. + Return the kind of token we got. */ + +enum cpp_token +_cpp_lex_token (pfile) + cpp_reader *pfile; +{ + register int c, c2, c3; + enum cpp_token token; + struct cpp_options *opts = CPP_OPTIONS (pfile); + + get_next: + c = GETC(); + switch (c) + { + case EOF: + return CPP_EOF; + + case '/': + if (PEEKC () == '=') + goto op2; + + comment: + if (opts->discard_comments) + c = skip_comment (pfile, c); + else + c = copy_comment (pfile, c); + if (c != ' ') + goto randomchar; + + /* Comments are equivalent to spaces. + For -traditional, a comment is equivalent to nothing. */ + if (opts->traditional || !opts->discard_comments) + return CPP_COMMENT; + else + { + CPP_PUTC (pfile, c); + return CPP_HSPACE; + } + + case '#': + if (pfile->parsing_if_directive) + { + _cpp_skip_hspace (pfile); + _cpp_parse_assertion (pfile); + return CPP_ASSERTION; + } + + if (pfile->parsing_define_directive && ! CPP_TRADITIONAL (pfile)) + { + CPP_RESERVE (pfile, 3); + CPP_PUTC_Q (pfile, '#'); + CPP_NUL_TERMINATE_Q (pfile); + if (PEEKC () != '#') + return CPP_STRINGIZE; + + FORWARD (1); + CPP_PUTC_Q (pfile, '#'); + CPP_NUL_TERMINATE_Q (pfile); + return CPP_TOKPASTE; + } + + if (!pfile->only_seen_white) + goto randomchar; + /* -traditional directives are recognized only with the # in + column 1. + XXX Layering violation. */ + if (CPP_TRADITIONAL (pfile) + && CPP_BUFFER (pfile)->cur - CPP_BUFFER (pfile)->line_base != 1) + goto randomchar; + return CPP_DIRECTIVE; + + case '\"': + case '\'': + parse_string (pfile, c); + pfile->only_seen_white = 0; + return c == '\'' ? CPP_CHAR : CPP_STRING; + + case '$': + if (!opts->dollars_in_ident) + goto randomchar; + goto letter; + + case ':': + if (opts->cplusplus && PEEKC () == ':') + goto op2; + goto randomchar; + + case '&': + case '+': + case '|': + c2 = PEEKC (); + if (c2 == c || c2 == '=') + goto op2; + goto randomchar; + + case '*': + case '!': + case '%': + case '=': + case '^': + if (PEEKC () == '=') + goto op2; + goto randomchar; + + case '-': + c2 = PEEKC (); + if (c2 == '-') + { + if (opts->chill) + goto comment; /* Chill style comment */ + else + goto op2; + } + else if (c2 == '=') + goto op2; + else if (c2 == '>') + { + if (opts->cplusplus && PEEKN (1) == '*') + { + /* In C++, there's a ->* operator. */ + token = CPP_OTHER; + pfile->only_seen_white = 0; + CPP_RESERVE (pfile, 4); + CPP_PUTC_Q (pfile, c); + CPP_PUTC_Q (pfile, GETC ()); + CPP_PUTC_Q (pfile, GETC ()); + CPP_NUL_TERMINATE_Q (pfile); + return token; + } + goto op2; + } + goto randomchar; + + case '<': + if (pfile->parsing_include_directive) + { + for (;;) + { + CPP_PUTC (pfile, c); + if (c == '>') + break; + c = GETC (); + if (c == '\n' || c == EOF) + { + cpp_error (pfile, + "missing '>' in `#include '"); + break; + } + else if (c == '\r') + { + if (!CPP_BUFFER (pfile)->has_escapes) + { + /* Backslash newline is replaced by nothing. */ + CPP_ADJUST_WRITTEN (pfile, -1); + CPP_BUMP_LINE (pfile); + } + else + { + /* We might conceivably get \r- or \r in + here. Just delete 'em. */ + int d = GETC(); + if (d != '-' && d != ' ') + cpp_ice (pfile, "unrecognized escape \\r%c", d); + CPP_ADJUST_WRITTEN (pfile, -1); + } + } + } + return CPP_STRING; + } + /* else fall through */ + case '>': + c2 = PEEKC (); + if (c2 == '=') + goto op2; + /* GNU C++ supports MIN and MAX operators ?. */ + if (c2 != c && (!opts->cplusplus || c2 != '?')) + goto randomchar; + FORWARD(1); + CPP_RESERVE (pfile, 4); + CPP_PUTC (pfile, c); + CPP_PUTC (pfile, c2); + c3 = PEEKC (); + if (c3 == '=') + CPP_PUTC_Q (pfile, GETC ()); + CPP_NUL_TERMINATE_Q (pfile); + pfile->only_seen_white = 0; + return CPP_OTHER; + + case '.': + c2 = PEEKC (); + if (ISDIGIT(c2)) + { + CPP_RESERVE(pfile, 2); + CPP_PUTC_Q (pfile, '.'); + c = GETC (); + goto number; + } + + /* In C++ there's a .* operator. */ + if (opts->cplusplus && c2 == '*') + goto op2; + + if (c2 == '.' && PEEKN(1) == '.') + { + CPP_RESERVE(pfile, 4); + CPP_PUTC_Q (pfile, '.'); + CPP_PUTC_Q (pfile, '.'); + CPP_PUTC_Q (pfile, '.'); + FORWARD (2); + CPP_NUL_TERMINATE_Q (pfile); + pfile->only_seen_white = 0; + return CPP_3DOTS; + } + goto randomchar; + + op2: + token = CPP_OTHER; + pfile->only_seen_white = 0; + CPP_RESERVE(pfile, 3); + CPP_PUTC_Q (pfile, c); + CPP_PUTC_Q (pfile, GETC ()); + CPP_NUL_TERMINATE_Q (pfile); + return token; + + case 'L': + c2 = PEEKC (); + if ((c2 == '\'' || c2 == '\"') && !CPP_TRADITIONAL (pfile)) + { + CPP_PUTC (pfile, c); + c = GETC (); + parse_string (pfile, c); + pfile->only_seen_white = 0; + return c == '\'' ? CPP_WCHAR : CPP_WSTRING; + } + goto letter; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + number: + c2 = '.'; + for (;;) + { + CPP_RESERVE (pfile, 2); + CPP_PUTC_Q (pfile, c); + c = PEEKC (); + if (c == EOF) + break; + if (!is_numchar(c) && c != '.' + && ((c2 != 'e' && c2 != 'E' + && ((c2 != 'p' && c2 != 'P') + || CPP_OPTIONS (pfile)->c89)) + || (c != '+' && c != '-'))) + break; + FORWARD(1); + c2= c; + } + CPP_NUL_TERMINATE_Q (pfile); + pfile->only_seen_white = 0; + return CPP_NUMBER; + case 'b': case 'c': case 'd': case 'h': case 'o': + case 'B': case 'C': case 'D': case 'H': case 'O': + if (opts->chill && PEEKC () == '\'') + { + pfile->only_seen_white = 0; + CPP_RESERVE (pfile, 2); + CPP_PUTC_Q (pfile, c); + CPP_PUTC_Q (pfile, '\''); + FORWARD(1); + for (;;) + { + c = GETC(); + if (c == EOF) + goto chill_number_eof; + if (!is_numchar(c)) + break; + CPP_PUTC (pfile, c); + } + if (c == '\'') + { + CPP_RESERVE (pfile, 2); + CPP_PUTC_Q (pfile, c); + CPP_NUL_TERMINATE_Q (pfile); + return CPP_STRING; + } + else + { + FORWARD(-1); + chill_number_eof: + CPP_NUL_TERMINATE (pfile); + return CPP_NUMBER; + } + } + else + goto letter; + case '_': + case 'a': case 'e': case 'f': case 'g': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'p': case 'q': + case 'r': case 's': case 't': case 'u': case 'v': case 'w': + case 'x': case 'y': case 'z': + case 'A': case 'E': case 'F': case 'G': case 'I': case 'J': + case 'K': case 'M': case 'N': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + letter: + pfile->only_seen_white = 0; + _cpp_parse_name (pfile, c); + return CPP_MACRO; + + case ' ': case '\t': case '\v': + for (;;) + { + CPP_PUTC (pfile, c); + c = PEEKC (); + if (c == EOF || !is_hspace(c)) + break; + FORWARD(1); + } + return CPP_HSPACE; + + case '\r': + if (CPP_BUFFER (pfile)->has_escapes) + { + c = GETC (); + if (c == '-') + { + if (pfile->output_escapes) + CPP_PUTS (pfile, "\r-", 2); + _cpp_parse_name (pfile, GETC ()); + return CPP_NAME; + } + else if (c == ' ') + { + CPP_RESERVE (pfile, 2); + if (pfile->output_escapes) + CPP_PUTC_Q (pfile, '\r'); + CPP_PUTC_Q (pfile, c); + return CPP_HSPACE; + } + else + { + cpp_ice (pfile, "unrecognized escape \\r%c", c); + goto get_next; + } + } + else + { + /* Backslash newline is ignored. */ + CPP_BUMP_LINE (pfile); + goto get_next; + } + + case '\n': + CPP_PUTC (pfile, c); + if (pfile->only_seen_white == 0) + pfile->only_seen_white = 1; + CPP_BUMP_LINE (pfile); + if (! CPP_OPTIONS (pfile)->no_line_commands) + { + pfile->lineno++; + if (CPP_BUFFER (pfile)->lineno != pfile->lineno) + _cpp_output_line_command (pfile, same_file); + } + return CPP_VSPACE; + + case '(': token = CPP_LPAREN; goto char1; + case ')': token = CPP_RPAREN; goto char1; + case '{': token = CPP_LBRACE; goto char1; + case '}': token = CPP_RBRACE; goto char1; + case ',': token = CPP_COMMA; goto char1; + case ';': token = CPP_SEMICOLON; goto char1; + + randomchar: + default: + token = CPP_OTHER; + char1: + pfile->only_seen_white = 0; + CPP_PUTC (pfile, c); + return token; + } +} + +/* Check for and expand a macro, which is from WRITTEN to CPP_WRITTEN (pfile). + Caller is expected to have checked no_macro_expand. */ +static int +maybe_macroexpand (pfile, written) + cpp_reader *pfile; + long written; +{ + U_CHAR *macro = pfile->token_buffer + written; + size_t len = CPP_WRITTEN (pfile) - written; + HASHNODE *hp = _cpp_lookup (pfile, macro, len); + + if (!hp) + return 0; + if (hp->type == T_DISABLED) + { + if (pfile->output_escapes) + { + /* Insert a no-reexpand marker before IDENT. */ + CPP_RESERVE (pfile, 2); + CPP_ADJUST_WRITTEN (pfile, 2); + macro = pfile->token_buffer + written; + + memmove (macro + 2, macro, len); + macro[0] = '\r'; + macro[1] = '-'; + } + return 0; + } + + /* If macro wants an arglist, verify that a '(' follows. */ + if (hp->type == T_MACRO && hp->value.defn->nargs >= 0) + { + int macbuf_whitespace = 0; + int c; + + while (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile))) + { + const U_CHAR *point = CPP_BUFFER (pfile)->cur; + for (;;) + { + _cpp_skip_hspace (pfile); + c = PEEKC (); + if (c == '\n') + FORWARD(1); + else + break; + } + if (point != CPP_BUFFER (pfile)->cur) + macbuf_whitespace = 1; + if (c == '(') + goto is_macro_call; + else if (c != EOF) + goto not_macro_call; + cpp_pop_buffer (pfile); + } + + CPP_SET_MARK (pfile); + for (;;) + { + _cpp_skip_hspace (pfile); + c = PEEKC (); + if (c == '\n') + FORWARD(1); + else + break; + } + CPP_GOTO_MARK (pfile); + + if (c != '(') + { + not_macro_call: + if (macbuf_whitespace) + CPP_PUTC (pfile, ' '); + return 0; + } + } + + is_macro_call: + /* This is now known to be a macro call. + Expand the macro, reading arguments as needed, + and push the expansion on the input stack. */ + _cpp_macroexpand (pfile, hp); + CPP_SET_WRITTEN (pfile, written); + return 1; +} + +enum cpp_token +cpp_get_token (pfile) + cpp_reader *pfile; +{ + enum cpp_token token; + long written = CPP_WRITTEN (pfile); + + get_next: + token = _cpp_lex_token (pfile); + + switch (token) + { + default: + return token; + + case CPP_DIRECTIVE: + if (_cpp_handle_directive (pfile)) + return CPP_DIRECTIVE; + pfile->only_seen_white = 0; + CPP_PUTC (pfile, '#'); + return CPP_OTHER; + + case CPP_MACRO: + if (! pfile->no_macro_expand + && maybe_macroexpand (pfile, written)) + goto get_next; + return CPP_NAME; + + case CPP_EOF: + if (CPP_BUFFER (pfile)->manual_pop) + /* If we've been reading from redirected input, the + frontend will pop the buffer. */ + return CPP_EOF; + else if (CPP_BUFFER (pfile)->seen_eof) + { + if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) == NULL) + return CPP_EOF; + + cpp_pop_buffer (pfile); + goto get_next; + } + else + { + _cpp_handle_eof (pfile); + return CPP_POP; + } + } +} + +/* Like cpp_get_token, but skip spaces and comments. */ + +enum cpp_token +cpp_get_non_space_token (pfile) + cpp_reader *pfile; +{ + int old_written = CPP_WRITTEN (pfile); + for (;;) + { + enum cpp_token token = cpp_get_token (pfile); + if (token != CPP_COMMENT && token != CPP_POP + && token != CPP_HSPACE && token != CPP_VSPACE) + return token; + CPP_SET_WRITTEN (pfile, old_written); + } +} + +/* Like cpp_get_token, except that it does not read past end-of-line. + Also, horizontal space is skipped, and macros are popped. */ + +enum cpp_token +_cpp_get_directive_token (pfile) + cpp_reader *pfile; +{ + long old_written = CPP_WRITTEN (pfile); + enum cpp_token token; + + for (;;) + { + _cpp_skip_hspace (pfile); + if (PEEKC () == '\n') + return CPP_VSPACE; + + token = cpp_get_token (pfile); + /* token could be hspace at the beginning of a macro. */ + if (token == CPP_HSPACE || token == CPP_COMMENT) + { + CPP_SET_WRITTEN (pfile, old_written); + continue; + } + + /* token cannot be vspace, it would have been caught above. */ + if (token == CPP_VSPACE) + { + cpp_ice (pfile, "VSPACE in get_directive_token"); + return token; + } + + /* token cannot be POP unless the buffer is a macro buffer. */ + if (token != CPP_POP) + return token; + + if (! CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile))) + { + cpp_ice (pfile, "POP of file buffer in get_directive_token"); + return token; + } + + /* We must pop the buffer by hand, or else cpp_get_token might + hand us white space or newline on the next invocation. */ + cpp_pop_buffer (pfile); + } +} + +/* Determine the current line and column. Used only by read_and_prescan. */ +static U_CHAR * +find_position (start, limit, linep) + U_CHAR *start; + U_CHAR *limit; + unsigned long *linep; +{ + unsigned long line = *linep; + U_CHAR *lbase = start; + while (start < limit) + { + U_CHAR ch = *start++; + if (ch == '\n' || ch == '\r') + { + line++; + lbase = start; + } + } + *linep = line; + return lbase; +} + +/* Read the entire contents of file DESC into buffer BUF. LEN is how + much memory to allocate initially; more will be allocated if + necessary. Convert end-of-line markers (\n, \r, \r\n, \n\r) to + canonical form (\n). If enabled, convert and/or warn about + trigraphs. Convert backslash-newline to a one-character escape + (\r) and remove it from "embarrassing" places (i.e. the middle of a + token). If there is no newline at the end of the file, add one and + warn. Returns -1 on failure, or the actual length of the data to + be scanned. + + This function does a lot of work, and can be a serious performance + bottleneck. It has been tuned heavily; make sure you understand it + before hacking. The common case - no trigraphs, Unix style line + breaks, backslash-newline set off by whitespace, newline at EOF - + has been optimized at the expense of the others. The performance + penalty for DOS style line breaks (\r\n) is about 15%. + + Warnings lose particularly heavily since we have to determine the + line number, which involves scanning from the beginning of the file + or from the last warning. The penalty for the absence of a newline + at the end of reload1.c is about 60%. (reload1.c is 329k.) + + If your file has more than one kind of end-of-line marker, you + will get messed-up line numbering. */ + +/* Table of characters that can't be handled in the inner loop. + Keep these contiguous to optimize the performance of the code generated + for the switch that uses them. */ +#define SPECCASE_EMPTY 0 +#define SPECCASE_NUL 1 +#define SPECCASE_CR 2 +#define SPECCASE_BACKSLASH 3 +#define SPECCASE_QUESTION 4 + +long +_cpp_read_and_prescan (pfile, fp, desc, len) + cpp_reader *pfile; + cpp_buffer *fp; + int desc; + size_t len; +{ + U_CHAR *buf = (U_CHAR *) xmalloc (len); + U_CHAR *ip, *op, *line_base; + U_CHAR *ibase; + U_CHAR *speccase = pfile->input_speccase; + unsigned long line; + unsigned int deferred_newlines; + int count; + size_t offset; + + offset = 0; + op = buf; + line_base = buf; + line = 1; + ibase = pfile->input_buffer + 2; + deferred_newlines = 0; + + for (;;) + { + read_next: + + count = read (desc, pfile->input_buffer + 2, pfile->input_buffer_len); + if (count < 0) + goto error; + else if (count == 0) + break; + + offset += count; + ip = ibase; + ibase = pfile->input_buffer + 2; + ibase[count] = ibase[count+1] = '\0'; + + if (offset > len) + { + size_t delta_op; + size_t delta_line_base; + len *= 2; + if (offset > len) + /* len overflowed. + This could happen if the file is larger than half the + maximum address space of the machine. */ + goto too_big; + + delta_op = op - buf; + delta_line_base = line_base - buf; + buf = (U_CHAR *) xrealloc (buf, len); + op = buf + delta_op; + line_base = buf + delta_line_base; + } + + for (;;) + { + unsigned int span = 0; + + /* Deal with \-newline in the middle of a token. */ + if (deferred_newlines) + { + while (speccase[ip[span]] == SPECCASE_EMPTY + && ip[span] != '\n' + && ip[span] != '\t' + && ip[span] != ' ') + span++; + memcpy (op, ip, span); + op += span; + ip += span; + /* If ip[0] is SPECCASE_EMPTY, we have hit white space. + Dump out the remaining deferred \-newlines. */ + if (speccase[ip[0]] == SPECCASE_EMPTY) + while (deferred_newlines) + deferred_newlines--, *op++ = '\r'; + span = 0; + } + + /* Copy as much as we can without special treatment. */ + while (speccase[ip[span]] == SPECCASE_EMPTY) span++; + memcpy (op, ip, span); + op += span; + ip += span; + + switch (speccase[*ip++]) + { + case SPECCASE_NUL: /* \0 */ + ibase[-1] = op[-1]; + goto read_next; + + case SPECCASE_CR: /* \r */ + if (ip[-2] == '\n') + continue; + else if (*ip == '\n') + ip++; + else if (*ip == '\0') + { + *--ibase = '\r'; + goto read_next; + } + *op++ = '\n'; + break; + + case SPECCASE_BACKSLASH: /* \ */ + backslash: + { + /* If we're at the end of the intermediate buffer, + we have to shift the backslash down to the start + and come back next pass. */ + if (*ip == '\0') + { + *--ibase = '\\'; + goto read_next; + } + else if (*ip == '\n') + { + ip++; + if (*ip == '\r') ip++; + if (*ip == '\n' || *ip == '\t' || *ip == ' ') + *op++ = '\r'; + else if (op[-1] == '\t' || op[-1] == ' ' + || op[-1] == '\r' || op[-1] == '\n') + *op++ = '\r'; + else + deferred_newlines++; + } + else if (*ip == '\r') + { + ip++; + if (*ip == '\n') ip++; + else if (*ip == '\0') + { + *--ibase = '\r'; + *--ibase = '\\'; + goto read_next; + } + else if (*ip == '\r' || *ip == '\t' || *ip == ' ') + *op++ = '\r'; + else + deferred_newlines++; + } + else + *op++ = '\\'; + } + break; + + case SPECCASE_QUESTION: /* ? */ + { + unsigned int d, t; + /* If we're at the end of the intermediate buffer, + we have to shift the ?'s down to the start and + come back next pass. */ + d = ip[0]; + if (d == '\0') + { + *--ibase = '?'; + goto read_next; + } + if (d != '?') + { + *op++ = '?'; + break; + } + d = ip[1]; + if (d == '\0') + { + *--ibase = '?'; + *--ibase = '?'; + goto read_next; + } + + /* Trigraph map: + * from to from to from to + * ?? = # ?? ) ] ?? ! | + * ?? ( [ ?? ' ^ ?? > } + * ?? / \ ?? < { ?? - ~ + */ + if (d == '=') t = '#'; + else if (d == ')') t = ']'; + else if (d == '!') t = '|'; + else if (d == '(') t = '['; + else if (d == '\'') t = '^'; + else if (d == '>') t = '}'; + else if (d == '/') t = '\\'; + else if (d == '<') t = '{'; + else if (d == '-') t = '~'; + else + { + *op++ = '?'; + break; + } + ip += 2; + if (CPP_OPTIONS (pfile)->warn_trigraphs) + { + unsigned long col; + line_base = find_position (line_base, op, &line); + col = op - line_base + 1; + if (CPP_OPTIONS (pfile)->trigraphs) + cpp_warning_with_line (pfile, line, col, + "trigraph ??%c converted to %c", d, t); + else + cpp_warning_with_line (pfile, line, col, + "trigraph ??%c ignored", d); + } + if (CPP_OPTIONS (pfile)->trigraphs) + { + if (t == '\\') + goto backslash; + else + *op++ = t; + } + else + { + *op++ = '?'; + *op++ = '?'; + *op++ = d; + } + } + } + } + } + + if (offset == 0) + return 0; + + /* Deal with pushed-back chars at true EOF. + This may be any of: ?? ? \ \r \n \\r \\n. + \r must become \n, \\r or \\n must become \r. + We know we have space already. */ + if (ibase == pfile->input_buffer) + { + if (*ibase == '?') + { + *op++ = '?'; + *op++ = '?'; + } + else + *op++ = '\r'; + } + else if (ibase == pfile->input_buffer + 1) + { + if (*ibase == '\r') + *op++ = '\n'; + else + *op++ = *ibase; + } + + if (op[-1] != '\n') + { + unsigned long col; + line_base = find_position (line_base, op, &line); + col = op - line_base + 1; + cpp_warning_with_line (pfile, line, col, "no newline at end of file\n"); + if (offset + 1 > len) + { + len += 1; + if (offset + 1 > len) + goto too_big; + buf = (U_CHAR *) xrealloc (buf, len); + op = buf + offset; + } + *op++ = '\n'; + } + + fp->buf = ((len - offset < 20) ? buf : (U_CHAR *)xrealloc (buf, op - buf)); + return op - buf; + + too_big: + cpp_error (pfile, "file is too large (>%lu bytes)\n", (unsigned long)offset); + free (buf); + return -1; + + error: + cpp_error_from_errno (pfile, fp->ihash->name); + free (buf); + return -1; +} + +/* Initialize the `input_buffer' and `input_speccase' tables. + These are only used by read_and_prescan, but they're large and + somewhat expensive to set up, so we want them allocated once for + the duration of the cpp run. */ + +void +_cpp_init_input_buffer (pfile) + cpp_reader *pfile; +{ + U_CHAR *tmp; + + /* Table of characters that cannot be handled by the + read_and_prescan inner loop. The number of non-EMPTY entries + should be as small as humanly possible. */ + + tmp = (U_CHAR *) xmalloc (1 << CHAR_BIT); + memset (tmp, SPECCASE_EMPTY, 1 << CHAR_BIT); + tmp['\0'] = SPECCASE_NUL; + tmp['\r'] = SPECCASE_CR; + tmp['\\'] = SPECCASE_BACKSLASH; + if (CPP_OPTIONS (pfile)->trigraphs || CPP_OPTIONS (pfile)->warn_trigraphs) + tmp['?'] = SPECCASE_QUESTION; + + pfile->input_speccase = tmp; + + /* Determine the appropriate size for the input buffer. Normal C + source files are smaller than eight K. */ + /* 8Kbytes of buffer proper, 2 to detect running off the end without + address arithmetic all the time, and 2 for pushback in the case + there's a potential trigraph or end-of-line digraph at the end of + a block. */ + + tmp = (U_CHAR *) xmalloc (8192 + 2 + 2); + pfile->input_buffer = tmp; + pfile->input_buffer_len = 8192; +} diff --git a/gcc/cpplib.c b/gcc/cpplib.c index 02a9318..1de14d3 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -28,19 +28,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "intl.h" #include "mkdeps.h" -#define SKIP_WHITE_SPACE(p) do { while (is_hspace(*p)) p++; } while (0) - -#define PEEKN(N) (CPP_BUFFER (pfile)->rlimit - CPP_BUFFER (pfile)->cur >= (N) ? CPP_BUFFER (pfile)->cur[N] : EOF) +#define PEEKN(N) (CPP_BUFFER (pfile)->rlimit - CPP_BUFFER (pfile)->cur >= (N) \ + ? CPP_BUFFER (pfile)->cur[N] : EOF) #define FORWARD(N) CPP_FORWARD (CPP_BUFFER (pfile), (N)) #define GETC() CPP_BUF_GET (CPP_BUFFER (pfile)) #define PEEKC() CPP_BUF_PEEK (CPP_BUFFER (pfile)) -/* CPP_IS_MACRO_BUFFER is true if the buffer contains macro expansion. - (Note that it is false while we're expanding macro *arguments*.) */ -#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->data != NULL) - -/* ACTIVE_MARK_P is true if there's a live mark in the buffer, in which - case CPP_BUMP_LINE must not be called. */ -#define ACTIVE_MARK_P() (CPP_BUFFER (pfile)->mark != -1) /* `struct directive' defines one #-directive, including how to handle it. */ @@ -93,22 +85,9 @@ static int do_warning PARAMS ((cpp_reader *, const struct directive *)); /* Forward declarations. */ static void validate_else PARAMS ((cpp_reader *, const char *)); -static int eval_if_expr PARAMS ((cpp_reader *)); static void conditional_skip PARAMS ((cpp_reader *, int, enum node_type, U_CHAR *)); static void skip_if_group PARAMS ((cpp_reader *)); -static void parse_name PARAMS ((cpp_reader *, int)); -static void parse_string PARAMS ((cpp_reader *, int)); -static int parse_assertion PARAMS ((cpp_reader *)); -static const char *if_directive_name PARAMS ((cpp_reader *, - struct if_stack *)); -static int null_cleanup PARAMS ((cpp_buffer *, cpp_reader *)); -static int skip_comment PARAMS ((cpp_reader *, int)); -static int copy_comment PARAMS ((cpp_reader *, int)); -static void skip_string PARAMS ((cpp_reader *, int)); -static void skip_rest_of_line PARAMS ((cpp_reader *)); -static void cpp_skip_hspace PARAMS ((cpp_reader *)); -static int handle_directive PARAMS ((cpp_reader *)); static void pass_thru_directive PARAMS ((const U_CHAR *, size_t, cpp_reader *, const struct directive *)); @@ -116,11 +95,9 @@ static int read_line_number PARAMS ((cpp_reader *, int *)); static U_CHAR *detect_if_not_defined PARAMS ((cpp_reader *)); static int consider_directive_while_skipping PARAMS ((cpp_reader *, IF_STACK *)); -static void skip_block_comment PARAMS ((cpp_reader *)); -static void skip_line_comment PARAMS ((cpp_reader *)); -static void parse_set_mark PARAMS ((cpp_reader *)); -static void parse_goto_mark PARAMS ((cpp_reader *)); static int get_macro_name PARAMS ((cpp_reader *)); +static const char *if_directive_name PARAMS ((cpp_reader *, + struct if_stack *)); /* Here is the actual list of #-directives. This table is ordered by frequency of occurrence; the numbers @@ -156,367 +133,11 @@ static const struct directive directive_table[] = { { -1, 0, "", T_UNUSED } }; -/* Place into PFILE a quoted string representing the string SRC. - Caller must reserve enough space in pfile->token_buffer. */ - -void -quote_string (pfile, src) - cpp_reader *pfile; - const char *src; -{ - U_CHAR c; - - CPP_PUTC_Q (pfile, '\"'); - for (;;) - switch ((c = *src++)) - { - default: - if (ISPRINT (c)) - CPP_PUTC_Q (pfile, c); - else - { - sprintf ((char *)CPP_PWRITTEN (pfile), "\\%03o", c); - CPP_ADJUST_WRITTEN (pfile, 4); - } - break; - - case '\"': - case '\\': - CPP_PUTC_Q (pfile, '\\'); - CPP_PUTC_Q (pfile, c); - break; - - case '\0': - CPP_PUTC_Q (pfile, '\"'); - CPP_NUL_TERMINATE_Q (pfile); - return; - } -} - -/* Re-allocates PFILE->token_buffer so it will hold at least N more chars. */ - -void -cpp_grow_buffer (pfile, n) - cpp_reader *pfile; - long n; -{ - long old_written = CPP_WRITTEN (pfile); - pfile->token_buffer_size = n + 2 * pfile->token_buffer_size; - pfile->token_buffer = (U_CHAR *) - xrealloc(pfile->token_buffer, pfile->token_buffer_size); - CPP_SET_WRITTEN (pfile, old_written); -} - -/* Process the string STR as if it appeared as the body of a #define. - If STR is just an identifier, define it with value 1. - If STR has anything after the identifier, then it should - be identifier=definition. */ - -void -cpp_define (pfile, str) - cpp_reader *pfile; - const char *str; -{ - char *buf, *p; - size_t count; - - p = strchr (str, '='); - /* Copy the entire option so we can modify it. - Change the first "=" in the string to a space. If there is none, - tack " 1" on the end. Then add a newline and a NUL. */ - - if (p) - { - count = strlen (str) + 2; - buf = alloca (count); - memcpy (buf, str, count - 2); - buf[p - str] = ' '; - buf[count - 2] = '\n'; - buf[count - 1] = '\0'; - } - else - { - count = strlen (str) + 4; - buf = alloca (count); - memcpy (buf, str, count - 4); - strcpy (&buf[count-4], " 1\n"); - } - - if (cpp_push_buffer (pfile, buf, count - 1) != NULL) - { - do_define (pfile, NULL); - cpp_pop_buffer (pfile); - } -} - -/* Process the string STR as if it appeared as the body of a #assert. */ -void -cpp_assert (pfile, str) - cpp_reader *pfile; - const char *str; -{ - if (cpp_push_buffer (pfile, str, strlen (str)) != NULL) - { - do_assert (pfile, NULL); - cpp_pop_buffer (pfile); - } -} - -/* Determine whether the identifier ID, of length LEN, is a defined macro. */ -int -cpp_defined (pfile, id, len) - cpp_reader *pfile; - const U_CHAR *id; - int len; -{ - HASHNODE *hp = _cpp_lookup (pfile, id, len); - if (hp && hp->type == T_POISON) - { - cpp_error (pfile, "attempt to use poisoned `%s'", hp->name); - return 0; - } - return (hp != NULL); -} - -static int -null_cleanup (pbuf, pfile) - cpp_buffer *pbuf ATTRIBUTE_UNUSED; - cpp_reader *pfile ATTRIBUTE_UNUSED; -{ - return 0; -} - -/* Skip a C-style block comment. We know it's a comment, and point is - at the second character of the starter. */ -static void -skip_block_comment (pfile) - cpp_reader *pfile; -{ - int c, prev_c = -1; - long line, col; - - FORWARD(1); - cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col); - for (;;) - { - c = GETC (); - if (c == EOF) - { - cpp_error_with_line (pfile, line, col, "unterminated comment"); - return; - } - else if (c == '\n' || c == '\r') - { - /* \r cannot be a macro escape marker here. */ - if (!ACTIVE_MARK_P()) - CPP_BUMP_LINE (pfile); - } - else if (c == '/' && prev_c == '*') - return; - else if (c == '*' && prev_c == '/' - && CPP_OPTIONS (pfile)->warn_comments) - cpp_warning (pfile, "`/*' within comment"); - - prev_c = c; - } -} - -/* Skip a C++/Chill line comment. We know it's a comment, and point - is at the second character of the initiator. */ -static void -skip_line_comment (pfile) - cpp_reader *pfile; -{ - FORWARD(1); - for (;;) - { - int c = GETC (); - - /* We don't have to worry about EOF in here. */ - if (c == '\n') - { - /* Don't consider final '\n' to be part of comment. */ - FORWARD(-1); - return; - } - else if (c == '\r') - { - /* \r cannot be a macro escape marker here. */ - if (!ACTIVE_MARK_P()) - CPP_BUMP_LINE (pfile); - if (CPP_OPTIONS (pfile)->warn_comments) - cpp_warning (pfile, "backslash-newline within line comment"); - } - } -} - -/* Skip a comment - C, C++, or Chill style. M is the first character - of the comment marker. If this really is a comment, skip to its - end and return ' '. If this is not a comment, return M (which will - be '/' or '-'). */ - -static int -skip_comment (pfile, m) - cpp_reader *pfile; - int m; -{ - if (m == '/' && PEEKC() == '*') - { - skip_block_comment (pfile); - return ' '; - } - else if (m == '/' && PEEKC() == '/') - { - if (CPP_BUFFER (pfile)->system_header_p) - { - /* We silently allow C++ comments in system headers, irrespective - of conformance mode, because lots of busted systems do that - and trying to clean it up in fixincludes is a nightmare. */ - skip_line_comment (pfile); - return ' '; - } - else if (CPP_OPTIONS (pfile)->cplusplus_comments) - { - if (CPP_OPTIONS (pfile)->c89 - && CPP_PEDANTIC (pfile) - && ! CPP_BUFFER (pfile)->warned_cplusplus_comments) - { - cpp_pedwarn (pfile, - "C++ style comments are not allowed in ISO C89"); - cpp_pedwarn (pfile, - "(this will be reported only once per input file)"); - CPP_BUFFER (pfile)->warned_cplusplus_comments = 1; - } - skip_line_comment (pfile); - return ' '; - } - else - return m; - } - else if (m == '-' && PEEKC() == '-' - && CPP_OPTIONS (pfile)->chill) - { - skip_line_comment (pfile); - return ' '; - } - else - return m; -} - -/* Identical to skip_comment except that it copies the comment into the - token_buffer. This is used if !discard_comments. */ -static int -copy_comment (pfile, m) - cpp_reader *pfile; - int m; -{ - const U_CHAR *start = CPP_BUFFER (pfile)->cur; /* XXX Layering violation */ - const U_CHAR *limit; - - if (skip_comment (pfile, m) == m) - return m; - - limit = CPP_BUFFER (pfile)->cur; - CPP_RESERVE (pfile, limit - start + 2); - CPP_PUTC_Q (pfile, m); - for (; start <= limit; start++) - if (*start != '\r') - CPP_PUTC_Q (pfile, *start); - - return ' '; -} - -/* Skip whitespace \-newline and comments. Does not macro-expand. */ - -static void -cpp_skip_hspace (pfile) - cpp_reader *pfile; -{ - int c; - while (1) - { - c = GETC(); - if (c == EOF) - return; - else if (is_hspace(c)) - { - if ((c == '\f' || c == '\v') && CPP_PEDANTIC (pfile)) - cpp_pedwarn (pfile, "%s in preprocessing directive", - c == '\f' ? "formfeed" : "vertical tab"); - } - else if (c == '\r') - { - /* \r is a backslash-newline marker if !has_escapes, and - a deletable-whitespace or no-reexpansion marker otherwise. */ - if (CPP_BUFFER (pfile)->has_escapes) - { - if (PEEKC() == ' ') - FORWARD(1); - else - break; - } - else - CPP_BUMP_LINE (pfile); - } - else if (c == '/' || c == '-') - { - c = skip_comment (pfile, c); - if (c != ' ') - break; - } - else - break; - } - FORWARD(-1); -} - -/* Read and discard the rest of the current line. */ - -static void -skip_rest_of_line (pfile) - cpp_reader *pfile; -{ - for (;;) - { - int c = GETC(); - switch (c) - { - case '\n': - FORWARD(-1); - case EOF: - return; - - case '\r': - if (! CPP_BUFFER (pfile)->has_escapes) - CPP_BUMP_LINE (pfile); - break; - - case '\'': - case '\"': - skip_string (pfile, c); - break; - - case '/': - case '-': - skip_comment (pfile, c); - break; - - case '\f': - case '\v': - if (CPP_PEDANTIC (pfile)) - cpp_pedwarn (pfile, "%s in preprocessing directive", - c == '\f' ? "formfeed" : "vertical tab"); - break; - - } - } -} - /* Handle a possible # directive. '#' has already been read. */ -static int -handle_directive (pfile) +int +_cpp_handle_directive (pfile) cpp_reader *pfile; { int c; @@ -531,7 +152,7 @@ handle_directive (pfile) return 0; } - cpp_skip_hspace (pfile); + _cpp_skip_hspace (pfile); c = PEEKC (); /* # followed by a number is equivalent to #line. Do not recognize @@ -558,7 +179,7 @@ handle_directive (pfile) /* Now find the directive name. */ CPP_PUTC (pfile, '#'); - parse_name (pfile, GETC()); + _cpp_parse_name (pfile, GETC()); ident = pfile->token_buffer + old_written + 1; ident_length = CPP_PWRITTEN (pfile) - ident; if (ident_length == 0) @@ -588,7 +209,7 @@ handle_directive (pfile) { cpp_error (pfile, "`#%s' may not be used inside a macro argument", kt->name); - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); } else (*kt->func) (pfile, kt); @@ -629,7 +250,7 @@ get_macro_name (pfile) here = CPP_WRITTEN (pfile); pfile->no_macro_expand++; - if (get_directive_token (pfile) != CPP_NAME) + if (_cpp_get_directive_token (pfile) != CPP_NAME) { cpp_error (pfile, "`#define' must be followed by an identifier"); goto invalid; @@ -646,7 +267,7 @@ get_macro_name (pfile) return len; invalid: - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); pfile->no_macro_expand--; return 0; } @@ -748,222 +369,48 @@ do_define (pfile, keyword) return 0; } +/* + * write out a #line command, for instance, after an #include file. + * FILE_CHANGE says whether we are entering a file, leaving, or neither. + */ -/* Allocate a new cpp_buffer for PFILE, and push it on the input buffer stack. - If BUFFER != NULL, then use the LENGTH characters in BUFFER - as the new input buffer. - Return the new buffer, or NULL on failure. */ - -cpp_buffer * -cpp_push_buffer (pfile, buffer, length) +void +_cpp_output_line_command (pfile, file_change) cpp_reader *pfile; - const U_CHAR *buffer; - long length; + enum file_change_code file_change; { - cpp_buffer *buf = CPP_BUFFER (pfile); - cpp_buffer *new; - if (++pfile->buffer_stack_depth == CPP_STACK_MAX) - { - cpp_fatal (pfile, "macro or `#include' recursion too deep"); - return NULL; - } - - new = (cpp_buffer *) xcalloc (1, sizeof (cpp_buffer)); - - new->if_stack = pfile->if_stack; - new->cleanup = null_cleanup; - new->buf = new->cur = buffer; - new->alimit = new->rlimit = buffer + length; - new->prev = buf; - new->mark = -1; - new->line_base = NULL; - - CPP_BUFFER (pfile) = new; - return new; -} + long line; + cpp_buffer *ip; -cpp_buffer * -cpp_pop_buffer (pfile) - cpp_reader *pfile; -{ - cpp_buffer *buf = CPP_BUFFER (pfile); - if (ACTIVE_MARK_P()) - cpp_ice (pfile, "mark active in cpp_pop_buffer"); - (*buf->cleanup) (buf, pfile); - CPP_BUFFER (pfile) = CPP_PREV_BUFFER (buf); - free (buf); - pfile->buffer_stack_depth--; - return CPP_BUFFER (pfile); -} + if (CPP_OPTIONS (pfile)->no_line_commands + || CPP_OPTIONS (pfile)->no_output) + return; -/* Scan until CPP_BUFFER (PFILE) is exhausted into PFILE->token_buffer. - Pop the buffer when done. */ + ip = cpp_file_buffer (pfile); + cpp_buf_line_and_col (ip, &line, NULL); -void -cpp_scan_buffer (pfile) - cpp_reader *pfile; -{ - cpp_buffer *buffer = CPP_BUFFER (pfile); - enum cpp_token token; - if (CPP_OPTIONS (pfile)->no_output) + /* If the current file has not changed, we omit the #line if it would + appear to be a no-op, and we output a few newlines instead + if we want to increase the line number by a small amount. + We cannot do this if pfile->lineno is zero, because that means we + haven't output any line commands yet. (The very first line command + output is a `same_file' command.) */ + if (file_change == same_file && pfile->lineno != 0) { - long old_written = CPP_WRITTEN (pfile); - /* In no-output mode, we can ignore everything but directives. */ - for (;;) + if (line == pfile->lineno) + return; + + /* If the inherited line number is a little too small, + output some newlines instead of a #line command. */ + if (line > pfile->lineno && line < pfile->lineno + 8) { - if (! pfile->only_seen_white) - skip_rest_of_line (pfile); - token = cpp_get_token (pfile); - if (token == CPP_EOF) /* Should not happen ... */ - break; - if (token == CPP_POP && CPP_BUFFER (pfile) == buffer) + CPP_RESERVE (pfile, 20); + while (line > pfile->lineno) { - if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) != NULL) - cpp_pop_buffer (pfile); - break; + CPP_PUTC_Q (pfile, '\n'); + pfile->lineno++; } - } - CPP_SET_WRITTEN (pfile, old_written); - } - else - { - for (;;) - { - token = cpp_get_token (pfile); - if (token == CPP_EOF) /* Should not happen ... */ - break; - if (token == CPP_POP && CPP_BUFFER (pfile) == buffer) - { - if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) != NULL) - cpp_pop_buffer (pfile); - break; - } - } - } -} - -/* - * Rescan a string (which may have escape marks) into pfile's buffer. - * Place the result in pfile->token_buffer. - * - * The input is copied before it is scanned, so it is safe to pass - * it something from the token_buffer that will get overwritten - * (because it follows CPP_WRITTEN). This is used by do_include. - */ - -void -cpp_expand_to_buffer (pfile, buf, length) - cpp_reader *pfile; - const U_CHAR *buf; - int length; -{ - register cpp_buffer *ip; - U_CHAR *buf1; - int save_no_output; - - if (length < 0) - { - cpp_ice (pfile, "length < 0 in cpp_expand_to_buffer"); - return; - } - - /* Set up the input on the input stack. */ - - buf1 = (U_CHAR *) alloca (length + 1); - memcpy (buf1, buf, length); - buf1[length] = 0; - - ip = cpp_push_buffer (pfile, buf1, length); - if (ip == NULL) - return; - ip->has_escapes = 1; - - /* Scan the input, create the output. */ - save_no_output = CPP_OPTIONS (pfile)->no_output; - CPP_OPTIONS (pfile)->no_output = 0; - CPP_OPTIONS (pfile)->no_line_commands++; - cpp_scan_buffer (pfile); - CPP_OPTIONS (pfile)->no_line_commands--; - CPP_OPTIONS (pfile)->no_output = save_no_output; - - CPP_NUL_TERMINATE (pfile); -} - -void -cpp_buf_line_and_col (pbuf, linep, colp) - register cpp_buffer *pbuf; - long *linep, *colp; -{ - if (pbuf) - { - *linep = pbuf->lineno; - if (colp) - *colp = pbuf->cur - pbuf->line_base; - } - else - { - *linep = 0; - if (colp) - *colp = 0; - } -} - -/* Return the cpp_buffer that corresponds to a file (not a macro). */ - -cpp_buffer * -cpp_file_buffer (pfile) - cpp_reader *pfile; -{ - cpp_buffer *ip; - - for (ip = CPP_BUFFER (pfile); ip; ip = CPP_PREV_BUFFER (ip)) - if (ip->ihash != NULL) - return ip; - return NULL; -} - -/* - * write out a #line command, for instance, after an #include file. - * FILE_CHANGE says whether we are entering a file, leaving, or neither. - */ - -void -output_line_command (pfile, file_change) - cpp_reader *pfile; - enum file_change_code file_change; -{ - long line; - cpp_buffer *ip; - - if (CPP_OPTIONS (pfile)->no_line_commands - || CPP_OPTIONS (pfile)->no_output) - return; - - ip = cpp_file_buffer (pfile); - cpp_buf_line_and_col (ip, &line, NULL); - - /* If the current file has not changed, we omit the #line if it would - appear to be a no-op, and we output a few newlines instead - if we want to increase the line number by a small amount. - We cannot do this if pfile->lineno is zero, because that means we - haven't output any line commands yet. (The very first line command - output is a `same_file' command.) */ - if (file_change == same_file && pfile->lineno != 0) - { - if (line == pfile->lineno) - return; - - /* If the inherited line number is a little too small, - output some newlines instead of a #line command. */ - if (line > pfile->lineno && line < pfile->lineno + 8) - { - CPP_RESERVE (pfile, 20); - while (line > pfile->lineno) - { - CPP_PUTC_Q (pfile, '\n'); - pfile->lineno++; - } - return; + return; } } @@ -973,7 +420,7 @@ output_line_command (pfile, file_change) sprintf ((char *) CPP_PWRITTEN (pfile), "%ld ", line); CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile))); - quote_string (pfile, ip->nominal_fname); + _cpp_quote_string (pfile, ip->nominal_fname); if (file_change != same_file && file_change != rename_file) { CPP_PUTC_Q (pfile, ' '); @@ -997,61 +444,7 @@ output_line_command (pfile, file_change) pfile->lineno = line; } - -/* Like cpp_get_token, except that it does not read past end-of-line. - Also, horizontal space is skipped, and macros are popped. */ - -enum cpp_token -get_directive_token (pfile) - cpp_reader *pfile; -{ - long old_written = CPP_WRITTEN (pfile); - enum cpp_token token; - - for (;;) - { - cpp_skip_hspace (pfile); - if (PEEKC () == '\n') - return CPP_VSPACE; - - token = cpp_get_token (pfile); - /* token could be hspace at the beginning of a macro. */ - if (token == CPP_HSPACE || token == CPP_COMMENT) - { - CPP_SET_WRITTEN (pfile, old_written); - continue; - } - - /* token cannot be vspace, it would have been caught above. */ - if (token == CPP_VSPACE) - { - cpp_ice (pfile, "VSPACE in get_directive_token"); - return token; - } - - /* token cannot be POP unless the buffer is a macro buffer. */ - if (token != CPP_POP) - return token; - - if (! CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile))) - { - cpp_ice (pfile, "POP of file buffer in get_directive_token"); - return token; - } - - /* We must pop the buffer by hand, or else cpp_get_token might - hand us white space or newline on the next invocation. */ - cpp_pop_buffer (pfile); - } -} - -/* Handle #include and #import. - This function expects to see "fname" or on the input. - - The input is normally in part of the output_buffer following - CPP_WRITTEN, and will get overwritten by output_line_command. - I.e. in input file specification has been popped by handle_directive. - This is safe. */ +/* Handle #include and #import. */ static int do_include (pfile, keyword) @@ -1094,7 +487,7 @@ do_include (pfile, keyword) } pfile->parsing_include_directive++; - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); pfile->parsing_include_directive--; if (token == CPP_STRING) @@ -1120,7 +513,7 @@ do_include (pfile, keyword) cpp_error (pfile, "`#%s' expects \"FILENAME\" or ", keyword->name); CPP_SET_WRITTEN (pfile, old_written); - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); return 0; } @@ -1129,10 +522,10 @@ do_include (pfile, keyword) memcpy (ftok, pfile->token_buffer + old_written, flen); ftok[flen] = '\0'; - if (get_directive_token (pfile) != CPP_VSPACE) + if (_cpp_get_directive_token (pfile) != CPP_VSPACE) { cpp_error (pfile, "junk at end of `#include'"); - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); } CPP_SET_WRITTEN (pfile, old_written); @@ -1270,7 +663,7 @@ do_include (pfile, keyword) if (_cpp_read_include_file (pfile, fd, ihash)) { - output_line_command (pfile, enter_file); + _cpp_output_line_command (pfile, enter_file); if (angle_brackets) pfile->system_include_depth++; /* Decremented in file_cleanup. */ } @@ -1288,9 +681,10 @@ read_line_number (pfile, num) int *num; { long save_written = CPP_WRITTEN (pfile); - U_CHAR *p = pfile->token_buffer + save_written; - enum cpp_token token = get_directive_token (pfile); + U_CHAR *p; + enum cpp_token token = _cpp_get_directive_token (pfile); CPP_SET_WRITTEN (pfile, save_written); + p = pfile->token_buffer + save_written; if (token == CPP_NUMBER && *p >= '1' && *p <= '4' && p[1] == '\0') { @@ -1321,7 +715,7 @@ do_line (pfile, keyword) enum cpp_token token; char *x; - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); if (token != CPP_NUMBER) { @@ -1340,7 +734,7 @@ do_line (pfile, keyword) if (CPP_PEDANTIC (pfile) && (new_lineno <= 0 || new_lineno > 32767)) cpp_pedwarn (pfile, "line number out of range in `#line' command"); - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); if (token == CPP_STRING) { @@ -1416,11 +810,11 @@ do_line (pfile, keyword) we must store a line number now that is one less. */ ip->lineno = new_lineno - 1; CPP_SET_WRITTEN (pfile, old_written); - output_line_command (pfile, file_change); + _cpp_output_line_command (pfile, file_change); return 0; bad_line_directive: - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); CPP_SET_WRITTEN (pfile, old_written); return 0; } @@ -1440,16 +834,16 @@ do_undef (pfile, keyword) long here = CPP_WRITTEN (pfile); enum cpp_token token; - cpp_skip_hspace (pfile); + _cpp_skip_hspace (pfile); c = GETC(); if (! is_idstart(c)) { cpp_error (pfile, "token after #undef is not an identifier"); - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); return 1; } - parse_name (pfile, c); + _cpp_parse_name (pfile, c); buf = pfile->token_buffer + here; limit = CPP_PWRITTEN(pfile); @@ -1459,11 +853,11 @@ do_undef (pfile, keyword) memcpy (name, buf, len); name[len] = '\0'; - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); if (token != CPP_VSPACE) { cpp_pedwarn (pfile, "junk on line after #undef"); - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); } CPP_SET_WRITTEN (pfile, here); @@ -1489,25 +883,6 @@ do_undef (pfile, keyword) return 0; } -/* Wrap do_undef for -U processing. */ -void -cpp_undef (pfile, macro) - cpp_reader *pfile; - const char *macro; -{ - /* Copy the string so we can append a newline. */ - size_t len = strlen (macro); - char *buf = alloca (len + 2); - memcpy (buf, macro, len); - buf[len] = '\n'; - buf[len + 1] = '\0'; - if (cpp_push_buffer (pfile, buf, len + 1)) - { - do_undef (pfile, NULL); - cpp_pop_buffer (pfile); - } -} - /* * Report an error detected by the program we are processing. * Use the text of the line in the error message. @@ -1521,9 +896,9 @@ do_error (pfile, keyword) { const U_CHAR *text, *limit; - cpp_skip_hspace (pfile); + _cpp_skip_hspace (pfile); text = CPP_BUFFER (pfile)->cur; - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); limit = CPP_BUFFER (pfile)->cur; cpp_error (pfile, "#error %.*s", (int)(limit - text), text); @@ -1542,9 +917,9 @@ do_warning (pfile, keyword) { const U_CHAR *text, *limit; - cpp_skip_hspace (pfile); + _cpp_skip_hspace (pfile); text = CPP_BUFFER (pfile)->cur; - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); limit = CPP_BUFFER (pfile)->cur; if (CPP_PEDANTIC (pfile)) @@ -1570,14 +945,14 @@ do_ident (pfile, keyword) CPP_PUTS (pfile, "#ident ", 7); /* Next token should be a string constant. */ - if (get_directive_token (pfile) == CPP_STRING) + if (_cpp_get_directive_token (pfile) == CPP_STRING) /* And then a newline. */ - if (get_directive_token (pfile) == CPP_VSPACE) + if (_cpp_get_directive_token (pfile) == CPP_VSPACE) /* Good - ship it. */ return 0; cpp_error (pfile, "invalid #ident"); - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); CPP_SET_WRITTEN (pfile, old_written); /* discard directive */ return 0; @@ -1616,7 +991,7 @@ do_pragma (pfile, keyword) key = CPP_WRITTEN (pfile); pfile->no_macro_expand++; - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); if (token != CPP_NAME) { if (token == CPP_VSPACE) @@ -1639,7 +1014,7 @@ do_pragma (pfile, keyword) pop = do_pragma_default (pfile); #undef tokis - if (get_directive_token (pfile) != CPP_VSPACE) + if (_cpp_get_directive_token (pfile) != CPP_VSPACE) goto skip; if (pop) @@ -1649,7 +1024,7 @@ do_pragma (pfile, keyword) skip: cpp_error (pfile, "malformed #pragma directive"); - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); empty: CPP_SET_WRITTEN (pfile, here); pfile->no_macro_expand--; @@ -1660,7 +1035,7 @@ static int do_pragma_default (pfile) cpp_reader *pfile; { - while (get_directive_token (pfile) != CPP_VSPACE) + while (_cpp_get_directive_token (pfile) != CPP_VSPACE) CPP_PUTC (pfile, ' '); return 0; } @@ -1696,7 +1071,7 @@ do_pragma_implementation (pfile) U_CHAR *copy; size_t len; - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); if (token == CPP_VSPACE) return 0; else if (token != CPP_STRING) @@ -1742,13 +1117,13 @@ do_pragma_poison (pfile) for (;;) { written = CPP_WRITTEN (pfile); - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); if (token == CPP_VSPACE) break; if (token != CPP_NAME) { cpp_error (pfile, "invalid #pragma poison directive"); - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); return 1; } @@ -1789,7 +1164,7 @@ do_sccs (pfile, keyword) { if (CPP_PEDANTIC (pfile)) cpp_pedwarn (pfile, "ANSI C does not allow `#sccs'"); - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); return 0; } #endif @@ -1817,18 +1192,18 @@ detect_if_not_defined (pfile) /* Save state required for restore. */ pfile->no_macro_expand++; - parse_set_mark (pfile); + CPP_SET_MARK (pfile); base_offset = CPP_WRITTEN (pfile); /* Look for `!', */ - if (get_directive_token (pfile) != CPP_OTHER + if (_cpp_get_directive_token (pfile) != CPP_OTHER || CPP_WRITTEN (pfile) != (size_t) base_offset + 1 || CPP_PWRITTEN (pfile)[-1] != '!') goto restore; /* ...then `defined', */ token_offset = CPP_WRITTEN (pfile); - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); if (token != CPP_NAME) goto restore; ident = pfile->token_buffer + token_offset; @@ -1838,11 +1213,11 @@ detect_if_not_defined (pfile) /* ...then an optional '(' and the name, */ token_offset = CPP_WRITTEN (pfile); - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); if (token == CPP_LPAREN) { token_offset = CPP_WRITTEN (pfile); - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); if (token != CPP_NAME) goto restore; need_rparen = 1; @@ -1854,22 +1229,22 @@ detect_if_not_defined (pfile) CPP_NUL_TERMINATE (pfile); /* ...then the ')', if necessary, */ - if ((!need_rparen || get_directive_token (pfile) == CPP_RPAREN) + if ((!need_rparen || _cpp_get_directive_token (pfile) == CPP_RPAREN) /* ...and make sure there's nothing else on the line. */ - && get_directive_token (pfile) == CPP_VSPACE) + && _cpp_get_directive_token (pfile) == CPP_VSPACE) control_macro = (U_CHAR *) xstrdup (ident); restore: CPP_SET_WRITTEN (pfile, base_offset); pfile->no_macro_expand--; - parse_goto_mark (pfile); + CPP_GOTO_MARK (pfile); } return control_macro; } /* - * #if is straightforward; just call eval_if_expr, then conditional_skip. + * #if is straightforward; just call _cpp_parse_expr, then conditional_skip. * Also, check for a reinclude preventer of the form #if !defined (MACRO). */ @@ -1879,7 +1254,7 @@ do_if (pfile, keyword) const struct directive *keyword ATTRIBUTE_UNUSED; { U_CHAR *control_macro = detect_if_not_defined (pfile); - int value = eval_if_expr (pfile); + int value = _cpp_parse_expr (pfile); conditional_skip (pfile, value == 0, T_IF, control_macro); return 0; } @@ -1914,39 +1289,17 @@ do_elif (pfile, keyword) skip_if_group (pfile); else { - int value = eval_if_expr (pfile); - if (value == 0) + if (_cpp_parse_expr (pfile) == 0) skip_if_group (pfile); else { ++pfile->if_stack->if_succeeded; /* continue processing input */ - output_line_command (pfile, same_file); + _cpp_output_line_command (pfile, same_file); } } return 0; } -/* Thin wrapper around _cpp_parse_expr, which doesn't have access to - * skip_rest_of_line. Also centralizes toggling parsing_if_directive. - */ - -static int -eval_if_expr (pfile) - cpp_reader *pfile; -{ - int value; - long old_written = CPP_WRITTEN (pfile); - - pfile->parsing_if_directive++; - value = _cpp_parse_expr (pfile); - pfile->parsing_if_directive--; - - skip_rest_of_line (pfile); - CPP_SET_WRITTEN (pfile, old_written); /* Pop */ - - return value; -} - /* * routine to handle ifdef/ifndef. Try to look up the symbol, * then do or don't skip to the #endif/#else/#elif depending @@ -1971,7 +1324,7 @@ do_ifdef (pfile, keyword) start_of_file = pfile->only_seen_white == 2; pfile->no_macro_expand++; - token = get_directive_token (pfile); + token = _cpp_get_directive_token (pfile); pfile->no_macro_expand--; ident = pfile->token_buffer + old_written; @@ -2005,12 +1358,12 @@ do_ifdef (pfile, keyword) if (!CPP_TRADITIONAL (pfile)) { int c; - cpp_skip_hspace (pfile); + _cpp_skip_hspace (pfile); c = PEEKC (); if (c != EOF && c != '\n') cpp_pedwarn (pfile, "garbage at end of `#%s' argument", keyword->name); } - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); conditional_skip (pfile, skip, T_IF, control_macro); return 0; @@ -2043,7 +1396,7 @@ conditional_skip (pfile, skip, type, control_macro) return; } else { ++pfile->if_stack->if_succeeded; - output_line_command (pfile, same_file); + _cpp_output_line_command (pfile, same_file); } } @@ -2061,10 +1414,10 @@ consider_directive_while_skipping (pfile, stack) const struct directive *kt; IF_STACK *temp; - cpp_skip_hspace (pfile); + _cpp_skip_hspace (pfile); ident = CPP_WRITTEN (pfile); - parse_name (pfile, GETC()); + _cpp_parse_name (pfile, GETC()); ident_len = CPP_WRITTEN (pfile) - ident; CPP_SET_WRITTEN (pfile, ident); @@ -2137,7 +1490,7 @@ skip_if_group (pfile) beg_of_line = CPP_BUFFER (pfile)->cur; if (! CPP_TRADITIONAL (pfile)) - cpp_skip_hspace (pfile); + _cpp_skip_hspace (pfile); c = GETC(); if (c == '\n') { @@ -2153,7 +1506,7 @@ skip_if_group (pfile) return; /* Caller will issue error. */ FORWARD(-1); - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); c = GETC(); if (c == EOF) @@ -2181,7 +1534,7 @@ do_else (pfile, keyword) const struct directive *keyword ATTRIBUTE_UNUSED; { validate_else (pfile, "#else"); - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack) { @@ -2208,7 +1561,7 @@ do_else (pfile, keyword) else { ++pfile->if_stack->if_succeeded; /* continue processing input */ - output_line_command (pfile, same_file); + _cpp_output_line_command (pfile, same_file); } return 0; } @@ -2223,7 +1576,7 @@ do_endif (pfile, keyword) const struct directive *keyword ATTRIBUTE_UNUSED; { validate_else (pfile, "#endif"); - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack) cpp_error (pfile, "`#endif' not within a conditional"); @@ -2237,16 +1590,16 @@ do_endif (pfile, keyword) See if it is at the end of the file. */ int c; - parse_set_mark (pfile); + CPP_SET_MARK (pfile); for (;;) { - cpp_skip_hspace (pfile); + _cpp_skip_hspace (pfile); c = GETC (); if (c != '\n') break; } - parse_goto_mark (pfile); + CPP_GOTO_MARK (pfile); if (c == EOF) { @@ -2258,7 +1611,7 @@ do_endif (pfile, keyword) } } free (temp); - output_line_command (pfile, same_file); + _cpp_output_line_command (pfile, same_file); } return 0; } @@ -2275,7 +1628,7 @@ validate_else (pfile, directive) if (! CPP_PEDANTIC (pfile)) return; - cpp_skip_hspace (pfile); + _cpp_skip_hspace (pfile); if (PEEKC () != '\n') cpp_pedwarn (pfile, "text following `%s' violates ANSI standard", directive); @@ -2300,734 +1653,40 @@ if_directive_name (pfile, ifs) } } -/* Get the next token, and add it to the text in pfile->token_buffer. - Return the kind of token we got. */ - -enum cpp_token -cpp_get_token (pfile) - cpp_reader *pfile; -{ - register int c, c2, c3; - enum cpp_token token; - struct cpp_options *opts = CPP_OPTIONS (pfile); - - get_next: - c = GETC(); - if (c == EOF) - { - if (CPP_BUFFER (pfile)->manual_pop) - /* If we've been reading from redirected input, the - frontend will pop the buffer. */ - return CPP_EOF; - else if (CPP_BUFFER (pfile)->seen_eof) - { - if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) == NULL) - return CPP_EOF; - - cpp_pop_buffer (pfile); - goto get_next; - } - else - { - cpp_buffer *next_buf = CPP_PREV_BUFFER (CPP_BUFFER (pfile)); - struct if_stack *ifs, *nifs; - - /* Unwind the conditional stack and generate error messages. */ - for (ifs = pfile->if_stack; - ifs != CPP_BUFFER (pfile)->if_stack; - ifs = nifs) - { - cpp_error_with_line (pfile, ifs->lineno, -1, - "unterminated `%s' conditional", - if_directive_name (pfile, ifs)); - - nifs = ifs->next; - free (ifs); - } - pfile->if_stack = ifs; - - if (CPP_BUFFER (pfile)->nominal_fname && next_buf != NULL) - { - /* We're about to return from an #include file. - Emit #line information now (as part of the CPP_POP) result. - But the #line refers to the file we will pop to. */ - cpp_buffer *cur_buffer = CPP_BUFFER (pfile); - CPP_BUFFER (pfile) = next_buf; - pfile->input_stack_listing_current = 0; - output_line_command (pfile, leave_file); - CPP_BUFFER (pfile) = cur_buffer; - } - - CPP_BUFFER (pfile)->seen_eof = 1; - return CPP_POP; - } - } - else - { - switch (c) - { - case '/': - if (PEEKC () == '=') - goto op2; - - comment: - if (opts->discard_comments) - c = skip_comment (pfile, c); - else - c = copy_comment (pfile, c); - if (c != ' ') - goto randomchar; - - /* Comments are equivalent to spaces. - For -traditional, a comment is equivalent to nothing. */ - if (opts->traditional || !opts->discard_comments) - return CPP_COMMENT; - else - { - CPP_PUTC (pfile, c); - return CPP_HSPACE; - } - - case '#': - if (pfile->parsing_if_directive) - { - cpp_skip_hspace (pfile); - parse_assertion (pfile); - return CPP_ASSERTION; - } - - if (pfile->parsing_define_directive && ! CPP_TRADITIONAL (pfile)) - { - CPP_RESERVE (pfile, 3); - CPP_PUTC_Q (pfile, '#'); - CPP_NUL_TERMINATE_Q (pfile); - if (PEEKC () != '#') - return CPP_STRINGIZE; - - FORWARD (1); - CPP_PUTC_Q (pfile, '#'); - CPP_NUL_TERMINATE_Q (pfile); - return CPP_TOKPASTE; - } - - if (!pfile->only_seen_white) - goto randomchar; - /* -traditional directives are recognized only with the # in - column 1. - XXX Layering violation. */ - if (CPP_TRADITIONAL (pfile) - && CPP_BUFFER (pfile)->cur - CPP_BUFFER (pfile)->line_base != 1) - goto randomchar; - if (handle_directive (pfile)) - return CPP_DIRECTIVE; - pfile->only_seen_white = 0; - goto randomchar; - - case '\"': - case '\'': - parse_string (pfile, c); - pfile->only_seen_white = 0; - return c == '\'' ? CPP_CHAR : CPP_STRING; - - case '$': - if (!opts->dollars_in_ident) - goto randomchar; - goto letter; - - case ':': - if (opts->cplusplus && PEEKC () == ':') - goto op2; - goto randomchar; - - case '&': - case '+': - case '|': - c2 = PEEKC (); - if (c2 == c || c2 == '=') - goto op2; - goto randomchar; - - case '*': - case '!': - case '%': - case '=': - case '^': - if (PEEKC () == '=') - goto op2; - goto randomchar; - - case '-': - c2 = PEEKC (); - if (c2 == '-' && opts->chill) - goto comment; /* Chill style comment */ - if (c2 == '-' || c2 == '=') - goto op2; - if (c2 == '>') - { - if (opts->cplusplus && PEEKN (1) == '*') - { - /* In C++, there's a ->* operator. */ - token = CPP_OTHER; - pfile->only_seen_white = 0; - CPP_RESERVE (pfile, 4); - CPP_PUTC_Q (pfile, c); - CPP_PUTC_Q (pfile, GETC ()); - CPP_PUTC_Q (pfile, GETC ()); - CPP_NUL_TERMINATE_Q (pfile); - return token; - } - goto op2; - } - goto randomchar; - - case '<': - if (pfile->parsing_include_directive) - { - for (;;) - { - CPP_PUTC (pfile, c); - if (c == '>') - break; - c = GETC (); - if (c == '\n' || c == EOF) - { - cpp_error (pfile, - "missing '>' in `#include '"); - break; - } - else if (c == '\r') - { - if (!CPP_BUFFER (pfile)->has_escapes) - { - /* Backslash newline is replaced by nothing. */ - CPP_ADJUST_WRITTEN (pfile, -1); - CPP_BUMP_LINE (pfile); - } - else - { - /* We might conceivably get \r- or \r in - here. Just delete 'em. */ - int d = GETC(); - if (d != '-' && d != ' ') - cpp_ice (pfile, "unrecognized escape \\r%c", d); - CPP_ADJUST_WRITTEN (pfile, -1); - } - } - } - return CPP_STRING; - } - /* else fall through */ - case '>': - c2 = PEEKC (); - if (c2 == '=') - goto op2; - /* GNU C++ supports MIN and MAX operators ?. */ - if (c2 != c && (!opts->cplusplus || c2 != '?')) - goto randomchar; - FORWARD(1); - CPP_RESERVE (pfile, 4); - CPP_PUTC (pfile, c); - CPP_PUTC (pfile, c2); - c3 = PEEKC (); - if (c3 == '=') - CPP_PUTC_Q (pfile, GETC ()); - CPP_NUL_TERMINATE_Q (pfile); - pfile->only_seen_white = 0; - return CPP_OTHER; - - case '.': - c2 = PEEKC (); - if (ISDIGIT(c2)) - { - CPP_RESERVE(pfile, 2); - CPP_PUTC_Q (pfile, '.'); - c = GETC (); - goto number; - } - - /* In C++ there's a .* operator. */ - if (opts->cplusplus && c2 == '*') - goto op2; - - if (c2 == '.' && PEEKN(1) == '.') - { - CPP_RESERVE(pfile, 4); - CPP_PUTC_Q (pfile, '.'); - CPP_PUTC_Q (pfile, '.'); - CPP_PUTC_Q (pfile, '.'); - FORWARD (2); - CPP_NUL_TERMINATE_Q (pfile); - pfile->only_seen_white = 0; - return CPP_3DOTS; - } - goto randomchar; - - op2: - token = CPP_OTHER; - pfile->only_seen_white = 0; - CPP_RESERVE(pfile, 3); - CPP_PUTC_Q (pfile, c); - CPP_PUTC_Q (pfile, GETC ()); - CPP_NUL_TERMINATE_Q (pfile); - return token; - - case 'L': - c2 = PEEKC (); - if ((c2 == '\'' || c2 == '\"') && !CPP_TRADITIONAL (pfile)) - { - CPP_PUTC (pfile, c); - c = GETC (); - parse_string (pfile, c); - pfile->only_seen_white = 0; - return c == '\'' ? CPP_WCHAR : CPP_WSTRING; - } - goto letter; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - number: - c2 = '.'; - for (;;) - { - CPP_RESERVE (pfile, 2); - CPP_PUTC_Q (pfile, c); - c = PEEKC (); - if (c == EOF) - break; - if (!is_numchar(c) && c != '.' - && ((c2 != 'e' && c2 != 'E' - && ((c2 != 'p' && c2 != 'P') - || CPP_OPTIONS (pfile)->c89)) - || (c != '+' && c != '-'))) - break; - FORWARD(1); - c2= c; - } - CPP_NUL_TERMINATE_Q (pfile); - pfile->only_seen_white = 0; - return CPP_NUMBER; - case 'b': case 'c': case 'd': case 'h': case 'o': - case 'B': case 'C': case 'D': case 'H': case 'O': - if (opts->chill && PEEKC () == '\'') - { - pfile->only_seen_white = 0; - CPP_RESERVE (pfile, 2); - CPP_PUTC_Q (pfile, c); - CPP_PUTC_Q (pfile, '\''); - FORWARD(1); - for (;;) - { - c = GETC(); - if (c == EOF) - goto chill_number_eof; - if (!is_numchar(c)) - break; - CPP_PUTC (pfile, c); - } - if (c == '\'') - { - CPP_RESERVE (pfile, 2); - CPP_PUTC_Q (pfile, c); - CPP_NUL_TERMINATE_Q (pfile); - return CPP_STRING; - } - else - { - FORWARD(-1); - chill_number_eof: - CPP_NUL_TERMINATE (pfile); - return CPP_NUMBER; - } - } - else - goto letter; - case '_': - case 'a': case 'e': case 'f': case 'g': case 'i': case 'j': - case 'k': case 'l': case 'm': case 'n': case 'p': case 'q': - case 'r': case 's': case 't': case 'u': case 'v': case 'w': - case 'x': case 'y': case 'z': - case 'A': case 'E': case 'F': case 'G': case 'I': case 'J': - case 'K': case 'M': case 'N': case 'P': case 'Q': case 'R': - case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': - case 'Y': case 'Z': - letter: - { - HASHNODE *hp; - unsigned char *ident; - int before_name_written = CPP_WRITTEN (pfile); - int ident_len; - parse_name (pfile, c); - pfile->only_seen_white = 0; - if (pfile->no_macro_expand) - return CPP_NAME; - ident = pfile->token_buffer + before_name_written; - ident_len = CPP_PWRITTEN (pfile) - ident; - hp = _cpp_lookup (pfile, ident, ident_len); - if (!hp) - return CPP_NAME; - if (hp->type == T_DISABLED) - { - if (pfile->output_escapes) - { /* Return "\r-IDENT", followed by '\0'. */ - int i; - CPP_RESERVE (pfile, 3); - ident = pfile->token_buffer + before_name_written; - CPP_ADJUST_WRITTEN (pfile, 2); - for (i = ident_len; i >= 0; i--) ident[i+2] = ident[i]; - ident[0] = '\r'; - ident[1] = '-'; - } - return CPP_NAME; - } - - /* If macro wants an arglist, verify that a '(' follows. */ - if (hp->type == T_MACRO && hp->value.defn->nargs >= 0) - { - int macbuf_whitespace = 0; - - while (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile))) - { - const U_CHAR *point = CPP_BUFFER (pfile)->cur; - for (;;) - { - cpp_skip_hspace (pfile); - c = PEEKC (); - if (c == '\n') - FORWARD(1); - else - break; - } - if (point != CPP_BUFFER (pfile)->cur) - macbuf_whitespace = 1; - if (c == '(') - goto is_macro_call; - else if (c != EOF) - goto not_macro_call; - cpp_pop_buffer (pfile); - } - - parse_set_mark (pfile); - for (;;) - { - cpp_skip_hspace (pfile); - c = PEEKC (); - if (c == '\n') - FORWARD(1); - else - break; - } - parse_goto_mark (pfile); - - if (c == '(') - goto is_macro_call; - - not_macro_call: - if (macbuf_whitespace) - CPP_PUTC (pfile, ' '); - return CPP_NAME; - } - is_macro_call: - /* This is now known to be a macro call. - Expand the macro, reading arguments as needed, - and push the expansion on the input stack. */ - _cpp_macroexpand (pfile, hp); - CPP_SET_WRITTEN (pfile, before_name_written); - } - goto get_next; - - case ' ': case '\t': case '\v': - for (;;) - { - CPP_PUTC (pfile, c); - c = PEEKC (); - if (c == EOF || !is_hspace(c)) - break; - FORWARD(1); - } - return CPP_HSPACE; - - case '\r': - if (CPP_BUFFER (pfile)->has_escapes) - { - c = GETC (); - if (c == '-') - { - if (pfile->output_escapes) - CPP_PUTS (pfile, "\r-", 2); - parse_name (pfile, GETC ()); - return CPP_NAME; - } - else if (c == ' ') - { - CPP_RESERVE (pfile, 2); - if (pfile->output_escapes) - CPP_PUTC_Q (pfile, '\r'); - CPP_PUTC_Q (pfile, c); - return CPP_HSPACE; - } - else - { - cpp_ice (pfile, "unrecognized escape \\r%c", c); - goto get_next; - } - } - else - { - /* Backslash newline is ignored. */ - CPP_BUMP_LINE (pfile); - goto get_next; - } - - case '\n': - CPP_PUTC (pfile, c); - if (pfile->only_seen_white == 0) - pfile->only_seen_white = 1; - CPP_BUMP_LINE (pfile); - if (! CPP_OPTIONS (pfile)->no_line_commands) - { - pfile->lineno++; - if (CPP_BUFFER (pfile)->lineno != pfile->lineno) - output_line_command (pfile, same_file); - } - return CPP_VSPACE; - - case '(': token = CPP_LPAREN; goto char1; - case ')': token = CPP_RPAREN; goto char1; - case '{': token = CPP_LBRACE; goto char1; - case '}': token = CPP_RBRACE; goto char1; - case ',': token = CPP_COMMA; goto char1; - case ';': token = CPP_SEMICOLON; goto char1; - - randomchar: - default: - token = CPP_OTHER; - char1: - pfile->only_seen_white = 0; - CPP_PUTC (pfile, c); - return token; - } - } -} - -/* Like cpp_get_token, but skip spaces and comments. */ - -enum cpp_token -cpp_get_non_space_token (pfile) - cpp_reader *pfile; -{ - int old_written = CPP_WRITTEN (pfile); - for (;;) - { - enum cpp_token token = cpp_get_token (pfile); - if (token != CPP_COMMENT && token != CPP_POP - && token != CPP_HSPACE && token != CPP_VSPACE) - return token; - CPP_SET_WRITTEN (pfile, old_written); - } -} - -/* Parse an identifier starting with C. */ - -static void -parse_name (pfile, c) - cpp_reader *pfile; - int c; -{ - for (;;) - { - if (! is_idchar(c)) - { - FORWARD (-1); - break; - } - - if (c == '$' && CPP_PEDANTIC (pfile)) - cpp_pedwarn (pfile, "`$' in identifier"); - - CPP_RESERVE(pfile, 2); /* One more for final NUL. */ - CPP_PUTC_Q (pfile, c); - c = GETC(); - if (c == EOF) - break; - } - CPP_NUL_TERMINATE_Q (pfile); - return; -} - -/* Parse and skip over a string starting with C. A single quoted - string is treated like a double -- some programs (e.g., troff) are - perverse this way. (However, a single quoted string is not allowed - to extend over multiple lines.) */ -static void -skip_string (pfile, c) - cpp_reader *pfile; - int c; -{ - long start_line, start_column; - cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column); - - while (1) - { - int cc = GETC(); - switch (cc) - { - case EOF: - cpp_error_with_line (pfile, start_line, start_column, - "unterminated string or character constant"); - if (pfile->multiline_string_line != start_line - && pfile->multiline_string_line != 0) - cpp_error_with_line (pfile, - pfile->multiline_string_line, -1, - "possible real start of unterminated constant"); - pfile->multiline_string_line = 0; - return; - - case '\n': - CPP_BUMP_LINE (pfile); - /* In Fortran and assembly language, silently terminate - strings of either variety at end of line. This is a - kludge around not knowing where comments are in these - languages. */ - if (CPP_OPTIONS (pfile)->lang_fortran - || CPP_OPTIONS (pfile)->lang_asm) - { - FORWARD(-1); - return; - } - /* Character constants may not extend over multiple lines. - In Standard C, neither may strings. We accept multiline - strings as an extension. */ - if (c == '\'') - { - cpp_error_with_line (pfile, start_line, start_column, - "unterminated character constant"); - FORWARD(-1); - return; - } - if (CPP_PEDANTIC (pfile) && pfile->multiline_string_line == 0) - cpp_pedwarn_with_line (pfile, start_line, start_column, - "string constant runs past end of line"); - if (pfile->multiline_string_line == 0) - pfile->multiline_string_line = start_line; - break; - - case '\r': - if (CPP_BUFFER (pfile)->has_escapes) - { - cpp_ice (pfile, "\\r escape inside string constant"); - FORWARD(1); - } - else - /* Backslash newline is replaced by nothing at all. */ - CPP_BUMP_LINE (pfile); - break; - - case '\\': - FORWARD(1); - break; - - case '\"': - case '\'': - if (cc == c) - return; - break; - } - } -} - -/* Parse a string and copy it to the output. */ - -static void -parse_string (pfile, c) +void +_cpp_handle_eof (pfile) cpp_reader *pfile; - int c; { - const U_CHAR *start = CPP_BUFFER (pfile)->cur; /* XXX Layering violation */ - const U_CHAR *limit; + cpp_buffer *next_buf = CPP_PREV_BUFFER (CPP_BUFFER (pfile)); + struct if_stack *ifs, *nifs; - skip_string (pfile, c); - - limit = CPP_BUFFER (pfile)->cur; - CPP_RESERVE (pfile, limit - start + 2); - CPP_PUTC_Q (pfile, c); - for (; start < limit; start++) - if (*start != '\r') - CPP_PUTC_Q (pfile, *start); -} - -/* Read an assertion into the token buffer, converting to - canonical form: `#predicate(a n swe r)' The next non-whitespace - character to read should be the first letter of the predicate. - Returns 0 for syntax error, 1 for bare predicate, 2 for predicate - with answer (see callers for why). In case of 0, an error has been - printed. */ -static int -parse_assertion (pfile) - cpp_reader *pfile; -{ - int c, dropwhite; - cpp_skip_hspace (pfile); - c = PEEKC(); - if (! is_idstart(c)) + /* Unwind the conditional stack and generate error messages. */ + for (ifs = pfile->if_stack; + ifs != CPP_BUFFER (pfile)->if_stack; + ifs = nifs) { - cpp_error (pfile, "assertion predicate is not an identifier"); - return 0; - } - CPP_PUTC(pfile, '#'); - FORWARD(1); - parse_name(pfile, c); + cpp_error_with_line (pfile, ifs->lineno, -1, + "unterminated `%s' conditional", + if_directive_name (pfile, ifs)); - c = PEEKC(); - if (c != '(') - { - if (is_hspace(c) || c == '\r') - cpp_skip_hspace (pfile); - c = PEEKC(); + nifs = ifs->next; + free (ifs); } - if (c != '(') - return 1; + pfile->if_stack = ifs; - CPP_PUTC(pfile, '('); - FORWARD(1); - dropwhite = 1; - while ((c = GETC()) != ')') + if (CPP_BUFFER (pfile)->nominal_fname && next_buf != NULL) { - if (is_space(c)) - { - if (! dropwhite) - { - CPP_PUTC(pfile, ' '); - dropwhite = 1; - } - } - else if (c == '\n' || c == EOF) - { - if (c == '\n') FORWARD(-1); - cpp_error (pfile, "un-terminated assertion answer"); - return 0; - } - else if (c == '\r') - /* \r cannot be a macro escape here. */ - CPP_BUMP_LINE (pfile); - else - { - CPP_PUTC (pfile, c); - dropwhite = 0; - } + /* We're about to return from an #include file. + Emit #line information now (as part of the CPP_POP) result. + But the #line refers to the file we will pop to. */ + cpp_buffer *cur_buffer = CPP_BUFFER (pfile); + CPP_BUFFER (pfile) = next_buf; + pfile->input_stack_listing_current = 0; + _cpp_output_line_command (pfile, leave_file); + CPP_BUFFER (pfile) = cur_buffer; } - if (pfile->limit[-1] == ' ') - pfile->limit[-1] = ')'; - else if (pfile->limit[-1] == '(') - { - cpp_error (pfile, "empty token sequence in assertion"); - return 0; - } - else - CPP_PUTC (pfile, ')'); - - CPP_NUL_TERMINATE (pfile); - return 2; + CPP_BUFFER (pfile)->seen_eof = 1; } static int @@ -3045,9 +1704,9 @@ do_assert (pfile, keyword) if (CPP_PEDANTIC (pfile) && CPP_OPTIONS (pfile)->done_initializing) cpp_pedwarn (pfile, "ANSI C does not allow `#assert'"); - cpp_skip_hspace (pfile); + _cpp_skip_hspace (pfile); sym = CPP_PWRITTEN (pfile); /* remember where it starts */ - ret = parse_assertion (pfile); + ret = _cpp_parse_assertion (pfile); if (ret == 0) goto error; else if (ret == 1) @@ -3056,7 +1715,7 @@ do_assert (pfile, keyword) goto error; } - cpp_skip_hspace (pfile); + _cpp_skip_hspace (pfile); c = PEEKC(); if (c != EOF && c != '\n') { @@ -3094,7 +1753,7 @@ do_assert (pfile, keyword) return 0; error: - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); pfile->limit = sym; /* Pop */ return 0; } @@ -3112,14 +1771,14 @@ do_unassert (pfile, keyword) if (CPP_PEDANTIC (pfile) && CPP_OPTIONS (pfile)->done_initializing) cpp_pedwarn (pfile, "ANSI C does not allow `#unassert'"); - cpp_skip_hspace (pfile); + _cpp_skip_hspace (pfile); sym = CPP_PWRITTEN (pfile); /* remember where it starts */ - ret = parse_assertion (pfile); + ret = _cpp_parse_assertion (pfile); if (ret == 0) goto error; - cpp_skip_hspace (pfile); + _cpp_skip_hspace (pfile); c = PEEKC (); if (c != EOF && c != '\n') cpp_error (pfile, "junk at end of `#unassert'"); @@ -3163,54 +1822,112 @@ do_unassert (pfile, keyword) pfile->limit = sym; /* Pop */ return 0; error: - skip_rest_of_line (pfile); + _cpp_skip_rest_of_line (pfile); pfile->limit = sym; /* Pop */ return 0; } -/* Process STR as if it appeared as the body of an #unassert. */ +/* These are for -D, -U, -A. */ + +/* Process the string STR as if it appeared as the body of a #define. + If STR is just an identifier, define it with value 1. + If STR has anything after the identifier, then it should + be identifier=definition. */ + void -cpp_unassert (pfile, str) +cpp_define (pfile, str) cpp_reader *pfile; const char *str; { - if (cpp_push_buffer (pfile, str, strlen (str)) != NULL) + char *buf, *p; + size_t count; + + p = strchr (str, '='); + /* Copy the entire option so we can modify it. + Change the first "=" in the string to a space. If there is none, + tack " 1" on the end. Then add a newline and a NUL. */ + + if (p) { - do_unassert (pfile, NULL); - cpp_pop_buffer (pfile); + count = strlen (str) + 2; + buf = alloca (count); + memcpy (buf, str, count - 2); + buf[p - str] = ' '; + buf[count - 2] = '\n'; + buf[count - 1] = '\0'; + } + else + { + count = strlen (str) + 4; + buf = alloca (count); + memcpy (buf, str, count - 4); + strcpy (&buf[count-4], " 1\n"); } -} - -/* Remember the current position of PFILE so it may be returned to - after looking ahead a bit. - Note that when you set a mark, you _must_ return to that mark. You - may not forget about it and continue parsing. You may not pop a - buffer with an active mark. You may not call CPP_BUMP_LINE while a - mark is active. */ + if (cpp_push_buffer (pfile, buf, count - 1) != NULL) + { + do_define (pfile, NULL); + cpp_pop_buffer (pfile); + } +} -static void -parse_set_mark (pfile) +/* Process MACRO as if it appeared as the body of an #undef. */ +void +cpp_undef (pfile, macro) cpp_reader *pfile; + const char *macro; { - cpp_buffer *ip = CPP_BUFFER (pfile); - if (ACTIVE_MARK_P()) - cpp_ice (pfile, "mark active in parse_set_mark"); - - ip->mark = ip->cur - ip->buf; + /* Copy the string so we can append a newline. */ + size_t len = strlen (macro); + char *buf = alloca (len + 2); + memcpy (buf, macro, len); + buf[len] = '\n'; + buf[len + 1] = '\0'; + if (cpp_push_buffer (pfile, buf, len + 1)) + { + do_undef (pfile, NULL); + cpp_pop_buffer (pfile); + } } -/* Backup the current position of PFILE to that saved in its mark, - and clear the mark. */ +/* Process the string STR as if it appeared as the body of a #assert. */ +void +cpp_assert (pfile, str) + cpp_reader *pfile; + const char *str; +{ + if (cpp_push_buffer (pfile, str, strlen (str)) != NULL) + { + do_assert (pfile, NULL); + cpp_pop_buffer (pfile); + } +} -static void -parse_goto_mark (pfile) +/* Process STR as if it appeared as the body of an #unassert. */ +void +cpp_unassert (pfile, str) cpp_reader *pfile; + const char *str; { - cpp_buffer *ip = CPP_BUFFER (pfile); - if (!ACTIVE_MARK_P()) - cpp_ice (pfile, "mark not active in parse_goto_mark"); + if (cpp_push_buffer (pfile, str, strlen (str)) != NULL) + { + do_unassert (pfile, NULL); + cpp_pop_buffer (pfile); + } +} - ip->cur = ip->buf + ip->mark; - ip->mark = -1; +/* Determine whether the identifier ID, of length LEN, is a defined macro. */ +int +cpp_defined (pfile, id, len) + cpp_reader *pfile; + const U_CHAR *id; + int len; +{ + HASHNODE *hp = _cpp_lookup (pfile, id, len); + if (hp && hp->type == T_POISON) + { + cpp_error (pfile, "attempt to use poisoned `%s'", hp->name); + return 0; + } + return (hp != NULL); } diff --git a/gcc/cpplib.h b/gcc/cpplib.h index 7906d0c..19f958f 100644 --- a/gcc/cpplib.h +++ b/gcc/cpplib.h @@ -40,6 +40,7 @@ enum cpp_token CPP_HSPACE, CPP_VSPACE, /* newlines and #line directives */ CPP_NAME, + CPP_MACRO, CPP_NUMBER, CPP_CHAR, CPP_WCHAR, @@ -233,11 +234,6 @@ struct cpp_reader #define CPP_ADJUST_WRITTEN(PFILE,DELTA) ((PFILE)->limit += (DELTA)) #define CPP_SET_WRITTEN(PFILE,N) ((PFILE)->limit = (PFILE)->token_buffer + (N)) -/* Make sure PFILE->token_buffer has space for at least N more characters. */ -#define CPP_RESERVE(PFILE, N) \ - (CPP_WRITTEN (PFILE) + (size_t)(N) > (PFILE)->token_buffer_size \ - && (cpp_grow_buffer (PFILE, N), 0)) - #define CPP_OPTIONS(PFILE) ((PFILE)->opts) #define CPP_BUFFER(PFILE) ((PFILE)->buffer) @@ -438,7 +434,6 @@ extern const char *progname; extern int cpp_handle_options PARAMS ((cpp_reader *, int, char **)); extern enum cpp_token cpp_get_token PARAMS ((cpp_reader *)); extern enum cpp_token cpp_get_non_space_token PARAMS ((cpp_reader *)); -extern enum cpp_token get_directive_token PARAMS ((cpp_reader *)); extern void cpp_reader_init PARAMS ((cpp_reader *)); extern void cpp_options_init PARAMS ((cpp_options *)); @@ -482,22 +477,15 @@ extern void cpp_pedwarn_with_file_and_line PARAMS ((cpp_reader *, const char *, extern void cpp_error_from_errno PARAMS ((cpp_reader *, const char *)); extern void cpp_notice_from_errno PARAMS ((cpp_reader *, const char *)); -extern void cpp_grow_buffer PARAMS ((cpp_reader *, long)); extern cpp_buffer *cpp_push_buffer PARAMS ((cpp_reader *, const unsigned char *, long)); extern cpp_buffer *cpp_pop_buffer PARAMS ((cpp_reader *)); extern int cpp_defined PARAMS ((cpp_reader *, const unsigned char *, int)); -extern void quote_string PARAMS ((cpp_reader *, const char *)); extern void cpp_expand_to_buffer PARAMS ((cpp_reader *, const unsigned char *, int)); extern void cpp_scan_buffer PARAMS ((cpp_reader *)); -/* Last arg to output_line_command. */ -enum file_change_code {same_file, rename_file, enter_file, leave_file}; -extern void output_line_command PARAMS ((cpp_reader *, - enum file_change_code)); - /* In cppfiles.c */ extern int cpp_included PARAMS ((cpp_reader *, const char *)); extern int cpp_read_file PARAMS ((cpp_reader *, const char *)); diff --git a/gcc/po/POTFILES.in b/gcc/po/POTFILES.in index 8f2b47a..48e1b5d 100644 --- a/gcc/po/POTFILES.in +++ b/gcc/po/POTFILES.in @@ -594,6 +594,7 @@ cppfiles.c cpphash.c cpphash.h cppinit.c +cpplex.c cpplib.c cpplib.h cppmain.c