preproc.c: merge from preproc-rewrite branch
[platform/upstream/nasm.git] / preproc.c
1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 1996-2010 The NASM Authors - All Rights Reserved
4  *   See the file AUTHORS included with the NASM distribution for
5  *   the specific copyright holders.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following
9  *   conditions are met:
10  *
11  *   * Redistributions of source code must retain the above copyright
12  *     notice, this list of conditions and the following disclaimer.
13  *   * Redistributions in binary form must reproduce the above
14  *     copyright notice, this list of conditions and the following
15  *     disclaimer in the documentation and/or other materials provided
16  *     with the distribution.
17  *
18  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * ----------------------------------------------------------------------- */
33
34 /*
35  * preproc.c   macro preprocessor for the Netwide Assembler
36  */
37
38 /* Typical flow of text through preproc
39  *
40  * pp_getline gets tokenized lines, either
41  *
42  *   from a macro expansion
43  *
44  * or
45  *   {
46  *   read_line  gets raw text from stdmacpos, or predef, or current input file
47  *   tokenize   converts to tokens
48  *   }
49  *
50  * expand_mmac_params is used to expand %1 etc., unless a macro is being
51  * defined or a false conditional is being processed
52  * (%0, %1, %+1, %-1, %%foo
53  *
54  * do_directive checks for directives
55  *
56  * expand_smacro is used to expand single line macros
57  *
58  * expand_mmacro is used to expand multi-line macros
59  *
60  * detoken is used to convert the line back to text
61  */
62
63 #include "compiler.h"
64
65 #include <stdio.h>
66 #include <stdarg.h>
67 #include <stdlib.h>
68 #include <stddef.h>
69 #include <string.h>
70 #include <ctype.h>
71 #include <limits.h>
72 #include <inttypes.h>
73
74 #include "nasm.h"
75 #include "nasmlib.h"
76 #include "preproc.h"
77 #include "hashtbl.h"
78 #include "quote.h"
79 #include "stdscan.h"
80 #include "eval.h"
81 #include "tokens.h"
82 #include "tables.h"
83
84 typedef struct SMacro SMacro;
85 typedef struct ExpDef ExpDef;
86 typedef struct ExpInv ExpInv;
87 typedef struct Context Context;
88 typedef struct Token Token;
89 typedef struct Blocks Blocks;
90 typedef struct Line Line;
91 typedef struct Include Include;
92 typedef struct Cond Cond;
93 typedef struct IncPath IncPath;
94
95 /*
96  * Note on the storage of both SMacro and MMacros: the hash table
97  * indexes them case-insensitively, and we then have to go through a
98  * linked list of potential case aliases (and, for MMacros, parameter
99  * ranges); this is to preserve the matching semantics of the earlier
100  * code.  If the number of case aliases for a specific macro is a
101  * performance issue, you may want to reconsider your coding style.
102  */
103
104 /*
105  * Store the definition of a single-line macro.
106  */
107 struct SMacro {
108     SMacro *next;
109     char *name;
110     bool casesense;
111     bool in_progress;
112     unsigned int nparam;
113     Token *expansion;
114 };
115
116 /*
117  * The context stack is composed of a linked list of these.
118  */
119 struct Context {
120     Context *next;
121     char *name;
122     struct hash_table localmac;
123     uint32_t number;
124 };
125
126 /*
127  * This is the internal form which we break input lines up into.
128  * Typically stored in linked lists.
129  *
130  * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
131  * necessarily used as-is, but is intended to denote the number of
132  * the substituted parameter. So in the definition
133  *
134  *     %define a(x,y) ( (x) & ~(y) )
135  *
136  * the token representing `x' will have its type changed to
137  * TOK_SMAC_PARAM, but the one representing `y' will be
138  * TOK_SMAC_PARAM+1.
139  *
140  * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
141  * which doesn't need quotes around it. Used in the pre-include
142  * mechanism as an alternative to trying to find a sensible type of
143  * quote to use on the filename we were passed.
144  */
145 enum pp_token_type {
146     TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID,
147     TOK_PREPROC_ID, TOK_STRING,
148     TOK_NUMBER, TOK_FLOAT, TOK_SMAC_END, TOK_OTHER,
149     TOK_INTERNAL_STRING,
150     TOK_PREPROC_Q, TOK_PREPROC_QQ,
151     TOK_PASTE,              /* %+ */
152     TOK_INDIRECT,           /* %[...] */
153     TOK_SMAC_PARAM,         /* MUST BE LAST IN THE LIST!!! */
154     TOK_MAX = INT_MAX       /* Keep compiler from reducing the range */
155 };
156
157 #define PP_CONCAT_MASK(x) (1 << (x))
158
159 struct tokseq_match {
160     int mask_head;
161     int mask_tail;
162 };
163
164 struct Token {
165     Token *next;
166     char *text;
167     union {
168         SMacro *mac;        /* associated macro for TOK_SMAC_END */
169         size_t len;         /* scratch length field */
170     } a;                    /* Auxiliary data */
171     enum pp_token_type type;
172 };
173
174 /*
175  * Expansion definitions are stored as a linked list of
176  * these, which is essentially a container to allow several linked
177  * lists of Tokens.
178  *
179  * Note that in this module, linked lists are treated as stacks
180  * wherever possible. For this reason, Lines are _pushed_ on to the
181  * `last' field in ExpDef structures, so that the linked list,
182  * if walked, would emit the expansion lines in the proper order.
183  */
184 struct Line {
185     Line *next;
186     Token *first;
187 };
188
189 /*
190  * Expansion Types
191  */
192 enum pp_exp_type {
193     EXP_NONE = 0, EXP_PREDEF,
194         EXP_MMACRO, EXP_REP,
195     EXP_IF, EXP_WHILE,
196         EXP_COMMENT, EXP_FINAL,
197     EXP_MAX = INT_MAX       /* Keep compiler from reducing the range */
198 };
199
200 /*
201  * Store the definition of an expansion, in which is any
202  * preprocessor directive that has an ending pair.
203  *
204  * This design allows for arbitrary expansion/recursion depth,
205  * upto the DEADMAN_LIMIT.
206  *
207  * The `next' field is used for storing ExpDef in hash tables; the
208  * `prev' field is for the global `expansions` linked-list.
209  */
210 struct ExpDef {
211     ExpDef *prev;               /* previous definition */
212         ExpDef *next;                           /* next in hash table */
213     enum pp_exp_type type;      /* expansion type */
214     char *name;                 /* definition name */
215     int nparam_min, nparam_max;
216     bool casesense;
217     bool plus;                  /* is the last parameter greedy? */
218     bool nolist;                /* is this expansion listing-inhibited? */
219     Token *dlist;               /* all defaults as one list */
220     Token **defaults;           /* parameter default pointers */
221     int ndefs;                  /* number of default parameters */
222         
223         int prepend;                            /* label prepend state */
224         Line *label;
225     Line *line;
226         Line *last;
227         int linecount;                          /* number of lines within expansion */
228         
229         int64_t def_depth;                      /* current number of definition pairs deep */
230     int64_t cur_depth;          /* current number of expansions */
231     int64_t max_depth;          /* maximum number of expansions allowed */
232         
233         int state;                                      /* condition state */
234         bool ignoring;                          /* ignoring definition lines */
235 };
236
237 /*
238  * Store the invocation of an expansion.
239  *
240  * The `prev' field is for the `istk->expansion` linked-list.
241  *
242  * When an expansion is being expanded, `params', `iline', `nparam',
243  * `paramlen', `rotate' and `unique' are local to the invocation.
244  */
245 struct ExpInv {
246     ExpInv *prev;               /* previous invocation */
247     enum pp_exp_type type;      /* expansion type */
248     ExpDef *def;                /* pointer to expansion definition */
249         char *name;                 /* invocation name */
250         Line *label;                /* pointer to label */
251         char *label_text;                       /* pointer to label text */
252     Line *current;              /* pointer to current line in invocation */
253         
254     Token **params;             /* actual parameters */
255     Token *iline;               /* invocation line */
256     unsigned int nparam, rotate;
257     int *paramlen;
258         
259         uint64_t unique;
260     bool emitting;
261     int lineno;                 /* current line number in expansion */
262         int linnum;                                     /* line number at invocation */
263         int relno;                                      /* relative line number at invocation */
264 };
265
266 /*
267  * To handle an arbitrary level of file inclusion, we maintain a
268  * stack (ie linked list) of these things.
269  */
270 struct Include {
271     Include *next;
272     FILE *fp;
273     Cond *conds;
274     ExpInv *expansion;
275     char *fname;
276     int lineno, lineinc;
277         int mmac_depth;
278 };
279
280 /*
281  * Include search path. This is simply a list of strings which get
282  * prepended, in turn, to the name of an include file, in an
283  * attempt to find the file if it's not in the current directory.
284  */
285 struct IncPath {
286     IncPath *next;
287     char *path;
288 };
289
290 /*
291  * Conditional assembly: we maintain a separate stack of these for
292  * each level of file inclusion. (The only reason we keep the
293  * stacks separate is to ensure that a stray `%endif' in a file
294  * included from within the true branch of a `%if' won't terminate
295  * it and cause confusion: instead, rightly, it'll cause an error.)
296  */
297 enum {
298     /*
299      * These states are for use just after %if or %elif: IF_TRUE
300      * means the condition has evaluated to truth so we are
301      * currently emitting, whereas IF_FALSE means we are not
302      * currently emitting but will start doing so if a %else comes
303      * up. In these states, all directives are admissible: %elif,
304      * %else and %endif. (And of course %if.)
305      */
306     COND_IF_TRUE, COND_IF_FALSE,
307     /*
308      * These states come up after a %else: ELSE_TRUE means we're
309      * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
310      * any %elif or %else will cause an error.
311      */
312     COND_ELSE_TRUE, COND_ELSE_FALSE,
313     /*
314      * These states mean that we're not emitting now, and also that
315      * nothing until %endif will be emitted at all. COND_DONE is
316      * used when we've had our moment of emission
317      * and have now started seeing %elifs. COND_NEVER is used when
318      * the condition construct in question is contained within a
319      * non-emitting branch of a larger condition construct,
320      * or if there is an error.
321      */
322     COND_DONE, COND_NEVER
323 };
324 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
325
326 /*
327  * These defines are used as the possible return values for do_directive
328  */
329 #define NO_DIRECTIVE_FOUND  0
330 #define DIRECTIVE_FOUND     1
331
332 /*
333  * This define sets the upper limit for smacro and expansions
334  */
335 #define DEADMAN_LIMIT (1 << 20)
336
337 /* max reps */
338 #define REP_LIMIT ((INT64_C(1) << 62))
339
340 /*
341  * Condition codes. Note that we use c_ prefix not C_ because C_ is
342  * used in nasm.h for the "real" condition codes. At _this_ level,
343  * we treat CXZ and ECXZ as condition codes, albeit non-invertible
344  * ones, so we need a different enum...
345  */
346 static const char * const conditions[] = {
347     "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
348     "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
349     "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
350 };
351 enum pp_conds {
352     c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
353     c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
354     c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
355     c_none = -1
356 };
357 static const enum pp_conds inverse_ccs[] = {
358     c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
359     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,
360     c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
361 };
362
363 /* For TASM compatibility we need to be able to recognise TASM compatible
364  * conditional compilation directives. Using the NASM pre-processor does
365  * not work, so we look for them specifically from the following list and
366  * then jam in the equivalent NASM directive into the input stream.
367  */
368
369 enum {
370     TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
371     TM_IFNDEF, TM_INCLUDE, TM_LOCAL
372 };
373
374 static const char * const tasm_directives[] = {
375     "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
376     "ifndef", "include", "local"
377 };
378
379 static int StackSize = 4;
380 static char *StackPointer = "ebp";
381 static int ArgOffset = 8;
382 static int LocalOffset = 0;
383
384 static Context *cstk;
385 static Include *istk;
386 static IncPath *ipath = NULL;
387
388 static int pass;            /* HACK: pass 0 = generate dependencies only */
389 static StrList **dephead, **deptail; /* Dependency list */
390
391 static uint64_t unique;     /* unique identifier numbers */
392
393 static Line *predef = NULL;
394 static bool do_predef;
395
396 static ListGen *list;
397
398 /*
399  * The current set of expansion definitions we have defined.
400  */
401 static struct hash_table expdefs;
402
403 /*
404  * The current set of single-line macros we have defined.
405  */
406 static struct hash_table smacros;
407
408 /*
409  * Linked List of all active expansion definitions
410  */
411 struct ExpDef *expansions = NULL;
412
413 /*
414  * The expansion we are currently defining
415  */
416 static ExpDef *defining = NULL;
417
418 static uint64_t nested_mac_count;
419 static uint64_t nested_rep_count;
420
421 /*
422  * Linked-list of lines to preprocess, prior to cleanup
423  */
424 static Line *finals = NULL;
425 static bool in_final = false;
426
427 /*
428  * The number of macro parameters to allocate space for at a time.
429  */
430 #define PARAM_DELTA 16
431
432 /*
433  * The standard macro set: defined in macros.c in the array nasm_stdmac.
434  * This gives our position in the macro set, when we're processing it.
435  */
436 static macros_t *stdmacpos;
437
438 /*
439  * The extra standard macros that come from the object format, if
440  * any.
441  */
442 static macros_t *extrastdmac = NULL;
443 static bool any_extrastdmac;
444
445 /*
446  * Tokens are allocated in blocks to improve speed
447  */
448 #define TOKEN_BLOCKSIZE 4096
449 static Token *freeTokens = NULL;
450 struct Blocks {
451     Blocks *next;
452     void *chunk;
453 };
454
455 static Blocks blocks = { NULL, NULL };
456
457 /*
458  * Forward declarations.
459  */
460 static Token *expand_mmac_params(Token * tline);
461 static Token *expand_smacro(Token * tline);
462 static Token *expand_id(Token * tline);
463 static Context *get_ctx(const char *name, const char **namep,
464                         bool all_contexts);
465 static void make_tok_num(Token * tok, int64_t val);
466 static void error(int severity, const char *fmt, ...);
467 static void error_precond(int severity, const char *fmt, ...);
468 static void *new_Block(size_t size);
469 static void delete_Blocks(void);
470 static Token *new_Token(Token * next, enum pp_token_type type,
471                         const char *text, int txtlen);
472 static Token *copy_Token(Token * tline);
473 static Token *delete_Token(Token * t);
474 static Line *new_Line(void);
475 static ExpDef *new_ExpDef(int exp_type);
476 static ExpInv *new_ExpInv(int exp_type, ExpDef *ed);
477
478 /*
479  * Macros for safe checking of token pointers, avoid *(NULL)
480  */
481 #define tok_type_(x,t)  ((x) && (x)->type == (t))
482 #define skip_white_(x)  if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
483 #define tok_is_(x,v)    (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
484 #define tok_isnt_(x,v)  ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
485
486 /*
487  * nasm_unquote with error if the string contains NUL characters.
488  * If the string contains NUL characters, issue an error and return
489  * the C len, i.e. truncate at the NUL.
490  */
491 static size_t nasm_unquote_cstr(char *qstr, enum preproc_token directive)
492 {
493     size_t len = nasm_unquote(qstr, NULL);
494     size_t clen = strlen(qstr);
495
496     if (len != clen)
497         error(ERR_NONFATAL, "NUL character in `%s' directive",
498               pp_directives[directive]);
499
500     return clen;
501 }
502
503 /*
504  * In-place reverse a list of tokens.
505  */
506 static Token *reverse_tokens(Token *t)
507 {
508     Token *prev = NULL;
509     Token *next;
510
511     while (t) {
512         next = t->next;
513         t->next = prev;
514         prev = t;
515         t = next;
516         }
517
518     return prev;
519 }
520
521 /*
522  * Handle TASM specific directives, which do not contain a % in
523  * front of them. We do it here because I could not find any other
524  * place to do it for the moment, and it is a hack (ideally it would
525  * be nice to be able to use the NASM pre-processor to do it).
526  */
527 static char *check_tasm_directive(char *line)
528 {
529     int32_t i, j, k, m, len;
530     char *p, *q, *oldline, oldchar;
531
532     p = nasm_skip_spaces(line);
533
534     /* Binary search for the directive name */
535     i = -1;
536     j = ARRAY_SIZE(tasm_directives);
537     q = nasm_skip_word(p);
538     len = q - p;
539     if (len) {
540         oldchar = p[len];
541         p[len] = 0;
542         while (j - i > 1) {
543             k = (j + i) / 2;
544             m = nasm_stricmp(p, tasm_directives[k]);
545             if (m == 0) {
546                 /* We have found a directive, so jam a % in front of it
547                  * so that NASM will then recognise it as one if it's own.
548                  */
549                 p[len] = oldchar;
550                 len = strlen(p);
551                 oldline = line;
552                 line = nasm_malloc(len + 2);
553                 line[0] = '%';
554                 if (k == TM_IFDIFI) {
555                     /*
556                      * NASM does not recognise IFDIFI, so we convert
557                      * it to %if 0. This is not used in NASM
558                      * compatible code, but does need to parse for the
559                      * TASM macro package.
560                      */
561                     strcpy(line + 1, "if 0");
562                 } else {
563                     memcpy(line + 1, p, len + 1);
564                 }
565                 nasm_free(oldline);
566                 return line;
567             } else if (m < 0) {
568                 j = k;
569             } else
570                 i = k;
571         }
572         p[len] = oldchar;
573     }
574     return line;
575 }
576
577 /*
578  * The pre-preprocessing stage... This function translates line
579  * number indications as they emerge from GNU cpp (`# lineno "file"
580  * flags') into NASM preprocessor line number indications (`%line
581  * lineno file').
582  */
583 static char *prepreproc(char *line)
584 {
585     int lineno, fnlen;
586     char *fname, *oldline;
587
588     if (line[0] == '#' && line[1] == ' ') {
589         oldline = line;
590         fname = oldline + 2;
591         lineno = atoi(fname);
592         fname += strspn(fname, "0123456789 ");
593         if (*fname == '"')
594             fname++;
595         fnlen = strcspn(fname, "\"");
596         line = nasm_malloc(20 + fnlen);
597         snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
598         nasm_free(oldline);
599     }
600     if (tasm_compatible_mode)
601         return check_tasm_directive(line);
602     return line;
603 }
604
605 /*
606  * Free a linked list of tokens.
607  */
608 static void free_tlist(Token * list)
609 {
610     while (list)
611         list = delete_Token(list);
612 }
613
614 /*
615  * Free a linked list of lines.
616  */
617 static void free_llist(Line * list)
618 {
619     Line *l, *tmp;
620     list_for_each_safe(l, tmp, list) {
621         free_tlist(l->first);
622         nasm_free(l);
623     }
624 }
625
626 /*
627  * Free an ExpDef
628  */
629 static void free_expdef(ExpDef * ed)
630 {
631     nasm_free(ed->name);
632     free_tlist(ed->dlist);
633     nasm_free(ed->defaults);
634     free_llist(ed->line);
635     nasm_free(ed);
636 }
637
638 /*
639  * Free an ExpInv
640  */
641 static void free_expinv(ExpInv * ei)
642 {
643         if (ei->name != NULL)
644                 nasm_free(ei->name);
645         if (ei->label_text != NULL)
646                 nasm_free(ei->label_text);
647         nasm_free(ei);
648 }
649
650 /*
651  * Free all currently defined macros, and free the hash tables
652  */
653 static void free_smacro_table(struct hash_table *smt)
654 {
655     SMacro *s, *tmp;
656     const char *key;
657     struct hash_tbl_node *it = NULL;
658
659     while ((s = hash_iterate(smt, &it, &key)) != NULL) {
660         nasm_free((void *)key);
661         list_for_each_safe(s, tmp, s) {
662             nasm_free(s->name);
663             free_tlist(s->expansion);
664             nasm_free(s);
665         }
666     }
667     hash_free(smt);
668 }
669
670 static void free_expdef_table(struct hash_table *edt)
671 {
672     ExpDef *ed, *tmp;
673     const char *key;
674     struct hash_tbl_node *it = NULL;
675
676     it = NULL;
677     while ((ed = hash_iterate(edt, &it, &key)) != NULL) {
678         nasm_free((void *)key);
679         list_for_each_safe(ed ,tmp, ed)
680             free_expdef(ed);
681     }
682     hash_free(edt);
683 }
684
685 static void free_macros(void)
686 {
687     free_smacro_table(&smacros);
688     free_expdef_table(&expdefs);
689 }
690
691 /*
692  * Initialize the hash tables
693  */
694 static void init_macros(void)
695 {
696     hash_init(&smacros, HASH_LARGE);
697     hash_init(&expdefs, HASH_LARGE);
698 }
699
700 /*
701  * Pop the context stack.
702  */
703 static void ctx_pop(void)
704 {
705     Context *c = cstk;
706
707     cstk = cstk->next;
708     free_smacro_table(&c->localmac);
709     nasm_free(c->name);
710     nasm_free(c);
711 }
712
713 /*
714  * Search for a key in the hash index; adding it if necessary
715  * (in which case we initialize the data pointer to NULL.)
716  */
717 static void **
718 hash_findi_add(struct hash_table *hash, const char *str)
719 {
720     struct hash_insert hi;
721     void **r;
722     char *strx;
723
724     r = hash_findi(hash, str, &hi);
725     if (r)
726         return r;
727
728     strx = nasm_strdup(str);    /* Use a more efficient allocator here? */
729     return hash_add(&hi, strx, NULL);
730 }
731
732 /*
733  * Like hash_findi, but returns the data element rather than a pointer
734  * to it.  Used only when not adding a new element, hence no third
735  * argument.
736  */
737 static void *
738 hash_findix(struct hash_table *hash, const char *str)
739 {
740     void **p;
741
742     p = hash_findi(hash, str, NULL);
743     return p ? *p : NULL;
744 }
745
746 /*
747  * read line from standard macros set,
748  * if there no more left -- return NULL
749  */
750 static char *line_from_stdmac(void)
751 {
752     unsigned char c;
753     const unsigned char *p = stdmacpos;
754     char *line, *q;
755     size_t len = 0;
756
757     if (!stdmacpos)
758         return NULL;
759
760     while ((c = *p++)) {
761         if (c >= 0x80)
762             len += pp_directives_len[c - 0x80] + 1;
763         else
764             len++;
765     }
766
767     line = nasm_malloc(len + 1);
768     q = line;
769     while ((c = *stdmacpos++)) {
770         if (c >= 0x80) {
771             memcpy(q, pp_directives[c - 0x80], pp_directives_len[c - 0x80]);
772             q += pp_directives_len[c - 0x80];
773             *q++ = ' ';
774         } else {
775             *q++ = c;
776         }
777     }
778     stdmacpos = p;
779     *q = '\0';
780
781     if (!*stdmacpos) {
782         /* This was the last of the standard macro chain... */
783         stdmacpos = NULL;
784         if (any_extrastdmac) {
785             stdmacpos = extrastdmac;
786             any_extrastdmac = false;
787         } else if (do_predef) {
788                         ExpInv *ei;
789             Line *pd, *l;
790             Token *head, **tail, *t;
791
792             /*
793              * Nasty hack: here we push the contents of
794              * `predef' on to the top-level expansion stack,
795              * since this is the most convenient way to
796              * implement the pre-include and pre-define
797              * features.
798              */
799             list_for_each(pd, predef) {
800                 head = NULL;
801                 tail = &head;
802                 list_for_each(t, pd->first) {
803                     *tail = new_Token(NULL, t->type, t->text, 0);
804                     tail = &(*tail)->next;
805                 }
806
807                 l = new_Line();
808                 l->first = head;
809                                 ei = new_ExpInv(EXP_PREDEF, NULL);
810                                 ei->current = l;
811                                 ei->emitting = true;
812                                 ei->prev = istk->expansion;
813                 istk->expansion = ei;
814             }
815             do_predef = false;
816         }
817     }
818
819     return line;
820 }
821
822 #define BUF_DELTA 512
823 /*
824  * Read a line from the top file in istk, handling multiple CR/LFs
825  * at the end of the line read, and handling spurious ^Zs. Will
826  * return lines from the standard macro set if this has not already
827  * been done.
828  */
829 static char *read_line(void)
830 {
831     char *buffer, *p, *q;
832     int bufsize, continued_count;
833
834     /*
835      * standart macros set (predefined) goes first
836      */
837     p = line_from_stdmac();
838     if (p)
839         return p;
840
841     /*
842      * regular read from a file
843      */
844     bufsize = BUF_DELTA;
845     buffer = nasm_malloc(BUF_DELTA);
846     p = buffer;
847     continued_count = 0;
848     while (1) {
849         q = fgets(p, bufsize - (p - buffer), istk->fp);
850         if (!q)
851             break;
852         p += strlen(p);
853         if (p > buffer && p[-1] == '\n') {
854             /*
855              * Convert backslash-CRLF line continuation sequences into
856              * nothing at all (for DOS and Windows)
857              */
858             if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
859                 p -= 3;
860                 *p = 0;
861                 continued_count++;
862             }
863             /*
864              * Also convert backslash-LF line continuation sequences into
865              * nothing at all (for Unix)
866              */
867             else if (((p - 1) > buffer) && (p[-2] == '\\')) {
868                 p -= 2;
869                 *p = 0;
870                 continued_count++;
871             } else {
872                 break;
873             }
874         }
875         if (p - buffer > bufsize - 10) {
876             int32_t offset = p - buffer;
877             bufsize += BUF_DELTA;
878             buffer = nasm_realloc(buffer, bufsize);
879             p = buffer + offset;        /* prevent stale-pointer problems */
880         }
881     }
882
883     if (!q && p == buffer) {
884         nasm_free(buffer);
885         return NULL;
886     }
887
888         src_set_linnum(src_get_linnum() + istk->lineinc +
889                                    (continued_count * istk->lineinc));
890
891     /*
892      * Play safe: remove CRs as well as LFs, if any of either are
893      * present at the end of the line.
894      */
895     while (--p >= buffer && (*p == '\n' || *p == '\r'))
896         *p = '\0';
897
898     /*
899      * Handle spurious ^Z, which may be inserted into source files
900      * by some file transfer utilities.
901      */
902     buffer[strcspn(buffer, "\032")] = '\0';
903
904     list->line(LIST_READ, buffer);
905
906     return buffer;
907 }
908
909 /*
910  * Tokenize a line of text. This is a very simple process since we
911  * don't need to parse the value out of e.g. numeric tokens: we
912  * simply split one string into many.
913  */
914 static Token *tokenize(char *line)
915 {
916     char c, *p = line;
917     enum pp_token_type type;
918     Token *list = NULL;
919     Token *t, **tail = &list;
920
921     while (*line) {
922         p = line;
923         if (*p == '%') {
924             p++;
925             if (*p == '+' && !nasm_isdigit(p[1])) {
926                 p++;
927                 type = TOK_PASTE;
928             } else if (nasm_isdigit(*p) ||
929                        ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
930                 do {
931                     p++;
932                 }
933                 while (nasm_isdigit(*p));
934                 type = TOK_PREPROC_ID;
935             } else if (*p == '{') {
936                 p++;
937                 while (*p && *p != '}') {
938                     p[-1] = *p;
939                     p++;
940                 }
941                 p[-1] = '\0';
942                 if (*p)
943                     p++;
944                 type = TOK_PREPROC_ID;
945             } else if (*p == '[') {
946                 int lvl = 1;
947                 line += 2;      /* Skip the leading %[ */
948                 p++;
949                 while (lvl && (c = *p++)) {
950                     switch (c) {
951                     case ']':
952                         lvl--;
953                         break;
954                     case '%':
955                         if (*p == '[')
956                             lvl++;
957                         break;
958                     case '\'':
959                     case '\"':
960                     case '`':
961                         p = nasm_skip_string(p - 1) + 1;
962                         break;
963                     default:
964                         break;
965                     }
966                 }
967                 p--;
968                 if (*p)
969                     *p++ = '\0';
970                 if (lvl)
971                     error(ERR_NONFATAL, "unterminated %[ construct");
972                 type = TOK_INDIRECT;
973             } else if (*p == '?') {
974                 type = TOK_PREPROC_Q; /* %? */
975                 p++;
976                 if (*p == '?') {
977                     type = TOK_PREPROC_QQ; /* %?? */
978                     p++;
979                 }
980             } else if (*p == '!') {
981                 type = TOK_PREPROC_ID;
982                 p++;
983                 if (isidchar(*p)) {
984                     do {
985                         p++;
986                     } while (isidchar(*p));
987                 } else if (*p == '\'' || *p == '\"' || *p == '`') {
988                     p = nasm_skip_string(p);
989                     if (*p)
990                         p++;
991                     else
992                         error(ERR_NONFATAL|ERR_PASS1, "unterminated %! string");
993                 } else {
994                     /* %! without string or identifier */
995                     type = TOK_OTHER; /* Legacy behavior... */
996                 }
997             } else if (isidchar(*p) ||
998                        ((*p == '!' || *p == '%' || *p == '$') &&
999                         isidchar(p[1]))) {
1000                 do {
1001                     p++;
1002                 }
1003                 while (isidchar(*p));
1004                 type = TOK_PREPROC_ID;
1005             } else {
1006                 type = TOK_OTHER;
1007                 if (*p == '%')
1008                     p++;
1009             }
1010         } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
1011             type = TOK_ID;
1012             p++;
1013             while (*p && isidchar(*p))
1014                 p++;
1015         } else if (*p == '\'' || *p == '"' || *p == '`') {
1016             /*
1017              * A string token.
1018              */
1019             type = TOK_STRING;
1020             p = nasm_skip_string(p);
1021
1022             if (*p) {
1023                 p++;
1024             } else {
1025                 error(ERR_WARNING|ERR_PASS1, "unterminated string");
1026                 /* Handling unterminated strings by UNV */
1027                 /* type = -1; */
1028             }
1029         } else if (p[0] == '$' && p[1] == '$') {
1030             type = TOK_OTHER;   /* TOKEN_BASE */
1031             p += 2;
1032         } else if (isnumstart(*p)) {
1033             bool is_hex = false;
1034             bool is_float = false;
1035             bool has_e = false;
1036             char c, *r;
1037
1038             /*
1039              * A numeric token.
1040              */
1041
1042             if (*p == '$') {
1043                 p++;
1044                 is_hex = true;
1045             }
1046
1047             for (;;) {
1048                 c = *p++;
1049
1050                 if (!is_hex && (c == 'e' || c == 'E')) {
1051                     has_e = true;
1052                     if (*p == '+' || *p == '-') {
1053                         /*
1054                          * e can only be followed by +/- if it is either a
1055                          * prefixed hex number or a floating-point number
1056                          */
1057                         p++;
1058                         is_float = true;
1059                     }
1060                 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
1061                     is_hex = true;
1062                 } else if (c == 'P' || c == 'p') {
1063                     is_float = true;
1064                     if (*p == '+' || *p == '-')
1065                         p++;
1066                 } else if (isnumchar(c) || c == '_')
1067                     ; /* just advance */
1068                 else if (c == '.') {
1069                     /*
1070                      * we need to deal with consequences of the legacy
1071                      * parser, like "1.nolist" being two tokens
1072                      * (TOK_NUMBER, TOK_ID) here; at least give it
1073                      * a shot for now.  In the future, we probably need
1074                      * a flex-based scanner with proper pattern matching
1075                      * to do it as well as it can be done.  Nothing in
1076                      * the world is going to help the person who wants
1077                      * 0x123.p16 interpreted as two tokens, though.
1078                      */
1079                     r = p;
1080                     while (*r == '_')
1081                         r++;
1082
1083                     if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
1084                         (!is_hex && (*r == 'e' || *r == 'E')) ||
1085                         (*r == 'p' || *r == 'P')) {
1086                         p = r;
1087                         is_float = true;
1088                     } else
1089                         break;  /* Terminate the token */
1090                 } else
1091                     break;
1092             }
1093             p--;        /* Point to first character beyond number */
1094
1095             if (p == line+1 && *line == '$') {
1096                 type = TOK_OTHER; /* TOKEN_HERE */
1097             } else {
1098                 if (has_e && !is_hex) {
1099                     /* 1e13 is floating-point, but 1e13h is not */
1100                     is_float = true;
1101                 }
1102
1103                 type = is_float ? TOK_FLOAT : TOK_NUMBER;
1104             }
1105         } else if (nasm_isspace(*p)) {
1106             type = TOK_WHITESPACE;
1107             p = nasm_skip_spaces(p);
1108             /*
1109              * Whitespace just before end-of-line is discarded by
1110              * pretending it's a comment; whitespace just before a
1111              * comment gets lumped into the comment.
1112              */
1113             if (!*p || *p == ';') {
1114                 type = TOK_COMMENT;
1115                 while (*p)
1116                     p++;
1117             }
1118         } else if (*p == ';') {
1119             type = TOK_COMMENT;
1120             while (*p)
1121                 p++;
1122         } else {
1123             /*
1124              * Anything else is an operator of some kind. We check
1125              * for all the double-character operators (>>, <<, //,
1126              * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1127              * else is a single-character operator.
1128              */
1129             type = TOK_OTHER;
1130             if ((p[0] == '>' && p[1] == '>') ||
1131                 (p[0] == '<' && p[1] == '<') ||
1132                 (p[0] == '/' && p[1] == '/') ||
1133                 (p[0] == '<' && p[1] == '=') ||
1134                 (p[0] == '>' && p[1] == '=') ||
1135                 (p[0] == '=' && p[1] == '=') ||
1136                 (p[0] == '!' && p[1] == '=') ||
1137                 (p[0] == '<' && p[1] == '>') ||
1138                 (p[0] == '&' && p[1] == '&') ||
1139                 (p[0] == '|' && p[1] == '|') ||
1140                 (p[0] == '^' && p[1] == '^')) {
1141                 p++;
1142             }
1143             p++;
1144         }
1145
1146         /* Handling unterminated string by UNV */
1147         /*if (type == -1)
1148           {
1149           *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1150           t->text[p-line] = *line;
1151           tail = &t->next;
1152           }
1153           else */
1154         if (type != TOK_COMMENT) {
1155             *tail = t = new_Token(NULL, type, line, p - line);
1156             tail = &t->next;
1157         }
1158         line = p;
1159     }
1160     return list;
1161 }
1162
1163 /*
1164  * this function allocates a new managed block of memory and
1165  * returns a pointer to the block.  The managed blocks are
1166  * deleted only all at once by the delete_Blocks function.
1167  */
1168 static void *new_Block(size_t size)
1169 {
1170     Blocks *b = &blocks;
1171
1172     /* first, get to the end of the linked list */
1173     while (b->next)
1174         b = b->next;
1175     /* now allocate the requested chunk */
1176     b->chunk = nasm_malloc(size);
1177
1178     /* now allocate a new block for the next request */
1179     b->next = nasm_malloc(sizeof(Blocks));
1180     /* and initialize the contents of the new block */
1181     b->next->next = NULL;
1182     b->next->chunk = NULL;
1183     return b->chunk;
1184 }
1185
1186 /*
1187  * this function deletes all managed blocks of memory
1188  */
1189 static void delete_Blocks(void)
1190 {
1191     Blocks *a, *b = &blocks;
1192
1193     /*
1194      * keep in mind that the first block, pointed to by blocks
1195      * is a static and not dynamically allocated, so we don't
1196      * free it.
1197      */
1198     while (b) {
1199         if (b->chunk)
1200             nasm_free(b->chunk);
1201         a = b;
1202         b = b->next;
1203         if (a != &blocks)
1204             nasm_free(a);
1205     }
1206 }
1207
1208 /*
1209  *  this function creates a new Token and passes a pointer to it
1210  *  back to the caller.  It sets the type and text elements, and
1211  *  also the a.mac and next elements to NULL.
1212  */
1213 static Token *new_Token(Token * next, enum pp_token_type type,
1214                         const char *text, int txtlen)
1215 {
1216     Token *t;
1217     int i;
1218
1219     if (!freeTokens) {
1220         freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
1221         for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
1222             freeTokens[i].next = &freeTokens[i + 1];
1223         freeTokens[i].next = NULL;
1224     }
1225     t = freeTokens;
1226     freeTokens = t->next;
1227     t->next = next;
1228     t->a.mac = NULL;
1229     t->type = type;
1230     if (type == TOK_WHITESPACE || !text) {
1231         t->text = NULL;
1232     } else {
1233         if (txtlen == 0)
1234             txtlen = strlen(text);
1235         t->text = nasm_malloc(txtlen+1);
1236         memcpy(t->text, text, txtlen);
1237         t->text[txtlen] = '\0';
1238     }
1239     return t;
1240 }
1241
1242 static Token *copy_Token(Token * tline)
1243 {
1244     Token *t, *tt, *first = NULL, *prev = NULL;
1245     int i;
1246         for (tt = tline; tt != NULL; tt = tt->next) {
1247                 if (!freeTokens) {
1248                         freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
1249                         for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
1250                                 freeTokens[i].next = &freeTokens[i + 1];
1251                         freeTokens[i].next = NULL;
1252                 }
1253                 t = freeTokens;
1254                 freeTokens = t->next;
1255                 t->next = NULL;
1256                 t->text = ((tt->text != NULL) ? strdup(tt->text) : NULL);
1257                 t->a.mac = tt->a.mac;
1258                 t->a.len = tt->a.len;
1259                 t->type = tt->type;
1260                 if (prev != NULL) {
1261                         prev->next = t;
1262                 } else {
1263                         first = t;
1264                 }
1265                 prev = t;
1266         }
1267     return first;
1268 }
1269
1270 static Token *delete_Token(Token * t)
1271 {
1272     Token *next = t->next;
1273     nasm_free(t->text);
1274     t->next = freeTokens;
1275     freeTokens = t;
1276     return next;
1277 }
1278
1279 /*
1280  * Convert a line of tokens back into text.
1281  * If expand_locals is not zero, identifiers of the form "%$*xxx"
1282  * will be transformed into ..@ctxnum.xxx
1283  */
1284 static char *detoken(Token * tlist, bool expand_locals)
1285 {
1286     Token *t;
1287     char *line, *p;
1288     const char *q;
1289     int len = 0;
1290
1291     list_for_each(t, tlist) {
1292         if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
1293             char *v;
1294             char *q = t->text;
1295
1296             v = t->text + 2;
1297             if (*v == '\'' || *v == '\"' || *v == '`') {
1298                 size_t len = nasm_unquote(v, NULL);
1299                 size_t clen = strlen(v);
1300
1301                 if (len != clen) {
1302                     error(ERR_NONFATAL | ERR_PASS1,
1303                           "NUL character in %! string");
1304                     v = NULL;
1305                 }
1306             }
1307
1308             if (v) {
1309                 char *p = getenv(v);
1310                 if (!p) {
1311                     error(ERR_NONFATAL | ERR_PASS1,
1312                           "nonexistent environment variable `%s'", v);
1313                     p = "";
1314                 }
1315                 t->text = nasm_strdup(p);
1316             }
1317             nasm_free(q);
1318         }
1319
1320         /* Expand local macros here and not during preprocessing */
1321         if (expand_locals &&
1322             t->type == TOK_PREPROC_ID && t->text &&
1323             t->text[0] == '%' && t->text[1] == '$') {
1324             const char *q;
1325             char *p;
1326             Context *ctx = get_ctx(t->text, &q, false);
1327             if (ctx) {
1328                 char buffer[40];
1329                 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
1330                 p = nasm_strcat(buffer, q);
1331                 nasm_free(t->text);
1332                 t->text = p;
1333             }
1334         }
1335
1336         /* Expand %? and %?? directives */
1337         if (expand_locals && (istk->expansion != NULL) &&
1338                         ((t->type == TOK_PREPROC_Q) ||
1339                          (t->type == TOK_PREPROC_QQ))) {
1340             ExpInv *ei;
1341                         for (ei = istk->expansion; ei != NULL; ei = ei->prev){
1342                                 if (ei->type == EXP_MMACRO) {
1343                                         nasm_free(t->text);
1344                                         if (t->type == TOK_PREPROC_Q) {
1345                                                 t->text = nasm_strdup(ei->name);
1346                                         } else {
1347                                                 t->text = nasm_strdup(ei->def->name);
1348                                         }
1349                                         break;
1350                                 }
1351                         }
1352                 }
1353
1354         if (t->type == TOK_WHITESPACE)
1355             len++;
1356         else if (t->text)
1357             len += strlen(t->text);
1358     }
1359
1360     p = line = nasm_malloc(len + 1);
1361
1362     list_for_each(t, tlist) {
1363         if (t->type == TOK_WHITESPACE) {
1364             *p++ = ' ';
1365         } else if (t->text) {
1366             q = t->text;
1367             while (*q)
1368                 *p++ = *q++;
1369         }
1370     }
1371     *p = '\0';
1372
1373     return line;
1374 }
1375
1376 /*
1377  * Initialize a new Line
1378  */
1379 static Line *new_Line(void)
1380 {
1381         Line *l = nasm_malloc(sizeof(Line));
1382         l->next = NULL;
1383         l->first = NULL;
1384         return l;
1385 }
1386
1387
1388 /*
1389  * Initialize a new Expansion Definition
1390  */
1391 static ExpDef *new_ExpDef(int exp_type)
1392 {
1393         ExpDef *ed = nasm_malloc(sizeof(ExpDef));
1394         ed->prev = NULL;
1395         ed->next = NULL;
1396         ed->type = exp_type;
1397         ed->name = NULL;
1398         ed->nparam_min = 0;
1399         ed->nparam_max = 0;
1400         ed->casesense = true;
1401         ed->plus = false;
1402         ed->prepend = 0;
1403         ed->label = NULL;
1404         ed->line = NULL;
1405         ed->last = NULL;
1406         ed->linecount = 0;
1407         ed->dlist = NULL;
1408         ed->defaults = NULL;
1409         ed->ndefs = 0;
1410         ed->state = COND_NEVER;
1411         ed->nolist = false;
1412         ed->def_depth = 0;
1413         ed->cur_depth = 0;
1414         ed->max_depth = 0;
1415         ed->ignoring = false;
1416         return ed;
1417 }
1418
1419
1420 /*
1421  * Initialize a new Expansion Instance
1422  */
1423 static ExpInv *new_ExpInv(int exp_type, ExpDef *ed)
1424 {
1425         unique ++;
1426         ExpInv *ei = nasm_malloc(sizeof(ExpInv));
1427         ei->prev = NULL;
1428         ei->type = exp_type;
1429         ei->def = ed;
1430         ei->name = NULL;
1431         ei->label = NULL;
1432         ei->label_text = NULL;
1433         ei->current = NULL;
1434         ei->params = NULL;
1435         ei->iline = NULL;
1436         ei->nparam = 0;
1437         ei->rotate = 0;
1438         ei->paramlen = NULL;
1439         ei->unique = unique;
1440         ei->emitting = false;
1441         ei->lineno = 0;
1442         if ((istk->mmac_depth < 1) &&
1443                 (istk->expansion == NULL) &&
1444                 (ed != NULL) &&
1445                 (ed->type != EXP_MMACRO) &&
1446                 (ed->type != EXP_REP) &&
1447                 (ed->type != EXP_WHILE)) {
1448                 ei->linnum = src_get_linnum();
1449                 src_set_linnum(ei->linnum - ed->linecount - 1);
1450         } else {
1451                 ei->linnum = -1;
1452         }
1453         if ((istk->expansion == NULL) ||
1454                 (ei->type == EXP_MMACRO)) {
1455                 ei->relno = 0;
1456         } else {
1457                 ei->relno = istk->expansion->lineno;
1458                 if (ed != NULL) {
1459                         ei->relno -= (ed->linecount + 1);
1460                 }
1461         }
1462         return ei;
1463 }
1464
1465 /*
1466  * A scanner, suitable for use by the expression evaluator, which
1467  * operates on a line of Tokens. Expects a pointer to a pointer to
1468  * the first token in the line to be passed in as its private_data
1469  * field.
1470  *
1471  * FIX: This really needs to be unified with stdscan.
1472  */
1473 static int ppscan(void *private_data, struct tokenval *tokval)
1474 {
1475     Token **tlineptr = private_data;
1476     Token *tline;
1477     char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
1478
1479     do {
1480         tline = *tlineptr;
1481         *tlineptr = tline ? tline->next : NULL;
1482     } while (tline && (tline->type == TOK_WHITESPACE ||
1483                        tline->type == TOK_COMMENT));
1484
1485     if (!tline)
1486         return tokval->t_type = TOKEN_EOS;
1487
1488     tokval->t_charptr = tline->text;
1489
1490     if (tline->text[0] == '$' && !tline->text[1])
1491         return tokval->t_type = TOKEN_HERE;
1492     if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
1493         return tokval->t_type = TOKEN_BASE;
1494
1495     if (tline->type == TOK_ID) {
1496         p = tokval->t_charptr = tline->text;
1497         if (p[0] == '$') {
1498             tokval->t_charptr++;
1499             return tokval->t_type = TOKEN_ID;
1500         }
1501
1502         for (r = p, s = ourcopy; *r; r++) {
1503             if (r >= p+MAX_KEYWORD)
1504                 return tokval->t_type = TOKEN_ID; /* Not a keyword */
1505             *s++ = nasm_tolower(*r);
1506         }
1507         *s = '\0';
1508         /* right, so we have an identifier sitting in temp storage. now,
1509          * is it actually a register or instruction name, or what? */
1510         return nasm_token_hash(ourcopy, tokval);
1511     }
1512
1513     if (tline->type == TOK_NUMBER) {
1514         bool rn_error;
1515         tokval->t_integer = readnum(tline->text, &rn_error);
1516         tokval->t_charptr = tline->text;
1517         if (rn_error)
1518             return tokval->t_type = TOKEN_ERRNUM;
1519         else
1520             return tokval->t_type = TOKEN_NUM;
1521     }
1522
1523     if (tline->type == TOK_FLOAT) {
1524         return tokval->t_type = TOKEN_FLOAT;
1525     }
1526
1527     if (tline->type == TOK_STRING) {
1528         char bq, *ep;
1529
1530         bq = tline->text[0];
1531         tokval->t_charptr = tline->text;
1532         tokval->t_inttwo = nasm_unquote(tline->text, &ep);
1533
1534         if (ep[0] != bq || ep[1] != '\0')
1535             return tokval->t_type = TOKEN_ERRSTR;
1536         else
1537             return tokval->t_type = TOKEN_STR;
1538     }
1539
1540     if (tline->type == TOK_OTHER) {
1541         if (!strcmp(tline->text, "<<"))
1542             return tokval->t_type = TOKEN_SHL;
1543         if (!strcmp(tline->text, ">>"))
1544             return tokval->t_type = TOKEN_SHR;
1545         if (!strcmp(tline->text, "//"))
1546             return tokval->t_type = TOKEN_SDIV;
1547         if (!strcmp(tline->text, "%%"))
1548             return tokval->t_type = TOKEN_SMOD;
1549         if (!strcmp(tline->text, "=="))
1550             return tokval->t_type = TOKEN_EQ;
1551         if (!strcmp(tline->text, "<>"))
1552             return tokval->t_type = TOKEN_NE;
1553         if (!strcmp(tline->text, "!="))
1554             return tokval->t_type = TOKEN_NE;
1555         if (!strcmp(tline->text, "<="))
1556             return tokval->t_type = TOKEN_LE;
1557         if (!strcmp(tline->text, ">="))
1558             return tokval->t_type = TOKEN_GE;
1559         if (!strcmp(tline->text, "&&"))
1560             return tokval->t_type = TOKEN_DBL_AND;
1561         if (!strcmp(tline->text, "^^"))
1562             return tokval->t_type = TOKEN_DBL_XOR;
1563         if (!strcmp(tline->text, "||"))
1564             return tokval->t_type = TOKEN_DBL_OR;
1565     }
1566
1567     /*
1568      * We have no other options: just return the first character of
1569      * the token text.
1570      */
1571     return tokval->t_type = tline->text[0];
1572 }
1573
1574 /*
1575  * Compare a string to the name of an existing macro; this is a
1576  * simple wrapper which calls either strcmp or nasm_stricmp
1577  * depending on the value of the `casesense' parameter.
1578  */
1579 static int mstrcmp(const char *p, const char *q, bool casesense)
1580 {
1581     return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
1582 }
1583
1584 /*
1585  * Compare a string to the name of an existing macro; this is a
1586  * simple wrapper which calls either strcmp or nasm_stricmp
1587  * depending on the value of the `casesense' parameter.
1588  */
1589 static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
1590 {
1591     return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
1592 }
1593
1594 /*
1595  * Return the Context structure associated with a %$ token. Return
1596  * NULL, having _already_ reported an error condition, if the
1597  * context stack isn't deep enough for the supplied number of $
1598  * signs.
1599  * If all_contexts == true, contexts that enclose current are
1600  * also scanned for such smacro, until it is found; if not -
1601  * only the context that directly results from the number of $'s
1602  * in variable's name.
1603  *
1604  * If "namep" is non-NULL, set it to the pointer to the macro name
1605  * tail, i.e. the part beyond %$...
1606  */
1607 static Context *get_ctx(const char *name, const char **namep,
1608                         bool all_contexts)
1609 {
1610     Context *ctx;
1611     SMacro *m;
1612     int i;
1613
1614     if (namep)
1615         *namep = name;
1616
1617     if (!name || name[0] != '%' || name[1] != '$')
1618         return NULL;
1619
1620     if (!cstk) {
1621         error(ERR_NONFATAL, "`%s': context stack is empty", name);
1622         return NULL;
1623     }
1624
1625     name += 2;
1626     ctx = cstk;
1627     i = 0;
1628     while (ctx && *name == '$') {
1629         name++;
1630         i++;
1631         ctx = ctx->next;
1632     }
1633     if (!ctx) {
1634         error(ERR_NONFATAL, "`%s': context stack is only"
1635               " %d level%s deep", name, i, (i == 1 ? "" : "s"));
1636         return NULL;
1637     }
1638
1639     if (namep)
1640         *namep = name;
1641
1642     if (!all_contexts)
1643         return ctx;
1644
1645     do {
1646         /* Search for this smacro in found context */
1647         m = hash_findix(&ctx->localmac, name);
1648         while (m) {
1649             if (!mstrcmp(m->name, name, m->casesense))
1650                 return ctx;
1651             m = m->next;
1652         }
1653         ctx = ctx->next;
1654     }
1655     while (ctx);
1656     return NULL;
1657 }
1658
1659 /*
1660  * Check to see if a file is already in a string list
1661  */
1662 static bool in_list(const StrList *list, const char *str)
1663 {
1664     while (list) {
1665         if (!strcmp(list->str, str))
1666             return true;
1667         list = list->next;
1668     }
1669     return false;
1670 }
1671
1672 /*
1673  * Open an include file. This routine must always return a valid
1674  * file pointer if it returns - it's responsible for throwing an
1675  * ERR_FATAL and bombing out completely if not. It should also try
1676  * the include path one by one until it finds the file or reaches
1677  * the end of the path.
1678  */
1679 static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
1680                        bool missing_ok)
1681 {
1682     FILE *fp;
1683     char *prefix = "";
1684     IncPath *ip = ipath;
1685     int len = strlen(file);
1686     size_t prefix_len = 0;
1687     StrList *sl;
1688
1689     while (1) {
1690         sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
1691         memcpy(sl->str, prefix, prefix_len);
1692         memcpy(sl->str+prefix_len, file, len+1);
1693         fp = fopen(sl->str, "r");
1694         if (fp && dhead && !in_list(*dhead, sl->str)) {
1695             sl->next = NULL;
1696             **dtail = sl;
1697             *dtail = &sl->next;
1698         } else {
1699             nasm_free(sl);
1700         }
1701         if (fp)
1702             return fp;
1703         if (!ip) {
1704             if (!missing_ok)
1705                 break;
1706             prefix = NULL;
1707         } else {
1708             prefix = ip->path;
1709             ip = ip->next;
1710         }
1711         if (prefix) {
1712             prefix_len = strlen(prefix);
1713         } else {
1714             /* -MG given and file not found */
1715             if (dhead && !in_list(*dhead, file)) {
1716                 sl = nasm_malloc(len+1+sizeof sl->next);
1717                 sl->next = NULL;
1718                 strcpy(sl->str, file);
1719                 **dtail = sl;
1720                 *dtail = &sl->next;
1721             }
1722             return NULL;
1723         }
1724     }
1725
1726     error(ERR_FATAL, "unable to open include file `%s'", file);
1727     return NULL;
1728 }
1729
1730 /*
1731  * Determine if we should warn on defining a single-line macro of
1732  * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1733  * return true if _any_ single-line macro of that name is defined.
1734  * Otherwise, will return true if a single-line macro with either
1735  * `nparam' or no parameters is defined.
1736  *
1737  * If a macro with precisely the right number of parameters is
1738  * defined, or nparam is -1, the address of the definition structure
1739  * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1740  * is NULL, no action will be taken regarding its contents, and no
1741  * error will occur.
1742  *
1743  * Note that this is also called with nparam zero to resolve
1744  * `ifdef'.
1745  *
1746  * If you already know which context macro belongs to, you can pass
1747  * the context pointer as first parameter; if you won't but name begins
1748  * with %$ the context will be automatically computed. If all_contexts
1749  * is true, macro will be searched in outer contexts as well.
1750  */
1751 static bool
1752 smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
1753                bool nocase)
1754 {
1755     struct hash_table *smtbl;
1756     SMacro *m;
1757
1758     if (ctx) {
1759         smtbl = &ctx->localmac;
1760     } else if (name[0] == '%' && name[1] == '$') {
1761         if (cstk)
1762             ctx = get_ctx(name, &name, false);
1763         if (!ctx)
1764             return false;       /* got to return _something_ */
1765         smtbl = &ctx->localmac;
1766     } else {
1767         smtbl = &smacros;
1768     }
1769     m = (SMacro *) hash_findix(smtbl, name);
1770
1771     while (m) {
1772         if (!mstrcmp(m->name, name, m->casesense && nocase) &&
1773             (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
1774             if (defn) {
1775                 if (nparam == (int) m->nparam || nparam == -1)
1776                     *defn = m;
1777                 else
1778                     *defn = NULL;
1779             }
1780             return true;
1781         }
1782         m = m->next;
1783     }
1784
1785     return false;
1786 }
1787
1788 /*
1789  * Count and mark off the parameters in a multi-line macro call.
1790  * This is called both from within the multi-line macro expansion
1791  * code, and also to mark off the default parameters when provided
1792  * in a %macro definition line.
1793  */
1794 static void count_mmac_params(Token * t, int *nparam, Token *** params)
1795 {
1796     int paramsize, brace;
1797
1798     *nparam = paramsize = 0;
1799     *params = NULL;
1800     while (t) {
1801         /* +1: we need space for the final NULL */
1802         if (*nparam+1 >= paramsize) {
1803             paramsize += PARAM_DELTA;
1804             *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1805         }
1806         skip_white_(t);
1807         brace = false;
1808         if (tok_is_(t, "{"))
1809             brace = true;
1810         (*params)[(*nparam)++] = t;
1811         while (tok_isnt_(t, brace ? "}" : ","))
1812             t = t->next;
1813         if (t) {                /* got a comma/brace */
1814             t = t->next;
1815             if (brace) {
1816                 /*
1817                  * Now we've found the closing brace, look further
1818                  * for the comma.
1819                  */
1820                 skip_white_(t);
1821                 if (tok_isnt_(t, ",")) {
1822                     error(ERR_NONFATAL,
1823                           "braces do not enclose all of macro parameter");
1824                     while (tok_isnt_(t, ","))
1825                         t = t->next;
1826                 }
1827                 if (t)
1828                     t = t->next;        /* eat the comma */
1829             }
1830         }
1831     }
1832 }
1833
1834 /*
1835  * Determine whether one of the various `if' conditions is true or
1836  * not.
1837  *
1838  * We must free the tline we get passed.
1839  */
1840 static bool if_condition(Token * tline, enum preproc_token ct)
1841 {
1842     enum pp_conditional i = PP_COND(ct);
1843     bool j;
1844     Token *t, *tt, **tptr, *origline;
1845     struct tokenval tokval;
1846     expr *evalresult;
1847     enum pp_token_type needtype;
1848     char *p;
1849
1850     origline = tline;
1851
1852     switch (i) {
1853     case PPC_IFCTX:
1854         j = false;              /* have we matched yet? */
1855         while (true) {
1856             skip_white_(tline);
1857             if (!tline)
1858                 break;
1859             if (tline->type != TOK_ID) {
1860                 error(ERR_NONFATAL,
1861                       "`%s' expects context identifiers", pp_directives[ct]);
1862                 free_tlist(origline);
1863                 return -1;
1864             }
1865             if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name))
1866                 j = true;
1867             tline = tline->next;
1868         }
1869         break;
1870
1871     case PPC_IFDEF:
1872         j = false;              /* have we matched yet? */
1873         while (tline) {
1874             skip_white_(tline);
1875             if (!tline || (tline->type != TOK_ID &&
1876                            (tline->type != TOK_PREPROC_ID ||
1877                             tline->text[1] != '$'))) {
1878                 error(ERR_NONFATAL,
1879                       "`%s' expects macro identifiers", pp_directives[ct]);
1880                 goto fail;
1881             }
1882             if (smacro_defined(NULL, tline->text, 0, NULL, true))
1883                 j = true;
1884             tline = tline->next;
1885         }
1886         break;
1887
1888     case PPC_IFENV:
1889         tline = expand_smacro(tline);
1890         j = false;              /* have we matched yet? */
1891         while (tline) {
1892             skip_white_(tline);
1893             if (!tline || (tline->type != TOK_ID &&
1894                            tline->type != TOK_STRING &&
1895                            (tline->type != TOK_PREPROC_ID ||
1896                             tline->text[1] != '!'))) {
1897                 error(ERR_NONFATAL,
1898                       "`%s' expects environment variable names",
1899                       pp_directives[ct]);
1900                 goto fail;
1901             }
1902             p = tline->text;
1903             if (tline->type == TOK_PREPROC_ID)
1904                 p += 2;         /* Skip leading %! */
1905             if (*p == '\'' || *p == '\"' || *p == '`')
1906                 nasm_unquote_cstr(p, ct);
1907             if (getenv(p))
1908                 j = true;
1909             tline = tline->next;
1910         }
1911         break;
1912
1913     case PPC_IFIDN:
1914     case PPC_IFIDNI:
1915         tline = expand_smacro(tline);
1916         t = tt = tline;
1917         while (tok_isnt_(tt, ","))
1918             tt = tt->next;
1919         if (!tt) {
1920             error(ERR_NONFATAL,
1921                   "`%s' expects two comma-separated arguments",
1922                   pp_directives[ct]);
1923             goto fail;
1924         }
1925         tt = tt->next;
1926         j = true;               /* assume equality unless proved not */
1927         while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1928             if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1929                 error(ERR_NONFATAL, "`%s': more than one comma on line",
1930                       pp_directives[ct]);
1931                 goto fail;
1932             }
1933             if (t->type == TOK_WHITESPACE) {
1934                 t = t->next;
1935                 continue;
1936             }
1937             if (tt->type == TOK_WHITESPACE) {
1938                 tt = tt->next;
1939                 continue;
1940             }
1941             if (tt->type != t->type) {
1942                 j = false;      /* found mismatching tokens */
1943                 break;
1944             }
1945             /* When comparing strings, need to unquote them first */
1946             if (t->type == TOK_STRING) {
1947                 size_t l1 = nasm_unquote(t->text, NULL);
1948                 size_t l2 = nasm_unquote(tt->text, NULL);
1949
1950                 if (l1 != l2) {
1951                     j = false;
1952                     break;
1953                 }
1954                 if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
1955                     j = false;
1956                     break;
1957                 }
1958             } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
1959                 j = false;      /* found mismatching tokens */
1960                 break;
1961             }
1962
1963             t = t->next;
1964             tt = tt->next;
1965         }
1966         if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1967             j = false;          /* trailing gunk on one end or other */
1968         break;
1969
1970     case PPC_IFMACRO:
1971     {
1972         bool found = false;
1973         ExpDef searching, *ed;
1974
1975         skip_white_(tline);
1976         tline = expand_id(tline);
1977         if (!tok_type_(tline, TOK_ID)) {
1978             error(ERR_NONFATAL,
1979                   "`%s' expects a macro name", pp_directives[ct]);
1980             goto fail;
1981         }
1982         searching.name = nasm_strdup(tline->text);
1983         searching.casesense = true;
1984         searching.plus = false;
1985         searching.nolist = false;
1986         //searching.in_progress = 0;
1987         searching.max_depth = 0;
1988         //searching.rep_nest = NULL;
1989         searching.nparam_min = 0;
1990         searching.nparam_max = INT_MAX;
1991         tline = expand_smacro(tline->next);
1992         skip_white_(tline);
1993         if (!tline) {
1994         } else if (!tok_type_(tline, TOK_NUMBER)) {
1995             error(ERR_NONFATAL,
1996                   "`%s' expects a parameter count or nothing",
1997                   pp_directives[ct]);
1998         } else {
1999             searching.nparam_min = searching.nparam_max =
2000                 readnum(tline->text, &j);
2001             if (j)
2002                 error(ERR_NONFATAL,
2003                       "unable to parse parameter count `%s'",
2004                       tline->text);
2005         }
2006         if (tline && tok_is_(tline->next, "-")) {
2007             tline = tline->next->next;
2008             if (tok_is_(tline, "*"))
2009                 searching.nparam_max = INT_MAX;
2010             else if (!tok_type_(tline, TOK_NUMBER))
2011                 error(ERR_NONFATAL,
2012                       "`%s' expects a parameter count after `-'",
2013                       pp_directives[ct]);
2014             else {
2015                 searching.nparam_max = readnum(tline->text, &j);
2016                 if (j)
2017                     error(ERR_NONFATAL,
2018                           "unable to parse parameter count `%s'",
2019                           tline->text);
2020                 if (searching.nparam_min > searching.nparam_max)
2021                     error(ERR_NONFATAL,
2022                           "minimum parameter count exceeds maximum");
2023             }
2024         }
2025         if (tline && tok_is_(tline->next, "+")) {
2026             tline = tline->next;
2027             searching.plus = true;
2028         }
2029         ed = (ExpDef *) hash_findix(&expdefs, searching.name);
2030         while (ed != NULL) {
2031             if (!strcmp(ed->name, searching.name) &&
2032                 (ed->nparam_min <= searching.nparam_max
2033                  || searching.plus)
2034                 && (searching.nparam_min <= ed->nparam_max
2035                     || ed->plus)) {
2036                 found = true;
2037                 break;
2038             }
2039             ed = ed->next;
2040         }
2041         if (tline && tline->next)
2042             error(ERR_WARNING|ERR_PASS1,
2043                   "trailing garbage after %%ifmacro ignored");
2044         nasm_free(searching.name);
2045         j = found;
2046         break;
2047     }
2048
2049     case PPC_IFID:
2050         needtype = TOK_ID;
2051         goto iftype;
2052     case PPC_IFNUM:
2053         needtype = TOK_NUMBER;
2054         goto iftype;
2055     case PPC_IFSTR:
2056         needtype = TOK_STRING;
2057         goto iftype;
2058
2059 iftype:
2060         t = tline = expand_smacro(tline);
2061
2062         while (tok_type_(t, TOK_WHITESPACE) ||
2063                (needtype == TOK_NUMBER &&
2064                 tok_type_(t, TOK_OTHER) &&
2065                 (t->text[0] == '-' || t->text[0] == '+') &&
2066                 !t->text[1]))
2067             t = t->next;
2068
2069         j = tok_type_(t, needtype);
2070         break;
2071
2072     case PPC_IFTOKEN:
2073         t = tline = expand_smacro(tline);
2074         while (tok_type_(t, TOK_WHITESPACE))
2075             t = t->next;
2076
2077         j = false;
2078         if (t) {
2079             t = t->next;        /* Skip the actual token */
2080             while (tok_type_(t, TOK_WHITESPACE))
2081                 t = t->next;
2082             j = !t;             /* Should be nothing left */
2083         }
2084         break;
2085
2086     case PPC_IFEMPTY:
2087         t = tline = expand_smacro(tline);
2088         while (tok_type_(t, TOK_WHITESPACE))
2089             t = t->next;
2090
2091         j = !t;                 /* Should be empty */
2092         break;
2093
2094     case PPC_IF:
2095         t = tline = expand_smacro(tline);
2096         tptr = &t;
2097         tokval.t_type = TOKEN_INVALID;
2098         evalresult = evaluate(ppscan, tptr, &tokval,
2099                               NULL, pass | CRITICAL, error, NULL);
2100         if (!evalresult)
2101             return -1;
2102         if (tokval.t_type)
2103             error(ERR_WARNING|ERR_PASS1,
2104                   "trailing garbage after expression ignored");
2105         if (!is_simple(evalresult)) {
2106             error(ERR_NONFATAL,
2107                   "non-constant value given to `%s'", pp_directives[ct]);
2108             goto fail;
2109         }
2110         j = reloc_value(evalresult) != 0;
2111         break;
2112
2113     default:
2114         error(ERR_FATAL,
2115               "preprocessor directive `%s' not yet implemented",
2116               pp_directives[ct]);
2117         goto fail;
2118     }
2119
2120     free_tlist(origline);
2121     return j ^ PP_NEGATIVE(ct);
2122
2123 fail:
2124     free_tlist(origline);
2125     return -1;
2126 }
2127
2128 /*
2129  * Common code for defining an smacro
2130  */
2131 static bool define_smacro(Context *ctx, const char *mname, bool casesense,
2132                           int nparam, Token *expansion)
2133 {
2134     SMacro *smac, **smhead;
2135     struct hash_table *smtbl;
2136
2137     if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
2138         if (!smac) {
2139             error(ERR_WARNING|ERR_PASS1,
2140                   "single-line macro `%s' defined both with and"
2141                   " without parameters", mname);
2142             /*
2143              * Some instances of the old code considered this a failure,
2144              * some others didn't.  What is the right thing to do here?
2145              */
2146             free_tlist(expansion);
2147             return false;       /* Failure */
2148         } else {
2149             /*
2150              * We're redefining, so we have to take over an
2151              * existing SMacro structure. This means freeing
2152              * what was already in it.
2153              */
2154             nasm_free(smac->name);
2155             free_tlist(smac->expansion);
2156         }
2157     } else {
2158         smtbl  = ctx ? &ctx->localmac : &smacros;
2159         smhead = (SMacro **) hash_findi_add(smtbl, mname);
2160         smac = nasm_malloc(sizeof(SMacro));
2161         smac->next = *smhead;
2162         *smhead = smac;
2163     }
2164     smac->name = nasm_strdup(mname);
2165     smac->casesense = casesense;
2166     smac->nparam = nparam;
2167     smac->expansion = expansion;
2168     smac->in_progress = false;
2169     return true;                /* Success */
2170 }
2171
2172 /*
2173  * Undefine an smacro
2174  */
2175 static void undef_smacro(Context *ctx, const char *mname)
2176 {
2177     SMacro **smhead, *s, **sp;
2178     struct hash_table *smtbl;
2179
2180     smtbl = ctx ? &ctx->localmac : &smacros;
2181     smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
2182
2183     if (smhead) {
2184         /*
2185          * We now have a macro name... go hunt for it.
2186          */
2187         sp = smhead;
2188         while ((s = *sp) != NULL) {
2189             if (!mstrcmp(s->name, mname, s->casesense)) {
2190                 *sp = s->next;
2191                 nasm_free(s->name);
2192                 free_tlist(s->expansion);
2193                 nasm_free(s);
2194             } else {
2195                 sp = &s->next;
2196             }
2197         }
2198     }
2199 }
2200
2201 /*
2202  * Parse a mmacro specification.
2203  */
2204 static bool parse_mmacro_spec(Token *tline, ExpDef *def, const char *directive)
2205 {
2206     bool err;
2207
2208     tline = tline->next;
2209     skip_white_(tline);
2210     tline = expand_id(tline);
2211     if (!tok_type_(tline, TOK_ID)) {
2212         error(ERR_NONFATAL, "`%s' expects a macro name", directive);
2213         return false;
2214     }
2215
2216     def->name = nasm_strdup(tline->text);
2217     def->plus = false;
2218     def->nolist = false;
2219 //    def->in_progress = 0;
2220 //    def->rep_nest = NULL;
2221     def->nparam_min = 0;
2222     def->nparam_max = 0;
2223
2224     tline = expand_smacro(tline->next);
2225     skip_white_(tline);
2226     if (!tok_type_(tline, TOK_NUMBER)) {
2227         error(ERR_NONFATAL, "`%s' expects a parameter count", directive);
2228     } else {
2229         def->nparam_min = def->nparam_max =
2230             readnum(tline->text, &err);
2231         if (err)
2232             error(ERR_NONFATAL,
2233                   "unable to parse parameter count `%s'", tline->text);
2234     }
2235     if (tline && tok_is_(tline->next, "-")) {
2236         tline = tline->next->next;
2237         if (tok_is_(tline, "*")) {
2238             def->nparam_max = INT_MAX;
2239         } else if (!tok_type_(tline, TOK_NUMBER)) {
2240             error(ERR_NONFATAL,
2241                   "`%s' expects a parameter count after `-'", directive);
2242         } else {
2243             def->nparam_max = readnum(tline->text, &err);
2244             if (err) {
2245                 error(ERR_NONFATAL, "unable to parse parameter count `%s'",
2246                       tline->text);
2247             }
2248             if (def->nparam_min > def->nparam_max) {
2249                 error(ERR_NONFATAL, "minimum parameter count exceeds maximum");
2250             }
2251         }
2252     }
2253     if (tline && tok_is_(tline->next, "+")) {
2254         tline = tline->next;
2255         def->plus = true;
2256     }
2257     if (tline && tok_type_(tline->next, TOK_ID) &&
2258         !nasm_stricmp(tline->next->text, ".nolist")) {
2259         tline = tline->next;
2260         def->nolist = true;
2261     }
2262
2263     /*
2264      * Handle default parameters.
2265      */
2266     if (tline && tline->next) {
2267         def->dlist = tline->next;
2268         tline->next = NULL;
2269         count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
2270     } else {
2271         def->dlist = NULL;
2272         def->defaults = NULL;
2273     }
2274     def->line = NULL;
2275
2276     if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
2277         !def->plus)
2278         error(ERR_WARNING|ERR_PASS1|ERR_WARN_MDP,
2279               "too many default macro parameters");
2280
2281     return true;
2282 }
2283
2284
2285 /*
2286  * Decode a size directive
2287  */
2288 static int parse_size(const char *str) {
2289     static const char *size_names[] =
2290         { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2291     static const int sizes[] =
2292         { 0, 1, 4, 16, 8, 10, 2, 32 };
2293
2294     return sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1];
2295 }
2296
2297 /**
2298  * find and process preprocessor directive in passed line
2299  * Find out if a line contains a preprocessor directive, and deal
2300  * with it if so.
2301  *
2302  * If a directive _is_ found, it is the responsibility of this routine
2303  * (and not the caller) to free_tlist() the line.
2304  *
2305  * @param tline a pointer to the current tokeninzed line linked list
2306  * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2307  *
2308  */
2309 static int do_directive(Token * tline)
2310 {
2311     enum preproc_token i;
2312     int j;
2313     bool err;
2314     int nparam;
2315     bool nolist;
2316     bool casesense;
2317     int k, m;
2318     int offset;
2319     char *p, *pp;
2320     const char *mname;
2321     Include *inc;
2322     Context *ctx;
2323         Line *l;
2324     Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
2325     struct tokenval tokval;
2326     expr *evalresult;
2327     ExpDef *ed, *eed, **edhead;
2328         ExpInv *ei, *eei;
2329     int64_t count;
2330     size_t len;
2331     int severity;
2332
2333     origline = tline;
2334
2335     skip_white_(tline);
2336     if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
2337         (tline->text[1] == '%' || tline->text[1] == '$'
2338          || tline->text[1] == '!'))
2339         return NO_DIRECTIVE_FOUND;
2340
2341     i = pp_token_hash(tline->text);
2342
2343     switch (i) {
2344     case PP_INVALID:
2345                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2346         error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2347               tline->text);
2348         return NO_DIRECTIVE_FOUND;      /* didn't get it */
2349
2350     case PP_STACKSIZE:
2351                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2352         /* Directive to tell NASM what the default stack size is. The
2353          * default is for a 16-bit stack, and this can be overriden with
2354          * %stacksize large.
2355          */
2356         tline = tline->next;
2357         if (tline && tline->type == TOK_WHITESPACE)
2358             tline = tline->next;
2359         if (!tline || tline->type != TOK_ID) {
2360             error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
2361             free_tlist(origline);
2362             return DIRECTIVE_FOUND;
2363         }
2364         if (nasm_stricmp(tline->text, "flat") == 0) {
2365             /* All subsequent ARG directives are for a 32-bit stack */
2366             StackSize = 4;
2367             StackPointer = "ebp";
2368             ArgOffset = 8;
2369             LocalOffset = 0;
2370         } else if (nasm_stricmp(tline->text, "flat64") == 0) {
2371             /* All subsequent ARG directives are for a 64-bit stack */
2372             StackSize = 8;
2373             StackPointer = "rbp";
2374             ArgOffset = 16;
2375             LocalOffset = 0;
2376         } else if (nasm_stricmp(tline->text, "large") == 0) {
2377             /* All subsequent ARG directives are for a 16-bit stack,
2378              * far function call.
2379              */
2380             StackSize = 2;
2381             StackPointer = "bp";
2382             ArgOffset = 4;
2383             LocalOffset = 0;
2384         } else if (nasm_stricmp(tline->text, "small") == 0) {
2385             /* All subsequent ARG directives are for a 16-bit stack,
2386              * far function call. We don't support near functions.
2387              */
2388             StackSize = 2;
2389             StackPointer = "bp";
2390             ArgOffset = 6;
2391             LocalOffset = 0;
2392         } else {
2393             error(ERR_NONFATAL, "`%%stacksize' invalid size type");
2394             free_tlist(origline);
2395             return DIRECTIVE_FOUND;
2396         }
2397         free_tlist(origline);
2398         return DIRECTIVE_FOUND;
2399
2400     case PP_ARG:
2401                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2402         /* TASM like ARG directive to define arguments to functions, in
2403          * the following form:
2404          *
2405          *      ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2406          */
2407         offset = ArgOffset;
2408         do {
2409             char *arg, directive[256];
2410             int size = StackSize;
2411
2412             /* Find the argument name */
2413             tline = tline->next;
2414             if (tline && tline->type == TOK_WHITESPACE)
2415                 tline = tline->next;
2416             if (!tline || tline->type != TOK_ID) {
2417                 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
2418                 free_tlist(origline);
2419                 return DIRECTIVE_FOUND;
2420             }
2421             arg = tline->text;
2422
2423             /* Find the argument size type */
2424             tline = tline->next;
2425             if (!tline || tline->type != TOK_OTHER
2426                 || tline->text[0] != ':') {
2427                 error(ERR_NONFATAL,
2428                       "Syntax error processing `%%arg' directive");
2429                 free_tlist(origline);
2430                 return DIRECTIVE_FOUND;
2431             }
2432             tline = tline->next;
2433             if (!tline || tline->type != TOK_ID) {
2434                 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
2435                 free_tlist(origline);
2436                 return DIRECTIVE_FOUND;
2437             }
2438
2439             /* Allow macro expansion of type parameter */
2440             tt = tokenize(tline->text);
2441             tt = expand_smacro(tt);
2442             size = parse_size(tt->text);
2443             if (!size) {
2444                 error(ERR_NONFATAL,
2445                       "Invalid size type for `%%arg' missing directive");
2446                 free_tlist(tt);
2447                 free_tlist(origline);
2448                 return DIRECTIVE_FOUND;
2449             }
2450             free_tlist(tt);
2451
2452             /* Round up to even stack slots */
2453             size = ALIGN(size, StackSize);
2454
2455             /* Now define the macro for the argument */
2456             snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
2457                      arg, StackPointer, offset);
2458             do_directive(tokenize(directive));
2459             offset += size;
2460
2461             /* Move to the next argument in the list */
2462             tline = tline->next;
2463             if (tline && tline->type == TOK_WHITESPACE)
2464                 tline = tline->next;
2465         } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2466         ArgOffset = offset;
2467         free_tlist(origline);
2468         return DIRECTIVE_FOUND;
2469
2470     case PP_LOCAL:
2471                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2472         /* TASM like LOCAL directive to define local variables for a
2473          * function, in the following form:
2474          *
2475          *      LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2476          *
2477          * The '= LocalSize' at the end is ignored by NASM, but is
2478          * required by TASM to define the local parameter size (and used
2479          * by the TASM macro package).
2480          */
2481         offset = LocalOffset;
2482         do {
2483             char *local, directive[256];
2484             int size = StackSize;
2485
2486             /* Find the argument name */
2487             tline = tline->next;
2488             if (tline && tline->type == TOK_WHITESPACE)
2489                 tline = tline->next;
2490             if (!tline || tline->type != TOK_ID) {
2491                 error(ERR_NONFATAL,
2492                       "`%%local' missing argument parameter");
2493                 free_tlist(origline);
2494                 return DIRECTIVE_FOUND;
2495             }
2496             local = tline->text;
2497
2498             /* Find the argument size type */
2499             tline = tline->next;
2500             if (!tline || tline->type != TOK_OTHER
2501                 || tline->text[0] != ':') {
2502                 error(ERR_NONFATAL,
2503                       "Syntax error processing `%%local' directive");
2504                 free_tlist(origline);
2505                 return DIRECTIVE_FOUND;
2506             }
2507             tline = tline->next;
2508             if (!tline || tline->type != TOK_ID) {
2509                 error(ERR_NONFATAL,
2510                       "`%%local' missing size type parameter");
2511                 free_tlist(origline);
2512                 return DIRECTIVE_FOUND;
2513             }
2514
2515             /* Allow macro expansion of type parameter */
2516             tt = tokenize(tline->text);
2517             tt = expand_smacro(tt);
2518             size = parse_size(tt->text);
2519             if (!size) {
2520                 error(ERR_NONFATAL,
2521                       "Invalid size type for `%%local' missing directive");
2522                 free_tlist(tt);
2523                 free_tlist(origline);
2524                 return DIRECTIVE_FOUND;
2525             }
2526             free_tlist(tt);
2527
2528             /* Round up to even stack slots */
2529             size = ALIGN(size, StackSize);
2530
2531             offset += size;     /* Negative offset, increment before */
2532
2533             /* Now define the macro for the argument */
2534             snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
2535                      local, StackPointer, offset);
2536             do_directive(tokenize(directive));
2537
2538             /* Now define the assign to setup the enter_c macro correctly */
2539             snprintf(directive, sizeof(directive),
2540                      "%%assign %%$localsize %%$localsize+%d", size);
2541             do_directive(tokenize(directive));
2542
2543             /* Move to the next argument in the list */
2544             tline = tline->next;
2545             if (tline && tline->type == TOK_WHITESPACE)
2546                 tline = tline->next;
2547         } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2548         LocalOffset = offset;
2549         free_tlist(origline);
2550         return DIRECTIVE_FOUND;
2551
2552     case PP_CLEAR:
2553                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2554         if (tline->next)
2555             error(ERR_WARNING|ERR_PASS1,
2556                   "trailing garbage after `%%clear' ignored");
2557         free_macros();
2558         init_macros();
2559         free_tlist(origline);
2560         return DIRECTIVE_FOUND;
2561
2562     case PP_DEPEND:
2563                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2564         t = tline->next = expand_smacro(tline->next);
2565         skip_white_(t);
2566         if (!t || (t->type != TOK_STRING &&
2567                    t->type != TOK_INTERNAL_STRING)) {
2568             error(ERR_NONFATAL, "`%%depend' expects a file name");
2569             free_tlist(origline);
2570             return DIRECTIVE_FOUND;     /* but we did _something_ */
2571         }
2572         if (t->next)
2573             error(ERR_WARNING|ERR_PASS1,
2574                   "trailing garbage after `%%depend' ignored");
2575         p = t->text;
2576         if (t->type != TOK_INTERNAL_STRING)
2577             nasm_unquote_cstr(p, i);
2578         if (dephead && !in_list(*dephead, p)) {
2579             StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next);
2580             sl->next = NULL;
2581             strcpy(sl->str, p);
2582             *deptail = sl;
2583             deptail = &sl->next;
2584         }
2585         free_tlist(origline);
2586         return DIRECTIVE_FOUND;
2587
2588     case PP_INCLUDE:
2589                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2590         t = tline->next = expand_smacro(tline->next);
2591         skip_white_(t);
2592
2593         if (!t || (t->type != TOK_STRING &&
2594                    t->type != TOK_INTERNAL_STRING)) {
2595             error(ERR_NONFATAL, "`%%include' expects a file name");
2596             free_tlist(origline);
2597             return DIRECTIVE_FOUND;     /* but we did _something_ */
2598         }
2599         if (t->next)
2600             error(ERR_WARNING|ERR_PASS1,
2601                   "trailing garbage after `%%include' ignored");
2602         p = t->text;
2603         if (t->type != TOK_INTERNAL_STRING)
2604             nasm_unquote_cstr(p, i);
2605         inc = nasm_malloc(sizeof(Include));
2606         inc->next = istk;
2607         inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
2608         if (!inc->fp) {
2609             /* -MG given but file not found */
2610             nasm_free(inc);
2611         } else {
2612             inc->fname = src_set_fname(nasm_strdup(p));
2613             inc->lineno = src_set_linnum(0);
2614             inc->lineinc = 1;
2615             inc->expansion = NULL;
2616             istk = inc;
2617             list->uplevel(LIST_INCLUDE);
2618         }
2619         free_tlist(origline);
2620         return DIRECTIVE_FOUND;
2621
2622     case PP_USE:
2623                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2624     {
2625         static macros_t *use_pkg;
2626         const char *pkg_macro = NULL;
2627
2628         tline = tline->next;
2629         skip_white_(tline);
2630         tline = expand_id(tline);
2631
2632         if (!tline || (tline->type != TOK_STRING &&
2633                        tline->type != TOK_INTERNAL_STRING &&
2634                        tline->type != TOK_ID)) {
2635             error(ERR_NONFATAL, "`%%use' expects a package name");
2636             free_tlist(origline);
2637             return DIRECTIVE_FOUND;     /* but we did _something_ */
2638         }
2639         if (tline->next)
2640             error(ERR_WARNING|ERR_PASS1,
2641                   "trailing garbage after `%%use' ignored");
2642         if (tline->type == TOK_STRING)
2643             nasm_unquote_cstr(tline->text, i);
2644         use_pkg = nasm_stdmac_find_package(tline->text);
2645         if (!use_pkg)
2646             error(ERR_NONFATAL, "unknown `%%use' package: %s", tline->text);
2647         else
2648             pkg_macro = (char *)use_pkg + 1; /* The first string will be <%define>__USE_*__ */
2649         if (use_pkg && ! smacro_defined(NULL, pkg_macro, 0, NULL, true)) {
2650             /* Not already included, go ahead and include it */
2651             stdmacpos = use_pkg;
2652         }
2653         free_tlist(origline);
2654         return DIRECTIVE_FOUND;
2655     }
2656     case PP_PUSH:
2657     case PP_REPL:
2658     case PP_POP:
2659                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2660         tline = tline->next;
2661         skip_white_(tline);
2662         tline = expand_id(tline);
2663         if (tline) {
2664             if (!tok_type_(tline, TOK_ID)) {
2665                 error(ERR_NONFATAL, "`%s' expects a context identifier",
2666                       pp_directives[i]);
2667                 free_tlist(origline);
2668                 return DIRECTIVE_FOUND;     /* but we did _something_ */
2669             }
2670             if (tline->next)
2671                 error(ERR_WARNING|ERR_PASS1,
2672                       "trailing garbage after `%s' ignored",
2673                       pp_directives[i]);
2674             p = nasm_strdup(tline->text);
2675         } else {
2676             p = NULL; /* Anonymous */
2677         }
2678
2679         if (i == PP_PUSH) {
2680             ctx = nasm_malloc(sizeof(Context));
2681             ctx->next = cstk;
2682             hash_init(&ctx->localmac, HASH_SMALL);
2683             ctx->name = p;
2684             ctx->number = unique++;
2685             cstk = ctx;
2686         } else {
2687             /* %pop or %repl */
2688             if (!cstk) {
2689                 error(ERR_NONFATAL, "`%s': context stack is empty",
2690                       pp_directives[i]);
2691             } else if (i == PP_POP) {
2692                 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
2693                     error(ERR_NONFATAL, "`%%pop' in wrong context: %s, "
2694                           "expected %s",
2695                           cstk->name ? cstk->name : "anonymous", p);
2696                 else
2697                     ctx_pop();
2698             } else {
2699                 /* i == PP_REPL */
2700                 nasm_free(cstk->name);
2701                 cstk->name = p;
2702                 p = NULL;
2703             }
2704             nasm_free(p);
2705         }
2706         free_tlist(origline);
2707         return DIRECTIVE_FOUND;
2708     case PP_FATAL:
2709         severity = ERR_FATAL;
2710         goto issue_error;
2711     case PP_ERROR:
2712         severity = ERR_NONFATAL;
2713         goto issue_error;
2714     case PP_WARNING:
2715         severity = ERR_WARNING|ERR_WARN_USER;
2716         goto issue_error;
2717
2718 issue_error:
2719                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2720     {
2721         /* Only error out if this is the final pass */
2722         if (pass != 2 && i != PP_FATAL)
2723             return DIRECTIVE_FOUND;
2724
2725         tline->next = expand_smacro(tline->next);
2726         tline = tline->next;
2727         skip_white_(tline);
2728         t = tline ? tline->next : NULL;
2729         skip_white_(t);
2730         if (tok_type_(tline, TOK_STRING) && !t) {
2731             /* The line contains only a quoted string */
2732             p = tline->text;
2733             nasm_unquote(p, NULL); /* Ignore NUL character truncation */
2734             error(severity, "%s",  p);
2735         } else {
2736             /* Not a quoted string, or more than a quoted string */
2737             p = detoken(tline, false);
2738             error(severity, "%s",  p);
2739             nasm_free(p);
2740         }
2741         free_tlist(origline);
2742         return DIRECTIVE_FOUND;
2743     }
2744
2745     CASE_PP_IF:
2746                 if (defining != NULL) {
2747                         if (defining->type == EXP_IF) {
2748                                 defining->def_depth ++; 
2749                         }
2750                         return NO_DIRECTIVE_FOUND;
2751                 }
2752                 if ((istk->expansion != NULL) &&
2753                         (istk->expansion->emitting == false)) {
2754                         j = COND_NEVER;
2755                 } else {
2756                         j = if_condition(tline->next, i);
2757                         tline->next = NULL; /* it got freed */
2758                         j = (((j < 0) ? COND_NEVER : j) ? COND_IF_TRUE : COND_IF_FALSE);
2759                 }
2760                 ed = new_ExpDef(EXP_IF);
2761                 ed->state = j;
2762                 ed->nolist = NULL;
2763                 ed->def_depth = 0;
2764                 ed->cur_depth = 0;
2765                 ed->max_depth = 0;
2766                 ed->ignoring = ((ed->state == COND_IF_TRUE) ? false : true);
2767                 ed->prev = defining;
2768                 defining = ed;
2769         free_tlist(origline);
2770         return DIRECTIVE_FOUND;
2771
2772     CASE_PP_ELIF:
2773                 if (defining != NULL) {
2774                         if ((defining->type != EXP_IF) || (defining->def_depth > 0)) {
2775                                 return NO_DIRECTIVE_FOUND;      
2776                         }
2777                 }
2778                 if ((defining == NULL) ||       (defining->type != EXP_IF)) {
2779                         error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
2780                 }
2781         switch (defining->state) {
2782                 case COND_IF_TRUE:
2783                         defining->state = COND_DONE;
2784                         defining->ignoring = true;
2785                         break;
2786
2787                 case COND_DONE:
2788                 case COND_NEVER:
2789                         defining->ignoring = true;
2790                         break;
2791
2792         case COND_ELSE_TRUE:
2793         case COND_ELSE_FALSE:
2794             error_precond(ERR_WARNING|ERR_PASS1,
2795                           "`%%elif' after `%%else' ignored");
2796                         defining->state = COND_NEVER;
2797                         defining->ignoring = true;
2798             break;
2799
2800         case COND_IF_FALSE:
2801             /*
2802              * IMPORTANT: In the case of %if, we will already have
2803              * called expand_mmac_params(); however, if we're
2804              * processing an %elif we must have been in a
2805              * non-emitting mode, which would have inhibited
2806              * the normal invocation of expand_mmac_params().
2807              * Therefore, we have to do it explicitly here.
2808              */
2809             j = if_condition(expand_mmac_params(tline->next), i);
2810             tline->next = NULL; /* it got freed */
2811                         defining->state =
2812                 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2813                         defining->ignoring = ((defining->state == COND_IF_TRUE) ? false : true);
2814             break;
2815         }
2816         free_tlist(origline);
2817         return DIRECTIVE_FOUND;
2818
2819     case PP_ELSE:
2820                 if (defining != NULL) {
2821                         if ((defining->type != EXP_IF) || (defining->def_depth > 0)) {
2822                                 return NO_DIRECTIVE_FOUND;      
2823                         }
2824                 }
2825         if (tline->next)
2826             error_precond(ERR_WARNING|ERR_PASS1,
2827                           "trailing garbage after `%%else' ignored");
2828                 if ((defining == NULL) || (defining->type != EXP_IF)) {
2829                         error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
2830                 }
2831         switch (defining->state) {
2832                 case COND_IF_TRUE:
2833                 case COND_DONE:
2834                         defining->state = COND_ELSE_FALSE;
2835                         defining->ignoring = true;
2836                         break;
2837
2838                 case COND_NEVER:
2839                         defining->ignoring = true;
2840                         break;
2841
2842                 case COND_IF_FALSE:
2843                         defining->state = COND_ELSE_TRUE;
2844                         defining->ignoring = false;
2845                         break;
2846
2847         case COND_ELSE_TRUE:
2848         case COND_ELSE_FALSE:
2849             error_precond(ERR_WARNING|ERR_PASS1,
2850                           "`%%else' after `%%else' ignored.");
2851                         defining->state = COND_NEVER;
2852                         defining->ignoring = true;
2853             break;
2854         }
2855         free_tlist(origline);
2856         return DIRECTIVE_FOUND;
2857
2858     case PP_ENDIF:
2859                 if (defining != NULL) {
2860                         if (defining->type == EXP_IF) {
2861                                 if (defining->def_depth > 0) {
2862                                         defining->def_depth --;
2863                                         return NO_DIRECTIVE_FOUND;
2864                                 }
2865                         } else {
2866                                 return NO_DIRECTIVE_FOUND;
2867                         }
2868                 }
2869         if (tline->next)
2870             error_precond(ERR_WARNING|ERR_PASS1,
2871                           "trailing garbage after `%%endif' ignored");
2872                 if ((defining == NULL) || (defining->type != EXP_IF)) {
2873                         error(ERR_NONFATAL, "`%%endif': no matching `%%if'");
2874                         return DIRECTIVE_FOUND;
2875                 }
2876                 ed = defining;
2877                 defining = ed->prev;
2878                 ed->prev = expansions;
2879                 expansions = ed;
2880                 ei = new_ExpInv(EXP_IF, ed);
2881                 ei->current = ed->line;
2882                 ei->emitting = true;
2883                 ei->prev = istk->expansion;
2884                 istk->expansion = ei;
2885         free_tlist(origline);
2886         return DIRECTIVE_FOUND;
2887
2888     case PP_RMACRO:
2889     case PP_IRMACRO:
2890     case PP_MACRO:
2891     case PP_IMACRO:
2892                 if (defining != NULL) {
2893                         if (defining->type == EXP_MMACRO) {
2894                                 defining->def_depth ++;
2895                         }
2896                         return NO_DIRECTIVE_FOUND;
2897                 }
2898                 ed = new_ExpDef(EXP_MMACRO);    
2899                 ed->max_depth =
2900             (i == PP_RMACRO) || (i == PP_IRMACRO) ? DEADMAN_LIMIT : 0;
2901                 ed->casesense = (i == PP_MACRO) || (i == PP_RMACRO);
2902         if (!parse_mmacro_spec(tline, ed, pp_directives[i])) {
2903             nasm_free(ed);
2904             ed = NULL;
2905             return DIRECTIVE_FOUND;
2906         }
2907                 ed->def_depth = 0;
2908                 ed->cur_depth = 0;
2909                 ed->max_depth = (ed->max_depth + 1);
2910                 ed->ignoring = false;
2911                 ed->prev = defining;
2912                 defining = ed;
2913
2914                 eed = (ExpDef *) hash_findix(&expdefs, ed->name);
2915                 while (eed) {
2916                         if (!strcmp(eed->name, ed->name) &&
2917                                 (eed->nparam_min <= ed->nparam_max
2918                                  || ed->plus)
2919                                 && (ed->nparam_min <= eed->nparam_max
2920                                         || eed->plus)) {
2921                                         error(ERR_WARNING|ERR_PASS1,
2922                                                   "redefining multi-line macro `%s'", ed->name);
2923                                         return DIRECTIVE_FOUND;
2924                                 }
2925                         eed = eed->next;
2926                 }
2927         free_tlist(origline);
2928         return DIRECTIVE_FOUND;
2929
2930     case PP_ENDM:
2931     case PP_ENDMACRO:
2932                 if (defining != NULL) {
2933                         if (defining->type == EXP_MMACRO) {
2934                                 if (defining->def_depth > 0) {
2935                                         defining->def_depth --;
2936                                         return NO_DIRECTIVE_FOUND;
2937                                 }
2938                         } else {
2939                                 return NO_DIRECTIVE_FOUND;
2940                         }
2941                 }
2942                 if (!(defining) || (defining->type != EXP_MMACRO)) {
2943                         error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2944                         return DIRECTIVE_FOUND;
2945                 }
2946                 edhead = (ExpDef **) hash_findi_add(&expdefs, defining->name);
2947                 defining->next = *edhead;
2948                 *edhead = defining;
2949                 ed = defining;
2950                 defining = ed->prev;
2951                 ed->prev = expansions;
2952                 expansions = ed;
2953                 ed = NULL;
2954         free_tlist(origline);
2955         return DIRECTIVE_FOUND;
2956
2957     case PP_EXITMACRO:
2958                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2959                 /*
2960                  * We must search along istk->expansion until we hit a
2961                  * macro invocation. Then we disable the emitting state(s)
2962                  * between exitmacro and endmacro.
2963                  */
2964                 for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
2965                         if(ei->type == EXP_MMACRO) {
2966                                 break;
2967                         }
2968                 }
2969                         
2970                 if (ei != NULL) {
2971                         /*
2972                          * Set all invocations leading back to the macro
2973                          * invocation to a non-emitting state.
2974                          */
2975                         for (eei = istk->expansion; eei != ei; eei = eei->prev) {
2976                                 eei->emitting = false;
2977                         }
2978                         eei->emitting = false;
2979                 } else {
2980                         error(ERR_NONFATAL, "`%%exitmacro' not within `%%macro' block");
2981                 }
2982         free_tlist(origline);
2983         return DIRECTIVE_FOUND;
2984
2985     case PP_UNMACRO:
2986     case PP_UNIMACRO:
2987                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2988     {
2989         ExpDef **ed_p;
2990         ExpDef spec;
2991
2992         spec.casesense = (i == PP_UNMACRO);
2993         if (!parse_mmacro_spec(tline, &spec, pp_directives[i])) {
2994             return DIRECTIVE_FOUND;
2995         }
2996         ed_p = (ExpDef **) hash_findi(&expdefs, spec.name, NULL);
2997         while (ed_p && *ed_p) {
2998             ed = *ed_p;
2999             if (ed->casesense == spec.casesense &&
3000                 !mstrcmp(ed->name, spec.name, spec.casesense) &&
3001                 ed->nparam_min == spec.nparam_min &&
3002                 ed->nparam_max == spec.nparam_max &&
3003                 ed->plus == spec.plus) {
3004                 *ed_p = ed->next;
3005                 free_expdef(ed);
3006             } else {
3007                 ed_p = &ed->next;
3008             }
3009         }
3010         free_tlist(origline);
3011         free_tlist(spec.dlist);
3012         return DIRECTIVE_FOUND;
3013     }
3014
3015     case PP_ROTATE:
3016                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3017         if (tline->next && tline->next->type == TOK_WHITESPACE)
3018             tline = tline->next;
3019         if (!tline->next) {
3020             free_tlist(origline);
3021             error(ERR_NONFATAL, "`%%rotate' missing rotate count");
3022             return DIRECTIVE_FOUND;
3023         }
3024         t = expand_smacro(tline->next);
3025         tline->next = NULL;
3026         free_tlist(origline);
3027         tline = t;
3028         tptr = &t;
3029         tokval.t_type = TOKEN_INVALID;
3030         evalresult =
3031             evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3032         free_tlist(tline);
3033         if (!evalresult)
3034             return DIRECTIVE_FOUND;
3035         if (tokval.t_type)
3036             error(ERR_WARNING|ERR_PASS1,
3037                   "trailing garbage after expression ignored");
3038         if (!is_simple(evalresult)) {
3039             error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
3040             return DIRECTIVE_FOUND;
3041         }
3042                 for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
3043                         if (ei->type == EXP_MMACRO) {
3044                                 break;
3045                         }
3046                 }
3047                 if (ei == NULL) {
3048                         error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
3049                 } else if (ei->nparam == 0) {
3050                         error(ERR_NONFATAL,
3051                                   "`%%rotate' invoked within macro without parameters");
3052                 } else {
3053                         int rotate = ei->rotate + reloc_value(evalresult);
3054                         
3055                         rotate %= (int)ei->nparam;
3056                         if (rotate < 0)
3057                                 rotate += ei->nparam;
3058                         ei->rotate = rotate;
3059                 }
3060         return DIRECTIVE_FOUND;
3061
3062     case PP_REP:
3063                 if (defining != NULL) {
3064                         if (defining->type == EXP_REP) {
3065                                 defining->def_depth ++;
3066                         }
3067                         return NO_DIRECTIVE_FOUND;
3068                 }
3069         nolist = false;
3070         do {
3071             tline = tline->next;
3072         } while (tok_type_(tline, TOK_WHITESPACE));
3073
3074         if (tok_type_(tline, TOK_ID) &&
3075             nasm_stricmp(tline->text, ".nolist") == 0) {
3076             nolist = true;
3077             do {
3078                 tline = tline->next;
3079             } while (tok_type_(tline, TOK_WHITESPACE));
3080         }
3081
3082         if (tline) {
3083             t = expand_smacro(tline);
3084             tptr = &t;
3085             tokval.t_type = TOKEN_INVALID;
3086             evalresult =
3087                 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3088             if (!evalresult) {
3089                 free_tlist(origline);
3090                 return DIRECTIVE_FOUND;
3091             }
3092             if (tokval.t_type)
3093                 error(ERR_WARNING|ERR_PASS1,
3094                       "trailing garbage after expression ignored");
3095             if (!is_simple(evalresult)) {
3096                 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
3097                 return DIRECTIVE_FOUND;
3098             }
3099             count = reloc_value(evalresult);
3100             if (count >= REP_LIMIT) {
3101                 error(ERR_NONFATAL, "`%%rep' value exceeds limit");
3102                 count = 0;
3103             } else
3104                 count++;
3105         } else {
3106             error(ERR_NONFATAL, "`%%rep' expects a repeat count");
3107             count = 0;
3108         }
3109         free_tlist(origline);
3110                 ed = new_ExpDef(EXP_REP);
3111                 ed->nolist = nolist;
3112                 ed->def_depth = 0;
3113                 ed->cur_depth = 1;
3114                 ed->max_depth = (count - 1);
3115                 ed->ignoring = false;
3116                 ed->prev = defining;
3117                 defining = ed;
3118         return DIRECTIVE_FOUND;
3119
3120     case PP_ENDREP:
3121                 if (defining != NULL) {
3122                         if (defining->type == EXP_REP) {
3123                                 if (defining->def_depth > 0) {
3124                                         defining->def_depth --;
3125                                         return NO_DIRECTIVE_FOUND;
3126                                 }
3127                         } else {
3128                                 return NO_DIRECTIVE_FOUND;
3129                         }
3130                 }
3131         if ((defining == NULL) || (defining->type != EXP_REP)) {
3132             error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
3133             return DIRECTIVE_FOUND;
3134         }
3135
3136         /*
3137          * Now we have a "macro" defined - although it has no name
3138          * and we won't be entering it in the hash tables - we must
3139          * push a macro-end marker for it on to istk->expansion.
3140          * After that, it will take care of propagating itself (a
3141          * macro-end marker line for a macro which is really a %rep
3142          * block will cause the macro to be re-expanded, complete
3143          * with another macro-end marker to ensure the process
3144          * continues) until the whole expansion is forcibly removed
3145          * from istk->expansion by a %exitrep.
3146          */
3147                 ed = defining;
3148                 defining = ed->prev;
3149                 ed->prev = expansions;
3150                 expansions = ed;
3151                 ei = new_ExpInv(EXP_REP, ed);
3152                 ei->current = ed->line;
3153                 ei->emitting = ((ed->max_depth > 0) ? true : false);
3154                 list->uplevel(ed->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
3155                 ei->prev = istk->expansion;
3156                 istk->expansion = ei;
3157         free_tlist(origline);
3158         return DIRECTIVE_FOUND;
3159
3160     case PP_EXITREP:
3161                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3162                 /*
3163                  * We must search along istk->expansion until we hit a
3164                  * rep invocation. Then we disable the emitting state(s)
3165                  * between exitrep and endrep.
3166                  */
3167                 for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
3168                         if (ei->type == EXP_REP) {
3169                                 break;
3170                         }
3171                 }
3172                         
3173                 if (ei != NULL) {
3174                         /*
3175                          * Set all invocations leading back to the rep
3176                          * invocation to a non-emitting state.
3177                          */
3178                         for (eei = istk->expansion; eei != ei; eei = eei->prev) {
3179                                 eei->emitting = false;
3180                         }
3181                         eei->emitting = false;
3182                         eei->current = NULL;
3183                         eei->def->cur_depth = eei->def->max_depth;
3184                 } else {
3185                         error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
3186                 }
3187         free_tlist(origline);
3188         return DIRECTIVE_FOUND;
3189
3190     case PP_XDEFINE:
3191     case PP_IXDEFINE:
3192     case PP_DEFINE:
3193     case PP_IDEFINE:
3194                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3195         casesense = (i == PP_DEFINE || i == PP_XDEFINE);
3196
3197         tline = tline->next;
3198         skip_white_(tline);
3199         tline = expand_id(tline);
3200         if (!tline || (tline->type != TOK_ID &&
3201                        (tline->type != TOK_PREPROC_ID ||
3202                         tline->text[1] != '$'))) {
3203             error(ERR_NONFATAL, "`%s' expects a macro identifier",
3204                   pp_directives[i]);
3205             free_tlist(origline);
3206             return DIRECTIVE_FOUND;
3207         }
3208
3209         ctx = get_ctx(tline->text, &mname, false);
3210         last = tline;
3211         param_start = tline = tline->next;
3212         nparam = 0;
3213
3214         /* Expand the macro definition now for %xdefine and %ixdefine */
3215         if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
3216             tline = expand_smacro(tline);
3217
3218         if (tok_is_(tline, "(")) {
3219             /*
3220              * This macro has parameters.
3221              */
3222
3223             tline = tline->next;
3224             while (1) {
3225                 skip_white_(tline);
3226                 if (!tline) {
3227                     error(ERR_NONFATAL, "parameter identifier expected");
3228                     free_tlist(origline);
3229                     return DIRECTIVE_FOUND;
3230                 }
3231                 if (tline->type != TOK_ID) {
3232                     error(ERR_NONFATAL,
3233                           "`%s': parameter identifier expected",
3234                           tline->text);
3235                     free_tlist(origline);
3236                     return DIRECTIVE_FOUND;
3237                 }
3238                 tline->type = TOK_SMAC_PARAM + nparam++;
3239                 tline = tline->next;
3240                 skip_white_(tline);
3241                 if (tok_is_(tline, ",")) {
3242                     tline = tline->next;
3243                 } else {
3244                     if (!tok_is_(tline, ")")) {
3245                         error(ERR_NONFATAL,
3246                               "`)' expected to terminate macro template");
3247                         free_tlist(origline);
3248                         return DIRECTIVE_FOUND;
3249                     }
3250                     break;
3251                 }
3252             }
3253             last = tline;
3254             tline = tline->next;
3255         }
3256         if (tok_type_(tline, TOK_WHITESPACE))
3257             last = tline, tline = tline->next;
3258         macro_start = NULL;
3259         last->next = NULL;
3260         t = tline;
3261         while (t) {
3262             if (t->type == TOK_ID) {
3263                 list_for_each(tt, param_start)
3264                     if (tt->type >= TOK_SMAC_PARAM &&
3265                         !strcmp(tt->text, t->text))
3266                         t->type = tt->type;
3267             }
3268             tt = t->next;
3269             t->next = macro_start;
3270             macro_start = t;
3271             t = tt;
3272         }
3273         /*
3274          * Good. We now have a macro name, a parameter count, and a
3275          * token list (in reverse order) for an expansion. We ought
3276          * to be OK just to create an SMacro, store it, and let
3277          * free_tlist have the rest of the line (which we have
3278          * carefully re-terminated after chopping off the expansion
3279          * from the end).
3280          */
3281         define_smacro(ctx, mname, casesense, nparam, macro_start);
3282         free_tlist(origline);
3283         return DIRECTIVE_FOUND;
3284
3285     case PP_UNDEF:
3286                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3287         tline = tline->next;
3288         skip_white_(tline);
3289         tline = expand_id(tline);
3290         if (!tline || (tline->type != TOK_ID &&
3291                        (tline->type != TOK_PREPROC_ID ||
3292                         tline->text[1] != '$'))) {
3293             error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
3294             free_tlist(origline);
3295             return DIRECTIVE_FOUND;
3296         }
3297         if (tline->next) {
3298             error(ERR_WARNING|ERR_PASS1,
3299                   "trailing garbage after macro name ignored");
3300         }
3301
3302         /* Find the context that symbol belongs to */
3303         ctx = get_ctx(tline->text, &mname, false);
3304         undef_smacro(ctx, mname);
3305         free_tlist(origline);
3306         return DIRECTIVE_FOUND;
3307
3308     case PP_DEFSTR:
3309     case PP_IDEFSTR:
3310                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3311         casesense = (i == PP_DEFSTR);
3312
3313         tline = tline->next;
3314         skip_white_(tline);
3315         tline = expand_id(tline);
3316         if (!tline || (tline->type != TOK_ID &&
3317                        (tline->type != TOK_PREPROC_ID ||
3318                         tline->text[1] != '$'))) {
3319             error(ERR_NONFATAL, "`%s' expects a macro identifier",
3320                   pp_directives[i]);
3321             free_tlist(origline);
3322             return DIRECTIVE_FOUND;
3323         }
3324
3325         ctx = get_ctx(tline->text, &mname, false);
3326         last = tline;
3327         tline = expand_smacro(tline->next);
3328         last->next = NULL;
3329
3330         while (tok_type_(tline, TOK_WHITESPACE))
3331             tline = delete_Token(tline);
3332
3333         p = detoken(tline, false);
3334         macro_start = nasm_malloc(sizeof(*macro_start));
3335         macro_start->next = NULL;
3336         macro_start->text = nasm_quote(p, strlen(p));
3337         macro_start->type = TOK_STRING;
3338         macro_start->a.mac = NULL;
3339         nasm_free(p);
3340
3341         /*
3342          * We now have a macro name, an implicit parameter count of
3343          * zero, and a string token to use as an expansion. Create
3344          * and store an SMacro.
3345          */
3346         define_smacro(ctx, mname, casesense, 0, macro_start);
3347         free_tlist(origline);
3348         return DIRECTIVE_FOUND;
3349
3350     case PP_DEFTOK:
3351     case PP_IDEFTOK:
3352                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3353         casesense = (i == PP_DEFTOK);
3354
3355         tline = tline->next;
3356         skip_white_(tline);
3357         tline = expand_id(tline);
3358         if (!tline || (tline->type != TOK_ID &&
3359                        (tline->type != TOK_PREPROC_ID ||
3360                         tline->text[1] != '$'))) {
3361             error(ERR_NONFATAL,
3362                   "`%s' expects a macro identifier as first parameter",
3363                   pp_directives[i]);
3364             free_tlist(origline);
3365             return DIRECTIVE_FOUND;
3366         }
3367         ctx = get_ctx(tline->text, &mname, false);
3368         last = tline;
3369         tline = expand_smacro(tline->next);
3370         last->next = NULL;
3371
3372         t = tline;
3373         while (tok_type_(t, TOK_WHITESPACE))
3374             t = t->next;
3375         /* t should now point to the string */
3376         if (!tok_type_(t, TOK_STRING)) {
3377             error(ERR_NONFATAL,
3378                   "`%s` requires string as second parameter",
3379                   pp_directives[i]);
3380             free_tlist(tline);
3381             free_tlist(origline);
3382             return DIRECTIVE_FOUND;
3383         }
3384
3385         /*
3386          * Convert the string to a token stream.  Note that smacros
3387          * are stored with the token stream reversed, so we have to
3388          * reverse the output of tokenize().
3389          */
3390         nasm_unquote_cstr(t->text, i);
3391         macro_start = reverse_tokens(tokenize(t->text));
3392
3393         /*
3394          * We now have a macro name, an implicit parameter count of
3395          * zero, and a numeric token to use as an expansion. Create
3396          * and store an SMacro.
3397          */
3398         define_smacro(ctx, mname, casesense, 0, macro_start);
3399         free_tlist(tline);
3400         free_tlist(origline);
3401         return DIRECTIVE_FOUND;
3402
3403     case PP_PATHSEARCH:
3404                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3405     {
3406         FILE *fp;
3407         StrList *xsl = NULL;
3408         StrList **xst = &xsl;
3409
3410         casesense = true;
3411
3412         tline = tline->next;
3413         skip_white_(tline);
3414         tline = expand_id(tline);
3415         if (!tline || (tline->type != TOK_ID &&
3416                        (tline->type != TOK_PREPROC_ID ||
3417                         tline->text[1] != '$'))) {
3418             error(ERR_NONFATAL,
3419                   "`%%pathsearch' expects a macro identifier as first parameter");
3420             free_tlist(origline);
3421             return DIRECTIVE_FOUND;
3422         }
3423         ctx = get_ctx(tline->text, &mname, false);
3424         last = tline;
3425         tline = expand_smacro(tline->next);
3426         last->next = NULL;
3427
3428         t = tline;
3429         while (tok_type_(t, TOK_WHITESPACE))
3430             t = t->next;
3431
3432         if (!t || (t->type != TOK_STRING &&
3433                    t->type != TOK_INTERNAL_STRING)) {
3434             error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
3435             free_tlist(tline);
3436             free_tlist(origline);
3437             return DIRECTIVE_FOUND;     /* but we did _something_ */
3438         }
3439         if (t->next)
3440             error(ERR_WARNING|ERR_PASS1,
3441                   "trailing garbage after `%%pathsearch' ignored");
3442         p = t->text;
3443         if (t->type != TOK_INTERNAL_STRING)
3444             nasm_unquote(p, NULL);
3445
3446         fp = inc_fopen(p, &xsl, &xst, true);
3447         if (fp) {
3448             p = xsl->str;
3449             fclose(fp);         /* Don't actually care about the file */
3450         }
3451         macro_start = nasm_malloc(sizeof(*macro_start));
3452         macro_start->next = NULL;
3453         macro_start->text = nasm_quote(p, strlen(p));
3454         macro_start->type = TOK_STRING;
3455         macro_start->a.mac = NULL;
3456         if (xsl)
3457             nasm_free(xsl);
3458
3459         /*
3460          * We now have a macro name, an implicit parameter count of
3461          * zero, and a string token to use as an expansion. Create
3462          * and store an SMacro.
3463          */
3464         define_smacro(ctx, mname, casesense, 0, macro_start);
3465         free_tlist(tline);
3466         free_tlist(origline);
3467         return DIRECTIVE_FOUND;
3468     }
3469
3470     case PP_STRLEN:
3471                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3472         casesense = true;
3473
3474         tline = tline->next;
3475         skip_white_(tline);
3476         tline = expand_id(tline);
3477         if (!tline || (tline->type != TOK_ID &&
3478                        (tline->type != TOK_PREPROC_ID ||
3479                         tline->text[1] != '$'))) {
3480             error(ERR_NONFATAL,
3481                   "`%%strlen' expects a macro identifier as first parameter");
3482             free_tlist(origline);
3483             return DIRECTIVE_FOUND;
3484         }
3485         ctx = get_ctx(tline->text, &mname, false);
3486         last = tline;
3487         tline = expand_smacro(tline->next);
3488         last->next = NULL;
3489
3490         t = tline;
3491         while (tok_type_(t, TOK_WHITESPACE))
3492             t = t->next;
3493         /* t should now point to the string */
3494         if (!tok_type_(t, TOK_STRING)) {
3495             error(ERR_NONFATAL,
3496                   "`%%strlen` requires string as second parameter");
3497             free_tlist(tline);
3498             free_tlist(origline);
3499             return DIRECTIVE_FOUND;
3500         }
3501
3502         macro_start = nasm_malloc(sizeof(*macro_start));
3503         macro_start->next = NULL;
3504         make_tok_num(macro_start, nasm_unquote(t->text, NULL));
3505         macro_start->a.mac = NULL;
3506
3507         /*
3508          * We now have a macro name, an implicit parameter count of
3509          * zero, and a numeric token to use as an expansion. Create
3510          * and store an SMacro.
3511          */
3512         define_smacro(ctx, mname, casesense, 0, macro_start);
3513         free_tlist(tline);
3514         free_tlist(origline);
3515         return DIRECTIVE_FOUND;
3516
3517     case PP_STRCAT:
3518                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3519         casesense = true;
3520
3521         tline = tline->next;
3522         skip_white_(tline);
3523         tline = expand_id(tline);
3524         if (!tline || (tline->type != TOK_ID &&
3525                        (tline->type != TOK_PREPROC_ID ||
3526                         tline->text[1] != '$'))) {
3527             error(ERR_NONFATAL,
3528                   "`%%strcat' expects a macro identifier as first parameter");
3529             free_tlist(origline);
3530             return DIRECTIVE_FOUND;
3531         }
3532         ctx = get_ctx(tline->text, &mname, false);
3533         last = tline;
3534         tline = expand_smacro(tline->next);
3535         last->next = NULL;
3536
3537         len = 0;
3538         list_for_each(t, tline) {
3539             switch (t->type) {
3540             case TOK_WHITESPACE:
3541                 break;
3542             case TOK_STRING:
3543                 len += t->a.len = nasm_unquote(t->text, NULL);
3544                 break;
3545             case TOK_OTHER:
3546                 if (!strcmp(t->text, ",")) /* permit comma separators */
3547                     break;
3548                 /* else fall through */
3549             default:
3550                 error(ERR_NONFATAL,
3551                       "non-string passed to `%%strcat' (%d)", t->type);
3552                 free_tlist(tline);
3553                 free_tlist(origline);
3554                 return DIRECTIVE_FOUND;
3555             }
3556         }
3557
3558         p = pp = nasm_malloc(len);
3559         list_for_each(t, tline) {
3560             if (t->type == TOK_STRING) {
3561                 memcpy(p, t->text, t->a.len);
3562                 p += t->a.len;
3563             }
3564         }
3565
3566         /*
3567          * We now have a macro name, an implicit parameter count of
3568          * zero, and a numeric token to use as an expansion. Create
3569          * and store an SMacro.
3570          */
3571         macro_start = new_Token(NULL, TOK_STRING, NULL, 0);
3572         macro_start->text = nasm_quote(pp, len);
3573         nasm_free(pp);
3574         define_smacro(ctx, mname, casesense, 0, macro_start);
3575         free_tlist(tline);
3576         free_tlist(origline);
3577         return DIRECTIVE_FOUND;
3578
3579     case PP_SUBSTR:
3580                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3581     {
3582         int64_t start, count;
3583         size_t len;
3584
3585         casesense = true;
3586
3587         tline = tline->next;
3588         skip_white_(tline);
3589         tline = expand_id(tline);
3590         if (!tline || (tline->type != TOK_ID &&
3591                        (tline->type != TOK_PREPROC_ID ||
3592                         tline->text[1] != '$'))) {
3593             error(ERR_NONFATAL,
3594                   "`%%substr' expects a macro identifier as first parameter");
3595             free_tlist(origline);
3596             return DIRECTIVE_FOUND;
3597         }
3598         ctx = get_ctx(tline->text, &mname, false);
3599         last = tline;
3600         tline = expand_smacro(tline->next);
3601         last->next = NULL;
3602
3603         if (tline) /* skip expanded id */
3604                         t = tline->next;
3605         while (tok_type_(t, TOK_WHITESPACE))
3606             t = t->next;
3607
3608         /* t should now point to the string */
3609         if (!tok_type_(t, TOK_STRING)) {
3610             error(ERR_NONFATAL,
3611                   "`%%substr` requires string as second parameter");
3612             free_tlist(tline);
3613             free_tlist(origline);
3614             return DIRECTIVE_FOUND;
3615         }
3616
3617         tt = t->next;
3618         tptr = &tt;
3619         tokval.t_type = TOKEN_INVALID;
3620         evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3621                               pass, error, NULL);
3622         if (!evalresult) {
3623             free_tlist(tline);
3624             free_tlist(origline);
3625             return DIRECTIVE_FOUND;
3626         } else if (!is_simple(evalresult)) {
3627             error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3628             free_tlist(tline);
3629             free_tlist(origline);
3630             return DIRECTIVE_FOUND;
3631         }
3632         start = evalresult->value - 1;
3633
3634         while (tok_type_(tt, TOK_WHITESPACE))
3635             tt = tt->next;
3636         if (!tt) {
3637             count = 1;             /* Backwards compatibility: one character */
3638         } else {
3639             tokval.t_type = TOKEN_INVALID;
3640             evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3641                                   pass, error, NULL);
3642             if (!evalresult) {
3643                 free_tlist(tline);
3644                 free_tlist(origline);
3645                 return DIRECTIVE_FOUND;
3646             } else if (!is_simple(evalresult)) {
3647                 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3648                 free_tlist(tline);
3649                 free_tlist(origline);
3650                 return DIRECTIVE_FOUND;
3651             }
3652             count = evalresult->value;
3653         }
3654
3655         len = nasm_unquote(t->text, NULL);
3656         /* make start and count being in range */
3657         if (start < 0)
3658             start = 0;
3659         if (count < 0)
3660             count = len + count + 1 - start;
3661         if (start + count > (int64_t)len)
3662             count = len - start;
3663         if (!len || count < 0 || start >=(int64_t)len)
3664             start = -1, count = 0; /* empty string */
3665
3666         macro_start = nasm_malloc(sizeof(*macro_start));
3667         macro_start->next = NULL;
3668         macro_start->text = nasm_quote((start < 0) ? "" : t->text + start, count);
3669         macro_start->type = TOK_STRING;
3670         macro_start->a.mac = NULL;
3671
3672         /*
3673          * We now have a macro name, an implicit parameter count of
3674          * zero, and a numeric token to use as an expansion. Create
3675          * and store an SMacro.
3676          */
3677         define_smacro(ctx, mname, casesense, 0, macro_start);
3678         free_tlist(tline);
3679         free_tlist(origline);
3680         return DIRECTIVE_FOUND;
3681     }
3682
3683     case PP_ASSIGN:
3684     case PP_IASSIGN:
3685                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3686         casesense = (i == PP_ASSIGN);
3687
3688         tline = tline->next;
3689         skip_white_(tline);
3690         tline = expand_id(tline);
3691         if (!tline || (tline->type != TOK_ID &&
3692                        (tline->type != TOK_PREPROC_ID ||
3693                         tline->text[1] != '$'))) {
3694             error(ERR_NONFATAL,
3695                   "`%%%sassign' expects a macro identifier",
3696                   (i == PP_IASSIGN ? "i" : ""));
3697             free_tlist(origline);
3698             return DIRECTIVE_FOUND;
3699         }
3700         ctx = get_ctx(tline->text, &mname, false);
3701         last = tline;
3702         tline = expand_smacro(tline->next);
3703         last->next = NULL;
3704
3705         t = tline;
3706         tptr = &t;
3707         tokval.t_type = TOKEN_INVALID;
3708         evalresult =
3709             evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3710         free_tlist(tline);
3711         if (!evalresult) {
3712             free_tlist(origline);
3713             return DIRECTIVE_FOUND;
3714         }
3715
3716         if (tokval.t_type)
3717             error(ERR_WARNING|ERR_PASS1,
3718                   "trailing garbage after expression ignored");
3719
3720         if (!is_simple(evalresult)) {
3721             error(ERR_NONFATAL,
3722                   "non-constant value given to `%%%sassign'",
3723                   (i == PP_IASSIGN ? "i" : ""));
3724             free_tlist(origline);
3725             return DIRECTIVE_FOUND;
3726         }
3727
3728         macro_start = nasm_malloc(sizeof(*macro_start));
3729         macro_start->next = NULL;
3730         make_tok_num(macro_start, reloc_value(evalresult));
3731         macro_start->a.mac = NULL;
3732
3733         /*
3734          * We now have a macro name, an implicit parameter count of
3735          * zero, and a numeric token to use as an expansion. Create
3736          * and store an SMacro.
3737          */
3738         define_smacro(ctx, mname, casesense, 0, macro_start);
3739         free_tlist(origline);
3740         return DIRECTIVE_FOUND;
3741
3742     case PP_LINE:
3743                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3744         /*
3745          * Syntax is `%line nnn[+mmm] [filename]'
3746          */
3747         tline = tline->next;
3748         skip_white_(tline);
3749         if (!tok_type_(tline, TOK_NUMBER)) {
3750             error(ERR_NONFATAL, "`%%line' expects line number");
3751             free_tlist(origline);
3752             return DIRECTIVE_FOUND;
3753         }
3754         k = readnum(tline->text, &err);
3755         m = 1;
3756         tline = tline->next;
3757         if (tok_is_(tline, "+")) {
3758             tline = tline->next;
3759             if (!tok_type_(tline, TOK_NUMBER)) {
3760                 error(ERR_NONFATAL, "`%%line' expects line increment");
3761                 free_tlist(origline);
3762                 return DIRECTIVE_FOUND;
3763             }
3764             m = readnum(tline->text, &err);
3765             tline = tline->next;
3766         }
3767         skip_white_(tline);
3768         src_set_linnum(k);
3769         istk->lineinc = m;
3770         if (tline) {
3771             nasm_free(src_set_fname(detoken(tline, false)));
3772         }
3773         free_tlist(origline);
3774         return DIRECTIVE_FOUND;
3775                         
3776         case PP_WHILE:
3777                 if (defining != NULL) {
3778                         if (defining->type == EXP_WHILE) {
3779                                 defining->def_depth ++;
3780                         }
3781                         return NO_DIRECTIVE_FOUND;
3782                 }
3783                 l = NULL;
3784                 if ((istk->expansion != NULL) &&
3785                         (istk->expansion->emitting == false)) {
3786                         j = COND_NEVER;
3787                 } else {
3788                         l = new_Line();
3789                         l->first = copy_Token(tline->next);
3790                         j = if_condition(tline->next, i);
3791                         tline->next = NULL; /* it got freed */
3792                         j = (((j < 0) ? COND_NEVER : j) ? COND_IF_TRUE : COND_IF_FALSE);
3793                 }                       
3794                 ed = new_ExpDef(EXP_WHILE);
3795                 ed->state = j;
3796                 ed->cur_depth = 1;
3797                 ed->max_depth = DEADMAN_LIMIT;
3798                 ed->ignoring = ((ed->state == COND_IF_TRUE) ? false : true);
3799                 if (ed->ignoring == false) {
3800                         ed->line = l;
3801                         ed->last = l;
3802                 } else if (l != NULL) {
3803                         delete_Token(l->first);
3804                         nasm_free(l);
3805                         l = NULL;
3806                 }
3807                 ed->prev = defining;
3808                 defining = ed;
3809                 free_tlist(origline);
3810                 return DIRECTIVE_FOUND;
3811                         
3812         case PP_ENDWHILE:
3813                 if (defining != NULL) {
3814                         if (defining->type == EXP_WHILE) {
3815                                 if (defining->def_depth > 0) {
3816                                         defining->def_depth --;
3817                                         return NO_DIRECTIVE_FOUND;
3818                                 }
3819                         } else {
3820                                 return NO_DIRECTIVE_FOUND;
3821                         }
3822                 }
3823                 if (tline->next != NULL) {
3824                         error_precond(ERR_WARNING|ERR_PASS1,
3825                                                   "trailing garbage after `%%endwhile' ignored");
3826                 }
3827                 if ((defining == NULL) || (defining->type != EXP_WHILE)) {
3828                         error(ERR_NONFATAL, "`%%endwhile': no matching `%%while'");
3829                         return DIRECTIVE_FOUND;
3830                 }
3831                 ed = defining;
3832                 defining = ed->prev;
3833                 if (ed->ignoring == false) {
3834                         ed->prev = expansions;
3835                         expansions = ed;
3836                         ei = new_ExpInv(EXP_WHILE, ed);
3837                         ei->current = ed->line->next;
3838                         ei->emitting = true;
3839                         ei->prev = istk->expansion;
3840                         istk->expansion = ei;
3841                 } else {
3842                         nasm_free(ed);
3843                 }
3844                 free_tlist(origline);
3845                 return DIRECTIVE_FOUND;
3846
3847         case PP_EXITWHILE:
3848                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3849                 /*
3850                  * We must search along istk->expansion until we hit a
3851                  * while invocation. Then we disable the emitting state(s)
3852                  * between exitwhile and endwhile.
3853                  */
3854                 for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
3855                         if (ei->type == EXP_WHILE) {
3856                                 break;
3857                         }
3858                 }
3859                         
3860                 if (ei != NULL) {
3861                         /*
3862                          * Set all invocations leading back to the while
3863                          * invocation to a non-emitting state.
3864                          */
3865                         for (eei = istk->expansion; eei != ei; eei = eei->prev) {
3866                                 eei->emitting = false;
3867                         }
3868                         eei->emitting = false;
3869                         eei->current = NULL;
3870                         eei->def->cur_depth = eei->def->max_depth;
3871                 } else {
3872                         error(ERR_NONFATAL, "`%%exitwhile' not within `%%while' block");
3873                 }
3874                 free_tlist(origline);
3875                 return DIRECTIVE_FOUND;
3876                         
3877         case PP_COMMENT:
3878                 if (defining != NULL) {
3879                         if (defining->type == EXP_COMMENT) {
3880                                 defining->def_depth ++;
3881                         }
3882                         return NO_DIRECTIVE_FOUND;
3883                 }
3884                 ed = new_ExpDef(EXP_COMMENT);
3885                 ed->ignoring = true;
3886                 ed->prev = defining;
3887                 defining = ed;
3888                 free_tlist(origline);
3889                 return DIRECTIVE_FOUND;
3890                 
3891         case PP_ENDCOMMENT:
3892                 if (defining != NULL) {
3893                         if (defining->type == EXP_COMMENT) {
3894                                 if (defining->def_depth > 0) {
3895                                         defining->def_depth --;
3896                                         return NO_DIRECTIVE_FOUND;
3897                                 }
3898                         } else {
3899                                 return NO_DIRECTIVE_FOUND;
3900                         }
3901                 }
3902                 if ((defining == NULL) || (defining->type != EXP_COMMENT)) {
3903                         error(ERR_NONFATAL, "`%%endcomment': no matching `%%comment'");
3904                         return DIRECTIVE_FOUND;
3905                 }
3906                 ed = defining;
3907                 defining = ed->prev;
3908                 nasm_free(ed);
3909                 free_tlist(origline);
3910                 return DIRECTIVE_FOUND;
3911                         
3912         case PP_FINAL:
3913                 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3914                 if (in_final != false) {
3915                         error(ERR_FATAL, "`%%final' cannot be used recursively");
3916                 }
3917                 tline = tline->next;
3918                 skip_white_(tline);
3919                 if (tline == NULL) {
3920                         error(ERR_NONFATAL, "`%%final' expects at least one parameter");
3921                 } else {        
3922                         l = new_Line();
3923                         l->first = copy_Token(tline);
3924                         l->next = finals;
3925                         finals = l;
3926                 }
3927                 free_tlist(origline);
3928                 return DIRECTIVE_FOUND;
3929
3930     default:
3931         error(ERR_FATAL,
3932               "preprocessor directive `%s' not yet implemented",
3933               pp_directives[i]);
3934         return DIRECTIVE_FOUND;
3935     }
3936 }
3937
3938 /*
3939  * Ensure that a macro parameter contains a condition code and
3940  * nothing else. Return the condition code index if so, or -1
3941  * otherwise.
3942  */
3943 static int find_cc(Token * t)
3944 {
3945     Token *tt;
3946     int i, j, k, m;
3947
3948     if (!t)
3949         return -1;              /* Probably a %+ without a space */
3950
3951     skip_white_(t);
3952     if (t->type != TOK_ID)
3953         return -1;
3954     tt = t->next;
3955     skip_white_(tt);
3956     if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
3957         return -1;
3958
3959     i = -1;
3960     j = ARRAY_SIZE(conditions);
3961     while (j - i > 1) {
3962         k = (j + i) / 2;
3963         m = nasm_stricmp(t->text, conditions[k]);
3964         if (m == 0) {
3965             i = k;
3966             j = -2;
3967             break;
3968         } else if (m < 0) {
3969             j = k;
3970         } else
3971             i = k;
3972     }
3973     if (j != -2)
3974         return -1;
3975     return i;
3976 }
3977
3978 static bool paste_tokens(Token **head, const struct tokseq_match *m,
3979                          int mnum, bool handle_paste_tokens)
3980 {
3981     Token **tail, *t, *tt;
3982     Token **paste_head;
3983     bool did_paste = false;
3984     char *tmp;
3985     int i;
3986
3987     /* Now handle token pasting... */
3988     paste_head = NULL;
3989     tail = head;
3990     while ((t = *tail) && (tt = t->next)) {
3991         switch (t->type) {
3992         case TOK_WHITESPACE:
3993             if (tt->type == TOK_WHITESPACE) {
3994                 /* Zap adjacent whitespace tokens */
3995                 t->next = delete_Token(tt);
3996             } else {
3997                 /* Do not advance paste_head here */
3998                 tail = &t->next;
3999             }
4000             break;
4001         case TOK_PASTE:         /* %+ */
4002             if (handle_paste_tokens) {
4003                 /* Zap %+ and whitespace tokens to the right */
4004                 while (t && (t->type == TOK_WHITESPACE ||
4005                              t->type == TOK_PASTE))
4006                     t = *tail = delete_Token(t);
4007                 if (!paste_head || !t)
4008                     break;      /* Nothing to paste with */
4009                 tail = paste_head;
4010                 t = *tail;
4011                 tt = t->next;
4012                 while (tok_type_(tt, TOK_WHITESPACE))
4013                     tt = t->next = delete_Token(tt);
4014                 if (tt) {
4015                     tmp = nasm_strcat(t->text, tt->text);
4016                     delete_Token(t);
4017                     tt = delete_Token(tt);
4018                     t = *tail = tokenize(tmp);
4019                     nasm_free(tmp);
4020                     while (t->next) {
4021                         tail = &t->next;
4022                         t = t->next;
4023                     }
4024                     t->next = tt; /* Attach the remaining token chain */
4025                     did_paste = true;
4026                 }
4027                 paste_head = tail;
4028                 tail = &t->next;
4029                 break;
4030             }
4031             /* else fall through */
4032         default:
4033             /*
4034              * Concatenation of tokens might look nontrivial
4035              * but in real it's pretty simple -- the caller
4036              * prepares the masks of token types to be concatenated
4037              * and we simply find matched sequences and slip
4038              * them together
4039              */
4040             for (i = 0; i < mnum; i++) {
4041                 if (PP_CONCAT_MASK(t->type) & m[i].mask_head) {
4042                     size_t len = 0;
4043                     char *tmp, *p;
4044
4045                     while (tt && (PP_CONCAT_MASK(tt->type) & m[i].mask_tail)) {
4046                          len += strlen(tt->text);
4047                          tt = tt->next;
4048                     }
4049
4050                     /*
4051                      * Now tt points to the first token after
4052                      * the potential paste area...
4053                      */
4054                     if (tt != t->next) {
4055                         /* We have at least two tokens... */
4056                         len += strlen(t->text);
4057                         p = tmp = nasm_malloc(len+1);
4058                         while (t != tt) {
4059                             strcpy(p, t->text);
4060                             p = strchr(p, '\0');
4061                             t = delete_Token(t);
4062                         }
4063                         t = *tail = tokenize(tmp);
4064                         nasm_free(tmp);
4065                         while (t->next) {
4066                             tail = &t->next;
4067                             t = t->next;
4068                         }
4069                         t->next = tt;   /* Attach the remaining token chain */
4070                         did_paste = true;
4071                     }
4072                     paste_head = tail;
4073                     tail = &t->next;
4074                     break;
4075                 }
4076             }
4077             if (i >= mnum) {    /* no match */
4078                 tail = &t->next;
4079                 if (!tok_type_(t->next, TOK_WHITESPACE))
4080                     paste_head = tail;
4081             }
4082             break;
4083         }
4084     }
4085     return did_paste;
4086 }
4087
4088 /*
4089  * expands to a list of tokens from %{x:y}
4090  */
4091 static Token *expand_mmac_params_range(ExpInv *ei, Token *tline, Token ***last)
4092 {
4093     Token *t = tline, **tt, *tm, *head;
4094     char *pos;
4095     int fst, lst, j, i;
4096         
4097     pos = strchr(tline->text, ':');
4098     nasm_assert(pos);
4099
4100     lst = atoi(pos + 1);
4101     fst = atoi(tline->text + 1);
4102
4103     /*
4104      * only macros params are accounted so
4105      * if someone passes %0 -- we reject such
4106      * value(s)
4107      */
4108     if (lst == 0 || fst == 0)
4109         goto err;
4110
4111     /* the values should be sane */
4112     if ((fst > (int)ei->nparam || fst < (-(int)ei->nparam)) ||
4113         (lst > (int)ei->nparam || lst < (-(int)ei->nparam)))
4114         goto err;
4115
4116     fst = fst < 0 ? fst + (int)ei->nparam + 1: fst;
4117     lst = lst < 0 ? lst + (int)ei->nparam + 1: lst;
4118
4119     /* counted from zero */
4120     fst--, lst--;
4121
4122     /*
4123      * it will be at least one token
4124      */
4125     tm = ei->params[(fst + ei->rotate) % ei->nparam];
4126     t = new_Token(NULL, tm->type, tm->text, 0);
4127     head = t, tt = &t->next;
4128     if (fst < lst) {
4129         for (i = fst + 1; i <= lst; i++) {
4130             t = new_Token(NULL, TOK_OTHER, ",", 0);
4131             *tt = t, tt = &t->next;
4132             j = (i + ei->rotate) % ei->nparam;
4133             tm = ei->params[j];
4134             t = new_Token(NULL, tm->type, tm->text, 0);
4135             *tt = t, tt = &t->next;
4136         }
4137     } else {
4138         for (i = fst - 1; i >= lst; i--) {
4139             t = new_Token(NULL, TOK_OTHER, ",", 0);
4140             *tt = t, tt = &t->next;
4141             j = (i + ei->rotate) % ei->nparam;
4142             tm = ei->params[j];
4143             t = new_Token(NULL, tm->type, tm->text, 0);
4144             *tt = t, tt = &t->next;
4145         }
4146     }
4147
4148     *last = tt;
4149     return head;
4150
4151 err:
4152     error(ERR_NONFATAL, "`%%{%s}': macro parameters out of range",
4153           &tline->text[1]);
4154     return tline;
4155 }
4156
4157 /*
4158  * Expand MMacro-local things: parameter references (%0, %n, %+n,
4159  * %-n) and MMacro-local identifiers (%%foo) as well as
4160  * macro indirection (%[...]) and range (%{..:..}).
4161  */
4162 static Token *expand_mmac_params(Token * tline)
4163 {
4164     Token *t, *tt, **tail, *thead;
4165     bool changed = false;
4166     char *pos;
4167
4168     tail = &thead;
4169     thead = NULL;
4170
4171     while (tline) {
4172         if (tline->type == TOK_PREPROC_ID &&
4173             (((tline->text[1] == '+' || tline->text[1] == '-') && tline->text[2])   ||
4174               (tline->text[1] >= '0' && tline->text[1] <= '9')                      ||
4175                tline->text[1] == '%')) {
4176             char *text = NULL;
4177             int type = 0, cc;   /* type = 0 to placate optimisers */
4178             char tmpbuf[30];
4179             unsigned int n;
4180             int i;
4181                         ExpInv *ei;
4182
4183             t = tline;
4184             tline = tline->next;
4185
4186                         for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
4187                                 if (ei->type == EXP_MMACRO) {
4188                                         break;
4189                                 }
4190                         }
4191             if (ei == NULL) {
4192                 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
4193             } else {
4194                 pos = strchr(t->text, ':');
4195                 if (!pos) {
4196                     switch (t->text[1]) {
4197                         /*
4198                          * We have to make a substitution of one of the
4199                          * forms %1, %-1, %+1, %%foo, %0.
4200                          */
4201                     case '0':
4202                                                 if ((strlen(t->text) > 2) && (t->text[2] == '0')) {
4203                                                         type = TOK_ID;
4204                                                         text = nasm_strdup(ei->label_text);
4205                                                 } else {
4206                                                         type = TOK_NUMBER;
4207                                                         snprintf(tmpbuf, sizeof(tmpbuf), "%d", ei->nparam);
4208                                                         text = nasm_strdup(tmpbuf);
4209                                                 }
4210                                                 break;
4211                     case '%':
4212                         type = TOK_ID;
4213                         snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
4214                                  ei->unique);
4215                         text = nasm_strcat(tmpbuf, t->text + 2);
4216                         break;
4217                     case '-':
4218                         n = atoi(t->text + 2) - 1;
4219                         if (n >= ei->nparam)
4220                             tt = NULL;
4221                         else {
4222                             if (ei->nparam > 1)
4223                                 n = (n + ei->rotate) % ei->nparam;
4224                             tt = ei->params[n];
4225                         }
4226                         cc = find_cc(tt);
4227                         if (cc == -1) {
4228                             error(ERR_NONFATAL,
4229                                   "macro parameter %d is not a condition code",
4230                                   n + 1);
4231                             text = NULL;
4232                         } else {
4233                             type = TOK_ID;
4234                             if (inverse_ccs[cc] == -1) {
4235                                 error(ERR_NONFATAL,
4236                                       "condition code `%s' is not invertible",
4237                                       conditions[cc]);
4238                                 text = NULL;
4239                             } else
4240                                 text = nasm_strdup(conditions[inverse_ccs[cc]]);
4241                         }
4242                         break;
4243                     case '+':
4244                         n = atoi(t->text + 2) - 1;
4245                         if (n >= ei->nparam)
4246                             tt = NULL;
4247                         else {
4248                             if (ei->nparam > 1)
4249                                 n = (n + ei->rotate) % ei->nparam;
4250                             tt = ei->params[n];
4251                         }
4252                         cc = find_cc(tt);
4253                         if (cc == -1) {
4254                             error(ERR_NONFATAL,
4255                                   "macro parameter %d is not a condition code",
4256                                   n + 1);
4257                             text = NULL;
4258                         } else {
4259                             type = TOK_ID;
4260                             text = nasm_strdup(conditions[cc]);
4261                         }
4262                         break;
4263                     default:
4264                         n = atoi(t->text + 1) - 1;
4265                         if (n >= ei->nparam)
4266                             tt = NULL;
4267                         else {
4268                             if (ei->nparam > 1)
4269                                 n = (n + ei->rotate) % ei->nparam;
4270                             tt = ei->params[n];
4271                         }
4272                         if (tt) {
4273                             for (i = 0; i < ei->paramlen[n]; i++) {
4274                                 *tail = new_Token(NULL, tt->type, tt->text, 0);
4275                                 tail = &(*tail)->next;
4276                                 tt = tt->next;
4277                             }
4278                         }
4279                         text = NULL;        /* we've done it here */
4280                         break;
4281                     }
4282                 } else {
4283                     /*
4284                      * seems we have a parameters range here
4285                      */
4286                     Token *head, **last;
4287                     head = expand_mmac_params_range(ei, t, &last);
4288                     if (head != t) {
4289                         *tail = head;
4290                         *last = tline;
4291                         tline = head;
4292                         text = NULL;
4293                     }
4294                 }
4295             }
4296             if (!text) {
4297                 delete_Token(t);
4298             } else {
4299                 *tail = t;
4300                 tail = &t->next;
4301                 t->type = type;
4302                 nasm_free(t->text);
4303                 t->text = text;
4304                 t->a.mac = NULL;
4305             }
4306             changed = true;
4307             continue;
4308         } else if (tline->type == TOK_INDIRECT) {
4309             t = tline;
4310             tline = tline->next;
4311             tt = tokenize(t->text);
4312             tt = expand_mmac_params(tt);
4313             tt = expand_smacro(tt);
4314             *tail = tt;
4315             while (tt) {
4316                 tt->a.mac = NULL; /* Necessary? */
4317                 tail = &tt->next;
4318                 tt = tt->next;
4319             }
4320             delete_Token(t);
4321             changed = true;
4322         } else {
4323             t = *tail = tline;
4324             tline = tline->next;
4325             t->a.mac = NULL;
4326             tail = &t->next;
4327         }
4328     }
4329     *tail = NULL;
4330
4331     if (changed) {
4332         const struct tokseq_match t[] = {
4333             {
4334                 PP_CONCAT_MASK(TOK_ID)          |
4335                 PP_CONCAT_MASK(TOK_FLOAT),          /* head */
4336                 PP_CONCAT_MASK(TOK_ID)          |
4337                 PP_CONCAT_MASK(TOK_NUMBER)      |
4338                 PP_CONCAT_MASK(TOK_FLOAT)       |
4339                 PP_CONCAT_MASK(TOK_OTHER)           /* tail */
4340             },
4341             {
4342                 PP_CONCAT_MASK(TOK_NUMBER),         /* head */
4343                 PP_CONCAT_MASK(TOK_NUMBER)          /* tail */
4344             }
4345         };
4346         paste_tokens(&thead, t, ARRAY_SIZE(t), false);
4347     }
4348
4349     return thead;
4350 }
4351
4352 /*
4353  * Expand all single-line macro calls made in the given line.
4354  * Return the expanded version of the line. The original is deemed
4355  * to be destroyed in the process. (In reality we'll just move
4356  * Tokens from input to output a lot of the time, rather than
4357  * actually bothering to destroy and replicate.)
4358  */
4359
4360 static Token *expand_smacro(Token * tline)
4361 {
4362     Token *t, *tt, *mstart, **tail, *thead;
4363     SMacro *head = NULL, *m;
4364     Token **params;
4365     int *paramsize;
4366     unsigned int nparam, sparam;
4367     int brackets;
4368     Token *org_tline = tline;
4369     Context *ctx;
4370     const char *mname;
4371     int deadman = DEADMAN_LIMIT;
4372     bool expanded;
4373
4374     /*
4375      * Trick: we should avoid changing the start token pointer since it can
4376      * be contained in "next" field of other token. Because of this
4377      * we allocate a copy of first token and work with it; at the end of
4378      * routine we copy it back
4379      */
4380     if (org_tline) {
4381         tline = new_Token(org_tline->next, org_tline->type,
4382                           org_tline->text, 0);
4383         tline->a.mac = org_tline->a.mac;
4384         nasm_free(org_tline->text);
4385         org_tline->text = NULL;
4386     }
4387
4388     expanded = true;            /* Always expand %+ at least once */
4389
4390 again:
4391     thead = NULL;
4392     tail = &thead;
4393
4394     while (tline) {             /* main token loop */
4395         if (!--deadman) {
4396             error(ERR_NONFATAL, "interminable macro recursion");
4397             goto err;
4398         }
4399
4400         if ((mname = tline->text)) {
4401             /* if this token is a local macro, look in local context */
4402             if (tline->type == TOK_ID) {
4403                 head = (SMacro *)hash_findix(&smacros, mname);
4404             } else if (tline->type == TOK_PREPROC_ID) {
4405                 ctx = get_ctx(mname, &mname, false);
4406                 head = ctx ? (SMacro *)hash_findix(&ctx->localmac, mname) : NULL;
4407             } else
4408                 head = NULL;
4409
4410             /*
4411              * We've hit an identifier. As in is_mmacro below, we first
4412              * check whether the identifier is a single-line macro at
4413              * all, then think about checking for parameters if
4414              * necessary.
4415              */
4416             list_for_each(m, head)
4417                 if (!mstrcmp(m->name, mname, m->casesense))
4418                     break;
4419             if (m) {
4420                 mstart = tline;
4421                 params = NULL;
4422                 paramsize = NULL;
4423                 if (m->nparam == 0) {
4424                     /*
4425                      * Simple case: the macro is parameterless. Discard the
4426                      * one token that the macro call took, and push the
4427                      * expansion back on the to-do stack.
4428                      */
4429                     if (!m->expansion) {
4430                         if (!strcmp("__FILE__", m->name)) {
4431                             int32_t num = 0;
4432                             char *file = NULL;
4433                             src_get(&num, &file);
4434                             tline->text = nasm_quote(file, strlen(file));
4435                             tline->type = TOK_STRING;
4436                             nasm_free(file);
4437                             continue;
4438                         }
4439                         if (!strcmp("__LINE__", m->name)) {
4440                             nasm_free(tline->text);
4441                             make_tok_num(tline, src_get_linnum());
4442                             continue;
4443                         }
4444                         if (!strcmp("__BITS__", m->name)) {
4445                             nasm_free(tline->text);
4446                             make_tok_num(tline, globalbits);
4447                             continue;
4448                         }
4449                         tline = delete_Token(tline);
4450                         continue;
4451                     }
4452                 } else {
4453                     /*
4454                      * Complicated case: at least one macro with this name
4455                      * exists and takes parameters. We must find the
4456                      * parameters in the call, count them, find the SMacro
4457                      * that corresponds to that form of the macro call, and
4458                      * substitute for the parameters when we expand. What a
4459                      * pain.
4460                      */
4461                     /*tline = tline->next;
4462                       skip_white_(tline); */
4463                     do {
4464                         t = tline->next;
4465                         while (tok_type_(t, TOK_SMAC_END)) {
4466                             t->a.mac->in_progress = false;
4467                             t->text = NULL;
4468                             t = tline->next = delete_Token(t);
4469                         }
4470                         tline = t;
4471                     } while (tok_type_(tline, TOK_WHITESPACE));
4472                     if (!tok_is_(tline, "(")) {
4473                         /*
4474                          * This macro wasn't called with parameters: ignore
4475                          * the call. (Behaviour borrowed from gnu cpp.)
4476                          */
4477                         tline = mstart;
4478                         m = NULL;
4479                     } else {
4480                         int paren = 0;
4481                         int white = 0;
4482                         brackets = 0;
4483                         nparam = 0;
4484                         sparam = PARAM_DELTA;
4485                         params = nasm_malloc(sparam * sizeof(Token *));
4486                         params[0] = tline->next;
4487                         paramsize = nasm_malloc(sparam * sizeof(int));
4488                         paramsize[0] = 0;
4489                         while (true) {  /* parameter loop */
4490                             /*
4491                              * For some unusual expansions
4492                              * which concatenates function call
4493                              */
4494                             t = tline->next;
4495                             while (tok_type_(t, TOK_SMAC_END)) {
4496                                 t->a.mac->in_progress = false;
4497                                 t->text = NULL;
4498                                 t = tline->next = delete_Token(t);
4499                             }
4500                             tline = t;
4501
4502                             if (!tline) {
4503                                 error(ERR_NONFATAL,
4504                                       "macro call expects terminating `)'");
4505                                 break;
4506                             }
4507                             if (tline->type == TOK_WHITESPACE
4508                                 && brackets <= 0) {
4509                                 if (paramsize[nparam])
4510                                     white++;
4511                                 else
4512                                     params[nparam] = tline->next;
4513                                 continue;       /* parameter loop */
4514                             }
4515                             if (tline->type == TOK_OTHER
4516                                 && tline->text[1] == 0) {
4517                                 char ch = tline->text[0];
4518                                 if (ch == ',' && !paren && brackets <= 0) {
4519                                     if (++nparam >= sparam) {
4520                                         sparam += PARAM_DELTA;
4521                                         params = nasm_realloc(params,
4522                                                         sparam * sizeof(Token *));
4523                                         paramsize = nasm_realloc(paramsize,
4524                                                         sparam * sizeof(int));
4525                                     }
4526                                     params[nparam] = tline->next;
4527                                     paramsize[nparam] = 0;
4528                                     white = 0;
4529                                     continue;   /* parameter loop */
4530                                 }
4531                                 if (ch == '{' &&
4532                                     (brackets > 0 || (brackets == 0 &&
4533                                                       !paramsize[nparam])))
4534                                 {
4535                                     if (!(brackets++)) {
4536                                         params[nparam] = tline->next;
4537                                         continue;       /* parameter loop */
4538                                     }
4539                                 }
4540                                 if (ch == '}' && brackets > 0)
4541                                     if (--brackets == 0) {
4542                                         brackets = -1;
4543                                         continue;       /* parameter loop */
4544                                     }
4545                                 if (ch == '(' && !brackets)
4546                                     paren++;
4547                                 if (ch == ')' && brackets <= 0)
4548                                     if (--paren < 0)
4549                                         break;
4550                             }
4551                             if (brackets < 0) {
4552                                 brackets = 0;
4553                                 error(ERR_NONFATAL, "braces do not "
4554                                       "enclose all of macro parameter");
4555                             }
4556                             paramsize[nparam] += white + 1;
4557                             white = 0;
4558                         }       /* parameter loop */
4559                         nparam++;
4560                         while (m && (m->nparam != nparam ||
4561                                      mstrcmp(m->name, mname,
4562                                              m->casesense)))
4563                             m = m->next;
4564                         if (!m)
4565                             error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
4566                                   "macro `%s' exists, "
4567                                   "but not taking %d parameters",
4568                                   mstart->text, nparam);
4569                     }
4570                 }
4571                 if (m && m->in_progress)
4572                     m = NULL;
4573                 if (!m) {       /* in progess or didn't find '(' or wrong nparam */
4574                     /*
4575                      * Design question: should we handle !tline, which
4576                      * indicates missing ')' here, or expand those
4577                      * macros anyway, which requires the (t) test a few
4578                      * lines down?
4579                      */
4580                     nasm_free(params);
4581                     nasm_free(paramsize);
4582                     tline = mstart;
4583                 } else {
4584                     /*
4585                      * Expand the macro: we are placed on the last token of the
4586                      * call, so that we can easily split the call from the
4587                      * following tokens. We also start by pushing an SMAC_END
4588                      * token for the cycle removal.
4589                      */
4590                     t = tline;
4591                     if (t) {
4592                         tline = t->next;
4593                         t->next = NULL;
4594                     }
4595                     tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
4596                     tt->a.mac = m;
4597                     m->in_progress = true;
4598                     tline = tt;
4599                     list_for_each(t, m->expansion) {
4600                         if (t->type >= TOK_SMAC_PARAM) {
4601                             Token *pcopy = tline, **ptail = &pcopy;
4602                             Token *ttt, *pt;
4603                             int i;
4604
4605                             ttt = params[t->type - TOK_SMAC_PARAM];
4606                             i = paramsize[t->type - TOK_SMAC_PARAM];
4607                             while (--i >= 0) {
4608                                 pt = *ptail = new_Token(tline, ttt->type,
4609                                                         ttt->text, 0);
4610                                 ptail = &pt->next;
4611                                 ttt = ttt->next;
4612                             }
4613                             tline = pcopy;
4614                         } else if (t->type == TOK_PREPROC_Q) {
4615                             tt = new_Token(tline, TOK_ID, mname, 0);
4616                             tline = tt;
4617                         } else if (t->type == TOK_PREPROC_QQ) {
4618                             tt = new_Token(tline, TOK_ID, m->name, 0);
4619                             tline = tt;
4620                         } else {
4621                             tt = new_Token(tline, t->type, t->text, 0);
4622                             tline = tt;
4623                         }
4624                     }
4625
4626                     /*
4627                      * Having done that, get rid of the macro call, and clean
4628                      * up the parameters.
4629                      */
4630                     nasm_free(params);
4631                     nasm_free(paramsize);
4632                     free_tlist(mstart);
4633                     expanded = true;
4634                     continue;   /* main token loop */
4635                 }
4636             }
4637         }
4638
4639         if (tline->type == TOK_SMAC_END) {
4640             tline->a.mac->in_progress = false;
4641             tline = delete_Token(tline);
4642         } else {
4643             t = *tail = tline;
4644             tline = tline->next;
4645             t->a.mac = NULL;
4646             t->next = NULL;
4647             tail = &t->next;
4648         }
4649     }
4650
4651     /*
4652      * Now scan the entire line and look for successive TOK_IDs that resulted
4653      * after expansion (they can't be produced by tokenize()). The successive
4654      * TOK_IDs should be concatenated.
4655      * Also we look for %+ tokens and concatenate the tokens before and after
4656      * them (without white spaces in between).
4657      */
4658     if (expanded) {
4659         const struct tokseq_match t[] = {
4660             {
4661                 PP_CONCAT_MASK(TOK_ID)          |
4662                 PP_CONCAT_MASK(TOK_PREPROC_ID),     /* head */
4663                 PP_CONCAT_MASK(TOK_ID)          |
4664                 PP_CONCAT_MASK(TOK_PREPROC_ID)  |
4665                 PP_CONCAT_MASK(TOK_NUMBER)          /* tail */
4666             }
4667         };
4668         if (paste_tokens(&thead, t, ARRAY_SIZE(t), true)) {
4669             /*
4670              * If we concatenated something, *and* we had previously expanded
4671              * an actual macro, scan the lines again for macros...
4672              */
4673             tline = thead;
4674             expanded = false;
4675             goto again;
4676         }
4677     }
4678
4679 err:
4680     if (org_tline) {
4681         if (thead) {
4682             *org_tline = *thead;
4683             /* since we just gave text to org_line, don't free it */
4684             thead->text = NULL;
4685             delete_Token(thead);
4686         } else {
4687             /* the expression expanded to empty line;
4688                we can't return NULL for some reasons
4689                we just set the line to a single WHITESPACE token. */
4690             memset(org_tline, 0, sizeof(*org_tline));
4691             org_tline->text = NULL;
4692             org_tline->type = TOK_WHITESPACE;
4693         }
4694         thead = org_tline;
4695     }
4696
4697     return thead;
4698 }
4699
4700 /*
4701  * Similar to expand_smacro but used exclusively with macro identifiers
4702  * right before they are fetched in. The reason is that there can be
4703  * identifiers consisting of several subparts. We consider that if there
4704  * are more than one element forming the name, user wants a expansion,
4705  * otherwise it will be left as-is. Example:
4706  *
4707  *      %define %$abc cde
4708  *
4709  * the identifier %$abc will be left as-is so that the handler for %define
4710  * will suck it and define the corresponding value. Other case:
4711  *
4712  *      %define _%$abc cde
4713  *
4714  * In this case user wants name to be expanded *before* %define starts
4715  * working, so we'll expand %$abc into something (if it has a value;
4716  * otherwise it will be left as-is) then concatenate all successive
4717  * PP_IDs into one.
4718  */
4719 static Token *expand_id(Token * tline)
4720 {
4721     Token *cur, *oldnext = NULL;
4722
4723     if (!tline || !tline->next)
4724         return tline;
4725
4726     cur = tline;
4727     while (cur->next &&
4728            (cur->next->type == TOK_ID ||
4729             cur->next->type == TOK_PREPROC_ID
4730             || cur->next->type == TOK_NUMBER))
4731         cur = cur->next;
4732
4733     /* If identifier consists of just one token, don't expand */
4734     if (cur == tline)
4735         return tline;
4736
4737     if (cur) {
4738         oldnext = cur->next;    /* Detach the tail past identifier */
4739         cur->next = NULL;       /* so that expand_smacro stops here */
4740     }
4741
4742     tline = expand_smacro(tline);
4743
4744     if (cur) {
4745         /* expand_smacro possibly changhed tline; re-scan for EOL */
4746         cur = tline;
4747         while (cur && cur->next)
4748             cur = cur->next;
4749         if (cur)
4750             cur->next = oldnext;
4751     }
4752
4753     return tline;
4754 }
4755
4756 /*
4757  * Determine whether the given line constitutes a multi-line macro
4758  * call, and return the ExpDef structure called if so. Doesn't have
4759  * to check for an initial label - that's taken care of in
4760  * expand_mmacro - but must check numbers of parameters. Guaranteed
4761  * to be called with tline->type == TOK_ID, so the putative macro
4762  * name is easy to find.
4763  */
4764 static ExpDef *is_mmacro(Token * tline, Token *** params_array)
4765 {
4766     ExpDef *head, *ed;
4767     Token **params;
4768     int nparam;
4769
4770     head = (ExpDef *) hash_findix(&expdefs, tline->text);
4771
4772     /*
4773      * Efficiency: first we see if any macro exists with the given
4774      * name. If not, we can return NULL immediately. _Then_ we
4775      * count the parameters, and then we look further along the
4776      * list if necessary to find the proper ExpDef.
4777      */
4778     list_for_each(ed, head)
4779         if (!mstrcmp(ed->name, tline->text, ed->casesense))
4780             break;
4781     if (!ed)
4782         return NULL;
4783
4784     /*
4785      * OK, we have a potential macro. Count and demarcate the
4786      * parameters.
4787      */
4788     count_mmac_params(tline->next, &nparam, &params);
4789
4790     /*
4791      * So we know how many parameters we've got. Find the ExpDef
4792      * structure that handles this number.
4793      */
4794     while (ed) {
4795         if (ed->nparam_min <= nparam
4796             && (ed->plus || nparam <= ed->nparam_max)) {
4797             /*
4798              * It's right, and we can use it. Add its default
4799              * parameters to the end of our list if necessary.
4800              */
4801             if (ed->defaults && nparam < ed->nparam_min + ed->ndefs) {
4802                 params =
4803                     nasm_realloc(params,
4804                                  ((ed->nparam_min + ed->ndefs +
4805                                    1) * sizeof(*params)));
4806                 while (nparam < ed->nparam_min + ed->ndefs) {
4807                     params[nparam] = ed->defaults[nparam - ed->nparam_min];
4808                     nparam++;
4809                 }
4810             }
4811             /*
4812              * If we've gone over the maximum parameter count (and
4813              * we're in Plus mode), ignore parameters beyond
4814              * nparam_max.
4815              */
4816             if (ed->plus && nparam > ed->nparam_max)
4817                 nparam = ed->nparam_max;
4818             /*
4819              * Then terminate the parameter list, and leave.
4820              */
4821             if (!params) {      /* need this special case */
4822                 params = nasm_malloc(sizeof(*params));
4823                 nparam = 0;
4824             }
4825             params[nparam] = NULL;
4826             *params_array = params;
4827             return ed;
4828         }
4829         /*
4830          * This one wasn't right: look for the next one with the
4831          * same name.
4832          */
4833         list_for_each(ed, ed->next)
4834             if (!mstrcmp(ed->name, tline->text, ed->casesense))
4835                 break;
4836     }
4837
4838     /*
4839      * After all that, we didn't find one with the right number of
4840      * parameters. Issue a warning, and fail to expand the macro.
4841      */
4842     error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
4843           "macro `%s' exists, but not taking %d parameters",
4844           tline->text, nparam);
4845     nasm_free(params);
4846     return NULL;
4847 }
4848
4849 /*
4850  * Expand the multi-line macro call made by the given line, if
4851  * there is one to be expanded. If there is, push the expansion on
4852  * istk->expansion and return true. Otherwise return false.
4853  */
4854 static bool expand_mmacro(Token * tline)
4855 {
4856     Token *label = NULL;
4857     int dont_prepend = 0;
4858     Token **params, *t, *mtok;
4859     Line *l = NULL;
4860         ExpDef *ed;
4861         ExpInv *ei;
4862     int i, nparam, *paramlen;
4863     const char *mname;
4864
4865     t = tline;
4866     skip_white_(t);
4867     /*    if (!tok_type_(t, TOK_ID))  Lino 02/25/02 */
4868     if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
4869         return false;
4870     mtok = t;
4871         ed = is_mmacro(t, &params);
4872     if (ed != NULL) {
4873         mname = t->text;
4874     } else {
4875         Token *last;
4876         /*
4877          * We have an id which isn't a macro call. We'll assume
4878          * it might be a label; we'll also check to see if a
4879          * colon follows it. Then, if there's another id after
4880          * that lot, we'll check it again for macro-hood.
4881          */
4882         label = last = t;
4883         t = t->next;
4884         if (tok_type_(t, TOK_WHITESPACE))
4885             last = t, t = t->next;
4886         if (tok_is_(t, ":")) {
4887             dont_prepend = 1;
4888             last = t, t = t->next;
4889             if (tok_type_(t, TOK_WHITESPACE))
4890                 last = t, t = t->next;
4891         }
4892         if (!tok_type_(t, TOK_ID) || !(ed = is_mmacro(t, &params)))
4893             return false;
4894         last->next = NULL;
4895         mname = t->text;
4896         tline = t;
4897     }
4898
4899     /*
4900      * Fix up the parameters: this involves stripping leading and
4901      * trailing whitespace, then stripping braces if they are
4902      * present.
4903      */
4904     for (nparam = 0; params[nparam]; nparam++) ;
4905     paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
4906
4907     for (i = 0; params[i]; i++) {
4908         int brace = false;
4909         int comma = (!ed->plus || i < nparam - 1);
4910
4911         t = params[i];
4912         skip_white_(t);
4913         if (tok_is_(t, "{"))
4914             t = t->next, brace = true, comma = false;
4915         params[i] = t;
4916         paramlen[i] = 0;
4917         while (t) {
4918             if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
4919                 break;          /* ... because we have hit a comma */
4920             if (comma && t->type == TOK_WHITESPACE
4921                 && tok_is_(t->next, ","))
4922                 break;          /* ... or a space then a comma */
4923             if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
4924                 break;          /* ... or a brace */
4925             t = t->next;
4926             paramlen[i]++;
4927         }
4928     }
4929
4930         if (ed->cur_depth >= ed->max_depth) {
4931                 if (ed->max_depth > 1) {
4932                         error(ERR_WARNING,
4933                                   "reached maximum macro recursion depth of %i for %s",
4934                                   ed->max_depth,ed->name);
4935                 }
4936                 return false;
4937         } else {
4938                 ed->cur_depth ++;
4939         }
4940
4941     /*
4942      * OK, we have found a ExpDef structure representing a
4943          * previously defined mmacro. Create an expansion invocation
4944          * and point it back to the expansion definition. Substitution of
4945      * parameter tokens and macro-local tokens doesn't get done
4946      * until the single-line macro substitution process; this is
4947      * because delaying them allows us to change the semantics
4948      * later through %rotate.
4949      */
4950         ei = new_ExpInv(EXP_MMACRO, ed);
4951         ei->name = nasm_strdup(mname);
4952 //      ei->label = label;
4953 //      ei->label_text = detoken(label, false);
4954         ei->current = ed->line;
4955         ei->emitting = true;
4956 //      ei->iline = tline;
4957         ei->params = params;
4958         ei->nparam = nparam;
4959         ei->rotate = 0;
4960         ei->paramlen = paramlen;
4961         ei->lineno = 0;
4962
4963         ei->prev = istk->expansion;
4964         istk->expansion = ei;
4965         
4966         /*
4967          * Special case: detect %00 on first invocation; if found,
4968          * avoid emitting any labels that precede the mmacro call.
4969          * ed->prepend is set to -1 when %00 is detected, else 1.
4970          */
4971         if (ed->prepend == 0) {
4972                 for (l = ed->line; l != NULL; l = l->next) {
4973                         for (t = l->first; t != NULL; t = t->next) {
4974                                 if ((t->type == TOK_PREPROC_ID) &&
4975                                         (strlen(t->text) == 3) &&
4976                                         (t->text[1] == '0') && (t->text[2] == '0')) {
4977                                         dont_prepend = -1;
4978                                         break;
4979                                 }
4980                         }
4981                         if (dont_prepend < 0) {
4982                                 break;
4983                         }
4984                 }
4985                 ed->prepend = ((dont_prepend < 0) ? -1 : 1);
4986         }
4987
4988     /*
4989      * If we had a label, push it on as the first line of
4990      * the macro expansion.
4991      */
4992     if (label != NULL) {
4993                 if (ed->prepend < 0) {
4994                         ei->label_text = detoken(label, false);
4995                 } else {
4996                         if (dont_prepend == 0) {
4997                                 t = label;
4998                                 while (t->next != NULL) {
4999                                         t = t->next;
5000                                 }
5001                                 t->next = new_Token(NULL, TOK_OTHER, ":", 0);
5002                         }
5003                         Line *l = new_Line();
5004                         l->first = copy_Token(label);
5005                         l->next = ei->current;
5006                         ei->current = l;
5007                 }
5008     }
5009
5010     list->uplevel(ed->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
5011
5012         istk->mmac_depth++;
5013     return true;
5014 }
5015
5016 /* The function that actually does the error reporting */
5017 static void verror(int severity, const char *fmt, va_list arg)
5018 {
5019     char buff[1024];
5020
5021     vsnprintf(buff, sizeof(buff), fmt, arg);
5022
5023     if ((istk != NULL) && (istk->mmac_depth > 0)) {
5024                 ExpInv *ei = istk->expansion;
5025                 int lineno = ei->lineno;
5026                 while (ei != NULL) {
5027                         if (ei->type == EXP_MMACRO) {
5028                                 break;
5029                         }
5030                         lineno += ei->relno;
5031                         ei = ei->prev;
5032                 }
5033         nasm_error(severity, "(%s:%d) %s", ei->def->name,
5034                                    lineno, buff);
5035     } else {
5036         nasm_error(severity, "%s", buff);
5037         }
5038 }
5039
5040 /*
5041  * Since preprocessor always operate only on the line that didn't
5042  * arrived yet, we should always use ERR_OFFBY1.
5043  */
5044 static void error(int severity, const char *fmt, ...)
5045 {
5046     va_list arg;
5047     va_start(arg, fmt);
5048     verror(severity, fmt, arg);
5049     va_end(arg);
5050 }
5051
5052 /*
5053  * Because %else etc are evaluated in the state context
5054  * of the previous branch, errors might get lost with error():
5055  *   %if 0 ... %else trailing garbage ... %endif
5056  * So %else etc should report errors with this function.
5057  */
5058 static void error_precond(int severity, const char *fmt, ...)
5059 {
5060     va_list arg;
5061
5062     /* Only ignore the error if it's really in a dead branch */
5063         if ((istk != NULL) &&
5064                 (istk->expansion != NULL) &&
5065                 (istk->expansion->type == EXP_IF) &&
5066                 (istk->expansion->def->state == COND_NEVER))
5067         return;
5068
5069     va_start(arg, fmt);
5070     verror(severity, fmt, arg);
5071     va_end(arg);
5072 }
5073
5074 static void
5075 pp_reset(char *file, int apass, ListGen * listgen, StrList **deplist)
5076 {
5077     Token *t;
5078
5079     cstk = NULL;
5080     istk = nasm_malloc(sizeof(Include));
5081     istk->next = NULL;
5082     istk->expansion = NULL;
5083     istk->fp = fopen(file, "r");
5084     istk->fname = NULL;
5085     src_set_fname(nasm_strdup(file));
5086     src_set_linnum(0);
5087     istk->lineinc = 1;
5088         istk->mmac_depth = 0;
5089     if (!istk->fp)
5090         error(ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'",
5091               file);
5092     defining = NULL;
5093         finals = NULL;
5094         in_final = false;
5095     nested_mac_count = 0;
5096     nested_rep_count = 0;
5097     init_macros();
5098     unique = 0;
5099     if (tasm_compatible_mode) {
5100         stdmacpos = nasm_stdmac;
5101     } else {
5102         stdmacpos = nasm_stdmac_after_tasm;
5103     }
5104     any_extrastdmac = extrastdmac && *extrastdmac;
5105     do_predef = true;
5106     list = listgen;
5107
5108     /*
5109      * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
5110      * The caller, however, will also pass in 3 for preprocess-only so
5111      * we can set __PASS__ accordingly.
5112      */
5113     pass = apass > 2 ? 2 : apass;
5114
5115     dephead = deptail = deplist;
5116     if (deplist) {
5117         StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
5118         sl->next = NULL;
5119         strcpy(sl->str, file);
5120         *deptail = sl;
5121         deptail = &sl->next;
5122     }
5123
5124     /*
5125      * Define the __PASS__ macro.  This is defined here unlike
5126      * all the other builtins, because it is special -- it varies between
5127      * passes.
5128      */
5129     t = nasm_malloc(sizeof(*t));
5130     t->next = NULL;
5131     make_tok_num(t, apass);
5132     t->a.mac = NULL;
5133     define_smacro(NULL, "__PASS__", true, 0, t);
5134 }
5135
5136 static char *pp_getline(void)
5137 {
5138     char *line;
5139     Token *tline;
5140         ExpInv *ei;
5141         
5142     while (1) {
5143         /*
5144          * Fetch a tokenized line, either from the expansion
5145          * buffer or from the input file.
5146          */
5147         tline = NULL;
5148                 
5149         while (1) {             /* until we get a line we can use */
5150                         /*
5151                          * Fetch a tokenized line from the expansion buffer
5152                          */
5153             if (istk->expansion != NULL) {
5154                                 ei = istk->expansion;
5155                                 if (ei->current != NULL) {
5156                                         if (ei->emitting == false) {
5157                                                 ei->current = NULL;
5158                                                 continue;
5159                                         }
5160                                         Line *l = NULL;
5161                                         l = ei->current;
5162                                         ei->current = l->next;
5163                                         ei->lineno++;
5164                                         tline = copy_Token(l->first);
5165                                         if (((ei->type == EXP_REP) ||
5166                                                  (ei->type == EXP_MMACRO) ||
5167                                                  (ei->type == EXP_WHILE))
5168                                                 && (ei->def->nolist == false)) {
5169                                                 char *p = detoken(tline, false);
5170                                                 list->line(LIST_MACRO, p);
5171                                                 nasm_free(p);
5172                                         }
5173                                         if (ei->linnum > -1) {
5174                                                 src_set_linnum(src_get_linnum() + 1);
5175                                         }
5176                                         break;
5177                                 } else if ((ei->type == EXP_REP) &&
5178                                                    (ei->def->cur_depth < ei->def->max_depth)) {
5179                                         ei->def->cur_depth ++;
5180                                         ei->current = ei->def->line;
5181                                         ei->lineno = 0;
5182                                         continue;
5183                                 } else if ((ei->type == EXP_WHILE) &&
5184                                                    (ei->def->cur_depth < ei->def->max_depth)) {
5185                                         ei->current = ei->def->line;
5186                                         ei->lineno = 0;
5187                                         tline = copy_Token(ei->current->first);
5188                                         int j = if_condition(tline, PP_WHILE);
5189                                         tline = NULL;
5190                                         j = (((j < 0) ? COND_NEVER : j) ? COND_IF_TRUE : COND_IF_FALSE);
5191                                         if (j == COND_IF_TRUE) {
5192                                                 ei->current = ei->current->next;
5193                                                 ei->def->cur_depth ++;
5194                                         } else {
5195                                                 ei->emitting = false;
5196                                                 ei->current = NULL;
5197                                                 ei->def->cur_depth = ei->def->max_depth;
5198                                         }
5199                                         continue;
5200                                 } else {
5201                                         istk->expansion = ei->prev;
5202                                         ExpDef *ed = ei->def;
5203                                         if (ed != NULL) {
5204                                                 if ((ei->emitting == true) &&
5205                                                         (ed->max_depth == DEADMAN_LIMIT) &&
5206                                                         (ed->cur_depth == DEADMAN_LIMIT)
5207                                                         ) {
5208                                                         error(ERR_FATAL, "runaway expansion detected, aborting");
5209                                                 }
5210                                                 if (ed->cur_depth > 0) {
5211                                                         ed->cur_depth --;
5212                                                 } else if ((ed->type != EXP_MMACRO) && (ed->type != EXP_IF)) {
5213                                                         /***** should this really be right here??? *****/
5214                                                         /*      
5215                                                         Line *l = NULL, *ll = NULL;
5216                                                         for (l = ed->line; l != NULL;) {
5217                                                                 if (l->first != NULL) {
5218                                                                         free_tlist(l->first);
5219                                                                         l->first = NULL;
5220                                                                 }
5221                                                                 ll = l;
5222                                                                 l = l->next;
5223                                                                 nasm_free(ll);
5224                                                         }
5225                                                         expansions = ed->prev;
5226                                                         nasm_free(ed);
5227                                                          */
5228                                                 }
5229                                                 if ((ei->type == EXP_REP) ||
5230                                                         (ei->type == EXP_MMACRO) ||
5231                                                         (ei->type == EXP_WHILE)) {
5232                                                         list->downlevel(LIST_MACRO);
5233                                                         if (ei->type == EXP_MMACRO) {
5234                                                                 istk->mmac_depth--;
5235                                                         }
5236                                                 }
5237                                         }
5238                                         if (ei->linnum > -1) {
5239                                                 src_set_linnum(ei->linnum);
5240                                         }
5241                                         free_expinv(ei);
5242                                         continue;
5243                                 }
5244                         }
5245
5246                         /*
5247                          * Read in line from input and tokenize
5248                          */
5249             line = read_line();
5250             if (line) {         /* from the current input file */
5251                 line = prepreproc(line);
5252                 tline = tokenize(line);
5253                 nasm_free(line);
5254                 break;
5255             }
5256                         
5257             /*
5258              * The current file has ended; work down the istk
5259              */
5260             {
5261                 Include *i = istk;
5262                 fclose(i->fp);
5263                                 if (i->expansion != NULL) {
5264                                         error(ERR_FATAL,
5265                                                   "end of file while still in an expansion");
5266                                 }
5267                 /* only set line and file name if there's a next node */
5268                 if (i->next) {
5269                     src_set_linnum(i->lineno);
5270                     nasm_free(src_set_fname(i->fname));
5271                 }
5272                                 if ((i->next == NULL) && (finals != NULL)) {
5273                                         in_final = true;
5274                                         ei = new_ExpInv(EXP_FINAL, NULL);
5275                                         ei->emitting = true;
5276                                         ei->current = finals;
5277                                         istk->expansion = ei;
5278                                         finals = NULL;
5279                                         continue;
5280                                 }
5281                 istk = i->next;
5282                 list->downlevel(LIST_INCLUDE);
5283                 nasm_free(i);
5284                 if (istk == NULL) {
5285                                         if (finals != NULL) {
5286                                                 in_final = true;
5287                                         } else {
5288                                                 return NULL;
5289                                         }
5290                                 }
5291                                 continue;
5292             }
5293                 }
5294                         
5295                 if (defining == NULL) {
5296                         tline = expand_mmac_params(tline);
5297                 }
5298                 
5299         /*
5300          * Check the line to see if it's a preprocessor directive.
5301          */
5302         if (do_directive(tline) == DIRECTIVE_FOUND) {
5303             continue;
5304         } else if (defining != NULL) {
5305             /*
5306              * We're defining an expansion. We emit nothing at all,
5307                          * and just shove the tokenized line on to the definition.
5308              */
5309                         if (defining->ignoring == false) {
5310                                 Line *l = new_Line();
5311                                 l->first = tline;
5312                                 if (defining->line == NULL) {
5313                                         defining->line = l;
5314                                         defining->last = l;
5315                                 } else {
5316                                         defining->last->next = l;
5317                                         defining->last = l;
5318                                 }
5319                         } else {
5320                                 //free_tlist(tline);    /***** sanity check: is this supposed to be here? *****/
5321                         }
5322                         defining->linecount++;
5323             continue;
5324         } else if ((istk->expansion != NULL) &&
5325                                    (istk->expansion->emitting != true)) {
5326             /*
5327              * We're in a non-emitting branch of an expansion.
5328              * Emit nothing at all, not even a blank line: when we
5329              * emerge from the expansion we'll give a line-number
5330              * directive so we keep our place correctly.
5331              */
5332                         free_tlist(tline);
5333             continue;
5334         } else {
5335                         tline = expand_smacro(tline);
5336             if (expand_mmacro(tline) != true) {
5337                 /*
5338                  * De-tokenize the line again, and emit it.
5339                  */
5340                                 line = detoken(tline, true);
5341                                 free_tlist(tline);
5342                 break;
5343                         } else {
5344                                 continue;
5345                         }
5346         }
5347         }
5348         return line;
5349 }
5350
5351 static void pp_cleanup(int pass)
5352 {
5353     if (defining != NULL) {
5354                 error(ERR_NONFATAL, "end of file while still defining an expansion");
5355                 while (defining != NULL) {
5356                         ExpDef *ed = defining;
5357                         defining = ed->prev;
5358                         free_expdef(ed);
5359                 }
5360                 defining = NULL;
5361     }
5362     while (cstk != NULL)
5363         ctx_pop();
5364     free_macros();
5365     while (istk != NULL) {
5366         Include *i = istk;
5367         istk = istk->next;
5368         fclose(i->fp);
5369         nasm_free(i->fname);
5370         nasm_free(i);
5371                 while (i->expansion != NULL) {
5372                         ExpInv *ei = i->expansion;
5373                         i->expansion = ei->prev;
5374                         free_expinv(ei);
5375                 }
5376     }
5377     while (cstk)
5378         ctx_pop();
5379     nasm_free(src_set_fname(NULL));
5380     if (pass == 0) {
5381         IncPath *i;
5382         free_llist(predef);
5383         delete_Blocks();
5384         while ((i = ipath)) {
5385             ipath = i->next;
5386             if (i->path)
5387                 nasm_free(i->path);
5388             nasm_free(i);
5389         }
5390     }
5391 }
5392
5393 void pp_include_path(char *path)
5394 {
5395     IncPath *i;
5396
5397     i = nasm_malloc(sizeof(IncPath));
5398     i->path = path ? nasm_strdup(path) : NULL;
5399     i->next = NULL;
5400
5401     if (ipath) {
5402         IncPath *j = ipath;
5403         while (j->next)
5404             j = j->next;
5405         j->next = i;
5406     } else {
5407         ipath = i;
5408     }
5409 }
5410
5411 void pp_pre_include(char *fname)
5412 {
5413     Token *inc, *space, *name;
5414     Line *l;
5415
5416     name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
5417     space = new_Token(name, TOK_WHITESPACE, NULL, 0);
5418     inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
5419
5420     l = new_Line();
5421     l->next = predef;
5422     l->first = inc;
5423     predef = l;
5424 }
5425
5426 void pp_pre_define(char *definition)
5427 {
5428     Token *def, *space;
5429     Line *l;
5430     char *equals;
5431
5432     equals = strchr(definition, '=');
5433     space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
5434     def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
5435     if (equals)
5436         *equals = ' ';
5437     space->next = tokenize(definition);
5438     if (equals)
5439         *equals = '=';
5440
5441     l = new_Line();
5442     l->next = predef;
5443     l->first = def;
5444     predef = l;
5445 }
5446
5447 void pp_pre_undefine(char *definition)
5448 {
5449     Token *def, *space;
5450     Line *l;
5451
5452     space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
5453     def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
5454     space->next = tokenize(definition);
5455
5456     l = new_Line();
5457     l->next = predef;
5458     l->first = def;
5459     predef = l;
5460 }
5461
5462 /*
5463  * This function is used to assist with "runtime" preprocessor
5464  * directives, e.g. pp_runtime("%define __BITS__ 64");
5465  *
5466  * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5467  * PASS A VALID STRING TO THIS FUNCTION!!!!!
5468  */
5469
5470 void pp_runtime(char *definition)
5471 {
5472     Token *def;
5473
5474     def = tokenize(definition);
5475     if (do_directive(def) == NO_DIRECTIVE_FOUND)
5476         free_tlist(def);
5477
5478 }
5479
5480 void pp_extra_stdmac(macros_t *macros)
5481 {
5482     extrastdmac = macros;
5483 }
5484
5485 static void make_tok_num(Token * tok, int64_t val)
5486 {
5487     char numbuf[20];
5488     snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
5489     tok->text = nasm_strdup(numbuf);
5490     tok->type = TOK_NUMBER;
5491 }
5492
5493 Preproc nasmpp = {
5494     pp_reset,
5495     pp_getline,
5496     pp_cleanup
5497 };