Mercurial > hg > index.cgi
comparison lwcc/preproc.c @ 299:856caf91ffaa ccdev
Added token list structure and switched some stuff to use it
Swithced to using a token list structure instead of manually fiddling
pointers throughout the macro expansion code. Also fixed up some problematic
things related to stringification and concatenation.
author | William Astle <lost@l-w.ca> |
---|---|
date | Sun, 15 Sep 2013 13:06:00 -0600 |
parents | 6112c67728ba |
children | 8d6c47395653 |
comparison
equal
deleted
inserted
replaced
298:6112c67728ba | 299:856caf91ffaa |
---|---|
252 check_eol(pp); | 252 check_eol(pp); |
253 } | 253 } |
254 | 254 |
255 static void dir_define(struct preproc_info *pp) | 255 static void dir_define(struct preproc_info *pp) |
256 { | 256 { |
257 struct token *tl = NULL; | 257 struct token_list *tl = NULL; |
258 struct token *ttl; | |
259 struct token *ct; | 258 struct token *ct; |
260 int nargs = -1; | 259 int nargs = -1; |
261 int vargs = 0; | 260 int vargs = 0; |
262 char *mname = NULL; | 261 char *mname = NULL; |
263 | 262 |
333 else | 332 else |
334 { | 333 { |
335 baddefine: | 334 baddefine: |
336 preproc_throw_error(pp, "bad #define"); | 335 preproc_throw_error(pp, "bad #define"); |
337 baddefine2: | 336 baddefine2: |
337 token_list_destroy(tl); | |
338 skip_eol(pp); | 338 skip_eol(pp); |
339 lw_free(mname); | 339 lw_free(mname); |
340 while (nargs > 0) | 340 while (nargs > 0) |
341 lw_free(arglist[--nargs]); | 341 lw_free(arglist[--nargs]); |
342 lw_free(arglist); | 342 lw_free(arglist); |
346 for (;;) | 346 for (;;) |
347 { | 347 { |
348 ct = preproc_next_token(pp); | 348 ct = preproc_next_token(pp); |
349 if (ct -> ttype == TOK_EOL) | 349 if (ct -> ttype == TOK_EOL) |
350 break; | 350 break; |
351 if (!tl) | 351 token_list_append(tl, token_dup(ct)); |
352 tl = ct; | |
353 else | |
354 ttl -> next = ct; | |
355 ttl = ct; | |
356 pp -> curtok = NULL; // tell *_next_token* not to clobber token | |
357 } | 352 } |
358 out: | 353 out: |
359 if (strcmp(mname, "defined") == 0) | 354 if (strcmp(mname, "defined") == 0) |
360 { | 355 { |
361 preproc_throw_warning(pp, "attempt to define 'defined' as a macro not allowed"); | 356 preproc_throw_warning(pp, "attempt to define 'defined' as a macro not allowed"); |
765 } | 760 } |
766 | 761 |
767 /* | 762 /* |
768 Below here is the logic for expanding a macro | 763 Below here is the logic for expanding a macro |
769 */ | 764 */ |
770 static char *stringify(struct token *tl) | 765 static char *stringify(struct token_list *tli) |
771 { | 766 { |
772 struct strbuf *s; | 767 struct strbuf *s; |
773 int ws = 0; | 768 int ws = 0; |
769 struct token *tl = tli -> head; | |
774 | 770 |
775 s = strbuf_new(); | 771 s = strbuf_new(); |
776 strbuf_add(s, '"'); | 772 strbuf_add(s, '"'); |
777 | 773 |
778 while (tl && tl -> ttype == TOK_WSPACE) | 774 while (tl && tl -> ttype == TOK_WSPACE) |
802 | 798 |
803 strbuf_add(s, '"'); | 799 strbuf_add(s, '"'); |
804 return strbuf_end(s); | 800 return strbuf_end(s); |
805 } | 801 } |
806 | 802 |
803 static int macro_arg(struct symtab_e *s, char *str) | |
804 { | |
805 int i; | |
806 if (strcmp(str, "__VA_ARGS__") == 0) | |
807 i = s -> nargs; | |
808 else | |
809 for (i = 0; i < s -> nargs; i++) | |
810 if (strcmp(s -> params[i], str) == 0) | |
811 break; | |
812 if (i == s -> nargs) | |
813 if (s -> vargs == 0) | |
814 return -1; | |
815 return i; | |
816 } | |
817 | |
807 /* return list to tokens as a result of ## expansion */ | 818 /* return list to tokens as a result of ## expansion */ |
808 static struct token *paste_tokens(struct preproc_info *pp, struct symtab_e *s, struct token **arglist, struct token *t1, struct token *t2) | 819 static struct token_list *paste_tokens(struct preproc_info *pp, struct symtab_e *s, struct token_list **arglist, struct token *t1, struct token *t2) |
809 { | 820 { |
810 struct token *rl = NULL, *rlt; | 821 struct token_list *left; |
811 struct token *s1, *s2; | 822 struct token_list *right; |
812 struct token *ws; | 823 char *tstr; |
824 struct token *ttok; | |
813 int i; | 825 int i; |
814 char *tstr; | |
815 | 826 |
816 if (t1 -> ttype == TOK_IDENT) | 827 if (t1 -> ttype == TOK_IDENT) |
817 { | 828 { |
818 if (strcmp(t1 -> strval, "__VA_ARGS__") == 0) | 829 i = macro_arg(s, t1 -> strval); |
819 { | 830 if (i == -1) |
820 i = s -> nargs; | 831 { |
832 left = token_list_create(); | |
833 token_list_append(left, token_dup(t1)); | |
821 } | 834 } |
822 else | 835 else |
823 { | 836 { |
824 for (i = 0; i < s -> nargs; i++) | 837 left = token_list_dup(arglist[i]); |
825 { | 838 } |
826 if (strcmp(s -> params[i], t1 -> strval) == 0) | 839 } |
827 break; | 840 else |
828 } | 841 { |
829 } | 842 left = token_list_create(); |
830 if ((i == s -> nargs) && !(s -> vargs)) | 843 token_list_append(left, token_dup(t1)); |
831 { | 844 } |
832 s1 = token_dup(t1); | 845 // munch trailing white space |
846 while (left -> tail && left -> tail -> ttype == TOK_WSPACE) | |
847 { | |
848 token_list_remove(left -> tail); | |
849 } | |
850 | |
851 if (t2 -> ttype == TOK_IDENT) | |
852 { | |
853 i = macro_arg(s, t2 -> strval); | |
854 if (i == -1) | |
855 { | |
856 right = token_list_create(); | |
857 token_list_append(right, token_dup(t2)); | |
833 } | 858 } |
834 else | 859 else |
835 { | 860 { |
836 /* find last non-whitespace token */ | 861 right = token_list_dup(arglist[i]); |
837 ws = NULL; | |
838 for (t1 = s -> tl; t1; t1 = t1 -> next) | |
839 { | |
840 if (t1 -> ttype != TOK_WSPACE) | |
841 ws = t1; | |
842 } | |
843 if (!ws) | |
844 { | |
845 s1 = NULL; | |
846 } | |
847 else | |
848 { | |
849 if (ws != s -> tl) | |
850 { | |
851 /* output extra tokens */ | |
852 for (t1 = s -> tl; t1 -> next != ws; t1 = t1 -> next) | |
853 { | |
854 if (!rl) | |
855 { | |
856 rl = token_dup(t1); | |
857 rlt = rl; | |
858 } | |
859 else | |
860 { | |
861 rlt -> next = token_dup(t1); | |
862 rlt = rlt -> next; | |
863 } | |
864 } | |
865 } | |
866 s1 = token_dup(ws); | |
867 } | |
868 } | 862 } |
869 } | 863 } |
870 else | 864 else |
871 { | 865 { |
872 s1 = token_dup(t1); | 866 right = token_list_create(); |
873 } | 867 token_list_append(right, token_dup(t2)); |
874 if (t2 -> ttype == TOK_IDENT) | 868 } |
875 { | 869 // munch leading white space |
876 if (strcmp(t1 -> strval, "__VA_ARGS__") == 0) | 870 while (right -> head && right -> head -> ttype == TOK_WSPACE) |
877 { | 871 { |
878 i = s -> nargs; | 872 token_list_remove(right -> head); |
879 } | 873 } |
880 else | 874 |
881 { | 875 // nothing to append at all |
882 for (i = 0; i < s -> nargs; i++) | 876 if (left -> head != NULL && right -> head == NULL) |
883 { | 877 { |
884 if (strcmp(s -> params[i], t1 -> strval) == 0) | 878 // right arg is empty - use left |
885 break; | 879 token_list_destroy(right); |
886 } | 880 return left; |
887 } | 881 } |
888 if ((i == s -> nargs) && !(s -> vargs)) | 882 if (left -> head == NULL && right -> head != NULL) |
889 { | 883 { |
890 s2 = token_dup(t2); | 884 // left arg is empty, use right |
891 t2 = NULL; | 885 token_list_destroy(left); |
892 } | 886 return right; |
893 else | 887 } |
894 { | 888 if (left -> head == NULL && right -> head == NULL) |
895 /* find last non-whitespace token */ | 889 { |
896 ws = NULL; | 890 // both empty, use left |
897 for (t2 = s -> tl; t2; t2 = t2 -> next) | 891 token_list_destroy(right); |
898 { | 892 return left; |
899 if (t2 -> ttype != TOK_WSPACE) | 893 } |
900 { | 894 |
901 ws = t2; | 895 // both non-empty - past left tail with right head |
902 t2 = t2 -> next; | 896 // then past the right list onto the left |
903 break; | 897 tstr = lw_alloc(strlen(left -> tail -> strval) + strlen(right -> head -> strval) + 1); |
904 } | 898 strcpy(tstr, left -> tail -> strval); |
905 } | 899 strcat(tstr, right -> head -> strval); |
906 if (!ws) | 900 |
907 { | 901 pp -> lexstr = tstr; |
908 s2 = NULL; | 902 pp -> lexstrloc = 0; |
909 } | 903 |
910 else | 904 ttok = preproc_lex_next_token(pp); |
911 { | 905 if (ttok -> ttype != TOK_ERROR && pp -> lexstr[pp -> lexstrloc] == 0) |
912 s2 = token_dup(ws); | 906 { |
913 } | 907 // we have a new token here |
914 } | 908 token_list_remove(left -> tail); |
915 } | 909 token_list_remove(right -> head); |
916 else | 910 token_list_append(left, token_dup(ttok)); |
917 { | 911 } |
918 s2 = token_dup(t2); | 912 lw_free(tstr); |
919 } | 913 pp -> lexstr = NULL; |
920 | 914 pp -> lexstrloc = 0; |
921 /* here, s1 is NULL if no left operand or a duplicated token for the actual left operand */ | 915 for (ttok = right -> head; ttok; ttok = ttok -> next) |
922 /* here, s2 is NULL if no right operand or a duplicated token for the actual right operand */ | 916 { |
923 /* here, t2 points to a possibly empty list of extra tokens to output after the concatenated tokens */ | 917 token_list_append(left, token_dup(ttok)); |
924 /* here, rl,rlt is a possibly non-empty list of tokens preceding the concatenation */ | 918 } |
925 | 919 token_list_destroy(right); |
926 /* tokens combine if the combination exactly matches "combinelist", in which case the string values are | 920 return left; |
927 concatenated and the new token type is used to create a new token. If the tokens do not combine, | 921 } |
928 s1 and s2 are returned in sequence. */ | |
929 | |
930 if (!s1 && s2) | |
931 { | |
932 if (!rl) | |
933 rl = s2; | |
934 else | |
935 rlt -> next = s2; | |
936 rlt = s2; | |
937 } | |
938 else if (s1 && !s2) | |
939 { | |
940 if (!rl) | |
941 rl = s1; | |
942 else | |
943 rlt -> next = s1; | |
944 rlt = s1; | |
945 } | |
946 else if (s1 && s2) | |
947 { | |
948 tstr = lw_alloc(strlen(s1 -> strval) + strlen(s2 -> strval) + 1); | |
949 strcpy(tstr, s1 -> strval); | |
950 strcat(tstr, s2 -> strval); | |
951 /* now try to lex the string */ | |
952 pp -> lexstr = tstr; | |
953 pp -> lexstrloc = 0; | |
954 t1 = preproc_lex_next_token(pp); | |
955 if (pp -> lexstr[pp -> lexstrloc]) | |
956 { | |
957 // doesn't make a new token - pass through the original two | |
958 if (!rl) | |
959 rl = s1; | |
960 else | |
961 rlt -> next = s1; | |
962 s1 -> next = s2; | |
963 rlt = s2; | |
964 } | |
965 else | |
966 { | |
967 // does make a new token | |
968 t1 -> fn = s1 -> fn; | |
969 t1 -> column = s1 -> column; | |
970 t1 -> lineno = s1 -> lineno; | |
971 if (!rl) | |
972 rl = t1; | |
973 else | |
974 rlt -> next = t1; | |
975 rlt = t1; | |
976 } | |
977 lw_free(tstr); | |
978 pp -> lexstr = NULL; | |
979 } | |
980 | |
981 /* add in any extra tokens */ | |
982 while (t2) | |
983 { | |
984 if (!rl) | |
985 { | |
986 rl = token_dup(t2); | |
987 rlt = rl; | |
988 } | |
989 else | |
990 { | |
991 rlt -> next = token_dup(t2); | |
992 rlt = rlt -> next; | |
993 } | |
994 t2 = t2 -> next; | |
995 } | |
996 | |
997 return rl; | |
998 } | |
999 | |
1000 | 922 |
1001 static int expand_macro(struct preproc_info *pp, char *mname) | 923 static int expand_macro(struct preproc_info *pp, char *mname) |
1002 { | 924 { |
1003 struct symtab_e *s; | 925 struct symtab_e *s; |
1004 struct token *t, *t2, *t3; | 926 struct token *t, *t2, *t3; |
1005 struct token **arglist = NULL; | |
1006 int nargs = 0; | 927 int nargs = 0; |
1007 struct expand_e *e; | 928 struct expand_e *e; |
1008 struct token **exparglist = NULL; | 929 struct token_list **exparglist = NULL; |
930 struct token_list **arglist = NULL; | |
1009 int i; | 931 int i; |
1010 int pcount; | 932 int pcount; |
1011 char *tstr; | 933 char *tstr; |
1012 | 934 struct token_list *expand_list; |
935 int repl; | |
936 struct token_list *rtl; | |
937 | |
1013 s = symtab_find(pp, mname); | 938 s = symtab_find(pp, mname); |
1014 if (!s) | 939 if (!s) |
1015 return 0; | 940 return 0; |
1016 | 941 |
1017 for (e = pp -> expand_list; e; e = e -> next) | 942 for (e = pp -> expand_list; e; e = e -> next) |
1054 } | 979 } |
1055 | 980 |
1056 // parse parameters here | 981 // parse parameters here |
1057 t = preproc_next_token_nws(pp); | 982 t = preproc_next_token_nws(pp); |
1058 nargs = 1; | 983 nargs = 1; |
1059 arglist = lw_alloc(sizeof(struct token *)); | 984 arglist = lw_alloc(sizeof(struct token_list *)); |
1060 arglist[0] = NULL; | 985 arglist[0] = token_list_create(); |
1061 t2 = NULL; | 986 t2 = NULL; |
1062 | 987 |
1063 while (t -> ttype != TOK_CPAREN) | 988 while (t -> ttype != TOK_CPAREN) |
1064 { | 989 { |
1065 pcount = 0; | 990 pcount = 0; |
1077 if (t -> ttype == TOK_COMMA && pcount == 0) | 1002 if (t -> ttype == TOK_COMMA && pcount == 0) |
1078 { | 1003 { |
1079 if (!(s -> vargs) || (nargs > s -> nargs)) | 1004 if (!(s -> vargs) || (nargs > s -> nargs)) |
1080 { | 1005 { |
1081 nargs++; | 1006 nargs++; |
1082 arglist = lw_realloc(arglist, sizeof(struct token *) * nargs); | 1007 arglist = lw_realloc(arglist, sizeof(struct token_list *) * nargs); |
1083 arglist[nargs - 1] = NULL; | 1008 arglist[nargs - 1] = token_list_create(); |
1084 t2 = NULL; | 1009 t2 = NULL; |
1085 continue; | 1010 continue; |
1086 } | 1011 } |
1087 } | 1012 } |
1088 if (t2) | 1013 token_list_append(arglist[nargs - 1], token_dup(t)); |
1089 { | |
1090 t2 -> next = token_dup(t); | |
1091 t2 = t2 -> next; | |
1092 } | |
1093 else | |
1094 { | |
1095 t2 = token_dup(t); | |
1096 arglist[nargs - 1] = t2; | |
1097 } | |
1098 } | 1014 } |
1099 | 1015 |
1100 if (s -> vargs) | 1016 if (s -> vargs) |
1101 { | 1017 { |
1102 if (nargs <= s -> nargs) | 1018 if (nargs <= s -> nargs) |
1111 preproc_throw_error(pp, "Wrong number of arguments (%d) for macro %s which takes %d arguments", nargs, mname, s -> nargs); | 1027 preproc_throw_error(pp, "Wrong number of arguments (%d) for macro %s which takes %d arguments", nargs, mname, s -> nargs); |
1112 } | 1028 } |
1113 } | 1029 } |
1114 | 1030 |
1115 /* now calculate the pre-expansions of the arguments */ | 1031 /* now calculate the pre-expansions of the arguments */ |
1116 exparglist = lw_alloc(nargs); | 1032 exparglist = lw_alloc(nargs * sizeof(struct token_list *)); |
1117 for (i = 0; i < nargs; i++) | 1033 for (i = 0; i < nargs; i++) |
1118 { | 1034 { |
1119 t2 = NULL; | 1035 exparglist[i] = token_list_create(); |
1120 exparglist[i] = NULL; | |
1121 // NOTE: do nothing if empty argument | 1036 // NOTE: do nothing if empty argument |
1122 if (arglist[i] == NULL) | 1037 if (arglist[i] == NULL || arglist[i] -> head == NULL) |
1123 continue; | 1038 continue; |
1124 pp -> sourcelist = arglist[i]; | 1039 pp -> sourcelist = arglist[i]->head; |
1125 for (;;) | 1040 for (;;) |
1126 { | 1041 { |
1127 t = preproc_next_processed_token(pp); | 1042 t = preproc_next_processed_token(pp); |
1128 if (t -> ttype == TOK_EOF) | 1043 if (t -> ttype == TOK_EOF) |
1129 break; | 1044 break; |
1130 if (t2) | 1045 token_list_append(exparglist[i], token_dup(t)); |
1046 } | |
1047 } | |
1048 | |
1049 expandmacro: | |
1050 expand_list = token_list_dup(s -> tl); | |
1051 | |
1052 // scan for stringification and handle it | |
1053 repl = 0; | |
1054 while (repl == 0) | |
1055 { | |
1056 for (t = expand_list -> head; t; t = t -> next) | |
1057 { | |
1058 if (t -> ttype == TOK_HASH && t -> next && t -> next -> ttype == TOK_IDENT) | |
1131 { | 1059 { |
1132 t2 -> next = token_dup(t); | 1060 i = macro_arg(s, t -> next -> strval); |
1133 t2 = t2 -> next; | 1061 if (i != -1) |
1134 } | |
1135 else | |
1136 { | |
1137 t2 = token_dup(t); | |
1138 exparglist[i] = t2; | |
1139 } | |
1140 } | |
1141 } | |
1142 | |
1143 expandmacro: | |
1144 t2 = NULL; | |
1145 t3 = NULL; | |
1146 | |
1147 for (t = s -> tl; t; t = t -> next) | |
1148 { | |
1149 again: | |
1150 if (t -> ttype != TOK_WSPACE && t -> next) | |
1151 { | |
1152 struct token *ct1, *ct2; | |
1153 | |
1154 for (ct1 = t -> next; ct1 && ct1 -> ttype == TOK_WSPACE; ct1 = ct1 -> next) | |
1155 { | |
1156 if (ct1 -> ttype == TOK_DBLHASH) | |
1157 { | 1062 { |
1158 // possible concatenation here | 1063 repl = 1; |
1159 for (ct2 = ct1 -> next; ct2 && ct2 -> ttype == TOK_WSPACE; ct2 = ct2 -> next) | 1064 tstr = stringify(arglist[i]); |
1160 /* do nothing */ ; | 1065 token_list_remove(t -> next); |
1161 if (ct2) | 1066 token_list_insert(expand_list, t, token_create(TOK_STRING, tstr, t -> lineno, t -> column, t -> fn)); |
1162 { | 1067 token_list_remove(t); |
1163 // we have concatenation here so we paste str1 and str2 together and see what we get | 1068 lw_free(tstr); |
1164 // if we get NULL, the past didn't make a valid token | 1069 break; |
1165 ct1 = paste_tokens(pp, s, arglist, t, ct2); | |
1166 if (ct1) | |
1167 { | |
1168 if (t2) | |
1169 { | |
1170 t2 -> next = ct1; | |
1171 } | |
1172 else | |
1173 { | |
1174 t3 = ct1; | |
1175 } | |
1176 for (t2 = ct1; t2 -> next; t2 = t2 -> next) | |
1177 /* do nothing */ ; | |
1178 | |
1179 /* because of the level of control structures, move to next token and restart loop */ | |
1180 t = ct2 -> next; | |
1181 goto again; | |
1182 } | |
1183 goto nopaste; | |
1184 } | |
1185 } | 1070 } |
1186 } | 1071 } |
1187 } | 1072 } |
1188 | 1073 } |
1189 nopaste: | 1074 |
1190 if (t -> ttype == TOK_HASH) | 1075 |
1191 { | 1076 // scan for concatenation and handle it |
1192 if (t -> next && t -> next -> ttype == TOK_IDENT) | 1077 |
1078 for (t = expand_list -> head; t; t = t -> next) | |
1079 { | |
1080 if (t -> ttype == TOK_DBLHASH) | |
1081 { | |
1082 // have a concatenation operator here | |
1083 for (t2 = t -> prev; t2; t2 = t2 -> prev) | |
1193 { | 1084 { |
1194 if (strcmp(t -> next -> strval, "__VA_ARGS__") == 0) | 1085 if (t2 -> ttype != TOK_WSPACE) |
1195 { | 1086 break; |
1196 i = nargs; | |
1197 } | |
1198 else | |
1199 { | |
1200 for (i = 0; i < nargs; i++) | |
1201 { | |
1202 if (strcmp(t -> next -> strval, s -> params[i]) == 0) | |
1203 break; | |
1204 } | |
1205 } | |
1206 if (!((i == s -> nargs) && !(s -> vargs))) | |
1207 { | |
1208 // we have a stringification here | |
1209 t = t -> next; | |
1210 tstr = stringify(arglist[i]); | |
1211 if (t2) | |
1212 { | |
1213 t2 = token_create(TOK_STRING, tstr, t -> lineno, t -> column, t -> fn); | |
1214 t2 = t2 -> next; | |
1215 } | |
1216 else | |
1217 { | |
1218 t3 = token_create(TOK_STRING, tstr, t -> lineno, t -> column, t -> fn); | |
1219 t2 = t3; | |
1220 } | |
1221 lw_free(tstr); | |
1222 continue; | |
1223 } | |
1224 } | 1087 } |
1225 } | 1088 for (t3 = t -> next; t3; t3 = t3 -> next); |
1089 { | |
1090 if (t3 -> ttype != TOK_WSPACE) | |
1091 break; | |
1092 } | |
1093 // if no non-whitespace before or after, ignore it | |
1094 if (!t2 || !t3) | |
1095 continue; | |
1096 // eat the whitespace before and after | |
1097 while (t -> prev != t2) | |
1098 token_list_remove(t -> prev); | |
1099 while (t -> next != t3) | |
1100 token_list_remove(t -> next); | |
1101 // now paste t -> prev with t -> next and replace t with the result | |
1102 // continue scanning for ## at t -> next -> next | |
1103 t3 = t -> next -> next; | |
1104 | |
1105 rtl = paste_tokens(pp, s, arglist, t -> prev, t -> next); | |
1106 token_list_remove(t -> next); | |
1107 token_list_remove(t -> prev); | |
1108 t2 = t -> prev; | |
1109 token_list_remove(t); | |
1110 for (t = rtl -> head; t; t = t -> next) | |
1111 { | |
1112 token_list_insert(expand_list, t2, token_dup(t)); | |
1113 } | |
1114 t = t3 -> prev; | |
1115 token_list_destroy(rtl); | |
1116 } | |
1117 } | |
1118 | |
1119 // now scan for arguments and expand them | |
1120 for (t = expand_list -> head; t; t = t -> next) | |
1121 { | |
1122 again: | |
1226 if (t -> ttype == TOK_IDENT) | 1123 if (t -> ttype == TOK_IDENT) |
1227 { | 1124 { |
1228 /* identifiers might need expansion to arguments */ | 1125 /* identifiers might need expansion to arguments */ |
1229 if (strcmp(t -> strval, "__VA_ARGS__") == 0) | 1126 i = macro_arg(s, t -> strval); |
1127 if (i != -1) | |
1230 { | 1128 { |
1231 i = s -> nargs; | 1129 t3 = t -> next; |
1130 for (t2 = exparglist[i] -> tail; t2; t2 = t2 -> prev) | |
1131 token_list_insert(expand_list, t, token_dup(t2)); | |
1132 token_list_remove(t); | |
1133 t = t3; | |
1134 goto again; | |
1232 } | 1135 } |
1233 else | |
1234 { | |
1235 for (i = 0; i < nargs; i++) | |
1236 { | |
1237 if (strcmp(t -> strval, s -> params[i]) == 0) | |
1238 break; | |
1239 } | |
1240 } | |
1241 if ((i == s -> nargs) && !(s -> vargs)) | |
1242 { | |
1243 struct token *te; | |
1244 // expand argument | |
1245 for (te = exparglist[i]; te; te = te -> next) | |
1246 { | |
1247 if (t2) | |
1248 { | |
1249 t2 -> next = token_dup(te); | |
1250 t2 = t2 -> next; | |
1251 } | |
1252 else | |
1253 { | |
1254 t3 = token_dup(te); | |
1255 t2 = t2; | |
1256 } | |
1257 } | |
1258 continue; | |
1259 } | |
1260 } | |
1261 if (t2) | |
1262 { | |
1263 t2 -> next = token_dup(t); | |
1264 t2 = t2 -> next; | |
1265 } | |
1266 else | |
1267 { | |
1268 t3 = token_dup(t); | |
1269 t2 = t3; | |
1270 } | 1136 } |
1271 } | 1137 } |
1272 | 1138 |
1273 /* put the new expansion in front of the input, if relevant; if we | 1139 /* put the new expansion in front of the input, if relevant; if we |
1274 expanded to nothing, no need to create an expansion record or | 1140 expanded to nothing, no need to create an expansion record or |
1275 put anything into the input queue */ | 1141 put anything into the input queue */ |
1276 if (t3) | 1142 if (expand_list -> head) |
1277 { | 1143 { |
1278 t2 -> next = token_create(TOK_ENDEXPAND, "", -1, -1, ""); | 1144 token_list_append(expand_list, token_create(TOK_ENDEXPAND, "", -1, -1, "")); |
1279 t2 -> next -> next = pp -> tokqueue; | 1145 |
1280 pp -> tokqueue = t3; | 1146 // move the expanded list into the token queue |
1281 | 1147 for (t = expand_list -> tail; t; t = t -> prev) |
1148 preproc_unget_token(pp, token_dup(t)); | |
1149 | |
1282 /* set up expansion record */ | 1150 /* set up expansion record */ |
1283 e = lw_alloc(sizeof(struct expand_e)); | 1151 e = lw_alloc(sizeof(struct expand_e)); |
1284 e -> next = pp -> expand_list; | 1152 e -> next = pp -> expand_list; |
1285 pp -> expand_list = e; | 1153 pp -> expand_list = e; |
1286 e -> s = s; | 1154 e -> s = s; |
1287 } | 1155 } |
1288 | 1156 |
1289 /* now clean up */ | 1157 /* now clean up */ |
1158 token_list_destroy(expand_list); | |
1290 for (i = 0; i < nargs; i++) | 1159 for (i = 0; i < nargs; i++) |
1291 { | 1160 { |
1292 lw_free(arglist[i]); | 1161 token_list_destroy(arglist[i]); |
1293 lw_free(exparglist[i]); | 1162 token_list_destroy(exparglist[i]); |
1294 } | 1163 } |
1295 lw_free(arglist); | 1164 lw_free(arglist); |
1296 lw_free(exparglist); | 1165 lw_free(exparglist); |
1297 | 1166 |
1298 return 1; | 1167 return 1; |