OSDN Git Service

* cpphash.h (_cpp_read_logical_line_trad,
[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, overlay)
302      cpp_reader *pfile;
303      int overlay;
304 {
305   cpp_buffer *buffer;
306   unsigned int first_line = 0;
307
308   if (overlay)
309     {
310       restore_buff (pfile);
311       first_line = pfile->line = pfile->trad_line;
312     }
313
314   buffer = pfile->buffer;
315   if (buffer->cur == buffer->rlimit)
316     {
317       bool stop = true;
318
319       /* Don't pop the last buffer.  */
320       if (buffer->prev)
321         {
322           stop = buffer->return_at_eof;
323           _cpp_pop_buffer (pfile);
324         }
325
326       if (stop)
327         return false;
328     }
329
330   CUR (pfile->context) = buffer->cur;
331   RLIMIT (pfile->context) = buffer->rlimit;
332   pfile->trad_out_cur = pfile->trad_out_base;
333   scan_out_logical_line (pfile, NULL);
334   buffer->cur = CUR (pfile->context);
335
336   if (overlay)
337     {
338       pfile->trad_line = pfile->line;
339       pfile->line = first_line;
340       _cpp_overlay_buffer (pfile, pfile->trad_out_base,
341                            pfile->trad_out_cur - pfile->trad_out_base);
342     }
343
344   return true;
345 }
346
347 /* Set up state for finding the opening '(' of a function-like
348    macro.  */
349 static void
350 maybe_start_funlike (pfile, node, start, macro)
351      cpp_reader *pfile;
352      cpp_hashnode *node;
353      const uchar *start;
354      struct fun_macro *macro;
355 {
356   unsigned int n = node->value.macro->paramc + 1;
357
358   if (macro->buff)
359     _cpp_release_buff (pfile, macro->buff);
360   macro->buff = _cpp_get_buff (pfile, n * sizeof (size_t));
361   macro->args = (size_t *) BUFF_FRONT (macro->buff);
362   macro->node = node;
363   macro->offset = start - pfile->trad_out_base;
364   macro->argc = 0;
365
366   pfile->state.parsing_args = 1;
367 }
368
369 /* Save the OFFSET of the start of the next argument to MACRO.  */
370 static void
371 save_argument (macro, offset)
372      struct fun_macro *macro;
373      size_t offset;
374 {
375   macro->argc++;
376   if (macro->argc <= macro->node->value.macro->paramc)
377     macro->args[macro->argc] = offset;
378 }
379
380 /* Copies the next logical line in the current buffer to the output
381    buffer.  The output is guaranteed to terminate with a NUL
382    character.
383
384    If MACRO is non-NULL, then we are scanning the replacement list of
385    MACRO, and we call save_replacement_text() every time we meet an
386    argument.  */
387 static void
388 scan_out_logical_line (pfile, macro)
389      cpp_reader *pfile;
390      cpp_macro *macro;
391 {
392   cpp_context *context;
393   const uchar *cur;
394   unsigned int c, paren_depth, quote = 0;
395   uchar *out;
396   struct fun_macro fmacro;
397
398   fmacro.buff = NULL;
399  new_context:
400   context = pfile->context;
401   cur = CUR (context);
402   check_output_buffer (pfile, RLIMIT (context) - cur);
403   out = pfile->trad_out_cur;
404
405   for (;;)
406     {
407       c = *cur++;
408       *out++ = c;
409
410       /* There are only a few entities we need to catch: comments,
411          identifiers, newlines, escaped newlines, # and '\0'.  */
412       switch (c)
413         {
414         case '\0':
415           if (cur - 1 != RLIMIT (context))
416             break;
417
418           /* If this is a macro's expansion, pop it.  */
419           if (context->prev)
420             {
421               pfile->trad_out_cur = out - 1;
422               _cpp_pop_context (pfile);
423               goto new_context;
424             }
425
426           /* Premature end of file.  Fake a new line.  */
427           cur--;
428           if (!pfile->buffer->from_stage3)
429             cpp_error (pfile, DL_PEDWARN, "no newline at end of file");
430           if (pfile->state.parsing_args == 2)
431             cpp_error (pfile, DL_ERROR,
432                        "unterminated argument list invoking macro \"%s\"",
433                        NODE_NAME (fmacro.node));
434           pfile->line++;
435           goto done;
436
437         case '\r': case '\n':
438           cur = handle_newline (pfile, cur - 1);
439           if (pfile->state.parsing_args == 2)
440             {
441               /* Newlines in arguments become a space.  */
442               out[-1] = ' ';
443               continue;
444             }
445           goto done;
446
447         case '"':
448         case '\'':
449           if (c == quote)
450             quote = 0;
451           else if (!quote)
452             quote = c;
453           break;
454
455         case '\\':
456           if (is_vspace (*cur))
457             out--, cur = skip_escaped_newlines (pfile, cur - 1);
458           else
459             {
460               /* Skip escaped quotes here, it's easier than above, but
461                  take care to first skip escaped newlines.  */
462               cur = skip_escaped_newlines (pfile, cur);
463               if (*cur == '\\' || *cur == '"' || *cur == '\'')
464                 *out++ = *cur++;
465             }
466           break;
467
468         case '/':
469           /* Traditional CPP does not recognize comments within
470              literals.  */
471           if (!quote)
472             {
473               cur = skip_escaped_newlines (pfile, cur);
474               if (*cur == '*')
475                 out--, cur = skip_comment (pfile, cur + 1);
476             }
477           break;
478
479         case '_':
480         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
481         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
482         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
483         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
484         case 'y': case 'z':
485         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
486         case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
487         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
488         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
489         case 'Y': case 'Z':
490           if (quote == 0 || macro)
491             {
492               cpp_hashnode *node;
493
494               pfile->trad_out_cur = --out;
495               node = lex_identifier (pfile, cur - 1);
496
497               if (node->type == NT_MACRO
498                   && pfile->state.parsing_args != 2
499                   && !pfile->state.prevent_expansion)
500                 {
501                   if (node->value.macro->fun_like)
502                     maybe_start_funlike (pfile, node, out, &fmacro);
503                   else
504                     {
505                       /* Remove the object-like macro's name from the
506                          output, and push its replacement text.  */
507                       pfile->trad_out_cur = out;
508                       push_replacement_text (pfile, node);
509                       goto new_context;
510                     }
511                 }
512               else if (macro && node->arg_index)
513                 {
514                   /* Found a parameter in the replacement text of a
515                      #define.  Remove its name from the output.  */
516                   pfile->trad_out_cur = out;
517                   save_replacement_text (pfile, macro, node->arg_index);
518                 }
519
520               out = pfile->trad_out_cur;
521               cur = CUR (context);
522             }
523           break;
524
525         case '(':
526           if (quote == 0)
527             {
528               paren_depth++;
529               if (pfile->state.parsing_args == 1)
530                 {
531                   const uchar *p = pfile->trad_out_base + fmacro.offset;
532
533                   /* Invoke a prior function-like macro if there is only
534                      white space in-between.  */
535                   while (is_numchar (*p))
536                     p++;
537                   while (is_space (*p))
538                     p++;
539
540                   if (p == out - 1)
541                     {
542                       pfile->state.parsing_args = 2;
543                       paren_depth = 1;
544                       out = pfile->trad_out_base + fmacro.offset;
545                       fmacro.args[0] = fmacro.offset;
546                     }
547                   else
548                     pfile->state.parsing_args = 0;
549                 }
550             }
551           break;
552
553         case ',':
554           if (quote == 0 && pfile->state.parsing_args == 2 && paren_depth == 1)
555             save_argument (&fmacro, out - pfile->trad_out_base);
556           break;
557
558         case ')':
559           if (quote == 0)
560             {
561               paren_depth--;
562               if (pfile->state.parsing_args == 2 && paren_depth == 0)
563                 {
564                   cpp_macro *m = fmacro.node->value.macro;
565
566                   pfile->state.parsing_args = 0;
567                   save_argument (&fmacro, out - pfile->trad_out_base);
568
569                   /* A single zero-length argument is no argument.  */
570                   if (fmacro.argc == 1
571                       && m->paramc == 0
572                       && out == pfile->trad_out_base + 1)
573                     fmacro.argc = 0;
574
575                   if (_cpp_arguments_ok (pfile, m, fmacro.node, fmacro.argc))
576                     {
577                       /* Remove the macro's invocation from the
578                          output, and push its replacement text.  */
579                       pfile->trad_out_cur = (pfile->trad_out_base
580                                              + fmacro.offset);
581                       CUR (context) = cur;
582                       replace_args_and_push (pfile, &fmacro);
583                       goto new_context;
584                     }
585                 }
586             }
587           break;
588
589         default:
590           break;
591         }
592     }
593
594  done:
595   out[-1] = '\0';
596   CUR (context) = cur;
597   pfile->trad_out_cur = out - 1;
598   if (fmacro.buff)
599     _cpp_release_buff (pfile, fmacro.buff);
600 }
601
602 /* Push a context holding the replacement text of the macro NODE on
603    the context stack.  NODE is either object-like, or a function-like
604    macro with no arguments.  */
605 static void
606 push_replacement_text (pfile, node)
607      cpp_reader *pfile;
608      cpp_hashnode *node;
609 {
610   cpp_macro *macro = node->value.macro;
611
612   _cpp_push_text_context (pfile, node, macro->exp.text, macro->count);
613 }
614
615 /* Push a context holding the replacement text of the macro NODE on
616    the context stack.  NODE is either object-like, or a function-like
617    macro with no arguments.  */
618 static void
619 replace_args_and_push (pfile, fmacro)
620      cpp_reader *pfile;
621      struct fun_macro *fmacro;
622 {
623   cpp_macro *macro = fmacro->node->value.macro;
624
625   if (macro->paramc == 0)
626     push_replacement_text (pfile, fmacro->node);
627   else
628     {
629       const uchar *exp;
630       uchar *p;
631       _cpp_buff *buff;
632       size_t len = 0;
633
634       /* Calculate the length of the argument-replaced text.  */
635       for (exp = macro->exp.text;;)
636         {
637           struct block *b = (struct block *) exp;
638
639           len += b->text_len;
640           if (b->arg_index == 0)
641             break;
642           len += (fmacro->args[b->arg_index]
643                   - fmacro->args[b->arg_index - 1] - 1);
644           exp += BLOCK_LEN (b->text_len);
645         }
646
647       /* Allocate room for the expansion plus NUL.  */
648       buff = _cpp_get_buff (pfile, len + 1);
649
650       /* Copy the expansion and replace arguments.  */
651       p = BUFF_FRONT (buff);
652       for (exp = macro->exp.text;;)
653         {
654           struct block *b = (struct block *) exp;
655           size_t arglen;
656
657           memcpy (p, b->text, b->text_len);
658           p += b->text_len;
659           if (b->arg_index == 0)
660             break;
661           arglen = (fmacro->args[b->arg_index]
662                     - fmacro->args[b->arg_index - 1] - 1);
663           memcpy (p, pfile->trad_out_base + fmacro->args[b->arg_index - 1],
664                   arglen);
665           p += arglen;
666           exp += BLOCK_LEN (b->text_len);
667         }
668
669       /* NUL-terminate.  */
670       *p = '\0';
671       _cpp_push_text_context (pfile, fmacro->node, BUFF_FRONT (buff), len);
672
673       /* So we free buffer allocation when macro is left.  */
674       pfile->context->buff = buff;
675     }
676 }
677
678 /* Read and record the parameters, if any, of a function-like macro
679    definition.  Destroys pfile->trad_out_cur.
680
681    Returns true on success, false on failure (syntax error or a
682    duplicate parameter).  On success, CUR (pfile->context) is just
683    past the closing parenthesis.  */
684 static bool
685 scan_parameters (pfile, macro)
686      cpp_reader *pfile;
687      cpp_macro *macro;
688 {
689   const uchar *cur = CUR (pfile->context) + 1;
690   bool ok;
691
692   for (;;)
693     {
694       cur = skip_whitespace (pfile, cur);
695
696       if (is_idstart (*cur))
697         {
698           ok = false;
699           if (_cpp_save_parameter (pfile, macro, lex_identifier (pfile, cur)))
700             break;
701           cur = skip_whitespace (pfile, CUR (pfile->context));
702           if (*cur == ',')
703             {
704               cur++;
705               continue;
706             }
707           ok = (*cur == ')');
708           break;
709         }
710
711       ok = (*cur == ')' && macro->paramc == 0);
712       break;
713     }
714
715   CUR (pfile->context) = cur + (*cur == ')');
716
717   return ok;
718 }
719
720 /* Save the text from pfile->trad_out_base to pfile->trad_out_cur as
721    the replacement text for the current macro, followed by argument
722    ARG_INDEX, with zero indicating the end of the replacement
723    text.  */
724 static void
725 save_replacement_text (pfile, macro, arg_index)
726      cpp_reader *pfile;
727      cpp_macro *macro;
728      unsigned int arg_index;
729 {
730   size_t len = pfile->trad_out_cur - pfile->trad_out_base;
731   uchar *exp;
732
733   if (macro->paramc == 0)
734     {
735       /* Object-like and function-like macros without parameters
736          simply store their NUL-terminated replacement text.  */
737       exp = _cpp_unaligned_alloc (pfile, len + 1);
738       memcpy (exp, pfile->trad_out_base, len);
739       exp[len] = '\0';
740       macro->exp.text = exp;
741       macro->count = len;
742     }
743   else
744     {
745       /* Store the text's length (unsigned int), the argument index
746          (unsigned short, base 1) and then the text.  */
747       size_t blen = BLOCK_LEN (len);
748       struct block *block;
749
750       if (macro->count + blen > BUFF_ROOM (pfile->a_buff))
751         _cpp_extend_buff (pfile, &pfile->a_buff, macro->count + blen);
752
753       exp = BUFF_FRONT (pfile->a_buff);
754       block = (struct block *) (exp + macro->count);
755       macro->exp.text = exp;
756
757       /* Write out the block information.  */
758       block->text_len = len;
759       block->arg_index = arg_index;
760       memcpy (block->text, pfile->trad_out_base, len);
761
762       /* Lex the rest into the start of the output buffer.  */
763       pfile->trad_out_cur = pfile->trad_out_base;
764
765       macro->count += blen;
766
767       /* If we've finished, commit the memory.  */
768       if (arg_index == 0)
769         BUFF_FRONT (pfile->a_buff) += macro->count;
770     }
771 }
772
773 /* Analyze and save the replacement text of a macro.  Returns true on
774    success.  */
775 bool
776 _cpp_create_trad_definition (pfile, macro)
777      cpp_reader *pfile;
778      cpp_macro *macro;
779 {
780   const uchar *cur;
781   uchar *limit;
782
783   /* Is this a function-like macro?  */
784   if (* CUR (pfile->context) == '(')
785     {
786       /* Setting macro to NULL indicates an error occurred, and
787          prevents unnecessary work in scan_out_logical_line.  */
788       if (!scan_parameters (pfile, macro))
789         macro = NULL;
790       else
791         {
792           /* Success.  Commit the parameter array.  */
793           macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
794           BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc];
795           macro->fun_like = 1;
796         }
797     }
798
799   /* Skip leading whitespace in the replacement text.  */
800   CUR (pfile->context) = skip_whitespace (pfile, CUR (pfile->context));
801
802   pfile->trad_out_cur = pfile->trad_out_base;
803   pfile->state.prevent_expansion++;
804   scan_out_logical_line (pfile, macro);
805   pfile->state.prevent_expansion--;
806
807   if (!macro)
808     return false;
809
810   /* Skip trailing white space.  */
811   cur = pfile->trad_out_base;
812   limit = pfile->trad_out_cur;
813   while (limit > cur && is_space (limit[-1]))
814     limit--;
815   pfile->trad_out_cur = limit;
816   save_replacement_text (pfile, macro, 0);
817
818   return true;
819 }
820
821 /* Copy SRC of length LEN to DEST, but convert all contiguous
822    whitespace to a single space, provided it is not in quotes.  The
823    quote currently in effect is pointed to by PQUOTE, and is updated
824    by the function.  Returns the number of bytes copied.  */
825 static size_t
826 canonicalize_text (dest, src, len, pquote)
827      uchar *dest;
828      const uchar *src;
829      size_t len;
830      uchar *pquote;
831 {
832   uchar *orig_dest = dest;
833   uchar quote = *pquote;
834
835   while (len)
836     {
837       if (is_space (*src) && !quote)
838         {
839           do
840             src++, len--;
841           while (len && is_space (*src));
842           *dest++ = ' ';
843         }
844       else
845         {
846           if (*src == '\'' || *src == '"')
847             {
848               if (!quote)
849                 quote = *src;
850               else if (quote == *src)
851                 quote = 0;
852             }
853           *dest++ = *src++, len--;
854         }
855     }
856
857   *pquote = quote;
858   return dest - orig_dest;
859 }
860
861 /* Returns true if MACRO1 and MACRO2 have expansions different other
862    than in the form of their whitespace.  */
863 bool
864 _cpp_expansions_different_trad (macro1, macro2)
865      const cpp_macro *macro1, *macro2;
866 {
867   uchar *p1 = xmalloc (macro1->count + macro2->count);
868   uchar *p2 = p1 + macro1->count;
869   uchar quote1 = 0, quote2;
870   bool mismatch;
871   size_t len1, len2;
872
873   if (macro1->paramc > 0)
874     {
875       const uchar *exp1 = macro1->exp.text, *exp2 = macro2->exp.text;
876
877       mismatch = true;
878       for (;;)
879         {
880           struct block *b1 = (struct block *) exp1;
881           struct block *b2 = (struct block *) exp2;
882
883           if (b1->arg_index != b2->arg_index)
884             break;
885
886           len1 = canonicalize_text (p1, b1->text, b1->text_len, &quote1);
887           len2 = canonicalize_text (p2, b2->text, b2->text_len, &quote2);
888           if (len1 != len2 || memcmp (p1, p2, len1))
889             break;
890           if (b1->arg_index == 0)
891             {
892               mismatch = false;
893               break;
894             }
895           exp1 += BLOCK_LEN (b1->text_len);
896           exp2 += BLOCK_LEN (b2->text_len);
897         }
898     }
899   else
900     {
901       len1 = canonicalize_text (p1, macro1->exp.text, macro1->count, &quote1);
902       len2 = canonicalize_text (p2, macro2->exp.text, macro2->count, &quote2);
903       mismatch = (len1 != len2 || memcmp (p1, p2, len1));
904     }
905
906   free (p1);
907   return mismatch;
908 }
909
910 /* Prepare to be able to scan the current buffer.  */
911 void
912 _cpp_set_trad_context (pfile)
913      cpp_reader *pfile;
914 {
915   cpp_buffer *buffer = pfile->buffer;
916   cpp_context *context = pfile->context;
917
918   if (pfile->context->prev)
919     abort ();
920
921   pfile->trad_out_cur = pfile->trad_out_base;
922   CUR (context) = buffer->cur;
923   RLIMIT (context) = buffer->rlimit;
924   check_output_buffer (pfile, RLIMIT (context) - CUR (context));
925 }