Added package with the documentation and the examples
[lwc.git] / cpp.c
blob68fcc4e2a57ced5e90f31c21da7e7efdae5786ff
1 /***************************************************************************
3 C preprocessor
5 The preprocessor is not a seperate stage but an extension to the lexical
6 analyser. This is possible and efficient since we avoid two passes of
7 the source file.
9 ***************************************************************************/
11 #include "global.h"
12 #include "SYS.h"
14 #ifdef DO_CPP
16 // these are borrowed from lex.c
18 extern int skip_ws ();
19 extern int skip_comment ();
20 extern int skip_line ();
21 extern int enter_symbol (char*);
22 extern int enter_string (char*);
24 extern int do_yylex ();
26 static void skip_pp_line ()
28 // Skip a line but respect that newlines inside:
29 // strings, comments, char consts and
30 // escaped ones don't count
31 for (;;) {
32 if (Ci >= Clen) return;
34 switch (Cpp [Ci]) {
35 case '/':
36 ++Ci;
37 if (Cpp [Ci] == '*') skip_comment ();
38 else if (Cpp [Ci] == '/') skip_line ();
39 ncase '\\':
40 if (Cpp [++Ci] == '\n') {
41 ++Ci;
42 ++line;
44 ncase '\n': return;
45 ncase '"':
46 for (++Ci; Ci < Clen && Cpp [Ci] != '"'; Ci++)
47 if (Cpp [Ci] == '\\') ++Ci;
48 else if (Cpp [Ci] == '\n') ++line;
49 ++Ci;
50 ncase '\'':
51 for (++Ci; Ci < Clen && Cpp [Ci] != '\''; Ci++)
52 if (Cpp [Ci] == '\\') ++Ci;
53 else if (Cpp [Ci] == '\n') ++line;
54 ++Ci;
55 ndefault:
56 ++Ci;
61 static Token *get_expanded_line ()
63 Token t;
65 SAVE_VAR (Ci, Ci);
66 skip_pp_line ();
67 SAVE_VAR (Clen, Ci+1);
68 RESTOR_VAR (Ci);
70 OUTSTREAM S = new_stream ();
71 while ((t = do_yylex ()) != THE_END)
72 if (ISSYMBOL (t))
73 if (t == RESERVED_defined) {
74 if (!issymbol (t = do_yylex ())
75 && (t != '(' || !issymbol (t = do_yylex ())
76 || do_yylex () != ')'))
77 parse_error_cpp ("defined (symbol)");
78 output_itoken (S, is_macro (t) == -1 ? RESERVED_0 : RESERVED_1);
79 } else if (is_macro (t) != -1) {
80 Token *E = expand_macro (t);
81 outprintf (S, ISTR (E), -1);
82 free (E);
83 } else goto jmp;
84 else jmp: output_itoken (S, t);
86 RESTOR_VAR (Clen);
87 return combine_output (S);
90 /******************************************************************************
92 File inclusion
94 Search for the file in the usual places and then recurse back to yydo_file.
95 If the directive is "#uses", then enclose everything inside extern "file" {}
97 ******************************************************************************/
98 static char **hsearch, **isearch;
100 static char *fixpath (char *path)
102 char *p = path, *s, *e;
104 while (*p)
105 if (p [0] == '.')
106 if (p [1] == '/') {
107 s = p; e = p + 2;
108 while (*s++ = *e++);
109 } else if (p [1] == '.' && p [2] == '/' && p > path + 1 && p [-1] == '/') {
110 e = p + 3;
111 for (s = p - 2; *s != '/' && s > path; s--);
112 p = *s == '/' ? ++s : s;
113 while (*s++ = *e++);
114 } else goto eelse;
115 else eelse: ++p;
116 return path;
119 static char *FindHeader (char *fn, char *ret, bool sys)
121 char **p = sys ? isearch : hsearch;
122 char tmp [256];
124 for (; *p; p++) {
125 tmp [0] = 0;
126 if (!sys && (**p != '/' || *p [1] != ':' && *p [2] != '/')
127 && strchr (current_file, '/')) {
128 strcpy (tmp, current_file);
129 char *t = strrchr (tmp, '/');
130 if (t) *(t + 1) = 0;
131 else tmp [0] = 0;
133 strcat (tmp, *p);
134 if (strlen (tmp) && tmp [strlen (tmp) - 1] != '/') strcat (tmp, "/");
135 strcat (tmp, fn);
137 fixpath (tmp);
139 if (access (tmp, R_OK) == 0)
140 return strcpy (ret, tmp);
143 fprintf (stderr, "Could not find file %s\n", fn);
144 fatal ("terminated");
145 return 0;
148 static intnode *included;
150 static void include (bool uses)
152 int closer, i, t;
153 char fn [128], path [256];
155 skip_ws ();
156 closer = Cpp [Ci] == '<' ? '>' : Cpp [Ci] == '"' ? '"' : 0;
157 if (!closer) fatal ("#include");
159 for (++Ci, i = 0; Cpp [Ci] != closer && Ci < Clen && i < sizeof fn;)
160 fn [i++] = Cpp [Ci++];
161 fn [i] = 0;
163 if (Cpp [Ci++] != closer) fatal ("#include");
165 FindHeader (fn, path, closer == '>');
166 t = enter_value (path);
168 if (!intfind (included, t)) {
169 union ival u;
170 intadd (&included, t, u);
172 if (uses) {
173 char path [256];
174 sprintf (path, "\"%s\"", fn);
175 outprintf (GLOBAL, RESERVED_extern, enter_value (path), '{', -1);
178 if (yydo_file (path) == -1) {
179 fprintf (stderr, "Problematic file [%s]\n", fn);
180 fatal ("Can't open file");;
183 if (uses) output_itoken (GLOBAL, '}');
187 /******************************************************************************
189 Macro Definitions && undefs
191 ******************************************************************************/
192 typedef struct {
193 int argc;
194 Token *body;
195 } macro;
197 static intnode *macrotree;
199 int is_macro (Token t)
201 intnode *n;
203 if (n = intfind (macrotree, t))
204 return ((macro*) n->v.p)->argc;
206 return ISPREDEF (t) ? 0 : -1;
209 static void define ()
211 int argc = 0, i, margc = 0;
212 Token n = do_yylex (), argv [100], t;
213 macro *m;
214 intnode *mn;
216 if (!ISSYMBOL (n)) fatal ("#define");
218 #ifdef DEBUG
219 if (debugflag.CPP) {
220 PRINTF ("define ["COLS"%s"COLE"]\n", expand (n));
222 #endif
224 if (Cpp [Ci] == '(') {
225 for (++Ci;;) {
226 t = do_yylex ();
227 if (t == ')') break;
228 if (t == ELLIPSIS) {
229 if (do_yylex () != ')')
230 parse_error_cpp ("#define X(arg,...) : C99 style");
231 break;
233 if (!ISSYMBOL (t)) fatal ("#define args");
234 argv [argc++] = t;
235 t = do_yylex ();
236 if (t == ')') break;
237 if (t == ELLIPSIS) fatal ("gnu varags not supported");
238 if (t != ',') fatal ("#define args separator");
240 margc = t == ELLIPSIS ? argc + VARBOOST : argc ?: VOIDARG;
243 SAVE_VAR (Ci, Ci);
244 skip_pp_line ();
245 SAVE_VAR (Clen, Ci+1);
246 RESTOR_VAR (Ci);
248 OUTSTREAM Def = new_stream ();
249 while ((t = do_yylex ()) != THE_END) {
250 for (i = 0; i < argc; i++)
251 if (argv [i] == t) {
252 t = i + ARGBASE;
253 break;
255 if (t == RESERVED___VA_ARGS__)
256 t = argc + ARGBASE;
257 output_itoken (Def, t);
259 m = (macro*) malloc (sizeof *m);
260 m->body = combine_output (Def);
261 m->argc = margc;
262 if (mn = intfind (macrotree, n)) {
263 macro *h = (macro*) mn->v.p;
264 if (h->argc != m->argc || intcmp (h->body, m->body))
265 fatal ("different macro redefinition");
266 free (m->body);
267 free (m);
268 } else {
269 union ival u = { .p m };
270 intadd (&macrotree, n, u);
273 RESTOR_VAR (Clen);
276 void undef ()
278 Token m = do_yylex ();
279 intnode *n = intfind (macrotree, m);
281 if (n) {
282 free (((macro*) n->v.p)->body);
283 intremove (&macrotree, n);
284 free (n);
288 /******************************************************************************
289 cpp expression evaluation (#if, #elif)
290 a mini-compiler inside the compiler...
292 right now works only with integers. floats and other stuff
293 evaluate to 1L. symbols evaluate to 0L
294 ******************************************************************************/
295 static Token *eval_expr;
296 static NormPtr eep;
298 static long long int cpp_expression ();
300 static long long int cpp_cond_getnum ()
302 Token s = eval_expr [eep++];
304 switch (s) {
305 case '!': return !cpp_cond_getnum ();
306 case '(': return cpp_expression ();
307 case '-': return -cpp_cond_getnum ();
308 case '~': return ~cpp_cond_getnum ();
311 if (ISVALUE (s))
312 return type_of_const (s) == typeID_int ?
313 eval_intll (s) : 1;
315 return 0;
318 static int op_pri (int type)
320 /* oh not again */
321 switch (type) {
322 case -1:
323 case ')': return 9;
324 case ANDAND:
325 case OROR: return 8;
326 case '|': return 7;
327 case '^': return 6;
328 case '&': return 5;
329 case NEQCMP:
330 case EQCMP: return 4;
331 case '<':
332 case '>':
333 case GEQCMP:
334 case LEQCMP: return 3;
335 case RSH:
336 case LSH: return 2;
337 case '+':
338 case '-': return 1;
339 case '*':
340 case '/':
341 case '%': return 0;
342 default: return -1;
346 #define CALC(operator) \
347 /* PRINTF ("calculating %lli %s %lli\n", Arr [ce-1], #operator, Arr[ce+1]); */\
348 Arr [ce - 1] = Arr [ce - 1] operator Arr [ce + 1];\
349 break;
351 static long long int cpp_expressionr ()
353 long long int Arr [64];
354 int pri, ce;
356 Arr [0] = 1;
358 /* DO NOT TRY THIS AT HOME */
359 for (;;) {
360 Arr [Arr [0]] = cpp_cond_getnum ();
361 pri = op_pri (eval_expr [eep]);
362 if (pri == -1)
363 if (eval_expr [eep] == '?' || eval_expr [eep] == ':')
364 return Arr [1];
365 else parse_error_cpp ("confusing expression in #if");
366 while (Arr [0] > 1)
367 if (op_pri (Arr [ce = Arr [0] - 1]) <= pri) {
368 switch (Arr [ce]) {
369 case '*': CALC (*);
370 case '/': CALC (/);
371 case '%': CALC (%);
372 case '+': CALC (+);
373 case '-': CALC (-);
374 case RSH: CALC (>>);
375 case LSH: CALC (<<);
376 case '<': CALC (<);
377 case '>': CALC (>);
378 case EQCMP: CALC (==);
379 case NEQCMP: CALC (!=);
380 case GEQCMP: CALC (>=);
381 case LEQCMP: CALC (<=);
382 case '&': CALC (&);
383 case '|': CALC (|);
384 case '^': CALC (^);
385 case ANDAND: CALC (&&);
387 Arr [0] -= 2;
388 } else break;
389 if (pri == 9) return Arr [1];
390 if (pri == 8) {
391 if (eval_expr [eep] == ANDAND && Arr [1] == 0) {
392 for (++eep; eval_expr [eep] != ')' && eval_expr [eep] != OROR
393 && eval_expr [eep] != -1; eep++)
394 if (eep == '(')
395 eep = skip_buffer_parenthesis (eval_expr, eep + 1) - 1;
396 if (eval_expr [eep] != OROR) return 0;
397 ++eep;
398 Arr [0] = 1;
399 continue;
401 if (eval_expr [eep] == OROR && Arr [1] != 0) {
402 for (++eep; eval_expr [eep] != ')' && eval_expr [eep] != -1; eep++)
403 if (eep == '(')
404 eep = skip_buffer_parenthesis (eval_expr, eep + 1) - 1;
405 return 1;
408 Arr [++Arr [0]] = eval_expr [eep++];
409 ++Arr [0];
413 static long long int cpp_expression ()
415 static bool expectcond;
417 long long int rez = cpp_expressionr ();
418 switch (eval_expr [eep]) {
419 case ')': ++eep; break;
420 case '?': {
421 ++eep;
422 SAVE_VAR (expectcond, true);
423 long long int r1 = cpp_expression ();
424 RESTOR_VAR (expectcond);
425 rez = rez ? r1 : cpp_expression ();
426 } break;
427 case ':': if (expectcond) ++eep;
428 else parse_error_cpp ("':' without '?'");
429 ndefault: if (expectcond) parse_error_cpp ("missing ':'");
431 return rez;
434 static bool cpp_condition ()
436 bool r;
437 eval_expr = get_expanded_line ();
438 #ifdef DEBUG
439 if (debugflag.CPP) {
440 PRINTF ("Conditional expression :");
441 INTPRINT (eval_expr);
442 PRINTF ("\n");
444 #endif
445 eep = 0;
446 r = cpp_expression () != 0;
447 free (eval_expr);
448 return r;
451 /******************************************************************************
452 Conditional compilation
453 don't try this at home....
454 ******************************************************************************/
455 static int conditional_pp;
457 static void skip_to_endif (bool checkelse)
459 Token t;
461 for (;;) {
462 t = do_yylex ();
464 if (t != CPP_DIRECTIVE) {
465 skip_pp_line ();
466 if (Ci >= Clen)
467 parse_error_cpp ("#if without endif");
468 continue;
471 t = do_yylex ();
473 if (t == RESERVED_endif) break;
475 if (t == RESERVED_if || t == RESERVED_ifdef || t == RESERVED_ifndef) {
476 skip_to_endif (false);
477 continue;
480 if (!checkelse) continue;
481 if (t == RESERVED_else) {
482 skip_pp_line ();
483 ++conditional_pp;
484 return;
487 if (t == RESERVED_elif)
488 if (cpp_condition ()) {
489 ++conditional_pp;
490 return;
495 static bool ifdef ()
497 Token m = do_yylex ();
498 return is_macro (m) != -1;
501 /******************************************************************************
502 Miscellanery
503 ******************************************************************************/
504 static void cpp_error ()
506 int ii = Ci;
507 skip_pp_line ();
508 Ci -= ii;
509 char *msg = (char*) alloca (2 + Ci);
510 strncpy (msg, Cpp + ii, Ci);
511 msg [Ci] = 0;
512 fprintf (stderr, "ERROR: %s\n", msg);
513 exit (1);
516 /******************************************************************************
518 Process a preprocessing line directive
520 ******************************************************************************/
522 void cpp_directive ()
524 if (skip_ws ()) return;
526 Token t = do_yylex ();
528 switch (t) {
529 case RESERVED_include:
530 case RESERVED_uses:
531 include (t == RESERVED_uses);
532 ncase RESERVED_define:
533 define ();
534 ncase RESERVED_undef:
535 undef ();
536 ncase RESERVED_ifdef:
537 if (ifdef ()) ++conditional_pp;
538 else skip_to_endif (true);
539 ncase RESERVED_ifndef:
540 if (!ifdef ()) ++conditional_pp;
541 else skip_to_endif (true);
542 ncase RESERVED_else:
543 if (!conditional_pp)
544 parse_error_cpp ("#else not in conditional");
545 --conditional_pp;
546 skip_to_endif (false);
547 ncase RESERVED_endif:
548 if (!conditional_pp)
549 parse_error_cpp ("#endif without #startif");
550 --conditional_pp;
551 skip_pp_line ();
552 ncase RESERVED_if:
553 if (!cpp_condition ()) skip_to_endif (true);
554 else ++conditional_pp;
555 ncase RESERVED_elif:
556 if (!conditional_pp) parse_error_cpp ("#elif without #if");
557 --conditional_pp;
558 skip_to_endif (false);
559 ncase RESERVED_error:
560 cpp_error ();
561 ncase RESERVED_line:
562 ndefault:
563 skip_pp_line ();
564 // PRINTF ("not implemented\n");
568 void setup_cpp (int argc, char **argv)
570 int i, j, id;
571 char *Idir [128];
573 for (id = i = 0; i < argc; i++)
574 if (argv [i][0] == '-')
575 switch (argv [i][1]) {
576 case 'I':
577 Idir [id++] = argv [i][2] == 0 ? argv [++i] : argv [i] + 2;
580 i = 1 + id + sizeof search_dirs / sizeof search_dirs [0];
581 hsearch = (char**) malloc (i * sizeof *hsearch);
582 hsearch [0] = "";
583 for (i = 1, j = 0; j < id; j++)
584 hsearch [i++] = strdup (Idir [j]);
585 for (j = 0; search_dirs [j]; j++)
586 hsearch [i++] = (char*) search_dirs [j];
587 hsearch [i] = 0;
588 isearch = hsearch + 1;
591 static void freeintnode (intnode *n)
593 if (n->less) freeintnode (n->less);
594 if (n->more) freeintnode (n->more);
595 free (n);
598 static void freemacronode (intnode *n)
600 if (n->less) freeintnode (n->less);
601 if (n->more) freeintnode (n->more);
602 free (((macro*)n->v.p)->body);
603 free (n);
606 void cleanup_cpp ()
608 free (hsearch);
609 if (included) freeintnode (included);
610 if (macrotree) freemacronode (macrotree);
613 /************************************************************************
615 Macro expansions
617 We deviate from the standard which sais that ``macro arguments are
618 expanded *before* the macro expansion unless they're followed by
619 '#' or '##' and then there is a second rescan to reexpand'' doh
621 ************************************************************************/
623 static Token *expand_predef (Token m)
625 static Token timetok;
626 char tmp [129];
627 Token *ret = mallocint (2);
628 ret [1] = -1;
630 switch (m) {
631 case RESERVED___LINE__:
632 sprintf (tmp, "%i", line);
633 ret [0] = enter_value (tmp);
634 ncase RESERVED___FILE__:
635 sprintf (tmp, "\"%s\"", tfile);
636 ret [0] = enter_string (tmp);
637 ncase RESERVED___TIME__:
638 case RESERVED___DATE__:
639 if (!timetok) {
640 time_t t = time (0);
641 sprintf (tmp, "\"%s", ctime (&t));
642 *(strchr (tmp, '\n')) = '"';
643 timetok = enter_string (tmp);
644 if (strstr (tmp, "Jan 1 "))
645 fputs ("Happy new year!\n", stderr);
647 ret [0] = timetok;
649 return ret;
652 static Token stringize (Token arg [])
654 char *tmp, *s;
655 int l, i, j;
657 for (l = 0, i = 4; arg [l] != -1; l++) {
658 i += strlen (s = expand (arg [l])) + 1;
659 for (j = 0; s [j]; j++)
660 if (s [j] == '\\'
661 || s [j] == '"') i++;
664 tmp = (char*) malloc (i);
665 tmp [0] = '"';
666 for (l = 0, i = 1; arg [l] != -1; l++) {
667 s = expand (arg [l]);
668 while (*s) {
669 if (*s == '\\' || *s == '"')
670 tmp [i++] = '\\';
671 tmp [i++] = *s++;
673 if (arg [l + 1] != -1) tmp [i++] = ' ';
675 tmp [i++] = '"';
676 tmp [i] = 0;
678 return enter_string (tmp);
681 static Token concat (OUTSTREAM S, Token a1[], Token a2[])
683 int i, l;
684 Token con, t;
686 if (a1 [i = 0] != -1)
687 while (a1 [i + 1] != -1)
688 output_itoken (S, a1 [i++]);
690 if (a2 [0] == -1) return a1 [i];
693 # define EXPAND(x) expand (x == -1 ? BLANKT : x)
694 char *tmp;
695 tmp = strcat (strcpy (
696 (char*) malloc (l = strlen (EXPAND (a1 [i])) + strlen (EXPAND (a2 [0])) + 1),
697 EXPAND (a1 [i])), EXPAND (a2 [0]));
699 if ((ISIDENT (a1 [i]) || a1 [i] == -1)
700 && (ISIDENT (a2 [0]) || a2 [0] == -1))
701 con = enter_symbol (tmp);
702 else {
703 SAVE_VAR (Cpp, tmp);
704 SAVE_VAR (Ci, 0);
705 SAVE_VAR (Clen, l - 1);
706 con = 0;
707 while ((t = do_yylex ()) != THE_END) {
708 if (con) output_itoken (S, con);
709 con = t;
711 RESTOR_VAR (Cpp);
712 RESTOR_VAR (Ci);
713 RESTOR_VAR (Clen);
717 if (a2 [1] == -1) return con;
719 output_itoken (S, con);
720 for (i = 1; a2 [i + 1] != -1; i++)
721 output_itoken (S, a2 [i]);
723 return a2 [i];
726 static Token *expanding, *tops;
727 static Token *expand_macro_arglist (Token, int, Token*);
729 static Token *expand_macro_argv (Token m, Token **argv)
731 Token *B = ((macro*) intfind (macrotree, m)->v.p)->body;
732 Token a1 [] = { 0, -1 }, a2 [] = { 0, -1 }, *a1p, *a2p, b;
733 int i, n;
734 OUTSTREAM S = new_stream ();
736 /* stringnify and concatenate */
737 for (;(b = *B++) != -1;) {
738 if (b == '#') {
739 b = *B++;
740 if (!ISTPLARG (b))
741 parse_error_cpp ("'#' not followed by macro argument");
742 output_itoken (S, stringize (argv [b - ARGBASE]));
743 continue;
745 if (*B == CPP_CONCAT) {
746 while (*B == CPP_CONCAT) {
747 if (!ISTPLARG (b)) a1 [0] = b;
748 a1p = ISTPLARG (b) ? argv [b - ARGBASE] : a1;
749 b = B [1];
750 if (b == -1) parse_error_cpp ("'##' is last");
751 if (!ISTPLARG (b)) a2 [0] = b;
752 a2p = ISTPLARG (b) ? argv [b - ARGBASE] : a2;
753 b = concat (S, a1p, a2p);
754 B += 2;
756 output_itoken (S, b);
757 continue;
759 if (ISTPLARG (b))
760 outprintf (S, ISTR (argv [b - ARGBASE]), -1);
761 else output_itoken (S, b);
764 B = combine_output (S);
765 for (i = 0; B [i] != -1; i++)
766 if (is_macro (B [i]) != -1)
767 goto further_expands;
768 return B;
770 further_expands:
772 /* macro contains further macros, non-recusrive */
773 *tops++ = m;
774 *tops = -1;
776 S = new_stream ();
777 for (i = 0; B [i] != -1; i++)
778 if ((n = is_macro (B [i])) == -1) noexpand:
779 output_itoken (S, B [i]);
780 else {
781 Token m, *E;
783 m = B [i];
784 for (E = expanding; *E != -1; E++)
785 if (*E == m)
786 goto noexpand;
788 if (ISPREDEF (m))
789 E = expand_predef (m);
790 else if (n == 0)
791 E = expand_macro_argv (m, 0);
792 else {
793 if (B [++i] != '(') parse_error_cpp ("No arguments to macro");
794 E = expand_macro_arglist (m, n, &B [++i]);
795 i = skip_buffer_parenthesis (B, i) - 1;
797 outprintf (S, ISTR (E), -1);
798 free (E);
801 *--tops = -1;
802 free (B);
803 return combine_output (S);
806 static Token *expand_macro_arglist (Token m, int argn, Token *s)
808 int argc, i;
809 Token **parg;
810 NormPtr pstart, pend;
812 for (i = 0, argc = 2; s [i] != ')'; i++)
813 if (s [i] == ',') ++argc;
814 parg = (Token**) alloca (argc * sizeof (Token*));
816 pstart = 0, argc = 0;
817 for (;;) {
818 pend = pstart;
819 while (s [pend] != ',' && s [pend] != ')')
820 if (s [pend] == '(')
821 pend = skip_buffer_parenthesis (s, pend + 1);
822 else if (s [pend] == -1)
823 parse_error_cpp ("Incomplete macro call");
824 else ++pend;
825 parg [argc] = allocaint (2 + pend - pstart);
826 intextract (parg [argc++], s + pstart, pend - pstart);
827 if (s [pend] == ')') break;
828 pstart = pend + 1;
830 parg [argc] = 0;
832 if (argc != argn)
833 if (argn < VOIDARG || argn == VOIDARG && argc != 1
834 || (argn >= VARBOOST && argn - VARBOOST > argc))
835 parse_error_cpp ("Argument number mismatch");
837 if (argn >= VARBOOST) {
838 int i, l;
839 int j = argn - VARBOOST;
840 Token *varg;
841 for (i = j, l = 10; parg [i]; i++)
842 l += intlen (parg [i]) + 1;
843 varg = allocaint (l);
844 varg [0] = -1;
845 for (i = j; parg [i]; i++) {
846 intcat (varg, parg [i]);
847 if (parg [i + 1]) intcatc (varg, ',');
849 parg [j] = varg;
850 parg [j + 1] = 0;
853 return expand_macro_argv (m, parg);
856 Token *expand_macro (Token m)
858 #ifdef DEBUG
859 if (0&&debugflag.CPP)
860 PRINTF ("expanding macro "COLS"%s"COLE"\n", expand (m));
861 #endif
862 if (ISPREDEF (m))
863 return expand_predef (m);
865 Token rarray [64];
866 tops = expanding = rarray;
867 int argn = is_macro (m);
869 if (!argn) return expand_macro_argv (m, 0);
871 if (do_yylex () != '(') parse_error_cpp ("No arguments to macro");
873 Token arglist [256], t;
874 int i = 0;
876 while ((arglist [i++] = t = do_yylex ()) != ')')
877 switch (t) {
878 case THE_END: parse_error_cpp ("Incomplete arglist");
879 case '(': {
880 int po = 1;
881 while (po) switch (t = arglist [i++] = do_yylex ()) {
882 case '(': ++po;
883 ncase ')': --po;
884 ncase THE_END: parse_error_cpp ("Incomplete arglist");
888 arglist [i] = -1;
889 return expand_macro_arglist (m, argn, arglist);
891 #endif