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