diff options
Diffstat (limited to 'gcc/cpplex.c')
-rw-r--r-- | gcc/cpplex.c | 418 |
1 files changed, 227 insertions, 191 deletions
diff --git a/gcc/cpplex.c b/gcc/cpplex.c index f0414a0..117f610 100644 --- a/gcc/cpplex.c +++ b/gcc/cpplex.c @@ -55,7 +55,6 @@ static void bump_column PARAMS ((cpp_printer *, unsigned int, unsigned int)); static void expand_name_space PARAMS ((cpp_toklist *, unsigned int)); static void expand_token_space PARAMS ((cpp_toklist *)); -static void init_token_list PARAMS ((cpp_reader *, cpp_toklist *, int)); static void pedantic_whitespace PARAMS ((cpp_reader *, U_CHAR *, unsigned int)); @@ -491,7 +490,7 @@ cpp_scan_buffer (pfile, print) for (;;) { token = cpp_get_token (pfile); - if (token == CPP_EOF || token == CPP_VSPACE + if (token == CPP_VSPACE || token == CPP_EOF /* XXX Temporary kluge - force flush after #include only */ || (token == CPP_DIRECTIVE && CPP_BUFFER (pfile)->nominal_fname != print->last_fname)) @@ -548,63 +547,212 @@ expand_token_space (list) cpp_toklist *list; { list->tokens_cap *= 2; + if (list->flags & LIST_OFFSET) + list->tokens--; list->tokens = (cpp_token *) - xrealloc (list->tokens - 1, (list->tokens_cap + 1) * sizeof (cpp_token)); - list->tokens++; /* Skip the dummy. */ + xrealloc (list->tokens, (list->tokens_cap + 1) * sizeof (cpp_token)); + if (list->flags & LIST_OFFSET) + list->tokens++; /* Skip the dummy. */ } /* Initialize a token list. We allocate an extra token in front of the token list, as this allows us to always peek at the previous token without worrying about underflowing the list. */ -static void -init_token_list (pfile, list, recycle) - cpp_reader *pfile; +void +_cpp_init_toklist (list) cpp_toklist *list; - int recycle; { - /* Recycling a used list saves 3 free-malloc pairs. */ - if (!recycle) - { - /* Initialize token space. Put a dummy token before the start - that will fail matches. */ - list->tokens_cap = 256; /* 4K's worth. */ - list->tokens = (cpp_token *) - xmalloc ((list->tokens_cap + 1) * sizeof (cpp_token)); - list->tokens[0].type = CPP_EOF; - list->tokens++; - - /* Initialize name space. */ - list->name_cap = 1024; - list->namebuf = (unsigned char *) xmalloc (list->name_cap); - - /* Only create a comment space on demand. */ - list->comments_cap = 0; - list->comments = 0; - } + /* Initialize token space. Put a dummy token before the start + that will fail matches. */ + list->tokens_cap = 256; /* 4K's worth. */ + list->tokens = (cpp_token *) + xmalloc ((list->tokens_cap + 1) * sizeof (cpp_token)); + list->tokens[0].type = CPP_EOF; + list->tokens++; + + /* Initialize name space. */ + list->name_cap = 1024; + list->namebuf = (unsigned char *) xmalloc (list->name_cap); + + /* Only create a comment space on demand. */ + list->comments_cap = 0; + list->comments = 0; + + list->flags = LIST_OFFSET; + _cpp_clear_toklist (list); +} +/* Clear a token list. */ +void +_cpp_clear_toklist (list) + cpp_toklist *list; +{ list->tokens_used = 0; list->name_used = 0; list->comments_used = 0; - if (pfile->buffer) - list->line = pfile->buffer->lineno; - list->dir_handler = 0; - list->dir_flags = 0; + list->dirno = -1; + list->flags &= LIST_OFFSET; /* clear all but that one */ +} + +/* Free a token list. Does not free the list itself, which may be + embedded in a larger structure. */ +void +_cpp_free_toklist (list) + cpp_toklist *list; +{ + if (list->comments) + free (list->comments); + if (list->flags & LIST_OFFSET) + free (list->tokens - 1); /* Backup over dummy token. */ + else + free (list->tokens); + free (list->namebuf); } -/* Scan an entire line and create a token list for it. Does not - macro-expand or execute directives. */ +/* Slice a token list: copy the sublist [START, FINISH) into COPY. + COPY is assumed not to be initialized. The comment space is not + copied. */ +void +_cpp_slice_toklist (copy, start, finish) + cpp_toklist *copy; + const cpp_token *start, *finish; +{ + unsigned int i, n; + size_t bytes; + + n = finish - start; + copy->tokens_cap = n; + copy->tokens = (cpp_token *) xmalloc (n * sizeof (cpp_token)); + memcpy (copy->tokens, start, n * sizeof (cpp_token)); + + bytes = 0; + for (i = 0; i < n; i++) + if (token_spellings[start[i].type].type > SPELL_NONE) + bytes += start[i].val.name.len; + + copy->namebuf = xmalloc (bytes); + bytes = 0; + for (i = 0; i < n; i++) + if (token_spellings[start[i].type].type > SPELL_NONE) + { + memcpy (copy->namebuf + bytes, + start[i].val.name.text, start[i].val.name.len); + copy->tokens[i].val.name.text = copy->namebuf + bytes; + bytes += start[i].val.name.len; + } + + copy->tokens_cap = n; + copy->tokens_used = n; + copy->name_used = bytes; + copy->name_cap = bytes; + copy->comments = 0; + copy->comments_cap = 0; + copy->comments_used = 0; + + copy->flags = 0; + copy->dirno = -1; +} +/* Shrink a token list down to the minimum size. */ void -_cpp_scan_line (pfile, list) +_cpp_squeeze_toklist (list) + cpp_toklist *list; +{ + long delta; + const U_CHAR *old_namebuf; + + if (list->flags & LIST_OFFSET) + { + list->tokens--; + memmove (list->tokens, list->tokens + 1, + list->tokens_used * sizeof (cpp_token)); + list->tokens = xrealloc (list->tokens, + list->tokens_used * sizeof (cpp_token)); + list->flags &= ~LIST_OFFSET; + } + else + list->tokens = xrealloc (list->tokens, + list->tokens_used * sizeof (cpp_token)); + list->tokens_cap = list->tokens_used; + + old_namebuf = list->namebuf; + list->namebuf = xrealloc (list->namebuf, list->name_used); + list->name_cap = list->name_used; + + /* Fix up token text pointers. */ + delta = list->namebuf - old_namebuf; + if (delta) + { + unsigned int i; + + for (i = 0; i < list->tokens_used; i++) + if (token_spellings[list->tokens[i].type].type > SPELL_NONE) + list->tokens[i].val.name.text += delta; + } + + if (list->comments_cap) + { + list->comments = xrealloc (list->comments, + list->comments_used * sizeof (cpp_token)); + list->comments_cap = list->comments_used; + } +} + +/* Compare two tokens. */ +int +_cpp_equiv_tokens (a, b) + const cpp_token *a, *b; +{ + if (a->type != b->type + || a->flags != b->flags + || a->aux != b->aux) + return 0; + + if (token_spellings[a->type].type > SPELL_NONE) + { + if (a->val.name.len != b->val.name.len + || ustrncmp(a->val.name.text, + b->val.name.text, + a->val.name.len)) + return 0; + } + return 1; +} + +/* Compare two token lists. */ +int +_cpp_equiv_toklists (a, b) + const cpp_toklist *a, *b; +{ + unsigned int i; + + if (a->tokens_used != b->tokens_used) + return 0; + + for (i = 0; i < a->tokens_used; i++) + if (! _cpp_equiv_tokens (&a->tokens[i], &b->tokens[i])) + return 0; + return 1; +} + +/* Scan until we encounter a token of type STOP or a newline, and + create a token list for it. Does not macro-expand or execute + directives. The final token is not included in the list or + consumed from the input. Returns the type of the token stopped at. */ + +enum cpp_ttype +_cpp_scan_until (pfile, list, stop) cpp_reader *pfile; cpp_toklist *list; + enum cpp_ttype stop; { int i, col; long written, len; enum cpp_ttype type; int space_before; - init_token_list (pfile, list, 1); + _cpp_clear_toklist (list); + list->line = CPP_BUF_LINE (CPP_BUFFER (pfile)); written = CPP_WRITTEN (pfile); i = 0; @@ -636,14 +784,14 @@ _cpp_scan_line (pfile, list) if (type == CPP_MACRO) type = CPP_NAME; + if (type == CPP_VSPACE || type == stop) + break; + list->tokens_used++; TOK_TYPE (list, i) = type; TOK_COL (list, i) = col; TOK_FLAGS (list, i) = space_before ? PREV_WHITESPACE : 0; - if (type == CPP_VSPACE) - break; - TOK_LEN (list, i) = len; if (token_spellings[type].type > SPELL_NONE) { @@ -656,12 +804,14 @@ _cpp_scan_line (pfile, list) i++; space_before = 0; } - TOK_AUX (list, i) = CPP_BUFFER (pfile)->lineno + 1; - /* XXX Temporary kluge: put back the newline. */ + /* XXX Temporary kluge: put back the newline (or whatever). */ FORWARD(-1); -} + /* Don't consider the first token to have white before. */ + TOK_FLAGS (list, 0) &= ~PREV_WHITESPACE; + return type; +} /* Skip a C-style block comment. We know it's a comment, and point is at the second character of the starter. */ @@ -1060,85 +1210,6 @@ parse_string (pfile, c) 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 (c == '\n') - { - cpp_error (pfile, "assertion without predicate"); - return 0; - } - else 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, ')'); - - return 2; -} - /* Get the next token, and add it to the text in pfile->token_buffer. Return the kind of token we got. */ @@ -1176,11 +1247,7 @@ _cpp_lex_token (pfile) if (!CPP_OPTION (pfile, discard_comments)) return CPP_COMMENT; else if (CPP_TRADITIONAL (pfile)) - { - if (pfile->parsing_define_directive) - return CPP_COMMENT; - goto get_next; - } + goto get_next; else { CPP_PUTC (pfile, c); @@ -1191,42 +1258,24 @@ _cpp_lex_token (pfile) CPP_PUTC (pfile, c); hash: - if (pfile->parsing_if_directive) + c2 = PEEKC (); + if (c2 == '#') { - CPP_ADJUST_WRITTEN (pfile, -1); - if (_cpp_parse_assertion (pfile)) - return CPP_ASSERTION; - return CPP_OTHER; + FORWARD (1); + CPP_PUTC (pfile, c2); + return CPP_PASTE; } - - if (pfile->parsing_define_directive) + else if (c2 == '%' && PEEKN (1) == ':') { - c2 = PEEKC (); - if (c2 == '#') - { - FORWARD (1); - CPP_PUTC (pfile, c2); - } - else if (c2 == '%' && PEEKN (1) == ':') - { - /* Digraph: "%:" == "#". */ - FORWARD (1); - CPP_RESERVE (pfile, 2); - CPP_PUTC_Q (pfile, c2); - CPP_PUTC_Q (pfile, GETC ()); - } - else - return CPP_HASH; - + /* Digraph: "%:" == "#". */ + FORWARD (1); + CPP_RESERVE (pfile, 2); + CPP_PUTC_Q (pfile, c2); + CPP_PUTC_Q (pfile, GETC ()); return CPP_PASTE; } - - if (!pfile->only_seen_white) - return CPP_OTHER; - - /* Remove the "#" or "%:" from the token buffer. */ - CPP_ADJUST_WRITTEN (pfile, (c == '#' ? -1 : -2)); - return CPP_DIRECTIVE; + else + return CPP_HASH; case '\"': case '\'': @@ -1697,13 +1746,22 @@ cpp_get_token (pfile) case CPP_COMMENT: return token; - case CPP_DIRECTIVE: + case CPP_HASH: pfile->potential_control_macro = 0; + if (!pfile->only_seen_white) + return CPP_HASH; + /* XXX shouldn't have to do this - remove the hash or %: from + the token buffer. */ + if (CPP_PWRITTEN (pfile)[-1] == '#') + CPP_ADJUST_WRITTEN (pfile, -1); + else + CPP_ADJUST_WRITTEN (pfile, -2); + if (_cpp_handle_directive (pfile)) - return CPP_DIRECTIVE; + return CPP_DIRECTIVE; pfile->only_seen_white = 0; CPP_PUTC (pfile, '#'); - return CPP_OTHER; + return CPP_HASH; case CPP_MACRO: pfile->potential_control_macro = 0; @@ -1777,11 +1835,6 @@ _cpp_get_directive_token (pfile) goto get_next; return CPP_HSPACE; - case CPP_DIRECTIVE: - /* Don't execute the directive, but don't smash it to OTHER either. */ - CPP_PUTC (pfile, '#'); - return CPP_DIRECTIVE; - case CPP_MACRO: if (! pfile->no_macro_expand && maybe_macroexpand (pfile, old_written)) @@ -2134,7 +2187,7 @@ _cpp_init_input_buffer (pfile) U_CHAR *tmp; init_chartab (); - init_token_list (pfile, &pfile->directbuf, 0); + _cpp_init_toklist (&pfile->directbuf); /* Determine the appropriate size for the input buffer. Normal C source files are smaller than eight K. */ @@ -2295,17 +2348,6 @@ expand_comment_space (list) } void -cpp_free_token_list (list) - cpp_toklist *list; -{ - if (list->comments) - free (list->comments); - free (list->tokens - 1); /* Backup over dummy token. */ - free (list->namebuf); - free (list); -} - -void init_trigraph_map () { trigraph_map['='] = '#'; @@ -3175,7 +3217,7 @@ _cpp_lex_line (pfile, list) break; } /* Is this the beginning of a header name? */ - if (list->dir_flags & SYNTAX_INCLUDE) + if (list->flags & SYNTAX_INCLUDE) { c = '>'; /* Terminator. */ cur_token->type = CPP_HEADER_NAME; @@ -3304,7 +3346,7 @@ _cpp_lex_line (pfile, list) invalid directives in assembly source, we don't know where the comments are, and # may introduce assembler pseudo-ops. */ - if (IS_DIRECTIVE (list) && list->dir_handler == 0 + if (IS_DIRECTIVE (list) && list->dirno == -1 && list->tokens[1].type != CPP_VSPACE && !CPP_OPTION (pfile, lang_asm)) cpp_error_with_line (pfile, list->line, list->tokens[1].col, @@ -3385,31 +3427,25 @@ void _cpp_lex_file (pfile) cpp_reader* pfile; { - int recycle; cpp_toklist* list; init_trigraph_map (); list = (cpp_toklist *) xmalloc (sizeof (cpp_toklist)); + _cpp_init_toklist (list); - for (recycle = 0; ;) + for (;;) { - init_token_list (pfile, list, recycle); - recycle = 1; - _cpp_lex_line (pfile, list); if (list->tokens[0].type == CPP_EOF) break; - if (list->dir_handler) - { - if (list->dir_handler (pfile)) - { - list = (cpp_toklist *) xmalloc (sizeof (cpp_toklist)); - recycle = 0; - } - } +#if 0 + if (list->dirno) + _cpp_handle_directive (pfile, list); else +#endif _cpp_output_list (pfile, list); + _cpp_clear_toklist (list); } } |