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