00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "config.h"
00020 #include "system.h"
00021 #include "cpplib.h"
00022 #include "cpphash.h"
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 struct block
00034 {
00035 unsigned int text_len;
00036 unsigned short arg_index;
00037 uchar text[1];
00038 };
00039
00040 #define BLOCK_HEADER_LEN offsetof (struct block, text)
00041 #define BLOCK_LEN(TEXT_LEN) CPP_ALIGN (BLOCK_HEADER_LEN + (TEXT_LEN))
00042
00043
00044
00045 struct fun_macro
00046 {
00047
00048 _cpp_buff *buff;
00049
00050
00051
00052
00053
00054 size_t *args;
00055
00056
00057 cpp_hashnode *node;
00058
00059
00060 size_t offset;
00061
00062
00063 unsigned int line;
00064
00065
00066 unsigned int argc;
00067 };
00068
00069
00070 enum ls {ls_none = 0,
00071 ls_fun_open,
00072 ls_fun_close,
00073 ls_defined,
00074 ls_defined_close,
00075 ls_hash,
00076 ls_predicate,
00077 ls_answer};
00078
00079
00080
00081
00082 static const uchar *handle_newline PARAMS ((cpp_reader *, const uchar *));
00083 static const uchar *skip_escaped_newlines PARAMS ((cpp_reader *,
00084 const uchar *));
00085 static const uchar *skip_whitespace PARAMS ((cpp_reader *, const uchar *,
00086 int));
00087 static cpp_hashnode *lex_identifier PARAMS ((cpp_reader *, const uchar *));
00088 static const uchar *copy_comment PARAMS ((cpp_reader *, const uchar *, int));
00089 static void scan_out_logical_line PARAMS ((cpp_reader *pfile, cpp_macro *));
00090 static void check_output_buffer PARAMS ((cpp_reader *, size_t));
00091 static void push_replacement_text PARAMS ((cpp_reader *, cpp_hashnode *));
00092 static bool scan_parameters PARAMS ((cpp_reader *, cpp_macro *));
00093 static bool recursive_macro PARAMS ((cpp_reader *, cpp_hashnode *));
00094 static void save_replacement_text PARAMS ((cpp_reader *, cpp_macro *,
00095 unsigned int));
00096 static void maybe_start_funlike PARAMS ((cpp_reader *, cpp_hashnode *,
00097 const uchar *, struct fun_macro *));
00098 static void save_argument PARAMS ((struct fun_macro *, size_t));
00099 static void replace_args_and_push PARAMS ((cpp_reader *, struct fun_macro *));
00100 static size_t canonicalize_text PARAMS ((uchar *, const uchar *, size_t,
00101 uchar *));
00102
00103
00104
00105 static void
00106 check_output_buffer (pfile, n)
00107 cpp_reader *pfile;
00108 size_t n;
00109 {
00110
00111
00112 n += 2 + 1;
00113
00114 if (n > (size_t) (pfile->out.limit - pfile->out.cur))
00115 {
00116 size_t size = pfile->out.cur - pfile->out.base;
00117 size_t new_size = (size + n) * 3 / 2;
00118
00119 pfile->out.base
00120 = (uchar *) xrealloc (pfile->out.base, new_size);
00121 pfile->out.limit = pfile->out.base + new_size;
00122 pfile->out.cur = pfile->out.base + size;
00123 }
00124 }
00125
00126
00127
00128
00129
00130
00131 static const uchar *
00132 handle_newline (pfile, cur)
00133 cpp_reader *pfile;
00134 const uchar *cur;
00135 {
00136 pfile->line++;
00137 if (cur[0] + cur[1] == '\r' + '\n')
00138 cur++;
00139 return cur + 1;
00140 }
00141
00142
00143
00144
00145
00146
00147 static const uchar *
00148 skip_escaped_newlines (pfile, cur)
00149 cpp_reader *pfile;
00150 const uchar *cur;
00151 {
00152 const uchar *orig_cur = cur;
00153
00154 while (*cur == '\\' && is_vspace (cur[1]))
00155 cur = handle_newline (pfile, cur + 1);
00156
00157 if (cur != orig_cur && cur == RLIMIT (pfile->context) && pfile->buffer->inc)
00158 cpp_error (pfile, DL_PEDWARN, "backslash-newline at end of file");
00159
00160 return cur;
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 static const uchar *
00176 copy_comment (pfile, cur, in_define)
00177 cpp_reader *pfile;
00178 const uchar *cur;
00179 int in_define;
00180 {
00181 unsigned int from_line = pfile->line;
00182 const uchar *limit = RLIMIT (pfile->context);
00183 uchar *out = pfile->out.cur;
00184
00185 do
00186 {
00187 unsigned int c = *cur++;
00188 *out++ = c;
00189
00190 if (c == '/')
00191 {
00192
00193 if (out[-2] == '*' && out - 2 > pfile->out.cur)
00194 goto done;
00195
00196 if (*cur == '*' && cur[1] != '/'
00197 && CPP_OPTION (pfile, warn_comments))
00198 cpp_error_with_line (pfile, DL_WARNING, pfile->line, 0,
00199 "\"/*\" within comment");
00200 }
00201 else if (is_vspace (c))
00202 {
00203 cur = handle_newline (pfile, cur - 1);
00204
00205 if (out[-2] == '\\')
00206 out -= 2;
00207 else
00208 out[-1] = '\n';
00209 }
00210 }
00211 while (cur < limit);
00212
00213 cpp_error_with_line (pfile, DL_ERROR, from_line, 0, "unterminated comment");
00214 *out++ = '*';
00215 *out++ = '/';
00216
00217 done:
00218
00219
00220
00221 if (pfile->state.in_directive)
00222 {
00223 if (in_define)
00224 {
00225 if (CPP_OPTION (pfile, discard_comments_in_macro_exp))
00226 pfile->out.cur--;
00227 else
00228 pfile->out.cur = out;
00229 }
00230 else
00231 pfile->out.cur[-1] = ' ';
00232 }
00233 else if (CPP_OPTION (pfile, discard_comments))
00234 pfile->out.cur--;
00235 else
00236 pfile->out.cur = out;
00237
00238 return cur;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 static const uchar *
00254 skip_whitespace (pfile, cur, skip_comments)
00255 cpp_reader *pfile;
00256 const uchar *cur;
00257 int skip_comments;
00258 {
00259 uchar *out = pfile->out.cur;
00260
00261 for (;;)
00262 {
00263 unsigned int c = *cur++;
00264 *out++ = c;
00265
00266 if (is_nvspace (c) && c)
00267 continue;
00268
00269 if (!c && cur - 1 != RLIMIT (pfile->context))
00270 continue;
00271
00272 if (c == '/' && skip_comments)
00273 {
00274 const uchar *tmp = skip_escaped_newlines (pfile, cur);
00275 if (*tmp == '*')
00276 {
00277 pfile->out.cur = out;
00278 cur = copy_comment (pfile, tmp, false );
00279 out = pfile->out.cur;
00280 continue;
00281 }
00282 }
00283
00284 out--;
00285 if (c == '\\' && is_vspace (*cur))
00286 {
00287 cur = skip_escaped_newlines (pfile, cur - 1);
00288 continue;
00289 }
00290
00291 break;
00292 }
00293
00294 pfile->out.cur = out;
00295 return cur - 1;
00296 }
00297
00298
00299
00300
00301 static cpp_hashnode *
00302 lex_identifier (pfile, cur)
00303 cpp_reader *pfile;
00304 const uchar *cur;
00305 {
00306 size_t len;
00307 uchar *out = pfile->out.cur;
00308 cpp_hashnode *result;
00309
00310 do
00311 {
00312 do
00313 *out++ = *cur++;
00314 while (is_numchar (*cur));
00315 cur = skip_escaped_newlines (pfile, cur);
00316 }
00317 while (is_numchar (*cur));
00318
00319 CUR (pfile->context) = cur;
00320 len = out - pfile->out.cur;
00321 result = (cpp_hashnode *) ht_lookup (pfile->hash_table, pfile->out.cur,
00322 len, HT_ALLOC);
00323 pfile->out.cur = out;
00324 return result;
00325 }
00326
00327
00328
00329
00330 void
00331 _cpp_overlay_buffer (pfile, start, len)
00332 cpp_reader *pfile;
00333 const uchar *start;
00334 size_t len;
00335 {
00336 cpp_buffer *buffer = pfile->buffer;
00337
00338 pfile->overlaid_buffer = buffer;
00339 buffer->saved_cur = buffer->cur;
00340 buffer->saved_rlimit = buffer->rlimit;
00341
00342 buffer->cur = start;
00343 buffer->rlimit = start + len;
00344
00345 pfile->saved_line = pfile->line;
00346 }
00347
00348
00349 void
00350 _cpp_remove_overlay (pfile)
00351 cpp_reader *pfile;
00352 {
00353 cpp_buffer *buffer = pfile->overlaid_buffer;
00354
00355 buffer->cur = buffer->saved_cur;
00356 buffer->rlimit = buffer->saved_rlimit;
00357
00358 pfile->line = pfile->saved_line;
00359 }
00360
00361
00362
00363 bool
00364 _cpp_read_logical_line_trad (pfile)
00365 cpp_reader *pfile;
00366 {
00367 do
00368 {
00369 if (pfile->buffer->cur == pfile->buffer->rlimit)
00370 {
00371 bool stop = true;
00372
00373
00374 if (pfile->buffer->prev)
00375 {
00376 stop = pfile->buffer->return_at_eof;
00377 _cpp_pop_buffer (pfile);
00378 }
00379
00380 if (stop)
00381 return false;
00382 }
00383
00384 scan_out_logical_line (pfile, NULL);
00385 }
00386 while (pfile->state.skipping);
00387
00388 return true;
00389 }
00390
00391
00392
00393 static void
00394 maybe_start_funlike (pfile, node, start, macro)
00395 cpp_reader *pfile;
00396 cpp_hashnode *node;
00397 const uchar *start;
00398 struct fun_macro *macro;
00399 {
00400 unsigned int n = node->value.macro->paramc + 1;
00401
00402 if (macro->buff)
00403 _cpp_release_buff (pfile, macro->buff);
00404 macro->buff = _cpp_get_buff (pfile, n * sizeof (size_t));
00405 macro->args = (size_t *) BUFF_FRONT (macro->buff);
00406 macro->node = node;
00407 macro->offset = start - pfile->out.base;
00408 macro->argc = 0;
00409 }
00410
00411
00412 static void
00413 save_argument (macro, offset)
00414 struct fun_macro *macro;
00415 size_t offset;
00416 {
00417 macro->argc++;
00418 if (macro->argc <= macro->node->value.macro->paramc)
00419 macro->args[macro->argc] = offset;
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429 static void
00430 scan_out_logical_line (pfile, macro)
00431 cpp_reader *pfile;
00432 cpp_macro *macro;
00433 {
00434 cpp_context *context;
00435 const uchar *cur;
00436 uchar *out;
00437 struct fun_macro fmacro;
00438 unsigned int c, paren_depth = 0, quote;
00439 enum ls lex_state = ls_none;
00440 bool header_ok;
00441
00442 fmacro.buff = NULL;
00443
00444 start_logical_line:
00445 quote = 0;
00446 header_ok = pfile->state.angled_headers;
00447 CUR (pfile->context) = pfile->buffer->cur;
00448 RLIMIT (pfile->context) = pfile->buffer->rlimit;
00449 pfile->out.cur = pfile->out.base;
00450 pfile->out.first_line = pfile->line;
00451 new_context:
00452 context = pfile->context;
00453 cur = CUR (context);
00454 check_output_buffer (pfile, RLIMIT (context) - cur);
00455 out = pfile->out.cur;
00456
00457 for (;;)
00458 {
00459 c = *cur++;
00460 *out++ = c;
00461
00462
00463
00464 switch (c)
00465 {
00466 case ' ':
00467 case '\t':
00468 case '\f':
00469 case '\v':
00470 continue;
00471
00472 case '\0':
00473 if (cur - 1 != RLIMIT (context))
00474 continue;
00475
00476
00477 if (context->prev)
00478 {
00479 pfile->out.cur = out - 1;
00480 _cpp_pop_context (pfile);
00481 goto new_context;
00482 }
00483
00484
00485 cur--;
00486 if (!pfile->buffer->from_stage3)
00487 cpp_error (pfile, DL_PEDWARN, "no newline at end of file");
00488 pfile->line++;
00489 goto done;
00490
00491 case '\r': case '\n':
00492 cur = handle_newline (pfile, cur - 1);
00493 if ((lex_state == ls_fun_open || lex_state == ls_fun_close)
00494 && !pfile->state.in_directive)
00495 {
00496
00497
00498 if (lex_state == ls_fun_close)
00499 out[-1] = ' ';
00500 continue;
00501 }
00502 goto done;
00503
00504 case '<':
00505 if (header_ok)
00506 quote = '>';
00507 break;
00508 case '>':
00509 if (c == quote)
00510 quote = 0;
00511 break;
00512
00513 case '"':
00514 case '\'':
00515 if (c == quote)
00516 quote = 0;
00517 else if (!quote)
00518 quote = c;
00519 break;
00520
00521 case '\\':
00522 if (is_vspace (*cur))
00523 {
00524 out--;
00525 cur = skip_escaped_newlines (pfile, cur - 1);
00526 continue;
00527 }
00528 else
00529 {
00530
00531
00532 cur = skip_escaped_newlines (pfile, cur);
00533 if (*cur == '\\' || *cur == '"' || *cur == '\'')
00534 *out++ = *cur++;
00535 }
00536 break;
00537
00538 case '/':
00539
00540
00541 if (!quote)
00542 {
00543 cur = skip_escaped_newlines (pfile, cur);
00544 if (*cur == '*')
00545 {
00546 pfile->out.cur = out;
00547 cur = copy_comment (pfile, cur, macro != 0);
00548 out = pfile->out.cur;
00549 continue;
00550 }
00551 }
00552 break;
00553
00554 case '_':
00555 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
00556 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
00557 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
00558 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
00559 case 'y': case 'z':
00560 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
00561 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
00562 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
00563 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
00564 case 'Y': case 'Z':
00565 if (!pfile->state.skipping && (quote == 0 || macro))
00566 {
00567 cpp_hashnode *node;
00568 uchar *out_start = out - 1;
00569
00570 pfile->out.cur = out_start;
00571 node = lex_identifier (pfile, cur - 1);
00572 out = pfile->out.cur;
00573 cur = CUR (context);
00574
00575 if (node->type == NT_MACRO
00576
00577 && (lex_state == ls_none || lex_state == ls_fun_open)
00578 && !pfile->state.prevent_expansion)
00579 {
00580
00581 pfile->mi_valid = false;
00582 if (! (node->flags & NODE_BUILTIN)
00583 && node->value.macro->fun_like)
00584 {
00585 maybe_start_funlike (pfile, node, out_start, &fmacro);
00586 lex_state = ls_fun_open;
00587 fmacro.line = pfile->line;
00588 continue;
00589 }
00590 else if (!recursive_macro (pfile, node))
00591 {
00592
00593
00594 pfile->out.cur = out_start;
00595 push_replacement_text (pfile, node);
00596 lex_state = ls_none;
00597 goto new_context;
00598 }
00599 }
00600 else if (macro && node->arg_index)
00601 {
00602
00603
00604 pfile->out.cur = out_start;
00605 save_replacement_text (pfile, macro, node->arg_index);
00606 out = pfile->out.base;
00607 }
00608 else if (lex_state == ls_hash)
00609 {
00610 lex_state = ls_predicate;
00611 continue;
00612 }
00613 else if (pfile->state.in_expression
00614 && node == pfile->spec_nodes.n_defined)
00615 {
00616 lex_state = ls_defined;
00617 continue;
00618 }
00619 }
00620 break;
00621
00622 case '(':
00623 if (quote == 0)
00624 {
00625 paren_depth++;
00626 if (lex_state == ls_fun_open)
00627 {
00628 if (recursive_macro (pfile, fmacro.node))
00629 lex_state = ls_none;
00630 else
00631 {
00632 lex_state = ls_fun_close;
00633 paren_depth = 1;
00634 out = pfile->out.base + fmacro.offset;
00635 fmacro.args[0] = fmacro.offset;
00636 }
00637 }
00638 else if (lex_state == ls_predicate)
00639 lex_state = ls_answer;
00640 else if (lex_state == ls_defined)
00641 lex_state = ls_defined_close;
00642 }
00643 break;
00644
00645 case ',':
00646 if (quote == 0 && lex_state == ls_fun_close && paren_depth == 1)
00647 save_argument (&fmacro, out - pfile->out.base);
00648 break;
00649
00650 case ')':
00651 if (quote == 0)
00652 {
00653 paren_depth--;
00654 if (lex_state == ls_fun_close && paren_depth == 0)
00655 {
00656 cpp_macro *m = fmacro.node->value.macro;
00657
00658 m->used = 1;
00659 lex_state = ls_none;
00660 save_argument (&fmacro, out - pfile->out.base);
00661
00662
00663 if (fmacro.argc == 1
00664 && m->paramc == 0
00665 && out == pfile->out.base + fmacro.offset + 1)
00666 fmacro.argc = 0;
00667
00668 if (_cpp_arguments_ok (pfile, m, fmacro.node, fmacro.argc))
00669 {
00670
00671
00672 pfile->out.cur = (pfile->out.base
00673 + fmacro.offset);
00674 CUR (context) = cur;
00675 replace_args_and_push (pfile, &fmacro);
00676 goto new_context;
00677 }
00678 }
00679 else if (lex_state == ls_answer || lex_state == ls_defined_close)
00680 lex_state = ls_none;
00681 }
00682 break;
00683
00684 case '#':
00685 if (out - 1 == pfile->out.base
00686
00687 && !pfile->context->prev
00688 && !pfile->state.in_directive)
00689 {
00690
00691
00692
00693
00694
00695
00696 pfile->out.cur = out;
00697 cur = skip_whitespace (pfile, cur, true );
00698 out = pfile->out.cur;
00699
00700 if (is_vspace (*cur))
00701 {
00702
00703
00704 out = pfile->out.base;
00705 continue;
00706 }
00707 else
00708 {
00709 bool do_it = false;
00710
00711 if (is_numstart (*cur)
00712 && CPP_OPTION (pfile, lang) != CLK_ASM)
00713 do_it = true;
00714 else if (is_idstart (*cur))
00715
00716
00717 do_it = lex_identifier (pfile, cur)->directive_index != 0;
00718
00719 if (do_it || CPP_OPTION (pfile, lang) != CLK_ASM)
00720 {
00721
00722
00723 pfile->buffer->cur = cur;
00724 _cpp_handle_directive (pfile, false );
00725
00726
00727 goto start_logical_line;
00728 }
00729 }
00730 }
00731
00732 if (pfile->state.in_expression)
00733 {
00734 lex_state = ls_hash;
00735 continue;
00736 }
00737 break;
00738
00739 default:
00740 break;
00741 }
00742
00743
00744
00745 header_ok = false;
00746 if (!pfile->state.in_directive)
00747 pfile->mi_valid = false;
00748
00749 if (lex_state == ls_none)
00750 continue;
00751
00752
00753
00754 if (lex_state == ls_fun_open)
00755
00756 lex_state = ls_none;
00757 else if (lex_state == ls_hash
00758 || lex_state == ls_predicate
00759 || lex_state == ls_defined)
00760 lex_state = ls_none;
00761
00762
00763 }
00764
00765 done:
00766 out[-1] = '\0';
00767 pfile->buffer->cur = cur;
00768 pfile->out.cur = out - 1;
00769 if (fmacro.buff)
00770 _cpp_release_buff (pfile, fmacro.buff);
00771
00772 if (lex_state == ls_fun_close)
00773 cpp_error_with_line (pfile, DL_ERROR, fmacro.line, 0,
00774 "unterminated argument list invoking macro \"%s\"",
00775 NODE_NAME (fmacro.node));
00776 }
00777
00778
00779
00780
00781 static void
00782 push_replacement_text (pfile, node)
00783 cpp_reader *pfile;
00784 cpp_hashnode *node;
00785 {
00786 size_t len;
00787 const uchar *text;
00788
00789 if (node->flags & NODE_BUILTIN)
00790 {
00791 text = _cpp_builtin_macro_text (pfile, node);
00792 len = ustrlen (text);
00793 }
00794 else
00795 {
00796 cpp_macro *macro = node->value.macro;
00797 macro->used = 1;
00798 text = macro->exp.text;
00799 len = macro->count;
00800 }
00801
00802 _cpp_push_text_context (pfile, node, text, len);
00803 }
00804
00805
00806 static bool
00807 recursive_macro (pfile, node)
00808 cpp_reader *pfile;
00809 cpp_hashnode *node;
00810 {
00811 bool recursing = !!(node->flags & NODE_DISABLED);
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 if (recursing && node->value.macro->fun_like)
00824 {
00825 size_t depth = 0;
00826 cpp_context *context = pfile->context;
00827
00828 do
00829 {
00830 depth++;
00831 if (context->macro == node && depth > 20)
00832 break;
00833 context = context->prev;
00834 }
00835 while (context);
00836 recursing = context != NULL;
00837 }
00838
00839 if (recursing)
00840 cpp_error (pfile, DL_ERROR,
00841 "detected recursion whilst expanding macro \"%s\"",
00842 NODE_NAME (node));
00843
00844 return recursing;
00845 }
00846
00847
00848
00849 size_t
00850 _cpp_replacement_text_len (macro)
00851 const cpp_macro *macro;
00852 {
00853 size_t len;
00854
00855 if (macro->fun_like && (macro->paramc != 0))
00856 {
00857 const uchar *exp;
00858
00859 len = 0;
00860 for (exp = macro->exp.text;;)
00861 {
00862 struct block *b = (struct block *) exp;
00863
00864 len += b->text_len;
00865 if (b->arg_index == 0)
00866 break;
00867 len += NODE_LEN (macro->params[b->arg_index - 1]);
00868 exp += BLOCK_LEN (b->text_len);
00869 }
00870 }
00871 else
00872 len = macro->count;
00873
00874 return len;
00875 }
00876
00877
00878
00879
00880 uchar *
00881 _cpp_copy_replacement_text (macro, dest)
00882 const cpp_macro *macro;
00883 uchar *dest;
00884 {
00885 if (macro->fun_like && (macro->paramc != 0))
00886 {
00887 const uchar *exp;
00888
00889 for (exp = macro->exp.text;;)
00890 {
00891 struct block *b = (struct block *) exp;
00892 cpp_hashnode *param;
00893
00894 memcpy (dest, b->text, b->text_len);
00895 dest += b->text_len;
00896 if (b->arg_index == 0)
00897 break;
00898 param = macro->params[b->arg_index - 1];
00899 memcpy (dest, NODE_NAME (param), NODE_LEN (param));
00900 dest += NODE_LEN (param);
00901 exp += BLOCK_LEN (b->text_len);
00902 }
00903 }
00904 else
00905 {
00906 memcpy (dest, macro->exp.text, macro->count);
00907 dest += macro->count;
00908 }
00909
00910 return dest;
00911 }
00912
00913
00914
00915
00916 static void
00917 replace_args_and_push (pfile, fmacro)
00918 cpp_reader *pfile;
00919 struct fun_macro *fmacro;
00920 {
00921 cpp_macro *macro = fmacro->node->value.macro;
00922
00923 if (macro->paramc == 0)
00924 push_replacement_text (pfile, fmacro->node);
00925 else
00926 {
00927 const uchar *exp;
00928 uchar *p;
00929 _cpp_buff *buff;
00930 size_t len = 0;
00931
00932
00933 for (exp = macro->exp.text;;)
00934 {
00935 struct block *b = (struct block *) exp;
00936
00937 len += b->text_len;
00938 if (b->arg_index == 0)
00939 break;
00940 len += (fmacro->args[b->arg_index]
00941 - fmacro->args[b->arg_index - 1] - 1);
00942 exp += BLOCK_LEN (b->text_len);
00943 }
00944
00945
00946 buff = _cpp_get_buff (pfile, len + 1);
00947
00948
00949 p = BUFF_FRONT (buff);
00950 for (exp = macro->exp.text;;)
00951 {
00952 struct block *b = (struct block *) exp;
00953 size_t arglen;
00954
00955 memcpy (p, b->text, b->text_len);
00956 p += b->text_len;
00957 if (b->arg_index == 0)
00958 break;
00959 arglen = (fmacro->args[b->arg_index]
00960 - fmacro->args[b->arg_index - 1] - 1);
00961 memcpy (p, pfile->out.base + fmacro->args[b->arg_index - 1],
00962 arglen);
00963 p += arglen;
00964 exp += BLOCK_LEN (b->text_len);
00965 }
00966
00967
00968 *p = '\0';
00969 _cpp_push_text_context (pfile, fmacro->node, BUFF_FRONT (buff), len);
00970
00971
00972 pfile->context->buff = buff;
00973 }
00974 }
00975
00976
00977
00978
00979
00980
00981
00982 static bool
00983 scan_parameters (pfile, macro)
00984 cpp_reader *pfile;
00985 cpp_macro *macro;
00986 {
00987 const uchar *cur = CUR (pfile->context) + 1;
00988 bool ok;
00989
00990 for (;;)
00991 {
00992 cur = skip_whitespace (pfile, cur, true );
00993
00994 if (is_idstart (*cur))
00995 {
00996 ok = false;
00997 if (_cpp_save_parameter (pfile, macro, lex_identifier (pfile, cur)))
00998 break;
00999 cur = skip_whitespace (pfile, CUR (pfile->context),
01000 true );
01001 if (*cur == ',')
01002 {
01003 cur++;
01004 continue;
01005 }
01006 ok = (*cur == ')');
01007 break;
01008 }
01009
01010 ok = (*cur == ')' && macro->paramc == 0);
01011 break;
01012 }
01013
01014 CUR (pfile->context) = cur + (*cur == ')');
01015
01016 return ok;
01017 }
01018
01019
01020
01021
01022
01023 static void
01024 save_replacement_text (pfile, macro, arg_index)
01025 cpp_reader *pfile;
01026 cpp_macro *macro;
01027 unsigned int arg_index;
01028 {
01029 size_t len = pfile->out.cur - pfile->out.base;
01030 uchar *exp;
01031
01032 if (macro->paramc == 0)
01033 {
01034
01035
01036 exp = _cpp_unaligned_alloc (pfile, len + 1);
01037 memcpy (exp, pfile->out.base, len);
01038 exp[len] = '\0';
01039 macro->exp.text = exp;
01040 macro->count = len;
01041 }
01042 else
01043 {
01044
01045
01046 size_t blen = BLOCK_LEN (len);
01047 struct block *block;
01048
01049 if (macro->count + blen > BUFF_ROOM (pfile->a_buff))
01050 _cpp_extend_buff (pfile, &pfile->a_buff, macro->count + blen);
01051
01052 exp = BUFF_FRONT (pfile->a_buff);
01053 block = (struct block *) (exp + macro->count);
01054 macro->exp.text = exp;
01055
01056
01057 block->text_len = len;
01058 block->arg_index = arg_index;
01059 memcpy (block->text, pfile->out.base, len);
01060
01061
01062 pfile->out.cur = pfile->out.base;
01063
01064 macro->count += blen;
01065
01066
01067 if (arg_index == 0)
01068 BUFF_FRONT (pfile->a_buff) += macro->count;
01069 }
01070 }
01071
01072
01073
01074 bool
01075 _cpp_create_trad_definition (pfile, macro)
01076 cpp_reader *pfile;
01077 cpp_macro *macro;
01078 {
01079 const uchar *cur;
01080 uchar *limit;
01081 cpp_context *context = pfile->context;
01082
01083
01084
01085 pfile->out.cur = pfile->out.base;
01086 CUR (context) = pfile->buffer->cur;
01087 RLIMIT (context) = pfile->buffer->rlimit;
01088 check_output_buffer (pfile, RLIMIT (context) - CUR (context));
01089
01090
01091 if (* CUR (context) == '(')
01092 {
01093
01094
01095 if (!scan_parameters (pfile, macro))
01096 macro = NULL;
01097 else
01098 {
01099
01100 macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
01101 BUFF_FRONT (pfile->a_buff) = (uchar *) ¯o->params[macro->paramc];
01102 macro->fun_like = 1;
01103 }
01104 }
01105
01106
01107 pfile->buffer->cur
01108 = skip_whitespace (pfile, CUR (context),
01109 CPP_OPTION (pfile, discard_comments_in_macro_exp));
01110
01111 pfile->state.prevent_expansion++;
01112 scan_out_logical_line (pfile, macro);
01113 pfile->state.prevent_expansion--;
01114
01115 if (!macro)
01116 return false;
01117
01118
01119 cur = pfile->out.base;
01120 limit = pfile->out.cur;
01121 while (limit > cur && is_space (limit[-1]))
01122 limit--;
01123 pfile->out.cur = limit;
01124 save_replacement_text (pfile, macro, 0);
01125
01126 return true;
01127 }
01128
01129
01130
01131
01132
01133 static size_t
01134 canonicalize_text (dest, src, len, pquote)
01135 uchar *dest;
01136 const uchar *src;
01137 size_t len;
01138 uchar *pquote;
01139 {
01140 uchar *orig_dest = dest;
01141 uchar quote = *pquote;
01142
01143 while (len)
01144 {
01145 if (is_space (*src) && !quote)
01146 {
01147 do
01148 src++, len--;
01149 while (len && is_space (*src));
01150 *dest++ = ' ';
01151 }
01152 else
01153 {
01154 if (*src == '\'' || *src == '"')
01155 {
01156 if (!quote)
01157 quote = *src;
01158 else if (quote == *src)
01159 quote = 0;
01160 }
01161 *dest++ = *src++, len--;
01162 }
01163 }
01164
01165 *pquote = quote;
01166 return dest - orig_dest;
01167 }
01168
01169
01170
01171 bool
01172 _cpp_expansions_different_trad (macro1, macro2)
01173 const cpp_macro *macro1, *macro2;
01174 {
01175 uchar *p1 = xmalloc (macro1->count + macro2->count);
01176 uchar *p2 = p1 + macro1->count;
01177 uchar quote1 = 0, quote2 = 0;
01178 bool mismatch;
01179 size_t len1, len2;
01180
01181 if (macro1->paramc > 0)
01182 {
01183 const uchar *exp1 = macro1->exp.text, *exp2 = macro2->exp.text;
01184
01185 mismatch = true;
01186 for (;;)
01187 {
01188 struct block *b1 = (struct block *) exp1;
01189 struct block *b2 = (struct block *) exp2;
01190
01191 if (b1->arg_index != b2->arg_index)
01192 break;
01193
01194 len1 = canonicalize_text (p1, b1->text, b1->text_len, "e1);
01195 len2 = canonicalize_text (p2, b2->text, b2->text_len, "e2);
01196 if (len1 != len2 || memcmp (p1, p2, len1))
01197 break;
01198 if (b1->arg_index == 0)
01199 {
01200 mismatch = false;
01201 break;
01202 }
01203 exp1 += BLOCK_LEN (b1->text_len);
01204 exp2 += BLOCK_LEN (b2->text_len);
01205 }
01206 }
01207 else
01208 {
01209 len1 = canonicalize_text (p1, macro1->exp.text, macro1->count, "e1);
01210 len2 = canonicalize_text (p2, macro2->exp.text, macro2->count, "e2);
01211 mismatch = (len1 != len2 || memcmp (p1, p2, len1));
01212 }
01213
01214 free (p1);
01215 return mismatch;
01216 }