00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "cpplib.h"
00025 #include "internal.h"
00026
00027 enum spell_type
00028 {
00029 SPELL_OPERATOR = 0,
00030 SPELL_IDENT,
00031 SPELL_LITERAL,
00032 SPELL_NONE
00033 };
00034
00035 struct token_spelling
00036 {
00037 enum spell_type category;
00038 const unsigned char *name;
00039 };
00040
00041 static const unsigned char *const digraph_spellings[] =
00042 { U"%:", U"%:%:", U"<:", U":>", U"<%", U"%>" };
00043
00044 #define OP(e, s) { SPELL_OPERATOR, U s },
00045 #define TK(e, s) { SPELL_ ## s, U #e },
00046 static const struct token_spelling token_spellings[N_TTYPES] = { TTYPE_TABLE };
00047 #undef OP
00048 #undef TK
00049
00050 #define TOKEN_SPELL(token) (token_spellings[(token)->type].category)
00051 #define TOKEN_NAME(token) (token_spellings[(token)->type].name)
00052
00053 static void add_line_note (cpp_buffer *, const uchar *, unsigned int);
00054 static int skip_line_comment (cpp_reader *);
00055 static void skip_whitespace (cpp_reader *, cppchar_t);
00056 static cpp_hashnode *lex_identifier (cpp_reader *, const uchar *);
00057 static void lex_number (cpp_reader *, cpp_string *);
00058 static bool forms_identifier_p (cpp_reader *, int);
00059 static void lex_string (cpp_reader *, cpp_token *, const uchar *);
00060 static void save_comment (cpp_reader *, cpp_token *, const uchar *, cppchar_t);
00061 static void create_literal (cpp_reader *, cpp_token *, const uchar *,
00062 unsigned int, enum cpp_ttype);
00063 static bool warn_in_comment (cpp_reader *, _cpp_line_note *);
00064 static int name_p (cpp_reader *, const cpp_string *);
00065 static tokenrun *next_tokenrun (tokenrun *);
00066
00067 static _cpp_buff *new_buff (size_t);
00068
00069
00070
00071
00072
00073
00074 int
00075 cpp_ideq (const cpp_token *token, const char *string)
00076 {
00077 if (token->type != CPP_NAME)
00078 return 0;
00079
00080 return !ustrcmp (NODE_NAME (token->val.node), (const uchar *) string);
00081 }
00082
00083
00084
00085 static void
00086 add_line_note (cpp_buffer *buffer, const uchar *pos, unsigned int type)
00087 {
00088 if (buffer->notes_used == buffer->notes_cap)
00089 {
00090 buffer->notes_cap = buffer->notes_cap * 2 + 200;
00091 buffer->notes = xrealloc (buffer->notes,
00092 buffer->notes_cap * sizeof (_cpp_line_note));
00093 }
00094
00095 buffer->notes[buffer->notes_used].pos = pos;
00096 buffer->notes[buffer->notes_used].type = type;
00097 buffer->notes_used++;
00098 }
00099
00100
00101
00102 void
00103 _cpp_clean_line (cpp_reader *pfile)
00104 {
00105 cpp_buffer *buffer;
00106 const uchar *s;
00107 uchar c, *d, *p;
00108
00109 buffer = pfile->buffer;
00110 buffer->cur_note = buffer->notes_used = 0;
00111 buffer->cur = buffer->line_base = buffer->next_line;
00112 buffer->need_line = false;
00113 s = buffer->next_line - 1;
00114
00115 if (!buffer->from_stage3)
00116 {
00117
00118
00119
00120 for (;;)
00121 {
00122 c = *++s;
00123 if (c == '\n' || c == '\r')
00124 {
00125 d = (uchar *) s;
00126
00127 if (s == buffer->rlimit)
00128 goto done;
00129
00130
00131 if (c == '\r' && s[1] == '\n')
00132 s++;
00133
00134 if (s == buffer->rlimit)
00135 goto done;
00136
00137
00138 p = d;
00139 while (p != buffer->next_line && is_nvspace (p[-1]))
00140 p--;
00141 if (p == buffer->next_line || p[-1] != '\\')
00142 goto done;
00143
00144
00145
00146 add_line_note (buffer, p - 1, p != d ? ' ' : '\\');
00147 d = p - 2;
00148 buffer->next_line = p - 1;
00149 break;
00150 }
00151 if (c == '?' && s[1] == '?' && _cpp_trigraph_map[s[2]])
00152 {
00153
00154
00155 add_line_note (buffer, s, s[2]);
00156 if (CPP_OPTION (pfile, trigraphs))
00157 {
00158
00159
00160 d = (uchar *) s;
00161 *d = _cpp_trigraph_map[s[2]];
00162 s += 2;
00163 break;
00164 }
00165 }
00166 }
00167
00168
00169 for (;;)
00170 {
00171 c = *++s;
00172 *++d = c;
00173
00174 if (c == '\n' || c == '\r')
00175 {
00176
00177 if (c == '\r' && s != buffer->rlimit && s[1] == '\n')
00178 s++;
00179 if (s == buffer->rlimit)
00180 break;
00181
00182
00183 p = d;
00184 while (p != buffer->next_line && is_nvspace (p[-1]))
00185 p--;
00186 if (p == buffer->next_line || p[-1] != '\\')
00187 break;
00188
00189 add_line_note (buffer, p - 1, p != d ? ' ': '\\');
00190 d = p - 2;
00191 buffer->next_line = p - 1;
00192 }
00193 else if (c == '?' && s[1] == '?' && _cpp_trigraph_map[s[2]])
00194 {
00195
00196 add_line_note (buffer, d, s[2]);
00197 if (CPP_OPTION (pfile, trigraphs))
00198 {
00199 *d = _cpp_trigraph_map[s[2]];
00200 s += 2;
00201 }
00202 }
00203 }
00204 }
00205 else
00206 {
00207 do
00208 s++;
00209 while (*s != '\n' && *s != '\r');
00210 d = (uchar *) s;
00211
00212
00213 if (*s == '\r' && s != buffer->rlimit && s[1] == '\n')
00214 s++;
00215 }
00216
00217 done:
00218 *d = '\n';
00219
00220 add_line_note (buffer, d + 1, '\n');
00221 buffer->next_line = s + 1;
00222 }
00223
00224
00225
00226 static bool
00227 warn_in_comment (cpp_reader *pfile, _cpp_line_note *note)
00228 {
00229 const uchar *p;
00230
00231
00232
00233
00234 if (note->type != '/')
00235 return false;
00236
00237
00238
00239 if (CPP_OPTION (pfile, trigraphs))
00240 return note[1].pos == note->pos;
00241
00242
00243 p = note->pos + 3;
00244 while (is_nvspace (*p))
00245 p++;
00246
00247
00248
00249 return (*p == '\n' && p < note[1].pos);
00250 }
00251
00252
00253
00254 void
00255 _cpp_process_line_notes (cpp_reader *pfile, int in_comment)
00256 {
00257 cpp_buffer *buffer = pfile->buffer;
00258
00259 for (;;)
00260 {
00261 _cpp_line_note *note = &buffer->notes[buffer->cur_note];
00262 unsigned int col;
00263
00264 if (note->pos > buffer->cur)
00265 break;
00266
00267 buffer->cur_note++;
00268 col = CPP_BUF_COLUMN (buffer, note->pos + 1);
00269
00270 if (note->type == '\\' || note->type == ' ')
00271 {
00272 if (note->type == ' ' && !in_comment)
00273 cpp_error_with_line (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
00274 "backslash and newline separated by space");
00275
00276 if (buffer->next_line > buffer->rlimit)
00277 {
00278 cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->line_table->highest_line, col,
00279 "backslash-newline at end of file");
00280
00281 buffer->next_line = buffer->rlimit;
00282 }
00283
00284 buffer->line_base = note->pos;
00285 CPP_INCREMENT_LINE (pfile, 0);
00286 }
00287 else if (_cpp_trigraph_map[note->type])
00288 {
00289 if (CPP_OPTION (pfile, warn_trigraphs)
00290 && (!in_comment || warn_in_comment (pfile, note)))
00291 {
00292 if (CPP_OPTION (pfile, trigraphs))
00293 cpp_error_with_line (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
00294 "trigraph ??%c converted to %c",
00295 note->type,
00296 (int) _cpp_trigraph_map[note->type]);
00297 else
00298 {
00299 cpp_error_with_line
00300 (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
00301 "trigraph ??%c ignored, use -trigraphs to enable",
00302 note->type);
00303 }
00304 }
00305 }
00306 else
00307 abort ();
00308 }
00309 }
00310
00311
00312
00313
00314
00315
00316 bool
00317 _cpp_skip_block_comment (cpp_reader *pfile)
00318 {
00319 cpp_buffer *buffer = pfile->buffer;
00320 const uchar *cur = buffer->cur;
00321 uchar c;
00322
00323 cur++;
00324 if (*cur == '/')
00325 cur++;
00326
00327 for (;;)
00328 {
00329
00330
00331 c = *cur++;
00332
00333 if (c == '/')
00334 {
00335 if (cur[-2] == '*')
00336 break;
00337
00338
00339
00340
00341 if (CPP_OPTION (pfile, warn_comments)
00342 && cur[0] == '*' && cur[1] != '/')
00343 {
00344 buffer->cur = cur;
00345 cpp_error_with_line (pfile, CPP_DL_WARNING,
00346 pfile->line_table->highest_line, CPP_BUF_COL (buffer),
00347 "\"/*\" within comment");
00348 }
00349 }
00350 else if (c == '\n')
00351 {
00352 unsigned int cols;
00353 buffer->cur = cur - 1;
00354 _cpp_process_line_notes (pfile, true);
00355 if (buffer->next_line >= buffer->rlimit)
00356 return true;
00357 _cpp_clean_line (pfile);
00358
00359 cols = buffer->next_line - buffer->line_base;
00360 CPP_INCREMENT_LINE (pfile, cols);
00361
00362 cur = buffer->cur;
00363 }
00364 }
00365
00366 buffer->cur = cur;
00367 _cpp_process_line_notes (pfile, true);
00368 return false;
00369 }
00370
00371
00372
00373
00374 static int
00375 skip_line_comment (cpp_reader *pfile)
00376 {
00377 cpp_buffer *buffer = pfile->buffer;
00378 unsigned int orig_line = pfile->line_table->highest_line;
00379
00380 while (*buffer->cur != '\n')
00381 buffer->cur++;
00382
00383 _cpp_process_line_notes (pfile, true);
00384 return orig_line != pfile->line_table->highest_line;
00385 }
00386
00387
00388 static void
00389 skip_whitespace (cpp_reader *pfile, cppchar_t c)
00390 {
00391 cpp_buffer *buffer = pfile->buffer;
00392 bool saw_NUL = false;
00393
00394 do
00395 {
00396
00397 if (c == ' ' || c == '\t')
00398 ;
00399
00400 else if (c == '\0')
00401 saw_NUL = true;
00402 else if (pfile->state.in_directive && CPP_PEDANTIC (pfile))
00403 cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->line_table->highest_line,
00404 CPP_BUF_COL (buffer),
00405 "%s in preprocessing directive",
00406 c == '\f' ? "form feed" : "vertical tab");
00407
00408 c = *buffer->cur++;
00409 }
00410
00411 while (is_nvspace (c));
00412
00413 if (saw_NUL)
00414 cpp_error (pfile, CPP_DL_WARNING, "null character(s) ignored");
00415
00416 buffer->cur--;
00417 }
00418
00419
00420
00421 static int
00422 name_p (cpp_reader *pfile, const cpp_string *string)
00423 {
00424 unsigned int i;
00425
00426 for (i = 0; i < string->len; i++)
00427 if (!is_idchar (string->text[i]))
00428 return 0;
00429
00430 return 1;
00431 }
00432
00433
00434
00435 static bool
00436 forms_identifier_p (cpp_reader *pfile, int first)
00437 {
00438 cpp_buffer *buffer = pfile->buffer;
00439
00440 if (*buffer->cur == '$')
00441 {
00442 if (!CPP_OPTION (pfile, dollars_in_ident))
00443 return false;
00444
00445 buffer->cur++;
00446 if (CPP_OPTION (pfile, warn_dollars) && !pfile->state.skipping)
00447 {
00448 CPP_OPTION (pfile, warn_dollars) = 0;
00449 cpp_error (pfile, CPP_DL_PEDWARN, "'$' in identifier or number");
00450 }
00451
00452 return true;
00453 }
00454
00455
00456 if (0 && *buffer->cur == '\\'
00457 && (buffer->cur[1] == 'u' || buffer->cur[1] == 'U'))
00458 {
00459 buffer->cur += 2;
00460 if (_cpp_valid_ucn (pfile, &buffer->cur, buffer->rlimit, 1 + !first))
00461 return true;
00462 buffer->cur -= 2;
00463 }
00464
00465 return false;
00466 }
00467
00468
00469 static cpp_hashnode *
00470 lex_identifier (cpp_reader *pfile, const uchar *base)
00471 {
00472 cpp_hashnode *result;
00473 const uchar *cur, *limit;
00474 unsigned int len;
00475 unsigned int hash = HT_HASHSTEP (0, *base);
00476
00477 cur = pfile->buffer->cur;
00478 for (;;)
00479 {
00480
00481 while (ISIDNUM (*cur))
00482 {
00483 hash = HT_HASHSTEP (hash, *cur);
00484 cur++;
00485 }
00486
00487 pfile->buffer->cur = cur;
00488 if (!forms_identifier_p (pfile, false))
00489 break;
00490
00491 limit = pfile->buffer->cur;
00492 while (cur < limit)
00493 {
00494 hash = HT_HASHSTEP (hash, *cur);
00495 cur++;
00496 }
00497 }
00498 len = cur - base;
00499 hash = HT_HASHFINISH (hash, len);
00500
00501 result = (cpp_hashnode *)
00502 ht_lookup_with_hash (pfile->hash_table, base, len, hash, HT_ALLOC);
00503
00504
00505 if (__builtin_expect ((result->flags & NODE_DIAGNOSTIC)
00506 && !pfile->state.skipping, 0))
00507 {
00508
00509 if ((result->flags & NODE_POISONED) && !pfile->state.poisoned_ok)
00510 cpp_error (pfile, CPP_DL_ERROR, "attempt to use poisoned \"%s\"",
00511 NODE_NAME (result));
00512
00513
00514
00515 if (result == pfile->spec_nodes.n__VA_ARGS__
00516 && !pfile->state.va_args_ok)
00517 cpp_error (pfile, CPP_DL_PEDWARN,
00518 "__VA_ARGS__ can only appear in the expansion"
00519 " of a C99 variadic macro");
00520 }
00521
00522 return result;
00523 }
00524
00525
00526 static void
00527 lex_number (cpp_reader *pfile, cpp_string *number)
00528 {
00529 const uchar *cur;
00530 const uchar *base;
00531 uchar *dest;
00532
00533 base = pfile->buffer->cur - 1;
00534 do
00535 {
00536 cur = pfile->buffer->cur;
00537
00538
00539 while (ISIDNUM (*cur) || *cur == '.' || VALID_SIGN (*cur, cur[-1]))
00540 cur++;
00541
00542 pfile->buffer->cur = cur;
00543 }
00544 while (forms_identifier_p (pfile, false));
00545
00546 number->len = cur - base;
00547 dest = _cpp_unaligned_alloc (pfile, number->len + 1);
00548 memcpy (dest, base, number->len);
00549 dest[number->len] = '\0';
00550 number->text = dest;
00551 }
00552
00553
00554 static void
00555 create_literal (cpp_reader *pfile, cpp_token *token, const uchar *base,
00556 unsigned int len, enum cpp_ttype type)
00557 {
00558 uchar *dest = _cpp_unaligned_alloc (pfile, len + 1);
00559
00560 memcpy (dest, base, len);
00561 dest[len] = '\0';
00562 token->type = type;
00563 token->val.str.len = len;
00564 token->val.str.text = dest;
00565 }
00566
00567
00568
00569
00570
00571
00572
00573
00574 static void
00575 lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
00576 {
00577 bool saw_NUL = false;
00578 const uchar *cur;
00579 cppchar_t terminator;
00580 enum cpp_ttype type;
00581
00582 cur = base;
00583 terminator = *cur++;
00584 if (terminator == 'L')
00585 terminator = *cur++;
00586 if (terminator == '\"')
00587 type = *base == 'L' ? CPP_WSTRING: CPP_STRING;
00588 else if (terminator == '\'')
00589 type = *base == 'L' ? CPP_WCHAR: CPP_CHAR;
00590 else
00591 terminator = '>', type = CPP_HEADER_NAME;
00592
00593 for (;;)
00594 {
00595 cppchar_t c = *cur++;
00596
00597
00598 if (c == '\\' && !pfile->state.angled_headers && *cur != '\n')
00599 cur++;
00600 else if (c == terminator)
00601 break;
00602 else if (c == '\n')
00603 {
00604 cur--;
00605 type = CPP_OTHER;
00606 break;
00607 }
00608 else if (c == '\0')
00609 saw_NUL = true;
00610 }
00611
00612 if (saw_NUL && !pfile->state.skipping)
00613 cpp_error (pfile, CPP_DL_WARNING,
00614 "null character(s) preserved in literal");
00615
00616 pfile->buffer->cur = cur;
00617 create_literal (pfile, token, base, cur - base, type);
00618 }
00619
00620
00621 static void
00622 save_comment (cpp_reader *pfile, cpp_token *token, const unsigned char *from,
00623 cppchar_t type)
00624 {
00625 unsigned char *buffer;
00626 unsigned int len, clen;
00627
00628 len = pfile->buffer->cur - from + 1;
00629
00630
00631
00632 if (is_vspace (pfile->buffer->cur[-1]))
00633 len--;
00634
00635
00636
00637
00638
00639
00640
00641 clen = (pfile->state.in_directive && type == '/') ? len + 2 : len;
00642
00643 buffer = _cpp_unaligned_alloc (pfile, clen);
00644
00645 token->type = CPP_COMMENT;
00646 token->val.str.len = clen;
00647 token->val.str.text = buffer;
00648
00649 buffer[0] = '/';
00650 memcpy (buffer + 1, from, len - 1);
00651
00652
00653 if (pfile->state.in_directive && type == '/')
00654 {
00655 buffer[1] = '*';
00656 buffer[clen - 2] = '*';
00657 buffer[clen - 1] = '/';
00658 }
00659 }
00660
00661
00662 void
00663 _cpp_init_tokenrun (tokenrun *run, unsigned int count)
00664 {
00665 run->base = XNEWVEC (cpp_token, count);
00666 run->limit = run->base + count;
00667 run->next = NULL;
00668 }
00669
00670
00671 static tokenrun *
00672 next_tokenrun (tokenrun *run)
00673 {
00674 if (run->next == NULL)
00675 {
00676 run->next = XNEW (tokenrun);
00677 run->next->prev = run;
00678 _cpp_init_tokenrun (run->next, 250);
00679 }
00680
00681 return run->next;
00682 }
00683
00684
00685
00686
00687
00688 cpp_token *
00689 _cpp_temp_token (cpp_reader *pfile)
00690 {
00691 cpp_token *old, *result;
00692
00693 old = pfile->cur_token - 1;
00694 if (pfile->cur_token == pfile->cur_run->limit)
00695 {
00696 pfile->cur_run = next_tokenrun (pfile->cur_run);
00697 pfile->cur_token = pfile->cur_run->base;
00698 }
00699
00700 result = pfile->cur_token++;
00701 result->src_loc = old->src_loc;
00702 return result;
00703 }
00704
00705
00706
00707
00708 const cpp_token *
00709 _cpp_lex_token (cpp_reader *pfile)
00710 {
00711 cpp_token *result;
00712
00713 for (;;)
00714 {
00715 if (pfile->cur_token == pfile->cur_run->limit)
00716 {
00717 pfile->cur_run = next_tokenrun (pfile->cur_run);
00718 pfile->cur_token = pfile->cur_run->base;
00719 }
00720
00721 if (pfile->lookaheads)
00722 {
00723 pfile->lookaheads--;
00724 result = pfile->cur_token++;
00725 }
00726 else
00727 result = _cpp_lex_direct (pfile);
00728
00729 if (result->flags & BOL)
00730 {
00731
00732
00733 if (result->type == CPP_HASH
00734
00735
00736
00737 && pfile->state.parsing_args != 1
00738 && _cpp_handle_directive (pfile, result->flags & PREV_WHITE))
00739 {
00740 if (pfile->directive_result.type == CPP_PADDING)
00741 continue;
00742 else
00743 {
00744 result = &pfile->directive_result;
00745 break;
00746 }
00747 }
00748
00749 if (pfile->cb.line_change && !pfile->state.skipping)
00750 pfile->cb.line_change (pfile, result, pfile->state.parsing_args);
00751 }
00752
00753
00754 if (pfile->state.in_directive)
00755 break;
00756
00757
00758
00759
00760 pfile->mi_valid = false;
00761
00762 if (!pfile->state.skipping || result->type == CPP_EOF)
00763 break;
00764 }
00765
00766 return result;
00767 }
00768
00769
00770 bool
00771 _cpp_get_fresh_line (cpp_reader *pfile)
00772 {
00773 int return_at_eof;
00774
00775
00776 if (pfile->state.in_directive)
00777 return false;
00778
00779 for (;;)
00780 {
00781 cpp_buffer *buffer = pfile->buffer;
00782
00783 if (!buffer->need_line)
00784 return true;
00785
00786 if (buffer->next_line < buffer->rlimit)
00787 {
00788 _cpp_clean_line (pfile);
00789 return true;
00790 }
00791
00792
00793 if (pfile->state.parsing_args)
00794 return false;
00795
00796
00797 if (buffer->buf != buffer->rlimit
00798 && buffer->next_line > buffer->rlimit
00799 && !buffer->from_stage3)
00800 {
00801
00802 buffer->next_line = buffer->rlimit;
00803 cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->line_table->highest_line,
00804 CPP_BUF_COLUMN (buffer, buffer->cur),
00805 "no newline at end of file");
00806 }
00807
00808 return_at_eof = buffer->return_at_eof;
00809 _cpp_pop_buffer (pfile);
00810 if (pfile->buffer == NULL || return_at_eof)
00811 return false;
00812 }
00813 }
00814
00815 #define IF_NEXT_IS(CHAR, THEN_TYPE, ELSE_TYPE) \
00816 do \
00817 { \
00818 result->type = ELSE_TYPE; \
00819 if (*buffer->cur == CHAR) \
00820 buffer->cur++, result->type = THEN_TYPE; \
00821 } \
00822 while (0)
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835 cpp_token *
00836 _cpp_lex_direct (cpp_reader *pfile)
00837 {
00838 cppchar_t c;
00839 cpp_buffer *buffer;
00840 const unsigned char *comment_start;
00841 cpp_token *result = pfile->cur_token++;
00842
00843 fresh_line:
00844 result->flags = 0;
00845 buffer = pfile->buffer;
00846 if (buffer->need_line)
00847 {
00848 if (!_cpp_get_fresh_line (pfile))
00849 {
00850 result->type = CPP_EOF;
00851 if (!pfile->state.in_directive)
00852 {
00853
00854 result->src_loc = pfile->line_table->highest_line;
00855 result->flags = BOL;
00856 }
00857 return result;
00858 }
00859 if (!pfile->keep_tokens)
00860 {
00861 pfile->cur_run = &pfile->base_run;
00862 result = pfile->base_run.base;
00863 pfile->cur_token = result + 1;
00864 }
00865 result->flags = BOL;
00866 if (pfile->state.parsing_args == 2)
00867 result->flags |= PREV_WHITE;
00868 }
00869 buffer = pfile->buffer;
00870 update_tokens_line:
00871 result->src_loc = pfile->line_table->highest_line;
00872
00873 skipped_white:
00874 if (buffer->cur >= buffer->notes[buffer->cur_note].pos
00875 && !pfile->overlaid_buffer)
00876 {
00877 _cpp_process_line_notes (pfile, false);
00878 result->src_loc = pfile->line_table->highest_line;
00879 }
00880 c = *buffer->cur++;
00881
00882 LINEMAP_POSITION_FOR_COLUMN (result->src_loc, pfile->line_table,
00883 CPP_BUF_COLUMN (buffer, buffer->cur));
00884
00885 switch (c)
00886 {
00887 case ' ': case '\t': case '\f': case '\v': case '\0':
00888 result->flags |= PREV_WHITE;
00889 skip_whitespace (pfile, c);
00890 goto skipped_white;
00891
00892 case '\n':
00893 if (buffer->cur < buffer->rlimit)
00894 CPP_INCREMENT_LINE (pfile, 0);
00895 buffer->need_line = true;
00896 goto fresh_line;
00897
00898 case '0': case '1': case '2': case '3': case '4':
00899 case '5': case '6': case '7': case '8': case '9':
00900 result->type = CPP_NUMBER;
00901 lex_number (pfile, &result->val.str);
00902 break;
00903
00904 case 'L':
00905
00906 if (*buffer->cur == '\'' || *buffer->cur == '"')
00907 {
00908 lex_string (pfile, result, buffer->cur - 1);
00909 break;
00910 }
00911
00912
00913 case '_':
00914 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
00915 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
00916 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
00917 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
00918 case 'y': case 'z':
00919 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
00920 case 'G': case 'H': case 'I': case 'J': case 'K':
00921 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
00922 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
00923 case 'Y': case 'Z':
00924 result->type = CPP_NAME;
00925 result->val.node = lex_identifier (pfile, buffer->cur - 1);
00926
00927
00928 if (result->val.node->flags & NODE_OPERATOR)
00929 {
00930 result->flags |= NAMED_OP;
00931 result->type = result->val.node->directive_index;
00932 }
00933 break;
00934
00935 case '\'':
00936 case '"':
00937 lex_string (pfile, result, buffer->cur - 1);
00938 break;
00939
00940 case '/':
00941
00942 comment_start = buffer->cur;
00943 c = *buffer->cur;
00944
00945 if (c == '*')
00946 {
00947 if (_cpp_skip_block_comment (pfile))
00948 cpp_error (pfile, CPP_DL_ERROR, "unterminated comment");
00949 }
00950 else if (c == '/' && (CPP_OPTION (pfile, cplusplus_comments)
00951 || cpp_in_system_header (pfile)))
00952 {
00953
00954
00955 if (CPP_OPTION (pfile, lang) == CLK_GNUC89 && CPP_PEDANTIC (pfile)
00956 && ! buffer->warned_cplusplus_comments)
00957 {
00958 cpp_error (pfile, CPP_DL_PEDWARN,
00959 "C++ style comments are not allowed in ISO C90");
00960 cpp_error (pfile, CPP_DL_PEDWARN,
00961 "(this will be reported only once per input file)");
00962 buffer->warned_cplusplus_comments = 1;
00963 }
00964
00965 if (skip_line_comment (pfile) && CPP_OPTION (pfile, warn_comments))
00966 cpp_error (pfile, CPP_DL_WARNING, "multi-line comment");
00967 }
00968 else if (c == '=')
00969 {
00970 buffer->cur++;
00971 result->type = CPP_DIV_EQ;
00972 break;
00973 }
00974 else
00975 {
00976 result->type = CPP_DIV;
00977 break;
00978 }
00979
00980 if (!pfile->state.save_comments)
00981 {
00982 result->flags |= PREV_WHITE;
00983 goto update_tokens_line;
00984 }
00985
00986
00987 save_comment (pfile, result, comment_start, c);
00988 break;
00989
00990 case '<':
00991 if (pfile->state.angled_headers)
00992 {
00993 lex_string (pfile, result, buffer->cur - 1);
00994 break;
00995 }
00996
00997 result->type = CPP_LESS;
00998 if (*buffer->cur == '=')
00999 buffer->cur++, result->type = CPP_LESS_EQ;
01000 else if (*buffer->cur == '<')
01001 {
01002 buffer->cur++;
01003 IF_NEXT_IS ('=', CPP_LSHIFT_EQ, CPP_LSHIFT);
01004 }
01005 else if (*buffer->cur == '?' && CPP_OPTION (pfile, cplusplus))
01006 {
01007 buffer->cur++;
01008 IF_NEXT_IS ('=', CPP_MIN_EQ, CPP_MIN);
01009 }
01010 else if (CPP_OPTION (pfile, digraphs))
01011 {
01012 if (*buffer->cur == ':')
01013 {
01014 buffer->cur++;
01015 result->flags |= DIGRAPH;
01016 result->type = CPP_OPEN_SQUARE;
01017 }
01018 else if (*buffer->cur == '%')
01019 {
01020 buffer->cur++;
01021 result->flags |= DIGRAPH;
01022 result->type = CPP_OPEN_BRACE;
01023 }
01024 }
01025 break;
01026
01027 case '>':
01028 result->type = CPP_GREATER;
01029 if (*buffer->cur == '=')
01030 buffer->cur++, result->type = CPP_GREATER_EQ;
01031 else if (*buffer->cur == '>')
01032 {
01033 buffer->cur++;
01034 IF_NEXT_IS ('=', CPP_RSHIFT_EQ, CPP_RSHIFT);
01035 }
01036 else if (*buffer->cur == '?' && CPP_OPTION (pfile, cplusplus))
01037 {
01038 buffer->cur++;
01039 IF_NEXT_IS ('=', CPP_MAX_EQ, CPP_MAX);
01040 }
01041 break;
01042
01043 case '%':
01044 result->type = CPP_MOD;
01045 if (*buffer->cur == '=')
01046 buffer->cur++, result->type = CPP_MOD_EQ;
01047 else if (CPP_OPTION (pfile, digraphs))
01048 {
01049 if (*buffer->cur == ':')
01050 {
01051 buffer->cur++;
01052 result->flags |= DIGRAPH;
01053 result->type = CPP_HASH;
01054 if (*buffer->cur == '%' && buffer->cur[1] == ':')
01055 buffer->cur += 2, result->type = CPP_PASTE;
01056 }
01057 else if (*buffer->cur == '>')
01058 {
01059 buffer->cur++;
01060 result->flags |= DIGRAPH;
01061 result->type = CPP_CLOSE_BRACE;
01062 }
01063 }
01064 break;
01065
01066 case '.':
01067 result->type = CPP_DOT;
01068 if (ISDIGIT (*buffer->cur))
01069 {
01070 result->type = CPP_NUMBER;
01071 lex_number (pfile, &result->val.str);
01072 }
01073 else if (*buffer->cur == '.' && buffer->cur[1] == '.')
01074 buffer->cur += 2, result->type = CPP_ELLIPSIS;
01075 else if (*buffer->cur == '*' && CPP_OPTION (pfile, cplusplus))
01076 buffer->cur++, result->type = CPP_DOT_STAR;
01077 break;
01078
01079 case '+':
01080 result->type = CPP_PLUS;
01081 if (*buffer->cur == '+')
01082 buffer->cur++, result->type = CPP_PLUS_PLUS;
01083 else if (*buffer->cur == '=')
01084 buffer->cur++, result->type = CPP_PLUS_EQ;
01085 break;
01086
01087 case '-':
01088 result->type = CPP_MINUS;
01089 if (*buffer->cur == '>')
01090 {
01091 buffer->cur++;
01092 result->type = CPP_DEREF;
01093 if (*buffer->cur == '*' && CPP_OPTION (pfile, cplusplus))
01094 buffer->cur++, result->type = CPP_DEREF_STAR;
01095 }
01096 else if (*buffer->cur == '-')
01097 buffer->cur++, result->type = CPP_MINUS_MINUS;
01098 else if (*buffer->cur == '=')
01099 buffer->cur++, result->type = CPP_MINUS_EQ;
01100 break;
01101
01102 case '&':
01103 result->type = CPP_AND;
01104 if (*buffer->cur == '&')
01105 buffer->cur++, result->type = CPP_AND_AND;
01106 else if (*buffer->cur == '=')
01107 buffer->cur++, result->type = CPP_AND_EQ;
01108 break;
01109
01110 case '|':
01111 result->type = CPP_OR;
01112 if (*buffer->cur == '|')
01113 buffer->cur++, result->type = CPP_OR_OR;
01114 else if (*buffer->cur == '=')
01115 buffer->cur++, result->type = CPP_OR_EQ;
01116 break;
01117
01118 case ':':
01119 result->type = CPP_COLON;
01120 if (*buffer->cur == ':' && CPP_OPTION (pfile, cplusplus))
01121 buffer->cur++, result->type = CPP_SCOPE;
01122 else if (*buffer->cur == '>' && CPP_OPTION (pfile, digraphs))
01123 {
01124 buffer->cur++;
01125 result->flags |= DIGRAPH;
01126 result->type = CPP_CLOSE_SQUARE;
01127 }
01128 break;
01129
01130 case '*': IF_NEXT_IS ('=', CPP_MULT_EQ, CPP_MULT); break;
01131 case '=': IF_NEXT_IS ('=', CPP_EQ_EQ, CPP_EQ); break;
01132 case '!': IF_NEXT_IS ('=', CPP_NOT_EQ, CPP_NOT); break;
01133 case '^': IF_NEXT_IS ('=', CPP_XOR_EQ, CPP_XOR); break;
01134 case '#': IF_NEXT_IS ('#', CPP_PASTE, CPP_HASH); break;
01135
01136 case '?': result->type = CPP_QUERY; break;
01137 case '~': result->type = CPP_COMPL; break;
01138 case ',': result->type = CPP_COMMA; break;
01139 case '(': result->type = CPP_OPEN_PAREN; break;
01140 case ')': result->type = CPP_CLOSE_PAREN; break;
01141 case '[': result->type = CPP_OPEN_SQUARE; break;
01142 case ']': result->type = CPP_CLOSE_SQUARE; break;
01143 case '{': result->type = CPP_OPEN_BRACE; break;
01144 case '}': result->type = CPP_CLOSE_BRACE; break;
01145 case ';': result->type = CPP_SEMICOLON; break;
01146
01147
01148 case '@': result->type = CPP_ATSIGN; break;
01149
01150 case '$':
01151 case '\\':
01152 {
01153 const uchar *base = --buffer->cur;
01154
01155 if (forms_identifier_p (pfile, true))
01156 {
01157 result->type = CPP_NAME;
01158 result->val.node = lex_identifier (pfile, base);
01159 break;
01160 }
01161 buffer->cur++;
01162 }
01163
01164 default:
01165 create_literal (pfile, result, buffer->cur - 1, 1, CPP_OTHER);
01166 break;
01167 }
01168
01169 return result;
01170 }
01171
01172
01173
01174 unsigned int
01175 cpp_token_len (const cpp_token *token)
01176 {
01177 unsigned int len;
01178
01179 switch (TOKEN_SPELL (token))
01180 {
01181 default: len = 4; break;
01182 case SPELL_LITERAL: len = token->val.str.len; break;
01183 case SPELL_IDENT: len = NODE_LEN (token->val.node); break;
01184 }
01185
01186 return len;
01187 }
01188
01189
01190
01191
01192
01193 unsigned char *
01194 cpp_spell_token (cpp_reader *pfile, const cpp_token *token,
01195 unsigned char *buffer)
01196 {
01197 switch (TOKEN_SPELL (token))
01198 {
01199 case SPELL_OPERATOR:
01200 {
01201 const unsigned char *spelling;
01202 unsigned char c;
01203
01204 if (token->flags & DIGRAPH)
01205 spelling
01206 = digraph_spellings[(int) token->type - (int) CPP_FIRST_DIGRAPH];
01207 else if (token->flags & NAMED_OP)
01208 goto spell_ident;
01209 else
01210 spelling = TOKEN_NAME (token);
01211
01212 while ((c = *spelling++) != '\0')
01213 *buffer++ = c;
01214 }
01215 break;
01216
01217 spell_ident:
01218 case SPELL_IDENT:
01219 memcpy (buffer, NODE_NAME (token->val.node), NODE_LEN (token->val.node));
01220 buffer += NODE_LEN (token->val.node);
01221 break;
01222
01223 case SPELL_LITERAL:
01224 memcpy (buffer, token->val.str.text, token->val.str.len);
01225 buffer += token->val.str.len;
01226 break;
01227
01228 case SPELL_NONE:
01229 cpp_error (pfile, CPP_DL_ICE,
01230 "unspellable token %s", TOKEN_NAME (token));
01231 break;
01232 }
01233
01234 return buffer;
01235 }
01236
01237
01238
01239 unsigned char *
01240 cpp_token_as_text (cpp_reader *pfile, const cpp_token *token)
01241 {
01242 unsigned int len = cpp_token_len (token) + 1;
01243 unsigned char *start = _cpp_unaligned_alloc (pfile, len), *end;
01244
01245 end = cpp_spell_token (pfile, token, start);
01246 end[0] = '\0';
01247
01248 return start;
01249 }
01250
01251
01252
01253 const char *
01254 cpp_type2name (enum cpp_ttype type)
01255 {
01256 return (const char *) token_spellings[type].name;
01257 }
01258
01259
01260
01261
01262 void
01263 cpp_output_token (const cpp_token *token, FILE *fp)
01264 {
01265 switch (TOKEN_SPELL (token))
01266 {
01267 case SPELL_OPERATOR:
01268 {
01269 const unsigned char *spelling;
01270 int c;
01271
01272 if (token->flags & DIGRAPH)
01273 spelling
01274 = digraph_spellings[(int) token->type - (int) CPP_FIRST_DIGRAPH];
01275 else if (token->flags & NAMED_OP)
01276 goto spell_ident;
01277 else
01278 spelling = TOKEN_NAME (token);
01279
01280 c = *spelling;
01281 do
01282 putc (c, fp);
01283 while ((c = *++spelling) != '\0');
01284 }
01285 break;
01286
01287 spell_ident:
01288 case SPELL_IDENT:
01289 fwrite (NODE_NAME (token->val.node), 1, NODE_LEN (token->val.node), fp);
01290 break;
01291
01292 case SPELL_LITERAL:
01293 fwrite (token->val.str.text, 1, token->val.str.len, fp);
01294 break;
01295
01296 case SPELL_NONE:
01297
01298 break;
01299 }
01300 }
01301
01302
01303 int
01304 _cpp_equiv_tokens (const cpp_token *a, const cpp_token *b)
01305 {
01306 if (a->type == b->type && a->flags == b->flags)
01307 switch (TOKEN_SPELL (a))
01308 {
01309 default:
01310 case SPELL_OPERATOR:
01311 return 1;
01312 case SPELL_NONE:
01313 return (a->type != CPP_MACRO_ARG || a->val.arg_no == b->val.arg_no);
01314 case SPELL_IDENT:
01315 return a->val.node == b->val.node;
01316 case SPELL_LITERAL:
01317 return (a->val.str.len == b->val.str.len
01318 && !memcmp (a->val.str.text, b->val.str.text,
01319 a->val.str.len));
01320 }
01321
01322 return 0;
01323 }
01324
01325
01326
01327
01328
01329 int
01330 cpp_avoid_paste (cpp_reader *pfile, const cpp_token *token1,
01331 const cpp_token *token2)
01332 {
01333 enum cpp_ttype a = token1->type, b = token2->type;
01334 cppchar_t c;
01335
01336 if (token1->flags & NAMED_OP)
01337 a = CPP_NAME;
01338 if (token2->flags & NAMED_OP)
01339 b = CPP_NAME;
01340
01341 c = EOF;
01342 if (token2->flags & DIGRAPH)
01343 c = digraph_spellings[(int) b - (int) CPP_FIRST_DIGRAPH][0];
01344 else if (token_spellings[b].category == SPELL_OPERATOR)
01345 c = token_spellings[b].name[0];
01346
01347
01348 if ((int) a <= (int) CPP_LAST_EQ && c == '=')
01349 return 1;
01350
01351 switch (a)
01352 {
01353 case CPP_GREATER: return c == '>' || c == '?';
01354 case CPP_LESS: return c == '<' || c == '?' || c == '%' || c == ':';
01355 case CPP_PLUS: return c == '+';
01356 case CPP_MINUS: return c == '-' || c == '>';
01357 case CPP_DIV: return c == '/' || c == '*';
01358 case CPP_MOD: return c == ':' || c == '>';
01359 case CPP_AND: return c == '&';
01360 case CPP_OR: return c == '|';
01361 case CPP_COLON: return c == ':' || c == '>';
01362 case CPP_DEREF: return c == '*';
01363 case CPP_DOT: return c == '.' || c == '%' || b == CPP_NUMBER;
01364 case CPP_HASH: return c == '#' || c == '%';
01365 case CPP_NAME: return ((b == CPP_NUMBER
01366 && name_p (pfile, &token2->val.str))
01367 || b == CPP_NAME
01368 || b == CPP_CHAR || b == CPP_STRING);
01369 case CPP_NUMBER: return (b == CPP_NUMBER || b == CPP_NAME
01370 || c == '.' || c == '+' || c == '-');
01371
01372 case CPP_OTHER: return ((token1->val.str.text[0] == '\\'
01373 && b == CPP_NAME)
01374 || (CPP_OPTION (pfile, objc)
01375 && token1->val.str.text[0] == '@'
01376 && (b == CPP_NAME || b == CPP_STRING)));
01377 default: break;
01378 }
01379
01380 return 0;
01381 }
01382
01383
01384
01385
01386 void
01387 cpp_output_line (cpp_reader *pfile, FILE *fp)
01388 {
01389 const cpp_token *token;
01390
01391 token = cpp_get_token (pfile);
01392 while (token->type != CPP_EOF)
01393 {
01394 cpp_output_token (token, fp);
01395 token = cpp_get_token (pfile);
01396 if (token->flags & PREV_WHITE)
01397 putc (' ', fp);
01398 }
01399
01400 putc ('\n', fp);
01401 }
01402
01403
01404
01405
01406
01407
01408
01409 #define MIN_BUFF_SIZE 8000
01410 #define BUFF_SIZE_UPPER_BOUND(MIN_SIZE) (MIN_BUFF_SIZE + (MIN_SIZE) * 3 / 2)
01411 #define EXTENDED_BUFF_SIZE(BUFF, MIN_EXTRA) \
01412 (MIN_EXTRA + ((BUFF)->limit - (BUFF)->cur) * 2)
01413
01414 #if MIN_BUFF_SIZE > BUFF_SIZE_UPPER_BOUND (0)
01415 #error BUFF_SIZE_UPPER_BOUND must be at least as large as MIN_BUFF_SIZE!
01416 #endif
01417
01418
01419
01420 static _cpp_buff *
01421 new_buff (size_t len)
01422 {
01423 _cpp_buff *result;
01424 unsigned char *base;
01425
01426 if (len < MIN_BUFF_SIZE)
01427 len = MIN_BUFF_SIZE;
01428 len = CPP_ALIGN (len);
01429
01430 base = xmalloc (len + sizeof (_cpp_buff));
01431 result = (_cpp_buff *) (base + len);
01432 result->base = base;
01433 result->cur = base;
01434 result->limit = base + len;
01435 result->next = NULL;
01436 return result;
01437 }
01438
01439
01440 void
01441 _cpp_release_buff (cpp_reader *pfile, _cpp_buff *buff)
01442 {
01443 _cpp_buff *end = buff;
01444
01445 while (end->next)
01446 end = end->next;
01447 end->next = pfile->free_buffs;
01448 pfile->free_buffs = buff;
01449 }
01450
01451
01452 _cpp_buff *
01453 _cpp_get_buff (cpp_reader *pfile, size_t min_size)
01454 {
01455 _cpp_buff *result, **p;
01456
01457 for (p = &pfile->free_buffs;; p = &(*p)->next)
01458 {
01459 size_t size;
01460
01461 if (*p == NULL)
01462 return new_buff (min_size);
01463 result = *p;
01464 size = result->limit - result->base;
01465
01466
01467 if (size >= min_size && size <= BUFF_SIZE_UPPER_BOUND (min_size))
01468 break;
01469 }
01470
01471 *p = result->next;
01472 result->next = NULL;
01473 result->cur = result->base;
01474 return result;
01475 }
01476
01477
01478
01479
01480
01481 _cpp_buff *
01482 _cpp_append_extend_buff (cpp_reader *pfile, _cpp_buff *buff, size_t min_extra)
01483 {
01484 size_t size = EXTENDED_BUFF_SIZE (buff, min_extra);
01485 _cpp_buff *new_buff = _cpp_get_buff (pfile, size);
01486
01487 buff->next = new_buff;
01488 memcpy (new_buff->base, buff->cur, BUFF_ROOM (buff));
01489 return new_buff;
01490 }
01491
01492
01493
01494
01495
01496
01497 void
01498 _cpp_extend_buff (cpp_reader *pfile, _cpp_buff **pbuff, size_t min_extra)
01499 {
01500 _cpp_buff *new_buff, *old_buff = *pbuff;
01501 size_t size = EXTENDED_BUFF_SIZE (old_buff, min_extra);
01502
01503 new_buff = _cpp_get_buff (pfile, size);
01504 memcpy (new_buff->base, old_buff->cur, BUFF_ROOM (old_buff));
01505 new_buff->next = old_buff;
01506 *pbuff = new_buff;
01507 }
01508
01509
01510 void
01511 _cpp_free_buff (_cpp_buff *buff)
01512 {
01513 _cpp_buff *next;
01514
01515 for (; buff; buff = next)
01516 {
01517 next = buff->next;
01518 free (buff->base);
01519 }
01520 }
01521
01522
01523 unsigned char *
01524 _cpp_unaligned_alloc (cpp_reader *pfile, size_t len)
01525 {
01526 _cpp_buff *buff = pfile->u_buff;
01527 unsigned char *result = buff->cur;
01528
01529 if (len > (size_t) (buff->limit - result))
01530 {
01531 buff = _cpp_get_buff (pfile, len);
01532 buff->next = pfile->u_buff;
01533 pfile->u_buff = buff;
01534 result = buff->cur;
01535 }
01536
01537 buff->cur = result + len;
01538 return result;
01539 }
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551 unsigned char *
01552 _cpp_aligned_alloc (cpp_reader *pfile, size_t len)
01553 {
01554 _cpp_buff *buff = pfile->a_buff;
01555 unsigned char *result = buff->cur;
01556
01557 if (len > (size_t) (buff->limit - result))
01558 {
01559 buff = _cpp_get_buff (pfile, len);
01560 buff->next = pfile->a_buff;
01561 pfile->a_buff = buff;
01562 result = buff->cur;
01563 }
01564
01565 buff->cur = result + len;
01566 return result;
01567 }
01568
01569
01570
01571 enum cpp_token_fld_kind
01572 cpp_token_val_index (cpp_token *tok)
01573 {
01574 switch (TOKEN_SPELL (tok))
01575 {
01576 case SPELL_IDENT:
01577 return CPP_TOKEN_FLD_NODE;
01578 case SPELL_LITERAL:
01579 return CPP_TOKEN_FLD_STR;
01580 case SPELL_NONE:
01581 if (tok->type == CPP_MACRO_ARG)
01582 return CPP_TOKEN_FLD_ARG_NO;
01583 else if (tok->type == CPP_PADDING)
01584 return CPP_TOKEN_FLD_SOURCE;
01585 else if (tok->type == CPP_PRAGMA)
01586 return CPP_TOKEN_FLD_STR;
01587
01588 default:
01589 return CPP_TOKEN_FLD_NONE;
01590 }
01591 }