comparison macro.c @ 178:0d5b9651b240

Merge Joerg's changes into upstream. (now that they've been thrashed out a bit, include CHANGES entries, etc.)
author David A. Holland
date Fri, 12 Jun 2015 03:05:49 -0400
parents 6119608a9817
children d359d9b86327
comparison
equal deleted inserted replaced
156:e8f7ae63844f 178:0d5b9651b240
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE. 27 * POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30 #include <stdint.h> 30 #include <stdint.h>
31 #include <stdio.h>
31 #include <stdlib.h> 32 #include <stdlib.h>
32 #include <string.h> 33 #include <string.h>
33 34
34 #include "array.h" 35 #include "array.h"
35 #include "mode.h" 36 #include "mode.h"
36 #include "place.h" 37 #include "place.h"
37 #include "macro.h" 38 #include "macro.h"
38 #include "output.h" 39 #include "output.h"
39 40
40 struct expansionitem { 41 struct expansionitem {
41 bool isstring; 42 enum { EI_STRING, EI_PARAM, EI_FILE, EI_LINE } itemtype;
42 union { 43 union {
43 char *string; 44 char *string; /* EI_STRING */
44 unsigned param; 45 unsigned param; /* EI_PARAM */
45 }; 46 };
46 }; 47 };
47 DECLARRAY(expansionitem, static UNUSED); 48 DECLARRAY(expansionitem, static UNUSED);
48 DEFARRAY(expansionitem, static); 49 DEFARRAY(expansionitem, static);
49 50
74 expansionitem_create_string(const char *string) 75 expansionitem_create_string(const char *string)
75 { 76 {
76 struct expansionitem *ei; 77 struct expansionitem *ei;
77 78
78 ei = domalloc(sizeof(*ei)); 79 ei = domalloc(sizeof(*ei));
79 ei->isstring = true; 80 ei->itemtype = EI_STRING;
80 ei->string = dostrdup(string); 81 ei->string = dostrdup(string);
81 return ei; 82 return ei;
82 } 83 }
83 84
84 static 85 static
86 expansionitem_create_stringlen(const char *string, size_t len) 87 expansionitem_create_stringlen(const char *string, size_t len)
87 { 88 {
88 struct expansionitem *ei; 89 struct expansionitem *ei;
89 90
90 ei = domalloc(sizeof(*ei)); 91 ei = domalloc(sizeof(*ei));
91 ei->isstring = true; 92 ei->itemtype = EI_STRING;
92 ei->string = dostrndup(string, len); 93 ei->string = dostrndup(string, len);
93 return ei; 94 return ei;
94 } 95 }
95 96
96 static 97 static
98 expansionitem_create_param(unsigned param) 99 expansionitem_create_param(unsigned param)
99 { 100 {
100 struct expansionitem *ei; 101 struct expansionitem *ei;
101 102
102 ei = domalloc(sizeof(*ei)); 103 ei = domalloc(sizeof(*ei));
103 ei->isstring = false; 104 ei->itemtype = EI_PARAM;
104 ei->param = param; 105 ei->param = param;
105 return ei; 106 return ei;
106 } 107 }
107 108
108 static 109 static
110 struct expansionitem *
111 expansionitem_create_file(void)
112 {
113 struct expansionitem *ei;
114
115 ei = domalloc(sizeof(*ei));
116 ei->itemtype = EI_FILE;
117 return ei;
118 }
119
120 static
121 struct expansionitem *
122 expansionitem_create_line(void)
123 {
124 struct expansionitem *ei;
125
126 ei = domalloc(sizeof(*ei));
127 ei->itemtype = EI_LINE;
128 return ei;
129 }
130
131 static
109 void 132 void
110 expansionitem_destroy(struct expansionitem *ei) 133 expansionitem_destroy(struct expansionitem *ei)
111 { 134 {
112 if (ei->isstring) { 135 switch (ei->itemtype) {
136 case EI_STRING:
113 dostrfree(ei->string); 137 dostrfree(ei->string);
138 break;
139 case EI_PARAM:
140 case EI_FILE:
141 case EI_LINE:
142 break;
114 } 143 }
115 dofree(ei, sizeof(*ei)); 144 dofree(ei, sizeof(*ei));
116 } 145 }
117 146
118 static 147 static
119 bool 148 bool
120 expansionitem_eq(const struct expansionitem *ei1, 149 expansionitem_eq(const struct expansionitem *ei1,
121 const struct expansionitem *ei2) 150 const struct expansionitem *ei2)
122 { 151 {
123 if (ei1->isstring != ei2->isstring) { 152 if (ei1->itemtype != ei2->itemtype) {
124 return false; 153 return false;
125 } 154 }
126 if (ei1->isstring) { 155 switch (ei1->itemtype) {
156 case EI_STRING:
127 if (strcmp(ei1->string, ei2->string) != 0) { 157 if (strcmp(ei1->string, ei2->string) != 0) {
128 return false; 158 return false;
129 } 159 }
130 } else { 160 break;
161 case EI_PARAM:
131 if (ei1->param != ei2->param) { 162 if (ei1->param != ei2->param) {
132 return false; 163 return false;
133 } 164 }
165 break;
166 case EI_FILE:
167 case EI_LINE:
168 break;
134 } 169 }
135 return true; 170 return true;
136 } 171 }
137 172
138 static 173 static
585 macro_parse_expansion(m, expansion); 620 macro_parse_expansion(m, expansion);
586 macro_define_common_end(m); 621 macro_define_common_end(m);
587 } 622 }
588 623
589 void 624 void
625 macro_define_magic(struct place *p, const char *macro)
626 {
627 struct macro *m;
628 struct expansionitem *ei;
629
630 m = macro_define_common_start(p, macro, p);
631 if (!strcmp(macro, "__FILE__")) {
632 ei = expansionitem_create_file();
633 }
634 else {
635 assert(!strcmp(macro, "__LINE__"));
636 ei = expansionitem_create_line();
637 }
638 expansionitemarray_add(&m->expansion, ei, NULL);
639 macro_define_common_end(m);
640 }
641
642 void
590 macro_undef(const char *macro) 643 macro_undef(const char *macro)
591 { 644 {
592 struct macro *m; 645 struct macro *m;
593 646
594 m = macrotable_find(macro, true); 647 m = macrotable_find(macro, true);
622 }; 675 };
623 676
624 static struct expstate mainstate; 677 static struct expstate mainstate;
625 678
626 static void doexpand(struct expstate *es, struct place *p, 679 static void doexpand(struct expstate *es, struct place *p,
627 char *buf, size_t len); 680 const char *buf, size_t len);
628 681
629 static 682 static
630 void 683 void
631 expstate_init(struct expstate *es, bool tobuf, bool honordefined) 684 expstate_init(struct expstate *es, bool tobuf, bool honordefined)
632 { 685 {
703 } 756 }
704 } 757 }
705 758
706 static 759 static
707 void 760 void
708 expand_newarg(struct expstate *es, char *buf, size_t len) 761 expand_newarg(struct expstate *es, const char *buf, size_t len)
709 { 762 {
710 char *text; 763 char *text;
711 764
712 text = dostrndup(buf, len); 765 text = dostrndup(buf, len);
713 stringarray_add(&es->args, text, NULL); 766 stringarray_add(&es->args, text, NULL);
714 } 767 }
715 768
716 static 769 static
717 void 770 void
718 expand_appendarg(struct expstate *es, char *buf, size_t len) 771 expand_appendarg(struct expstate *es, const char *buf, size_t len)
719 { 772 {
720 unsigned num; 773 unsigned num;
721 char *text; 774 char *text;
722 size_t oldlen; 775 size_t oldlen;
723 776
740 unsigned i, num; 793 unsigned i, num;
741 size_t len; 794 size_t len;
742 char *arg; 795 char *arg;
743 char *ret; 796 char *ret;
744 unsigned numargs, numparams; 797 unsigned numargs, numparams;
798 char numbuf[64];
745 799
746 numargs = stringarray_num(&es->args); 800 numargs = stringarray_num(&es->args);
747 numparams = stringarray_num(&es->curmacro->params); 801 numparams = stringarray_num(&es->curmacro->params);
748 802
749 if (numargs == 0 && numparams == 1) { 803 if (numargs == 0 && numparams == 1) {
764 818
765 len = 0; 819 len = 0;
766 num = expansionitemarray_num(&es->curmacro->expansion); 820 num = expansionitemarray_num(&es->curmacro->expansion);
767 for (i=0; i<num; i++) { 821 for (i=0; i<num; i++) {
768 ei = expansionitemarray_get(&es->curmacro->expansion, i); 822 ei = expansionitemarray_get(&es->curmacro->expansion, i);
769 if (ei->isstring) { 823 switch (ei->itemtype) {
824 case EI_STRING:
770 len += strlen(ei->string); 825 len += strlen(ei->string);
771 } else { 826 break;
827 case EI_PARAM:
772 arg = stringarray_get(&es->args, ei->param); 828 arg = stringarray_get(&es->args, ei->param);
773 len += strlen(arg); 829 len += strlen(arg);
830 break;
831 case EI_FILE:
832 len += strlen(place_getname(p)) + 2;
833 break;
834 case EI_LINE:
835 len += snprintf(numbuf, sizeof(numbuf), "%u", p->line);
836 break;
774 } 837 }
775 } 838 }
776 839
777 ret = domalloc(len+1); 840 ret = domalloc(len+1);
778 *ret = '\0'; 841 *ret = '\0';
779 for (i=0; i<num; i++) { 842 for (i=0; i<num; i++) {
780 ei = expansionitemarray_get(&es->curmacro->expansion, i); 843 ei = expansionitemarray_get(&es->curmacro->expansion, i);
781 if (ei->isstring) { 844 switch (ei->itemtype) {
845 case EI_STRING:
782 strcat(ret, ei->string); 846 strcat(ret, ei->string);
783 } else { 847 break;
848 case EI_PARAM:
784 arg = stringarray_get(&es->args, ei->param); 849 arg = stringarray_get(&es->args, ei->param);
785 strcat(ret, arg); 850 strcat(ret, arg);
851 break;
852 case EI_FILE:
853 strcat(ret, "\"");
854 strcat(ret, place_getname(p));
855 strcat(ret, "\"");
856 break;
857 case EI_LINE:
858 snprintf(numbuf, sizeof(numbuf), "%u", p->line);
859 strcat(ret, numbuf);
860 break;
786 } 861 }
787 } 862 }
788 863
789 return ret; 864 return ret;
790 } 865 }
844 } 919 }
845 } 920 }
846 921
847 static 922 static
848 void 923 void
849 expand_got_ws(struct expstate *es, struct place *p, char *buf, size_t len) 924 expand_got_ws(struct expstate *es, struct place *p,
925 const char *buf, size_t len)
850 { 926 {
851 switch (es->state) { 927 switch (es->state) {
852 case ES_NORMAL: 928 case ES_NORMAL:
853 expand_send(es, p, buf, len); 929 expand_send(es, p, buf, len);
854 break; 930 break;
866 } 942 }
867 } 943 }
868 944
869 static 945 static
870 void 946 void
871 expand_got_word(struct expstate *es, struct place *p, char *buf, size_t len) 947 expand_got_word(struct expstate *es, struct place *p,
948 const char *buf, size_t len)
872 { 949 {
873 struct macro *m; 950 struct macro *m;
874 951
875 switch (es->state) { 952 switch (es->state) {
876 case ES_NORMAL: 953 case ES_NORMAL:
915 } 992 }
916 } 993 }
917 994
918 static 995 static
919 void 996 void
920 expand_got_lparen(struct expstate *es, struct place *p, char *buf, size_t len) 997 expand_got_lparen(struct expstate *es, struct place *p,
998 const char *buf, size_t len)
921 { 999 {
922 switch (es->state) { 1000 switch (es->state) {
923 case ES_NORMAL: 1001 case ES_NORMAL:
924 expand_send(es, p, buf, len); 1002 expand_send(es, p, buf, len);
925 break; 1003 break;
938 } 1016 }
939 } 1017 }
940 1018
941 static 1019 static
942 void 1020 void
943 expand_got_rparen(struct expstate *es, struct place *p, char *buf, size_t len) 1021 expand_got_rparen(struct expstate *es, struct place *p,
1022 const char *buf, size_t len)
944 { 1023 {
945 switch (es->state) { 1024 switch (es->state) {
946 case ES_NORMAL: 1025 case ES_NORMAL:
947 expand_send(es, p, buf, len); 1026 expand_send(es, p, buf, len);
948 break; 1027 break;
973 } 1052 }
974 } 1053 }
975 1054
976 static 1055 static
977 void 1056 void
978 expand_got_comma(struct expstate *es, struct place *p, char *buf, size_t len) 1057 expand_got_comma(struct expstate *es, struct place *p,
1058 const char *buf, size_t len)
979 { 1059 {
980 switch (es->state) { 1060 switch (es->state) {
981 case ES_NORMAL: 1061 case ES_NORMAL:
982 expand_send(es, p, buf, len); 1062 expand_send(es, p, buf, len);
983 break; 1063 break;
1001 } 1081 }
1002 } 1082 }
1003 1083
1004 static 1084 static
1005 void 1085 void
1006 expand_got_other(struct expstate *es, struct place *p, char *buf, size_t len) 1086 expand_got_other(struct expstate *es, struct place *p,
1087 const char *buf, size_t len)
1007 { 1088 {
1008 switch (es->state) { 1089 switch (es->state) {
1009 case ES_NORMAL: 1090 case ES_NORMAL:
1010 expand_send(es, p, buf, len); 1091 expand_send(es, p, buf, len);
1011 break; 1092 break;
1053 es->argparens = 0; 1134 es->argparens = 0;
1054 } 1135 }
1055 1136
1056 static 1137 static
1057 void 1138 void
1058 doexpand(struct expstate *es, struct place *p, char *buf, size_t len) 1139 doexpand(struct expstate *es, struct place *p, const char *buf, size_t len)
1059 { 1140 {
1060 char *s; 1141 char *s;
1061 size_t x; 1142 size_t x;
1062 bool inquote = false; 1143 bool inquote = false;
1063 char quote = '\0'; 1144 char quote = '\0';
1142 len--; 1223 len--;
1143 } 1224 }
1144 } 1225 }
1145 1226
1146 char * 1227 char *
1147 macroexpand(struct place *p, char *buf, size_t len, bool honordefined) 1228 macroexpand(struct place *p, const char *buf, size_t len, bool honordefined)
1148 { 1229 {
1149 struct expstate es; 1230 struct expstate es;
1150 char *ret; 1231 char *ret;
1151 1232
1152 expstate_init(&es, true, honordefined); 1233 expstate_init(&es, true, honordefined);
1164 1245
1165 return ret; 1246 return ret;
1166 } 1247 }
1167 1248
1168 void 1249 void
1169 macro_sendline(struct place *p, char *buf, size_t len) 1250 macro_sendline(struct place *p, const char *buf, size_t len)
1170 { 1251 {
1171 doexpand(&mainstate, p, buf, len); 1252 doexpand(&mainstate, p, buf, len);
1172 output(p, "\n", 1); 1253 switch (mainstate.state) {
1254 case ES_NORMAL:
1255 /*
1256 * If we were sent a blank line, don't emit a newline
1257 * for it. This matches the prior behavior of tradcpp.
1258 */
1259 if (len > 0) {
1260 output(p, "\n", 1);
1261 }
1262 break;
1263 case ES_WANTLPAREN:
1264 case ES_NOARG:
1265 case ES_HAVEARG:
1266 /*
1267 * Apparently to match gcc's -traditional behavior we
1268 * need to emit a space for each newline that appears
1269 * while processing macro args.
1270 */
1271 expand_got_ws(&mainstate, p, " ", 1);
1272 break;
1273 }
1173 } 1274 }
1174 1275
1175 void 1276 void
1176 macro_sendeof(struct place *p) 1277 macro_sendeof(struct place *p)
1177 { 1278 {