对于我们的案例,这下一个符号是“FUN”。对于这个节点,它的类型无疑是NT_MACRO。只要它不是失能的宏,并且不是在禁止宏展开的环境下(即,在处理断言、pragma、#if系列指示,解析宏参数、函数式的宏调用),enter_macro_context将被调用。
709 static int
710 enter_macro_context (cpp_reader *pfile, cpp_hashnode *node) in cppmacro.c
711 {
712 /* The presence of a macro invalidates a file's controlling macro. */
713 pfile->mi_valid = false;
714
715 pfile->state.angled_headers = false;
716
717 /* Handle standard macros. */
718 if (! (node->flags & NODE_BUILTIN))
719 {
720 cpp_macro *macro = node->value.macro;
721
722 if (macro->fun_like)
723 {
724 _cpp_buff *buff;
725
726 pfile->state.prevent_expansion++;
727 pfile->keep_tokens++;
728 pfile->state.parsing_args = 1;
729 buff = funlike_invocation_p (pfile, node);
730 pfile->state.parsing_args = 0;
731 pfile->keep_tokens--;
732 pfile->state.prevent_expansion--;
733
734 if (buff == NULL)
735 {
736 if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr)
737 cpp_error (pfile, CPP_DL_WARNING,
738 "function-like macro /"%s/" must be used with arguments in traditional C",
739 NODE_NAME (node));
740
741 return 0;
742 }
743
744 if (macro->paramc > 0)
745 replace_args (pfile, node, macro, (macro_arg *) buff->base);
746 _cpp_release_buff (pfile, buff);
747 }
748
749 /* Disable the macro within its expansion. */
750 node->flags |= NODE_DISABLED;
751
752 macro->used = 1;
753
754 if (macro->paramc == 0)
755 push_token_context (pfile, node, macro->exp.tokens, macro->count);
756
757 return 1;
758 }
759
760 /* Handle built-in macros and the _Pragma operator. */
761 return builtin_macro (pfile, node);
762 }
注意在729行对funlike_invocation_p调用前后,对pfile的设置。
对于非内建宏,它需要设立上下文来进行宏的扩展。在720行,回忆整个宏的定义保存在宏的标识符节点的macro域中(参考create_iso_definition)。对于非函数形式的宏,把这部分符号放入一个新的上下文就可以了,如上面的755行。但对于还是形式的宏,它还需要进行宏的实参替换,这个上下文在实参替换中给出。注意在728行,域parsing_args在调用funlik_invocation_p前,设为1,之后重置为0。
669 static _cpp_buff *
670 funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node) in cppmacro.c
671 {
672 const cpp_token *token, *padding = NULL;
673
674 for (;;)
675 {
676 token = cpp_get_token (pfile);
677 if (token->type != CPP_PADDING)
678 break;
679 if (padding == NULL
680 || (!(padding->flags & PREV_WHITE) && token->val.source == NULL))
681 padding = token;
682 }
683
684 if (token->type == CPP_OPEN_PAREN)
685 {
686 pfile->state.parsing_args = 2;
687 return collect_args (pfile, node);
688 }
689
690 /* CPP_EOF can be the end of macro arguments, or the end of the
691 file. We mustn't back up over the latter. Ugh. */
692 if (token->type != CPP_EOF || token == &pfile->eof)
693 {
694 /* Back up. We may have skipped padding, in which case backing
695 up more than one token when expanding macros is in general
696 too difficult. We re-insert it in its own context. */
697 _cpp_backup_tokens (pfile, 1);
698 if (padding)
699 push_token_context (pfile, NULL, padding, 1);
700 }
701
702 return NULL;
703 }
例程collect_args收集宏调用时的实参。这些实参被保存,随后用于实参替换。注意到在进入该函数前,域parsing_args被设为2——已找到左括号。
535 static _cpp_buff *
536 collect_args (cpp_reader *pfile, const cpp_hashnode *node) in cppmacro.c
537 {
538 _cpp_buff *buff, *base_buff;
539 cpp_macro *macro;
540 macro_arg *args, *arg;
541 const cpp_token *token;
542 unsigned int argc;
543
544 macro = node->value.macro;
545 if (macro->paramc)
546 argc = macro->paramc;
547 else
548 argc = 1;
549 buff = _cpp_get_buff (pfile, argc * (50 * sizeof (cpp_token *)
550 + sizeof (macro_arg)));
551 base_buff = buff;
552 args = (macro_arg *) buff->base;
553 memset (args, 0, argc * sizeof (macro_arg));
554 buff->cur = (unsigned char *) &args[argc];
555 arg = args, argc = 0;
cpp_macro的paramc域记录了宏参数的个数。类型macro_arg被设计用来保存用于实参替换的必要信息。
32 struct macro_arg in cppmacro.c
33 {
34 const cpp_token **first; /* First token in unexpanded argument. */
35 const cpp_token **expanded; /* Macro-expanded argument. */
36 const cpp_token *stringified; /* Stringified argument. */
37 unsigned int count; /* # of tokens in argument. */
38 unsigned int expanded_count; /* # of tokens in expanded argument. */
39 };
下面,在578行,看到cpp_get_token被调用提取实参的符号。对于我们的案例,指示#ifdef将被作为第三个符号读入,根据[12]这样的指示的行为标准没有定义,不过GCC决定让这些指示的行为如常——也就是调用_cpp_handle_directive。注意,在解析参数的过程中, 如果实参是一个宏,标准要求它被禁止展开(但在实参替换时展开)。
collect_args (continue)
557 /* Collect the tokens making up each argument. We don't yet know
558 how many arguments have been supplied, whether too many or too
559 few. Hence the slightly bizarre usage of "argc" and "arg". */
560 do
561 {
562 unsigned int paren_depth = 0;
563 unsigned int ntokens = 0;
564
565 argc++;
566 arg->first = (const cpp_token **) buff->cur;
567
568 for (;;)
569 {
570 /* Require space for 2 new tokens (including a CPP_EOF). */
571 if ((unsigned char *) &arg->first[ntokens + 2] > buff->limit)
572 {
573 buff = _cpp_append_extend_buff (pfile, buff,
574 1000 * sizeof (cpp_token *));
575 arg->first = (const cpp_token **) buff->cur;
576 }
577
578 token = cpp_get_token (pfile);
579
580 if (token->type == CPP_PADDING)
581 {
582 /* Drop leading padding. */
583 if (ntokens == 0)
584 continue;
585 }
586 else if (token->type == CPP_OPEN_PAREN)
587 paren_depth++;
588 else if (token->type == CPP_CLOSE_PAREN)
589 {
590 if (paren_depth-- == 0)
591 break;
592 }
593 else if (token->type == CPP_COMMA)
594 {
595 /* A comma does not terminate an argument within
596 parentheses or as part of a variable argument. */
597 if (paren_depth == 0
598 && ! (macro->variadic && argc == macro->paramc))
599 break;
600 }
601 else if (token->type == CPP_EOF
602 || (token->type == CPP_HASH && token->flags & BOL))
603 break;
604
605 arg->first[ntokens++] = token;
606 }
607
608 /* Drop trailing padding. */
609 while (ntokens > 0 && arg->first[ntokens - 1]->type == CPP_PADDING)
610 ntokens--;
611
612 arg->count = ntokens;
613 arg->first[ntokens] = &pfile->eof;
614
615 /* Terminate the argument. Excess arguments loop back and
616 overwrite the final legitimate argument, before failing. */
617 if (argc <= macro->paramc)
618 {
619 buff->cur = (unsigned char *) &arg->first[ntokens + 1];
620 if (argc != macro->paramc)
621 arg++;
622 }
623 }
624 while (token->type != CPP_CLOSE_PAREN && token->type != CPP_EOF);
注意到虽然实参由逗号分隔,但ISO标准允许在逗号两边插入任意的空白符,因而使用嵌套的循环来处理这个情形。内层的FOR循环取出可能带有拖尾空白符的参数(注意空白符也是符号),然后609行的while循环剥除这些空白符,只留下参数符号。
collect_args (continue)
626 if (token->type == CPP_EOF)
627 {
628 /* We still need the CPP_EOF to end directives, and to end
629 pre-expansion of a macro argument. Step back is not
630 unconditional, since we don't want to return a CPP_EOF to our
631 callers at the end of an -include-d file. */
632 if (pfile->context->prev || pfile->state.in_directive)
633 _cpp_backup_tokens (pfile, 1);
634 cpp_error (pfile, CPP_DL_ERROR,
635 "unterminated argument list invoking macro /"%s/"",
636 NODE_NAME (node));
637 }
638 else
639 {
640 /* A single empty argument is counted as no argument. */
641 if (argc == 1 && macro->paramc == 0 && args[0].count == 0)
642 argc = 0;
643 if (_cpp_arguments_ok (pfile, macro, node, argc))
644 {
645 /* GCC has special semantics for , ## b where b is a varargs
646 parameter: we remove the comma if b was omitted entirely.
647 If b was merely an empty argument, the comma is retained.
648 If the macro takes just one (varargs) parameter, then we
649 retain the comma only if we are standards conforming.
650
651 If FIRST is NULL replace_args () swallows the comma. */
652 if (macro->variadic && (argc < macro->paramc
653 || (argc == 1 && args[0].count == 0
654 && !CPP_OPTION (pfile, std))))
655 args[macro->paramc - 1].first = NULL;
656 return base_buff;
657 }
658 }
659
660 /* An error occurred. */
661 _cpp_release_buff (pfile, base_buff);
662 return NULL;
663 }
在找到右括号前,碰到文件结尾是一种异常的情况。否则右括号将结束符号的提取,实参接下来需要验证有效性。
494 bool
495 _cpp_arguments_ok(cpp_reader *pfile, cpp_macro *macro, const cpp_hashnode *node, unsigned int argc)
496 {
497 if (argc == macro->paramc)
498 return true;
499
500 if (argc < macro->paramc)
501 {
502 /* As an extension, a rest argument is allowed to not appear in
503 the invocation at all.
504 e.g. #define debug(format, args...) something
505 debug("string");
506
507 This is exactly the same as if there had been an empty rest
508 argument - debug("string", ). */
509
510 if (argc + 1 == macro->paramc && macro->variadic)
511 {
512 if (CPP_PEDANTIC (pfile) && ! macro->syshdr)
513 cpp_error (pfile, CPP_DL_PEDWARN,
514 "ISO C99 requires rest arguments to be used");
515 return true;
516 }
517
518 cpp_error (pfile, CPP_DL_ERROR,
519 "macro /"%s/" requires %u arguments, but only %u given",
520 NODE_NAME (node), macro->paramc, argc);
521 }
522 else
523 cpp_error (pfile, CPP_DL_ERROR,
524 "macro /"%s/" passed %u arguments, but takes just %u",
525 NODE_NAME (node), argc, macro->paramc);
526
527 return false;
528 }
这个有效性验证仅考虑实参数目的准确性。
在收集了实参之后,在enter_macro_context的745行,这些实参将由replace_args来替换定义中的形参。
768 static void
769 replace_args(cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg *args)
770 {
771 unsigned int i, total;
772 const cpp_token *src, *limit;
773 const cpp_token **dest, **first;
774 macro_arg *arg;
775 _cpp_buff *buff;
776
777 /* First, fully macro-expand arguments, calculating the number of
778 tokens in the final expansion as we go. The ordering of the if
779 statements below is subtle; we must handle stringification before
780 pasting. */
781 total = macro->count;
782 limit = macro->exp.tokens + macro->count;
783
784 for (src = macro->exp.tokens; src < limit; src++)
785 if (src->type == CPP_MACRO_ARG)
786 {
787 /* Leading and trailing padding tokens. */
788 total += 2;
789
790 /* We have an argument. If it is not being stringified or
791 pasted it is macro-replaced before insertion. */
792 arg = &args[src->val.arg_no - 1];
793
794 if (src->flags & STRINGIFY_ARG)
795 {
796 if (!arg->stringified)
797 arg->stringified = stringify_arg (pfile, arg);
798 }
799 else if ((src->flags & PASTE_LEFT)
800 || (src > macro->exp.tokens && (src[-1].flags & PASTE_LEFT)))
801 total += arg->count - 1;
802 else
803 {
804 if (!arg->expanded)
805 expand_arg (pfile, arg);
806 total += arg->expanded_count - 1;
807 }
808 }
在781行,域count记录了定义中的符号数,但实参替换后,这个数字可能就不准确了。在784行开始的FOR循环更新这个数字。对于定义体中所出现的形参,它们具有类型CPP_MACRO_ARG。
根据ISO C/C++标准,跟在#(字符串化操作符)后的符号,及##(粘贴操作符)两边的符号,就算是宏,也不能展开。对于字符串化的情况,#操作符只能后跟一个符号,因此符号数没有变化。对于符号粘贴的情况,事实上,我们可以把一个表达式作为一个实参传入,例如:
#define fA(A, B) c = A##B;
fA (a+b, B) // output a+bB;
显然增加的符号数是构成实参符号的数目减去1。而对于剩下的情况,作为宏的实参应该被正常地展开。
979 static void
980 expand_arg (cpp_reader *pfile, macro_arg *arg) in cppmacro.c
981 {
982 unsigned int capacity;
983 bool saved_warn_trad;
984
985 if (arg->count == 0)
986 return;
987
988 /* Don't warn about funlike macros when pre-expanding. */
989 saved_warn_trad = CPP_WTRADITIONAL (pfile);
990 CPP_WTRADITIONAL (pfile) = 0;
991
992 /* Loop, reading in the arguments. */
993 capacity = 256;
994 arg->expanded = xmalloc (capacity * sizeof (cpp_token *));
995
996 push_ptoken_context (pfile, NULL, NULL, arg->first, arg->count + 1);
997 for (;;)
998 {
999 const cpp_token *token;
1000
1001 if (arg->expanded_count + 1 >= capacity)
1002 {
1003 capacity *= 2;
1004 arg->expanded = xrealloc (arg->expanded,
1005 capacity * sizeof (cpp_token *));
1006 }
1007
1008 token = cpp_get_token (pfile);
1009
1010 if (token->type == CPP_EOF)
1011 break;
1012
1013 arg->expanded[arg->expanded_count++] = token;
1014 }
1015
1016 _cpp_pop_context (pfile);
1017
1018 CPP_WTRADITIONAL (pfile) = saved_warn_trad;
1019 }
为了正确解析任意的嵌套的宏,需要由push_ptoken_context设立新的上下文。
931 static void
932 push_ptoken_context (cpp_reader *pfile, cpp_hashnode *macro, in cppmacro.c
933 _cpp_buff *buff, const cpp_token **first, unsigned int count)
934 {
935 cpp_context *context = next_context (pfile);
936
937 context->direct_p = false;
938 context->macro = macro;
939 context->buff = buff;
940 FIRST (context).ptoken = first;
941 LAST (context).ptoken = first + count;
942 }
设立了这个上下文后,在expand_arg的1008行,cpp_get_token 将从这个上下文提取符号。如果实参也是宏,在1099行,enter_macro_context被再一次调用。从调用的次序,可以看到,嵌套的宏的处理是深度优先的,因此当在1011行退出FOR循环时,所有的嵌套其中的宏都应该得到处理。注意对于这个展开后的实参,所产生的符号保存在对应的macro_arg对象的expanded域。
replace_args (continue)
810 /* Now allocate space for the expansion, copy the tokens and replace
811 the arguments. */
812 buff = _cpp_get_buff (pfile, total * sizeof (cpp_token *));
813 first = (const cpp_token **) buff->base;
814 dest = first;
815
816 for (src = macro->exp.tokens; src < limit; src++)
817 {
818 unsigned int count;
819 const cpp_token **from, **paste_flag;
820
821 if (src->type != CPP_MACRO_ARG)
822 {
823 *dest++ = src;
824 continue;
825 }
826
827 paste_flag = 0;
828 arg = &args[src->val.arg_no - 1];
829 if (src->flags & STRINGIFY_ARG)
830 count = 1, from = &arg->stringified;
831 else if (src->flags & PASTE_LEFT)
832 count = arg->count, from = arg->first;
833 else if (src != macro->exp.tokens && (src[-1].flags & PASTE_LEFT))
834 {
835 count = arg->count, from = arg->first;
836 if (dest != first)
837 {
838 if (dest[-1]->type == CPP_COMMA
839 && macro->variadic
840 && src->val.arg_no == macro->paramc)
841 {
842 /* Swallow a pasted comma if from == NULL, otherwise
843 drop the paste flag. */
844 if (from == NULL)
845 dest--;
846 else
847 paste_flag = dest - 1;
848 }
849 /* Remove the paste flag if the RHS is a placemarker. */
850 else if (count == 0)
851 paste_flag = dest - 1;
852 }
853 }
854 else
855 count = arg->expanded_count, from = arg->expanded;
856
857 /* Padding on the left of an argument (unless RHS of ##). */
858 if ((!pfile->state.in_directive || pfile->state.directive_wants_padding)
859 && src != macro->exp.tokens && !(src[-1].flags & PASTE_LEFT))
860 *dest++ = padding_token (pfile, src);
861
862 if (count)
863 {
864 memcpy (dest, from, count * sizeof (cpp_token *));
865 dest += count;
866
867 /* With a non-empty argument on the LHS of ##, the last
868 token should be flagged PASTE_LEFT. */
869 if (src->flags & PASTE_LEFT)
870 paste_flag = dest - 1;
871 }
872
873 /* Avoid paste on RHS (even case count == 0). */
874 if (!pfile->state.in_directive && !(src->flags & PASTE_LEFT))
875 *dest++ = &pfile->avoid_paste;
876
877 /* Add a new paste flag, or remove an unwanted one. */
878 if (paste_flag)
879 {
880 cpp_token *token = _cpp_temp_token (pfile);
881 token->type = (*paste_flag)->type;
882 token->val.str = (*paste_flag)->val.str;
883 if (src->flags & PASTE_LEFT)
884 token->flags = (*paste_flag)->flags | PASTE_LEFT;
885 else
886 token->flags = (*paste_flag)->flags & ~PASTE_LEFT;
887 *paste_flag = token;
888 }
889 }
890
891 /* Free the expanded arguments. */
892 for (i = 0; i < macro->paramc; i++)
893 if (args[i].expanded)
894 free (args[i].expanded);
895
896 push_ptoken_context (pfile, node, buff, first, dest - first);
897 }
因为用于展开宏的空间已经被计算了,那么创建这个尺寸的缓存用于保存展开宏的符号。因为有可能将由多个符号组成的符号序列作为实参(如上例的表达式),对于符号粘贴操作,需要将序列中第一个符号(在##右边),或最后的符号(在##左边)标记为PASTE_LEFT。在896行,又一个新的上下文被创建,使得这些符号成为下一个提前的候选。
对于符号粘贴的情况,在cpp_get_token的1071行,将调用paste_all_tokens。
448 static void
449 paste_all_tokens (cpp_reader *pfile, const cpp_token *lhs) in cppmacro.c
450 {
451 const cpp_token *rhs;
452 cpp_context *context = pfile->context;
453
454 do
455 {
456 /* Take the token directly from the current context. We can do
457 this, because we are in the replacement list of either an
458 object-like macro, or a function-like macro with arguments
459 inserted. In either case, the constraints to #define
460 guarantee we have at least one more token. */
461 if (context->direct_p)
462 rhs = FIRST (context).token++;
463 else
464 rhs = *FIRST (context).ptoken++;
465
466 if (rhs->type == CPP_PADDING)
467 abort ();
468
469 if (!paste_tokens (pfile, &lhs, rhs))
470 {
471 _cpp_backup_tokens (pfile, 1);
472
473 /* Mandatory error for all apart from assembler. */
474 if (CPP_OPTION (pfile, lang) != CLK_ASM)
475 cpp_error (pfile, CPP_DL_ERROR,
476 "pasting /"%s/" and /"%s/" does not give a valid preprocessing token",
477 cpp_token_as_text (pfile, lhs),
478 cpp_token_as_text (pfile, rhs));
479 break;
480 }
481 }
482 while (rhs->flags & PASTE_LEFT);
483
484 /* Put the resulting token in its own context. */
485 push_token_context (pfile, NULL, lhs, 1);
486 }
注意在424行,只有‘/’及‘=’可以被粘贴起来产生‘/=’操作符,其他‘/’及非‘=’对需要在中间插入空白符。而下面433行,_cpp_temp_token创建了一个新的可用符号,其行号、列号从file的cur_token拷贝(即被粘贴的符号)。这样确保诊断系统能给出准确的诊断信息。
407 static bool
408 paste_tokens (cpp_reader *pfile, const cpp_token **plhs, const cpp_token *rhs)
409 {
410 unsigned char *buf, *end;
411 const cpp_token *lhs;
412 unsigned int len;
413 bool valid;
414
415 lhs = *plhs;
416 len = cpp_token_len (lhs) + cpp_token_len (rhs) + 1;
417 buf = alloca (len);
418 end = cpp_spell_token (pfile, lhs, buf);
419
420 /* Avoid comment headers, since they are still processed in stage 3.
421 It is simpler to insert a space here, rather than modifying the
422 lexer to ignore comments in some circumstances. Simply returning
423 false doesn't work, since we want to clear the PASTE_LEFT flag. */
424 if (lhs->type == CPP_DIV && rhs->type != CPP_EQ)
425 *end++ = ' ';
426 end = cpp_spell_token (pfile, rhs, end);
427 *end = '/n';
428
429 cpp_push_buffer (pfile, buf, end - buf, /* from_stage3 */ true);
430 _cpp_clean_line (pfile);
431
432 /* Set pfile->cur_token as required by _cpp_lex_direct. */
433 pfile->cur_token = _cpp_temp_token (pfile);
434 *plhs = _cpp_lex_direct (pfile);
435 valid = pfile->buffer->cur == pfile->buffer->rlimit;
436 _cpp_pop_buffer (pfile);
437
438 return valid;
439 }
在上面的429行,串接起来的名字被加入file的buffer域, 然后_cpp_lex_direct将这个串接名字作为符号提前出来,并赋给plhs。同样看到当返回到paste_all_tokens后,在485行,这个符号被2放入一个新的上下文,它在下一次调用cpp_get_token 时被提取出来。
在离开这一节前,我们看一下_cpp_lex_token里,lookahead域中的符号是从那里来的。它们来自在基本上下文中回退一个或多个符号时。
1153 void
1154 _cpp_backup_tokens (cpp_reader *pfile, unsigned int count) in cppmacro.c
1155 {
1156 if (pfile->context->prev == NULL)
1157 {
1158 pfile->lookaheads += count;
1159 while (count--)
1160 {
1161 pfile->cur_token--;
1162 if (pfile->cur_token == pfile->cur_run->base
1163 /* Possible with -fpreprocessed and no leading #line. */
1164 && pfile->cur_run->prev != NULL)
1165 {
1166 pfile->cur_run = pfile->cur_run->prev;
1167 pfile->cur_token = pfile->cur_run->limit;
1168 }
1169 }
1170 }
1171 else
1172 {
1173 if (count != 1)
1174 abort ();
1175 if (pfile->context->direct_p)
1176 FIRST (pfile->context).token--;
1177 else
1178 FIRST (pfile->context).ptoken--;
1179 }
1180 }
在enter_macro_context的末尾,注意到在750行,现在宏的标识符节点被标记为禁止扩展。这意味着在随后的读入中,如果在扩展体内发现了宏,它将被按普通标识符来处理。它避免了宏调用自己而导致无限递归,从而弄垮编译器。
而当这个宏展开后的上下文被读取完成后,在移除时,这个宏将重新被激活。
1024 void
1025 _cpp_pop_context (cpp_reader *pfile) in cppmacro.c
1026 {
1027 cpp_context *context = pfile->context;
1028
1029 if (context->macro)
1030 context->macro->flags &= ~NODE_DISABLED;
1031
1032 if (context->buff)
1033 _cpp_release_buff (pfile, context->buff);
1034
1035 pfile->context = context->prev;
1036 }