OSDN Git Service

* cpphash.h (struct cpp_macro): Put comments on their own lines.
[pf3gnuchains/gcc-fork.git] / gcc / cpptrad.c
1 /* CPP Library - traditional lexical analysis and macro expansion.
2    Copyright (C) 2002 Free Software Foundation, Inc.
3    Contributed by Neil Booth, May 2002
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18
19 #include "config.h"
20 #include "system.h"
21 #include "cpplib.h"
22 #include "cpphash.h"
23
24 /* The replacement text of a function-like macro is stored as a
25    contiguous sequence of aligned blocks.  Each block represents the
26    portion of text from the start of the previous block (or the start
27    of the macro replacement text in the case of the first block) to
28    the next parameter, or the end of the replacement list if there
29    are none left.
30
31    Each block consists of an unsigned int, which is the length of text
32    contained in the third part, an unsigned short, which is the
33    one-based index of the argument that immediately follows that text,
34    and the text itself.  The final block in the macro expansion is
35    recognizable as it has an argument index of zero.  */
36
37 struct block
38 {
39   unsigned int text_len;
40   unsigned short arg_index;
41   uchar text[1];
42 };
43
44 #define BLOCK_HEADER_LEN offsetof (struct block, text)
45 #define BLOCK_LEN(TEXT_LEN) CPP_ALIGN (BLOCK_HEADER_LEN + TEXT_LEN)
46
47 /* Structure holding information about a function-like macro
48    invocation.  */
49 struct fun_macro
50 {
51   /* Memory buffer holding the trad_arg array.  */
52   _cpp_buff *buff;
53
54   /* An array of size the number of macro parameters + 1, containing
55      the offsets of the start of each macro argument in the output
56      buffer.  The argument continues until the character before the
57      start of the next one.  */
58   size_t *args;
59
60   /* The hashnode of the macro.  */
61   cpp_hashnode *node;
62
63   /* The offset of the macro name in the output buffer.  */
64   size_t offset;
65
66   /* Zero-based index of argument being currently lexed.  */
67   unsigned int argc;
68 };
69
70 /* Lexing TODO: Handle -C, maybe -CC, and space in escaped newlines.
71    Stop cpplex.c from recognizing comments and directives during its
72    lexing pass.  Get rid of line_base usage - seems pointless?  Do we
73    get escaped newline at EOF correct?  */
74
75 static const uchar *handle_newline PARAMS ((cpp_reader *, const uchar *));
76 static const uchar *skip_escaped_newlines PARAMS ((cpp_reader *,
77                                                    const uchar *));
78 static const uchar *skip_whitespace PARAMS ((cpp_reader *, const uchar *));
79 static cpp_hashnode *lex_identifier PARAMS ((cpp_reader *, const uchar *));
80 static const uchar *skip_comment PARAMS ((cpp_reader *, const uchar *));
81 static void scan_out_logical_line PARAMS ((cpp_reader *pfile, cpp_macro *));
82 static void check_output_buffer PARAMS ((cpp_reader *, size_t));
83 static void restore_buff PARAMS ((cpp_reader *));
84 static void push_replacement_text PARAMS ((cpp_reader *, cpp_hashnode *));
85 static bool scan_parameters PARAMS ((cpp_reader *, cpp_macro *));
86 static void save_replacement_text PARAMS ((cpp_reader *, cpp_macro *,
87                                            unsigned int));
88 static void maybe_start_funlike PARAMS ((cpp_reader *, cpp_hashnode *,
89                                          const uchar *, struct fun_macro *));
90 static void save_argument PARAMS ((struct fun_macro *, size_t));
91 static void replace_args_and_push PARAMS ((cpp_reader *, struct fun_macro *));
92 static size_t canonicalize_text PARAMS ((uchar *, const uchar *, size_t,
93                                          uchar *));
94
95 /* Ensures we have N bytes' space in the output buffer, and
96    reallocates it if not.  */
97 static void
98 check_output_buffer (pfile, n)
99      cpp_reader *pfile;
100      size_t n;
101 {
102   if (n > (size_t) (pfile->trad_out_limit - pfile->trad_out_cur))
103     {
104       size_t size = pfile->trad_out_cur - pfile->trad_out_base;
105       size_t new_size = (size + n) * 3 / 2;
106
107       pfile->trad_out_base
108         = (uchar *) xrealloc (pfile->trad_out_base, new_size);
109       pfile->trad_out_limit = pfile->trad_out_base + new_size;
110       pfile->trad_out_cur = pfile->trad_out_base + size;
111     }
112 }
113
114 /* To be called whenever a newline character is encountered in the
115    input file, at CUR.  Handles DOS, MAC and Unix ends of line, and
116    returns the character after the newline sequence.  */
117 static const uchar *
118 handle_newline (pfile, cur)
119      cpp_reader *pfile;
120      const uchar *cur;
121 {
122   pfile->line++;
123   if (cur[0] + cur[1] == '\r' + '\n')
124     cur++;
125   pfile->buffer->line_base = cur + 1;
126   return cur + 1;
127 }
128
129 /* CUR points to any character in the buffer, not necessarily a
130    backslash.  Advances CUR until all escaped newlines are skipped,
131    and returns the new position.  */
132 static const uchar *
133 skip_escaped_newlines (pfile, cur)
134      cpp_reader *pfile;
135      const uchar *cur;
136 {
137   while (*cur == '\\' && is_vspace (cur[1]))
138     cur = handle_newline (pfile, cur + 1);
139
140   return cur;
141 }
142
143 /* CUR points to the character after the asterisk introducing a
144    comment.  Returns the position after the comment.  */
145 static const uchar *
146 skip_comment (pfile, cur)
147      cpp_reader *pfile;
148      const uchar *cur;
149 {
150   unsigned int from_line = pfile->line;
151   unsigned int c = 0, prevc = 0;
152   const uchar *limit = RLIMIT (pfile->context);
153
154   while (cur < limit)
155     {
156       prevc = c;
157       c = *cur++;
158
159       if (c == '/')
160         {
161           if (prevc == '*')
162             break;
163           if (*cur == '*' && cur[1] != '/'
164               && CPP_OPTION (pfile, warn_comments))
165             cpp_error_with_line (pfile, DL_WARNING, pfile->line, 0,
166                                  "\"/*\" within comment");
167         }
168       else if (is_vspace (c))
169         cur = handle_newline (pfile, cur - 1);
170     }
171
172   if (c != '/' || prevc != '*')
173     cpp_error_with_line (pfile, DL_ERROR, from_line, 0,
174                          "unterminated comment");
175
176   return cur;
177 }
178
179 /* Skip any horizontal whitespace and comments beginning at CUR,
180    returning the following character.  */
181 static const uchar *
182 skip_whitespace (pfile, cur)
183      cpp_reader *pfile;
184      const uchar *cur;
185 {
186   const uchar *tmp;
187
188   for (;;)
189     {
190       while (is_nvspace (*cur) && *cur != 0)
191         cur++;
192
193       if (*cur == '\0' && cur != RLIMIT (pfile->context))
194         continue;
195
196       if (*cur == '\\')
197         {
198           tmp = cur;
199           cur = skip_escaped_newlines (pfile, cur);
200           if (tmp != cur)
201             continue;
202         }
203
204       if (*cur == '/')
205         {
206           tmp = skip_escaped_newlines (pfile, cur + 1);
207           if (*tmp == '*')
208             {
209               cur = skip_comment (pfile, tmp + 1);
210               continue;
211             }
212         }
213
214       break;
215     }
216
217   return cur;
218 }
219
220 /* Lexes and outputs an identifier starting at CUR, which is assumed
221    to point to a valid first character of an identifier.  Returns
222    the hashnode, and updates trad_out_cur.  */
223 static cpp_hashnode *
224 lex_identifier (pfile, cur)
225      cpp_reader *pfile;
226      const uchar *cur;
227 {
228   size_t len;
229   uchar *out = pfile->trad_out_cur;
230   cpp_hashnode *result;
231
232   do
233     {
234       do
235         *out++ = *cur++;
236       while (is_numchar (*cur));
237       cur = skip_escaped_newlines (pfile, cur);
238     }
239   while (is_numchar (*cur));
240
241   CUR (pfile->context) = cur;
242   len = out - pfile->trad_out_cur;
243   result = (cpp_hashnode *) ht_lookup (pfile->hash_table, pfile->trad_out_cur,
244                                        len, HT_ALLOC);
245   pfile->trad_out_cur = out;
246   return result;
247 }
248
249 /* Reads an identifier, returning its hashnode.  If the next token is
250    not an identifier, returns NULL.  */
251 cpp_hashnode *
252 _cpp_lex_identifier_trad (pfile)
253      cpp_reader *pfile;
254 {
255   const uchar *cur = skip_whitespace (pfile, CUR (pfile->context));
256
257   if (!is_idstart (*cur))
258     {
259       CUR (pfile->context) = cur;
260       return NULL;
261     }
262
263   return lex_identifier (pfile, cur);
264 }
265
266 /* Overlays the true file buffer temporarily with text of length LEN
267    starting at START.  The true buffer is restored upon calling
268    restore_buff().  */
269 void
270 _cpp_overlay_buffer (pfile, start, len)
271      cpp_reader *pfile;
272      const uchar *start;
273      size_t len;
274 {
275   cpp_buffer *buffer = pfile->buffer;
276
277   buffer->saved_cur = buffer->cur;
278   buffer->saved_rlimit = buffer->rlimit;
279   buffer->saved_line_base = buffer->line_base;
280
281   buffer->cur = start;
282   buffer->line_base = start;
283   buffer->rlimit = start + len;
284 }
285
286 /* Restores a buffer overlaid by _cpp_overlay_buffer().  */
287 static void
288 restore_buff (pfile)
289      cpp_reader *pfile;
290 {
291   cpp_buffer *buffer = pfile->buffer;
292
293   buffer->cur = buffer->saved_cur;
294   buffer->rlimit = buffer->saved_rlimit;
295   buffer->line_base = buffer->saved_line_base;
296 }
297
298 /* Reads a logical line into the output buffer.  Returns TRUE if there
299    is more text left in the buffer.  */
300 bool
301 _cpp_read_logical_line_trad (pfile)
302      cpp_reader *pfile;
303 {
304   cpp_buffer *buffer;
305   unsigned int first_line;
306
307   restore_buff (pfile);
308
309   first_line = pfile->line = pfile->trad_line;
310
311   buffer = pfile->buffer;
312   if (buffer->cur == buffer->rlimit)
313     {
314       bool stop = true;
315
316       /* Don't pop the last buffer.  */
317       if (buffer->prev)
318         {
319           stop = buffer->return_at_eof;
320           _cpp_pop_buffer (pfile);
321         }
322
323       if (stop)
324         return false;
325     }
326
327   CUR (pfile->context) = buffer->cur;
328   RLIMIT (pfile->context) = buffer->rlimit;
329   pfile->trad_out_cur = pfile->trad_out_base;
330   scan_out_logical_line (pfile, NULL);
331   buffer->cur = CUR (pfile->context);
332
333   pfile->trad_line = pfile->line;
334   pfile->line = first_line;
335   _cpp_overlay_buffer (pfile, pfile->trad_out_base,
336                        pfile->trad_out_cur - pfile->trad_out_base);
337   return true;
338 }
339
340 /* Set up state for finding the opening '(' of a function-like
341    macro.  */
342 static void
343 maybe_start_funlike (pfile, node, start, macro)
344      cpp_reader *pfile;
345      cpp_hashnode *node;
346      const uchar *start;
347      struct fun_macro *macro;
348 {
349   unsigned int n = node->value.macro->paramc + 1;
350
351   if (macro->buff)
352     _cpp_release_buff (pfile, macro->buff);
353   macro->buff = _cpp_get_buff (pfile, n * sizeof (size_t));
354   macro->args = (size_t *) BUFF_FRONT (macro->buff);
355   macro->node = node;
356   macro->offset = start - pfile->trad_out_base;
357   macro->argc = 0;
358
359   pfile->state.parsing_args = 1;
360 }
361
362 /* Save the OFFSET of the start of the next argument to MACRO.  */
363 static void
364 save_argument (macro, offset)
365      struct fun_macro *macro;
366      size_t offset;
367 {
368   macro->argc++;
369   if (macro->argc <= macro->node->value.macro->paramc)
370     macro->args[macro->argc] = offset;
371 }
372
373 /* Copies the next logical line in the current buffer to the output
374    buffer.  The output is guaranteed to terminate with a NUL
375    character.
376
377    If MACRO is non-NULL, then we are scanning the replacement list of
378    MACRO, and we call save_replacement_text() every time we meet an
379    argument.  */
380 static void
381 scan_out_logical_line (pfile, macro)
382      cpp_reader *pfile;
383      cpp_macro *macro;
384 {
385   cpp_context *context;
386   const uchar *cur;
387   unsigned int c, paren_depth, quote = 0;
388   uchar *out;
389   struct fun_macro fmacro;
390
391   fmacro.buff = NULL;
392  new_context:
393   context = pfile->context;
394   cur = CUR (context);
395   check_output_buffer (pfile, RLIMIT (context) - cur);
396   out = pfile->trad_out_cur;
397
398   for (;;)
399     {
400       c = *cur++;
401       *out++ = c;
402
403       /* There are only a few entities we need to catch: comments,
404          identifiers, newlines, escaped newlines, # and '\0'.  */
405       switch (c)
406         {
407         case '\0':
408           if (cur - 1 != RLIMIT (context))
409             break;
410
411           /* If this is a macro's expansion, pop it.  */
412           if (context->prev)
413             {
414               pfile->trad_out_cur = out - 1;
415               _cpp_pop_context (pfile);
416               goto new_context;
417             }
418
419           /* Premature end of file.  Fake a new line.  */
420           cur--;
421           if (!pfile->buffer->from_stage3)
422             cpp_error (pfile, DL_PEDWARN, "no newline at end of file");
423           if (pfile->state.parsing_args == 2)
424             cpp_error (pfile, DL_ERROR,
425                        "unterminated argument list invoking macro \"%s\"",
426                        NODE_NAME (fmacro.node));
427           pfile->line++;
428           goto done;
429
430         case '\r': case '\n':
431           cur = handle_newline (pfile, cur - 1);
432           if (pfile->state.parsing_args == 2)
433             {
434               /* Newlines in arguments become a space.  */
435               out[-1] = ' ';
436               continue;
437             }
438           goto done;
439
440         case '"':
441         case '\'':
442           if (c == quote)
443             quote = 0;
444           else if (!quote)
445             quote = c;
446           break;
447
448         case '\\':
449           if (is_vspace (*cur))
450             out--, cur = skip_escaped_newlines (pfile, cur - 1);
451           else
452             {
453               /* Skip escaped quotes here, it's easier than above, but
454                  take care to first skip escaped newlines.  */
455               cur = skip_escaped_newlines (pfile, cur);
456               if (*cur == '\\' || *cur == '"' || *cur == '\'')
457                 *out++ = *cur++;
458             }
459           break;
460
461         case '/':
462           /* Traditional CPP does not recognize comments within
463              literals.  */
464           if (!quote)
465             {
466               cur = skip_escaped_newlines (pfile, cur);
467               if (*cur == '*')
468                 out--, cur = skip_comment (pfile, cur + 1);
469             }
470           break;
471
472         case '_':
473         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
474         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
475         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
476         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
477         case 'y': case 'z':
478         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
479         case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
480         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
481         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
482         case 'Y': case 'Z':
483           if (quote == 0 || macro)
484             {
485               cpp_hashnode *node;
486
487               pfile->trad_out_cur = --out;
488               node = lex_identifier (pfile, cur - 1);
489
490               if (node->type == NT_MACRO
491                   && pfile->state.parsing_args != 2
492                   && !pfile->state.prevent_expansion)
493                 {
494                   if (node->value.macro->fun_like)
495                     maybe_start_funlike (pfile, node, out, &fmacro);
496                   else
497                     {
498                       /* Remove the object-like macro's name from the
499                          output, and push its replacement text.  */
500                       pfile->trad_out_cur = out;
501                       push_replacement_text (pfile, node);
502                       goto new_context;
503                     }
504                 }
505               else if (macro && node->arg_index)
506                 {
507                   /* Found a parameter in the replacement text of a
508                      #define.  Remove its name from the output.  */
509                   pfile->trad_out_cur = out;
510                   save_replacement_text (pfile, macro, node->arg_index);
511                 }
512
513               out = pfile->trad_out_cur;
514               cur = CUR (context);
515             }
516           break;
517
518         case '(':
519           if (quote == 0)
520             {
521               paren_depth++;
522               if (pfile->state.parsing_args == 1)
523                 {
524                   const uchar *p = pfile->trad_out_base + fmacro.offset;
525
526                   /* Invoke a prior function-like macro if there is only
527                      white space in-between.  */
528                   while (is_numchar (*p))
529                     p++;
530                   while (is_space (*p))
531                     p++;
532
533                   if (p == out - 1)
534                     {
535                       pfile->state.parsing_args = 2;
536                       paren_depth = 1;
537                       out = pfile->trad_out_base + fmacro.offset;
538                       fmacro.args[0] = fmacro.offset;
539                     }
540                   else
541                     pfile->state.parsing_args = 0;
542                 }
543             }
544           break;
545
546         case ',':
547           if (quote == 0 && pfile->state.parsing_args == 2 && paren_depth == 1)
548             save_argument (&fmacro, out - pfile->trad_out_base);
549           break;
550
551         case ')':
552           if (quote == 0)
553             {
554               paren_depth--;
555               if (pfile->state.parsing_args == 2 && paren_depth == 0)
556                 {
557                   cpp_macro *m = fmacro.node->value.macro;
558
559                   pfile->state.parsing_args = 0;
560                   save_argument (&fmacro, out - pfile->trad_out_base);
561
562                   /* A single zero-length argument is no argument.  */
563                   if (fmacro.argc == 1
564                       && m->paramc == 0
565                       && out == pfile->trad_out_base + 1)
566                     fmacro.argc = 0;
567
568                   if (_cpp_arguments_ok (pfile, m, fmacro.node, fmacro.argc))
569                     {
570                       /* Remove the macro's invocation from the
571                          output, and push its replacement text.  */
572                       pfile->trad_out_cur = (pfile->trad_out_base
573                                              + fmacro.offset);
574                       CUR (context) = cur;
575                       replace_args_and_push (pfile, &fmacro);
576                       goto new_context;
577                     }
578                 }
579             }
580           break;
581
582         default:
583           break;
584         }
585     }
586
587  done:
588   out[-1] = '\0';
589   CUR (context) = cur;
590   pfile->trad_out_cur = out - 1;
591   if (fmacro.buff)
592     _cpp_release_buff (pfile, fmacro.buff);
593 }
594
595 /* Push a context holding the replacement text of the macro NODE on
596    the context stack.  NODE is either object-like, or a function-like
597    macro with no arguments.  */
598 static void
599 push_replacement_text (pfile, node)
600      cpp_reader *pfile;
601      cpp_hashnode *node;
602 {
603   cpp_macro *macro = node->value.macro;
604
605   _cpp_push_text_context (pfile, node, macro->exp.text, macro->count);
606 }
607
608 /* Push a context holding the replacement text of the macro NODE on
609    the context stack.  NODE is either object-like, or a function-like
610    macro with no arguments.  */
611 static void
612 replace_args_and_push (pfile, fmacro)
613      cpp_reader *pfile;
614      struct fun_macro *fmacro;
615 {
616   cpp_macro *macro = fmacro->node->value.macro;
617
618   if (macro->paramc == 0)
619     push_replacement_text (pfile, fmacro->node);
620   else
621     {
622       const uchar *exp;
623       uchar *p;
624       _cpp_buff *buff;
625       size_t len = 0;
626
627       /* Calculate the length of the argument-replaced text.  */
628       for (exp = macro->exp.text;;)
629         {
630           struct block *b = (struct block *) exp;
631
632           len += b->text_len;
633           if (b->arg_index == 0)
634             break;
635           len += (fmacro->args[b->arg_index]
636                   - fmacro->args[b->arg_index - 1] - 1);
637           exp += BLOCK_LEN (b->text_len);
638         }
639
640       /* Allocate room for the expansion plus NUL.  */
641       buff = _cpp_get_buff (pfile, len + 1);
642
643       /* Copy the expansion and replace arguments.  */
644       p = BUFF_FRONT (buff);
645       for (exp = macro->exp.text;;)
646         {
647           struct block *b = (struct block *) exp;
648           size_t arglen;
649
650           memcpy (p, b->text, b->text_len);
651           p += b->text_len;
652           if (b->arg_index == 0)
653             break;
654           arglen = (fmacro->args[b->arg_index]
655                     - fmacro->args[b->arg_index - 1] - 1);
656           memcpy (p, pfile->trad_out_base + fmacro->args[b->arg_index - 1],
657                   arglen);
658           p += arglen;
659           exp += BLOCK_LEN (b->text_len);
660         }
661
662       /* NUL-terminate.  */
663       *p = '\0';
664       _cpp_push_text_context (pfile, fmacro->node, BUFF_FRONT (buff), len);
665
666       /* So we free buffer allocation when macro is left.  */
667       pfile->context->buff = buff;
668     }
669 }
670
671 /* Read and record the parameters, if any, of a function-like macro
672    definition.  Destroys pfile->trad_out_cur.
673
674    Returns true on success, false on failure (syntax error or a
675    duplicate parameter).  On success, CUR (pfile->context) is just
676    past the closing parenthesis.  */
677 static bool
678 scan_parameters (pfile, macro)
679      cpp_reader *pfile;
680      cpp_macro *macro;
681 {
682   const uchar *cur = CUR (pfile->context) + 1;
683   bool ok;
684
685   for (;;)
686     {
687       cur = skip_whitespace (pfile, cur);
688
689       if (is_idstart (*cur))
690         {
691           ok = false;
692           if (_cpp_save_parameter (pfile, macro, lex_identifier (pfile, cur)))
693             break;
694           cur = skip_whitespace (pfile, CUR (pfile->context));
695           if (*cur == ',')
696             {
697               cur++;
698               continue;
699             }
700           ok = (*cur == ')');
701           break;
702         }
703
704       ok = (*cur == ')' && macro->paramc == 0);
705       break;
706     }
707
708   CUR (pfile->context) = cur + (*cur == ')');
709
710   return ok;
711 }
712
713 /* Save the text from pfile->trad_out_base to pfile->trad_out_cur as
714    the replacement text for the current macro, followed by argument
715    ARG_INDEX, with zero indicating the end of the replacement
716    text.  */
717 static void
718 save_replacement_text (pfile, macro, arg_index)
719      cpp_reader *pfile;
720      cpp_macro *macro;
721      unsigned int arg_index;
722 {
723   size_t len = pfile->trad_out_cur - pfile->trad_out_base;
724   uchar *exp;
725
726   if (macro->paramc == 0)
727     {
728       /* Object-like and function-like macros without parameters
729          simply store their NUL-terminated replacement text.  */
730       exp = _cpp_unaligned_alloc (pfile, len + 1);
731       memcpy (exp, pfile->trad_out_base, len);
732       exp[len] = '\0';
733       macro->exp.text = exp;
734       macro->count = len;
735     }
736   else
737     {
738       /* Store the text's length (unsigned int), the argument index
739          (unsigned short, base 1) and then the text.  */
740       size_t blen = BLOCK_LEN (len);
741       struct block *block;
742
743       if (macro->count + blen > BUFF_ROOM (pfile->a_buff))
744         _cpp_extend_buff (pfile, &pfile->a_buff, macro->count + blen);
745
746       exp = BUFF_FRONT (pfile->a_buff);
747       block = (struct block *) (exp + macro->count);
748       macro->exp.text = exp;
749
750       /* Write out the block information.  */
751       block->text_len = len;
752       block->arg_index = arg_index;
753       memcpy (block->text, pfile->trad_out_base, len);
754
755       /* Lex the rest into the start of the output buffer.  */
756       pfile->trad_out_cur = pfile->trad_out_base;
757
758       macro->count += blen;
759
760       /* If we've finished, commit the memory.  */
761       if (arg_index == 0)
762         BUFF_FRONT (pfile->a_buff) += macro->count;
763     }
764 }
765
766 /* Analyze and save the replacement text of a macro.  Returns true on
767    success.  */
768 bool
769 _cpp_create_trad_definition (pfile, macro)
770      cpp_reader *pfile;
771      cpp_macro *macro;
772 {
773   const uchar *cur;
774   uchar *limit;
775
776   /* Is this a function-like macro?  */
777   if (* CUR (pfile->context) == '(')
778     {
779       /* Setting macro to NULL indicates an error occurred, and
780          prevents unnecessary work in scan_out_logical_line.  */
781       if (!scan_parameters (pfile, macro))
782         macro = NULL;
783       else
784         {
785           /* Success.  Commit the parameter array.  */
786           macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
787           BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc];
788           macro->fun_like = 1;
789         }
790     }
791
792   /* Skip leading whitespace in the replacement text.  */
793   CUR (pfile->context) = skip_whitespace (pfile, CUR (pfile->context));
794
795   pfile->trad_out_cur = pfile->trad_out_base;
796   pfile->state.prevent_expansion++;
797   scan_out_logical_line (pfile, macro);
798   pfile->state.prevent_expansion--;
799
800   if (!macro)
801     return false;
802
803   /* Skip trailing white space.  */
804   cur = pfile->trad_out_base;
805   limit = pfile->trad_out_cur;
806   while (limit > cur && is_space (limit[-1]))
807     limit--;
808   pfile->trad_out_cur = limit;
809   save_replacement_text (pfile, macro, 0);
810
811   return true;
812 }
813
814 /* Copy SRC of length LEN to DEST, but convert all contiguous
815    whitespace to a single space, provided it is not in quotes.  The
816    quote currently in effect is pointed to by PQUOTE, and is updated
817    by the function.  Returns the number of bytes copied.  */
818 static size_t
819 canonicalize_text (dest, src, len, pquote)
820      uchar *dest;
821      const uchar *src;
822      size_t len;
823      uchar *pquote;
824 {
825   uchar *orig_dest = dest;
826   uchar quote = *pquote;
827
828   while (len)
829     {
830       if (is_space (*src) && !quote)
831         {
832           do
833             src++, len--;
834           while (len && is_space (*src));
835           *dest++ = ' ';
836         }
837       else
838         {
839           if (*src == '\'' || *src == '"')
840             {
841               if (!quote)
842                 quote = *src;
843               else if (quote == *src)
844                 quote = 0;
845             }
846           *dest++ = *src++, len--;
847         }
848     }
849
850   *pquote = quote;
851   return dest - orig_dest;
852 }
853
854 /* Returns true if MACRO1 and MACRO2 have expansions different other
855    than in the form of their whitespace.  */
856 bool
857 _cpp_expansions_different_trad (macro1, macro2)
858      cpp_macro *macro1, *macro2;
859 {
860   uchar *p1 = xmalloc (macro1->count + macro2->count);
861   uchar *p2 = p1 + macro1->count;
862   uchar quote1 = 0, quote2;
863   bool mismatch;
864   size_t len1, len2;
865
866   if (macro1->paramc > 0)
867     {
868       const uchar *exp1 = macro1->exp.text, *exp2 = macro2->exp.text;
869
870       mismatch = true;
871       for (;;)
872         {
873           struct block *b1 = (struct block *) exp1;
874           struct block *b2 = (struct block *) exp2;
875
876           if (b1->arg_index != b2->arg_index)
877             break;
878
879           len1 = canonicalize_text (p1, b1->text, b1->text_len, &quote1);
880           len2 = canonicalize_text (p2, b2->text, b2->text_len, &quote2);
881           if (len1 != len2 || memcmp (p1, p2, len1))
882             break;
883           if (b1->arg_index == 0)
884             {
885               mismatch = false;
886               break;
887             }
888           exp1 += BLOCK_LEN (b1->text_len);
889           exp2 += BLOCK_LEN (b2->text_len);
890         }
891     }
892   else
893     {
894       len1 = canonicalize_text (p1, macro1->exp.text, macro1->count, &quote1);
895       len2 = canonicalize_text (p2, macro2->exp.text, macro2->count, &quote2);
896       mismatch = (len1 != len2 || memcmp (p1, p2, len1));
897     }
898
899   free (p1);
900   return mismatch;
901 }
902
903 /* Prepare to be able to scan the current buffer.  */
904 void
905 _cpp_set_trad_context (pfile)
906      cpp_reader *pfile;
907 {
908   cpp_buffer *buffer = pfile->buffer;
909   cpp_context *context = pfile->context;
910
911   if (pfile->context->prev)
912     abort ();
913
914   pfile->trad_out_cur = pfile->trad_out_base;
915   CUR (context) = buffer->cur;
916   RLIMIT (context) = buffer->rlimit;
917   check_output_buffer (pfile, RLIMIT (context) - CUR (context));
918 }