blob: 4318e33f01f8b05e2c5209c0312d141955e31e79 [file] [log] [blame]
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001/* preproc.c macro preprocessor for the Netwide Assembler
2 *
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
7 *
8 * initial version 18/iii/97 by Simon Tatham
9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <stddef.h>
14#include <string.h>
15#include <ctype.h>
H. Peter Anvin76690a12002-04-30 20:52:49 +000016#include <limits.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000017
18#include "nasm.h"
19#include "nasmlib.h"
20
21typedef struct SMacro SMacro;
22typedef struct MMacro MMacro;
23typedef struct Context Context;
24typedef struct Token Token;
25typedef struct Line Line;
26typedef struct Include Include;
27typedef struct Cond Cond;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000028typedef struct IncPath IncPath;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000029
30/*
31 * Store the definition of a single-line macro.
32 */
33struct SMacro {
34 SMacro *next;
35 char *name;
36 int casesense;
37 int nparam;
38 int in_progress;
39 Token *expansion;
40};
41
42/*
H. Peter Anvin76690a12002-04-30 20:52:49 +000043 * Store the definition of a multi-line macro. This is also used to
44 * store the interiors of `%rep...%endrep' blocks, which are
45 * effectively self-re-invoking multi-line macros which simply
46 * don't have a name or bother to appear in the hash tables. %rep
47 * blocks are signified by having a NULL `name' field.
48 *
49 * In a MMacro describing a `%rep' block, the `in_progress' field
50 * isn't merely boolean, but gives the number of repeats left to
51 * run.
52 *
53 * The `next' field is used for storing MMacros in hash tables; the
54 * `next_active' field is for stacking them on istk entries.
55 *
56 * When a MMacro is being expanded, `params', `iline', `nparam',
57 * `paramlen', `rotate' and `unique' are local to the invocation.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000058 */
59struct MMacro {
60 MMacro *next;
61 char *name;
62 int casesense;
63 int nparam_min, nparam_max;
64 int plus; /* is the last parameter greedy? */
H. Peter Anvin6768eb72002-04-30 20:52:26 +000065 int nolist; /* is this macro listing-inhibited? */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000066 int in_progress;
67 Token **defaults, *dlist;
H. Peter Anvin76690a12002-04-30 20:52:49 +000068 int ndefs; /* number of default parameters */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000069 Line *expansion;
H. Peter Anvin76690a12002-04-30 20:52:49 +000070
71 MMacro *next_active;
72 Token **params, *iline;
73 int nparam, rotate, *paramlen;
74 unsigned long unique;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000075};
76
77/*
78 * The context stack is composed of a linked list of these.
79 */
80struct Context {
81 Context *next;
82 SMacro *localmac;
83 char *name;
84 unsigned long number;
85};
86
87/*
88 * This is the internal form which we break input lines up into.
89 * Typically stored in linked lists.
90 *
91 * TOK_PS_OTHER is a token type used internally within
92 * expand_smacro(), to denote a token which has already been
93 * checked for being a potential macro, but may still be a context-
94 * local label.
95 *
96 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
97 * necessarily used as-is, but is intended to denote the number of
98 * the substituted parameter. So in the definition
99 *
100 * %define a(x,y) ( (x) & ~(y) )
101 *
102 * the token representing `x' will have its type changed to
103 * TOK_SMAC_PARAM, but the one representing `y' will be
104 * TOK_SMAC_PARAM+1.
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000105 *
106 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
107 * which doesn't need quotes around it. Used in the pre-include
108 * mechanism as an alternative to trying to find a sensible type of
109 * quote to use on the filename we were passed.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000110 */
111struct Token {
112 Token *next;
113 char *text;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000114 SMacro *mac; /* associated macro for TOK_SMAC_END */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000115 int type;
116};
117enum {
118 TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000119 TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_PS_OTHER, TOK_SMAC_PARAM,
120 TOK_INTERNAL_STRING
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000121};
122
123/*
124 * Multi-line macro definitions are stored as a linked list of
125 * these, which is essentially a container to allow several linked
126 * lists of Tokens.
127 *
128 * Note that in this module, linked lists are treated as stacks
129 * wherever possible. For this reason, Lines are _pushed_ on to the
130 * `expansion' field in MMacro structures, so that the linked list,
131 * if walked, would give the macro lines in reverse order; this
132 * means that we can walk the list when expanding a macro, and thus
133 * push the lines on to the `expansion' field in _istk_ in reverse
134 * order (so that when popped back off they are in the right
135 * order). It may seem cockeyed, and it relies on my design having
136 * an even number of steps in, but it works...
137 *
138 * Some of these structures, rather than being actual lines, are
139 * markers delimiting the end of the expansion of a given macro.
H. Peter Anvin76690a12002-04-30 20:52:49 +0000140 * This is for use in the cycle-tracking and %rep-handling code.
141 * Such structures have `finishes' non-NULL, and `first' NULL. All
142 * others have `finishes' NULL, but `first' may still be NULL if
143 * the line is blank.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000144 */
145struct Line {
146 Line *next;
147 MMacro *finishes;
148 Token *first;
149};
150
151/*
152 * To handle an arbitrary level of file inclusion, we maintain a
153 * stack (ie linked list) of these things.
154 */
155struct Include {
156 Include *next;
157 FILE *fp;
158 Cond *conds;
159 Line *expansion;
160 char *fname;
161 int lineno, lineinc;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000162 MMacro *mstk; /* stack of active macros/reps */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000163};
164
165/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000166 * Include search path. This is simply a list of strings which get
167 * prepended, in turn, to the name of an include file, in an
168 * attempt to find the file if it's not in the current directory.
169 */
170struct IncPath {
171 IncPath *next;
172 char *path;
173};
174
175/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000176 * Conditional assembly: we maintain a separate stack of these for
177 * each level of file inclusion. (The only reason we keep the
178 * stacks separate is to ensure that a stray `%endif' in a file
179 * included from within the true branch of a `%if' won't terminate
180 * it and cause confusion: instead, rightly, it'll cause an error.)
181 */
182struct Cond {
183 Cond *next;
184 int state;
185};
186enum {
187 /*
188 * These states are for use just after %if or %elif: IF_TRUE
189 * means the condition has evaluated to truth so we are
190 * currently emitting, whereas IF_FALSE means we are not
191 * currently emitting but will start doing so if a %else comes
192 * up. In these states, all directives are admissible: %elif,
193 * %else and %endif. (And of course %if.)
194 */
195 COND_IF_TRUE, COND_IF_FALSE,
196 /*
197 * These states come up after a %else: ELSE_TRUE means we're
198 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
199 * any %elif or %else will cause an error.
200 */
201 COND_ELSE_TRUE, COND_ELSE_FALSE,
202 /*
203 * This state means that we're not emitting now, and also that
204 * nothing until %endif will be emitted at all. It's for use in
205 * two circumstances: (i) when we've had our moment of emission
206 * and have now started seeing %elifs, and (ii) when the
207 * condition construct in question is contained within a
208 * non-emitting branch of a larger condition construct.
209 */
210 COND_NEVER
211};
212#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
213
214/*
215 * Condition codes. Note that we use c_ prefix not C_ because C_ is
216 * used in nasm.h for the "real" condition codes. At _this_ level,
217 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
218 * ones, so we need a different enum...
219 */
220static char *conditions[] = {
221 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
222 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
223 "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
224};
225enum {
226 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
227 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
228 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
229};
230static int inverse_ccs[] = {
231 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
232 c_A, c_AE, c_B, c_BE, c_C, c_E, c_G, c_GE, c_L, c_LE, c_O, c_P, c_S,
233 c_Z, c_NO, c_NP, c_PO, c_PE, c_NS, c_NZ
234};
235
H. Peter Anvin76690a12002-04-30 20:52:49 +0000236/*
237 * Directive names.
238 */
239static char *directives[] = {
240 "%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
241 "%elifid", "%elifidn", "%elifidni", "%elifnctx", "%elifndef",
242 "%elifnid", "%elifnidn", "%elifnidni", "%elifnnum", "%elifnstr",
243 "%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro",
244 "%endrep", "%error", "%exitrep", "%iassign", "%idefine", "%if",
245 "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifnctx",
246 "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnnum",
247 "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include", "%line",
248 "%macro", "%pop", "%push", "%rep", "%repl", "%rotate"
249};
250enum {
251 PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
252 PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFNCTX, PP_ELIFNDEF,
253 PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNNUM, PP_ELIFNSTR,
254 PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO,
255 PP_ENDREP, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
256 PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFNCTX,
257 PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNNUM,
258 PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE, PP_LINE,
259 PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE
260};
261
262
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000263static Context *cstk;
264static Include *istk;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000265static IncPath *ipath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000266
267static efunc error;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000268static evalfunc evaluate;
269
270static int pass;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000271
272static unsigned long unique; /* unique identifier numbers */
273
274static char *linesync, *outline;
275
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000276static Line *predef = NULL;
277
278static ListGen *list;
279
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000280/*
281 * The number of hash values we use for the macro lookup tables.
282 */
283#define NHASH 31
284
285/*
286 * The current set of multi-line macros we have defined.
287 */
288static MMacro *mmacros[NHASH];
289
290/*
291 * The current set of single-line macros we have defined.
292 */
293static SMacro *smacros[NHASH];
294
295/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000296 * The multi-line macro we are currently defining, or the %rep
297 * block we are currently reading, if any.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000298 */
299static MMacro *defining;
300
301/*
302 * The number of macro parameters to allocate space for at a time.
303 */
304#define PARAM_DELTA 16
305
306/*
307 * The standard macro set: defined as `static char *stdmac[]'. Also
308 * gives our position in the macro set, when we're processing it.
309 */
310#include "macros.c"
311static char **stdmacpos;
312
313/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000314 * The extra standard macros that come from the object format, if
315 * any.
316 */
317static char **extrastdmac = NULL;
318int any_extrastdmac;
319
320/*
321 * Forward declarations.
322 */
323static Token *expand_smacro (Token *tline);
324static void update_fileline (int which);
325
326/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000327 * The pre-preprocessing stage... This function translates line
328 * number indications as they emerge from GNU cpp (`# lineno "file"
329 * flags') into NASM preprocessor line number indications (`%line
330 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000331 */
332static char *prepreproc(char *line) {
333 int lineno, fnlen;
334 char *fname, *oldline;
335
336 if (line[0] == '#' && line[1] == ' ') {
337 oldline = line;
338 fname = oldline+2;
339 lineno = atoi(fname);
340 fname += strspn(fname, "0123456789 ");
341 if (*fname == '"')
342 fname++;
343 fnlen = strcspn(fname, "\"");
344 line = nasm_malloc(20+fnlen);
345 sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);
346 nasm_free (oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000347 }
348 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000349}
350
351/*
352 * The hash function for macro lookups. Note that due to some
353 * macros having case-insensitive names, the hash function must be
354 * invariant under case changes. We implement this by applying a
355 * perfectly normal hash function to the uppercase of the string.
356 */
357static int hash(char *s) {
358 /*
359 * Powers of three, mod 31.
360 */
361 static const int multipliers[] = {
362 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
363 30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
364 };
365 int h = 0;
366 int i = 0;
367
368 while (*s) {
369 h += multipliers[i] * (unsigned char) (toupper(*s));
370 s++;
371 if (++i >= sizeof(multipliers)/sizeof(*multipliers))
372 i = 0;
373 }
374 h %= NHASH;
375 return h;
376}
377
378/*
379 * Free a linked list of tokens.
380 */
381static void free_tlist (Token *list) {
382 Token *t;
383 while (list) {
384 t = list;
385 list = list->next;
386 nasm_free (t->text);
387 nasm_free (t);
388 }
389}
390
391/*
392 * Free a linked list of lines.
393 */
394static void free_llist (Line *list) {
395 Line *l;
396 while (list) {
397 l = list;
398 list = list->next;
399 free_tlist (l->first);
400 nasm_free (l);
401 }
402}
403
404/*
405 * Pop the context stack.
406 */
407static void ctx_pop (void) {
408 Context *c = cstk;
409 SMacro *smac, *s;
410
411 cstk = cstk->next;
412 smac = c->localmac;
413 while (smac) {
414 s = smac;
415 smac = smac->next;
416 nasm_free (s->name);
417 free_tlist (s->expansion);
418 nasm_free (s);
419 }
420 nasm_free (c->name);
421 nasm_free (c);
422}
423
424/*
425 * Generate a line synchronisation comment, to ensure the assembler
426 * knows which source file the current output has really come from.
427 */
428static void line_sync (void) {
H. Peter Anvin76690a12002-04-30 20:52:49 +0000429 char text[30+FILENAME_MAX];
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000430 sprintf(text, "%%line %d+%d %s",
431 (istk->expansion ? istk->lineno - istk->lineinc : istk->lineno),
432 (istk->expansion ? 0 : istk->lineinc), istk->fname);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000433 nasm_free (linesync);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000434 linesync = nasm_strdup(text);
435}
436
437#define BUF_DELTA 512
438/*
439 * Read a line from the top file in istk, handling multiple CR/LFs
440 * at the end of the line read, and handling spurious ^Zs. Will
441 * return lines from the standard macro set if this has not already
442 * been done.
443 */
444static char *read_line (void) {
445 char *buffer, *p, *q;
446 int bufsize;
447
448 if (stdmacpos) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000449 if (*stdmacpos) {
450 char *ret = nasm_strdup(*stdmacpos++);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000451 if (!*stdmacpos && any_extrastdmac) {
452 stdmacpos = extrastdmac;
453 any_extrastdmac = FALSE;
454 return ret;
455 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000456 /*
457 * Nasty hack: here we push the contents of `predef' on
458 * to the top-level expansion stack, since this is the
459 * most convenient way to implement the pre-include and
460 * pre-define features.
461 */
462 if (!*stdmacpos) {
463 Line *pd, *l;
464 Token *head, **tail, *t, *tt;
465
466 for (pd = predef; pd; pd = pd->next) {
467 head = NULL;
468 tail = &head;
469 for (t = pd->first; t; t = t->next) {
470 tt = *tail = nasm_malloc(sizeof(Token));
471 tt->next = NULL;
472 tail = &tt->next;
473 tt->type = t->type;
474 tt->text = nasm_strdup(t->text);
475 tt->mac = t->mac; /* always NULL here, in fact */
476 }
477 l = nasm_malloc(sizeof(Line));
478 l->next = istk->expansion;
479 l->first = head;
480 l->finishes = FALSE;
481 istk->expansion = l;
482 }
483 }
484 return ret;
485 } else {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000486 stdmacpos = NULL;
487 line_sync();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000488 update_fileline(3); /* update __FILE__ and __LINE__ */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000489 }
490 }
491
492 bufsize = BUF_DELTA;
493 buffer = nasm_malloc(BUF_DELTA);
494 p = buffer;
495 while (1) {
496 q = fgets(p, bufsize-(p-buffer), istk->fp);
497 if (!q)
498 break;
499 p += strlen(p);
500 if (p > buffer && p[-1] == '\n') {
501 istk->lineno += istk->lineinc;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000502 update_fileline(1); /* update __LINE__ only */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000503 break;
504 }
505 if (p-buffer > bufsize-10) {
506 bufsize += BUF_DELTA;
507 buffer = nasm_realloc(buffer, bufsize);
508 }
509 }
510
511 if (!q && p == buffer) {
512 nasm_free (buffer);
513 return NULL;
514 }
515
516 /*
517 * Play safe: remove CRs as well as LFs, if any of either are
518 * present at the end of the line.
519 */
520 while (p > buffer && (p[-1] == '\n' || p[-1] == '\r'))
521 *--p = '\0';
522
523 /*
524 * Handle spurious ^Z, which may be inserted into source files
525 * by some file transfer utilities.
526 */
527 buffer[strcspn(buffer, "\032")] = '\0';
528
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000529 list->line (LIST_READ, buffer);
530
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000531 return buffer;
532}
533
534/*
535 * Tokenise a line of text. This is a very simple process since we
536 * don't need to parse the value out of e.g. numeric tokens: we
537 * simply split one string into many.
538 */
539static Token *tokenise (char *line) {
540 char *p = line;
541 int type;
542 Token *list = NULL;
543 Token *t, **tail = &list;
544
545 while (*line) {
546 p = line;
547 if (*p == '%' &&
548 (p[1] == '{' || p[1] == '!' || (p[1] == '%' && isidchar(p[2])) ||
549 p[1] == '$' || p[1] == '+' || p[1] == '-' || isidchar(p[1]))) {
550 type = TOK_PREPROC_ID;
551 p++;
552 if (*p == '{') {
553 p++;
554 while (*p && *p != '}') {
555 p[-1] = *p;
556 p++;
557 }
558 p[-1] = '\0';
559 if (*p) p++;
560 } else {
561 if (*p == '!' || *p == '%' || *p == '$' ||
562 *p == '+' || *p == '-') p++;
563 while (*p && isidchar(*p))
564 p++;
565 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000566 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000567 type = TOK_ID;
568 p++;
569 while (*p && isidchar(*p))
570 p++;
571 } else if (*p == '\'' || *p == '"') {
572 /*
573 * A string token.
574 */
575 char c = *p;
576 p++;
577 type = TOK_STRING;
578 while (*p && *p != c)
579 p++;
580 if (*p) p++;
581 } else if (isnumstart(*p)) {
582 /*
583 * A number token.
584 */
585 type = TOK_NUMBER;
586 p++;
587 while (*p && isnumchar(*p))
588 p++;
589 } else if (isspace(*p)) {
590 type = TOK_WHITESPACE;
591 p++;
592 while (*p && isspace(*p))
593 p++;
594 /*
595 * Whitespace just before end-of-line is discarded by
596 * pretending it's a comment; whitespace just before a
597 * comment gets lumped into the comment.
598 */
599 if (!*p || *p == ';') {
600 type = TOK_COMMENT;
601 while (*p) p++;
602 }
603 } else if (*p == ';') {
604 type = TOK_COMMENT;
605 while (*p) p++;
606 } else {
607 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000608 * Anything else is an operator of some kind. We check
609 * for all the double-character operators (>>, <<, //,
610 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
611 * else is a single-character operator.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000612 */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000613 type = TOK_OTHER;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000614 if ((p[0] == '>' && p[1] == '>') ||
615 (p[0] == '<' && p[1] == '<') ||
616 (p[0] == '/' && p[1] == '/') ||
617 (p[0] == '%' && p[1] == '%') ||
618 (p[0] == '<' && p[1] == '=') ||
619 (p[0] == '>' && p[1] == '=') ||
620 (p[0] == '=' && p[1] == '=') ||
621 (p[0] == '!' && p[1] == '=') ||
622 (p[0] == '<' && p[1] == '>') ||
623 (p[0] == '&' && p[1] == '&') ||
624 (p[0] == '|' && p[1] == '|') ||
625 (p[0] == '^' && p[1] == '^'))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000626 p++;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000627 p++;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000628 }
629 if (type != TOK_COMMENT) {
630 *tail = t = nasm_malloc (sizeof(Token));
631 tail = &t->next;
632 t->next = NULL;
633 t->type = type;
634 t->text = nasm_malloc(1+p-line);
635 strncpy(t->text, line, p-line);
636 t->text[p-line] = '\0';
637 }
638 line = p;
639 }
640
641 return list;
642}
643
644/*
645 * Convert a line of tokens back into text.
646 */
647static char *detoken (Token *tlist) {
648 Token *t;
649 int len;
650 char *line, *p;
651
652 len = 0;
653 for (t = tlist; t; t = t->next) {
654 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
655 char *p = getenv(t->text+2);
656 nasm_free (t->text);
657 if (p)
658 t->text = nasm_strdup(p);
659 else
660 t->text = NULL;
661 }
662 if (t->text)
663 len += strlen(t->text);
664 }
665 p = line = nasm_malloc(len+1);
666 for (t = tlist; t; t = t->next) {
667 if (t->text) {
668 strcpy (p, t->text);
669 p += strlen(p);
670 }
671 }
672 *p = '\0';
673 return line;
674}
675
676/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000677 * A scanner, suitable for use by the expression evaluator, which
678 * operates on a line of Tokens. Expects a pointer to a pointer to
679 * the first token in the line to be passed in as its private_data
680 * field.
681 */
682static int ppscan(void *private_data, struct tokenval *tokval) {
683 Token **tlineptr = private_data;
684 Token *tline;
685
686 do {
687 tline = *tlineptr;
688 *tlineptr = tline ? tline->next : NULL;
689 } while (tline && (tline->type == TOK_WHITESPACE ||
690 tline->type == TOK_COMMENT));
691
692 if (!tline)
693 return tokval->t_type = TOKEN_EOS;
694
695 if (tline->text[0] == '$' && !tline->text[1])
696 return tokval->t_type = TOKEN_HERE;
697 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[1])
698 return tokval->t_type = TOKEN_BASE;
699
700 if (tline->type == TOK_ID) {
701 tokval->t_charptr = tline->text;
702 if (tline->text[0] == '$') {
703 tokval->t_charptr++;
704 return tokval->t_type = TOKEN_ID;
705 }
706
707 /*
708 * This is the only special case we actually need to worry
709 * about in this restricted context.
710 */
711 if (!nasm_stricmp(tline->text, "seg"))
712 return tokval->t_type = TOKEN_SEG;
713
714 return tokval->t_type = TOKEN_ID;
715 }
716
717 if (tline->type == TOK_NUMBER) {
718 int rn_error;
719
720 tokval->t_integer = readnum(tline->text, &rn_error);
721 if (rn_error)
722 return tokval->t_type = TOKEN_ERRNUM;
723 tokval->t_charptr = NULL;
724 return tokval->t_type = TOKEN_NUM;
725 }
726
727 if (tline->type == TOK_OTHER) {
728 if (!strcmp(tline->text, "<<")) return tokval->t_type = TOKEN_SHL;
729 if (!strcmp(tline->text, ">>")) return tokval->t_type = TOKEN_SHR;
730 if (!strcmp(tline->text, "//")) return tokval->t_type = TOKEN_SDIV;
731 if (!strcmp(tline->text, "%%")) return tokval->t_type = TOKEN_SMOD;
732 if (!strcmp(tline->text, "==")) return tokval->t_type = TOKEN_EQ;
733 if (!strcmp(tline->text, "<>")) return tokval->t_type = TOKEN_NE;
734 if (!strcmp(tline->text, "!=")) return tokval->t_type = TOKEN_NE;
735 if (!strcmp(tline->text, "<=")) return tokval->t_type = TOKEN_LE;
736 if (!strcmp(tline->text, ">=")) return tokval->t_type = TOKEN_GE;
737 if (!strcmp(tline->text, "&&")) return tokval->t_type = TOKEN_DBL_AND;
738 if (!strcmp(tline->text, "^^")) return tokval->t_type = TOKEN_DBL_XOR;
739 if (!strcmp(tline->text, "||")) return tokval->t_type = TOKEN_DBL_OR;
740 }
741
742 /*
743 * We have no other options: just return the first character of
744 * the token text.
745 */
746 return tokval->t_type = tline->text[0];
747}
748
749/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000750 * Return the Context structure associated with a %$ token. Return
751 * NULL, having _already_ reported an error condition, if the
752 * context stack isn't deep enough for the supplied number of $
753 * signs.
754 */
755static Context *get_ctx (char *name) {
756 Context *ctx;
757 int i;
758
759 if (!cstk) {
760 error (ERR_NONFATAL|ERR_OFFBY1, "`%s': context stack is empty", name);
761 return NULL;
762 }
763
764 i = 1;
765 ctx = cstk;
766 while (name[i+1] == '$') {
767 i++;
768 ctx = ctx->next;
769 if (!ctx) {
770 error (ERR_NONFATAL|ERR_OFFBY1, "`%s': context stack is only"
771 " %d level%s deep", name, i-1, (i==2 ? "" : "s"));
772 return NULL;
773 }
774 }
775 return ctx;
776}
777
778/*
779 * Compare a string to the name of an existing macro; this is a
780 * simple wrapper which calls either strcmp or nasm_stricmp
781 * depending on the value of the `casesense' parameter.
782 */
783static int mstrcmp(char *p, char *q, int casesense) {
784 return casesense ? strcmp(p,q) : nasm_stricmp(p,q);
785}
786
787/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000788 * Open an include file. This routine must always return a valid
789 * file pointer if it returns - it's responsible for throwing an
790 * ERR_FATAL and bombing out completely if not. It should also try
791 * the include path one by one until it finds the file or reaches
792 * the end of the path.
793 */
794static FILE *inc_fopen(char *file) {
795 FILE *fp;
796 char *prefix = "", *combine;
797 IncPath *ip = ipath;
798 int len = strlen(file);
799
800 do {
801 combine = nasm_malloc(strlen(prefix)+len+1);
802 strcpy(combine, prefix);
803 strcat(combine, file);
804 fp = fopen(combine, "r");
805 nasm_free (combine);
806 if (fp)
807 return fp;
808 prefix = ip ? ip->path : NULL;
809 if (ip)
810 ip = ip->next;
811 } while (prefix);
812
813 error (ERR_FATAL|ERR_OFFBY1,
814 "unable to open include file `%s'", file);
815 return NULL; /* never reached - placate compilers */
816}
817
818/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000819 * Determine if we should warn on defining a single-line macro of
820 * name `name', with `nparam' parameters. If nparam is 0, will
821 * return TRUE if _any_ single-line macro of that name is defined.
822 * Otherwise, will return TRUE if a single-line macro with either
823 * `nparam' or no parameters is defined.
824 *
825 * If a macro with precisely the right number of parameters is
826 * defined, the address of the definition structure will be
827 * returned in `defn'; otherwise NULL will be returned. If `defn'
828 * is NULL, no action will be taken regarding its contents, and no
829 * error will occur.
830 *
831 * Note that this is also called with nparam zero to resolve
832 * `ifdef'.
833 */
834static int smacro_defined (char *name, int nparam, SMacro **defn) {
835 SMacro *m;
836 Context *ctx;
837 char *p;
838
839 if (name[0] == '%' && name[1] == '$') {
840 ctx = get_ctx (name);
841 if (!ctx)
842 return FALSE; /* got to return _something_ */
843 m = ctx->localmac;
844 p = name+1;
845 p += strspn(p, "$");
846 } else {
847 m = smacros[hash(name)];
848 p = name;
849 }
850
851 while (m) {
852 if (!mstrcmp(m->name, p, m->casesense) &&
853 (nparam == 0 || m->nparam == 0 || nparam == m->nparam)) {
854 if (defn) {
855 if (nparam == m->nparam)
856 *defn = m;
857 else
858 *defn = NULL;
859 }
860 return TRUE;
861 }
862 m = m->next;
863 }
864 return FALSE;
865}
866
867/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000868 * Update the __FILE__ and __LINE__ macros. Specifically, update
869 * __FILE__ if bit 1 of our argument is set, and update __LINE__ if
870 * bit 0 is set.
871 *
872 * If the macros don't exist, a `%clear' must have happened, in
873 * which case we should exit quite happily and carry on going. It's
874 * not an error condition.
875 */
876static void update_fileline(int which) {
877 SMacro *sm;
878 char num[20];
879
880 if ((which & 3) && smacro_defined ("__FILE__", 0, &sm) && sm) {
881 free_tlist(sm->expansion);
882 sm->expansion = nasm_malloc(sizeof(Token));
883 sm->expansion->next = NULL;
884 sm->expansion->mac = NULL;
885 sm->expansion->type = TOK_STRING;
886 sm->expansion->text = nasm_malloc(3+strlen(istk->fname));
887 /* FIXME: throw an error if both sorts of quote are present */
888 /* Better still, invent a way for us to cope with that case */
889 sprintf(sm->expansion->text, "\"%s\"", istk->fname);
890 }
891
892 if ((which & 1) && smacro_defined ("__LINE__", 0, &sm) && sm) {
893 free_tlist(sm->expansion);
894 sm->expansion = nasm_malloc(sizeof(Token));
895 sm->expansion->next = NULL;
896 sm->expansion->mac = NULL;
897 sm->expansion->type = TOK_NUMBER;
898 sprintf(num, "%d", istk->lineno - istk->lineinc);
899 sm->expansion->text = nasm_strdup(num);
900 }
901}
902
903/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000904 * Count and mark off the parameters in a multi-line macro call.
905 * This is called both from within the multi-line macro expansion
906 * code, and also to mark off the default parameters when provided
907 * in a %macro definition line.
908 */
909static void count_mmac_params (Token *t, int *nparam, Token ***params) {
910 int paramsize, brace;
911
912 *nparam = paramsize = 0;
913 *params = NULL;
914 while (t) {
915 if (*nparam >= paramsize) {
916 paramsize += PARAM_DELTA;
917 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
918 }
919 if (t && t->type == TOK_WHITESPACE)
920 t = t->next;
921 brace = FALSE;
922 if (t && t->type == TOK_OTHER && !strcmp(t->text, "{"))
923 brace = TRUE;
924 (*params)[(*nparam)++] = t;
925 while (t && (t->type != TOK_OTHER ||
926 strcmp(t->text, brace ? "}" : ",")))
927 t = t->next;
928 if (t) { /* got a comma/brace */
929 t = t->next;
930 if (brace) {
931 /*
932 * Now we've found the closing brace, look further
933 * for the comma.
934 */
935 if (t && t->type == TOK_WHITESPACE)
936 t = t->next;
937 if (t && (t->type != TOK_OTHER || strcmp(t->text, ","))) {
938 error (ERR_NONFATAL|ERR_OFFBY1,
939 "braces do not enclose all of macro parameter");
940 while (t && (t->type != TOK_OTHER ||
941 strcmp(t->text, ",")))
942 t = t->next;
943 }
944 if (t)
945 t = t->next; /* eat the comma */
946 }
947 }
948 else /* got EOL */
949 break;
950 }
951}
952
953/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000954 * Determine whether one of the various `if' conditions is true or
955 * not.
956 *
957 * We must free the tline we get passed.
958 */
959static int if_condition (Token *tline, int i) {
960 int j, casesense;
961 Token *t, *tt, **tptr, *origline;
962 struct tokenval tokval;
963 expr *evalresult;
964
965 origline = tline;
966
967 switch (i) {
968 case PP_IFCTX: case PP_ELIFCTX:
969 case PP_IFNCTX: case PP_ELIFNCTX:
970 j = FALSE; /* have we matched yet? */
971 if (!cstk)
972 error(ERR_FATAL|ERR_OFFBY1,
973 "`%s': context stack is empty", directives[i]);
974 else while (tline) {
975 if (tline->type == TOK_WHITESPACE)
976 tline = tline->next;
977 if (!tline || tline->type != TOK_ID) {
978 error(ERR_NONFATAL|ERR_OFFBY1,
979 "`%s' expects context identifiers", directives[i]);
980 free_tlist (origline);
981 return -1;
982 }
983 if (!nasm_stricmp(tline->text, cstk->name))
984 j = TRUE;
985 tline = tline->next;
986 }
987 if (i == PP_IFNCTX || i == PP_ELIFNCTX)
988 j = !j;
989 free_tlist (origline);
990 return j;
991
992 case PP_IFDEF: case PP_ELIFDEF:
993 case PP_IFNDEF: case PP_ELIFNDEF:
994 j = FALSE; /* have we matched yet? */
995 while (tline) {
996 if (tline->type == TOK_WHITESPACE)
997 tline = tline->next;
998 if (!tline || (tline->type != TOK_ID &&
999 (tline->type != TOK_PREPROC_ID ||
1000 tline->text[1] != '$'))) {
1001 error(ERR_NONFATAL|ERR_OFFBY1,
1002 "`%%if%sdef' expects macro identifiers",
1003 (i==PP_ELIFNDEF ? "n" : ""));
1004 free_tlist (origline);
1005 return -1;
1006 }
1007 if (smacro_defined(tline->text, 0, NULL))
1008 j = TRUE;
1009 tline = tline->next;
1010 }
1011 if (i == PP_IFNDEF || i == PP_ELIFNDEF)
1012 j = !j;
1013 free_tlist (origline);
1014 return j;
1015
1016 case PP_IFIDN: case PP_ELIFIDN: case PP_IFNIDN: case PP_ELIFNIDN:
1017 case PP_IFIDNI: case PP_ELIFIDNI: case PP_IFNIDNI: case PP_ELIFNIDNI:
1018 tline = expand_smacro(tline);
1019 t = tt = tline;
1020 while (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
1021 tt = tt->next;
1022 if (!tt) {
1023 error(ERR_NONFATAL, "`%s' expects two comma-separated arguments");
1024 free_tlist (tline);
1025 return -1;
1026 }
1027 tt = tt->next;
1028 casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||
1029 i == PP_IFNIDN || i == PP_ELIFNIDN);
1030 j = TRUE; /* assume equality unless proved not */
1031 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1032 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1033 error(ERR_NONFATAL, "`%s': more than one comma on line",
1034 directives[i]);
1035 free_tlist (tline);
1036 return -1;
1037 }
1038 if (t->type == TOK_WHITESPACE) {
1039 t = t->next;
1040 continue;
1041 } else if (tt->type == TOK_WHITESPACE) {
1042 tt = tt->next;
1043 continue;
1044 } else if (tt->type != t->type ||
1045 (casesense ? strcmp(tt->text, t->text) :
1046 nasm_stricmp(tt->text, t->text))) {
1047 j = FALSE; /* found mismatching tokens */
1048 break;
1049 } else {
1050 t = t->next;
1051 tt = tt->next;
1052 continue;
1053 }
1054 }
1055 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1056 j = FALSE; /* trailing gunk on one end or other */
1057 if (i == PP_IFNIDN || i == PP_ELIFNIDN)
1058 j = !j;
1059 free_tlist (tline);
1060 return j;
1061
1062 case PP_IFID: case PP_ELIFID: case PP_IFNID: case PP_ELIFNID:
1063 case PP_IFNUM: case PP_ELIFNUM: case PP_IFNNUM: case PP_ELIFNNUM:
1064 case PP_IFSTR: case PP_ELIFSTR: case PP_IFNSTR: case PP_ELIFNSTR:
1065 tline = expand_smacro(tline);
1066 t = tline;
1067 while (t && t->type == TOK_WHITESPACE)
1068 t = t->next;
1069 j = FALSE; /* placate optimiser */
1070 switch (i) {
1071 case PP_IFID: case PP_ELIFID: case PP_IFNID: case PP_ELIFNID:
1072 j = (t->type == TOK_ID);
1073 break;
1074 case PP_IFNUM: case PP_ELIFNUM: case PP_IFNNUM: case PP_ELIFNNUM:
1075 j = (t->type == TOK_NUMBER);
1076 break;
1077 case PP_IFSTR: case PP_ELIFSTR: case PP_IFNSTR: case PP_ELIFNSTR:
1078 j = (t->type == TOK_STRING);
1079 break;
1080 }
1081 if (i == PP_IFNID || i == PP_ELIFNID ||
1082 i == PP_IFNNUM || i == PP_ELIFNNUM ||
1083 i == PP_IFNSTR || i == PP_ELIFNSTR)
1084 j = !j;
1085 free_tlist (tline);
1086 return j;
1087
1088 case PP_IF: case PP_ELIF:
1089 t = tline = expand_smacro(tline);
1090 tptr = &t;
1091 tokval.t_type = TOKEN_INVALID;
1092 evalresult = evaluate (ppscan, tptr, &tokval,
1093 NULL, pass | 0x10, error, NULL);
1094 free_tlist (tline);
1095 if (!evalresult)
1096 return -1;
1097 if (tokval.t_type)
1098 error(ERR_WARNING|ERR_OFFBY1,
1099 "trailing garbage after expression ignored");
1100 if (!is_simple(evalresult)) {
1101 error(ERR_NONFATAL|ERR_OFFBY1,
1102 "non-constant value given to `%s'", directives[i]);
1103 return -1;
1104 }
1105 return reloc_value(evalresult) != 0;
1106
1107 default:
1108 error(ERR_FATAL|ERR_OFFBY1,
1109 "preprocessor directive `%s' not yet implemented",
1110 directives[i]);
1111 free_tlist (origline);
1112 return -1; /* yeah, right */
1113 }
1114}
1115
1116/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001117 * Find out if a line contains a preprocessor directive, and deal
1118 * with it if so.
1119 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00001120 * If a directive _is_ found, we are expected to free_tlist() the
1121 * line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001122 *
1123 * Return values go like this:
1124 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00001125 * bit 0 is set if a directive was found (so the line gets freed)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001126 * bit 1 is set if a blank line should be emitted
1127 * bit 2 is set if a re-sync line number comment should be emitted
1128 *
1129 * (bits 1 and 2 are mutually exclusive in that the rest of the
1130 * preprocessor doesn't guarantee to be able to handle the case in
1131 * which both are set)
1132 */
1133static int do_directive (Token *tline) {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001134 int i, j, k, m, nparam, nolist;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001135 char *p, *mname;
1136 Include *inc;
1137 Context *ctx;
1138 Cond *cond;
1139 SMacro *smac, **smhead;
1140 MMacro *mmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001141 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
1142 Line *l;
1143 struct tokenval tokval;
1144 expr *evalresult;
1145
1146 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001147
1148 if (tline && tline->type == TOK_WHITESPACE)
1149 tline = tline->next;
1150 if (!tline || tline->type != TOK_PREPROC_ID ||
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001151 (tline->text[1]=='%' || tline->text[1]=='$' || tline->text[1]=='!'))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001152 return 0;
1153
1154 i = -1;
1155 j = sizeof(directives)/sizeof(*directives);
1156 while (j-i > 1) {
1157 k = (j+i) / 2;
1158 m = nasm_stricmp(tline->text, directives[k]);
1159 if (m == 0) {
1160 i = k;
1161 j = -2;
1162 break;
1163 } else if (m < 0) {
1164 j = k;
1165 } else
1166 i = k;
1167 }
1168
1169 /*
1170 * If we're in a non-emitting branch of a condition construct,
H. Peter Anvin76690a12002-04-30 20:52:49 +00001171 * or walking to the end of an already terminated %rep block,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001172 * we should ignore all directives except for condition
1173 * directives.
1174 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001175 if (((istk->conds && !emitting(istk->conds->state)) ||
1176 (istk->mstk && !istk->mstk->in_progress)) &&
1177 i != PP_IF && i != PP_ELIF &&
1178 i != PP_IFCTX && i != PP_ELIFCTX &&
1179 i != PP_IFDEF && i != PP_ELIFDEF &&
1180 i != PP_IFID && i != PP_ELIFID &&
1181 i != PP_IFIDN && i != PP_ELIFIDN &&
1182 i != PP_IFIDNI && i != PP_ELIFIDNI &&
1183 i != PP_IFNCTX && i != PP_ELIFNCTX &&
1184 i != PP_IFNDEF && i != PP_ELIFNDEF &&
1185 i != PP_IFNID && i != PP_ELIFNID &&
1186 i != PP_IFNIDN && i != PP_ELIFNIDN &&
1187 i != PP_IFNIDNI && i != PP_ELIFNIDNI &&
1188 i != PP_IFNNUM && i != PP_ELIFNNUM &&
1189 i != PP_IFNSTR && i != PP_ELIFNSTR &&
1190 i != PP_IFNUM && i != PP_ELIFNUM &&
1191 i != PP_IFSTR && i != PP_ELIFSTR &&
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001192 i != PP_ELSE && i != PP_ENDIF)
1193 return 0;
1194
1195 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001196 * If we're defining a macro or reading a %rep block, we should
1197 * ignore all directives except for %macro/%imacro (which
1198 * generate an error), %endm/%endmacro, and (only if we're in a
1199 * %rep block) %endrep.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001200 */
1201 if (defining && i != PP_MACRO && i != PP_IMACRO &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001202 i != PP_ENDMACRO && i != PP_ENDM &&
1203 (defining->name || i != PP_ENDREP))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001204 return 0;
1205
1206 if (j != -2) {
1207 error(ERR_NONFATAL|ERR_OFFBY1, "unknown preprocessor directive `%s'",
1208 tline->text);
1209 return 0; /* didn't get it */
1210 }
1211
1212 switch (i) {
1213
1214 case PP_CLEAR:
1215 if (tline->next)
1216 error(ERR_WARNING|ERR_OFFBY1,
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001217 "trailing garbage after `%%clear' ignored");
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001218 for (j=0; j<NHASH; j++) {
1219 while (mmacros[j]) {
1220 MMacro *m = mmacros[j];
1221 mmacros[j] = mmacros[j]->next;
1222 nasm_free (m->name);
1223 free_tlist (m->dlist);
1224 free_llist (m->expansion);
1225 nasm_free (m);
1226 }
1227 while (smacros[j]) {
1228 SMacro *s = smacros[j];
1229 smacros[j] = smacros[j]->next;
1230 nasm_free (s->name);
1231 free_tlist (s->expansion);
1232 nasm_free (s);
1233 }
1234 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001235 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001236 return 3;
1237
1238 case PP_INCLUDE:
1239 tline = tline->next;
1240 if (tline && tline->type == TOK_WHITESPACE)
1241 tline = tline->next;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001242 if (!tline || (tline->type != TOK_STRING &&
1243 tline->type != TOK_INTERNAL_STRING)) {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001244 error(ERR_NONFATAL|ERR_OFFBY1, "`%%include' expects a file name");
H. Peter Anvin76690a12002-04-30 20:52:49 +00001245 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001246 return 3; /* but we did _something_ */
1247 }
1248 if (tline->next)
1249 error(ERR_WARNING|ERR_OFFBY1,
1250 "trailing garbage after `%%include' ignored");
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001251 if (tline->type != TOK_INTERNAL_STRING) {
1252 p = tline->text+1; /* point past the quote to the name */
1253 p[strlen(p)-1] = '\0'; /* remove the trailing quote */
1254 } else
1255 p = tline->text; /* internal_string is easier */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001256 inc = nasm_malloc(sizeof(Include));
1257 inc->next = istk;
1258 inc->conds = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001259 inc->fp = inc_fopen(p);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001260 inc->fname = nasm_strdup(p);
1261 inc->lineno = inc->lineinc = 1;
1262 inc->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001263 inc->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001264 istk = inc;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001265 list->uplevel (LIST_INCLUDE);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001266 update_fileline(3); /* update __FILE__ and __LINE__ */
1267 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001268 return 5;
1269
1270 case PP_PUSH:
1271 tline = tline->next;
1272 if (tline && tline->type == TOK_WHITESPACE)
1273 tline = tline->next;
1274 if (!tline || tline->type != TOK_ID) {
1275 error(ERR_NONFATAL|ERR_OFFBY1,
1276 "`%%push' expects a context identifier");
H. Peter Anvin76690a12002-04-30 20:52:49 +00001277 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001278 return 3; /* but we did _something_ */
1279 }
1280 if (tline->next)
1281 error(ERR_WARNING|ERR_OFFBY1,
1282 "trailing garbage after `%%push' ignored");
1283 ctx = nasm_malloc(sizeof(Context));
1284 ctx->next = cstk;
1285 ctx->localmac = NULL;
1286 ctx->name = nasm_strdup(tline->text);
1287 ctx->number = unique++;
1288 cstk = ctx;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001289 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001290 break;
1291
1292 case PP_REPL:
1293 tline = tline->next;
1294 if (tline && tline->type == TOK_WHITESPACE)
1295 tline = tline->next;
1296 if (!tline || tline->type != TOK_ID) {
1297 error(ERR_NONFATAL|ERR_OFFBY1,
1298 "`%%repl' expects a context identifier");
H. Peter Anvin76690a12002-04-30 20:52:49 +00001299 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001300 return 3; /* but we did _something_ */
1301 }
1302 if (tline->next)
1303 error(ERR_WARNING|ERR_OFFBY1,
1304 "trailing garbage after `%%repl' ignored");
1305 if (!cstk)
1306 error(ERR_NONFATAL|ERR_OFFBY1,
1307 "`%%repl': context stack is empty");
1308 else {
1309 nasm_free (cstk->name);
1310 cstk->name = nasm_strdup(tline->text);
1311 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001312 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001313 break;
1314
1315 case PP_POP:
1316 if (tline->next)
1317 error(ERR_WARNING|ERR_OFFBY1,
1318 "trailing garbage after `%%pop' ignored");
1319 if (!cstk)
1320 error(ERR_NONFATAL|ERR_OFFBY1,
1321 "`%%pop': context stack is already empty");
1322 else
1323 ctx_pop();
H. Peter Anvin76690a12002-04-30 20:52:49 +00001324 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001325 break;
1326
1327 case PP_ERROR:
1328 tline = tline->next;
1329 if (tline && tline->type == TOK_WHITESPACE)
1330 tline = tline->next;
1331 if (!tline || tline->type != TOK_STRING) {
1332 error(ERR_NONFATAL|ERR_OFFBY1,
1333 "`%%error' expects an error string");
H. Peter Anvin76690a12002-04-30 20:52:49 +00001334 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001335 return 3; /* but we did _something_ */
1336 }
1337 if (tline->next)
1338 error(ERR_WARNING|ERR_OFFBY1,
1339 "trailing garbage after `%%error' ignored");
1340 p = tline->text+1; /* point past the quote to the name */
1341 p[strlen(p)-1] = '\0'; /* remove the trailing quote */
1342 error(ERR_NONFATAL|ERR_OFFBY1, "user error: %s", p);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001343 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001344 break;
1345
H. Peter Anvin76690a12002-04-30 20:52:49 +00001346 case PP_IF:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001347 case PP_IFCTX:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001348 case PP_IFDEF:
H. Peter Anvin76690a12002-04-30 20:52:49 +00001349 case PP_IFID:
1350 case PP_IFIDN:
1351 case PP_IFIDNI:
1352 case PP_IFNCTX:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001353 case PP_IFNDEF:
H. Peter Anvin76690a12002-04-30 20:52:49 +00001354 case PP_IFNID:
1355 case PP_IFNIDN:
1356 case PP_IFNIDNI:
1357 case PP_IFNNUM:
1358 case PP_IFNSTR:
1359 case PP_IFNUM:
1360 case PP_IFSTR:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001361 if (istk->conds && !emitting(istk->conds->state))
1362 j = COND_NEVER;
1363 else {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001364 j = if_condition(tline->next, i);
1365 tline->next = NULL; /* it got freed */
1366 free_tlist (origline);
1367 if (j < 0)
1368 return 3;
1369 else
1370 j = j ? COND_IF_TRUE : COND_IF_FALSE;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001371 }
1372 cond = nasm_malloc(sizeof(Cond));
1373 cond->next = istk->conds;
1374 cond->state = j;
1375 istk->conds = cond;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001376 return (j == COND_IF_TRUE ? 3 : 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001377
H. Peter Anvin76690a12002-04-30 20:52:49 +00001378 case PP_ELIF:
1379 case PP_ELIFCTX:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001380 case PP_ELIFDEF:
H. Peter Anvin76690a12002-04-30 20:52:49 +00001381 case PP_ELIFID:
1382 case PP_ELIFIDN:
1383 case PP_ELIFIDNI:
1384 case PP_ELIFNCTX:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001385 case PP_ELIFNDEF:
H. Peter Anvin76690a12002-04-30 20:52:49 +00001386 case PP_ELIFNID:
1387 case PP_ELIFNIDN:
1388 case PP_ELIFNIDNI:
1389 case PP_ELIFNNUM:
1390 case PP_ELIFNSTR:
1391 case PP_ELIFNUM:
1392 case PP_ELIFSTR:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001393 if (!istk->conds)
H. Peter Anvin76690a12002-04-30 20:52:49 +00001394 error(ERR_FATAL|ERR_OFFBY1, "`%s': no matching `%%if'",
1395 directives[i]);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001396 if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
1397 istk->conds->state = COND_NEVER;
1398 else {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001399 j = if_condition(tline->next, i);
1400 tline->next = NULL; /* it got freed */
1401 free_tlist (origline);
1402 if (j < 0)
1403 return 3;
1404 else
1405 istk->conds->state = j ? COND_IF_TRUE : COND_IF_FALSE;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001406 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001407 return (istk->conds->state == COND_IF_TRUE ? 5 : 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001408
1409 case PP_ELSE:
1410 if (tline->next)
1411 error(ERR_WARNING|ERR_OFFBY1,
1412 "trailing garbage after `%%else' ignored");
1413 if (!istk->conds)
1414 error(ERR_FATAL|ERR_OFFBY1,
1415 "`%%else': no matching `%%if'");
1416 if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
1417 istk->conds->state = COND_ELSE_FALSE;
1418 else
1419 istk->conds->state = COND_ELSE_TRUE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001420 free_tlist (origline);
1421 return 5;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001422
1423 case PP_ENDIF:
1424 if (tline->next)
1425 error(ERR_WARNING|ERR_OFFBY1,
1426 "trailing garbage after `%%endif' ignored");
1427 if (!istk->conds)
1428 error(ERR_FATAL|ERR_OFFBY1,
1429 "`%%endif': no matching `%%if'");
1430 cond = istk->conds;
1431 istk->conds = cond->next;
1432 nasm_free (cond);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001433 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001434 return 5;
1435
1436 case PP_MACRO:
1437 case PP_IMACRO:
1438 if (defining)
1439 error (ERR_FATAL|ERR_OFFBY1,
1440 "`%%%smacro': already defining a macro",
1441 (i == PP_IMACRO ? "i" : ""));
1442 tline = tline->next;
1443 if (tline && tline->type == TOK_WHITESPACE)
1444 tline = tline->next;
1445 if (!tline || tline->type != TOK_ID) {
1446 error (ERR_NONFATAL|ERR_OFFBY1,
1447 "`%%%smacro' expects a macro name",
1448 (i == PP_IMACRO ? "i" : ""));
1449 return 3;
1450 }
1451 defining = nasm_malloc(sizeof(MMacro));
1452 defining->name = nasm_strdup(tline->text);
1453 defining->casesense = (i == PP_MACRO);
1454 defining->plus = FALSE;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001455 defining->nolist = FALSE;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001456 defining->in_progress = FALSE;
1457 tline = tline->next;
1458 if (tline && tline->type == TOK_WHITESPACE)
1459 tline = tline->next;
1460 if (!tline || tline->type != TOK_NUMBER) {
1461 error (ERR_NONFATAL|ERR_OFFBY1,
1462 "`%%%smacro' expects a parameter count",
1463 (i == PP_IMACRO ? "i" : ""));
1464 defining->nparam_min = defining->nparam_max = 0;
1465 } else {
1466 defining->nparam_min = defining->nparam_max =
1467 readnum(tline->text, &j);
1468 if (j)
1469 error (ERR_NONFATAL|ERR_OFFBY1,
1470 "unable to parse parameter count `%s'", tline->text);
1471 }
1472 if (tline && tline->next && tline->next->type == TOK_OTHER &&
1473 !strcmp(tline->next->text, "-")) {
1474 tline = tline->next->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001475 if (tline && tline->type == TOK_OTHER &&
1476 !strcmp(tline->text, "*"))
1477 defining->nparam_max = INT_MAX;
1478 else if (!tline || tline->type != TOK_NUMBER)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001479 error (ERR_NONFATAL|ERR_OFFBY1,
1480 "`%%%smacro' expects a parameter count after `-'",
1481 (i == PP_IMACRO ? "i" : ""));
1482 else {
1483 defining->nparam_max = readnum(tline->text, &j);
1484 if (j)
1485 error (ERR_NONFATAL|ERR_OFFBY1,
1486 "unable to parse parameter count `%s'",
1487 tline->text);
1488 if (defining->nparam_min > defining->nparam_max)
1489 error (ERR_NONFATAL|ERR_OFFBY1,
1490 "minimum parameter count exceeds maximum");
1491 }
1492 }
1493 if (tline && tline->next && tline->next->type == TOK_OTHER &&
1494 !strcmp(tline->next->text, "+")) {
1495 tline = tline->next;
1496 defining->plus = TRUE;
1497 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001498 if (tline && tline->next && tline->next->type == TOK_ID &&
1499 !nasm_stricmp(tline->next->text, ".nolist")) {
1500 tline = tline->next;
1501 defining->nolist = TRUE;
1502 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001503 mmac = mmacros[hash(defining->name)];
1504 while (mmac) {
1505 if (!strcmp(mmac->name, defining->name) &&
1506 (mmac->nparam_min<=defining->nparam_max || defining->plus) &&
1507 (defining->nparam_min<=mmac->nparam_max || mmac->plus)) {
1508 error (ERR_WARNING|ERR_OFFBY1,
1509 "redefining multi-line macro `%s'", defining->name);
1510 break;
1511 }
1512 mmac = mmac->next;
1513 }
1514 /*
1515 * Handle default parameters.
1516 */
1517 if (tline && tline->next) {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001518 defining->dlist = tline->next;
1519 tline->next = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001520 count_mmac_params (defining->dlist, &defining->ndefs,
1521 &defining->defaults);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001522 } else {
1523 defining->dlist = NULL;
1524 defining->defaults = NULL;
1525 }
1526 defining->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001527 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001528 return 1;
1529
1530 case PP_ENDM:
1531 case PP_ENDMACRO:
1532 if (!defining) {
1533 error (ERR_NONFATAL|ERR_OFFBY1, "`%s': not defining a macro",
1534 tline->text);
1535 return 3;
1536 }
1537 k = hash(defining->name);
1538 defining->next = mmacros[k];
1539 mmacros[k] = defining;
1540 defining = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001541 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001542 return 5;
1543
H. Peter Anvin76690a12002-04-30 20:52:49 +00001544 case PP_ROTATE:
1545 if (tline->next && tline->next->type == TOK_WHITESPACE)
1546 tline = tline->next;
1547 t = expand_smacro(tline->next);
1548 tline->next = NULL;
1549 free_tlist (origline);
1550 tline = t;
1551 tptr = &t;
1552 tokval.t_type = TOKEN_INVALID;
1553 evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
1554 free_tlist (tline);
1555 if (!evalresult)
1556 return 3;
1557 if (tokval.t_type)
1558 error(ERR_WARNING|ERR_OFFBY1,
1559 "trailing garbage after expression ignored");
1560 if (!is_simple(evalresult)) {
1561 error(ERR_NONFATAL|ERR_OFFBY1,
1562 "non-constant value given to `%%rotate'");
1563 return 3;
1564 }
1565 mmac = istk->mstk;
1566 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
1567 mmac = mmac->next_active;
1568 if (!mmac)
1569 error(ERR_NONFATAL, "`%rotate' invoked outside a macro call");
1570 mmac->rotate = mmac->rotate + reloc_value(evalresult);
1571 if (mmac->rotate < 0)
1572 mmac->rotate = mmac->nparam - (-mmac->rotate) % mmac->nparam;
1573 mmac->rotate %= mmac->nparam;
1574 return 1;
1575
1576 case PP_REP:
1577 nolist = FALSE;
1578 tline = tline->next;
1579 if (tline->next && tline->next->type == TOK_WHITESPACE)
1580 tline = tline->next;
1581 if (tline->next && tline->next->type == TOK_ID &&
1582 !nasm_stricmp(tline->next->text, ".nolist")) {
1583 tline = tline->next;
1584 nolist = TRUE;
1585 }
1586 t = expand_smacro(tline->next);
1587 tline->next = NULL;
1588 free_tlist (origline);
1589 tline = t;
1590 tptr = &t;
1591 tokval.t_type = TOKEN_INVALID;
1592 evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
1593 free_tlist (tline);
1594 if (!evalresult)
1595 return 3;
1596 if (tokval.t_type)
1597 error(ERR_WARNING|ERR_OFFBY1,
1598 "trailing garbage after expression ignored");
1599 if (!is_simple(evalresult)) {
1600 error(ERR_NONFATAL|ERR_OFFBY1,
1601 "non-constant value given to `%%rep'");
1602 return 3;
1603 }
1604 defining = nasm_malloc(sizeof(MMacro));
1605 defining->name = NULL; /* flags this macro as a %rep block */
1606 defining->casesense = 0;
1607 defining->plus = FALSE;
1608 defining->nolist = nolist;
1609 defining->in_progress = reloc_value(evalresult) + 1;
1610 defining->nparam_min = defining->nparam_max = 0;
1611 defining->expansion = NULL;
1612 defining->next_active = istk->mstk;
1613 return 1;
1614
1615 case PP_ENDREP:
1616 if (!defining) {
1617 error (ERR_NONFATAL|ERR_OFFBY1,
1618 "`%%endrep': no matching `%%rep'");
1619 return 3;
1620 }
1621
1622 /*
1623 * Now we have a "macro" defined - although it has no name
1624 * and we won't be entering it in the hash tables - we must
1625 * push a macro-end marker for it on to istk->expansion.
1626 * After that, it will take care of propagating itself (a
1627 * macro-end marker line for a macro which is really a %rep
1628 * block will cause the macro to be re-expanded, complete
1629 * with another macro-end marker to ensure the process
1630 * continues) until the whole expansion is forcibly removed
1631 * from istk->expansion by a %exitrep.
1632 */
1633 l = nasm_malloc(sizeof(Line));
1634 l->next = istk->expansion;
1635 l->finishes = defining;
1636 l->first = NULL;
1637 istk->expansion = l;
1638
1639 istk->mstk = defining;
1640
1641 list->uplevel (defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
1642 defining = NULL;
1643 free_tlist (origline);
1644 return 1; /* the expansion will line-sync */
1645
1646 case PP_EXITREP:
1647 /*
1648 * We must search along istk->expansion until we hit a
1649 * macro-end marker for a macro with no name. Then we set
1650 * its `in_progress' flag to 0.
1651 */
1652 for (l = istk->expansion; l; l = l->next)
1653 if (l->finishes && !l->finishes->name)
1654 break;
1655
1656 if (l->finishes && !l->finishes->name)
1657 l->finishes->in_progress = 0;
1658 else
1659 error (ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
1660 free_tlist (origline);
1661 return 1; /* the end marker will line-sync */
1662
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001663 case PP_DEFINE:
1664 case PP_IDEFINE:
1665 tline = tline->next;
1666 if (tline && tline->type == TOK_WHITESPACE)
1667 tline = tline->next;
1668 if (!tline || (tline->type != TOK_ID &&
1669 (tline->type != TOK_PREPROC_ID ||
1670 tline->text[1] != '$'))) {
1671 error (ERR_NONFATAL|ERR_OFFBY1,
1672 "`%%%sdefine' expects a macro identifier",
1673 (i == PP_IDEFINE ? "i" : ""));
H. Peter Anvin76690a12002-04-30 20:52:49 +00001674 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001675 return 3;
1676 }
1677 mname = tline->text;
1678 if (tline->type == TOK_ID) {
1679 p = tline->text;
1680 smhead = &smacros[hash(mname)];
1681 } else {
1682 ctx = get_ctx (tline->text);
1683 if (ctx == NULL)
1684 return 3;
1685 else {
1686 p = tline->text+1;
1687 p += strspn(p, "$");
1688 smhead = &ctx->localmac;
1689 }
1690 }
1691 last = tline;
1692 param_start = tline = tline->next;
1693 nparam = 0;
1694 if (tline && tline->type == TOK_OTHER && !strcmp(tline->text, "(")) {
1695 /*
1696 * This macro has parameters.
1697 */
1698
1699 tline = tline->next;
1700 while (1) {
1701 if (tline && tline->type == TOK_WHITESPACE)
1702 tline = tline->next;
1703 if (!tline) {
1704 error (ERR_NONFATAL|ERR_OFFBY1,
1705 "parameter identifier expected");
H. Peter Anvin76690a12002-04-30 20:52:49 +00001706 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001707 return 3;
1708 }
1709 if (tline->type != TOK_ID) {
1710 error (ERR_NONFATAL|ERR_OFFBY1,
1711 "`%s': parameter identifier expected",
1712 tline->text);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001713 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001714 return 3;
1715 }
1716 tline->type = TOK_SMAC_PARAM + nparam++;
1717 tline = tline->next;
1718 if (tline && tline->type == TOK_WHITESPACE)
1719 tline = tline->next;
1720 if (tline && tline->type == TOK_OTHER &&
1721 !strcmp(tline->text, ",")) {
1722 tline = tline->next;
1723 continue;
1724 }
1725 if (!tline || tline->type != TOK_OTHER ||
1726 strcmp(tline->text, ")")) {
1727 error (ERR_NONFATAL|ERR_OFFBY1,
1728 "`)' expected to terminate macro template");
H. Peter Anvin76690a12002-04-30 20:52:49 +00001729 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001730 return 3;
1731 }
1732 break;
1733 }
1734 last = tline;
1735 tline = tline->next;
1736 }
1737 if (tline && tline->type == TOK_WHITESPACE)
1738 last = tline, tline = tline->next;
1739 macro_start = NULL;
1740 last->next = NULL;
1741 t = tline;
1742 while (t) {
1743 if (t->type == TOK_ID) {
1744 for (tt = param_start; tt; tt = tt->next)
1745 if (tt->type >= TOK_SMAC_PARAM &&
1746 !strcmp(tt->text, t->text))
1747 t->type = tt->type;
1748 }
1749 tt = t->next;
1750 t->next = macro_start;
1751 macro_start = t;
1752 t = tt;
1753 }
1754 /*
1755 * Good. We now have a macro name, a parameter count, and a
1756 * token list (in reverse order) for an expansion. We ought
1757 * to be OK just to create an SMacro, store it, and let
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001758 * free_tlist have the rest of the line (which we have
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001759 * carefully re-terminated after chopping off the expansion
1760 * from the end).
1761 */
1762 if (smacro_defined (mname, nparam, &smac)) {
1763 if (!smac)
1764 error (ERR_WARNING|ERR_OFFBY1,
1765 "single-line macro `%s' defined both with and"
1766 " without parameters", mname);
1767 else {
1768 /*
1769 * We're redefining, so we have to take over an
1770 * existing SMacro structure. This means freeing
1771 * what was already in it.
1772 */
1773 nasm_free (smac->name);
1774 free_tlist (smac->expansion);
1775 }
1776 } else {
1777 smac = nasm_malloc(sizeof(SMacro));
1778 smac->next = *smhead;
1779 *smhead = smac;
1780 }
1781 smac->name = nasm_strdup(p);
1782 smac->casesense = (i == PP_DEFINE);
1783 smac->nparam = nparam;
1784 smac->expansion = macro_start;
1785 smac->in_progress = FALSE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001786 free_tlist (origline);
1787 return 3;
1788
1789 case PP_ASSIGN:
1790 case PP_IASSIGN:
1791 tline = tline->next;
1792 if (tline && tline->type == TOK_WHITESPACE)
1793 tline = tline->next;
1794 if (!tline || (tline->type != TOK_ID &&
1795 (tline->type != TOK_PREPROC_ID ||
1796 tline->text[1] != '$'))) {
1797 error (ERR_NONFATAL|ERR_OFFBY1,
1798 "`%%%sassign' expects a macro identifier",
1799 (i == PP_IASSIGN ? "i" : ""));
1800 free_tlist (origline);
1801 return 3;
1802 }
1803 mname = tline->text;
1804 if (tline->type == TOK_ID) {
1805 p = tline->text;
1806 smhead = &smacros[hash(mname)];
1807 } else {
1808 ctx = get_ctx (tline->text);
1809 if (ctx == NULL) {
1810 free_tlist (origline);
1811 return 3;
1812 } else {
1813 p = tline->text+1;
1814 p += strspn(p, "$");
1815 smhead = &ctx->localmac;
1816 }
1817 }
1818 last = tline;
1819 tline = tline->next;
1820 last->next = NULL;
1821
1822 tline = expand_smacro (tline);
1823 t = tline;
1824 tptr = &t;
1825 tokval.t_type = TOKEN_INVALID;
1826 evalresult = evaluate (ppscan, tptr, &tokval, NULL, pass, error, NULL);
1827 free_tlist (tline);
1828 if (!evalresult) {
1829 free_tlist (origline);
1830 return 3;
1831 }
1832
1833 if (tokval.t_type)
1834 error(ERR_WARNING|ERR_OFFBY1,
1835 "trailing garbage after expression ignored");
1836
1837 if (!is_simple(evalresult)) {
1838 error(ERR_NONFATAL|ERR_OFFBY1,
1839 "non-constant value given to `%%%sassign'",
1840 (i == PP_IASSIGN ? "i" : ""));
1841 free_tlist (origline);
1842 return 3;
1843 }
1844
1845 macro_start = nasm_malloc(sizeof(*macro_start));
1846 macro_start->next = NULL;
1847 {
1848 char numbuf[20];
1849 sprintf(numbuf, "%ld", reloc_value(evalresult));
1850 macro_start->text = nasm_strdup(numbuf);
1851 }
1852 macro_start->mac = NULL;
1853 macro_start->type = TOK_NUMBER;
1854
1855 /*
1856 * We now have a macro name, an implicit parameter count of
1857 * zero, and a numeric token to use as an expansion. Create
1858 * and store an SMacro.
1859 */
1860 if (smacro_defined (mname, 0, &smac)) {
1861 if (!smac)
1862 error (ERR_WARNING|ERR_OFFBY1,
1863 "single-line macro `%s' defined both with and"
1864 " without parameters", mname);
1865 else {
1866 /*
1867 * We're redefining, so we have to take over an
1868 * existing SMacro structure. This means freeing
1869 * what was already in it.
1870 */
1871 nasm_free (smac->name);
1872 free_tlist (smac->expansion);
1873 }
1874 } else {
1875 smac = nasm_malloc(sizeof(SMacro));
1876 smac->next = *smhead;
1877 *smhead = smac;
1878 }
1879 smac->name = nasm_strdup(p);
1880 smac->casesense = (i == PP_ASSIGN);
1881 smac->nparam = 0;
1882 smac->expansion = macro_start;
1883 smac->in_progress = FALSE;
1884 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001885 return 3;
1886
1887 case PP_LINE:
1888 /*
1889 * Syntax is `%line nnn[+mmm] [filename]'
1890 */
1891 tline = tline->next;
1892 if (tline && tline->type == TOK_WHITESPACE)
1893 tline = tline->next;
1894 if (!tline || tline->type != TOK_NUMBER) {
1895 error (ERR_NONFATAL|ERR_OFFBY1, "`%%line' expects line number");
H. Peter Anvin76690a12002-04-30 20:52:49 +00001896 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001897 return 3;
1898 }
1899 k = readnum(tline->text, &j);
1900 m = 1;
1901 tline = tline->next;
1902 if (tline && tline->type == TOK_OTHER && !strcmp(tline->text, "+")) {
1903 tline = tline->next;
1904 if (!tline || tline->type != TOK_NUMBER) {
1905 error (ERR_NONFATAL|ERR_OFFBY1,
1906 "`%%line' expects line increment");
H. Peter Anvin76690a12002-04-30 20:52:49 +00001907 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001908 return 3;
1909 }
1910 m = readnum(tline->text, &j);
1911 tline = tline->next;
1912 }
1913 if (tline && tline->type == TOK_WHITESPACE)
1914 tline = tline->next;
1915 istk->lineno = k;
1916 istk->lineinc = m;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001917 update_fileline(3); /* update __FILE__ and __LINE__ */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001918 if (tline) {
1919 char *s = detoken(tline);
1920 nasm_free (istk->fname);
1921 istk->fname = s;
1922 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001923 free_tlist (origline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001924 return 5;
1925
1926 default:
1927 error(ERR_FATAL|ERR_OFFBY1,
1928 "preprocessor directive `%s' not yet implemented",
H. Peter Anvin76690a12002-04-30 20:52:49 +00001929 directives[i]);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001930 break;
1931 }
1932 return 3;
1933}
1934
1935/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001936 * Ensure that a macro parameter contains a condition code and
1937 * nothing else. Return the condition code index if so, or -1
1938 * otherwise.
1939 */
1940static int find_cc (Token *t) {
1941 Token *tt;
1942 int i, j, k, m;
1943
1944 if (t && t->type == TOK_WHITESPACE)
1945 t = t->next;
1946 if (t->type != TOK_ID)
1947 return -1;
1948 tt = t->next;
1949 if (tt && tt->type == TOK_WHITESPACE)
1950 tt = tt->next;
1951 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
1952 return -1;
1953
1954 i = -1;
1955 j = sizeof(conditions)/sizeof(*conditions);
1956 while (j-i > 1) {
1957 k = (j+i) / 2;
1958 m = nasm_stricmp(t->text, conditions[k]);
1959 if (m == 0) {
1960 i = k;
1961 j = -2;
1962 break;
1963 } else if (m < 0) {
1964 j = k;
1965 } else
1966 i = k;
1967 }
1968 if (j != -2)
1969 return -1;
1970 return i;
1971}
1972
1973/*
1974 * Expand MMacro-local things: parameter references (%0, %n, %+n,
1975 * %-n) and MMacro-local identifiers (%%foo).
1976 */
1977static Token *expand_mmac_params (Token *tline) {
1978 Token *t, *tt, *ttt, **tail, *thead;
1979
1980 tail = &thead;
1981 thead = NULL;
1982
1983 while (tline) {
1984 if (tline->type == TOK_PREPROC_ID &&
1985 (tline->text[1] == '+' || tline->text[1] == '-' ||
1986 tline->text[1] == '%' ||
1987 (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
1988 char *text = NULL;
1989 int type = 0, cc; /* type = 0 to placate optimisers */
1990 char tmpbuf[30];
1991 int n, i;
1992 MMacro *mac;
1993
1994 t = tline;
1995 tline = tline->next;
1996
1997 mac = istk->mstk;
1998 while (mac && !mac->name) /* avoid mistaking %reps for macros */
1999 mac = mac->next_active;
2000 if (!mac)
2001 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
2002 else switch (t->text[1]) {
2003 /*
2004 * We have to make a substitution of one of the
2005 * forms %1, %-1, %+1, %%foo, %0.
2006 */
2007 case '0':
2008 type = TOK_NUMBER;
2009 sprintf(tmpbuf, "%d", mac->nparam);
2010 text = nasm_strdup(tmpbuf);
2011 break;
2012 case '%':
2013 type = TOK_ID;
2014 sprintf(tmpbuf, "..@%lu.", mac->unique);
2015 text = nasm_malloc(strlen(tmpbuf)+strlen(t->text+2)+1);
2016 strcpy(text, tmpbuf);
2017 strcat(text, t->text+2);
2018 break;
2019 case '-':
2020 n = atoi(t->text+2)-1;
2021 if (n >= mac->nparam)
2022 tt = NULL;
2023 else {
2024 if (mac->nparam > 1)
2025 n = (n + mac->rotate) % mac->nparam;
2026 tt = mac->params[n];
2027 }
2028 cc = find_cc (tt);
2029 if (cc == -1) {
2030 error (ERR_NONFATAL|ERR_OFFBY1,
2031 "macro parameter %d is not a condition code",
2032 n+1);
2033 text = NULL;
2034 } else {
2035 type = TOK_ID;
2036 if (inverse_ccs[cc] == -1) {
2037 error (ERR_NONFATAL|ERR_OFFBY1,
2038 "condition code `%s' is not invertible",
2039 conditions[cc]);
2040 text = NULL;
2041 } else
2042 text = nasm_strdup(conditions[inverse_ccs[cc]]);
2043 }
2044 break;
2045 case '+':
2046 n = atoi(t->text+2)-1;
2047 if (n >= mac->nparam)
2048 tt = NULL;
2049 else {
2050 if (mac->nparam > 1)
2051 n = (n + mac->rotate) % mac->nparam;
2052 tt = mac->params[n];
2053 }
2054 cc = find_cc (tt);
2055 if (cc == -1) {
2056 error (ERR_NONFATAL|ERR_OFFBY1,
2057 "macro parameter %d is not a condition code",
2058 n+1);
2059 text = NULL;
2060 } else {
2061 type = TOK_ID;
2062 text = nasm_strdup(conditions[cc]);
2063 }
2064 break;
2065 default:
2066 n = atoi(t->text+1)-1;
2067 if (n >= mac->nparam)
2068 tt = NULL;
2069 else {
2070 if (mac->nparam > 1)
2071 n = (n + mac->rotate) % mac->nparam;
2072 tt = mac->params[n];
2073 }
2074 if (tt) {
2075 for (i=0; i<mac->paramlen[n]; i++) {
2076 ttt = *tail = nasm_malloc(sizeof(Token));
2077 ttt->next = NULL;
2078 tail = &ttt->next;
2079 ttt->type = tt->type;
2080 ttt->text = nasm_strdup(tt->text);
2081 ttt->mac = NULL;
2082 tt = tt->next;
2083 }
2084 }
2085 text = NULL; /* we've done it here */
2086 break;
2087 }
2088 nasm_free (t->text);
2089 nasm_free (t);
2090 if (text) {
2091 t = *tail = nasm_malloc(sizeof(Token));
2092 t->next = NULL;
2093 tail = &t->next;
2094 t->type = type;
2095 t->text = text;
2096 t->mac = NULL;
2097 }
2098 continue;
2099 } else {
2100 t = *tail = tline;
2101 tline = tline->next;
2102 t->mac = NULL;
2103 t->next = NULL;
2104 tail = &t->next;
2105 }
2106 }
2107 return thead;
2108}
2109
2110/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002111 * Expand all single-line macro calls made in the given line.
2112 * Return the expanded version of the line. The original is deemed
2113 * to be destroyed in the process. (In reality we'll just move
2114 * Tokens from input to output a lot of the time, rather than
2115 * actually bothering to destroy and replicate.)
2116 */
2117static Token *expand_smacro (Token *tline) {
2118 Token *t, *tt, *mstart, **tail, *thead;
2119 SMacro *head, *m;
2120 Token **params;
2121 int *paramsize;
2122 int nparam, sparam, brackets;
2123 char *p;
2124
2125 tail = &thead;
2126 thead = NULL;
2127
2128 while (tline) {
2129 while (tline && tline->type != TOK_ID &&
2130 (tline->type != TOK_PREPROC_ID || tline->text[1] != '$')) {
2131 if (tline->type == TOK_SMAC_END) {
2132 tline->mac->in_progress = FALSE;
2133 t = tline;
2134 tline = tline->next;
2135 nasm_free (t);
2136 } else {
2137 t = *tail = tline;
2138 tline = tline->next;
2139 t->mac = NULL;
2140 t->next = NULL;
2141 tail = &t->next;
2142 if (t->type == TOK_PS_OTHER) {
2143 /*
2144 * If we see a PS_OTHER, we must at the very
2145 * least restore its correct token type. We
2146 * should also check for a %$ token, since this
2147 * is the point at which we expand context-
2148 * local labels.
2149 */
2150 t->type = TOK_ID;
2151 if (t->text[0] == '%' && t->text[1] == '$') {
2152 Context *c = get_ctx (t->text);
2153 char *p, *q, buffer[40];
2154
2155 if (c) {
2156 q = t->text+1;
2157 q += strspn(q, "$");
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002158 sprintf(buffer, "..@%lu.", c->number);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002159 p = nasm_malloc (strlen(buffer)+strlen(q)+1);
2160 strcpy (p, buffer);
2161 strcat (p, q);
2162 nasm_free (t->text);
2163 t->text = p;
2164 }
2165 }
2166 }
2167 }
2168 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002169
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002170 if (!tline)
2171 break;
2172 /*
2173 * We've hit an identifier. As in is_mmacro below, we first
2174 * check whether the identifier is a single-line macro at
2175 * all, then think about checking for parameters if
2176 * necessary.
2177 */
2178 if (tline->type == TOK_ID) {
2179 head = smacros[hash(tline->text)];
2180 p = tline->text;
2181 } else {
2182 Context *ctx = get_ctx (tline->text);
2183 if (ctx) {
2184 p = tline->text+1;
2185 p += strspn(p, "$");
2186 head = ctx->localmac;
2187 } else {
2188 tline->type = TOK_OTHER; /* so it will get copied above */
2189 continue;
2190 }
2191 }
2192 for (m = head; m; m = m->next)
2193 if (!mstrcmp(m->name, p, m->casesense))
2194 break;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002195 if (!m || m->in_progress) {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002196 /*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002197 * Either we didn't find a macro, so this can't be a
2198 * macro call, or we found a macro which was already in
2199 * progress, in which case we don't _treat_ this as a
2200 * macro call. Copy it through and ignore it.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002201 */
2202 tline->type = TOK_PS_OTHER; /* so it will get copied above */
2203 continue;
2204 }
2205 mstart = tline;
2206 if (m->nparam == 0) {
2207 /*
2208 * Simple case: the macro is parameterless. Discard the
2209 * one token that the macro call took, and push the
2210 * expansion back on the to-do stack.
2211 */
2212 params = NULL;
2213 paramsize = NULL;
2214 } else {
2215 /*
2216 * Complicated case: at least one macro with this name
2217 * exists and takes parameters. We must find the
2218 * parameters in the call, count them, find the SMacro
2219 * that corresponds to that form of the macro call, and
2220 * substitute for the parameters when we expand. What a
2221 * pain.
2222 */
2223 nparam = sparam = 0;
2224 params = NULL;
2225 paramsize = NULL;
2226 tline = tline->next;
2227 if (tline && tline->type == TOK_WHITESPACE)
2228 tline = tline->next;
2229 if (!tline || tline->type != TOK_OTHER ||
2230 strcmp(tline->text, "(")) {
2231 /*
2232 * This macro wasn't called with parameters: ignore
2233 * the call. (Behaviour borrowed from gnu cpp.)
2234 */
2235 tline = mstart;
2236 tline->type = TOK_PS_OTHER;
2237 continue;
2238 }
2239 tline = tline->next;
2240 while (1) {
2241 if (tline && tline->type == TOK_WHITESPACE)
2242 tline = tline->next;
2243 if (!tline) {
2244 error(ERR_NONFATAL|ERR_OFFBY1,
2245 "macro call expects terminating `)'");
2246 break;
2247 }
2248 if (nparam >= sparam) {
2249 sparam += PARAM_DELTA;
2250 params = nasm_realloc (params, sparam*sizeof(Token *));
2251 paramsize = nasm_realloc (paramsize, sparam*sizeof(int));
2252 }
2253 params[nparam] = tline;
2254 paramsize[nparam] = 0;
2255 brackets = 0;
2256 if (tline && tline->type == TOK_OTHER &&
2257 !strcmp(tline->text, "{")) {
2258 params[nparam] = tline = tline->next;
2259 while (tline && (brackets > 0 ||
2260 tline->type != TOK_OTHER ||
2261 strcmp(tline->text, "}"))) {
2262 tline = tline->next;
2263 paramsize[nparam]++;
2264 }
2265 tline = tline->next;
2266 if (tline && tline->type == TOK_WHITESPACE)
2267 tline = tline->next;
2268 if (tline && (tline->type != TOK_OTHER ||
2269 (strcmp(tline->text, ")") &&
2270 strcmp(tline->text, ",")))) {
2271 error (ERR_NONFATAL|ERR_OFFBY1, "braces do not "
2272 "enclose all of macro parameter");
2273 }
2274 if (tline && tline->type == TOK_OTHER &&
2275 !strcmp(tline->text, ","))
2276 tline = tline->next;
2277 } else {
2278 while (tline && (brackets > 0 ||
2279 tline->type != TOK_OTHER ||
2280 (strcmp(tline->text, ",") &&
2281 strcmp(tline->text, ")")))) {
2282 if (tline->type == TOK_OTHER && !tline->text[1])
2283 brackets += (tline->text[0] == '(' ? 1 :
2284 tline->text[0] == ')' ? -1 : 0);
2285 tline = tline->next;
2286 paramsize[nparam]++;
2287 }
2288 }
2289 nparam++;
2290 if (tline && !strcmp(tline->text, ")"))
2291 break;
2292 if (tline && !strcmp(tline->text, ","))
2293 tline = tline->next;
2294 }
2295 while (m && m->nparam != nparam) {
2296 while ( (m = m->next) )
2297 if (!strcmp(m->name, mstart->text))
2298 break;
2299 }
2300 if (!m) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002301 error (ERR_WARNING|ERR_OFFBY1|ERR_WARN_MNP,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002302 "macro `%s' exists, but not taking %d parameters",
2303 mstart->text, nparam);
2304 nasm_free (params);
2305 nasm_free (paramsize);
2306 tline = mstart;
2307 tline->type = TOK_PS_OTHER;
2308 continue;
2309 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002310 }
2311 /*
2312 * Expand the macro: we are placed on the last token of the
2313 * call, so that we can easily split the call from the
2314 * following tokens. We also start by pushing an SMAC_END
2315 * token for the cycle removal.
2316 */
2317 t = tline;
2318 tline = tline->next;
2319 t->next = NULL;
2320 tt = nasm_malloc(sizeof(Token));
2321 tt->type = TOK_SMAC_END;
2322 tt->text = NULL;
2323 tt->mac = m;
2324 m->in_progress = TRUE;
2325 tt->next = tline;
2326 tline = tt;
2327 for (t = m->expansion; t; t = t->next) {
2328 if (t->type >= TOK_SMAC_PARAM) {
2329 Token *pcopy = tline, **ptail = &pcopy;
2330 Token *ttt, *pt;
2331 int i;
2332
2333 ttt = params[t->type - TOK_SMAC_PARAM];
2334 for (i=0; i<paramsize[t->type-TOK_SMAC_PARAM]; i++) {
2335 pt = *ptail = nasm_malloc(sizeof(Token));
2336 pt->next = tline;
2337 ptail = &pt->next;
2338 pt->text = nasm_strdup(ttt->text);
2339 pt->type = ttt->type;
2340 pt->mac = NULL;
2341 ttt = ttt->next;
2342 }
2343 tline = pcopy;
2344 } else {
2345 tt = nasm_malloc(sizeof(Token));
2346 tt->type = t->type;
2347 tt->text = nasm_strdup(t->text);
2348 tt->mac = NULL;
2349 tt->next = tline;
2350 tline = tt;
2351 }
2352 }
2353
2354 /*
2355 * Having done that, get rid of the macro call, and clean
2356 * up the parameters.
2357 */
2358 nasm_free (params);
2359 nasm_free (paramsize);
2360 free_tlist (mstart);
2361 }
2362
2363 return thead;
2364}
2365
2366/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002367 * Determine whether the given line constitutes a multi-line macro
2368 * call, and return the MMacro structure called if so. Doesn't have
2369 * to check for an initial label - that's taken care of in
2370 * expand_mmacro - but must check numbers of parameters. Guaranteed
2371 * to be called with tline->type == TOK_ID, so the putative macro
2372 * name is easy to find.
2373 */
2374static MMacro *is_mmacro (Token *tline, Token ***params_array) {
2375 MMacro *head, *m;
2376 Token **params;
2377 int nparam;
2378
2379 head = mmacros[hash(tline->text)];
2380
2381 /*
2382 * Efficiency: first we see if any macro exists with the given
2383 * name. If not, we can return NULL immediately. _Then_ we
2384 * count the parameters, and then we look further along the
2385 * list if necessary to find the proper MMacro.
2386 */
2387 for (m = head; m; m = m->next)
2388 if (!mstrcmp(m->name, tline->text, m->casesense))
2389 break;
2390 if (!m)
2391 return NULL;
2392
2393 /*
2394 * OK, we have a potential macro. Count and demarcate the
2395 * parameters.
2396 */
2397 count_mmac_params (tline->next, &nparam, &params);
2398
2399 /*
2400 * So we know how many parameters we've got. Find the MMacro
2401 * structure that handles this number.
2402 */
2403 while (m) {
2404 if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max)) {
2405 /*
2406 * This one is right. Just check if cycle removal
2407 * prohibits us using it before we actually celebrate...
2408 */
2409 if (m->in_progress) {
2410 error (ERR_NONFATAL|ERR_OFFBY1,
2411 "self-reference in multi-line macro `%s'",
2412 m->name);
2413 nasm_free (params);
2414 return NULL;
2415 }
2416 /*
2417 * It's right, and we can use it. Add its default
2418 * parameters to the end of our list if necessary.
2419 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00002420 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
2421 params = nasm_realloc (params, ((m->nparam_min+m->ndefs+1) *
2422 sizeof(*params)));
2423 while (nparam < m->nparam_min + m->ndefs) {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002424 params[nparam] = m->defaults[nparam - m->nparam_min];
2425 nparam++;
2426 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002427 }
2428 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002429 * If we've gone over the maximum parameter count (and
2430 * we're in Plus mode), ignore parameters beyond
2431 * nparam_max.
2432 */
2433 if (m->plus && nparam > m->nparam_max)
2434 nparam = m->nparam_max;
2435 /*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002436 * Then terminate the parameter list, and leave.
2437 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00002438 if (!params) { /* need this special case */
2439 params = nasm_malloc(sizeof(*params));
2440 nparam = 0;
2441 }
2442 params[nparam] = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002443 *params_array = params;
2444 return m;
2445 }
2446 /*
2447 * This one wasn't right: look for the next one with the
2448 * same name.
2449 */
2450 for (m = m->next; m; m = m->next)
2451 if (!mstrcmp(m->name, tline->text, m->casesense))
2452 break;
2453 }
2454
2455 /*
2456 * After all that, we didn't find one with the right number of
2457 * parameters. Issue a warning, and fail to expand the macro.
2458 */
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002459 error (ERR_WARNING|ERR_OFFBY1|ERR_WARN_MNP,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002460 "macro `%s' exists, but not taking %d parameters",
2461 tline->text, nparam);
2462 nasm_free (params);
2463 return NULL;
2464}
2465
2466/*
2467 * Expand the multi-line macro call made by the given line, if
2468 * there is one to be expanded. If there is, push the expansion on
2469 * istk->expansion and return 1 or 2, as according to whether a
2470 * line sync is needed (2 if it is). Otherwise return 0.
2471 */
2472static int expand_mmacro (Token *tline) {
H. Peter Anvin76690a12002-04-30 20:52:49 +00002473 Token *label = NULL, **params, *t, *tt, *last = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002474 MMacro *m = NULL;
2475 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002476 int i, nparam, *paramlen;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002477 int need_sync = FALSE;
2478
2479 t = tline;
2480 if (t && t->type == TOK_WHITESPACE)
2481 t = t->next;
2482 if (t && t->type == TOK_ID) {
2483 m = is_mmacro (t, &params);
2484 if (!m) {
2485 /*
2486 * We have an id which isn't a macro call. We'll assume
2487 * it might be a label; we'll also check to see if a
2488 * colon follows it. Then, if there's another id after
2489 * that lot, we'll check it again for macro-hood.
2490 */
2491 last = t, t = t->next;
2492 if (t && t->type == TOK_WHITESPACE)
2493 last = t, t = t->next;
2494 if (t && t->type == TOK_OTHER && !strcmp(t->text, ":"))
2495 last = t, t = t->next;
2496 if (t && t->type == TOK_WHITESPACE)
2497 last = t, t = t->next;
2498 if (t && t->type == TOK_ID) {
2499 m = is_mmacro(t, &params);
2500 if (m) {
2501 last->next = NULL;
2502 label = tline;
2503 tline = t;
2504 }
2505 }
2506 }
2507 }
2508 if (!m)
2509 return 0;
2510
2511 /*
2512 * If we're not already inside another macro expansion, we'd
2513 * better push a line synchronisation to ensure we stay put on
2514 * line numbering.
2515 */
2516 if (!istk->expansion)
2517 need_sync = TRUE;
2518
2519 /*
2520 * Fix up the parameters: this involves stripping leading and
2521 * trailing whitespace, then stripping braces if they are
2522 * present.
2523 */
2524 for (nparam = 0; params[nparam]; nparam++);
2525 paramlen = nparam ? nasm_malloc(nparam*sizeof(*paramlen)) : NULL;
2526
2527 for (i = 0; params[i]; i++) {
2528 int brace = FALSE;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002529 int comma = (!m->plus || i < nparam-1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002530
2531 t = params[i];
2532 if (t && t->type == TOK_WHITESPACE)
2533 t = t->next;
2534 if (t && t->type == TOK_OTHER && !strcmp(t->text, "{"))
2535 t = t->next, brace = TRUE, comma = FALSE;
2536 params[i] = t;
2537 paramlen[i] = 0;
2538 while (t) {
2539 if (!t) /* end of param because EOL */
2540 break;
2541 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002542 break; /* ... because we have hit a comma */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002543 if (comma && t->type == TOK_WHITESPACE &&
2544 t->next->type == TOK_OTHER && !strcmp(t->next->text, ","))
2545 break; /* ... or a space then a comma */
2546 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002547 break; /* ... or a brace */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002548 t = t->next;
2549 paramlen[i]++;
2550 }
2551 }
2552
2553 /*
2554 * OK, we have a MMacro structure together with a set of
2555 * parameters. We must now go through the expansion and push
H. Peter Anvin76690a12002-04-30 20:52:49 +00002556 * copies of each Line on to istk->expansion. Substitution of
2557 * parameter tokens and macro-local tokens doesn't get done
2558 * until the single-line macro substitution process; this is
2559 * because delaying them allows us to change the semantics
2560 * later through %rotate.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002561 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00002562 * First, push an end marker on to istk->expansion, mark this
2563 * macro as in progress, and set up its invocation-specific
2564 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002565 */
2566 ll = nasm_malloc(sizeof(Line));
2567 ll->next = istk->expansion;
2568 ll->finishes = m;
2569 ll->first = NULL;
2570 istk->expansion = ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002571
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002572 m->in_progress = TRUE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002573 m->params = params;
2574 m->iline = tline;
2575 m->nparam = nparam;
2576 m->rotate = 0;
2577 m->paramlen = paramlen;
2578 m->unique = unique++;
2579
2580 m->next_active = istk->mstk;
2581 istk->mstk = m;
2582
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002583 for (l = m->expansion; l; l = l->next) {
2584 Token **tail;
2585
2586 ll = nasm_malloc(sizeof(Line));
2587 ll->next = istk->expansion;
2588 ll->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002589 ll->first = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002590 tail = &ll->first;
2591
2592 for (t = l->first; t; t = t->next) {
H. Peter Anvin76690a12002-04-30 20:52:49 +00002593 tt = *tail = nasm_malloc(sizeof(Token));
2594 tt->next = NULL;
2595 tail = &tt->next;
2596 tt->type = t->type;
2597 tt->text = nasm_strdup(t->text);
2598 tt->mac = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002599 }
2600
2601 istk->expansion = ll;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002602
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002603 }
2604
2605 /*
2606 * If we had a label, push it on the front of the first line of
2607 * the macro expansion.
2608 */
2609 if (label) {
2610 last->next = istk->expansion->first;
2611 istk->expansion->first = label;
2612 }
2613
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002614 list->uplevel (m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2615
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002616 return need_sync ? 2 : 1;
2617}
2618
H. Peter Anvin76690a12002-04-30 20:52:49 +00002619static void pp_reset (char *file, int apass, efunc errfunc, evalfunc eval,
2620 ListGen *listgen) {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002621 int h;
2622
2623 error = errfunc;
2624 cstk = NULL;
2625 linesync = outline = NULL;
2626 istk = nasm_malloc(sizeof(Include));
2627 istk->next = NULL;
2628 istk->conds = NULL;
2629 istk->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002630 istk->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002631 istk->fp = fopen(file, "r");
2632 istk->fname = nasm_strdup(file);
2633 istk->lineno = istk->lineinc = 1;
2634 if (!istk->fp)
2635 error (ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'", file);
2636 defining = NULL;
2637 for (h=0; h<NHASH; h++) {
2638 mmacros[h] = NULL;
2639 smacros[h] = NULL;
2640 }
2641 unique = 0;
2642 stdmacpos = stdmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002643 any_extrastdmac = (extrastdmac != NULL);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002644 list = listgen;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002645 evaluate = eval;
2646 pass = apass;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002647}
2648
2649static char *pp_getline (void) {
2650 char *line;
2651 Token *tline;
2652 int ret;
2653
2654 if (outline) {
2655 line = outline;
2656 outline = NULL;
2657 return line;
2658 }
2659
2660 while (1) {
2661 /*
2662 * Fetch a tokenised line, either from the macro-expansion
2663 * buffer or from the input file.
2664 */
2665 tline = NULL;
2666 while (istk->expansion && istk->expansion->finishes) {
2667 Line *l = istk->expansion;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002668 if (!l->finishes->name && l->finishes->in_progress > 1) {
2669 Line *ll;
2670
2671 /*
2672 * This is a macro-end marker for a macro with no
2673 * name, which means it's not really a macro at all
2674 * but a %rep block, and the `in_progress' field is
2675 * more than 1, meaning that we still need to
2676 * repeat. (1 means the natural last repetition; 0
2677 * means termination by %exitrep.) We have
2678 * therefore expanded up to the %endrep, and must
2679 * push the whole block on to the expansion buffer
2680 * again. We don't bother to remove the macro-end
2681 * marker: we'd only have to generate another one
2682 * if we did.
2683 */
2684 l->finishes->in_progress--;
2685 for (l = l->finishes->expansion; l; l = l->next) {
2686 Token *t, *tt, **tail;
2687
2688 ll = nasm_malloc(sizeof(Line));
2689 ll->next = istk->expansion;
2690 ll->finishes = NULL;
2691 ll->first = NULL;
2692 tail = &ll->first;
2693
2694 for (t = l->first; t; t = t->next) {
2695 if (t->text) {
2696 tt = *tail = nasm_malloc(sizeof(Token));
2697 tt->next = NULL;
2698 tail = &tt->next;
2699 tt->type = t->type;
2700 tt->text = nasm_strdup(t->text);
2701 tt->mac = NULL;
2702 }
2703 }
2704
2705 istk->expansion = ll;
2706 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002707 line_sync();
H. Peter Anvin76690a12002-04-30 20:52:49 +00002708 } else {
2709 if (istk->mstk->name) {
2710 /*
2711 * This was a real macro call, not a %rep, and
2712 * therefore the parameter information needs to
2713 * be freed.
2714 */
2715 nasm_free(istk->mstk->params);
2716 free_tlist(istk->mstk->iline);
2717 nasm_free(istk->mstk->paramlen);
2718 }
2719 istk->mstk = istk->mstk->next_active;
2720 l->finishes->in_progress = FALSE;
2721 istk->expansion = l->next;
2722 nasm_free (l);
2723 list->downlevel (LIST_MACRO);
2724 if (!istk->expansion)
2725 line_sync();
2726 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002727 }
2728 if (istk->expansion) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002729 char *p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002730 Line *l = istk->expansion;
2731 tline = l->first;
2732 istk->expansion = l->next;
2733 nasm_free (l);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002734 p = detoken(tline);
2735 list->line (LIST_MACRO, p);
2736 nasm_free(p);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002737 if (!istk->expansion)
2738 line_sync();
2739 } else {
2740 line = read_line();
2741 while (!line) {
2742 /*
2743 * The current file has ended; work down the istk
2744 * until we find a file we can read from.
2745 */
2746 Include *i;
2747 fclose(istk->fp);
2748 if (istk->conds)
2749 error(ERR_FATAL, "expected `%%endif' before end of file");
2750 i = istk;
2751 istk = istk->next;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002752 list->downlevel (LIST_INCLUDE);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002753 nasm_free (i->fname);
2754 nasm_free (i);
2755 if (!istk)
2756 return NULL;
2757 else
2758 line_sync();
H. Peter Anvin76690a12002-04-30 20:52:49 +00002759 update_fileline(3); /* update __FILE__ and __LINE__ */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002760 line = read_line();
2761 }
2762 line = prepreproc(line);
2763 tline = tokenise(line);
2764 nasm_free (line);
2765 }
2766
2767 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002768 * We must expand MMacro parameters and MMacro-local labels
2769 * _before_ we plunge into directive processing, to cope
2770 * with things like `%define something %1' such as STRUC
2771 * uses. Unless we're _defining_ a MMacro, in which case
2772 * those tokens should be left alone to go into the
2773 * definition.
2774 */
2775 if (!defining)
2776 tline = expand_mmac_params(tline);
2777
2778 /*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002779 * Check the line to see if it's a preprocessor directive.
2780 */
2781 ret = do_directive(tline);
2782 if (ret & 1) {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002783 if (ret & 4)
2784 line_sync();
2785 if ((ret & 2) && !stdmacpos) {/* give a blank line to the output */
2786 outline = nasm_strdup("");
2787 break;
2788 }
2789 else
2790 continue;
2791 } else if (defining) {
2792 /*
2793 * We're defining a multi-line macro. We emit nothing
2794 * at all, not even a blank line (when we finish
2795 * defining the macro, we'll emit a line-number
2796 * directive so that we keep sync properly), and just
2797 * shove the tokenised line on to the macro definition.
2798 */
2799 Line *l = nasm_malloc(sizeof(Line));
2800 l->next = defining->expansion;
2801 l->first = tline;
2802 l->finishes = FALSE;
2803 defining->expansion = l;
2804 continue;
2805 } else if (istk->conds && !emitting(istk->conds->state)) {
2806 /*
2807 * We're in a non-emitting branch of a condition block.
2808 * Emit nothing at all, not even a blank line: when we
2809 * emerge from the condition we'll give a line-number
2810 * directive so we keep our place correctly.
2811 */
2812 free_tlist(tline);
2813 continue;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002814 } else if (istk->mstk && !istk->mstk->in_progress) {
2815 /*
2816 * We're in a %rep block which has been terminated, so
2817 * we're walking through to the %endrep without
2818 * emitting anything. Emit nothing at all, not even a
2819 * blank line: when we emerge from the %rep block we'll
2820 * give a line-number directive so we keep our place
2821 * correctly.
2822 */
2823 free_tlist(tline);
2824 continue;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002825 } else {
2826 tline = expand_smacro(tline);
2827 ret = expand_mmacro(tline);
2828 if (!ret) {
2829 /*
2830 * De-tokenise the line again, and emit it.
2831 */
2832 line = detoken(tline);
2833 free_tlist (tline);
2834 outline = line;
2835 break;
2836 } else {
2837 if (ret == 2)
2838 line_sync();
2839 continue; /* expand_mmacro calls free_tlist */
2840 }
2841 }
2842 }
2843
2844 /*
2845 * Once we're out of this loop, outline _must_ be non-NULL. The
2846 * only question is whether linesync is NULL or not.
2847 */
2848 if (linesync) {
2849 line = linesync;
2850 linesync = NULL;
2851 } else {
2852 line = outline;
2853 outline = NULL;
2854 }
2855 return line;
2856}
2857
2858static void pp_cleanup (void) {
2859 int h;
2860
2861 if (defining) {
2862 error (ERR_NONFATAL, "end of file while still defining macro `%s'",
2863 defining->name);
2864 nasm_free (defining->name);
2865 free_tlist (defining->dlist);
2866 free_llist (defining->expansion);
2867 nasm_free (defining);
2868 }
2869 nasm_free (linesync); /* might just be necessary */
2870 nasm_free (outline); /* really shouldn't be necessary */
2871 while (cstk)
2872 ctx_pop();
2873 for (h=0; h<NHASH; h++) {
2874 while (mmacros[h]) {
2875 MMacro *m = mmacros[h];
2876 mmacros[h] = mmacros[h]->next;
2877 nasm_free (m->name);
2878 free_tlist (m->dlist);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002879 nasm_free (m->defaults);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002880 free_llist (m->expansion);
2881 nasm_free (m);
2882 }
2883 while (smacros[h]) {
2884 SMacro *s = smacros[h];
2885 smacros[h] = smacros[h]->next;
2886 nasm_free (s->name);
2887 free_tlist (s->expansion);
2888 nasm_free (s);
2889 }
2890 }
2891 while (istk) {
2892 Include *i = istk;
2893 istk = istk->next;
2894 fclose(i->fp);
2895 nasm_free (i->fname);
2896 nasm_free (i);
2897 }
2898 while (cstk)
2899 ctx_pop();
2900}
2901
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002902void pp_include_path (char *path) {
2903 IncPath *i;
2904
2905 i = nasm_malloc(sizeof(IncPath));
2906 i->path = nasm_strdup(path);
2907 i->next = ipath;
2908
2909 ipath = i;
2910}
2911
2912void pp_pre_include (char *fname) {
2913 Token *inc, *space, *name;
2914 Line *l;
2915
2916 inc = nasm_malloc(sizeof(Token));
2917 inc->next = space = nasm_malloc(sizeof(Token));
2918 space->next = name = nasm_malloc(sizeof(Token));
2919 name->next = NULL;
2920
2921 inc->type = TOK_PREPROC_ID;
2922 inc->text = nasm_strdup("%include");
2923 space->type = TOK_WHITESPACE;
2924 space->text = nasm_strdup(" ");
2925 name->type = TOK_INTERNAL_STRING;
2926 name->text = nasm_strdup(fname);
2927
2928 inc->mac = space->mac = name->mac = NULL;
2929
2930 l = nasm_malloc(sizeof(Line));
2931 l->next = predef;
2932 l->first = inc;
2933 l->finishes = FALSE;
2934 predef = l;
2935}
2936
2937void pp_pre_define (char *definition) {
2938 Token *def, *space, *name;
2939 Line *l;
2940 char *equals;
2941
2942 equals = strchr(definition, '=');
2943
2944 def = nasm_malloc(sizeof(Token));
2945 def->next = space = nasm_malloc(sizeof(Token));
2946 if (equals)
2947 *equals = ' ';
2948 space->next = name = tokenise(definition);
2949 if (equals)
2950 *equals = '=';
2951
2952 def->type = TOK_PREPROC_ID;
2953 def->text = nasm_strdup("%define");
2954 space->type = TOK_WHITESPACE;
2955 space->text = nasm_strdup(" ");
2956
2957 def->mac = space->mac = NULL;
2958
2959 l = nasm_malloc(sizeof(Line));
2960 l->next = predef;
2961 l->first = def;
2962 l->finishes = FALSE;
2963 predef = l;
2964}
2965
H. Peter Anvin76690a12002-04-30 20:52:49 +00002966void pp_extra_stdmac (char **macros) {
2967 extrastdmac = macros;
2968}
2969
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002970Preproc nasmpp = {
2971 pp_reset,
2972 pp_getline,
2973 pp_cleanup
2974};