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