1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include "defs.h"
6 #include "externs.h"
7 #include "protos.h"
8
9 int mopt;
10 int in_macro;
11 int expand_macro;
12 char marg[8][10][80];
13 int midx;
14 int mcounter, mcntmax;
15 int mcntstack[8];
16 struct t_line *mstack[8];
17 struct t_line *mlptr;
18 struct t_macro *macro_tbl[256];
19 struct t_macro *mptr;
20
21 /* .macro pseudo */
22
23 void
do_macro(int * ip)24 do_macro(int *ip)
25 {
26 if (pass == LAST_PASS)
27 println();
28 else {
29 /* error checking */
30 if (expand_macro) {
31 error("Can not nest macro definitions!");
32 return;
33 }
34 if (lablptr == NULL) {
35 /* skip spaces */
36 while (isspace(prlnbuf[*ip]))
37 (*ip)++;
38
39 /* search a label after the .macro */
40 if (colsym(ip) == 0) {
41 error("No name for this macro!");
42 return;
43 }
44
45 /* put the macro name in the symbol table */
46 if ((lablptr = stlook(1)) == NULL)
47 return;
48 }
49 if (lablptr->refcnt) {
50 switch (lablptr->type) {
51 case MACRO:
52 fatal_error("Macro already defined!");
53 return;
54
55 case FUNC:
56 fatal_error("Symbol already used by a function!");
57 return;
58
59 default:
60 fatal_error("Symbol already used by a label!");
61 return;
62 }
63 }
64 if (!check_eol(ip))
65 return;
66
67 /* install this new macro in the hash table */
68 if (!macro_install())
69 return;
70 }
71 in_macro = 1;
72 }
73
74 /* .endm pseudo */
75
76 void
do_endm(int * ip)77 do_endm(int *ip)
78 {
79 error("Unexpected ENDM!");
80 return;
81 }
82
83 /* search a macro in the hash table */
84
macro_look(int * ip)85 struct t_macro *macro_look(int *ip)
86 {
87 struct t_macro *ptr;
88 char name[32];
89 char c;
90 int hash;
91 int l;
92
93 /* calculate the symbol hash value and check syntax */
94 l = 0;
95 hash = 0;
96 for (;;) {
97 c = prlnbuf[*ip];
98 if (c == '\0' || c == ' ' || c == '\t' || c == ';')
99 break;
100 if (!isalnum(c) && c != '_')
101 return (NULL);
102 if (l == 0) {
103 if (isdigit(c))
104 return (NULL);
105 }
106 if (l == 31)
107 return (NULL);
108 name[l++] = c;
109 hash += c;
110 hash = (hash << 3) + (hash >> 5) + c;
111 (*ip)++;
112 }
113 name[l] = '\0';
114 hash &= 0xFF;
115
116 /* browse the hash table */
117 ptr = macro_tbl[hash];
118 while (ptr) {
119 if (!strcmp(name, ptr->name))
120 break;
121 ptr = ptr->next;
122 }
123
124 /* return result */
125 return (ptr);
126 }
127
128 /* extract macro arguments */
129
130 int
macro_getargs(int ip)131 macro_getargs(int ip)
132 {
133 char *ptr;
134 char c, t;
135 int i, j, f, arg;
136 int level;
137
138 /* can not nest too much macros */
139 if (midx == 7) {
140 error("Too many nested macro calls!");
141 return (0);
142 }
143
144 /* initialize args */
145 mcntstack[midx] = mcounter;
146 mstack[midx++] = mlptr;
147 ptr = marg[midx][0];
148 arg = 0;
149
150 for (i = 0; i < 9; i++)
151 marg[midx][i][0] = '\0';
152
153 /* extract args */
154 for (;;) {
155 /* skip spaces */
156 while (isspace(prlnbuf[ip]))
157 ip++;
158
159 c = prlnbuf[ip++];
160 switch (c) {
161 /* no arg */
162 case ',':
163 arg++;
164 ptr = marg[midx][arg];
165 if (arg == 9) {
166 error("Too many arguments for a macro!");
167 return (0);
168 }
169 break;
170
171 /* string */
172 case '{':
173 c = '}';
174 case '\"':
175 i = 0;
176 if (c == '\"')
177 ptr[i++] = c;
178 for (;;) {
179 t = prlnbuf[ip++];
180 if (t == '\0') {
181 error("Unterminated string!");
182 return (0);
183 }
184 if (i == 80) {
185 error("String too long, max. 80 characters!");
186 return (0);
187 }
188 if (t == c)
189 break;
190 ptr[i++] = t;
191 }
192 if (c == '\"')
193 ptr[i++] = t;
194
195 /* skip spaces */
196 while (isspace(prlnbuf[ip]))
197 ip++;
198
199 /* check end of arg */
200 switch (prlnbuf[ip]) {
201 case '\0':
202 case ',':
203 case ';':
204 break;
205
206 default:
207 error("Syntax error!");
208 return (0);
209 }
210
211 /* end arg string */
212 ptr[i] = '\0';
213 break;
214
215 /* end of line */
216 case ';':
217 case '\0':
218 return (1);
219
220 /* continuation char */
221 case '\\':
222 /* skip spaces */
223 i = ip;
224 while (isspace(prlnbuf[i]))
225 i++;
226
227 /* check */
228 if (prlnbuf[i] == ';' || prlnbuf[i] == '\0') {
229 /* output line */
230 if (pass == LAST_PASS) {
231 println();
232 clearln();
233 }
234
235 /* read a new line */
236 if (readline() == -1)
237 return (0);
238
239 /* rewind line pointer and continue */
240 ip = SFIELD;
241 break;
242 }
243
244 /* other */
245 default:
246 i = 0;
247 j = 0;
248 f = 0;
249 level = 0;
250 while (c) {
251 if (c == ',') {
252 if (level == 0)
253 break;
254 }
255 else if ((c == '(') || (c == '[')) {
256 level++;
257 }
258 else if ((c == ')') || (c == ']')) {
259 if (level)
260 level--;
261 }
262 else if (c == ';') {
263 break;
264 }
265 if (f) {
266 if (c != ' ') {
267 while (i < j)
268 ptr[i++] = ' ';
269 ptr[i++] = c;
270 f = 0;
271 }
272 }
273 else if (c == ' ') {
274 f = 1;
275 }
276 else {
277 ptr[i++] = c;
278 }
279 if (i == 80) {
280 error("Macro argument string too long, max. 80 characters!");
281 return (0);
282 }
283 j++;
284 c = prlnbuf[ip++];
285 }
286 ptr[i] = '\0';
287 ip--;
288
289 /* check if arg is X or Y */
290 if (strlen(ptr) && arg) {
291 c = tolower(ptr[0]);
292
293 if ((c == 'x') || (c == 'y')) {
294 if ((strcasecmp(ptr, "x++") == 0) ||
295 (strcasecmp(ptr, "y++") == 0) ||
296 (strlen(ptr) == 1))
297 {
298 arg--;
299 ptr = marg[midx][arg];
300
301 /* check string length */
302 if (strlen(ptr) > 75) {
303 error("Macro argument string too long, max. 80 characters!");
304 return (0);
305 }
306
307 /* attach current arg to the previous one */
308 strcat(ptr, ",");
309 strcat(ptr, marg[midx][arg + 1]);
310 ptr = marg[midx][arg + 1];
311 ptr[0] = '\0';
312 }
313 }
314 }
315 break;
316 }
317 }
318 }
319
320 /* install a macro in the hash table */
321
322 int
macro_install(void)323 macro_install(void)
324 {
325 char c;
326 int hash = 0;
327 int i;
328
329 /* mark the macro name as reserved */
330 lablptr->type = MACRO;
331
332 /* check macro name syntax */
333 if (strchr(&symbol[1], '.')) {
334 error("Invalid macro name!");
335 return (0);
336 }
337
338 /* calculate symbol hash value */
339 for (i = 1; i <= symbol[0]; i++) {
340 c = symbol[i];
341 hash += c;
342 hash = (hash << 3) + (hash >> 5) + c;
343 }
344 hash &= 0xFF;
345
346 /* allocate a macro struct */
347 mptr = (void *)malloc(sizeof(struct t_macro));
348 if (mptr == NULL) {
349 error("Out of memory!");
350 return (0);
351 }
352
353 /* initialize it */
354 strcpy(mptr->name, &symbol[1]);
355 mptr->line = NULL;
356 mptr->next = macro_tbl[hash];
357 macro_tbl[hash] = mptr;
358 mlptr = NULL;
359
360 /* ok */
361 return (1);
362 }
363
364 /* send back the addressing mode of a macro arg */
365
366 int
macro_getargtype(char * arg)367 macro_getargtype(char *arg)
368 {
369 struct t_symbol *sym;
370 char c;
371 int i;
372
373 /* skip spaces */
374 while (isspace(*arg))
375 arg++;
376
377 /* get type */
378 switch (toupper(*arg++)) {
379 case '\0':
380 return (NO_ARG);
381
382 case '"':
383 return (ARG_STRING);
384
385 case '#':
386 return (ARG_IMM);
387
388 case '[':
389 return (ARG_INDIRECT);
390
391 case 'A':
392 case 'X':
393 case 'Y':
394 if (*arg == '\0')
395 return (ARG_REG);
396
397 default:
398 /* symbol */
399 for(i = 0; i < SBOLSZ; i++) {
400 c = arg[i];
401 if (isdigit(c) && (i == 0))
402 break;
403 if ((!isalnum(c)) && (c != '_') && (c != '.'))
404 break;
405 }
406
407 if (i == 0)
408 return (ARG_ABS);
409 else {
410 if (c != '\0')
411 return (ARG_ABS);
412 else {
413 strncpy(&symbol[1], arg, i);
414 symbol[0] = i;
415 symbol[i+1] = '\0';
416
417 if ((sym = stlook(0)) == NULL)
418 return (ARG_LABEL);
419 else {
420 if((sym->type == UNDEF) || (sym->type == IFUNDEF))
421 return (ARG_LABEL);
422 if (sym->bank == RESERVED_BANK)
423 return (ARG_ABS);
424 else
425 return (ARG_LABEL);
426 }
427 }
428 }
429 }
430 }
431
432