OSDN Git Service

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