Mercurial > ~dholland > hg > tradcpp > index.cgi
comparison macro.c @ 159:8cef6d7227a8
Expand __FILE__ and __LINE__.
author | Joerg Sonnenberger <joerg@bec.de> |
---|---|
date | Fri, 27 Feb 2015 00:41:46 +0100 |
parents | 19278e2f885d |
children | 4a4b3d5c41fa |
comparison
equal
deleted
inserted
replaced
158:19278e2f885d | 159:8cef6d7227a8 |
---|---|
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_PARAM, EI_STRING, EI_FILE, EI_LINE } itemtype; |
42 union { | 43 union { |
43 char *string; | 44 char *string; |
44 unsigned param; | 45 unsigned param; |
45 }; | 46 }; |
46 }; | 47 }; |
53 struct stringarray params; | 54 struct stringarray params; |
54 struct expansionitemarray expansion; | 55 struct expansionitemarray expansion; |
55 char *name; | 56 char *name; |
56 unsigned hash; | 57 unsigned hash; |
57 bool hasparams; | 58 bool hasparams; |
59 bool isspecial; | |
58 bool inuse; | 60 bool inuse; |
59 }; | 61 }; |
60 DECLARRAY(macro, static UNUSED); | 62 DECLARRAY(macro, static UNUSED); |
61 DEFARRAY(macro, static); | 63 DEFARRAY(macro, static); |
62 DECLARRAY(macroarray, static UNUSED); | 64 DECLARRAY(macroarray, static UNUSED); |
74 expansionitem_create_string(const char *string) | 76 expansionitem_create_string(const char *string) |
75 { | 77 { |
76 struct expansionitem *ei; | 78 struct expansionitem *ei; |
77 | 79 |
78 ei = domalloc(sizeof(*ei)); | 80 ei = domalloc(sizeof(*ei)); |
79 ei->isstring = true; | 81 ei->itemtype = EI_STRING; |
80 ei->string = dostrdup(string); | 82 ei->string = dostrdup(string); |
81 return ei; | 83 return ei; |
82 } | 84 } |
83 | 85 |
84 static | 86 static |
86 expansionitem_create_stringlen(const char *string, size_t len) | 88 expansionitem_create_stringlen(const char *string, size_t len) |
87 { | 89 { |
88 struct expansionitem *ei; | 90 struct expansionitem *ei; |
89 | 91 |
90 ei = domalloc(sizeof(*ei)); | 92 ei = domalloc(sizeof(*ei)); |
91 ei->isstring = true; | 93 ei->itemtype = EI_STRING; |
92 ei->string = dostrndup(string, len); | 94 ei->string = dostrndup(string, len); |
93 return ei; | 95 return ei; |
94 } | 96 } |
95 | 97 |
96 static | 98 static |
98 expansionitem_create_param(unsigned param) | 100 expansionitem_create_param(unsigned param) |
99 { | 101 { |
100 struct expansionitem *ei; | 102 struct expansionitem *ei; |
101 | 103 |
102 ei = domalloc(sizeof(*ei)); | 104 ei = domalloc(sizeof(*ei)); |
103 ei->isstring = false; | 105 ei->itemtype = EI_PARAM; |
104 ei->param = param; | 106 ei->param = param; |
105 return ei; | 107 return ei; |
106 } | 108 } |
107 | 109 |
108 static | 110 static |
111 struct expansionitem * | |
112 expansionitem_create_file(void) | |
113 { | |
114 struct expansionitem *ei; | |
115 | |
116 ei = domalloc(sizeof(*ei)); | |
117 ei->itemtype = EI_FILE; | |
118 return ei; | |
119 } | |
120 | |
121 static | |
122 struct expansionitem * | |
123 expansionitem_create_line(void) | |
124 { | |
125 struct expansionitem *ei; | |
126 | |
127 ei = domalloc(sizeof(*ei)); | |
128 ei->itemtype = EI_LINE; | |
129 return ei; | |
130 } | |
131 | |
132 static | |
109 void | 133 void |
110 expansionitem_destroy(struct expansionitem *ei) | 134 expansionitem_destroy(struct expansionitem *ei) |
111 { | 135 { |
112 if (ei->isstring) { | 136 if (ei->itemtype == EI_STRING) { |
113 dostrfree(ei->string); | 137 dostrfree(ei->string); |
114 } | 138 } |
115 dofree(ei, sizeof(*ei)); | 139 dofree(ei, sizeof(*ei)); |
116 } | 140 } |
117 | 141 |
118 static | 142 static |
119 bool | 143 bool |
120 expansionitem_eq(const struct expansionitem *ei1, | 144 expansionitem_eq(const struct expansionitem *ei1, |
121 const struct expansionitem *ei2) | 145 const struct expansionitem *ei2) |
122 { | 146 { |
123 if (ei1->isstring != ei2->isstring) { | 147 if ((ei1->itemtype == EI_STRING) != (ei2->itemtype == EI_STRING)) { |
124 return false; | 148 return false; |
125 } | 149 } |
126 if (ei1->isstring) { | 150 if (ei1->itemtype == EI_STRING) { |
127 if (strcmp(ei1->string, ei2->string) != 0) { | 151 if (strcmp(ei1->string, ei2->string) != 0) { |
128 return false; | 152 return false; |
129 } | 153 } |
130 } else { | 154 } else { |
131 if (ei1->param != ei2->param) { | 155 if (ei1->param != ei2->param) { |
171 macro_eq(const struct macro *m1, const struct macro *m2) | 195 macro_eq(const struct macro *m1, const struct macro *m2) |
172 { | 196 { |
173 unsigned num1, num2, i; | 197 unsigned num1, num2, i; |
174 struct expansionitem *ei1, *ei2; | 198 struct expansionitem *ei1, *ei2; |
175 const char *p1, *p2; | 199 const char *p1, *p2; |
200 | |
201 if (m2->isspecial) { | |
202 return false; | |
203 } | |
176 | 204 |
177 if (strcmp(m1->name, m2->name) != 0) { | 205 if (strcmp(m1->name, m2->name) != 0) { |
178 return false; | 206 return false; |
179 } | 207 } |
180 | 208 |
571 expansionitemarray_add(&m->expansion, ei, NULL); | 599 expansionitemarray_add(&m->expansion, ei, NULL); |
572 macro_define_common_end(m); | 600 macro_define_common_end(m); |
573 } | 601 } |
574 | 602 |
575 void | 603 void |
604 macro_define_file(struct place *p) | |
605 { | |
606 struct macro *m; | |
607 struct expansionitem *ei; | |
608 | |
609 m = macro_define_common_start(p, "__FILE__", p); | |
610 m->isspecial = true; | |
611 ei = expansionitem_create_file(); | |
612 expansionitemarray_add(&m->expansion, ei, NULL); | |
613 macro_define_common_end(m); | |
614 } | |
615 | |
616 void | |
617 macro_define_line(struct place *p) | |
618 { | |
619 struct macro *m; | |
620 struct expansionitem *ei; | |
621 | |
622 m = macro_define_common_start(p, "__LINE__", p); | |
623 m->isspecial = true; | |
624 ei = expansionitem_create_line(); | |
625 expansionitemarray_add(&m->expansion, ei, NULL); | |
626 macro_define_common_end(m); | |
627 } | |
628 | |
629 void | |
576 macro_define_params(struct place *p1, const char *macro, | 630 macro_define_params(struct place *p1, const char *macro, |
577 struct place *p2, const char *params, | 631 struct place *p2, const char *params, |
578 struct place *p3, const char *expansion) | 632 struct place *p3, const char *expansion) |
579 { | 633 { |
580 struct macro *m; | 634 struct macro *m; |
740 unsigned i, num; | 794 unsigned i, num; |
741 size_t len; | 795 size_t len; |
742 char *arg; | 796 char *arg; |
743 char *ret; | 797 char *ret; |
744 unsigned numargs, numparams; | 798 unsigned numargs, numparams; |
799 char numbuf[64]; | |
745 | 800 |
746 numargs = stringarray_num(&es->args); | 801 numargs = stringarray_num(&es->args); |
747 numparams = stringarray_num(&es->curmacro->params); | 802 numparams = stringarray_num(&es->curmacro->params); |
748 | 803 |
749 if (numargs == 0 && numparams == 1) { | 804 if (numargs == 0 && numparams == 1) { |
764 | 819 |
765 len = 0; | 820 len = 0; |
766 num = expansionitemarray_num(&es->curmacro->expansion); | 821 num = expansionitemarray_num(&es->curmacro->expansion); |
767 for (i=0; i<num; i++) { | 822 for (i=0; i<num; i++) { |
768 ei = expansionitemarray_get(&es->curmacro->expansion, i); | 823 ei = expansionitemarray_get(&es->curmacro->expansion, i); |
769 if (ei->isstring) { | 824 switch (ei->itemtype) { |
825 case EI_STRING: | |
770 len += strlen(ei->string); | 826 len += strlen(ei->string); |
771 } else { | 827 break; |
828 case EI_PARAM: | |
772 arg = stringarray_get(&es->args, ei->param); | 829 arg = stringarray_get(&es->args, ei->param); |
773 len += strlen(arg); | 830 len += strlen(arg); |
831 break; | |
832 case EI_FILE: | |
833 len += strlen(place_getname(p)) + 2; | |
834 break; | |
835 case EI_LINE: | |
836 len += snprintf(numbuf, sizeof(numbuf), "%u", p->line); | |
837 break; | |
774 } | 838 } |
775 } | 839 } |
776 | 840 |
777 ret = domalloc(len+1); | 841 ret = domalloc(len+1); |
778 *ret = '\0'; | 842 *ret = '\0'; |
779 for (i=0; i<num; i++) { | 843 for (i=0; i<num; i++) { |
780 ei = expansionitemarray_get(&es->curmacro->expansion, i); | 844 ei = expansionitemarray_get(&es->curmacro->expansion, i); |
781 if (ei->isstring) { | 845 switch (ei->itemtype) { |
846 case EI_STRING: | |
782 strcat(ret, ei->string); | 847 strcat(ret, ei->string); |
783 } else { | 848 break; |
849 case EI_PARAM: | |
784 arg = stringarray_get(&es->args, ei->param); | 850 arg = stringarray_get(&es->args, ei->param); |
785 strcat(ret, arg); | 851 strcat(ret, arg); |
852 break; | |
853 case EI_FILE: | |
854 strcat(ret, "\""); | |
855 strcat(ret, place_getname(p)); | |
856 strcat(ret, "\""); | |
857 break; | |
858 case EI_LINE: | |
859 snprintf(numbuf, sizeof(numbuf), "%u", p->line); | |
860 strcat(ret, numbuf); | |
861 break; | |
786 } | 862 } |
787 } | 863 } |
788 | 864 |
789 return ret; | 865 return ret; |
790 } | 866 } |
881 break; | 957 break; |
882 } | 958 } |
883 m = macrotable_findlen(buf, len, false); | 959 m = macrotable_findlen(buf, len, false); |
884 if (m == NULL || m->inuse) { | 960 if (m == NULL || m->inuse) { |
885 expand_send(es, p, buf, len); | 961 expand_send(es, p, buf, len); |
962 } else if (m->isspecial) { | |
963 es->curmacro = m; | |
964 newbuf = expand_substitute(p, es); | |
965 expand_send(es, p, newbuf, strlen(newbuf)); | |
966 dostrfree(newbuf); | |
967 es->curmacro = NULL; | |
968 m->inuse = false; | |
886 } else if (!m->hasparams) { | 969 } else if (!m->hasparams) { |
887 m->inuse = true; | 970 m->inuse = true; |
888 assert(expansionitemarray_num(&m->expansion) == 1); | 971 assert(expansionitemarray_num(&m->expansion) == 1); |
889 ei = expansionitemarray_get(&m->expansion, 0); | 972 ei = expansionitemarray_get(&m->expansion, 0); |
890 assert(ei->isstring); | 973 assert(ei->itemtype == EI_STRING); |
891 newbuf = macroexpand(p, ei->string, | 974 newbuf = macroexpand(p, ei->string, |
892 strlen(ei->string), false); | 975 strlen(ei->string), false); |
893 doexpand(es, p, newbuf, strlen(newbuf)); | 976 doexpand(es, p, newbuf, strlen(newbuf)); |
894 dostrfree(newbuf); | 977 dostrfree(newbuf); |
895 m->inuse = false; | 978 m->inuse = false; |