0
|
1 /*
|
|
2 * macro.c
|
|
3 *
|
|
4 * stuff associated with macro processing
|
|
5 */
|
|
6
|
|
7 #include <ctype.h>
|
|
8 #include <stdlib.h>
|
|
9 #include <string.h>
|
|
10 #include "lwasm.h"
|
|
11
|
|
12 extern void resolve_insn(asmstate_t *as, sourceline_t *cl);
|
|
13
|
|
14 void pseudo_macro(asmstate_t *as, sourceline_t *cl, char **optr)
|
|
15 {
|
|
16 macrotab_t *m;
|
|
17
|
|
18 if (as -> inmacro)
|
|
19 {
|
|
20 errorp1(ERR_MACRO);
|
|
21 return;
|
|
22 }
|
|
23 as -> inmacro = 1;
|
|
24 if (as -> passnum != 1)
|
|
25 return;
|
|
26
|
|
27 for (m = as -> macros; m; m = m -> next)
|
|
28 {
|
|
29 if (!strcmp(m -> name, cl -> symstr))
|
|
30 break;
|
|
31 }
|
|
32 if (m)
|
|
33 {
|
|
34 errorp1(ERR_DUPSYM);
|
|
35 return;
|
|
36 }
|
|
37 m = calloc(sizeof(macrotab_t), 1);
|
|
38 m -> name = strdup(cl -> symstr);
|
|
39 m -> next = as -> macros;
|
|
40 as -> macros = m;
|
|
41 cl -> hassym = 0;
|
|
42 while (**optr && !isspace(**optr))
|
|
43 (*optr)++;
|
|
44 cl -> macrodef = 1;
|
|
45 }
|
|
46
|
|
47 void pseudo_endm(asmstate_t *as, sourceline_t *cl, char **optr)
|
|
48 {
|
|
49 if (!as -> inmacro)
|
|
50 {
|
|
51 errorp1(ERR_ENDM);
|
|
52 return;
|
|
53 }
|
|
54
|
|
55 as -> inmacro = 0;
|
|
56 cl -> macrodef = 1;
|
|
57 }
|
|
58
|
|
59 int add_macro_line(asmstate_t *as, sourceline_t *cl, char *optr)
|
|
60 {
|
|
61 macroline_t *l;
|
|
62
|
|
63 if (!as -> inmacro)
|
|
64 return 0;
|
|
65
|
|
66 if (as -> passnum == 2)
|
|
67 return 1;
|
|
68
|
|
69 l = calloc(sizeof(macroline_t), 1);
|
|
70 l -> linetext = strdup(optr);
|
|
71 if (as -> macros -> linetail)
|
|
72 as -> macros -> linetail -> next = l;
|
|
73 as -> macros -> linetail = l;
|
|
74 if (!(as -> macros -> linehead))
|
|
75 as -> macros -> linehead = l;
|
|
76 return 1;
|
|
77 }
|
|
78
|
|
79 void macro_add_to_buff(char **buff, int *loc, int *len, char c)
|
|
80 {
|
|
81 if (*loc == *len)
|
|
82 {
|
|
83 *buff = realloc(*buff, *len + 32);
|
|
84 *len += 32;
|
|
85 }
|
|
86 (*buff)[(*loc)++] = c;
|
|
87 }
|
|
88
|
|
89 // this is just like a regular operation function
|
|
90 /*
|
|
91 macro args are references by "\n" where 1 <= n <= 9
|
|
92 or by "\{n}"; a \ can be included by writing \\
|
|
93 */
|
|
94 void expand_macro(asmstate_t *as, sourceline_t *cl, char **optr)
|
|
95 {
|
|
96 char **args = NULL;
|
|
97 int nargs = 0;
|
|
98 int c;
|
|
99 sourceline_t *nl;
|
|
100 int nline = 1;
|
|
101 macrotab_t *m;
|
|
102 macroline_t *ml;
|
|
103 char *buff = NULL;
|
|
104 int bufflen = 0, buffloc;
|
|
105
|
|
106 m = cl -> macro;
|
|
107
|
|
108 // step the first: parse arguments
|
|
109 while (**optr && !isspace(**optr))
|
|
110 {
|
|
111 c = 0;
|
|
112 while ((*optr)[c] && !isspace((*optr)[c]) && (*optr)[c] != ',')
|
|
113 {
|
|
114 c++;
|
|
115 }
|
|
116 args = realloc(args, sizeof(char *) * (nargs + 1));
|
|
117 args[nargs] = malloc(c + 1);
|
|
118 strncpy(args[nargs], *optr, c);
|
|
119 args[nargs][c] = '\0';
|
|
120 nargs++;
|
|
121 *optr += c;
|
|
122 if (**optr == ',')
|
|
123 (*optr)++;
|
|
124 }
|
|
125
|
|
126 // step the second: iterate over the lines and expand arguments and add
|
|
127 // them after "cl"
|
|
128 for (ml = m -> linehead; ml; ml = ml -> next)
|
|
129 {
|
|
130 nl = calloc(sizeof(sourceline_t), 1);
|
|
131
|
|
132 nl -> lineno = nline++;
|
|
133 nl -> sourcefile = m -> name;
|
|
134 nl -> opcode = -1;
|
|
135 nl -> addrmode = -1;
|
|
136 nl -> addr = as -> addr;
|
|
137 nl -> dpval = as -> dpval;
|
|
138 nl -> prev = cl;
|
|
139 if (!(cl -> next))
|
|
140 as -> source_tail = nl;
|
|
141 nl -> next = cl -> next;
|
|
142 cl -> next = nl;
|
|
143
|
|
144 buffloc = 0;
|
|
145 c = 0;
|
|
146 while (ml -> linetext[c])
|
|
147 {
|
|
148 int ch;
|
|
149 ch = ml -> linetext[c++];
|
|
150 if (ch == '{')
|
|
151 {
|
|
152 int v = 0;
|
|
153 again:
|
|
154 ch = ml -> linetext[c++];
|
|
155 if (!ch)
|
|
156 {
|
|
157 c--;
|
|
158 continue;
|
|
159 }
|
|
160 if (ch >= '0' && ch <= '9')
|
|
161 {
|
|
162 v = v * 10 + (ch - '0');
|
|
163 goto again;
|
|
164 }
|
|
165 if (ch == '}')
|
|
166 {
|
|
167 v--;
|
|
168 if (v < nargs)
|
|
169 {
|
|
170 char *t;
|
|
171 for (t = args[v]; *t; t++)
|
|
172 {
|
|
173 macro_add_to_buff(&buff, &buffloc, &bufflen, *t);
|
|
174 }
|
|
175 }
|
|
176 continue;
|
|
177 }
|
|
178 else
|
|
179 continue;
|
|
180 }
|
|
181 else if (ch == '\\' && ml -> linetext[c])
|
|
182 {
|
|
183 ch = ml -> linetext[c++];
|
|
184 if (ch >= '1' && ch <= '9')
|
|
185 {
|
|
186 ch -= '1';
|
|
187 if (ch < nargs)
|
|
188 {
|
|
189 char *t;
|
|
190 for (t = args[ch]; *t; t++)
|
|
191 {
|
|
192 macro_add_to_buff(&buff, &buffloc, &bufflen, *t);
|
|
193 }
|
|
194 }
|
|
195 }
|
|
196 else
|
|
197 {
|
|
198 c--;
|
|
199 macro_add_to_buff(&buff, &buffloc, &bufflen, '\\');
|
|
200 }
|
|
201 }
|
|
202 else
|
|
203 {
|
|
204 macro_add_to_buff(&buff, &buffloc, &bufflen, ch);
|
|
205 }
|
|
206 }
|
|
207 macro_add_to_buff(&buff, &buffloc, &bufflen, 0);
|
|
208 nl -> line = strdup(buff);
|
|
209
|
|
210 resolve_insn(as, nl);
|
|
211 cl = nl;
|
|
212 }
|
|
213 if (buff)
|
|
214 free(buff);
|
|
215 }
|