NASM 0.95
[platform/upstream/nasm.git] / preproc.c
1 /* 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>
16
17 #include "nasm.h"
18 #include "nasmlib.h"
19
20 typedef struct SMacro SMacro;
21 typedef struct MMacro MMacro;
22 typedef struct Context Context;
23 typedef struct Token Token;
24 typedef struct Line Line;
25 typedef struct Include Include;
26 typedef struct Cond Cond;
27 typedef struct IncPath IncPath;
28
29 /*
30  * Store the definition of a single-line macro.
31  */
32 struct SMacro {
33     SMacro *next;
34     char *name;
35     int casesense;
36     int nparam;
37     int in_progress;
38     Token *expansion;
39 };
40
41 /*
42  * Store the definition of a multi-line macro.
43  */
44 struct MMacro {
45     MMacro *next;
46     char *name;
47     int casesense;
48     int nparam_min, nparam_max;
49     int plus;                          /* is the last parameter greedy? */
50     int nolist;                        /* is this macro listing-inhibited? */
51     int in_progress;
52     Token **defaults, *dlist;
53     Line *expansion;
54 };
55
56 /*
57  * The context stack is composed of a linked list of these.
58  */
59 struct Context {
60     Context *next;
61     SMacro *localmac;
62     char *name;
63     unsigned long number;
64 };
65
66 /*
67  * This is the internal form which we break input lines up into.
68  * Typically stored in linked lists.
69  *
70  * TOK_PS_OTHER is a token type used internally within
71  * expand_smacro(), to denote a token which has already been
72  * checked for being a potential macro, but may still be a context-
73  * local label.
74  *
75  * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
76  * necessarily used as-is, but is intended to denote the number of
77  * the substituted parameter. So in the definition
78  *
79  *     %define a(x,y) ( (x) & ~(y) )
80  * 
81  * the token representing `x' will have its type changed to
82  * TOK_SMAC_PARAM, but the one representing `y' will be
83  * TOK_SMAC_PARAM+1.
84  *
85  * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
86  * which doesn't need quotes around it. Used in the pre-include
87  * mechanism as an alternative to trying to find a sensible type of
88  * quote to use on the filename we were passed.
89  */
90 struct Token {
91     Token *next;
92     char *text;
93     SMacro *mac;                       /* associated macro for TOK_MAC_END */
94     int type;
95 };
96 enum {
97     TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
98     TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_PS_OTHER, TOK_SMAC_PARAM,
99     TOK_INTERNAL_STRING
100 };
101
102 /*
103  * Multi-line macro definitions are stored as a linked list of
104  * these, which is essentially a container to allow several linked
105  * lists of Tokens.
106  * 
107  * Note that in this module, linked lists are treated as stacks
108  * wherever possible. For this reason, Lines are _pushed_ on to the
109  * `expansion' field in MMacro structures, so that the linked list,
110  * if walked, would give the macro lines in reverse order; this
111  * means that we can walk the list when expanding a macro, and thus
112  * push the lines on to the `expansion' field in _istk_ in reverse
113  * order (so that when popped back off they are in the right
114  * order). It may seem cockeyed, and it relies on my design having
115  * an even number of steps in, but it works...
116  *
117  * Some of these structures, rather than being actual lines, are
118  * markers delimiting the end of the expansion of a given macro.
119  * This is for use in the cycle-tracking code. Such structures have
120  * `finishes' non-NULL, and `first' NULL. All others have
121  * `finishes' NULL, but `first' may still be NULL if the line is
122  * blank.
123  */
124 struct Line {
125     Line *next;
126     MMacro *finishes;
127     Token *first;
128 };
129
130 /*
131  * To handle an arbitrary level of file inclusion, we maintain a
132  * stack (ie linked list) of these things.
133  */
134 struct Include {
135     Include *next;
136     FILE *fp;
137     Cond *conds;
138     Line *expansion;
139     char *fname;
140     int lineno, lineinc;
141 };
142
143 /*
144  * Include search path. This is simply a list of strings which get
145  * prepended, in turn, to the name of an include file, in an
146  * attempt to find the file if it's not in the current directory.
147  */
148 struct IncPath {
149     IncPath *next;
150     char *path;
151 };
152
153 /*
154  * Conditional assembly: we maintain a separate stack of these for
155  * each level of file inclusion. (The only reason we keep the
156  * stacks separate is to ensure that a stray `%endif' in a file
157  * included from within the true branch of a `%if' won't terminate
158  * it and cause confusion: instead, rightly, it'll cause an error.)
159  */
160 struct Cond {
161     Cond *next;
162     int state;
163 };
164 enum {
165     /*
166      * These states are for use just after %if or %elif: IF_TRUE
167      * means the condition has evaluated to truth so we are
168      * currently emitting, whereas IF_FALSE means we are not
169      * currently emitting but will start doing so if a %else comes
170      * up. In these states, all directives are admissible: %elif,
171      * %else and %endif. (And of course %if.)
172      */
173     COND_IF_TRUE, COND_IF_FALSE,
174     /*
175      * These states come up after a %else: ELSE_TRUE means we're
176      * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
177      * any %elif or %else will cause an error.
178      */
179     COND_ELSE_TRUE, COND_ELSE_FALSE,
180     /*
181      * This state means that we're not emitting now, and also that
182      * nothing until %endif will be emitted at all. It's for use in
183      * two circumstances: (i) when we've had our moment of emission
184      * and have now started seeing %elifs, and (ii) when the
185      * condition construct in question is contained within a
186      * non-emitting branch of a larger condition construct.
187      */
188     COND_NEVER
189 };
190 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
191
192 /*
193  * Condition codes. Note that we use c_ prefix not C_ because C_ is
194  * used in nasm.h for the "real" condition codes. At _this_ level,
195  * we treat CXZ and ECXZ as condition codes, albeit non-invertible
196  * ones, so we need a different enum...
197  */
198 static char *conditions[] = {
199     "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
200     "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
201     "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
202 };
203 enum {
204     c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
205     c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
206     c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
207 };
208 static int inverse_ccs[] = {
209     c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
210     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,
211     c_Z, c_NO, c_NP, c_PO, c_PE, c_NS, c_NZ
212 };
213
214 static Context *cstk;
215 static Include *istk;
216 static IncPath *ipath = NULL;
217
218 static efunc error;
219
220 static unsigned long unique;           /* unique identifier numbers */
221
222 static char *linesync, *outline;
223
224 static Line *predef = NULL;
225
226 static ListGen *list;
227
228 /*
229  * The number of hash values we use for the macro lookup tables.
230  */
231 #define NHASH 31
232
233 /*
234  * The current set of multi-line macros we have defined.
235  */
236 static MMacro *mmacros[NHASH];
237
238 /*
239  * The current set of single-line macros we have defined.
240  */
241 static SMacro *smacros[NHASH];
242
243 /*
244  * The multi-line macro we are currently defining, if any.
245  */
246 static MMacro *defining;
247
248 /*
249  * The number of macro parameters to allocate space for at a time.
250  */
251 #define PARAM_DELTA 16
252
253 /*
254  * The standard macro set: defined as `static char *stdmac[]'. Also
255  * gives our position in the macro set, when we're processing it.
256  */
257 #include "macros.c"
258 static char **stdmacpos;
259
260 /*
261  * The pre-preprocessing stage... This function translates line
262  * number indications as they emerge from GNU cpp (`# lineno "file"
263  * flags') into NASM preprocessor line number indications (`%line
264  * lineno file').
265  */
266 static char *prepreproc(char *line) {
267     int lineno, fnlen;
268     char *fname, *oldline;
269
270     if (line[0] == '#' && line[1] == ' ') {
271         oldline = line;
272         fname = oldline+2;
273         lineno = atoi(fname);
274         fname += strspn(fname, "0123456789 ");
275         if (*fname == '"')
276             fname++;
277         fnlen = strcspn(fname, "\"");
278         line = nasm_malloc(20+fnlen);
279         sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);
280         nasm_free (oldline);
281     }
282     return line;
283 }
284
285 /*
286  * The hash function for macro lookups. Note that due to some
287  * macros having case-insensitive names, the hash function must be
288  * invariant under case changes. We implement this by applying a
289  * perfectly normal hash function to the uppercase of the string.
290  */
291 static int hash(char *s) {
292     /*
293      * Powers of three, mod 31.
294      */
295     static const int multipliers[] = {
296         1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
297         30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
298     };
299     int h = 0;
300     int i = 0;
301
302     while (*s) {
303         h += multipliers[i] * (unsigned char) (toupper(*s));
304         s++;
305         if (++i >= sizeof(multipliers)/sizeof(*multipliers))
306             i = 0;
307     }
308     h %= NHASH;
309     return h;
310 }
311
312 /*
313  * Free a linked list of tokens.
314  */
315 static void free_tlist (Token *list) {
316     Token *t;
317     while (list) {
318         t = list;
319         list = list->next;
320         nasm_free (t->text);
321         nasm_free (t);
322     }
323 }
324
325 /*
326  * Free a linked list of lines.
327  */
328 static void free_llist (Line *list) {
329     Line *l;
330     while (list) {
331         l = list;
332         list = list->next;
333         free_tlist (l->first);
334         nasm_free (l);
335     }
336 }
337
338 /*
339  * Pop the context stack.
340  */
341 static void ctx_pop (void) {
342     Context *c = cstk;
343     SMacro *smac, *s;
344
345     cstk = cstk->next;
346     smac = c->localmac;
347     while (smac) {
348         s = smac;
349         smac = smac->next;
350         nasm_free (s->name);
351         free_tlist (s->expansion);
352         nasm_free (s);
353     }
354     nasm_free (c->name);
355     nasm_free (c);
356 }
357
358 /*
359  * Generate a line synchronisation comment, to ensure the assembler
360  * knows which source file the current output has really come from.
361  */
362 static void line_sync (void) {
363     char text[80];
364     sprintf(text, "%%line %d+%d %s",
365             (istk->expansion ? istk->lineno - istk->lineinc : istk->lineno),
366             (istk->expansion ? 0 : istk->lineinc), istk->fname);
367     if (linesync)
368         free (linesync);
369     linesync = nasm_strdup(text);
370 }
371
372 #define BUF_DELTA 512
373 /*
374  * Read a line from the top file in istk, handling multiple CR/LFs
375  * at the end of the line read, and handling spurious ^Zs. Will
376  * return lines from the standard macro set if this has not already
377  * been done.
378  */
379 static char *read_line (void) {
380     char *buffer, *p, *q;
381     int bufsize;
382
383     if (stdmacpos) {
384         if (*stdmacpos) {
385             char *ret = nasm_strdup(*stdmacpos++);
386             /*
387              * Nasty hack: here we push the contents of `predef' on
388              * to the top-level expansion stack, since this is the
389              * most convenient way to implement the pre-include and
390              * pre-define features.
391              */
392             if (!*stdmacpos) {
393                 Line *pd, *l;
394                 Token *head, **tail, *t, *tt;
395
396                 for (pd = predef; pd; pd = pd->next) {
397                     head = NULL;
398                     tail = &head;
399                     for (t = pd->first; t; t = t->next) {
400                         tt = *tail = nasm_malloc(sizeof(Token));
401                         tt->next = NULL;
402                         tail = &tt->next;
403                         tt->type = t->type;
404                         tt->text = nasm_strdup(t->text);
405                         tt->mac = t->mac;   /* always NULL here, in fact */
406                     }
407                     l = nasm_malloc(sizeof(Line));
408                     l->next = istk->expansion;
409                     l->first = head;
410                     l->finishes = FALSE;
411                     istk->expansion = l;
412                 }
413             }
414             return ret;
415         } else {
416             stdmacpos = NULL;
417             line_sync();
418         }
419     }
420
421     bufsize = BUF_DELTA;
422     buffer = nasm_malloc(BUF_DELTA);
423     p = buffer;
424     while (1) {
425         q = fgets(p, bufsize-(p-buffer), istk->fp);
426         if (!q)
427             break;
428         p += strlen(p);
429         if (p > buffer && p[-1] == '\n') {
430             istk->lineno += istk->lineinc;
431             break;
432         }
433         if (p-buffer > bufsize-10) {
434             bufsize += BUF_DELTA;
435             buffer = nasm_realloc(buffer, bufsize);
436         }
437     }
438
439     if (!q && p == buffer) {
440         nasm_free (buffer);
441         return NULL;
442     }
443
444     /*
445      * Play safe: remove CRs as well as LFs, if any of either are
446      * present at the end of the line.
447      */
448     while (p > buffer && (p[-1] == '\n' || p[-1] == '\r'))
449         *--p = '\0';
450
451     /*
452      * Handle spurious ^Z, which may be inserted into source files
453      * by some file transfer utilities.
454      */
455     buffer[strcspn(buffer, "\032")] = '\0';
456
457     list->line (LIST_READ, buffer);
458
459     return buffer;
460 }
461
462 /*
463  * Tokenise a line of text. This is a very simple process since we
464  * don't need to parse the value out of e.g. numeric tokens: we
465  * simply split one string into many.
466  */
467 static Token *tokenise (char *line) {
468     char *p = line;
469     int type;
470     Token *list = NULL;
471     Token *t, **tail = &list;
472
473     while (*line) {
474         p = line;
475         if (*p == '%' &&
476             (p[1] == '{' || p[1] == '!' || (p[1] == '%' && isidchar(p[2])) ||
477              p[1] == '$' || p[1] == '+' || p[1] == '-' || isidchar(p[1]))) {
478             type = TOK_PREPROC_ID;
479             p++;
480             if (*p == '{') {
481                 p++;
482                 while (*p && *p != '}') {
483                     p[-1] = *p;
484                     p++;
485                 }
486                 p[-1] = '\0';
487                 if (*p) p++;
488             } else {
489                 if (*p == '!' || *p == '%' || *p == '$' ||
490                     *p == '+' || *p == '-') p++;
491                 while (*p && isidchar(*p))
492                     p++;
493             }
494         } else if (isidstart(*p)) {
495             type = TOK_ID;
496             p++;
497             while (*p && isidchar(*p))
498                 p++;
499         } else if (*p == '\'' || *p == '"') {
500             /*
501              * A string token.
502              */
503             char c = *p;
504             p++;
505             type = TOK_STRING;
506             while (*p && *p != c)
507                 p++;
508             if (*p) p++;
509         } else if (isnumstart(*p)) {
510             /*
511              * A number token.
512              */
513             type = TOK_NUMBER;
514             p++;
515             while (*p && isnumchar(*p))
516                 p++;
517         } else if (isspace(*p)) {
518             type = TOK_WHITESPACE;
519             p++;
520             while (*p && isspace(*p))
521                 p++;
522             /*
523              * Whitespace just before end-of-line is discarded by
524              * pretending it's a comment; whitespace just before a
525              * comment gets lumped into the comment.
526              */
527             if (!*p || *p == ';') {
528                 type = TOK_COMMENT;
529                 while (*p) p++;
530             }
531         } else if (*p == ';') {
532             type = TOK_COMMENT;
533             while (*p) p++;
534         } else {
535             /*
536              * Anything else is an operator of some kind; with the
537              * exceptions of >>, <<, // and %%, all operator tokens
538              * are single-character.
539              */
540             char c = *p++;
541             type = TOK_OTHER;
542             if ( (c == '>' || c == '<' || c == '/' || c == '%') && *p == c)
543                 p++;
544         }
545         if (type != TOK_COMMENT) {
546             *tail = t = nasm_malloc (sizeof(Token));
547             tail = &t->next;
548             t->next = NULL;
549             t->type = type;
550             t->text = nasm_malloc(1+p-line);
551             strncpy(t->text, line, p-line);
552             t->text[p-line] = '\0';
553         }
554         line = p;
555     }
556
557     return list;
558 }
559
560 /*
561  * Convert a line of tokens back into text.
562  */
563 static char *detoken (Token *tlist) {
564     Token *t;
565     int len;
566     char *line, *p;
567
568     len = 0;
569     for (t = tlist; t; t = t->next) {
570         if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
571             char *p = getenv(t->text+2);
572             nasm_free (t->text);
573             if (p)
574                 t->text = nasm_strdup(p);
575             else
576                 t->text = NULL;
577         }
578         if (t->text)
579             len += strlen(t->text);
580     }
581     p = line = nasm_malloc(len+1);
582     for (t = tlist; t; t = t->next) {
583         if (t->text) {
584             strcpy (p, t->text);
585             p += strlen(p);
586         }
587     }
588     *p = '\0';
589     return line;
590 }
591
592 /*
593  * Return the Context structure associated with a %$ token. Return
594  * NULL, having _already_ reported an error condition, if the
595  * context stack isn't deep enough for the supplied number of $
596  * signs.
597  */
598 static Context *get_ctx (char *name) {
599     Context *ctx;
600     int i;
601
602     if (!cstk) {
603         error (ERR_NONFATAL|ERR_OFFBY1, "`%s': context stack is empty", name);
604         return NULL;
605     }
606
607     i = 1;
608     ctx = cstk;
609     while (name[i+1] == '$') {
610         i++;
611         ctx = ctx->next;
612         if (!ctx) {
613             error (ERR_NONFATAL|ERR_OFFBY1, "`%s': context stack is only"
614                    " %d level%s deep", name, i-1, (i==2 ? "" : "s"));
615             return NULL;
616         }
617     }
618     return ctx;
619 }
620
621 /*
622  * Compare a string to the name of an existing macro; this is a
623  * simple wrapper which calls either strcmp or nasm_stricmp
624  * depending on the value of the `casesense' parameter.
625  */
626 static int mstrcmp(char *p, char *q, int casesense) {
627     return casesense ? strcmp(p,q) : nasm_stricmp(p,q);
628 }
629
630 /*
631  * Open an include file. This routine must always return a valid
632  * file pointer if it returns - it's responsible for throwing an
633  * ERR_FATAL and bombing out completely if not. It should also try
634  * the include path one by one until it finds the file or reaches
635  * the end of the path.
636  */
637 static FILE *inc_fopen(char *file) {
638     FILE *fp;
639     char *prefix = "", *combine;
640     IncPath *ip = ipath;
641     int len = strlen(file);
642
643     do {
644         combine = nasm_malloc(strlen(prefix)+len+1);
645         strcpy(combine, prefix);
646         strcat(combine, file);
647         fp = fopen(combine, "r");
648         nasm_free (combine);
649         if (fp)
650             return fp;
651         prefix = ip ? ip->path : NULL;
652         if (ip)
653             ip = ip->next;
654     } while (prefix);
655
656     error (ERR_FATAL|ERR_OFFBY1,
657            "unable to open include file `%s'", file);
658     return NULL;                       /* never reached - placate compilers */
659 }
660
661 /*
662  * Determine if we should warn on defining a single-line macro of
663  * name `name', with `nparam' parameters. If nparam is 0, will
664  * return TRUE if _any_ single-line macro of that name is defined.
665  * Otherwise, will return TRUE if a single-line macro with either
666  * `nparam' or no parameters is defined.
667  *
668  * If a macro with precisely the right number of parameters is
669  * defined, the address of the definition structure will be
670  * returned in `defn'; otherwise NULL will be returned. If `defn'
671  * is NULL, no action will be taken regarding its contents, and no
672  * error will occur.
673  *
674  * Note that this is also called with nparam zero to resolve
675  * `ifdef'.
676  */
677 static int smacro_defined (char *name, int nparam, SMacro **defn) {
678     SMacro *m;
679     Context *ctx;
680     char *p;
681
682     if (name[0] == '%' && name[1] == '$') {
683         ctx = get_ctx (name);
684         if (!ctx)
685             return FALSE;              /* got to return _something_ */
686         m = ctx->localmac;
687         p = name+1;
688         p += strspn(p, "$");
689     } else {
690         m = smacros[hash(name)];
691         p = name;
692     }
693
694     while (m) {
695         if (!mstrcmp(m->name, p, m->casesense) &&
696             (nparam == 0 || m->nparam == 0 || nparam == m->nparam)) {
697             if (defn) {
698                 if (nparam == m->nparam)
699                     *defn = m;
700                 else
701                     *defn = NULL;
702             }
703             return TRUE;
704         }
705         m = m->next;
706     }
707     return FALSE;
708 }
709
710 /*
711  * Count and mark off the parameters in a multi-line macro call.
712  * This is called both from within the multi-line macro expansion
713  * code, and also to mark off the default parameters when provided
714  * in a %macro definition line.
715  */
716 static void count_mmac_params (Token *t, int *nparam, Token ***params) {
717     int paramsize, brace;
718
719     *nparam = paramsize = 0;
720     *params = NULL;
721     while (t) {
722         if (*nparam >= paramsize) {
723             paramsize += PARAM_DELTA;
724             *params = nasm_realloc(*params, sizeof(**params) * paramsize);
725         }
726         if (t && t->type == TOK_WHITESPACE)
727             t = t->next;
728         brace = FALSE;
729         if (t && t->type == TOK_OTHER && !strcmp(t->text, "{"))
730             brace = TRUE;
731         (*params)[(*nparam)++] = t;
732         while (t && (t->type != TOK_OTHER ||
733                      strcmp(t->text, brace ? "}" : ",")))
734             t = t->next;
735         if (t) {                       /* got a comma/brace */
736             t = t->next;
737             if (brace) {
738                 /*
739                  * Now we've found the closing brace, look further
740                  * for the comma.
741                  */
742                 if (t && t->type == TOK_WHITESPACE)
743                     t = t->next;
744                 if (t && (t->type != TOK_OTHER || strcmp(t->text, ","))) {
745                     error (ERR_NONFATAL|ERR_OFFBY1,
746                            "braces do not enclose all of macro parameter");
747                     while (t && (t->type != TOK_OTHER ||
748                                  strcmp(t->text, ",")))
749                         t = t->next;
750                 }
751                 if (t)
752                     t = t->next;               /* eat the comma */
753             }
754         }
755         else                           /* got EOL */
756             break;
757     }
758 }
759
760 /*
761  * Find out if a line contains a preprocessor directive, and deal
762  * with it if so.
763  * 
764  * If a directive _is_ found, the line will never be de-tokenised
765  * as is, so we have carte blanche to fiddle with it and adjust
766  * token values.
767  *
768  * Return values go like this:
769  * 
770  * bit 0 is set if a directive was found
771  * bit 1 is set if a blank line should be emitted
772  * bit 2 is set if a re-sync line number comment should be emitted
773  *
774  * (bits 1 and 2 are mutually exclusive in that the rest of the
775  * preprocessor doesn't guarantee to be able to handle the case in
776  * which both are set)
777  */
778 static int do_directive (Token *tline) {
779     static char *directives[] = {
780         "%clear", "%define", "%elifctx", "%elifdef", "%elifnctx",
781         "%elifndef", "%else", "%endif", "%endm", "%endmacro", "%error",
782         "%idefine", "%ifctx", "%ifdef", "%ifnctx", "%ifndef", "%imacro",
783         "%include", "%line", "%macro", "%pop", "%push", "%repl"
784     };
785     enum {
786         PP_CLEAR, PP_DEFINE, PP_ELIFCTX, PP_ELIFDEF, PP_ELIFNCTX,
787         PP_ELIFNDEF, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO, PP_ERROR,
788         PP_IDEFINE, PP_IFCTX, PP_IFDEF, PP_IFNCTX, PP_IFNDEF, PP_IMACRO,
789         PP_INCLUDE, PP_LINE, PP_MACRO, PP_POP, PP_PUSH, PP_REPL
790     };
791     int i, j, k, m, nparam;
792     char *p, *mname;
793     Include *inc;
794     Context *ctx;
795     Cond *cond;
796     SMacro *smac, **smhead;
797     MMacro *mmac;
798     Token *t, *tt, *param_start, *macro_start, *last;
799
800     if (tline && tline->type == TOK_WHITESPACE)
801         tline = tline->next;
802     if (!tline || tline->type != TOK_PREPROC_ID ||
803         (tline->text[1]=='%' || tline->text[1]=='$' || tline->text[1]=='!'))
804         return 0;
805
806     i = -1;
807     j = sizeof(directives)/sizeof(*directives);
808     while (j-i > 1) {
809         k = (j+i) / 2;
810         m = nasm_stricmp(tline->text, directives[k]);
811         if (m == 0) {
812             i = k;
813             j = -2;
814             break;
815         } else if (m < 0) {
816             j = k;
817         } else
818             i = k;
819     }
820
821     /*
822      * If we're in a non-emitting branch of a condition construct,
823      * we should ignore all directives except for condition
824      * directives.
825      */
826     if (istk->conds && !emitting(istk->conds->state) &&
827         i != PP_IFCTX && i != PP_IFDEF && i != PP_IFNCTX && i != PP_IFNDEF &&
828         i!=PP_ELIFCTX && i!=PP_ELIFDEF && i!=PP_ELIFNCTX && i!=PP_ELIFNDEF &&
829         i != PP_ELSE && i != PP_ENDIF)
830         return 0;
831
832     /*
833      * If we're defining a macro, we should ignore all directives
834      * except for %macro/%imacro (which generate an error) and
835      * %endm/%endmacro.
836      */
837     if (defining && i != PP_MACRO && i != PP_IMACRO &&
838         i != PP_ENDMACRO && i != PP_ENDM)
839         return 0;
840
841     if (j != -2) {
842         error(ERR_NONFATAL|ERR_OFFBY1, "unknown preprocessor directive `%s'",
843               tline->text);
844         return 0;                      /* didn't get it */
845     }
846
847     switch (i) {
848
849       case PP_CLEAR:
850         if (tline->next)
851             error(ERR_WARNING|ERR_OFFBY1,
852                   "trailing garbage after `%%clear' ignored");
853         for (j=0; j<NHASH; j++) {
854             while (mmacros[j]) {
855                 MMacro *m = mmacros[j];
856                 mmacros[j] = mmacros[j]->next;
857                 nasm_free (m->name);
858                 free_tlist (m->dlist);
859                 free_llist (m->expansion);
860                 nasm_free (m);
861             }
862             while (smacros[j]) {
863                 SMacro *s = smacros[j];
864                 smacros[j] = smacros[j]->next;
865                 nasm_free (s->name);
866                 free_tlist (s->expansion);
867                 nasm_free (s);
868             }
869         }
870         return 3;
871
872       case PP_INCLUDE:
873         tline = tline->next;
874         if (tline && tline->type == TOK_WHITESPACE)
875             tline = tline->next;
876         if (!tline || (tline->type != TOK_STRING &&
877                        tline->type != TOK_INTERNAL_STRING)) {
878             error(ERR_NONFATAL|ERR_OFFBY1, "`%%include' expects a file name");
879             return 3;                  /* but we did _something_ */
880         }
881         if (tline->next)
882             error(ERR_WARNING|ERR_OFFBY1,
883                   "trailing garbage after `%%include' ignored");
884         if (tline->type != TOK_INTERNAL_STRING) {
885             p = tline->text+1;         /* point past the quote to the name */
886             p[strlen(p)-1] = '\0';     /* remove the trailing quote */
887         } else
888             p = tline->text;           /* internal_string is easier */
889         inc = nasm_malloc(sizeof(Include));
890         inc->next = istk;
891         inc->conds = NULL;
892         inc->fp = inc_fopen(p);
893         inc->fname = nasm_strdup(p);
894         inc->lineno = inc->lineinc = 1;
895         inc->expansion = NULL;
896         istk = inc;
897         list->uplevel (LIST_INCLUDE);
898         return 5;
899
900       case PP_PUSH:
901         tline = tline->next;
902         if (tline && tline->type == TOK_WHITESPACE)
903             tline = tline->next;
904         if (!tline || tline->type != TOK_ID) {
905             error(ERR_NONFATAL|ERR_OFFBY1,
906                   "`%%push' expects a context identifier");
907             return 3;                  /* but we did _something_ */
908         }
909         if (tline->next)
910             error(ERR_WARNING|ERR_OFFBY1,
911                   "trailing garbage after `%%push' ignored");
912         ctx = nasm_malloc(sizeof(Context));
913         ctx->next = cstk;
914         ctx->localmac = NULL;
915         ctx->name = nasm_strdup(tline->text);
916         ctx->number = unique++;
917         cstk = ctx;
918         break;
919
920       case PP_REPL:
921         tline = tline->next;
922         if (tline && tline->type == TOK_WHITESPACE)
923             tline = tline->next;
924         if (!tline || tline->type != TOK_ID) {
925             error(ERR_NONFATAL|ERR_OFFBY1,
926                   "`%%repl' expects a context identifier");
927             return 3;                  /* but we did _something_ */
928         }
929         if (tline->next)
930             error(ERR_WARNING|ERR_OFFBY1,
931                   "trailing garbage after `%%repl' ignored");
932         if (!cstk)
933             error(ERR_NONFATAL|ERR_OFFBY1,
934                   "`%%repl': context stack is empty");
935         else {
936             nasm_free (cstk->name);
937             cstk->name = nasm_strdup(tline->text);
938         }
939         break;
940
941       case PP_POP:
942         if (tline->next)
943             error(ERR_WARNING|ERR_OFFBY1,
944                   "trailing garbage after `%%pop' ignored");
945         if (!cstk)
946             error(ERR_NONFATAL|ERR_OFFBY1,
947                   "`%%pop': context stack is already empty");
948         else
949             ctx_pop();
950         break;
951
952       case PP_ERROR:
953         tline = tline->next;
954         if (tline && tline->type == TOK_WHITESPACE)
955             tline = tline->next;
956         if (!tline || tline->type != TOK_STRING) {
957             error(ERR_NONFATAL|ERR_OFFBY1,
958                   "`%%error' expects an error string");
959             return 3;                  /* but we did _something_ */
960         }
961         if (tline->next)
962             error(ERR_WARNING|ERR_OFFBY1,
963                   "trailing garbage after `%%error' ignored");
964         p = tline->text+1;             /* point past the quote to the name */
965         p[strlen(p)-1] = '\0';         /* remove the trailing quote */
966         error(ERR_NONFATAL|ERR_OFFBY1, "user error: %s", p);
967         break;
968
969       case PP_IFCTX:
970       case PP_IFNCTX:
971         tline = tline->next;
972         if (istk->conds && !emitting(istk->conds->state))
973             j = COND_NEVER;
974         else {
975             j = FALSE;                 /* have we matched yet? */
976             if (!cstk)
977                 error(ERR_FATAL|ERR_OFFBY1,
978                       "`%%if%sctx': context stack is empty",
979                       (i==PP_IFNCTX ? "n" : ""));
980             else while (tline) {
981                 if (tline->type == TOK_WHITESPACE)
982                     tline = tline->next;
983                 if (!tline || tline->type != TOK_ID) {
984                     error(ERR_NONFATAL|ERR_OFFBY1,
985                           "`%%ifctx' expects context identifiers");
986                     return 3;          /* but we did _something_ */
987                 }
988                 if (!nasm_stricmp(tline->text, cstk->name))
989                     j = TRUE;
990                 tline = tline->next;
991             }
992             if (i == PP_IFNCTX)
993                 j = !j;
994             j = (j ? COND_IF_TRUE : COND_IF_FALSE);
995         }
996         cond = nasm_malloc(sizeof(Cond));
997         cond->next = istk->conds;
998         cond->state = j;
999         istk->conds = cond;
1000         return 1;
1001
1002       case PP_ELIFCTX:
1003       case PP_ELIFNCTX:
1004         tline = tline->next;
1005         if (!istk->conds)
1006             error(ERR_FATAL|ERR_OFFBY1, "`%%elif%sctx': no matching `%%if'",
1007                   (i==PP_ELIFNCTX ? "n" : ""));
1008         if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
1009             istk->conds->state = COND_NEVER;
1010         else {
1011             j = FALSE;                 /* have we matched yet? */
1012             if (!cstk)
1013                 error(ERR_FATAL|ERR_OFFBY1,
1014                       "`%%elif%sctx': context stack is empty",
1015                       (i==PP_ELIFNCTX ? "n" : ""));
1016             else while (tline) {
1017                 if (tline->type == TOK_WHITESPACE)
1018                     tline = tline->next;
1019                 if (!tline || tline->type != TOK_ID) {
1020                     error(ERR_NONFATAL|ERR_OFFBY1,
1021                           "`%%elif%sctx' expects context identifiers",
1022                           (i==PP_ELIFNCTX ? "n" : ""));
1023                     return 3;          /* but we did _something_ */
1024                 }
1025                 if (!nasm_stricmp(tline->text, cstk->name))
1026                     j = TRUE;
1027                 tline = tline->next;
1028             }
1029             if (i == PP_ELIFNCTX)
1030                 j = !j;
1031             istk->conds->state = (j ? COND_IF_TRUE : COND_IF_FALSE);
1032         }
1033         return 1;
1034
1035       case PP_IFDEF:
1036       case PP_IFNDEF:
1037         tline = tline->next;
1038         if (istk->conds && !emitting(istk->conds->state))
1039             j = COND_NEVER;
1040         else {
1041             j = FALSE;                 /* have we matched yet? */
1042             while (tline) {
1043                 if (tline->type == TOK_WHITESPACE)
1044                     tline = tline->next;
1045                 if (!tline || (tline->type != TOK_ID &&
1046                                (tline->type != TOK_PREPROC_ID ||
1047                                 tline->text[1] != '$'))) {
1048                     error(ERR_NONFATAL|ERR_OFFBY1,
1049                           "`%%if%sdef' expects macro identifiers",
1050                           (i==PP_ELIFNDEF ? "n" : ""));
1051                     return 3;          /* but we did _something_ */
1052                 }
1053                 if (smacro_defined(tline->text, 0, NULL))
1054                     j = TRUE;
1055                 tline = tline->next;
1056             }
1057             if (i == PP_IFNDEF)
1058                 j = !j;
1059             j = (j ? COND_IF_TRUE : COND_IF_FALSE);
1060         }
1061         cond = nasm_malloc(sizeof(Cond));
1062         cond->next = istk->conds;
1063         cond->state = j;
1064         istk->conds = cond;
1065         return 1;
1066
1067       case PP_ELIFDEF:
1068       case PP_ELIFNDEF:
1069         tline = tline->next;
1070         if (!istk->conds)
1071             error(ERR_FATAL|ERR_OFFBY1, "`%%elif%sctx': no matching `%%if'",
1072                   (i==PP_ELIFNCTX ? "n" : ""));
1073         if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
1074             istk->conds->state = COND_NEVER;
1075         else {
1076             j = FALSE;                 /* have we matched yet? */
1077             while (tline) {
1078                 if (tline->type == TOK_WHITESPACE)
1079                     tline = tline->next;
1080                 if (!tline || (tline->type != TOK_ID &&
1081                                (tline->type != TOK_PREPROC_ID ||
1082                                 tline->text[1] != '$'))) {
1083                     error(ERR_NONFATAL|ERR_OFFBY1,
1084                           "`%%elif%sdef' expects macro identifiers",
1085                           (i==PP_ELIFNDEF ? "n" : ""));
1086                     return 3;          /* but we did _something_ */
1087                 }
1088                 if (smacro_defined(tline->text, 0, NULL))
1089                     j = TRUE;
1090                 tline = tline->next;
1091             }
1092             if (i == PP_ELIFNDEF)
1093                 j = !j;
1094             istk->conds->state = (j ? COND_IF_TRUE : COND_IF_FALSE);
1095         }
1096         return 1;
1097
1098       case PP_ELSE:
1099         if (tline->next)
1100             error(ERR_WARNING|ERR_OFFBY1,
1101                   "trailing garbage after `%%else' ignored");
1102         if (!istk->conds)
1103             error(ERR_FATAL|ERR_OFFBY1,
1104                   "`%%else': no matching `%%if'");
1105         if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER)
1106             istk->conds->state = COND_ELSE_FALSE;
1107         else
1108             istk->conds->state = COND_ELSE_TRUE;
1109         return 1;
1110
1111       case PP_ENDIF:
1112         if (tline->next)
1113             error(ERR_WARNING|ERR_OFFBY1,
1114                   "trailing garbage after `%%endif' ignored");
1115         if (!istk->conds)
1116             error(ERR_FATAL|ERR_OFFBY1,
1117                   "`%%endif': no matching `%%if'");
1118         cond = istk->conds;
1119         istk->conds = cond->next;
1120         nasm_free (cond);
1121         return 5;
1122
1123       case PP_MACRO:
1124       case PP_IMACRO:
1125         if (defining)
1126             error (ERR_FATAL|ERR_OFFBY1,
1127                    "`%%%smacro': already defining a macro",
1128                    (i == PP_IMACRO ? "i" : ""));
1129         tline = tline->next;
1130         if (tline && tline->type == TOK_WHITESPACE)
1131             tline = tline->next;
1132         if (!tline || tline->type != TOK_ID) {
1133             error (ERR_NONFATAL|ERR_OFFBY1,
1134                    "`%%%smacro' expects a macro name",
1135                    (i == PP_IMACRO ? "i" : ""));
1136             return 3;
1137         }
1138         defining = nasm_malloc(sizeof(MMacro));
1139         defining->name = nasm_strdup(tline->text);
1140         defining->casesense = (i == PP_MACRO);
1141         defining->plus = FALSE;
1142         defining->nolist = FALSE;
1143         defining->in_progress = FALSE;
1144         tline = tline->next;
1145         if (tline && tline->type == TOK_WHITESPACE)
1146             tline = tline->next;
1147         if (!tline || tline->type != TOK_NUMBER) {
1148             error (ERR_NONFATAL|ERR_OFFBY1,
1149                    "`%%%smacro' expects a parameter count",
1150                    (i == PP_IMACRO ? "i" : ""));
1151             defining->nparam_min = defining->nparam_max = 0;
1152         } else {
1153             defining->nparam_min = defining->nparam_max =
1154                 readnum(tline->text, &j);
1155             if (j)
1156                 error (ERR_NONFATAL|ERR_OFFBY1,
1157                        "unable to parse parameter count `%s'", tline->text);
1158         }
1159         if (tline && tline->next && tline->next->type == TOK_OTHER &&
1160             !strcmp(tline->next->text, "-")) {
1161             tline = tline->next->next;
1162             if (!tline || tline->type != TOK_NUMBER)
1163                 error (ERR_NONFATAL|ERR_OFFBY1,
1164                        "`%%%smacro' expects a parameter count after `-'",
1165                        (i == PP_IMACRO ? "i" : ""));
1166             else {
1167                 defining->nparam_max = readnum(tline->text, &j);
1168                 if (j)
1169                     error (ERR_NONFATAL|ERR_OFFBY1,
1170                            "unable to parse parameter count `%s'",
1171                            tline->text);
1172                 if (defining->nparam_min > defining->nparam_max)
1173                     error (ERR_NONFATAL|ERR_OFFBY1,
1174                            "minimum parameter count exceeds maximum");
1175             }
1176         }
1177         if (tline && tline->next && tline->next->type == TOK_OTHER &&
1178             !strcmp(tline->next->text, "+")) {
1179             tline = tline->next;
1180             defining->plus = TRUE;
1181         }
1182         if (tline && tline->next && tline->next->type == TOK_ID &&
1183             !nasm_stricmp(tline->next->text, ".nolist")) {
1184             tline = tline->next;
1185             defining->nolist = TRUE;
1186         }
1187         mmac = mmacros[hash(defining->name)];
1188         while (mmac) {
1189             if (!strcmp(mmac->name, defining->name) &&
1190                 (mmac->nparam_min<=defining->nparam_max || defining->plus) &&
1191                 (defining->nparam_min<=mmac->nparam_max || mmac->plus)) {
1192                 error (ERR_WARNING|ERR_OFFBY1,
1193                        "redefining multi-line macro `%s'", defining->name);
1194                 break;
1195             }
1196             mmac = mmac->next;
1197         }
1198         /*
1199          * Handle default parameters.
1200          */
1201         if (tline && tline->next) {
1202             int np, want_np;
1203
1204             defining->dlist = tline->next;
1205             tline->next = NULL;
1206             count_mmac_params (defining->dlist, &np, &defining->defaults);
1207             want_np = defining->nparam_max - defining->nparam_min;
1208             defining->defaults = nasm_realloc (defining->defaults,
1209                                                want_np*sizeof(Token *));
1210             while (np < want_np)
1211                 defining->defaults[np++] = NULL;
1212         } else {
1213             defining->dlist = NULL;
1214             defining->defaults = NULL;
1215         }
1216         defining->expansion = NULL;
1217         return 1;
1218
1219       case PP_ENDM:
1220       case PP_ENDMACRO:
1221         if (!defining) {
1222             error (ERR_NONFATAL|ERR_OFFBY1, "`%s': not defining a macro",
1223                    tline->text);
1224             return 3;
1225         }
1226         k = hash(defining->name);
1227         defining->next = mmacros[k];
1228         mmacros[k] = defining;
1229         defining = NULL;
1230         return 5;
1231
1232       case PP_DEFINE:
1233       case PP_IDEFINE:
1234         tline = tline->next;
1235         if (tline && tline->type == TOK_WHITESPACE)
1236             tline = tline->next;
1237         if (!tline || (tline->type != TOK_ID &&
1238                        (tline->type != TOK_PREPROC_ID ||
1239                         tline->text[1] != '$'))) {
1240             error (ERR_NONFATAL|ERR_OFFBY1,
1241                    "`%%%sdefine' expects a macro identifier",
1242                    (i == PP_IDEFINE ? "i" : ""));
1243             return 3;
1244         }
1245         mname = tline->text;
1246         if (tline->type == TOK_ID) {
1247             p = tline->text;
1248             smhead = &smacros[hash(mname)];
1249         } else {
1250             ctx = get_ctx (tline->text);
1251             if (ctx == NULL)
1252                 return 3;
1253             else {
1254                 p = tline->text+1;
1255                 p += strspn(p, "$");
1256                 smhead = &ctx->localmac;
1257             }
1258         }
1259         last = tline;
1260         param_start = tline = tline->next;
1261         nparam = 0;
1262         if (tline && tline->type == TOK_OTHER && !strcmp(tline->text, "(")) {
1263             /*
1264              * This macro has parameters.
1265              */
1266
1267             tline = tline->next;
1268             while (1) {
1269                 if (tline && tline->type == TOK_WHITESPACE)
1270                     tline = tline->next;
1271                 if (!tline) {
1272                     error (ERR_NONFATAL|ERR_OFFBY1,
1273                            "parameter identifier expected");
1274                     return 3;
1275                 }
1276                 if (tline->type != TOK_ID) {
1277                     error (ERR_NONFATAL|ERR_OFFBY1,
1278                            "`%s': parameter identifier expected",
1279                            tline->text);
1280                     return 3;
1281                 }
1282                 tline->type = TOK_SMAC_PARAM + nparam++;
1283                 tline = tline->next;
1284                 if (tline && tline->type == TOK_WHITESPACE)
1285                     tline = tline->next;
1286                 if (tline && tline->type == TOK_OTHER &&
1287                     !strcmp(tline->text, ",")) {
1288                     tline = tline->next;
1289                     continue;
1290                 }
1291                 if (!tline || tline->type != TOK_OTHER ||
1292                     strcmp(tline->text, ")")) {
1293                     error (ERR_NONFATAL|ERR_OFFBY1,
1294                            "`)' expected to terminate macro template");
1295                     return 3;
1296                 }
1297                 break;
1298             }
1299             last = tline;
1300             tline = tline->next;
1301         }
1302         if (tline && tline->type == TOK_WHITESPACE)
1303             last = tline, tline = tline->next;
1304         macro_start = NULL;
1305         last->next = NULL;
1306         t = tline;
1307         while (t) {
1308             if (t->type == TOK_ID) {
1309                 for (tt = param_start; tt; tt = tt->next)
1310                     if (tt->type >= TOK_SMAC_PARAM &&
1311                         !strcmp(tt->text, t->text))
1312                         t->type = tt->type;
1313             }
1314             tt = t->next;
1315             t->next = macro_start;
1316             macro_start = t;
1317             t = tt;
1318         }
1319         /*
1320          * Good. We now have a macro name, a parameter count, and a
1321          * token list (in reverse order) for an expansion. We ought
1322          * to be OK just to create an SMacro, store it, and let
1323          * free_tlist have the rest of the line (which we have
1324          * carefully re-terminated after chopping off the expansion
1325          * from the end).
1326          */
1327         if (smacro_defined (mname, nparam, &smac)) {
1328             if (!smac)
1329                 error (ERR_WARNING|ERR_OFFBY1,
1330                        "single-line macro `%s' defined both with and"
1331                        " without parameters", mname);
1332             else {
1333                 /*
1334                  * We're redefining, so we have to take over an
1335                  * existing SMacro structure. This means freeing
1336                  * what was already in it.
1337                  */
1338                 nasm_free (smac->name);
1339                 free_tlist (smac->expansion);
1340             }
1341         } else {
1342             smac = nasm_malloc(sizeof(SMacro));
1343             smac->next = *smhead;
1344             *smhead = smac;
1345         }
1346         smac->name = nasm_strdup(p);
1347         smac->casesense = (i == PP_DEFINE);
1348         smac->nparam = nparam;
1349         smac->expansion = macro_start;
1350         smac->in_progress = FALSE;
1351         return 3;
1352
1353       case PP_LINE:
1354         /*
1355          * Syntax is `%line nnn[+mmm] [filename]'
1356          */
1357         tline = tline->next;
1358         if (tline && tline->type == TOK_WHITESPACE)
1359             tline = tline->next;
1360         if (!tline || tline->type != TOK_NUMBER) {
1361             error (ERR_NONFATAL|ERR_OFFBY1, "`%%line' expects line number");
1362             return 3;
1363         }
1364         k = readnum(tline->text, &j);
1365         m = 1;
1366         tline = tline->next;
1367         if (tline && tline->type == TOK_OTHER && !strcmp(tline->text, "+")) {
1368             tline = tline->next;
1369             if (!tline || tline->type != TOK_NUMBER) {
1370                 error (ERR_NONFATAL|ERR_OFFBY1,
1371                        "`%%line' expects line increment");
1372                 return 3;
1373             }
1374             m = readnum(tline->text, &j);
1375             tline = tline->next;
1376         }
1377         if (tline && tline->type == TOK_WHITESPACE)
1378             tline = tline->next;
1379         istk->lineno = k;
1380         istk->lineinc = m;
1381         if (tline) {
1382             char *s = detoken(tline);
1383             nasm_free (istk->fname);
1384             istk->fname = s;
1385         }
1386         return 5;
1387
1388       default:
1389         error(ERR_FATAL|ERR_OFFBY1,
1390               "preprocessor directive `%s' not yet implemented",
1391               directives[k]);
1392         break;
1393     }
1394     return 3;
1395 }
1396
1397 /*
1398  * Expand all single-line macro calls made in the given line.
1399  * Return the expanded version of the line. The original is deemed
1400  * to be destroyed in the process. (In reality we'll just move
1401  * Tokens from input to output a lot of the time, rather than
1402  * actually bothering to destroy and replicate.)
1403  */
1404 static Token *expand_smacro (Token *tline) {
1405     Token *t, *tt, *mstart, **tail, *thead;
1406     SMacro *head, *m;
1407     Token **params;
1408     int *paramsize;
1409     int nparam, sparam, brackets;
1410     char *p;
1411
1412     tail = &thead;
1413     thead = NULL;
1414
1415     while (tline) {
1416         while (tline && tline->type != TOK_ID &&
1417                (tline->type != TOK_PREPROC_ID || tline->text[1] != '$')) {
1418             if (tline->type == TOK_SMAC_END) {
1419                 tline->mac->in_progress = FALSE;
1420                 t = tline;
1421                 tline = tline->next;
1422                 nasm_free (t);
1423             } else {
1424                 t = *tail = tline;
1425                 tline = tline->next;
1426                 t->mac = NULL;
1427                 t->next = NULL;
1428                 tail = &t->next;
1429                 if (t->type == TOK_PS_OTHER) {
1430                     /*
1431                      * If we see a PS_OTHER, we must at the very
1432                      * least restore its correct token type. We
1433                      * should also check for a %$ token, since this
1434                      * is the point at which we expand context-
1435                      * local labels.
1436                      */
1437                     t->type = TOK_ID;
1438                     if (t->text[0] == '%' && t->text[1] == '$') {
1439                         Context *c = get_ctx (t->text);
1440                         char *p, *q, buffer[40];
1441
1442                         if (c) {
1443                             q = t->text+1;
1444                             q += strspn(q, "$");
1445                             sprintf(buffer, "..@%lu.", c->number);
1446                             p = nasm_malloc (strlen(buffer)+strlen(q)+1);
1447                             strcpy (p, buffer);
1448                             strcat (p, q);
1449                             nasm_free (t->text);
1450                             t->text = p;
1451                         }
1452                     }
1453                 }
1454             }
1455         }
1456         if (!tline)
1457             break;
1458         /*
1459          * We've hit an identifier. As in is_mmacro below, we first
1460          * check whether the identifier is a single-line macro at
1461          * all, then think about checking for parameters if
1462          * necessary.
1463          */
1464         if (tline->type == TOK_ID) {
1465             head = smacros[hash(tline->text)];
1466             p = tline->text;
1467         } else {
1468             Context *ctx = get_ctx (tline->text);
1469             if (ctx) {
1470                 p = tline->text+1;
1471                 p += strspn(p, "$");
1472                 head = ctx->localmac;
1473             } else {
1474                 tline->type = TOK_OTHER; /* so it will get copied above */
1475                 continue;               
1476             }
1477         }
1478         for (m = head; m; m = m->next)
1479             if (!mstrcmp(m->name, p, m->casesense))
1480                 break;
1481         if (!m || m->in_progress) {
1482             /*
1483              * Either we didn't find a macro, so this can't be a
1484              * macro call, or we found a macro which was already in
1485              * progress, in which case we don't _treat_ this as a
1486              * macro call. Copy it through and ignore it.
1487              */
1488             tline->type = TOK_PS_OTHER;   /* so it will get copied above */
1489             continue;
1490         }
1491         mstart = tline;
1492         if (m->nparam == 0) {
1493             /*
1494              * Simple case: the macro is parameterless. Discard the
1495              * one token that the macro call took, and push the
1496              * expansion back on the to-do stack.
1497              */
1498             params = NULL;
1499             paramsize = NULL;
1500         } else {
1501             /*
1502              * Complicated case: at least one macro with this name
1503              * exists and takes parameters. We must find the
1504              * parameters in the call, count them, find the SMacro
1505              * that corresponds to that form of the macro call, and
1506              * substitute for the parameters when we expand. What a
1507              * pain.
1508              */
1509             nparam = sparam = 0;
1510             params = NULL;
1511             paramsize = NULL;
1512             tline = tline->next;
1513             if (tline && tline->type == TOK_WHITESPACE)
1514                 tline = tline->next;
1515             if (!tline || tline->type != TOK_OTHER ||
1516                 strcmp(tline->text, "(")) {
1517                 /*
1518                  * This macro wasn't called with parameters: ignore
1519                  * the call. (Behaviour borrowed from gnu cpp.)
1520                  */
1521                 tline = mstart;
1522                 tline->type = TOK_PS_OTHER;
1523                 continue;
1524             }
1525             tline = tline->next;
1526             while (1) {
1527                 if (tline && tline->type == TOK_WHITESPACE)
1528                     tline = tline->next;
1529                 if (!tline) {
1530                     error(ERR_NONFATAL|ERR_OFFBY1,
1531                           "macro call expects terminating `)'");
1532                     break;
1533                 }
1534                 if (nparam >= sparam) {
1535                     sparam += PARAM_DELTA;
1536                     params = nasm_realloc (params, sparam*sizeof(Token *));
1537                     paramsize = nasm_realloc (paramsize, sparam*sizeof(int));
1538                 }
1539                 params[nparam] = tline;
1540                 paramsize[nparam] = 0;
1541                 brackets = 0;
1542                 if (tline && tline->type == TOK_OTHER &&
1543                     !strcmp(tline->text, "{")) {
1544                     params[nparam] = tline = tline->next;
1545                     while (tline && (brackets > 0 ||
1546                                      tline->type != TOK_OTHER ||
1547                                      strcmp(tline->text, "}"))) {
1548                         tline = tline->next;
1549                         paramsize[nparam]++;
1550                     }
1551                     tline = tline->next;
1552                     if (tline && tline->type == TOK_WHITESPACE)
1553                         tline = tline->next;
1554                     if (tline && (tline->type != TOK_OTHER ||
1555                                   (strcmp(tline->text, ")") &&
1556                                    strcmp(tline->text, ",")))) {
1557                         error (ERR_NONFATAL|ERR_OFFBY1, "braces do not "
1558                                "enclose all of macro parameter");
1559                     }
1560                     if (tline && tline->type == TOK_OTHER &&
1561                         !strcmp(tline->text, ","))
1562                         tline = tline->next;
1563                 } else {
1564                     while (tline && (brackets > 0 ||
1565                                      tline->type != TOK_OTHER ||
1566                                      (strcmp(tline->text, ",") &&
1567                                       strcmp(tline->text, ")")))) {
1568                         if (tline->type == TOK_OTHER && !tline->text[1])
1569                             brackets += (tline->text[0] == '(' ? 1 :
1570                                          tline->text[0] == ')' ? -1 : 0);
1571                         tline = tline->next;
1572                         paramsize[nparam]++;
1573                     }
1574                 }
1575                 nparam++;
1576                 if (tline && !strcmp(tline->text, ")"))
1577                     break;
1578                 if (tline && !strcmp(tline->text, ","))
1579                     tline = tline->next;
1580             }
1581             while (m && m->nparam != nparam) {
1582                 while ( (m = m->next) )
1583                     if (!strcmp(m->name, mstart->text))
1584                         break;
1585             }
1586             if (!m) {
1587                 error (ERR_WARNING|ERR_OFFBY1|ERR_WARN_MNP,
1588                        "macro `%s' exists, but not taking %d parameters",
1589                        mstart->text, nparam);
1590                 nasm_free (params);
1591                 nasm_free (paramsize);
1592                 tline = mstart;
1593                 tline->type = TOK_PS_OTHER;
1594                 continue;
1595             }
1596         }
1597         /*
1598          * Expand the macro: we are placed on the last token of the
1599          * call, so that we can easily split the call from the
1600          * following tokens. We also start by pushing an SMAC_END
1601          * token for the cycle removal.
1602          */
1603         t = tline;
1604         tline = tline->next;
1605         t->next = NULL;
1606         tt = nasm_malloc(sizeof(Token));
1607         tt->type = TOK_SMAC_END;
1608         tt->text = NULL;
1609         tt->mac = m;
1610         m->in_progress = TRUE;
1611         tt->next = tline;
1612         tline = tt;
1613         for (t = m->expansion; t; t = t->next) {
1614             if (t->type >= TOK_SMAC_PARAM) {
1615                 Token *pcopy = tline, **ptail = &pcopy;
1616                 Token *ttt, *pt;
1617                 int i;
1618                 
1619                 ttt = params[t->type - TOK_SMAC_PARAM];
1620                 for (i=0; i<paramsize[t->type-TOK_SMAC_PARAM]; i++) {
1621                     pt = *ptail = nasm_malloc(sizeof(Token));
1622                     pt->next = tline;
1623                     ptail = &pt->next;
1624                     pt->text = nasm_strdup(ttt->text);
1625                     pt->type = ttt->type;
1626                     pt->mac = NULL;
1627                     ttt = ttt->next;
1628                 }
1629                 tline = pcopy;
1630             } else {
1631                 tt = nasm_malloc(sizeof(Token));
1632                 tt->type = t->type;
1633                 tt->text = nasm_strdup(t->text);
1634                 tt->mac = NULL;
1635                 tt->next = tline;
1636                 tline = tt;
1637             }
1638         }
1639
1640         /*
1641          * Having done that, get rid of the macro call, and clean
1642          * up the parameters.
1643          */
1644         nasm_free (params);
1645         nasm_free (paramsize);
1646         free_tlist (mstart);
1647     }
1648
1649     return thead;
1650 }
1651
1652 /*
1653  * Ensure that a macro parameter contains a condition code and
1654  * nothing else. Return the condition code index if so, or -1
1655  * otherwise.
1656  */
1657 static int find_cc (Token *t) {
1658     Token *tt;
1659     int i, j, k, m;
1660
1661     if (t && t->type == TOK_WHITESPACE)
1662         t = t->next;
1663     if (t->type != TOK_ID)
1664         return -1;
1665     tt = t->next;
1666     if (tt && tt->type == TOK_WHITESPACE)
1667         tt = tt->next;
1668     if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
1669         return -1;
1670
1671     i = -1;
1672     j = sizeof(conditions)/sizeof(*conditions);
1673     while (j-i > 1) {
1674         k = (j+i) / 2;
1675         m = nasm_stricmp(t->text, conditions[k]);
1676         if (m == 0) {
1677             i = k;
1678             j = -2;
1679             break;
1680         } else if (m < 0) {
1681             j = k;
1682         } else
1683             i = k;
1684     }
1685     if (j != -2)
1686         return -1;
1687     return i;
1688 }
1689
1690 /*
1691  * Determine whether the given line constitutes a multi-line macro
1692  * call, and return the MMacro structure called if so. Doesn't have
1693  * to check for an initial label - that's taken care of in
1694  * expand_mmacro - but must check numbers of parameters. Guaranteed
1695  * to be called with tline->type == TOK_ID, so the putative macro
1696  * name is easy to find.
1697  */
1698 static MMacro *is_mmacro (Token *tline, Token ***params_array) {
1699     MMacro *head, *m;
1700     Token **params;
1701     int nparam;
1702
1703     head = mmacros[hash(tline->text)];
1704
1705     /*
1706      * Efficiency: first we see if any macro exists with the given
1707      * name. If not, we can return NULL immediately. _Then_ we
1708      * count the parameters, and then we look further along the
1709      * list if necessary to find the proper MMacro.
1710      */
1711     for (m = head; m; m = m->next)
1712         if (!mstrcmp(m->name, tline->text, m->casesense))
1713             break;
1714     if (!m)
1715         return NULL;
1716
1717     /*
1718      * OK, we have a potential macro. Count and demarcate the
1719      * parameters.
1720      */
1721     count_mmac_params (tline->next, &nparam, &params);
1722
1723     /*
1724      * So we know how many parameters we've got. Find the MMacro
1725      * structure that handles this number.
1726      */
1727     while (m) {
1728         if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max)) {
1729             /*
1730              * This one is right. Just check if cycle removal
1731              * prohibits us using it before we actually celebrate...
1732              */
1733             if (m->in_progress) {
1734                 error (ERR_NONFATAL|ERR_OFFBY1,
1735                        "self-reference in multi-line macro `%s'",
1736                        m->name);
1737                 nasm_free (params);
1738                 return NULL;
1739             }
1740             /*
1741              * It's right, and we can use it. Add its default
1742              * parameters to the end of our list if necessary.
1743              */
1744             params = nasm_realloc (params, (m->nparam_max+1)*sizeof(*params));
1745             if (m->defaults) {
1746                 while (nparam < m->nparam_max) {
1747                     params[nparam] = m->defaults[nparam - m->nparam_min];
1748                     nparam++;
1749                 }
1750             } else {
1751                 while (nparam < m->nparam_max) {
1752                     params[nparam] = NULL;
1753                     nparam++;
1754                 }
1755             }
1756             /*
1757              * Then terminate the parameter list, and leave.
1758              */
1759             params[m->nparam_max] = NULL;
1760             *params_array = params;
1761             return m;
1762         }
1763         /*
1764          * This one wasn't right: look for the next one with the
1765          * same name.
1766          */
1767         for (m = m->next; m; m = m->next)
1768             if (!mstrcmp(m->name, tline->text, m->casesense))
1769                 break;
1770     }
1771
1772     /*
1773      * After all that, we didn't find one with the right number of
1774      * parameters. Issue a warning, and fail to expand the macro.
1775      */
1776     error (ERR_WARNING|ERR_OFFBY1|ERR_WARN_MNP,
1777            "macro `%s' exists, but not taking %d parameters",
1778            tline->text, nparam);
1779     nasm_free (params);
1780     return NULL;
1781 }
1782
1783 /*
1784  * Expand the multi-line macro call made by the given line, if
1785  * there is one to be expanded. If there is, push the expansion on
1786  * istk->expansion and return 1 or 2, as according to whether a
1787  * line sync is needed (2 if it is). Otherwise return 0.
1788  */
1789 static int expand_mmacro (Token *tline) {
1790     Token *label = NULL, **params, *t, *tt, *ttt, *last = NULL;
1791     MMacro *m = NULL;
1792     Line *l, *ll;
1793     int i, n, nparam, *paramlen;
1794     int need_sync = FALSE;
1795
1796     t = tline;
1797     if (t && t->type == TOK_WHITESPACE)
1798         t = t->next;
1799     if (t && t->type == TOK_ID) {
1800         m = is_mmacro (t, &params);
1801         if (!m) {
1802             /*
1803              * We have an id which isn't a macro call. We'll assume
1804              * it might be a label; we'll also check to see if a
1805              * colon follows it. Then, if there's another id after
1806              * that lot, we'll check it again for macro-hood.
1807              */
1808             last = t, t = t->next;
1809             if (t && t->type == TOK_WHITESPACE)
1810                 last = t, t = t->next;
1811             if (t && t->type == TOK_OTHER && !strcmp(t->text, ":"))
1812                 last = t, t = t->next;
1813             if (t && t->type == TOK_WHITESPACE)
1814                 last = t, t = t->next;
1815             if (t && t->type == TOK_ID) {
1816                 m = is_mmacro(t, &params);
1817                 if (m) {
1818                     last->next = NULL;
1819                     label = tline;
1820                     tline = t;
1821                 }
1822             }
1823         }       
1824     }
1825     if (!m)
1826         return 0;
1827
1828     /*
1829      * If we're not already inside another macro expansion, we'd
1830      * better push a line synchronisation to ensure we stay put on
1831      * line numbering.
1832      */
1833     if (!istk->expansion)
1834         need_sync = TRUE;
1835
1836     /*
1837      * Fix up the parameters: this involves stripping leading and
1838      * trailing whitespace, then stripping braces if they are
1839      * present.
1840      */
1841     for (nparam = 0; params[nparam]; nparam++);
1842     paramlen = nparam ? nasm_malloc(nparam*sizeof(*paramlen)) : NULL;
1843
1844     for (i = 0; params[i]; i++) {
1845         int brace = FALSE;
1846         int comma = (!m->plus || i < nparam-1);
1847
1848         t = params[i];
1849         if (t && t->type == TOK_WHITESPACE)
1850             t = t->next;
1851         if (t && t->type == TOK_OTHER && !strcmp(t->text, "{"))
1852             t = t->next, brace = TRUE, comma = FALSE;
1853         params[i] = t;
1854         paramlen[i] = 0;
1855         while (t) {
1856             if (!t)                    /* end of param because EOL */
1857                 break;
1858             if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
1859                 break;                 /* ... because we have hit a comma */
1860             if (comma && t->type == TOK_WHITESPACE &&
1861                 t->next->type == TOK_OTHER && !strcmp(t->next->text, ","))
1862                 break;                 /* ... or a space then a comma */
1863             if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
1864                 break;                 /* ... or a brace */
1865             t = t->next;
1866             paramlen[i]++;
1867         }
1868     }
1869
1870     /*
1871      * OK, we have a MMacro structure together with a set of
1872      * parameters. We must now go through the expansion and push
1873      * _copies_ of each Line on to istk->expansion, having first
1874      * substituted for most % tokens (%1, %+1, %-1, %%foo). Note
1875      * that %$bar, %$$baz, %$$$quux, and so on, do not get
1876      * substituted here but rather have to wait until the
1877      * single-line macro substitution process. This is because they
1878      * don't just crop up in macro definitions, but can appear
1879      * anywhere they like.
1880      *
1881      * First, push an end marker on to istk->expansion, and mark
1882      * this macro as in progress.
1883      */
1884     ll = nasm_malloc(sizeof(Line));
1885     ll->next = istk->expansion;
1886     ll->finishes = m;
1887     ll->first = NULL;
1888     istk->expansion = ll;
1889     m->in_progress = TRUE;
1890     for (l = m->expansion; l; l = l->next) {
1891         Token **tail;
1892
1893         ll = nasm_malloc(sizeof(Line));
1894         ll->next = istk->expansion;
1895         ll->finishes = NULL;
1896         ll->first = NULL;
1897         tail = &ll->first;
1898
1899         for (t = l->first; t; t = t->next) {
1900             char *text;
1901             int type = 0, cc;          /* type = 0 to placate optimisers */
1902             char tmpbuf[30];
1903
1904             if (t->type == TOK_PREPROC_ID &&
1905                 (t->text[1] == '+' || t->text[1] == '-' ||
1906                  t->text[1] == '%' ||
1907                  (t->text[1] >= '0' && t->text[1] <= '9'))) {
1908                 /*
1909                  * We have to make a substitution of one of the
1910                  * forms %1, %-1, %+1, %%foo.
1911                  */
1912                 switch (t->text[1]) {
1913                   case '%':
1914                     type = TOK_ID;
1915                     sprintf(tmpbuf, "..@%lu.", unique);
1916                     text = nasm_malloc(strlen(tmpbuf)+strlen(t->text+2)+1);
1917                     strcpy(text, tmpbuf);
1918                     strcat(text, t->text+2);
1919                     break;
1920                   case '-':
1921                     n = atoi(t->text+2)-1;
1922                     tt = params[n];
1923                     cc = find_cc (tt);
1924                     if (cc == -1) {
1925                         error (ERR_NONFATAL|ERR_OFFBY1,
1926                                "macro parameter %d is not a condition code",
1927                                n+1);
1928                         text = NULL;
1929                     } else {
1930                         type = TOK_ID;
1931                         if (inverse_ccs[cc] == -1) {
1932                             error (ERR_NONFATAL|ERR_OFFBY1,
1933                                    "condition code `%s' is not invertible",
1934                                    conditions[cc]);
1935                             text = NULL;
1936                         } else
1937                             text = nasm_strdup(conditions[inverse_ccs[cc]]);
1938                     }
1939                     break;
1940                   case '+':
1941                     n = atoi(t->text+2)-1;
1942                     tt = params[n];
1943                     cc = find_cc (tt);
1944                     if (cc == -1) {
1945                         error (ERR_NONFATAL|ERR_OFFBY1,
1946                                "macro parameter %d is not a condition code",
1947                                n+1);
1948                         text = NULL;
1949                     } else {
1950                         type = TOK_ID;
1951                         text = nasm_strdup(conditions[cc]);
1952                     }
1953                     break;
1954                   default:
1955                     n = atoi(t->text+1)-1;
1956                     if (n < nparam) {
1957                         ttt = params[n];
1958                         for (i=0; i<paramlen[n]; i++) {
1959                             tt = *tail = nasm_malloc(sizeof(Token));
1960                             tt->next = NULL;
1961                             tail = &tt->next;
1962                             tt->type = ttt->type;
1963                             tt->text = nasm_strdup(ttt->text);
1964                             tt->mac = NULL;
1965                             ttt = ttt->next;
1966                         }
1967                     }
1968                     text = NULL;       /* we've done it here */
1969                     break;
1970                 }
1971             } else {
1972                 type = t->type;
1973                 text = nasm_strdup(t->text);
1974             }
1975
1976             if (text) {
1977                 tt = *tail = nasm_malloc(sizeof(Token));
1978                 tt->next = NULL;
1979                 tail = &tt->next;
1980                 tt->type = type;
1981                 tt->text = text;
1982                 tt->mac = NULL;
1983             }
1984         }
1985
1986         istk->expansion = ll;
1987
1988     }
1989
1990     /*
1991      * If we had a label, push it on the front of the first line of
1992      * the macro expansion.
1993      */
1994     if (label) {
1995         last->next = istk->expansion->first;
1996         istk->expansion->first = label;
1997     }
1998
1999     /*
2000      * Clean up.
2001      */
2002     unique++;
2003     nasm_free (paramlen);
2004     nasm_free (params);
2005     free_tlist (tline);
2006
2007     list->uplevel (m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2008
2009     return need_sync ? 2 : 1;
2010 }
2011
2012 static void pp_reset (char *file, efunc errfunc, ListGen *listgen) {
2013     int h;
2014
2015     error = errfunc;
2016     cstk = NULL;
2017     linesync = outline = NULL;
2018     istk = nasm_malloc(sizeof(Include));
2019     istk->next = NULL;
2020     istk->conds = NULL;
2021     istk->expansion = NULL;
2022     istk->fp = fopen(file, "r");
2023     istk->fname = nasm_strdup(file);
2024     istk->lineno = istk->lineinc = 1;
2025     if (!istk->fp)
2026         error (ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'", file);
2027     defining = NULL;
2028     for (h=0; h<NHASH; h++) {
2029         mmacros[h] = NULL;
2030         smacros[h] = NULL;
2031     }
2032     unique = 0;
2033     stdmacpos = stdmac;
2034     list = listgen;
2035 }
2036
2037 static char *pp_getline (void) {
2038     char *line;
2039     Token *tline;
2040     int ret;
2041
2042     if (outline) {
2043         line = outline;
2044         outline = NULL;
2045         return line;
2046     }
2047
2048     while (1) {
2049         /*
2050          * Fetch a tokenised line, either from the macro-expansion
2051          * buffer or from the input file.
2052          */
2053         tline = NULL;
2054         while (istk->expansion && istk->expansion->finishes) {
2055             Line *l = istk->expansion;
2056             l->finishes->in_progress = FALSE;
2057             istk->expansion = l->next;
2058             nasm_free (l);
2059             list->downlevel (LIST_MACRO);
2060             if (!istk->expansion)
2061                 line_sync();
2062         }
2063         if (istk->expansion) {
2064             char *p;
2065             Line *l = istk->expansion;
2066             tline = l->first;
2067             istk->expansion = l->next;
2068             nasm_free (l);
2069             p = detoken(tline);
2070             list->line (LIST_MACRO, p);
2071             nasm_free(p);
2072             if (!istk->expansion)
2073                 line_sync();
2074         } else {
2075             line = read_line();
2076             while (!line) {
2077                 /*
2078                  * The current file has ended; work down the istk
2079                  * until we find a file we can read from.
2080                  */
2081                 Include *i;
2082                 fclose(istk->fp);
2083                 if (istk->conds)
2084                     error(ERR_FATAL, "expected `%%endif' before end of file");
2085                 i = istk;
2086                 istk = istk->next;
2087                 list->downlevel (LIST_INCLUDE);
2088                 nasm_free (i->fname);
2089                 nasm_free (i);
2090                 if (!istk)
2091                     return NULL;
2092                 else
2093                     line_sync();
2094                 line = read_line();
2095             }
2096             line = prepreproc(line);
2097             tline = tokenise(line);
2098             nasm_free (line);
2099         }
2100
2101         /*
2102          * Check the line to see if it's a preprocessor directive.
2103          */
2104         ret = do_directive(tline);
2105         if (ret & 1) {
2106             free_tlist (tline);
2107             if (ret & 4)
2108                 line_sync();
2109             if ((ret & 2) && !stdmacpos) {/* give a blank line to the output */
2110                 outline = nasm_strdup("");
2111                 break;
2112             }
2113             else
2114                 continue;
2115         } else if (defining) {
2116             /*
2117              * We're defining a multi-line macro. We emit nothing
2118              * at all, not even a blank line (when we finish
2119              * defining the macro, we'll emit a line-number
2120              * directive so that we keep sync properly), and just
2121              * shove the tokenised line on to the macro definition.
2122              */
2123             Line *l = nasm_malloc(sizeof(Line));
2124             l->next = defining->expansion;
2125             l->first = tline;
2126             l->finishes = FALSE;
2127             defining->expansion = l;
2128             continue;
2129         } else if (istk->conds && !emitting(istk->conds->state)) {
2130             /*
2131              * We're in a non-emitting branch of a condition block.
2132              * Emit nothing at all, not even a blank line: when we
2133              * emerge from the condition we'll give a line-number
2134              * directive so we keep our place correctly.
2135              */
2136             free_tlist(tline);
2137             continue;
2138         } else {
2139             tline = expand_smacro(tline);
2140             ret = expand_mmacro(tline);
2141             if (!ret) {
2142                 /*
2143                  * De-tokenise the line again, and emit it.
2144                  */
2145                 line = detoken(tline);
2146                 free_tlist (tline);
2147                 outline = line;
2148                 break;
2149             } else {
2150                 if (ret == 2)
2151                     line_sync();
2152                 continue;              /* expand_mmacro calls free_tlist */
2153             }
2154         }
2155     }
2156
2157     /*
2158      * Once we're out of this loop, outline _must_ be non-NULL. The
2159      * only question is whether linesync is NULL or not.
2160      */
2161     if (linesync) {
2162         line = linesync;
2163         linesync = NULL;
2164     } else {
2165         line = outline;
2166         outline = NULL;
2167     }
2168     return line;
2169 }
2170
2171 static void pp_cleanup (void) {
2172     int h;
2173
2174     if (defining) {
2175         error (ERR_NONFATAL, "end of file while still defining macro `%s'",
2176                defining->name);
2177         nasm_free (defining->name);
2178         free_tlist (defining->dlist);
2179         free_llist (defining->expansion);
2180         nasm_free (defining);
2181     }
2182     nasm_free (linesync);              /* might just be necessary */
2183     nasm_free (outline);               /* really shouldn't be necessary */
2184     while (cstk)
2185         ctx_pop();
2186     for (h=0; h<NHASH; h++) {
2187         while (mmacros[h]) {
2188             MMacro *m = mmacros[h];
2189             mmacros[h] = mmacros[h]->next;
2190             nasm_free (m->name);
2191             free_tlist (m->dlist);
2192             free_llist (m->expansion);
2193             nasm_free (m);
2194         }
2195         while (smacros[h]) {
2196             SMacro *s = smacros[h];
2197             smacros[h] = smacros[h]->next;
2198             nasm_free (s->name);
2199             free_tlist (s->expansion);
2200             nasm_free (s);
2201         }
2202     }
2203     while (istk) {
2204         Include *i = istk;
2205         istk = istk->next;
2206         fclose(i->fp);
2207         nasm_free (i->fname);
2208         nasm_free (i);
2209     }
2210     while (cstk)
2211         ctx_pop();
2212 }
2213
2214 void pp_include_path (char *path) {
2215     IncPath *i;
2216
2217     i = nasm_malloc(sizeof(IncPath));
2218     i->path = nasm_strdup(path);
2219     i->next = ipath;
2220
2221     ipath = i;
2222 }
2223
2224 void pp_pre_include (char *fname) {
2225     Token *inc, *space, *name;
2226     Line *l;
2227
2228     inc = nasm_malloc(sizeof(Token));
2229     inc->next = space = nasm_malloc(sizeof(Token));
2230     space->next = name = nasm_malloc(sizeof(Token));
2231     name->next = NULL;
2232
2233     inc->type = TOK_PREPROC_ID;
2234     inc->text = nasm_strdup("%include");
2235     space->type = TOK_WHITESPACE;
2236     space->text = nasm_strdup(" ");
2237     name->type = TOK_INTERNAL_STRING;
2238     name->text = nasm_strdup(fname);
2239
2240     inc->mac = space->mac = name->mac = NULL;
2241
2242     l = nasm_malloc(sizeof(Line));
2243     l->next = predef;
2244     l->first = inc;
2245     l->finishes = FALSE;
2246     predef = l;
2247 }
2248
2249 void pp_pre_define (char *definition) {
2250     Token *def, *space, *name;
2251     Line *l;
2252     char *equals;
2253
2254     equals = strchr(definition, '=');
2255
2256     def = nasm_malloc(sizeof(Token));
2257     def->next = space = nasm_malloc(sizeof(Token));
2258     if (equals)
2259         *equals = ' ';
2260     space->next = name = tokenise(definition);
2261     if (equals)
2262         *equals = '=';
2263
2264     def->type = TOK_PREPROC_ID;
2265     def->text = nasm_strdup("%define");
2266     space->type = TOK_WHITESPACE;
2267     space->text = nasm_strdup(" ");
2268
2269     def->mac = space->mac = NULL;
2270
2271     l = nasm_malloc(sizeof(Line));
2272     l->next = predef;
2273     l->first = def;
2274     l->finishes = FALSE;
2275     predef = l;
2276 }
2277
2278 Preproc nasmpp = {
2279     pp_reset,
2280     pp_getline,
2281     pp_cleanup
2282 };