eval: rexp3 should operate with 64bit numbers
[nasm/nasm.git] / preproc.c
blobdd52e1e13a4b7beb4dd706de36e14a50e7bb4bca
1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2010 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
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.
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.
32 * ----------------------------------------------------------------------- */
35 * preproc.c macro preprocessor for the Netwide Assembler
38 /* Typical flow of text through preproc
40 * pp_getline gets tokenized lines, either
42 * from a macro expansion
44 * or
45 * {
46 * read_line gets raw text from stdmacpos, or predef, or current input file
47 * tokenize converts to tokens
48 * }
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
54 * do_directive checks for directives
56 * expand_smacro is used to expand single line macros
58 * expand_mmacro is used to expand multi-line macros
60 * detoken is used to convert the line back to text
63 #include "compiler.h"
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>
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"
84 typedef struct SMacro SMacro;
85 typedef struct MMacro MMacro;
86 typedef struct MMacroInvocation MMacroInvocation;
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;
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.
105 * Store the definition of a single-line macro.
107 struct SMacro {
108 SMacro *next;
109 char *name;
110 bool casesense;
111 bool in_progress;
112 unsigned int nparam;
113 Token *expansion;
117 * Store the definition of a multi-line macro. This is also used to
118 * store the interiors of `%rep...%endrep' blocks, which are
119 * effectively self-re-invoking multi-line macros which simply
120 * don't have a name or bother to appear in the hash tables. %rep
121 * blocks are signified by having a NULL `name' field.
123 * In a MMacro describing a `%rep' block, the `in_progress' field
124 * isn't merely boolean, but gives the number of repeats left to
125 * run.
127 * The `next' field is used for storing MMacros in hash tables; the
128 * `next_active' field is for stacking them on istk entries.
130 * When a MMacro is being expanded, `params', `iline', `nparam',
131 * `paramlen', `rotate' and `unique' are local to the invocation.
133 struct MMacro {
134 MMacro *next;
135 MMacroInvocation *prev; /* previous invocation */
136 char *name;
137 int nparam_min, nparam_max;
138 bool casesense;
139 bool plus; /* is the last parameter greedy? */
140 bool nolist; /* is this macro listing-inhibited? */
141 int64_t in_progress; /* is this macro currently being expanded? */
142 int32_t max_depth; /* maximum number of recursive expansions allowed */
143 Token *dlist; /* All defaults as one list */
144 Token **defaults; /* Parameter default pointers */
145 int ndefs; /* number of default parameters */
146 Line *expansion;
148 MMacro *next_active;
149 MMacro *rep_nest; /* used for nesting %rep */
150 Token **params; /* actual parameters */
151 Token *iline; /* invocation line */
152 unsigned int nparam, rotate;
153 int *paramlen;
154 uint64_t unique;
155 int lineno; /* Current line number on expansion */
156 uint64_t condcnt; /* number of if blocks... */
160 /* Store the definition of a multi-line macro, as defined in a
161 * previous recursive macro expansion.
163 struct MMacroInvocation {
164 MMacroInvocation *prev; /* previous invocation */
165 Token **params; /* actual parameters */
166 Token *iline; /* invocation line */
167 unsigned int nparam, rotate;
168 int *paramlen;
169 uint64_t unique;
170 uint64_t condcnt;
175 * The context stack is composed of a linked list of these.
177 struct Context {
178 Context *next;
179 char *name;
180 struct hash_table localmac;
181 uint32_t number;
185 * This is the internal form which we break input lines up into.
186 * Typically stored in linked lists.
188 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
189 * necessarily used as-is, but is intended to denote the number of
190 * the substituted parameter. So in the definition
192 * %define a(x,y) ( (x) & ~(y) )
194 * the token representing `x' will have its type changed to
195 * TOK_SMAC_PARAM, but the one representing `y' will be
196 * TOK_SMAC_PARAM+1.
198 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
199 * which doesn't need quotes around it. Used in the pre-include
200 * mechanism as an alternative to trying to find a sensible type of
201 * quote to use on the filename we were passed.
203 enum pp_token_type {
204 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID,
205 TOK_PREPROC_ID, TOK_STRING,
206 TOK_NUMBER, TOK_FLOAT, TOK_SMAC_END, TOK_OTHER,
207 TOK_INTERNAL_STRING,
208 TOK_PREPROC_Q, TOK_PREPROC_QQ,
209 TOK_PASTE, /* %+ */
210 TOK_INDIRECT, /* %[...] */
211 TOK_SMAC_PARAM, /* MUST BE LAST IN THE LIST!!! */
212 TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
215 #define PP_CONCAT_MASK(x) (1 << (x))
217 struct tokseq_match {
218 int mask_head;
219 int mask_tail;
222 struct Token {
223 Token *next;
224 char *text;
225 union {
226 SMacro *mac; /* associated macro for TOK_SMAC_END */
227 size_t len; /* scratch length field */
228 } a; /* Auxiliary data */
229 enum pp_token_type type;
233 * Multi-line macro definitions are stored as a linked list of
234 * these, which is essentially a container to allow several linked
235 * lists of Tokens.
237 * Note that in this module, linked lists are treated as stacks
238 * wherever possible. For this reason, Lines are _pushed_ on to the
239 * `expansion' field in MMacro structures, so that the linked list,
240 * if walked, would give the macro lines in reverse order; this
241 * means that we can walk the list when expanding a macro, and thus
242 * push the lines on to the `expansion' field in _istk_ in reverse
243 * order (so that when popped back off they are in the right
244 * order). It may seem cockeyed, and it relies on my design having
245 * an even number of steps in, but it works...
247 * Some of these structures, rather than being actual lines, are
248 * markers delimiting the end of the expansion of a given macro.
249 * This is for use in the cycle-tracking and %rep-handling code.
250 * Such structures have `finishes' non-NULL, and `first' NULL. All
251 * others have `finishes' NULL, but `first' may still be NULL if
252 * the line is blank.
254 struct Line {
255 Line *next;
256 MMacro *finishes;
257 Token *first;
261 * To handle an arbitrary level of file inclusion, we maintain a
262 * stack (ie linked list) of these things.
264 struct Include {
265 Include *next;
266 FILE *fp;
267 Cond *conds;
268 Line *expansion;
269 char *fname;
270 int lineno, lineinc;
271 MMacro *mstk; /* stack of active macros/reps */
275 * Include search path. This is simply a list of strings which get
276 * prepended, in turn, to the name of an include file, in an
277 * attempt to find the file if it's not in the current directory.
279 struct IncPath {
280 IncPath *next;
281 char *path;
285 * Conditional assembly: we maintain a separate stack of these for
286 * each level of file inclusion. (The only reason we keep the
287 * stacks separate is to ensure that a stray `%endif' in a file
288 * included from within the true branch of a `%if' won't terminate
289 * it and cause confusion: instead, rightly, it'll cause an error.)
291 struct Cond {
292 Cond *next;
293 int state;
295 enum {
297 * These states are for use just after %if or %elif: IF_TRUE
298 * means the condition has evaluated to truth so we are
299 * currently emitting, whereas IF_FALSE means we are not
300 * currently emitting but will start doing so if a %else comes
301 * up. In these states, all directives are admissible: %elif,
302 * %else and %endif. (And of course %if.)
304 COND_IF_TRUE, COND_IF_FALSE,
306 * These states come up after a %else: ELSE_TRUE means we're
307 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
308 * any %elif or %else will cause an error.
310 COND_ELSE_TRUE, COND_ELSE_FALSE,
312 * These states mean that we're not emitting now, and also that
313 * nothing until %endif will be emitted at all. COND_DONE is
314 * used when we've had our moment of emission
315 * and have now started seeing %elifs. COND_NEVER is used when
316 * the condition construct in question is contained within a
317 * non-emitting branch of a larger condition construct,
318 * or if there is an error.
320 COND_DONE, COND_NEVER
322 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
325 * These defines are used as the possible return values for do_directive
327 #define NO_DIRECTIVE_FOUND 0
328 #define DIRECTIVE_FOUND 1
331 * This define sets the upper limit for smacro and recursive mmacro
332 * expansions
334 #define DEADMAN_LIMIT (1 << 20)
336 /* max reps */
337 #define REP_LIMIT ((INT64_C(1) << 62))
340 * Condition codes. Note that we use c_ prefix not C_ because C_ is
341 * used in nasm.h for the "real" condition codes. At _this_ level,
342 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
343 * ones, so we need a different enum...
345 static const char * const conditions[] = {
346 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
347 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
348 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
350 enum pp_conds {
351 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
352 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
353 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
354 c_none = -1
356 static const enum pp_conds inverse_ccs[] = {
357 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
358 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,
359 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
363 * Directive names.
365 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
366 static int is_condition(enum preproc_token arg)
368 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
371 /* For TASM compatibility we need to be able to recognise TASM compatible
372 * conditional compilation directives. Using the NASM pre-processor does
373 * not work, so we look for them specifically from the following list and
374 * then jam in the equivalent NASM directive into the input stream.
377 enum {
378 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
379 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
382 static const char * const tasm_directives[] = {
383 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
384 "ifndef", "include", "local"
387 static int StackSize = 4;
388 static char *StackPointer = "ebp";
389 static int ArgOffset = 8;
390 static int LocalOffset = 0;
392 static Context *cstk;
393 static Include *istk;
394 static IncPath *ipath = NULL;
396 static int pass; /* HACK: pass 0 = generate dependencies only */
397 static StrList **dephead, **deptail; /* Dependency list */
399 static uint64_t unique; /* unique identifier numbers */
401 static Line *predef = NULL;
402 static bool do_predef;
404 static ListGen *list;
407 * The current set of multi-line macros we have defined.
409 static struct hash_table mmacros;
412 * The current set of single-line macros we have defined.
414 static struct hash_table smacros;
417 * The multi-line macro we are currently defining, or the %rep
418 * block we are currently reading, if any.
420 static MMacro *defining;
422 static uint64_t nested_mac_count;
423 static uint64_t nested_rep_count;
426 * The number of macro parameters to allocate space for at a time.
428 #define PARAM_DELTA 16
431 * The standard macro set: defined in macros.c in the array nasm_stdmac.
432 * This gives our position in the macro set, when we're processing it.
434 static macros_t *stdmacpos;
437 * The extra standard macros that come from the object format, if
438 * any.
440 static macros_t *extrastdmac = NULL;
441 static bool any_extrastdmac;
444 * Tokens are allocated in blocks to improve speed
446 #define TOKEN_BLOCKSIZE 4096
447 static Token *freeTokens = NULL;
448 struct Blocks {
449 Blocks *next;
450 void *chunk;
453 static Blocks blocks = { NULL, NULL };
456 * Forward declarations.
458 static Token *expand_mmac_params(Token * tline);
459 static Token *expand_smacro(Token * tline);
460 static Token *expand_id(Token * tline);
461 static Context *get_ctx(const char *name, const char **namep,
462 bool all_contexts);
463 static void make_tok_num(Token * tok, int64_t val);
464 static void error(int severity, const char *fmt, ...);
465 static void error_precond(int severity, const char *fmt, ...);
466 static void *new_Block(size_t size);
467 static void delete_Blocks(void);
468 static Token *new_Token(Token * next, enum pp_token_type type,
469 const char *text, int txtlen);
470 static Token *delete_Token(Token * t);
473 * Macros for safe checking of token pointers, avoid *(NULL)
475 #define tok_type_(x,t) ((x) && (x)->type == (t))
476 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
477 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
478 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
481 * nasm_unquote with error if the string contains NUL characters.
482 * If the string contains NUL characters, issue an error and return
483 * the C len, i.e. truncate at the NUL.
485 static size_t nasm_unquote_cstr(char *qstr, enum preproc_token directive)
487 size_t len = nasm_unquote(qstr, NULL);
488 size_t clen = strlen(qstr);
490 if (len != clen)
491 error(ERR_NONFATAL, "NUL character in `%s' directive",
492 pp_directives[directive]);
494 return clen;
498 * In-place reverse a list of tokens.
500 static Token *reverse_tokens(Token *t)
502 Token *prev = NULL;
503 Token *next;
505 while (t) {
506 next = t->next;
507 t->next = prev;
508 prev = t;
509 t = next;
512 return prev;
516 * Handle TASM specific directives, which do not contain a % in
517 * front of them. We do it here because I could not find any other
518 * place to do it for the moment, and it is a hack (ideally it would
519 * be nice to be able to use the NASM pre-processor to do it).
521 static char *check_tasm_directive(char *line)
523 int32_t i, j, k, m, len;
524 char *p, *q, *oldline, oldchar;
526 p = nasm_skip_spaces(line);
528 /* Binary search for the directive name */
529 i = -1;
530 j = ARRAY_SIZE(tasm_directives);
531 q = nasm_skip_word(p);
532 len = q - p;
533 if (len) {
534 oldchar = p[len];
535 p[len] = 0;
536 while (j - i > 1) {
537 k = (j + i) / 2;
538 m = nasm_stricmp(p, tasm_directives[k]);
539 if (m == 0) {
540 /* We have found a directive, so jam a % in front of it
541 * so that NASM will then recognise it as one if it's own.
543 p[len] = oldchar;
544 len = strlen(p);
545 oldline = line;
546 line = nasm_malloc(len + 2);
547 line[0] = '%';
548 if (k == TM_IFDIFI) {
550 * NASM does not recognise IFDIFI, so we convert
551 * it to %if 0. This is not used in NASM
552 * compatible code, but does need to parse for the
553 * TASM macro package.
555 strcpy(line + 1, "if 0");
556 } else {
557 memcpy(line + 1, p, len + 1);
559 nasm_free(oldline);
560 return line;
561 } else if (m < 0) {
562 j = k;
563 } else
564 i = k;
566 p[len] = oldchar;
568 return line;
572 * The pre-preprocessing stage... This function translates line
573 * number indications as they emerge from GNU cpp (`# lineno "file"
574 * flags') into NASM preprocessor line number indications (`%line
575 * lineno file').
577 static char *prepreproc(char *line)
579 int lineno, fnlen;
580 char *fname, *oldline;
582 if (line[0] == '#' && line[1] == ' ') {
583 oldline = line;
584 fname = oldline + 2;
585 lineno = atoi(fname);
586 fname += strspn(fname, "0123456789 ");
587 if (*fname == '"')
588 fname++;
589 fnlen = strcspn(fname, "\"");
590 line = nasm_malloc(20 + fnlen);
591 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
592 nasm_free(oldline);
594 if (tasm_compatible_mode)
595 return check_tasm_directive(line);
596 return line;
600 * Free a linked list of tokens.
602 static void free_tlist(Token * list)
604 while (list)
605 list = delete_Token(list);
609 * Free a linked list of lines.
611 static void free_llist(Line * list)
613 Line *l, *tmp;
614 list_for_each_safe(l, tmp, list) {
615 free_tlist(l->first);
616 nasm_free(l);
621 * Free an MMacro
623 static void free_mmacro(MMacro * m)
625 nasm_free(m->name);
626 free_tlist(m->dlist);
627 nasm_free(m->defaults);
628 free_llist(m->expansion);
629 nasm_free(m);
633 * Free all currently defined macros, and free the hash tables
635 static void free_smacro_table(struct hash_table *smt)
637 SMacro *s, *tmp;
638 const char *key;
639 struct hash_tbl_node *it = NULL;
641 while ((s = hash_iterate(smt, &it, &key)) != NULL) {
642 nasm_free((void *)key);
643 list_for_each_safe(s, tmp, s) {
644 nasm_free(s->name);
645 free_tlist(s->expansion);
646 nasm_free(s);
649 hash_free(smt);
652 static void free_mmacro_table(struct hash_table *mmt)
654 MMacro *m, *tmp;
655 const char *key;
656 struct hash_tbl_node *it = NULL;
658 it = NULL;
659 while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
660 nasm_free((void *)key);
661 list_for_each_safe(m ,tmp, m)
662 free_mmacro(m);
664 hash_free(mmt);
667 static void free_macros(void)
669 free_smacro_table(&smacros);
670 free_mmacro_table(&mmacros);
674 * Initialize the hash tables
676 static void init_macros(void)
678 hash_init(&smacros, HASH_LARGE);
679 hash_init(&mmacros, HASH_LARGE);
683 * Pop the context stack.
685 static void ctx_pop(void)
687 Context *c = cstk;
689 cstk = cstk->next;
690 free_smacro_table(&c->localmac);
691 nasm_free(c->name);
692 nasm_free(c);
696 * Search for a key in the hash index; adding it if necessary
697 * (in which case we initialize the data pointer to NULL.)
699 static void **
700 hash_findi_add(struct hash_table *hash, const char *str)
702 struct hash_insert hi;
703 void **r;
704 char *strx;
706 r = hash_findi(hash, str, &hi);
707 if (r)
708 return r;
710 strx = nasm_strdup(str); /* Use a more efficient allocator here? */
711 return hash_add(&hi, strx, NULL);
715 * Like hash_findi, but returns the data element rather than a pointer
716 * to it. Used only when not adding a new element, hence no third
717 * argument.
719 static void *
720 hash_findix(struct hash_table *hash, const char *str)
722 void **p;
724 p = hash_findi(hash, str, NULL);
725 return p ? *p : NULL;
729 * read line from standart macros set,
730 * if there no more left -- return NULL
732 static char *line_from_stdmac(void)
734 unsigned char c;
735 const unsigned char *p = stdmacpos;
736 char *line, *q;
737 size_t len = 0;
739 if (!stdmacpos)
740 return NULL;
742 while ((c = *p++)) {
743 if (c >= 0x80)
744 len += pp_directives_len[c - 0x80] + 1;
745 else
746 len++;
749 line = nasm_malloc(len + 1);
750 q = line;
751 while ((c = *stdmacpos++)) {
752 if (c >= 0x80) {
753 memcpy(q, pp_directives[c - 0x80], pp_directives_len[c - 0x80]);
754 q += pp_directives_len[c - 0x80];
755 *q++ = ' ';
756 } else {
757 *q++ = c;
760 stdmacpos = p;
761 *q = '\0';
763 if (!*stdmacpos) {
764 /* This was the last of the standard macro chain... */
765 stdmacpos = NULL;
766 if (any_extrastdmac) {
767 stdmacpos = extrastdmac;
768 any_extrastdmac = false;
769 } else if (do_predef) {
770 Line *pd, *l;
771 Token *head, **tail, *t;
774 * Nasty hack: here we push the contents of
775 * `predef' on to the top-level expansion stack,
776 * since this is the most convenient way to
777 * implement the pre-include and pre-define
778 * features.
780 list_for_each(pd, predef) {
781 head = NULL;
782 tail = &head;
783 list_for_each(t, pd->first) {
784 *tail = new_Token(NULL, t->type, t->text, 0);
785 tail = &(*tail)->next;
788 l = nasm_malloc(sizeof(Line));
789 l->next = istk->expansion;
790 l->first = head;
791 l->finishes = NULL;
793 istk->expansion = l;
795 do_predef = false;
799 return line;
802 #define BUF_DELTA 512
804 * Read a line from the top file in istk, handling multiple CR/LFs
805 * at the end of the line read, and handling spurious ^Zs. Will
806 * return lines from the standard macro set if this has not already
807 * been done.
809 static char *read_line(void)
811 char *buffer, *p, *q;
812 int bufsize, continued_count;
815 * standart macros set (predefined) goes first
817 p = line_from_stdmac();
818 if (p)
819 return p;
822 * regular read from a file
824 bufsize = BUF_DELTA;
825 buffer = nasm_malloc(BUF_DELTA);
826 p = buffer;
827 continued_count = 0;
828 while (1) {
829 q = fgets(p, bufsize - (p - buffer), istk->fp);
830 if (!q)
831 break;
832 p += strlen(p);
833 if (p > buffer && p[-1] == '\n') {
835 * Convert backslash-CRLF line continuation sequences into
836 * nothing at all (for DOS and Windows)
838 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
839 p -= 3;
840 *p = 0;
841 continued_count++;
844 * Also convert backslash-LF line continuation sequences into
845 * nothing at all (for Unix)
847 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
848 p -= 2;
849 *p = 0;
850 continued_count++;
851 } else {
852 break;
855 if (p - buffer > bufsize - 10) {
856 int32_t offset = p - buffer;
857 bufsize += BUF_DELTA;
858 buffer = nasm_realloc(buffer, bufsize);
859 p = buffer + offset; /* prevent stale-pointer problems */
863 if (!q && p == buffer) {
864 nasm_free(buffer);
865 return NULL;
868 src_set_linnum(src_get_linnum() + istk->lineinc +
869 (continued_count * istk->lineinc));
872 * Play safe: remove CRs as well as LFs, if any of either are
873 * present at the end of the line.
875 while (--p >= buffer && (*p == '\n' || *p == '\r'))
876 *p = '\0';
879 * Handle spurious ^Z, which may be inserted into source files
880 * by some file transfer utilities.
882 buffer[strcspn(buffer, "\032")] = '\0';
884 list->line(LIST_READ, buffer);
886 return buffer;
890 * Tokenize a line of text. This is a very simple process since we
891 * don't need to parse the value out of e.g. numeric tokens: we
892 * simply split one string into many.
894 static Token *tokenize(char *line)
896 char c, *p = line;
897 enum pp_token_type type;
898 Token *list = NULL;
899 Token *t, **tail = &list;
901 while (*line) {
902 p = line;
903 if (*p == '%') {
904 p++;
905 if (*p == '+' && !nasm_isdigit(p[1])) {
906 p++;
907 type = TOK_PASTE;
908 } else if (nasm_isdigit(*p) ||
909 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
910 do {
911 p++;
913 while (nasm_isdigit(*p));
914 type = TOK_PREPROC_ID;
915 } else if (*p == '{') {
916 p++;
917 while (*p) {
918 if (*p == '}')
919 break;
920 p[-1] = *p;
921 p++;
923 if (*p != '}')
924 error(ERR_WARNING | ERR_PASS1, "unterminated %{ construct");
925 p[-1] = '\0';
926 if (*p)
927 p++;
928 type = TOK_PREPROC_ID;
929 } else if (*p == '[') {
930 int lvl = 1;
931 line += 2; /* Skip the leading %[ */
932 p++;
933 while (lvl && (c = *p++)) {
934 switch (c) {
935 case ']':
936 lvl--;
937 break;
938 case '%':
939 if (*p == '[')
940 lvl++;
941 break;
942 case '\'':
943 case '\"':
944 case '`':
945 p = nasm_skip_string(p - 1) + 1;
946 break;
947 default:
948 break;
951 p--;
952 if (*p)
953 *p++ = '\0';
954 if (lvl)
955 error(ERR_NONFATAL, "unterminated %[ construct");
956 type = TOK_INDIRECT;
957 } else if (*p == '?') {
958 type = TOK_PREPROC_Q; /* %? */
959 p++;
960 if (*p == '?') {
961 type = TOK_PREPROC_QQ; /* %?? */
962 p++;
964 } else if (*p == '!') {
965 type = TOK_PREPROC_ID;
966 p++;
967 if (isidchar(*p)) {
968 do {
969 p++;
970 } while (isidchar(*p));
971 } else if (*p == '\'' || *p == '\"' || *p == '`') {
972 p = nasm_skip_string(p);
973 if (*p)
974 p++;
975 else
976 error(ERR_NONFATAL|ERR_PASS1, "unterminated %! string");
977 } else {
978 /* %! without string or identifier */
979 type = TOK_OTHER; /* Legacy behavior... */
981 } else if (isidchar(*p) ||
982 ((*p == '!' || *p == '%' || *p == '$') &&
983 isidchar(p[1]))) {
984 do {
985 p++;
987 while (isidchar(*p));
988 type = TOK_PREPROC_ID;
989 } else {
990 type = TOK_OTHER;
991 if (*p == '%')
992 p++;
994 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
995 type = TOK_ID;
996 p++;
997 while (*p && isidchar(*p))
998 p++;
999 } else if (*p == '\'' || *p == '"' || *p == '`') {
1001 * A string token.
1003 type = TOK_STRING;
1004 p = nasm_skip_string(p);
1006 if (*p) {
1007 p++;
1008 } else {
1009 error(ERR_WARNING|ERR_PASS1, "unterminated string");
1010 /* Handling unterminated strings by UNV */
1011 /* type = -1; */
1013 } else if (p[0] == '$' && p[1] == '$') {
1014 type = TOK_OTHER; /* TOKEN_BASE */
1015 p += 2;
1016 } else if (isnumstart(*p)) {
1017 bool is_hex = false;
1018 bool is_float = false;
1019 bool has_e = false;
1020 char c, *r;
1023 * A numeric token.
1026 if (*p == '$') {
1027 p++;
1028 is_hex = true;
1031 for (;;) {
1032 c = *p++;
1034 if (!is_hex && (c == 'e' || c == 'E')) {
1035 has_e = true;
1036 if (*p == '+' || *p == '-') {
1038 * e can only be followed by +/- if it is either a
1039 * prefixed hex number or a floating-point number
1041 p++;
1042 is_float = true;
1044 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
1045 is_hex = true;
1046 } else if (c == 'P' || c == 'p') {
1047 is_float = true;
1048 if (*p == '+' || *p == '-')
1049 p++;
1050 } else if (isnumchar(c) || c == '_')
1051 ; /* just advance */
1052 else if (c == '.') {
1054 * we need to deal with consequences of the legacy
1055 * parser, like "1.nolist" being two tokens
1056 * (TOK_NUMBER, TOK_ID) here; at least give it
1057 * a shot for now. In the future, we probably need
1058 * a flex-based scanner with proper pattern matching
1059 * to do it as well as it can be done. Nothing in
1060 * the world is going to help the person who wants
1061 * 0x123.p16 interpreted as two tokens, though.
1063 r = p;
1064 while (*r == '_')
1065 r++;
1067 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
1068 (!is_hex && (*r == 'e' || *r == 'E')) ||
1069 (*r == 'p' || *r == 'P')) {
1070 p = r;
1071 is_float = true;
1072 } else
1073 break; /* Terminate the token */
1074 } else
1075 break;
1077 p--; /* Point to first character beyond number */
1079 if (p == line+1 && *line == '$') {
1080 type = TOK_OTHER; /* TOKEN_HERE */
1081 } else {
1082 if (has_e && !is_hex) {
1083 /* 1e13 is floating-point, but 1e13h is not */
1084 is_float = true;
1087 type = is_float ? TOK_FLOAT : TOK_NUMBER;
1089 } else if (nasm_isspace(*p)) {
1090 type = TOK_WHITESPACE;
1091 p = nasm_skip_spaces(p);
1093 * Whitespace just before end-of-line is discarded by
1094 * pretending it's a comment; whitespace just before a
1095 * comment gets lumped into the comment.
1097 if (!*p || *p == ';') {
1098 type = TOK_COMMENT;
1099 while (*p)
1100 p++;
1102 } else if (*p == ';') {
1103 type = TOK_COMMENT;
1104 while (*p)
1105 p++;
1106 } else {
1108 * Anything else is an operator of some kind. We check
1109 * for all the double-character operators (>>, <<, //,
1110 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1111 * else is a single-character operator.
1113 type = TOK_OTHER;
1114 if ((p[0] == '>' && p[1] == '>') ||
1115 (p[0] == '<' && p[1] == '<') ||
1116 (p[0] == '/' && p[1] == '/') ||
1117 (p[0] == '<' && p[1] == '=') ||
1118 (p[0] == '>' && p[1] == '=') ||
1119 (p[0] == '=' && p[1] == '=') ||
1120 (p[0] == '!' && p[1] == '=') ||
1121 (p[0] == '<' && p[1] == '>') ||
1122 (p[0] == '&' && p[1] == '&') ||
1123 (p[0] == '|' && p[1] == '|') ||
1124 (p[0] == '^' && p[1] == '^')) {
1125 p++;
1127 p++;
1130 /* Handling unterminated string by UNV */
1131 /*if (type == -1)
1133 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1134 t->text[p-line] = *line;
1135 tail = &t->next;
1137 else */
1138 if (type != TOK_COMMENT) {
1139 *tail = t = new_Token(NULL, type, line, p - line);
1140 tail = &t->next;
1142 line = p;
1144 return list;
1148 * this function allocates a new managed block of memory and
1149 * returns a pointer to the block. The managed blocks are
1150 * deleted only all at once by the delete_Blocks function.
1152 static void *new_Block(size_t size)
1154 Blocks *b = &blocks;
1156 /* first, get to the end of the linked list */
1157 while (b->next)
1158 b = b->next;
1159 /* now allocate the requested chunk */
1160 b->chunk = nasm_malloc(size);
1162 /* now allocate a new block for the next request */
1163 b->next = nasm_malloc(sizeof(Blocks));
1164 /* and initialize the contents of the new block */
1165 b->next->next = NULL;
1166 b->next->chunk = NULL;
1167 return b->chunk;
1171 * this function deletes all managed blocks of memory
1173 static void delete_Blocks(void)
1175 Blocks *a, *b = &blocks;
1178 * keep in mind that the first block, pointed to by blocks
1179 * is a static and not dynamically allocated, so we don't
1180 * free it.
1182 while (b) {
1183 if (b->chunk)
1184 nasm_free(b->chunk);
1185 a = b;
1186 b = b->next;
1187 if (a != &blocks)
1188 nasm_free(a);
1193 * this function creates a new Token and passes a pointer to it
1194 * back to the caller. It sets the type and text elements, and
1195 * also the a.mac and next elements to NULL.
1197 static Token *new_Token(Token * next, enum pp_token_type type,
1198 const char *text, int txtlen)
1200 Token *t;
1201 int i;
1203 if (!freeTokens) {
1204 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
1205 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
1206 freeTokens[i].next = &freeTokens[i + 1];
1207 freeTokens[i].next = NULL;
1209 t = freeTokens;
1210 freeTokens = t->next;
1211 t->next = next;
1212 t->a.mac = NULL;
1213 t->type = type;
1214 if (type == TOK_WHITESPACE || !text) {
1215 t->text = NULL;
1216 } else {
1217 if (txtlen == 0)
1218 txtlen = strlen(text);
1219 t->text = nasm_malloc(txtlen+1);
1220 memcpy(t->text, text, txtlen);
1221 t->text[txtlen] = '\0';
1223 return t;
1226 static Token *delete_Token(Token * t)
1228 Token *next = t->next;
1229 nasm_free(t->text);
1230 t->next = freeTokens;
1231 freeTokens = t;
1232 return next;
1236 * Convert a line of tokens back into text.
1237 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1238 * will be transformed into ..@ctxnum.xxx
1240 static char *detoken(Token * tlist, bool expand_locals)
1242 Token *t;
1243 char *line, *p;
1244 const char *q;
1245 int len = 0;
1247 list_for_each(t, tlist) {
1248 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
1249 char *v;
1250 char *q = t->text;
1252 v = t->text + 2;
1253 if (*v == '\'' || *v == '\"' || *v == '`') {
1254 size_t len = nasm_unquote(v, NULL);
1255 size_t clen = strlen(v);
1257 if (len != clen) {
1258 error(ERR_NONFATAL | ERR_PASS1,
1259 "NUL character in %! string");
1260 v = NULL;
1264 if (v) {
1265 char *p = getenv(v);
1266 if (!p) {
1267 error(ERR_NONFATAL | ERR_PASS1,
1268 "nonexistent environment variable `%s'", v);
1269 p = "";
1271 t->text = nasm_strdup(p);
1273 nasm_free(q);
1276 /* Expand local macros here and not during preprocessing */
1277 if (expand_locals &&
1278 t->type == TOK_PREPROC_ID && t->text &&
1279 t->text[0] == '%' && t->text[1] == '$') {
1280 const char *q;
1281 char *p;
1282 Context *ctx = get_ctx(t->text, &q, false);
1283 if (ctx) {
1284 char buffer[40];
1285 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
1286 p = nasm_strcat(buffer, q);
1287 nasm_free(t->text);
1288 t->text = p;
1291 if (t->type == TOK_WHITESPACE)
1292 len++;
1293 else if (t->text)
1294 len += strlen(t->text);
1297 p = line = nasm_malloc(len + 1);
1299 list_for_each(t, tlist) {
1300 if (t->type == TOK_WHITESPACE) {
1301 *p++ = ' ';
1302 } else if (t->text) {
1303 q = t->text;
1304 while (*q)
1305 *p++ = *q++;
1308 *p = '\0';
1310 return line;
1314 * A scanner, suitable for use by the expression evaluator, which
1315 * operates on a line of Tokens. Expects a pointer to a pointer to
1316 * the first token in the line to be passed in as its private_data
1317 * field.
1319 * FIX: This really needs to be unified with stdscan.
1321 static int ppscan(void *private_data, struct tokenval *tokval)
1323 Token **tlineptr = private_data;
1324 Token *tline;
1325 char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
1327 do {
1328 tline = *tlineptr;
1329 *tlineptr = tline ? tline->next : NULL;
1330 } while (tline && (tline->type == TOK_WHITESPACE ||
1331 tline->type == TOK_COMMENT));
1333 if (!tline)
1334 return tokval->t_type = TOKEN_EOS;
1336 tokval->t_charptr = tline->text;
1338 if (tline->text[0] == '$' && !tline->text[1])
1339 return tokval->t_type = TOKEN_HERE;
1340 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
1341 return tokval->t_type = TOKEN_BASE;
1343 if (tline->type == TOK_ID) {
1344 p = tokval->t_charptr = tline->text;
1345 if (p[0] == '$') {
1346 tokval->t_charptr++;
1347 return tokval->t_type = TOKEN_ID;
1350 for (r = p, s = ourcopy; *r; r++) {
1351 if (r >= p+MAX_KEYWORD)
1352 return tokval->t_type = TOKEN_ID; /* Not a keyword */
1353 *s++ = nasm_tolower(*r);
1355 *s = '\0';
1356 /* right, so we have an identifier sitting in temp storage. now,
1357 * is it actually a register or instruction name, or what? */
1358 return nasm_token_hash(ourcopy, tokval);
1361 if (tline->type == TOK_NUMBER) {
1362 bool rn_error;
1363 tokval->t_integer = readnum(tline->text, &rn_error);
1364 tokval->t_charptr = tline->text;
1365 if (rn_error)
1366 return tokval->t_type = TOKEN_ERRNUM;
1367 else
1368 return tokval->t_type = TOKEN_NUM;
1371 if (tline->type == TOK_FLOAT) {
1372 return tokval->t_type = TOKEN_FLOAT;
1375 if (tline->type == TOK_STRING) {
1376 char bq, *ep;
1378 bq = tline->text[0];
1379 tokval->t_charptr = tline->text;
1380 tokval->t_inttwo = nasm_unquote(tline->text, &ep);
1382 if (ep[0] != bq || ep[1] != '\0')
1383 return tokval->t_type = TOKEN_ERRSTR;
1384 else
1385 return tokval->t_type = TOKEN_STR;
1388 if (tline->type == TOK_OTHER) {
1389 if (!strcmp(tline->text, "<<"))
1390 return tokval->t_type = TOKEN_SHL;
1391 if (!strcmp(tline->text, ">>"))
1392 return tokval->t_type = TOKEN_SHR;
1393 if (!strcmp(tline->text, "//"))
1394 return tokval->t_type = TOKEN_SDIV;
1395 if (!strcmp(tline->text, "%%"))
1396 return tokval->t_type = TOKEN_SMOD;
1397 if (!strcmp(tline->text, "=="))
1398 return tokval->t_type = TOKEN_EQ;
1399 if (!strcmp(tline->text, "<>"))
1400 return tokval->t_type = TOKEN_NE;
1401 if (!strcmp(tline->text, "!="))
1402 return tokval->t_type = TOKEN_NE;
1403 if (!strcmp(tline->text, "<="))
1404 return tokval->t_type = TOKEN_LE;
1405 if (!strcmp(tline->text, ">="))
1406 return tokval->t_type = TOKEN_GE;
1407 if (!strcmp(tline->text, "&&"))
1408 return tokval->t_type = TOKEN_DBL_AND;
1409 if (!strcmp(tline->text, "^^"))
1410 return tokval->t_type = TOKEN_DBL_XOR;
1411 if (!strcmp(tline->text, "||"))
1412 return tokval->t_type = TOKEN_DBL_OR;
1416 * We have no other options: just return the first character of
1417 * the token text.
1419 return tokval->t_type = tline->text[0];
1423 * Compare a string to the name of an existing macro; this is a
1424 * simple wrapper which calls either strcmp or nasm_stricmp
1425 * depending on the value of the `casesense' parameter.
1427 static int mstrcmp(const char *p, const char *q, bool casesense)
1429 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
1433 * Compare a string to the name of an existing macro; this is a
1434 * simple wrapper which calls either strcmp or nasm_stricmp
1435 * depending on the value of the `casesense' parameter.
1437 static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
1439 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
1443 * Return the Context structure associated with a %$ token. Return
1444 * NULL, having _already_ reported an error condition, if the
1445 * context stack isn't deep enough for the supplied number of $
1446 * signs.
1447 * If all_contexts == true, contexts that enclose current are
1448 * also scanned for such smacro, until it is found; if not -
1449 * only the context that directly results from the number of $'s
1450 * in variable's name.
1452 * If "namep" is non-NULL, set it to the pointer to the macro name
1453 * tail, i.e. the part beyond %$...
1455 static Context *get_ctx(const char *name, const char **namep,
1456 bool all_contexts)
1458 Context *ctx;
1459 SMacro *m;
1460 int i;
1462 if (namep)
1463 *namep = name;
1465 if (!name || name[0] != '%' || name[1] != '$')
1466 return NULL;
1468 if (!cstk) {
1469 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1470 return NULL;
1473 name += 2;
1474 ctx = cstk;
1475 i = 0;
1476 while (ctx && *name == '$') {
1477 name++;
1478 i++;
1479 ctx = ctx->next;
1481 if (!ctx) {
1482 error(ERR_NONFATAL, "`%s': context stack is only"
1483 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
1484 return NULL;
1487 if (namep)
1488 *namep = name;
1490 if (!all_contexts)
1491 return ctx;
1494 * NOTE: In 2.10 we will not need lookup in extarnal
1495 * contexts, so this is a gentle way to inform users
1496 * about their source code need to be updated
1499 /* first round -- check the current context */
1500 m = hash_findix(&ctx->localmac, name);
1501 while (m) {
1502 if (!mstrcmp(m->name, name, m->casesense))
1503 return ctx;
1504 m = m->next;
1507 /* second round - external contexts */
1508 while ((ctx = ctx->next)) {
1509 /* Search for this smacro in found context */
1510 m = hash_findix(&ctx->localmac, name);
1511 while (m) {
1512 if (!mstrcmp(m->name, name, m->casesense)) {
1513 /* NOTE: deprecated as of 2.10 */
1514 static int once = 0;
1515 if (!once) {
1516 error(ERR_WARNING, "context-local macro expansion"
1517 " fall-through (automatic searching of outer"
1518 " contexts) will be deprecated starting in"
1519 " NASM 2.10, please see the NASM Manual for"
1520 " more information");
1521 once = 1;
1523 error(ERR_WARNING, "`%s': context-local macro expansion fall-through", name);
1524 return ctx;
1526 m = m->next;
1530 return NULL;
1534 * Check to see if a file is already in a string list
1536 static bool in_list(const StrList *list, const char *str)
1538 while (list) {
1539 if (!strcmp(list->str, str))
1540 return true;
1541 list = list->next;
1543 return false;
1547 * Open an include file. This routine must always return a valid
1548 * file pointer if it returns - it's responsible for throwing an
1549 * ERR_FATAL and bombing out completely if not. It should also try
1550 * the include path one by one until it finds the file or reaches
1551 * the end of the path.
1553 static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
1554 bool missing_ok)
1556 FILE *fp;
1557 char *prefix = "";
1558 IncPath *ip = ipath;
1559 int len = strlen(file);
1560 size_t prefix_len = 0;
1561 StrList *sl;
1563 while (1) {
1564 sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
1565 memcpy(sl->str, prefix, prefix_len);
1566 memcpy(sl->str+prefix_len, file, len+1);
1567 fp = fopen(sl->str, "r");
1568 if (fp && dhead && !in_list(*dhead, sl->str)) {
1569 sl->next = NULL;
1570 **dtail = sl;
1571 *dtail = &sl->next;
1572 } else {
1573 nasm_free(sl);
1575 if (fp)
1576 return fp;
1577 if (!ip) {
1578 if (!missing_ok)
1579 break;
1580 prefix = NULL;
1581 } else {
1582 prefix = ip->path;
1583 ip = ip->next;
1585 if (prefix) {
1586 prefix_len = strlen(prefix);
1587 } else {
1588 /* -MG given and file not found */
1589 if (dhead && !in_list(*dhead, file)) {
1590 sl = nasm_malloc(len+1+sizeof sl->next);
1591 sl->next = NULL;
1592 strcpy(sl->str, file);
1593 **dtail = sl;
1594 *dtail = &sl->next;
1596 return NULL;
1600 error(ERR_FATAL, "unable to open include file `%s'", file);
1601 return NULL;
1605 * Determine if we should warn on defining a single-line macro of
1606 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1607 * return true if _any_ single-line macro of that name is defined.
1608 * Otherwise, will return true if a single-line macro with either
1609 * `nparam' or no parameters is defined.
1611 * If a macro with precisely the right number of parameters is
1612 * defined, or nparam is -1, the address of the definition structure
1613 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1614 * is NULL, no action will be taken regarding its contents, and no
1615 * error will occur.
1617 * Note that this is also called with nparam zero to resolve
1618 * `ifdef'.
1620 * If you already know which context macro belongs to, you can pass
1621 * the context pointer as first parameter; if you won't but name begins
1622 * with %$ the context will be automatically computed. If all_contexts
1623 * is true, macro will be searched in outer contexts as well.
1625 static bool
1626 smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
1627 bool nocase)
1629 struct hash_table *smtbl;
1630 SMacro *m;
1632 if (ctx) {
1633 smtbl = &ctx->localmac;
1634 } else if (name[0] == '%' && name[1] == '$') {
1635 if (cstk)
1636 ctx = get_ctx(name, &name, false);
1637 if (!ctx)
1638 return false; /* got to return _something_ */
1639 smtbl = &ctx->localmac;
1640 } else {
1641 smtbl = &smacros;
1643 m = (SMacro *) hash_findix(smtbl, name);
1645 while (m) {
1646 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
1647 (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
1648 if (defn) {
1649 if (nparam == (int) m->nparam || nparam == -1)
1650 *defn = m;
1651 else
1652 *defn = NULL;
1654 return true;
1656 m = m->next;
1659 return false;
1663 * Count and mark off the parameters in a multi-line macro call.
1664 * This is called both from within the multi-line macro expansion
1665 * code, and also to mark off the default parameters when provided
1666 * in a %macro definition line.
1668 static void count_mmac_params(Token * t, int *nparam, Token *** params)
1670 int paramsize, brace;
1672 *nparam = paramsize = 0;
1673 *params = NULL;
1674 while (t) {
1675 /* +1: we need space for the final NULL */
1676 if (*nparam+1 >= paramsize) {
1677 paramsize += PARAM_DELTA;
1678 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1680 skip_white_(t);
1681 brace = false;
1682 if (tok_is_(t, "{"))
1683 brace = true;
1684 (*params)[(*nparam)++] = t;
1685 while (tok_isnt_(t, brace ? "}" : ","))
1686 t = t->next;
1687 if (t) { /* got a comma/brace */
1688 t = t->next;
1689 if (brace) {
1691 * Now we've found the closing brace, look further
1692 * for the comma.
1694 skip_white_(t);
1695 if (tok_isnt_(t, ",")) {
1696 error(ERR_NONFATAL,
1697 "braces do not enclose all of macro parameter");
1698 while (tok_isnt_(t, ","))
1699 t = t->next;
1701 if (t)
1702 t = t->next; /* eat the comma */
1709 * Determine whether one of the various `if' conditions is true or
1710 * not.
1712 * We must free the tline we get passed.
1714 static bool if_condition(Token * tline, enum preproc_token ct)
1716 enum pp_conditional i = PP_COND(ct);
1717 bool j;
1718 Token *t, *tt, **tptr, *origline;
1719 struct tokenval tokval;
1720 expr *evalresult;
1721 enum pp_token_type needtype;
1722 char *p;
1724 origline = tline;
1726 switch (i) {
1727 case PPC_IFCTX:
1728 j = false; /* have we matched yet? */
1729 while (true) {
1730 skip_white_(tline);
1731 if (!tline)
1732 break;
1733 if (tline->type != TOK_ID) {
1734 error(ERR_NONFATAL,
1735 "`%s' expects context identifiers", pp_directives[ct]);
1736 free_tlist(origline);
1737 return -1;
1739 if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name))
1740 j = true;
1741 tline = tline->next;
1743 break;
1745 case PPC_IFDEF:
1746 j = false; /* have we matched yet? */
1747 while (tline) {
1748 skip_white_(tline);
1749 if (!tline || (tline->type != TOK_ID &&
1750 (tline->type != TOK_PREPROC_ID ||
1751 tline->text[1] != '$'))) {
1752 error(ERR_NONFATAL,
1753 "`%s' expects macro identifiers", pp_directives[ct]);
1754 goto fail;
1756 if (smacro_defined(NULL, tline->text, 0, NULL, true))
1757 j = true;
1758 tline = tline->next;
1760 break;
1762 case PPC_IFENV:
1763 tline = expand_smacro(tline);
1764 j = false; /* have we matched yet? */
1765 while (tline) {
1766 skip_white_(tline);
1767 if (!tline || (tline->type != TOK_ID &&
1768 tline->type != TOK_STRING &&
1769 (tline->type != TOK_PREPROC_ID ||
1770 tline->text[1] != '!'))) {
1771 error(ERR_NONFATAL,
1772 "`%s' expects environment variable names",
1773 pp_directives[ct]);
1774 goto fail;
1776 p = tline->text;
1777 if (tline->type == TOK_PREPROC_ID)
1778 p += 2; /* Skip leading %! */
1779 if (*p == '\'' || *p == '\"' || *p == '`')
1780 nasm_unquote_cstr(p, ct);
1781 if (getenv(p))
1782 j = true;
1783 tline = tline->next;
1785 break;
1787 case PPC_IFIDN:
1788 case PPC_IFIDNI:
1789 tline = expand_smacro(tline);
1790 t = tt = tline;
1791 while (tok_isnt_(tt, ","))
1792 tt = tt->next;
1793 if (!tt) {
1794 error(ERR_NONFATAL,
1795 "`%s' expects two comma-separated arguments",
1796 pp_directives[ct]);
1797 goto fail;
1799 tt = tt->next;
1800 j = true; /* assume equality unless proved not */
1801 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1802 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1803 error(ERR_NONFATAL, "`%s': more than one comma on line",
1804 pp_directives[ct]);
1805 goto fail;
1807 if (t->type == TOK_WHITESPACE) {
1808 t = t->next;
1809 continue;
1811 if (tt->type == TOK_WHITESPACE) {
1812 tt = tt->next;
1813 continue;
1815 if (tt->type != t->type) {
1816 j = false; /* found mismatching tokens */
1817 break;
1819 /* When comparing strings, need to unquote them first */
1820 if (t->type == TOK_STRING) {
1821 size_t l1 = nasm_unquote(t->text, NULL);
1822 size_t l2 = nasm_unquote(tt->text, NULL);
1824 if (l1 != l2) {
1825 j = false;
1826 break;
1828 if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
1829 j = false;
1830 break;
1832 } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
1833 j = false; /* found mismatching tokens */
1834 break;
1837 t = t->next;
1838 tt = tt->next;
1840 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1841 j = false; /* trailing gunk on one end or other */
1842 break;
1844 case PPC_IFMACRO:
1846 bool found = false;
1847 MMacro searching, *mmac;
1849 skip_white_(tline);
1850 tline = expand_id(tline);
1851 if (!tok_type_(tline, TOK_ID)) {
1852 error(ERR_NONFATAL,
1853 "`%s' expects a macro name", pp_directives[ct]);
1854 goto fail;
1856 searching.name = nasm_strdup(tline->text);
1857 searching.casesense = true;
1858 searching.plus = false;
1859 searching.nolist = false;
1860 searching.in_progress = 0;
1861 searching.max_depth = 0;
1862 searching.rep_nest = NULL;
1863 searching.nparam_min = 0;
1864 searching.nparam_max = INT_MAX;
1865 tline = expand_smacro(tline->next);
1866 skip_white_(tline);
1867 if (!tline) {
1868 } else if (!tok_type_(tline, TOK_NUMBER)) {
1869 error(ERR_NONFATAL,
1870 "`%s' expects a parameter count or nothing",
1871 pp_directives[ct]);
1872 } else {
1873 searching.nparam_min = searching.nparam_max =
1874 readnum(tline->text, &j);
1875 if (j)
1876 error(ERR_NONFATAL,
1877 "unable to parse parameter count `%s'",
1878 tline->text);
1880 if (tline && tok_is_(tline->next, "-")) {
1881 tline = tline->next->next;
1882 if (tok_is_(tline, "*"))
1883 searching.nparam_max = INT_MAX;
1884 else if (!tok_type_(tline, TOK_NUMBER))
1885 error(ERR_NONFATAL,
1886 "`%s' expects a parameter count after `-'",
1887 pp_directives[ct]);
1888 else {
1889 searching.nparam_max = readnum(tline->text, &j);
1890 if (j)
1891 error(ERR_NONFATAL,
1892 "unable to parse parameter count `%s'",
1893 tline->text);
1894 if (searching.nparam_min > searching.nparam_max)
1895 error(ERR_NONFATAL,
1896 "minimum parameter count exceeds maximum");
1899 if (tline && tok_is_(tline->next, "+")) {
1900 tline = tline->next;
1901 searching.plus = true;
1903 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
1904 while (mmac) {
1905 if (!strcmp(mmac->name, searching.name) &&
1906 (mmac->nparam_min <= searching.nparam_max
1907 || searching.plus)
1908 && (searching.nparam_min <= mmac->nparam_max
1909 || mmac->plus)) {
1910 found = true;
1911 break;
1913 mmac = mmac->next;
1915 if (tline && tline->next)
1916 error(ERR_WARNING|ERR_PASS1,
1917 "trailing garbage after %%ifmacro ignored");
1918 nasm_free(searching.name);
1919 j = found;
1920 break;
1923 case PPC_IFID:
1924 needtype = TOK_ID;
1925 goto iftype;
1926 case PPC_IFNUM:
1927 needtype = TOK_NUMBER;
1928 goto iftype;
1929 case PPC_IFSTR:
1930 needtype = TOK_STRING;
1931 goto iftype;
1933 iftype:
1934 t = tline = expand_smacro(tline);
1936 while (tok_type_(t, TOK_WHITESPACE) ||
1937 (needtype == TOK_NUMBER &&
1938 tok_type_(t, TOK_OTHER) &&
1939 (t->text[0] == '-' || t->text[0] == '+') &&
1940 !t->text[1]))
1941 t = t->next;
1943 j = tok_type_(t, needtype);
1944 break;
1946 case PPC_IFTOKEN:
1947 t = tline = expand_smacro(tline);
1948 while (tok_type_(t, TOK_WHITESPACE))
1949 t = t->next;
1951 j = false;
1952 if (t) {
1953 t = t->next; /* Skip the actual token */
1954 while (tok_type_(t, TOK_WHITESPACE))
1955 t = t->next;
1956 j = !t; /* Should be nothing left */
1958 break;
1960 case PPC_IFEMPTY:
1961 t = tline = expand_smacro(tline);
1962 while (tok_type_(t, TOK_WHITESPACE))
1963 t = t->next;
1965 j = !t; /* Should be empty */
1966 break;
1968 case PPC_IF:
1969 t = tline = expand_smacro(tline);
1970 tptr = &t;
1971 tokval.t_type = TOKEN_INVALID;
1972 evalresult = evaluate(ppscan, tptr, &tokval,
1973 NULL, pass | CRITICAL, error, NULL);
1974 if (!evalresult)
1975 return -1;
1976 if (tokval.t_type)
1977 error(ERR_WARNING|ERR_PASS1,
1978 "trailing garbage after expression ignored");
1979 if (!is_simple(evalresult)) {
1980 error(ERR_NONFATAL,
1981 "non-constant value given to `%s'", pp_directives[ct]);
1982 goto fail;
1984 j = reloc_value(evalresult) != 0;
1985 break;
1987 default:
1988 error(ERR_FATAL,
1989 "preprocessor directive `%s' not yet implemented",
1990 pp_directives[ct]);
1991 goto fail;
1994 free_tlist(origline);
1995 return j ^ PP_NEGATIVE(ct);
1997 fail:
1998 free_tlist(origline);
1999 return -1;
2003 * Common code for defining an smacro
2005 static bool define_smacro(Context *ctx, const char *mname, bool casesense,
2006 int nparam, Token *expansion)
2008 SMacro *smac, **smhead;
2009 struct hash_table *smtbl;
2011 if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
2012 if (!smac) {
2013 error(ERR_WARNING|ERR_PASS1,
2014 "single-line macro `%s' defined both with and"
2015 " without parameters", mname);
2017 * Some instances of the old code considered this a failure,
2018 * some others didn't. What is the right thing to do here?
2020 free_tlist(expansion);
2021 return false; /* Failure */
2022 } else {
2024 * We're redefining, so we have to take over an
2025 * existing SMacro structure. This means freeing
2026 * what was already in it.
2028 nasm_free(smac->name);
2029 free_tlist(smac->expansion);
2031 } else {
2032 smtbl = ctx ? &ctx->localmac : &smacros;
2033 smhead = (SMacro **) hash_findi_add(smtbl, mname);
2034 smac = nasm_malloc(sizeof(SMacro));
2035 smac->next = *smhead;
2036 *smhead = smac;
2038 smac->name = nasm_strdup(mname);
2039 smac->casesense = casesense;
2040 smac->nparam = nparam;
2041 smac->expansion = expansion;
2042 smac->in_progress = false;
2043 return true; /* Success */
2047 * Undefine an smacro
2049 static void undef_smacro(Context *ctx, const char *mname)
2051 SMacro **smhead, *s, **sp;
2052 struct hash_table *smtbl;
2054 smtbl = ctx ? &ctx->localmac : &smacros;
2055 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
2057 if (smhead) {
2059 * We now have a macro name... go hunt for it.
2061 sp = smhead;
2062 while ((s = *sp) != NULL) {
2063 if (!mstrcmp(s->name, mname, s->casesense)) {
2064 *sp = s->next;
2065 nasm_free(s->name);
2066 free_tlist(s->expansion);
2067 nasm_free(s);
2068 } else {
2069 sp = &s->next;
2076 * Parse a mmacro specification.
2078 static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
2080 bool err;
2082 tline = tline->next;
2083 skip_white_(tline);
2084 tline = expand_id(tline);
2085 if (!tok_type_(tline, TOK_ID)) {
2086 error(ERR_NONFATAL, "`%s' expects a macro name", directive);
2087 return false;
2090 def->prev = NULL;
2091 def->name = nasm_strdup(tline->text);
2092 def->plus = false;
2093 def->nolist = false;
2094 def->in_progress = 0;
2095 def->rep_nest = NULL;
2096 def->nparam_min = 0;
2097 def->nparam_max = 0;
2099 tline = expand_smacro(tline->next);
2100 skip_white_(tline);
2101 if (!tok_type_(tline, TOK_NUMBER)) {
2102 error(ERR_NONFATAL, "`%s' expects a parameter count", directive);
2103 } else {
2104 def->nparam_min = def->nparam_max =
2105 readnum(tline->text, &err);
2106 if (err)
2107 error(ERR_NONFATAL,
2108 "unable to parse parameter count `%s'", tline->text);
2110 if (tline && tok_is_(tline->next, "-")) {
2111 tline = tline->next->next;
2112 if (tok_is_(tline, "*")) {
2113 def->nparam_max = INT_MAX;
2114 } else if (!tok_type_(tline, TOK_NUMBER)) {
2115 error(ERR_NONFATAL,
2116 "`%s' expects a parameter count after `-'", directive);
2117 } else {
2118 def->nparam_max = readnum(tline->text, &err);
2119 if (err) {
2120 error(ERR_NONFATAL, "unable to parse parameter count `%s'",
2121 tline->text);
2123 if (def->nparam_min > def->nparam_max) {
2124 error(ERR_NONFATAL, "minimum parameter count exceeds maximum");
2128 if (tline && tok_is_(tline->next, "+")) {
2129 tline = tline->next;
2130 def->plus = true;
2132 if (tline && tok_type_(tline->next, TOK_ID) &&
2133 !nasm_stricmp(tline->next->text, ".nolist")) {
2134 tline = tline->next;
2135 def->nolist = true;
2139 * Handle default parameters.
2141 if (tline && tline->next) {
2142 def->dlist = tline->next;
2143 tline->next = NULL;
2144 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
2145 } else {
2146 def->dlist = NULL;
2147 def->defaults = NULL;
2149 def->expansion = NULL;
2151 if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
2152 !def->plus)
2153 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MDP,
2154 "too many default macro parameters");
2156 return true;
2161 * Decode a size directive
2163 static int parse_size(const char *str) {
2164 static const char *size_names[] =
2165 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2166 static const int sizes[] =
2167 { 0, 1, 4, 16, 8, 10, 2, 32 };
2169 return sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1];
2173 * find and process preprocessor directive in passed line
2174 * Find out if a line contains a preprocessor directive, and deal
2175 * with it if so.
2177 * If a directive _is_ found, it is the responsibility of this routine
2178 * (and not the caller) to free_tlist() the line.
2180 * @param tline a pointer to the current tokeninzed line linked list
2181 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2184 static int do_directive(Token * tline)
2186 enum preproc_token i;
2187 int j;
2188 bool err;
2189 int nparam;
2190 bool nolist;
2191 bool casesense;
2192 int k, m;
2193 int offset;
2194 char *p, *pp;
2195 const char *mname;
2196 Include *inc;
2197 Context *ctx;
2198 Cond *cond;
2199 MMacro *mmac, **mmhead;
2200 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
2201 Line *l;
2202 struct tokenval tokval;
2203 expr *evalresult;
2204 MMacro *tmp_defining; /* Used when manipulating rep_nest */
2205 int64_t count;
2206 size_t len;
2207 int severity;
2209 origline = tline;
2211 skip_white_(tline);
2212 if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
2213 (tline->text[1] == '%' || tline->text[1] == '$'
2214 || tline->text[1] == '!'))
2215 return NO_DIRECTIVE_FOUND;
2217 i = pp_token_hash(tline->text);
2220 * FIXME: We zap execution of PP_RMACRO, PP_IRMACRO, PP_EXITMACRO
2221 * since they are known to be buggy at moment, we need to fix them
2222 * in future release (2.09-2.10)
2224 if (i == PP_RMACRO || i == PP_RMACRO || i == PP_EXITMACRO) {
2225 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2226 tline->text);
2227 return NO_DIRECTIVE_FOUND;
2231 * If we're in a non-emitting branch of a condition construct,
2232 * or walking to the end of an already terminated %rep block,
2233 * we should ignore all directives except for condition
2234 * directives.
2236 if (((istk->conds && !emitting(istk->conds->state)) ||
2237 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
2238 return NO_DIRECTIVE_FOUND;
2242 * If we're defining a macro or reading a %rep block, we should
2243 * ignore all directives except for %macro/%imacro (which nest),
2244 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2245 * If we're in a %rep block, another %rep nests, so should be let through.
2247 if (defining && i != PP_MACRO && i != PP_IMACRO &&
2248 i != PP_RMACRO && i != PP_IRMACRO &&
2249 i != PP_ENDMACRO && i != PP_ENDM &&
2250 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
2251 return NO_DIRECTIVE_FOUND;
2254 if (defining) {
2255 if (i == PP_MACRO || i == PP_IMACRO ||
2256 i == PP_RMACRO || i == PP_IRMACRO) {
2257 nested_mac_count++;
2258 return NO_DIRECTIVE_FOUND;
2259 } else if (nested_mac_count > 0) {
2260 if (i == PP_ENDMACRO) {
2261 nested_mac_count--;
2262 return NO_DIRECTIVE_FOUND;
2265 if (!defining->name) {
2266 if (i == PP_REP) {
2267 nested_rep_count++;
2268 return NO_DIRECTIVE_FOUND;
2269 } else if (nested_rep_count > 0) {
2270 if (i == PP_ENDREP) {
2271 nested_rep_count--;
2272 return NO_DIRECTIVE_FOUND;
2278 switch (i) {
2279 case PP_INVALID:
2280 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2281 tline->text);
2282 return NO_DIRECTIVE_FOUND; /* didn't get it */
2284 case PP_STACKSIZE:
2285 /* Directive to tell NASM what the default stack size is. The
2286 * default is for a 16-bit stack, and this can be overriden with
2287 * %stacksize large.
2289 tline = tline->next;
2290 if (tline && tline->type == TOK_WHITESPACE)
2291 tline = tline->next;
2292 if (!tline || tline->type != TOK_ID) {
2293 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
2294 free_tlist(origline);
2295 return DIRECTIVE_FOUND;
2297 if (nasm_stricmp(tline->text, "flat") == 0) {
2298 /* All subsequent ARG directives are for a 32-bit stack */
2299 StackSize = 4;
2300 StackPointer = "ebp";
2301 ArgOffset = 8;
2302 LocalOffset = 0;
2303 } else if (nasm_stricmp(tline->text, "flat64") == 0) {
2304 /* All subsequent ARG directives are for a 64-bit stack */
2305 StackSize = 8;
2306 StackPointer = "rbp";
2307 ArgOffset = 16;
2308 LocalOffset = 0;
2309 } else if (nasm_stricmp(tline->text, "large") == 0) {
2310 /* All subsequent ARG directives are for a 16-bit stack,
2311 * far function call.
2313 StackSize = 2;
2314 StackPointer = "bp";
2315 ArgOffset = 4;
2316 LocalOffset = 0;
2317 } else if (nasm_stricmp(tline->text, "small") == 0) {
2318 /* All subsequent ARG directives are for a 16-bit stack,
2319 * far function call. We don't support near functions.
2321 StackSize = 2;
2322 StackPointer = "bp";
2323 ArgOffset = 6;
2324 LocalOffset = 0;
2325 } else {
2326 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
2327 free_tlist(origline);
2328 return DIRECTIVE_FOUND;
2330 free_tlist(origline);
2331 return DIRECTIVE_FOUND;
2333 case PP_ARG:
2334 /* TASM like ARG directive to define arguments to functions, in
2335 * the following form:
2337 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2339 offset = ArgOffset;
2340 do {
2341 char *arg, directive[256];
2342 int size = StackSize;
2344 /* Find the argument name */
2345 tline = tline->next;
2346 if (tline && tline->type == TOK_WHITESPACE)
2347 tline = tline->next;
2348 if (!tline || tline->type != TOK_ID) {
2349 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
2350 free_tlist(origline);
2351 return DIRECTIVE_FOUND;
2353 arg = tline->text;
2355 /* Find the argument size type */
2356 tline = tline->next;
2357 if (!tline || tline->type != TOK_OTHER
2358 || tline->text[0] != ':') {
2359 error(ERR_NONFATAL,
2360 "Syntax error processing `%%arg' directive");
2361 free_tlist(origline);
2362 return DIRECTIVE_FOUND;
2364 tline = tline->next;
2365 if (!tline || tline->type != TOK_ID) {
2366 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
2367 free_tlist(origline);
2368 return DIRECTIVE_FOUND;
2371 /* Allow macro expansion of type parameter */
2372 tt = tokenize(tline->text);
2373 tt = expand_smacro(tt);
2374 size = parse_size(tt->text);
2375 if (!size) {
2376 error(ERR_NONFATAL,
2377 "Invalid size type for `%%arg' missing directive");
2378 free_tlist(tt);
2379 free_tlist(origline);
2380 return DIRECTIVE_FOUND;
2382 free_tlist(tt);
2384 /* Round up to even stack slots */
2385 size = ALIGN(size, StackSize);
2387 /* Now define the macro for the argument */
2388 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
2389 arg, StackPointer, offset);
2390 do_directive(tokenize(directive));
2391 offset += size;
2393 /* Move to the next argument in the list */
2394 tline = tline->next;
2395 if (tline && tline->type == TOK_WHITESPACE)
2396 tline = tline->next;
2397 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2398 ArgOffset = offset;
2399 free_tlist(origline);
2400 return DIRECTIVE_FOUND;
2402 case PP_LOCAL:
2403 /* TASM like LOCAL directive to define local variables for a
2404 * function, in the following form:
2406 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2408 * The '= LocalSize' at the end is ignored by NASM, but is
2409 * required by TASM to define the local parameter size (and used
2410 * by the TASM macro package).
2412 offset = LocalOffset;
2413 do {
2414 char *local, directive[256];
2415 int size = StackSize;
2417 /* Find the argument name */
2418 tline = tline->next;
2419 if (tline && tline->type == TOK_WHITESPACE)
2420 tline = tline->next;
2421 if (!tline || tline->type != TOK_ID) {
2422 error(ERR_NONFATAL,
2423 "`%%local' missing argument parameter");
2424 free_tlist(origline);
2425 return DIRECTIVE_FOUND;
2427 local = tline->text;
2429 /* Find the argument size type */
2430 tline = tline->next;
2431 if (!tline || tline->type != TOK_OTHER
2432 || tline->text[0] != ':') {
2433 error(ERR_NONFATAL,
2434 "Syntax error processing `%%local' directive");
2435 free_tlist(origline);
2436 return DIRECTIVE_FOUND;
2438 tline = tline->next;
2439 if (!tline || tline->type != TOK_ID) {
2440 error(ERR_NONFATAL,
2441 "`%%local' missing size type parameter");
2442 free_tlist(origline);
2443 return DIRECTIVE_FOUND;
2446 /* Allow macro expansion of type parameter */
2447 tt = tokenize(tline->text);
2448 tt = expand_smacro(tt);
2449 size = parse_size(tt->text);
2450 if (!size) {
2451 error(ERR_NONFATAL,
2452 "Invalid size type for `%%local' missing directive");
2453 free_tlist(tt);
2454 free_tlist(origline);
2455 return DIRECTIVE_FOUND;
2457 free_tlist(tt);
2459 /* Round up to even stack slots */
2460 size = ALIGN(size, StackSize);
2462 offset += size; /* Negative offset, increment before */
2464 /* Now define the macro for the argument */
2465 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
2466 local, StackPointer, offset);
2467 do_directive(tokenize(directive));
2469 /* Now define the assign to setup the enter_c macro correctly */
2470 snprintf(directive, sizeof(directive),
2471 "%%assign %%$localsize %%$localsize+%d", size);
2472 do_directive(tokenize(directive));
2474 /* Move to the next argument in the list */
2475 tline = tline->next;
2476 if (tline && tline->type == TOK_WHITESPACE)
2477 tline = tline->next;
2478 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2479 LocalOffset = offset;
2480 free_tlist(origline);
2481 return DIRECTIVE_FOUND;
2483 case PP_CLEAR:
2484 if (tline->next)
2485 error(ERR_WARNING|ERR_PASS1,
2486 "trailing garbage after `%%clear' ignored");
2487 free_macros();
2488 init_macros();
2489 free_tlist(origline);
2490 return DIRECTIVE_FOUND;
2492 case PP_DEPEND:
2493 t = tline->next = expand_smacro(tline->next);
2494 skip_white_(t);
2495 if (!t || (t->type != TOK_STRING &&
2496 t->type != TOK_INTERNAL_STRING)) {
2497 error(ERR_NONFATAL, "`%%depend' expects a file name");
2498 free_tlist(origline);
2499 return DIRECTIVE_FOUND; /* but we did _something_ */
2501 if (t->next)
2502 error(ERR_WARNING|ERR_PASS1,
2503 "trailing garbage after `%%depend' ignored");
2504 p = t->text;
2505 if (t->type != TOK_INTERNAL_STRING)
2506 nasm_unquote_cstr(p, i);
2507 if (dephead && !in_list(*dephead, p)) {
2508 StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next);
2509 sl->next = NULL;
2510 strcpy(sl->str, p);
2511 *deptail = sl;
2512 deptail = &sl->next;
2514 free_tlist(origline);
2515 return DIRECTIVE_FOUND;
2517 case PP_INCLUDE:
2518 t = tline->next = expand_smacro(tline->next);
2519 skip_white_(t);
2521 if (!t || (t->type != TOK_STRING &&
2522 t->type != TOK_INTERNAL_STRING)) {
2523 error(ERR_NONFATAL, "`%%include' expects a file name");
2524 free_tlist(origline);
2525 return DIRECTIVE_FOUND; /* but we did _something_ */
2527 if (t->next)
2528 error(ERR_WARNING|ERR_PASS1,
2529 "trailing garbage after `%%include' ignored");
2530 p = t->text;
2531 if (t->type != TOK_INTERNAL_STRING)
2532 nasm_unquote_cstr(p, i);
2533 inc = nasm_malloc(sizeof(Include));
2534 inc->next = istk;
2535 inc->conds = NULL;
2536 inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
2537 if (!inc->fp) {
2538 /* -MG given but file not found */
2539 nasm_free(inc);
2540 } else {
2541 inc->fname = src_set_fname(nasm_strdup(p));
2542 inc->lineno = src_set_linnum(0);
2543 inc->lineinc = 1;
2544 inc->expansion = NULL;
2545 inc->mstk = NULL;
2546 istk = inc;
2547 list->uplevel(LIST_INCLUDE);
2549 free_tlist(origline);
2550 return DIRECTIVE_FOUND;
2552 case PP_USE:
2554 static macros_t *use_pkg;
2555 const char *pkg_macro = NULL;
2557 tline = tline->next;
2558 skip_white_(tline);
2559 tline = expand_id(tline);
2561 if (!tline || (tline->type != TOK_STRING &&
2562 tline->type != TOK_INTERNAL_STRING &&
2563 tline->type != TOK_ID)) {
2564 error(ERR_NONFATAL, "`%%use' expects a package name");
2565 free_tlist(origline);
2566 return DIRECTIVE_FOUND; /* but we did _something_ */
2568 if (tline->next)
2569 error(ERR_WARNING|ERR_PASS1,
2570 "trailing garbage after `%%use' ignored");
2571 if (tline->type == TOK_STRING)
2572 nasm_unquote_cstr(tline->text, i);
2573 use_pkg = nasm_stdmac_find_package(tline->text);
2574 if (!use_pkg)
2575 error(ERR_NONFATAL, "unknown `%%use' package: %s", tline->text);
2576 else
2577 pkg_macro = (char *)use_pkg + 1; /* The first string will be <%define>__USE_*__ */
2578 if (use_pkg && ! smacro_defined(NULL, pkg_macro, 0, NULL, true)) {
2579 /* Not already included, go ahead and include it */
2580 stdmacpos = use_pkg;
2582 free_tlist(origline);
2583 return DIRECTIVE_FOUND;
2585 case PP_PUSH:
2586 case PP_REPL:
2587 case PP_POP:
2588 tline = tline->next;
2589 skip_white_(tline);
2590 tline = expand_id(tline);
2591 if (tline) {
2592 if (!tok_type_(tline, TOK_ID)) {
2593 error(ERR_NONFATAL, "`%s' expects a context identifier",
2594 pp_directives[i]);
2595 free_tlist(origline);
2596 return DIRECTIVE_FOUND; /* but we did _something_ */
2598 if (tline->next)
2599 error(ERR_WARNING|ERR_PASS1,
2600 "trailing garbage after `%s' ignored",
2601 pp_directives[i]);
2602 p = nasm_strdup(tline->text);
2603 } else {
2604 p = NULL; /* Anonymous */
2607 if (i == PP_PUSH) {
2608 ctx = nasm_malloc(sizeof(Context));
2609 ctx->next = cstk;
2610 hash_init(&ctx->localmac, HASH_SMALL);
2611 ctx->name = p;
2612 ctx->number = unique++;
2613 cstk = ctx;
2614 } else {
2615 /* %pop or %repl */
2616 if (!cstk) {
2617 error(ERR_NONFATAL, "`%s': context stack is empty",
2618 pp_directives[i]);
2619 } else if (i == PP_POP) {
2620 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
2621 error(ERR_NONFATAL, "`%%pop' in wrong context: %s, "
2622 "expected %s",
2623 cstk->name ? cstk->name : "anonymous", p);
2624 else
2625 ctx_pop();
2626 } else {
2627 /* i == PP_REPL */
2628 nasm_free(cstk->name);
2629 cstk->name = p;
2630 p = NULL;
2632 nasm_free(p);
2634 free_tlist(origline);
2635 return DIRECTIVE_FOUND;
2636 case PP_FATAL:
2637 severity = ERR_FATAL;
2638 goto issue_error;
2639 case PP_ERROR:
2640 severity = ERR_NONFATAL;
2641 goto issue_error;
2642 case PP_WARNING:
2643 severity = ERR_WARNING|ERR_WARN_USER;
2644 goto issue_error;
2646 issue_error:
2648 /* Only error out if this is the final pass */
2649 if (pass != 2 && i != PP_FATAL)
2650 return DIRECTIVE_FOUND;
2652 tline->next = expand_smacro(tline->next);
2653 tline = tline->next;
2654 skip_white_(tline);
2655 t = tline ? tline->next : NULL;
2656 skip_white_(t);
2657 if (tok_type_(tline, TOK_STRING) && !t) {
2658 /* The line contains only a quoted string */
2659 p = tline->text;
2660 nasm_unquote(p, NULL); /* Ignore NUL character truncation */
2661 error(severity, "%s", p);
2662 } else {
2663 /* Not a quoted string, or more than a quoted string */
2664 p = detoken(tline, false);
2665 error(severity, "%s", p);
2666 nasm_free(p);
2668 free_tlist(origline);
2669 return DIRECTIVE_FOUND;
2672 CASE_PP_IF:
2673 if (istk->conds && !emitting(istk->conds->state))
2674 j = COND_NEVER;
2675 else {
2676 j = if_condition(tline->next, i);
2677 tline->next = NULL; /* it got freed */
2678 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2680 cond = nasm_malloc(sizeof(Cond));
2681 cond->next = istk->conds;
2682 cond->state = j;
2683 istk->conds = cond;
2684 if(istk->mstk)
2685 istk->mstk->condcnt ++;
2686 free_tlist(origline);
2687 return DIRECTIVE_FOUND;
2689 CASE_PP_ELIF:
2690 if (!istk->conds)
2691 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
2692 switch(istk->conds->state) {
2693 case COND_IF_TRUE:
2694 istk->conds->state = COND_DONE;
2695 break;
2697 case COND_DONE:
2698 case COND_NEVER:
2699 break;
2701 case COND_ELSE_TRUE:
2702 case COND_ELSE_FALSE:
2703 error_precond(ERR_WARNING|ERR_PASS1,
2704 "`%%elif' after `%%else' ignored");
2705 istk->conds->state = COND_NEVER;
2706 break;
2708 case COND_IF_FALSE:
2710 * IMPORTANT: In the case of %if, we will already have
2711 * called expand_mmac_params(); however, if we're
2712 * processing an %elif we must have been in a
2713 * non-emitting mode, which would have inhibited
2714 * the normal invocation of expand_mmac_params().
2715 * Therefore, we have to do it explicitly here.
2717 j = if_condition(expand_mmac_params(tline->next), i);
2718 tline->next = NULL; /* it got freed */
2719 istk->conds->state =
2720 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2721 break;
2723 free_tlist(origline);
2724 return DIRECTIVE_FOUND;
2726 case PP_ELSE:
2727 if (tline->next)
2728 error_precond(ERR_WARNING|ERR_PASS1,
2729 "trailing garbage after `%%else' ignored");
2730 if (!istk->conds)
2731 error(ERR_FATAL, "`%%else': no matching `%%if'");
2732 switch(istk->conds->state) {
2733 case COND_IF_TRUE:
2734 case COND_DONE:
2735 istk->conds->state = COND_ELSE_FALSE;
2736 break;
2738 case COND_NEVER:
2739 break;
2741 case COND_IF_FALSE:
2742 istk->conds->state = COND_ELSE_TRUE;
2743 break;
2745 case COND_ELSE_TRUE:
2746 case COND_ELSE_FALSE:
2747 error_precond(ERR_WARNING|ERR_PASS1,
2748 "`%%else' after `%%else' ignored.");
2749 istk->conds->state = COND_NEVER;
2750 break;
2752 free_tlist(origline);
2753 return DIRECTIVE_FOUND;
2755 case PP_ENDIF:
2756 if (tline->next)
2757 error_precond(ERR_WARNING|ERR_PASS1,
2758 "trailing garbage after `%%endif' ignored");
2759 if (!istk->conds)
2760 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2761 cond = istk->conds;
2762 istk->conds = cond->next;
2763 nasm_free(cond);
2764 if(istk->mstk)
2765 istk->mstk->condcnt --;
2766 free_tlist(origline);
2767 return DIRECTIVE_FOUND;
2769 case PP_RMACRO:
2770 case PP_IRMACRO:
2771 case PP_MACRO:
2772 case PP_IMACRO:
2773 if (defining) {
2774 error(ERR_FATAL, "`%s': already defining a macro",
2775 pp_directives[i]);
2776 return DIRECTIVE_FOUND;
2778 defining = nasm_malloc(sizeof(MMacro));
2779 defining->max_depth =
2780 (i == PP_RMACRO) || (i == PP_IRMACRO) ? DEADMAN_LIMIT : 0;
2781 defining->casesense = (i == PP_MACRO) || (i == PP_RMACRO);
2782 if (!parse_mmacro_spec(tline, defining, pp_directives[i])) {
2783 nasm_free(defining);
2784 defining = NULL;
2785 return DIRECTIVE_FOUND;
2788 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
2789 while (mmac) {
2790 if (!strcmp(mmac->name, defining->name) &&
2791 (mmac->nparam_min <= defining->nparam_max
2792 || defining->plus)
2793 && (defining->nparam_min <= mmac->nparam_max
2794 || mmac->plus)) {
2795 error(ERR_WARNING|ERR_PASS1,
2796 "redefining multi-line macro `%s'", defining->name);
2797 return DIRECTIVE_FOUND;
2799 mmac = mmac->next;
2801 free_tlist(origline);
2802 return DIRECTIVE_FOUND;
2804 case PP_ENDM:
2805 case PP_ENDMACRO:
2806 if (! (defining && defining->name)) {
2807 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2808 return DIRECTIVE_FOUND;
2810 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
2811 defining->next = *mmhead;
2812 *mmhead = defining;
2813 defining = NULL;
2814 free_tlist(origline);
2815 return DIRECTIVE_FOUND;
2817 case PP_EXITMACRO:
2819 * We must search along istk->expansion until we hit a
2820 * macro-end marker for a macro with a name. Then we
2821 * bypass all lines between exitmacro and endmacro.
2823 list_for_each(l, istk->expansion)
2824 if (l->finishes && l->finishes->name)
2825 break;
2827 if (l) {
2829 * Remove all conditional entries relative to this
2830 * macro invocation. (safe to do in this context)
2832 for ( ; l->finishes->condcnt > 0; l->finishes->condcnt --) {
2833 cond = istk->conds;
2834 istk->conds = cond->next;
2835 nasm_free(cond);
2837 istk->expansion = l;
2838 } else {
2839 error(ERR_NONFATAL, "`%%exitmacro' not within `%%macro' block");
2841 free_tlist(origline);
2842 return DIRECTIVE_FOUND;
2844 case PP_UNMACRO:
2845 case PP_UNIMACRO:
2847 MMacro **mmac_p;
2848 MMacro spec;
2850 spec.casesense = (i == PP_UNMACRO);
2851 if (!parse_mmacro_spec(tline, &spec, pp_directives[i])) {
2852 return DIRECTIVE_FOUND;
2854 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
2855 while (mmac_p && *mmac_p) {
2856 mmac = *mmac_p;
2857 if (mmac->casesense == spec.casesense &&
2858 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
2859 mmac->nparam_min == spec.nparam_min &&
2860 mmac->nparam_max == spec.nparam_max &&
2861 mmac->plus == spec.plus) {
2862 *mmac_p = mmac->next;
2863 free_mmacro(mmac);
2864 } else {
2865 mmac_p = &mmac->next;
2868 free_tlist(origline);
2869 free_tlist(spec.dlist);
2870 return DIRECTIVE_FOUND;
2873 case PP_ROTATE:
2874 if (tline->next && tline->next->type == TOK_WHITESPACE)
2875 tline = tline->next;
2876 if (!tline->next) {
2877 free_tlist(origline);
2878 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2879 return DIRECTIVE_FOUND;
2881 t = expand_smacro(tline->next);
2882 tline->next = NULL;
2883 free_tlist(origline);
2884 tline = t;
2885 tptr = &t;
2886 tokval.t_type = TOKEN_INVALID;
2887 evalresult =
2888 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2889 free_tlist(tline);
2890 if (!evalresult)
2891 return DIRECTIVE_FOUND;
2892 if (tokval.t_type)
2893 error(ERR_WARNING|ERR_PASS1,
2894 "trailing garbage after expression ignored");
2895 if (!is_simple(evalresult)) {
2896 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2897 return DIRECTIVE_FOUND;
2899 mmac = istk->mstk;
2900 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2901 mmac = mmac->next_active;
2902 if (!mmac) {
2903 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2904 } else if (mmac->nparam == 0) {
2905 error(ERR_NONFATAL,
2906 "`%%rotate' invoked within macro without parameters");
2907 } else {
2908 int rotate = mmac->rotate + reloc_value(evalresult);
2910 rotate %= (int)mmac->nparam;
2911 if (rotate < 0)
2912 rotate += mmac->nparam;
2914 mmac->rotate = rotate;
2916 return DIRECTIVE_FOUND;
2918 case PP_REP:
2919 nolist = false;
2920 do {
2921 tline = tline->next;
2922 } while (tok_type_(tline, TOK_WHITESPACE));
2924 if (tok_type_(tline, TOK_ID) &&
2925 nasm_stricmp(tline->text, ".nolist") == 0) {
2926 nolist = true;
2927 do {
2928 tline = tline->next;
2929 } while (tok_type_(tline, TOK_WHITESPACE));
2932 if (tline) {
2933 t = expand_smacro(tline);
2934 tptr = &t;
2935 tokval.t_type = TOKEN_INVALID;
2936 evalresult =
2937 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2938 if (!evalresult) {
2939 free_tlist(origline);
2940 return DIRECTIVE_FOUND;
2942 if (tokval.t_type)
2943 error(ERR_WARNING|ERR_PASS1,
2944 "trailing garbage after expression ignored");
2945 if (!is_simple(evalresult)) {
2946 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2947 return DIRECTIVE_FOUND;
2949 count = reloc_value(evalresult);
2950 if (count >= REP_LIMIT) {
2951 error(ERR_NONFATAL, "`%%rep' value exceeds limit");
2952 count = 0;
2953 } else
2954 count++;
2955 } else {
2956 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
2957 count = 0;
2959 free_tlist(origline);
2961 tmp_defining = defining;
2962 defining = nasm_malloc(sizeof(MMacro));
2963 defining->prev = NULL;
2964 defining->name = NULL; /* flags this macro as a %rep block */
2965 defining->casesense = false;
2966 defining->plus = false;
2967 defining->nolist = nolist;
2968 defining->in_progress = count;
2969 defining->max_depth = 0;
2970 defining->nparam_min = defining->nparam_max = 0;
2971 defining->defaults = NULL;
2972 defining->dlist = NULL;
2973 defining->expansion = NULL;
2974 defining->next_active = istk->mstk;
2975 defining->rep_nest = tmp_defining;
2976 return DIRECTIVE_FOUND;
2978 case PP_ENDREP:
2979 if (!defining || defining->name) {
2980 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2981 return DIRECTIVE_FOUND;
2985 * Now we have a "macro" defined - although it has no name
2986 * and we won't be entering it in the hash tables - we must
2987 * push a macro-end marker for it on to istk->expansion.
2988 * After that, it will take care of propagating itself (a
2989 * macro-end marker line for a macro which is really a %rep
2990 * block will cause the macro to be re-expanded, complete
2991 * with another macro-end marker to ensure the process
2992 * continues) until the whole expansion is forcibly removed
2993 * from istk->expansion by a %exitrep.
2995 l = nasm_malloc(sizeof(Line));
2996 l->next = istk->expansion;
2997 l->finishes = defining;
2998 l->first = NULL;
2999 istk->expansion = l;
3001 istk->mstk = defining;
3003 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
3004 tmp_defining = defining;
3005 defining = defining->rep_nest;
3006 free_tlist(origline);
3007 return DIRECTIVE_FOUND;
3009 case PP_EXITREP:
3011 * We must search along istk->expansion until we hit a
3012 * macro-end marker for a macro with no name. Then we set
3013 * its `in_progress' flag to 0.
3015 list_for_each(l, istk->expansion)
3016 if (l->finishes && !l->finishes->name)
3017 break;
3019 if (l)
3020 l->finishes->in_progress = 1;
3021 else
3022 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
3023 free_tlist(origline);
3024 return DIRECTIVE_FOUND;
3026 case PP_XDEFINE:
3027 case PP_IXDEFINE:
3028 case PP_DEFINE:
3029 case PP_IDEFINE:
3030 casesense = (i == PP_DEFINE || i == PP_XDEFINE);
3032 tline = tline->next;
3033 skip_white_(tline);
3034 tline = expand_id(tline);
3035 if (!tline || (tline->type != TOK_ID &&
3036 (tline->type != TOK_PREPROC_ID ||
3037 tline->text[1] != '$'))) {
3038 error(ERR_NONFATAL, "`%s' expects a macro identifier",
3039 pp_directives[i]);
3040 free_tlist(origline);
3041 return DIRECTIVE_FOUND;
3044 ctx = get_ctx(tline->text, &mname, false);
3045 last = tline;
3046 param_start = tline = tline->next;
3047 nparam = 0;
3049 /* Expand the macro definition now for %xdefine and %ixdefine */
3050 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
3051 tline = expand_smacro(tline);
3053 if (tok_is_(tline, "(")) {
3055 * This macro has parameters.
3058 tline = tline->next;
3059 while (1) {
3060 skip_white_(tline);
3061 if (!tline) {
3062 error(ERR_NONFATAL, "parameter identifier expected");
3063 free_tlist(origline);
3064 return DIRECTIVE_FOUND;
3066 if (tline->type != TOK_ID) {
3067 error(ERR_NONFATAL,
3068 "`%s': parameter identifier expected",
3069 tline->text);
3070 free_tlist(origline);
3071 return DIRECTIVE_FOUND;
3073 tline->type = TOK_SMAC_PARAM + nparam++;
3074 tline = tline->next;
3075 skip_white_(tline);
3076 if (tok_is_(tline, ",")) {
3077 tline = tline->next;
3078 } else {
3079 if (!tok_is_(tline, ")")) {
3080 error(ERR_NONFATAL,
3081 "`)' expected to terminate macro template");
3082 free_tlist(origline);
3083 return DIRECTIVE_FOUND;
3085 break;
3088 last = tline;
3089 tline = tline->next;
3091 if (tok_type_(tline, TOK_WHITESPACE))
3092 last = tline, tline = tline->next;
3093 macro_start = NULL;
3094 last->next = NULL;
3095 t = tline;
3096 while (t) {
3097 if (t->type == TOK_ID) {
3098 list_for_each(tt, param_start)
3099 if (tt->type >= TOK_SMAC_PARAM &&
3100 !strcmp(tt->text, t->text))
3101 t->type = tt->type;
3103 tt = t->next;
3104 t->next = macro_start;
3105 macro_start = t;
3106 t = tt;
3109 * Good. We now have a macro name, a parameter count, and a
3110 * token list (in reverse order) for an expansion. We ought
3111 * to be OK just to create an SMacro, store it, and let
3112 * free_tlist have the rest of the line (which we have
3113 * carefully re-terminated after chopping off the expansion
3114 * from the end).
3116 define_smacro(ctx, mname, casesense, nparam, macro_start);
3117 free_tlist(origline);
3118 return DIRECTIVE_FOUND;
3120 case PP_UNDEF:
3121 tline = tline->next;
3122 skip_white_(tline);
3123 tline = expand_id(tline);
3124 if (!tline || (tline->type != TOK_ID &&
3125 (tline->type != TOK_PREPROC_ID ||
3126 tline->text[1] != '$'))) {
3127 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
3128 free_tlist(origline);
3129 return DIRECTIVE_FOUND;
3131 if (tline->next) {
3132 error(ERR_WARNING|ERR_PASS1,
3133 "trailing garbage after macro name ignored");
3136 /* Find the context that symbol belongs to */
3137 ctx = get_ctx(tline->text, &mname, false);
3138 undef_smacro(ctx, mname);
3139 free_tlist(origline);
3140 return DIRECTIVE_FOUND;
3142 case PP_DEFSTR:
3143 case PP_IDEFSTR:
3144 casesense = (i == PP_DEFSTR);
3146 tline = tline->next;
3147 skip_white_(tline);
3148 tline = expand_id(tline);
3149 if (!tline || (tline->type != TOK_ID &&
3150 (tline->type != TOK_PREPROC_ID ||
3151 tline->text[1] != '$'))) {
3152 error(ERR_NONFATAL, "`%s' expects a macro identifier",
3153 pp_directives[i]);
3154 free_tlist(origline);
3155 return DIRECTIVE_FOUND;
3158 ctx = get_ctx(tline->text, &mname, false);
3159 last = tline;
3160 tline = expand_smacro(tline->next);
3161 last->next = NULL;
3163 while (tok_type_(tline, TOK_WHITESPACE))
3164 tline = delete_Token(tline);
3166 p = detoken(tline, false);
3167 macro_start = nasm_malloc(sizeof(*macro_start));
3168 macro_start->next = NULL;
3169 macro_start->text = nasm_quote(p, strlen(p));
3170 macro_start->type = TOK_STRING;
3171 macro_start->a.mac = NULL;
3172 nasm_free(p);
3175 * We now have a macro name, an implicit parameter count of
3176 * zero, and a string token to use as an expansion. Create
3177 * and store an SMacro.
3179 define_smacro(ctx, mname, casesense, 0, macro_start);
3180 free_tlist(origline);
3181 return DIRECTIVE_FOUND;
3183 case PP_DEFTOK:
3184 case PP_IDEFTOK:
3185 casesense = (i == PP_DEFTOK);
3187 tline = tline->next;
3188 skip_white_(tline);
3189 tline = expand_id(tline);
3190 if (!tline || (tline->type != TOK_ID &&
3191 (tline->type != TOK_PREPROC_ID ||
3192 tline->text[1] != '$'))) {
3193 error(ERR_NONFATAL,
3194 "`%s' expects a macro identifier as first parameter",
3195 pp_directives[i]);
3196 free_tlist(origline);
3197 return DIRECTIVE_FOUND;
3199 ctx = get_ctx(tline->text, &mname, false);
3200 last = tline;
3201 tline = expand_smacro(tline->next);
3202 last->next = NULL;
3204 t = tline;
3205 while (tok_type_(t, TOK_WHITESPACE))
3206 t = t->next;
3207 /* t should now point to the string */
3208 if (!tok_type_(t, TOK_STRING)) {
3209 error(ERR_NONFATAL,
3210 "`%s` requires string as second parameter",
3211 pp_directives[i]);
3212 free_tlist(tline);
3213 free_tlist(origline);
3214 return DIRECTIVE_FOUND;
3218 * Convert the string to a token stream. Note that smacros
3219 * are stored with the token stream reversed, so we have to
3220 * reverse the output of tokenize().
3222 nasm_unquote_cstr(t->text, i);
3223 macro_start = reverse_tokens(tokenize(t->text));
3226 * We now have a macro name, an implicit parameter count of
3227 * zero, and a numeric token to use as an expansion. Create
3228 * and store an SMacro.
3230 define_smacro(ctx, mname, casesense, 0, macro_start);
3231 free_tlist(tline);
3232 free_tlist(origline);
3233 return DIRECTIVE_FOUND;
3235 case PP_PATHSEARCH:
3237 FILE *fp;
3238 StrList *xsl = NULL;
3239 StrList **xst = &xsl;
3241 casesense = true;
3243 tline = tline->next;
3244 skip_white_(tline);
3245 tline = expand_id(tline);
3246 if (!tline || (tline->type != TOK_ID &&
3247 (tline->type != TOK_PREPROC_ID ||
3248 tline->text[1] != '$'))) {
3249 error(ERR_NONFATAL,
3250 "`%%pathsearch' expects a macro identifier as first parameter");
3251 free_tlist(origline);
3252 return DIRECTIVE_FOUND;
3254 ctx = get_ctx(tline->text, &mname, false);
3255 last = tline;
3256 tline = expand_smacro(tline->next);
3257 last->next = NULL;
3259 t = tline;
3260 while (tok_type_(t, TOK_WHITESPACE))
3261 t = t->next;
3263 if (!t || (t->type != TOK_STRING &&
3264 t->type != TOK_INTERNAL_STRING)) {
3265 error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
3266 free_tlist(tline);
3267 free_tlist(origline);
3268 return DIRECTIVE_FOUND; /* but we did _something_ */
3270 if (t->next)
3271 error(ERR_WARNING|ERR_PASS1,
3272 "trailing garbage after `%%pathsearch' ignored");
3273 p = t->text;
3274 if (t->type != TOK_INTERNAL_STRING)
3275 nasm_unquote(p, NULL);
3277 fp = inc_fopen(p, &xsl, &xst, true);
3278 if (fp) {
3279 p = xsl->str;
3280 fclose(fp); /* Don't actually care about the file */
3282 macro_start = nasm_malloc(sizeof(*macro_start));
3283 macro_start->next = NULL;
3284 macro_start->text = nasm_quote(p, strlen(p));
3285 macro_start->type = TOK_STRING;
3286 macro_start->a.mac = NULL;
3287 if (xsl)
3288 nasm_free(xsl);
3291 * We now have a macro name, an implicit parameter count of
3292 * zero, and a string token to use as an expansion. Create
3293 * and store an SMacro.
3295 define_smacro(ctx, mname, casesense, 0, macro_start);
3296 free_tlist(tline);
3297 free_tlist(origline);
3298 return DIRECTIVE_FOUND;
3301 case PP_STRLEN:
3302 casesense = true;
3304 tline = tline->next;
3305 skip_white_(tline);
3306 tline = expand_id(tline);
3307 if (!tline || (tline->type != TOK_ID &&
3308 (tline->type != TOK_PREPROC_ID ||
3309 tline->text[1] != '$'))) {
3310 error(ERR_NONFATAL,
3311 "`%%strlen' expects a macro identifier as first parameter");
3312 free_tlist(origline);
3313 return DIRECTIVE_FOUND;
3315 ctx = get_ctx(tline->text, &mname, false);
3316 last = tline;
3317 tline = expand_smacro(tline->next);
3318 last->next = NULL;
3320 t = tline;
3321 while (tok_type_(t, TOK_WHITESPACE))
3322 t = t->next;
3323 /* t should now point to the string */
3324 if (!tok_type_(t, TOK_STRING)) {
3325 error(ERR_NONFATAL,
3326 "`%%strlen` requires string as second parameter");
3327 free_tlist(tline);
3328 free_tlist(origline);
3329 return DIRECTIVE_FOUND;
3332 macro_start = nasm_malloc(sizeof(*macro_start));
3333 macro_start->next = NULL;
3334 make_tok_num(macro_start, nasm_unquote(t->text, NULL));
3335 macro_start->a.mac = NULL;
3338 * We now have a macro name, an implicit parameter count of
3339 * zero, and a numeric token to use as an expansion. Create
3340 * and store an SMacro.
3342 define_smacro(ctx, mname, casesense, 0, macro_start);
3343 free_tlist(tline);
3344 free_tlist(origline);
3345 return DIRECTIVE_FOUND;
3347 case PP_STRCAT:
3348 casesense = true;
3350 tline = tline->next;
3351 skip_white_(tline);
3352 tline = expand_id(tline);
3353 if (!tline || (tline->type != TOK_ID &&
3354 (tline->type != TOK_PREPROC_ID ||
3355 tline->text[1] != '$'))) {
3356 error(ERR_NONFATAL,
3357 "`%%strcat' expects a macro identifier as first parameter");
3358 free_tlist(origline);
3359 return DIRECTIVE_FOUND;
3361 ctx = get_ctx(tline->text, &mname, false);
3362 last = tline;
3363 tline = expand_smacro(tline->next);
3364 last->next = NULL;
3366 len = 0;
3367 list_for_each(t, tline) {
3368 switch (t->type) {
3369 case TOK_WHITESPACE:
3370 break;
3371 case TOK_STRING:
3372 len += t->a.len = nasm_unquote(t->text, NULL);
3373 break;
3374 case TOK_OTHER:
3375 if (!strcmp(t->text, ",")) /* permit comma separators */
3376 break;
3377 /* else fall through */
3378 default:
3379 error(ERR_NONFATAL,
3380 "non-string passed to `%%strcat' (%d)", t->type);
3381 free_tlist(tline);
3382 free_tlist(origline);
3383 return DIRECTIVE_FOUND;
3387 p = pp = nasm_malloc(len);
3388 list_for_each(t, tline) {
3389 if (t->type == TOK_STRING) {
3390 memcpy(p, t->text, t->a.len);
3391 p += t->a.len;
3396 * We now have a macro name, an implicit parameter count of
3397 * zero, and a numeric token to use as an expansion. Create
3398 * and store an SMacro.
3400 macro_start = new_Token(NULL, TOK_STRING, NULL, 0);
3401 macro_start->text = nasm_quote(pp, len);
3402 nasm_free(pp);
3403 define_smacro(ctx, mname, casesense, 0, macro_start);
3404 free_tlist(tline);
3405 free_tlist(origline);
3406 return DIRECTIVE_FOUND;
3408 case PP_SUBSTR:
3410 int64_t start, count;
3411 size_t len;
3413 casesense = true;
3415 tline = tline->next;
3416 skip_white_(tline);
3417 tline = expand_id(tline);
3418 if (!tline || (tline->type != TOK_ID &&
3419 (tline->type != TOK_PREPROC_ID ||
3420 tline->text[1] != '$'))) {
3421 error(ERR_NONFATAL,
3422 "`%%substr' expects a macro identifier as first parameter");
3423 free_tlist(origline);
3424 return DIRECTIVE_FOUND;
3426 ctx = get_ctx(tline->text, &mname, false);
3427 last = tline;
3428 tline = expand_smacro(tline->next);
3429 last->next = NULL;
3431 if (tline) /* skip expanded id */
3432 t = tline->next;
3433 while (tok_type_(t, TOK_WHITESPACE))
3434 t = t->next;
3436 /* t should now point to the string */
3437 if (!tok_type_(t, TOK_STRING)) {
3438 error(ERR_NONFATAL,
3439 "`%%substr` requires string as second parameter");
3440 free_tlist(tline);
3441 free_tlist(origline);
3442 return DIRECTIVE_FOUND;
3445 tt = t->next;
3446 tptr = &tt;
3447 tokval.t_type = TOKEN_INVALID;
3448 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3449 pass, error, NULL);
3450 if (!evalresult) {
3451 free_tlist(tline);
3452 free_tlist(origline);
3453 return DIRECTIVE_FOUND;
3454 } else if (!is_simple(evalresult)) {
3455 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3456 free_tlist(tline);
3457 free_tlist(origline);
3458 return DIRECTIVE_FOUND;
3460 start = evalresult->value - 1;
3462 while (tok_type_(tt, TOK_WHITESPACE))
3463 tt = tt->next;
3464 if (!tt) {
3465 count = 1; /* Backwards compatibility: one character */
3466 } else {
3467 tokval.t_type = TOKEN_INVALID;
3468 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3469 pass, error, NULL);
3470 if (!evalresult) {
3471 free_tlist(tline);
3472 free_tlist(origline);
3473 return DIRECTIVE_FOUND;
3474 } else if (!is_simple(evalresult)) {
3475 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3476 free_tlist(tline);
3477 free_tlist(origline);
3478 return DIRECTIVE_FOUND;
3480 count = evalresult->value;
3483 len = nasm_unquote(t->text, NULL);
3485 /* make start and count being in range */
3486 if (start < 0)
3487 start = 0;
3488 if (count < 0)
3489 count = len + count + 1 - start;
3490 if (start + count > (int64_t)len)
3491 count = len - start;
3492 if (!len || count < 0 || start >=(int64_t)len)
3493 start = -1, count = 0; /* empty string */
3495 macro_start = nasm_malloc(sizeof(*macro_start));
3496 macro_start->next = NULL;
3497 macro_start->text = nasm_quote((start < 0) ? "" : t->text + start, count);
3498 macro_start->type = TOK_STRING;
3499 macro_start->a.mac = NULL;
3502 * We now have a macro name, an implicit parameter count of
3503 * zero, and a numeric token to use as an expansion. Create
3504 * and store an SMacro.
3506 define_smacro(ctx, mname, casesense, 0, macro_start);
3507 free_tlist(tline);
3508 free_tlist(origline);
3509 return DIRECTIVE_FOUND;
3512 case PP_ASSIGN:
3513 case PP_IASSIGN:
3514 casesense = (i == PP_ASSIGN);
3516 tline = tline->next;
3517 skip_white_(tline);
3518 tline = expand_id(tline);
3519 if (!tline || (tline->type != TOK_ID &&
3520 (tline->type != TOK_PREPROC_ID ||
3521 tline->text[1] != '$'))) {
3522 error(ERR_NONFATAL,
3523 "`%%%sassign' expects a macro identifier",
3524 (i == PP_IASSIGN ? "i" : ""));
3525 free_tlist(origline);
3526 return DIRECTIVE_FOUND;
3528 ctx = get_ctx(tline->text, &mname, false);
3529 last = tline;
3530 tline = expand_smacro(tline->next);
3531 last->next = NULL;
3533 t = tline;
3534 tptr = &t;
3535 tokval.t_type = TOKEN_INVALID;
3536 evalresult =
3537 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3538 free_tlist(tline);
3539 if (!evalresult) {
3540 free_tlist(origline);
3541 return DIRECTIVE_FOUND;
3544 if (tokval.t_type)
3545 error(ERR_WARNING|ERR_PASS1,
3546 "trailing garbage after expression ignored");
3548 if (!is_simple(evalresult)) {
3549 error(ERR_NONFATAL,
3550 "non-constant value given to `%%%sassign'",
3551 (i == PP_IASSIGN ? "i" : ""));
3552 free_tlist(origline);
3553 return DIRECTIVE_FOUND;
3556 macro_start = nasm_malloc(sizeof(*macro_start));
3557 macro_start->next = NULL;
3558 make_tok_num(macro_start, reloc_value(evalresult));
3559 macro_start->a.mac = NULL;
3562 * We now have a macro name, an implicit parameter count of
3563 * zero, and a numeric token to use as an expansion. Create
3564 * and store an SMacro.
3566 define_smacro(ctx, mname, casesense, 0, macro_start);
3567 free_tlist(origline);
3568 return DIRECTIVE_FOUND;
3570 case PP_LINE:
3572 * Syntax is `%line nnn[+mmm] [filename]'
3574 tline = tline->next;
3575 skip_white_(tline);
3576 if (!tok_type_(tline, TOK_NUMBER)) {
3577 error(ERR_NONFATAL, "`%%line' expects line number");
3578 free_tlist(origline);
3579 return DIRECTIVE_FOUND;
3581 k = readnum(tline->text, &err);
3582 m = 1;
3583 tline = tline->next;
3584 if (tok_is_(tline, "+")) {
3585 tline = tline->next;
3586 if (!tok_type_(tline, TOK_NUMBER)) {
3587 error(ERR_NONFATAL, "`%%line' expects line increment");
3588 free_tlist(origline);
3589 return DIRECTIVE_FOUND;
3591 m = readnum(tline->text, &err);
3592 tline = tline->next;
3594 skip_white_(tline);
3595 src_set_linnum(k);
3596 istk->lineinc = m;
3597 if (tline) {
3598 nasm_free(src_set_fname(detoken(tline, false)));
3600 free_tlist(origline);
3601 return DIRECTIVE_FOUND;
3603 default:
3604 error(ERR_FATAL,
3605 "preprocessor directive `%s' not yet implemented",
3606 pp_directives[i]);
3607 return DIRECTIVE_FOUND;
3612 * Ensure that a macro parameter contains a condition code and
3613 * nothing else. Return the condition code index if so, or -1
3614 * otherwise.
3616 static int find_cc(Token * t)
3618 Token *tt;
3619 int i, j, k, m;
3621 if (!t)
3622 return -1; /* Probably a %+ without a space */
3624 skip_white_(t);
3625 if (t->type != TOK_ID)
3626 return -1;
3627 tt = t->next;
3628 skip_white_(tt);
3629 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
3630 return -1;
3632 i = -1;
3633 j = ARRAY_SIZE(conditions);
3634 while (j - i > 1) {
3635 k = (j + i) / 2;
3636 m = nasm_stricmp(t->text, conditions[k]);
3637 if (m == 0) {
3638 i = k;
3639 j = -2;
3640 break;
3641 } else if (m < 0) {
3642 j = k;
3643 } else
3644 i = k;
3646 if (j != -2)
3647 return -1;
3648 return i;
3651 static bool paste_tokens(Token **head, const struct tokseq_match *m,
3652 int mnum, bool handle_paste_tokens)
3654 Token **tail, *t, *tt;
3655 Token **paste_head;
3656 bool did_paste = false;
3657 char *tmp;
3658 int i;
3660 /* Now handle token pasting... */
3661 paste_head = NULL;
3662 tail = head;
3663 while ((t = *tail) && (tt = t->next)) {
3664 switch (t->type) {
3665 case TOK_WHITESPACE:
3666 if (tt->type == TOK_WHITESPACE) {
3667 /* Zap adjacent whitespace tokens */
3668 t->next = delete_Token(tt);
3669 } else {
3670 /* Do not advance paste_head here */
3671 tail = &t->next;
3673 break;
3674 case TOK_PASTE: /* %+ */
3675 if (handle_paste_tokens) {
3676 /* Zap %+ and whitespace tokens to the right */
3677 while (t && (t->type == TOK_WHITESPACE ||
3678 t->type == TOK_PASTE))
3679 t = *tail = delete_Token(t);
3680 if (!paste_head || !t)
3681 break; /* Nothing to paste with */
3682 tail = paste_head;
3683 t = *tail;
3684 tt = t->next;
3685 while (tok_type_(tt, TOK_WHITESPACE))
3686 tt = t->next = delete_Token(tt);
3687 if (tt) {
3688 tmp = nasm_strcat(t->text, tt->text);
3689 delete_Token(t);
3690 tt = delete_Token(tt);
3691 t = *tail = tokenize(tmp);
3692 nasm_free(tmp);
3693 while (t->next) {
3694 tail = &t->next;
3695 t = t->next;
3697 t->next = tt; /* Attach the remaining token chain */
3698 did_paste = true;
3700 paste_head = tail;
3701 tail = &t->next;
3702 break;
3704 /* else fall through */
3705 default:
3707 * Concatenation of tokens might look nontrivial
3708 * but in real it's pretty simple -- the caller
3709 * prepares the masks of token types to be concatenated
3710 * and we simply find matched sequences and slip
3711 * them together
3713 for (i = 0; i < mnum; i++) {
3714 if (PP_CONCAT_MASK(t->type) & m[i].mask_head) {
3715 size_t len = 0;
3716 char *tmp, *p;
3718 while (tt && (PP_CONCAT_MASK(tt->type) & m[i].mask_tail)) {
3719 len += strlen(tt->text);
3720 tt = tt->next;
3724 * Now tt points to the first token after
3725 * the potential paste area...
3727 if (tt != t->next) {
3728 /* We have at least two tokens... */
3729 len += strlen(t->text);
3730 p = tmp = nasm_malloc(len+1);
3731 while (t != tt) {
3732 strcpy(p, t->text);
3733 p = strchr(p, '\0');
3734 t = delete_Token(t);
3736 t = *tail = tokenize(tmp);
3737 nasm_free(tmp);
3738 while (t->next) {
3739 tail = &t->next;
3740 t = t->next;
3742 t->next = tt; /* Attach the remaining token chain */
3743 did_paste = true;
3745 paste_head = tail;
3746 tail = &t->next;
3747 break;
3750 if (i >= mnum) { /* no match */
3751 tail = &t->next;
3752 if (!tok_type_(t->next, TOK_WHITESPACE))
3753 paste_head = tail;
3755 break;
3758 return did_paste;
3762 * expands to a list of tokens from %{x:y}
3764 static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
3766 Token *t = tline, **tt, *tm, *head;
3767 char *pos;
3768 int fst, lst, j, i;
3770 pos = strchr(tline->text, ':');
3771 nasm_assert(pos);
3773 lst = atoi(pos + 1);
3774 fst = atoi(tline->text + 1);
3777 * only macros params are accounted so
3778 * if someone passes %0 -- we reject such
3779 * value(s)
3781 if (lst == 0 || fst == 0)
3782 goto err;
3784 /* the values should be sane */
3785 if ((fst > (int)mac->nparam || fst < (-(int)mac->nparam)) ||
3786 (lst > (int)mac->nparam || lst < (-(int)mac->nparam)))
3787 goto err;
3789 fst = fst < 0 ? fst + (int)mac->nparam + 1: fst;
3790 lst = lst < 0 ? lst + (int)mac->nparam + 1: lst;
3792 /* counted from zero */
3793 fst--, lst--;
3796 * it will be at least one token
3798 tm = mac->params[(fst + mac->rotate) % mac->nparam];
3799 t = new_Token(NULL, tm->type, tm->text, 0);
3800 head = t, tt = &t->next;
3801 if (fst < lst) {
3802 for (i = fst + 1; i <= lst; i++) {
3803 t = new_Token(NULL, TOK_OTHER, ",", 0);
3804 *tt = t, tt = &t->next;
3805 j = (i + mac->rotate) % mac->nparam;
3806 tm = mac->params[j];
3807 t = new_Token(NULL, tm->type, tm->text, 0);
3808 *tt = t, tt = &t->next;
3810 } else {
3811 for (i = fst - 1; i >= lst; i--) {
3812 t = new_Token(NULL, TOK_OTHER, ",", 0);
3813 *tt = t, tt = &t->next;
3814 j = (i + mac->rotate) % mac->nparam;
3815 tm = mac->params[j];
3816 t = new_Token(NULL, tm->type, tm->text, 0);
3817 *tt = t, tt = &t->next;
3821 *last = tt;
3822 return head;
3824 err:
3825 error(ERR_NONFATAL, "`%%{%s}': macro parameters out of range",
3826 &tline->text[1]);
3827 return tline;
3831 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3832 * %-n) and MMacro-local identifiers (%%foo) as well as
3833 * macro indirection (%[...]) and range (%{..:..}).
3835 static Token *expand_mmac_params(Token * tline)
3837 Token *t, *tt, **tail, *thead;
3838 bool changed = false;
3839 char *pos;
3841 tail = &thead;
3842 thead = NULL;
3844 while (tline) {
3845 if (tline->type == TOK_PREPROC_ID &&
3846 (((tline->text[1] == '+' || tline->text[1] == '-') && tline->text[2]) ||
3847 (tline->text[1] >= '0' && tline->text[1] <= '9') ||
3848 tline->text[1] == '%')) {
3849 char *text = NULL;
3850 int type = 0, cc; /* type = 0 to placate optimisers */
3851 char tmpbuf[30];
3852 unsigned int n;
3853 int i;
3854 MMacro *mac;
3856 t = tline;
3857 tline = tline->next;
3859 mac = istk->mstk;
3860 while (mac && !mac->name) /* avoid mistaking %reps for macros */
3861 mac = mac->next_active;
3862 if (!mac) {
3863 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
3864 } else {
3865 pos = strchr(t->text, ':');
3866 if (!pos) {
3867 switch (t->text[1]) {
3869 * We have to make a substitution of one of the
3870 * forms %1, %-1, %+1, %%foo, %0.
3872 case '0':
3873 type = TOK_NUMBER;
3874 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
3875 text = nasm_strdup(tmpbuf);
3876 break;
3877 case '%':
3878 type = TOK_ID;
3879 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
3880 mac->unique);
3881 text = nasm_strcat(tmpbuf, t->text + 2);
3882 break;
3883 case '-':
3884 n = atoi(t->text + 2) - 1;
3885 if (n >= mac->nparam)
3886 tt = NULL;
3887 else {
3888 if (mac->nparam > 1)
3889 n = (n + mac->rotate) % mac->nparam;
3890 tt = mac->params[n];
3892 cc = find_cc(tt);
3893 if (cc == -1) {
3894 error(ERR_NONFATAL,
3895 "macro parameter %d is not a condition code",
3896 n + 1);
3897 text = NULL;
3898 } else {
3899 type = TOK_ID;
3900 if (inverse_ccs[cc] == -1) {
3901 error(ERR_NONFATAL,
3902 "condition code `%s' is not invertible",
3903 conditions[cc]);
3904 text = NULL;
3905 } else
3906 text = nasm_strdup(conditions[inverse_ccs[cc]]);
3908 break;
3909 case '+':
3910 n = atoi(t->text + 2) - 1;
3911 if (n >= mac->nparam)
3912 tt = NULL;
3913 else {
3914 if (mac->nparam > 1)
3915 n = (n + mac->rotate) % mac->nparam;
3916 tt = mac->params[n];
3918 cc = find_cc(tt);
3919 if (cc == -1) {
3920 error(ERR_NONFATAL,
3921 "macro parameter %d is not a condition code",
3922 n + 1);
3923 text = NULL;
3924 } else {
3925 type = TOK_ID;
3926 text = nasm_strdup(conditions[cc]);
3928 break;
3929 default:
3930 n = atoi(t->text + 1) - 1;
3931 if (n >= mac->nparam)
3932 tt = NULL;
3933 else {
3934 if (mac->nparam > 1)
3935 n = (n + mac->rotate) % mac->nparam;
3936 tt = mac->params[n];
3938 if (tt) {
3939 for (i = 0; i < mac->paramlen[n]; i++) {
3940 *tail = new_Token(NULL, tt->type, tt->text, 0);
3941 tail = &(*tail)->next;
3942 tt = tt->next;
3945 text = NULL; /* we've done it here */
3946 break;
3948 } else {
3950 * seems we have a parameters range here
3952 Token *head, **last;
3953 head = expand_mmac_params_range(mac, t, &last);
3954 if (head != t) {
3955 *tail = head;
3956 *last = tline;
3957 tline = head;
3958 text = NULL;
3962 if (!text) {
3963 delete_Token(t);
3964 } else {
3965 *tail = t;
3966 tail = &t->next;
3967 t->type = type;
3968 nasm_free(t->text);
3969 t->text = text;
3970 t->a.mac = NULL;
3972 changed = true;
3973 continue;
3974 } else if (tline->type == TOK_INDIRECT) {
3975 t = tline;
3976 tline = tline->next;
3977 tt = tokenize(t->text);
3978 tt = expand_mmac_params(tt);
3979 tt = expand_smacro(tt);
3980 *tail = tt;
3981 while (tt) {
3982 tt->a.mac = NULL; /* Necessary? */
3983 tail = &tt->next;
3984 tt = tt->next;
3986 delete_Token(t);
3987 changed = true;
3988 } else {
3989 t = *tail = tline;
3990 tline = tline->next;
3991 t->a.mac = NULL;
3992 tail = &t->next;
3995 *tail = NULL;
3997 if (changed) {
3998 const struct tokseq_match t[] = {
4000 PP_CONCAT_MASK(TOK_ID) |
4001 PP_CONCAT_MASK(TOK_FLOAT), /* head */
4002 PP_CONCAT_MASK(TOK_ID) |
4003 PP_CONCAT_MASK(TOK_NUMBER) |
4004 PP_CONCAT_MASK(TOK_FLOAT) |
4005 PP_CONCAT_MASK(TOK_OTHER) /* tail */
4008 PP_CONCAT_MASK(TOK_NUMBER), /* head */
4009 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
4012 paste_tokens(&thead, t, ARRAY_SIZE(t), false);
4015 return thead;
4019 * Expand all single-line macro calls made in the given line.
4020 * Return the expanded version of the line. The original is deemed
4021 * to be destroyed in the process. (In reality we'll just move
4022 * Tokens from input to output a lot of the time, rather than
4023 * actually bothering to destroy and replicate.)
4026 static Token *expand_smacro(Token * tline)
4028 Token *t, *tt, *mstart, **tail, *thead;
4029 SMacro *head = NULL, *m;
4030 Token **params;
4031 int *paramsize;
4032 unsigned int nparam, sparam;
4033 int brackets;
4034 Token *org_tline = tline;
4035 Context *ctx;
4036 const char *mname;
4037 int deadman = DEADMAN_LIMIT;
4038 bool expanded;
4041 * Trick: we should avoid changing the start token pointer since it can
4042 * be contained in "next" field of other token. Because of this
4043 * we allocate a copy of first token and work with it; at the end of
4044 * routine we copy it back
4046 if (org_tline) {
4047 tline = new_Token(org_tline->next, org_tline->type,
4048 org_tline->text, 0);
4049 tline->a.mac = org_tline->a.mac;
4050 nasm_free(org_tline->text);
4051 org_tline->text = NULL;
4054 expanded = true; /* Always expand %+ at least once */
4056 again:
4057 thead = NULL;
4058 tail = &thead;
4060 while (tline) { /* main token loop */
4061 if (!--deadman) {
4062 error(ERR_NONFATAL, "interminable macro recursion");
4063 goto err;
4066 if ((mname = tline->text)) {
4067 /* if this token is a local macro, look in local context */
4068 if (tline->type == TOK_ID) {
4069 head = (SMacro *)hash_findix(&smacros, mname);
4070 } else if (tline->type == TOK_PREPROC_ID) {
4071 ctx = get_ctx(mname, &mname, true);
4072 head = ctx ? (SMacro *)hash_findix(&ctx->localmac, mname) : NULL;
4073 } else
4074 head = NULL;
4077 * We've hit an identifier. As in is_mmacro below, we first
4078 * check whether the identifier is a single-line macro at
4079 * all, then think about checking for parameters if
4080 * necessary.
4082 list_for_each(m, head)
4083 if (!mstrcmp(m->name, mname, m->casesense))
4084 break;
4085 if (m) {
4086 mstart = tline;
4087 params = NULL;
4088 paramsize = NULL;
4089 if (m->nparam == 0) {
4091 * Simple case: the macro is parameterless. Discard the
4092 * one token that the macro call took, and push the
4093 * expansion back on the to-do stack.
4095 if (!m->expansion) {
4096 if (!strcmp("__FILE__", m->name)) {
4097 int32_t num = 0;
4098 char *file = NULL;
4099 src_get(&num, &file);
4100 tline->text = nasm_quote(file, strlen(file));
4101 tline->type = TOK_STRING;
4102 nasm_free(file);
4103 continue;
4105 if (!strcmp("__LINE__", m->name)) {
4106 nasm_free(tline->text);
4107 make_tok_num(tline, src_get_linnum());
4108 continue;
4110 if (!strcmp("__BITS__", m->name)) {
4111 nasm_free(tline->text);
4112 make_tok_num(tline, globalbits);
4113 continue;
4115 tline = delete_Token(tline);
4116 continue;
4118 } else {
4120 * Complicated case: at least one macro with this name
4121 * exists and takes parameters. We must find the
4122 * parameters in the call, count them, find the SMacro
4123 * that corresponds to that form of the macro call, and
4124 * substitute for the parameters when we expand. What a
4125 * pain.
4127 /*tline = tline->next;
4128 skip_white_(tline); */
4129 do {
4130 t = tline->next;
4131 while (tok_type_(t, TOK_SMAC_END)) {
4132 t->a.mac->in_progress = false;
4133 t->text = NULL;
4134 t = tline->next = delete_Token(t);
4136 tline = t;
4137 } while (tok_type_(tline, TOK_WHITESPACE));
4138 if (!tok_is_(tline, "(")) {
4140 * This macro wasn't called with parameters: ignore
4141 * the call. (Behaviour borrowed from gnu cpp.)
4143 tline = mstart;
4144 m = NULL;
4145 } else {
4146 int paren = 0;
4147 int white = 0;
4148 brackets = 0;
4149 nparam = 0;
4150 sparam = PARAM_DELTA;
4151 params = nasm_malloc(sparam * sizeof(Token *));
4152 params[0] = tline->next;
4153 paramsize = nasm_malloc(sparam * sizeof(int));
4154 paramsize[0] = 0;
4155 while (true) { /* parameter loop */
4157 * For some unusual expansions
4158 * which concatenates function call
4160 t = tline->next;
4161 while (tok_type_(t, TOK_SMAC_END)) {
4162 t->a.mac->in_progress = false;
4163 t->text = NULL;
4164 t = tline->next = delete_Token(t);
4166 tline = t;
4168 if (!tline) {
4169 error(ERR_NONFATAL,
4170 "macro call expects terminating `)'");
4171 break;
4173 if (tline->type == TOK_WHITESPACE
4174 && brackets <= 0) {
4175 if (paramsize[nparam])
4176 white++;
4177 else
4178 params[nparam] = tline->next;
4179 continue; /* parameter loop */
4181 if (tline->type == TOK_OTHER
4182 && tline->text[1] == 0) {
4183 char ch = tline->text[0];
4184 if (ch == ',' && !paren && brackets <= 0) {
4185 if (++nparam >= sparam) {
4186 sparam += PARAM_DELTA;
4187 params = nasm_realloc(params,
4188 sparam * sizeof(Token *));
4189 paramsize = nasm_realloc(paramsize,
4190 sparam * sizeof(int));
4192 params[nparam] = tline->next;
4193 paramsize[nparam] = 0;
4194 white = 0;
4195 continue; /* parameter loop */
4197 if (ch == '{' &&
4198 (brackets > 0 || (brackets == 0 &&
4199 !paramsize[nparam])))
4201 if (!(brackets++)) {
4202 params[nparam] = tline->next;
4203 continue; /* parameter loop */
4206 if (ch == '}' && brackets > 0)
4207 if (--brackets == 0) {
4208 brackets = -1;
4209 continue; /* parameter loop */
4211 if (ch == '(' && !brackets)
4212 paren++;
4213 if (ch == ')' && brackets <= 0)
4214 if (--paren < 0)
4215 break;
4217 if (brackets < 0) {
4218 brackets = 0;
4219 error(ERR_NONFATAL, "braces do not "
4220 "enclose all of macro parameter");
4222 paramsize[nparam] += white + 1;
4223 white = 0;
4224 } /* parameter loop */
4225 nparam++;
4226 while (m && (m->nparam != nparam ||
4227 mstrcmp(m->name, mname,
4228 m->casesense)))
4229 m = m->next;
4230 if (!m)
4231 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
4232 "macro `%s' exists, "
4233 "but not taking %d parameters",
4234 mstart->text, nparam);
4237 if (m && m->in_progress)
4238 m = NULL;
4239 if (!m) { /* in progess or didn't find '(' or wrong nparam */
4241 * Design question: should we handle !tline, which
4242 * indicates missing ')' here, or expand those
4243 * macros anyway, which requires the (t) test a few
4244 * lines down?
4246 nasm_free(params);
4247 nasm_free(paramsize);
4248 tline = mstart;
4249 } else {
4251 * Expand the macro: we are placed on the last token of the
4252 * call, so that we can easily split the call from the
4253 * following tokens. We also start by pushing an SMAC_END
4254 * token for the cycle removal.
4256 t = tline;
4257 if (t) {
4258 tline = t->next;
4259 t->next = NULL;
4261 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
4262 tt->a.mac = m;
4263 m->in_progress = true;
4264 tline = tt;
4265 list_for_each(t, m->expansion) {
4266 if (t->type >= TOK_SMAC_PARAM) {
4267 Token *pcopy = tline, **ptail = &pcopy;
4268 Token *ttt, *pt;
4269 int i;
4271 ttt = params[t->type - TOK_SMAC_PARAM];
4272 i = paramsize[t->type - TOK_SMAC_PARAM];
4273 while (--i >= 0) {
4274 pt = *ptail = new_Token(tline, ttt->type,
4275 ttt->text, 0);
4276 ptail = &pt->next;
4277 ttt = ttt->next;
4279 tline = pcopy;
4280 } else if (t->type == TOK_PREPROC_Q) {
4281 tt = new_Token(tline, TOK_ID, mname, 0);
4282 tline = tt;
4283 } else if (t->type == TOK_PREPROC_QQ) {
4284 tt = new_Token(tline, TOK_ID, m->name, 0);
4285 tline = tt;
4286 } else {
4287 tt = new_Token(tline, t->type, t->text, 0);
4288 tline = tt;
4293 * Having done that, get rid of the macro call, and clean
4294 * up the parameters.
4296 nasm_free(params);
4297 nasm_free(paramsize);
4298 free_tlist(mstart);
4299 expanded = true;
4300 continue; /* main token loop */
4305 if (tline->type == TOK_SMAC_END) {
4306 tline->a.mac->in_progress = false;
4307 tline = delete_Token(tline);
4308 } else {
4309 t = *tail = tline;
4310 tline = tline->next;
4311 t->a.mac = NULL;
4312 t->next = NULL;
4313 tail = &t->next;
4318 * Now scan the entire line and look for successive TOK_IDs that resulted
4319 * after expansion (they can't be produced by tokenize()). The successive
4320 * TOK_IDs should be concatenated.
4321 * Also we look for %+ tokens and concatenate the tokens before and after
4322 * them (without white spaces in between).
4324 if (expanded) {
4325 const struct tokseq_match t[] = {
4327 PP_CONCAT_MASK(TOK_ID) |
4328 PP_CONCAT_MASK(TOK_PREPROC_ID), /* head */
4329 PP_CONCAT_MASK(TOK_ID) |
4330 PP_CONCAT_MASK(TOK_PREPROC_ID) |
4331 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
4334 if (paste_tokens(&thead, t, ARRAY_SIZE(t), true)) {
4336 * If we concatenated something, *and* we had previously expanded
4337 * an actual macro, scan the lines again for macros...
4339 tline = thead;
4340 expanded = false;
4341 goto again;
4345 err:
4346 if (org_tline) {
4347 if (thead) {
4348 *org_tline = *thead;
4349 /* since we just gave text to org_line, don't free it */
4350 thead->text = NULL;
4351 delete_Token(thead);
4352 } else {
4353 /* the expression expanded to empty line;
4354 we can't return NULL for some reasons
4355 we just set the line to a single WHITESPACE token. */
4356 memset(org_tline, 0, sizeof(*org_tline));
4357 org_tline->text = NULL;
4358 org_tline->type = TOK_WHITESPACE;
4360 thead = org_tline;
4363 return thead;
4367 * Similar to expand_smacro but used exclusively with macro identifiers
4368 * right before they are fetched in. The reason is that there can be
4369 * identifiers consisting of several subparts. We consider that if there
4370 * are more than one element forming the name, user wants a expansion,
4371 * otherwise it will be left as-is. Example:
4373 * %define %$abc cde
4375 * the identifier %$abc will be left as-is so that the handler for %define
4376 * will suck it and define the corresponding value. Other case:
4378 * %define _%$abc cde
4380 * In this case user wants name to be expanded *before* %define starts
4381 * working, so we'll expand %$abc into something (if it has a value;
4382 * otherwise it will be left as-is) then concatenate all successive
4383 * PP_IDs into one.
4385 static Token *expand_id(Token * tline)
4387 Token *cur, *oldnext = NULL;
4389 if (!tline || !tline->next)
4390 return tline;
4392 cur = tline;
4393 while (cur->next &&
4394 (cur->next->type == TOK_ID ||
4395 cur->next->type == TOK_PREPROC_ID
4396 || cur->next->type == TOK_NUMBER))
4397 cur = cur->next;
4399 /* If identifier consists of just one token, don't expand */
4400 if (cur == tline)
4401 return tline;
4403 if (cur) {
4404 oldnext = cur->next; /* Detach the tail past identifier */
4405 cur->next = NULL; /* so that expand_smacro stops here */
4408 tline = expand_smacro(tline);
4410 if (cur) {
4411 /* expand_smacro possibly changhed tline; re-scan for EOL */
4412 cur = tline;
4413 while (cur && cur->next)
4414 cur = cur->next;
4415 if (cur)
4416 cur->next = oldnext;
4419 return tline;
4423 * Determine whether the given line constitutes a multi-line macro
4424 * call, and return the MMacro structure called if so. Doesn't have
4425 * to check for an initial label - that's taken care of in
4426 * expand_mmacro - but must check numbers of parameters. Guaranteed
4427 * to be called with tline->type == TOK_ID, so the putative macro
4428 * name is easy to find.
4430 static MMacro *is_mmacro(Token * tline, Token *** params_array)
4432 MMacro *head, *m;
4433 Token **params;
4434 int nparam;
4436 head = (MMacro *) hash_findix(&mmacros, tline->text);
4439 * Efficiency: first we see if any macro exists with the given
4440 * name. If not, we can return NULL immediately. _Then_ we
4441 * count the parameters, and then we look further along the
4442 * list if necessary to find the proper MMacro.
4444 list_for_each(m, head)
4445 if (!mstrcmp(m->name, tline->text, m->casesense))
4446 break;
4447 if (!m)
4448 return NULL;
4451 * OK, we have a potential macro. Count and demarcate the
4452 * parameters.
4454 count_mmac_params(tline->next, &nparam, &params);
4457 * So we know how many parameters we've got. Find the MMacro
4458 * structure that handles this number.
4460 while (m) {
4461 if (m->nparam_min <= nparam
4462 && (m->plus || nparam <= m->nparam_max)) {
4464 * This one is right. Just check if cycle removal
4465 * prohibits us using it before we actually celebrate...
4467 if (m->in_progress > m->max_depth) {
4468 if (m->max_depth > 0) {
4469 error(ERR_WARNING,
4470 "reached maximum recursion depth of %i",
4471 m->max_depth);
4473 nasm_free(params);
4474 return NULL;
4477 * It's right, and we can use it. Add its default
4478 * parameters to the end of our list if necessary.
4480 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
4481 params =
4482 nasm_realloc(params,
4483 ((m->nparam_min + m->ndefs +
4484 1) * sizeof(*params)));
4485 while (nparam < m->nparam_min + m->ndefs) {
4486 params[nparam] = m->defaults[nparam - m->nparam_min];
4487 nparam++;
4491 * If we've gone over the maximum parameter count (and
4492 * we're in Plus mode), ignore parameters beyond
4493 * nparam_max.
4495 if (m->plus && nparam > m->nparam_max)
4496 nparam = m->nparam_max;
4498 * Then terminate the parameter list, and leave.
4500 if (!params) { /* need this special case */
4501 params = nasm_malloc(sizeof(*params));
4502 nparam = 0;
4504 params[nparam] = NULL;
4505 *params_array = params;
4506 return m;
4509 * This one wasn't right: look for the next one with the
4510 * same name.
4512 list_for_each(m, m->next)
4513 if (!mstrcmp(m->name, tline->text, m->casesense))
4514 break;
4518 * After all that, we didn't find one with the right number of
4519 * parameters. Issue a warning, and fail to expand the macro.
4521 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
4522 "macro `%s' exists, but not taking %d parameters",
4523 tline->text, nparam);
4524 nasm_free(params);
4525 return NULL;
4530 * Save MMacro invocation specific fields in
4531 * preparation for a recursive macro expansion
4533 static void push_mmacro(MMacro *m)
4535 MMacroInvocation *i;
4537 i = nasm_malloc(sizeof(MMacroInvocation));
4538 i->prev = m->prev;
4539 i->params = m->params;
4540 i->iline = m->iline;
4541 i->nparam = m->nparam;
4542 i->rotate = m->rotate;
4543 i->paramlen = m->paramlen;
4544 i->unique = m->unique;
4545 i->condcnt = m->condcnt;
4546 m->prev = i;
4551 * Restore MMacro invocation specific fields that were
4552 * saved during a previous recursive macro expansion
4554 static void pop_mmacro(MMacro *m)
4556 MMacroInvocation *i;
4558 if (m->prev) {
4559 i = m->prev;
4560 m->prev = i->prev;
4561 m->params = i->params;
4562 m->iline = i->iline;
4563 m->nparam = i->nparam;
4564 m->rotate = i->rotate;
4565 m->paramlen = i->paramlen;
4566 m->unique = i->unique;
4567 m->condcnt = i->condcnt;
4568 nasm_free(i);
4574 * Expand the multi-line macro call made by the given line, if
4575 * there is one to be expanded. If there is, push the expansion on
4576 * istk->expansion and return 1. Otherwise return 0.
4578 static int expand_mmacro(Token * tline)
4580 Token *startline = tline;
4581 Token *label = NULL;
4582 int dont_prepend = 0;
4583 Token **params, *t, *mtok, *tt;
4584 MMacro *m;
4585 Line *l, *ll;
4586 int i, nparam, *paramlen;
4587 const char *mname;
4589 t = tline;
4590 skip_white_(t);
4591 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4592 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
4593 return 0;
4594 mtok = t;
4595 m = is_mmacro(t, &params);
4596 if (m) {
4597 mname = t->text;
4598 } else {
4599 Token *last;
4601 * We have an id which isn't a macro call. We'll assume
4602 * it might be a label; we'll also check to see if a
4603 * colon follows it. Then, if there's another id after
4604 * that lot, we'll check it again for macro-hood.
4606 label = last = t;
4607 t = t->next;
4608 if (tok_type_(t, TOK_WHITESPACE))
4609 last = t, t = t->next;
4610 if (tok_is_(t, ":")) {
4611 dont_prepend = 1;
4612 last = t, t = t->next;
4613 if (tok_type_(t, TOK_WHITESPACE))
4614 last = t, t = t->next;
4616 if (!tok_type_(t, TOK_ID) || !(m = is_mmacro(t, &params)))
4617 return 0;
4618 last->next = NULL;
4619 mname = t->text;
4620 tline = t;
4624 * Fix up the parameters: this involves stripping leading and
4625 * trailing whitespace, then stripping braces if they are
4626 * present.
4628 for (nparam = 0; params[nparam]; nparam++) ;
4629 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
4631 for (i = 0; params[i]; i++) {
4632 int brace = false;
4633 int comma = (!m->plus || i < nparam - 1);
4635 t = params[i];
4636 skip_white_(t);
4637 if (tok_is_(t, "{"))
4638 t = t->next, brace = true, comma = false;
4639 params[i] = t;
4640 paramlen[i] = 0;
4641 while (t) {
4642 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
4643 break; /* ... because we have hit a comma */
4644 if (comma && t->type == TOK_WHITESPACE
4645 && tok_is_(t->next, ","))
4646 break; /* ... or a space then a comma */
4647 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
4648 break; /* ... or a brace */
4649 t = t->next;
4650 paramlen[i]++;
4655 * OK, we have a MMacro structure together with a set of
4656 * parameters. We must now go through the expansion and push
4657 * copies of each Line on to istk->expansion. Substitution of
4658 * parameter tokens and macro-local tokens doesn't get done
4659 * until the single-line macro substitution process; this is
4660 * because delaying them allows us to change the semantics
4661 * later through %rotate.
4663 * First, push an end marker on to istk->expansion, mark this
4664 * macro as in progress, and set up its invocation-specific
4665 * variables.
4667 ll = nasm_malloc(sizeof(Line));
4668 ll->next = istk->expansion;
4669 ll->finishes = m;
4670 ll->first = NULL;
4671 istk->expansion = ll;
4674 * Save the previous MMacro expansion in the case of
4675 * macro recursion
4677 if (m->max_depth && m->in_progress)
4678 push_mmacro(m);
4680 m->in_progress ++;
4681 m->params = params;
4682 m->iline = tline;
4683 m->nparam = nparam;
4684 m->rotate = 0;
4685 m->paramlen = paramlen;
4686 m->unique = unique++;
4687 m->lineno = 0;
4688 m->condcnt = 0;
4690 m->next_active = istk->mstk;
4691 istk->mstk = m;
4693 list_for_each(l, m->expansion) {
4694 Token **tail;
4696 ll = nasm_malloc(sizeof(Line));
4697 ll->finishes = NULL;
4698 ll->next = istk->expansion;
4699 istk->expansion = ll;
4700 tail = &ll->first;
4702 list_for_each(t, l->first) {
4703 Token *x = t;
4704 switch (t->type) {
4705 case TOK_PREPROC_Q:
4706 tt = *tail = new_Token(NULL, TOK_ID, mname, 0);
4707 break;
4708 case TOK_PREPROC_QQ:
4709 tt = *tail = new_Token(NULL, TOK_ID, m->name, 0);
4710 break;
4711 case TOK_PREPROC_ID:
4712 if (t->text[1] == '0' && t->text[2] == '0') {
4713 dont_prepend = -1;
4714 x = label;
4715 if (!x)
4716 continue;
4718 /* fall through */
4719 default:
4720 tt = *tail = new_Token(NULL, x->type, x->text, 0);
4721 break;
4723 tail = &tt->next;
4725 *tail = NULL;
4729 * If we had a label, push it on as the first line of
4730 * the macro expansion.
4732 if (label) {
4733 if (dont_prepend < 0)
4734 free_tlist(startline);
4735 else {
4736 ll = nasm_malloc(sizeof(Line));
4737 ll->finishes = NULL;
4738 ll->next = istk->expansion;
4739 istk->expansion = ll;
4740 ll->first = startline;
4741 if (!dont_prepend) {
4742 while (label->next)
4743 label = label->next;
4744 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
4749 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
4751 return 1;
4754 /* The function that actually does the error reporting */
4755 static void verror(int severity, const char *fmt, va_list arg)
4757 char buff[1024];
4758 MMacro *mmac = NULL;
4759 int delta = 0;
4761 vsnprintf(buff, sizeof(buff), fmt, arg);
4763 /* get %macro name */
4764 if (istk && istk->mstk) {
4765 mmac = istk->mstk;
4766 /* but %rep blocks should be skipped */
4767 while (mmac && !mmac->name)
4768 mmac = mmac->next_active, delta++;
4771 if (mmac)
4772 nasm_error(severity, "(%s:%d) %s",
4773 mmac->name, mmac->lineno - delta, buff);
4774 else
4775 nasm_error(severity, "%s", buff);
4779 * Since preprocessor always operate only on the line that didn't
4780 * arrived yet, we should always use ERR_OFFBY1.
4782 static void error(int severity, const char *fmt, ...)
4784 va_list arg;
4786 /* If we're in a dead branch of IF or something like it, ignore the error */
4787 if (istk && istk->conds && !emitting(istk->conds->state))
4788 return;
4790 va_start(arg, fmt);
4791 verror(severity, fmt, arg);
4792 va_end(arg);
4796 * Because %else etc are evaluated in the state context
4797 * of the previous branch, errors might get lost with error():
4798 * %if 0 ... %else trailing garbage ... %endif
4799 * So %else etc should report errors with this function.
4801 static void error_precond(int severity, const char *fmt, ...)
4803 va_list arg;
4805 /* Only ignore the error if it's really in a dead branch */
4806 if (istk && istk->conds && istk->conds->state == COND_NEVER)
4807 return;
4809 va_start(arg, fmt);
4810 verror(severity, fmt, arg);
4811 va_end(arg);
4814 static void
4815 pp_reset(char *file, int apass, ListGen * listgen, StrList **deplist)
4817 Token *t;
4819 cstk = NULL;
4820 istk = nasm_malloc(sizeof(Include));
4821 istk->next = NULL;
4822 istk->conds = NULL;
4823 istk->expansion = NULL;
4824 istk->mstk = NULL;
4825 istk->fp = fopen(file, "r");
4826 istk->fname = NULL;
4827 src_set_fname(nasm_strdup(file));
4828 src_set_linnum(0);
4829 istk->lineinc = 1;
4830 if (!istk->fp)
4831 error(ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'",
4832 file);
4833 defining = NULL;
4834 nested_mac_count = 0;
4835 nested_rep_count = 0;
4836 init_macros();
4837 unique = 0;
4838 if (tasm_compatible_mode) {
4839 stdmacpos = nasm_stdmac;
4840 } else {
4841 stdmacpos = nasm_stdmac_after_tasm;
4843 any_extrastdmac = extrastdmac && *extrastdmac;
4844 do_predef = true;
4845 list = listgen;
4848 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4849 * The caller, however, will also pass in 3 for preprocess-only so
4850 * we can set __PASS__ accordingly.
4852 pass = apass > 2 ? 2 : apass;
4854 dephead = deptail = deplist;
4855 if (deplist) {
4856 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
4857 sl->next = NULL;
4858 strcpy(sl->str, file);
4859 *deptail = sl;
4860 deptail = &sl->next;
4864 * Define the __PASS__ macro. This is defined here unlike
4865 * all the other builtins, because it is special -- it varies between
4866 * passes.
4868 t = nasm_malloc(sizeof(*t));
4869 t->next = NULL;
4870 make_tok_num(t, apass);
4871 t->a.mac = NULL;
4872 define_smacro(NULL, "__PASS__", true, 0, t);
4875 static char *pp_getline(void)
4877 char *line;
4878 Token *tline;
4880 while (1) {
4882 * Fetch a tokenized line, either from the macro-expansion
4883 * buffer or from the input file.
4885 tline = NULL;
4886 while (istk->expansion && istk->expansion->finishes) {
4887 Line *l = istk->expansion;
4888 if (!l->finishes->name && l->finishes->in_progress > 1) {
4889 Line *ll;
4892 * This is a macro-end marker for a macro with no
4893 * name, which means it's not really a macro at all
4894 * but a %rep block, and the `in_progress' field is
4895 * more than 1, meaning that we still need to
4896 * repeat. (1 means the natural last repetition; 0
4897 * means termination by %exitrep.) We have
4898 * therefore expanded up to the %endrep, and must
4899 * push the whole block on to the expansion buffer
4900 * again. We don't bother to remove the macro-end
4901 * marker: we'd only have to generate another one
4902 * if we did.
4904 l->finishes->in_progress--;
4905 list_for_each(l, l->finishes->expansion) {
4906 Token *t, *tt, **tail;
4908 ll = nasm_malloc(sizeof(Line));
4909 ll->next = istk->expansion;
4910 ll->finishes = NULL;
4911 ll->first = NULL;
4912 tail = &ll->first;
4914 list_for_each(t, l->first) {
4915 if (t->text || t->type == TOK_WHITESPACE) {
4916 tt = *tail = new_Token(NULL, t->type, t->text, 0);
4917 tail = &tt->next;
4921 istk->expansion = ll;
4923 } else {
4925 * Check whether a `%rep' was started and not ended
4926 * within this macro expansion. This can happen and
4927 * should be detected. It's a fatal error because
4928 * I'm too confused to work out how to recover
4929 * sensibly from it.
4931 if (defining) {
4932 if (defining->name)
4933 error(ERR_PANIC,
4934 "defining with name in expansion");
4935 else if (istk->mstk->name)
4936 error(ERR_FATAL,
4937 "`%%rep' without `%%endrep' within"
4938 " expansion of macro `%s'",
4939 istk->mstk->name);
4943 * FIXME: investigate the relationship at this point between
4944 * istk->mstk and l->finishes
4947 MMacro *m = istk->mstk;
4948 istk->mstk = m->next_active;
4949 if (m->name) {
4951 * This was a real macro call, not a %rep, and
4952 * therefore the parameter information needs to
4953 * be freed.
4955 if (m->prev) {
4956 pop_mmacro(m);
4957 l->finishes->in_progress --;
4958 } else {
4959 nasm_free(m->params);
4960 free_tlist(m->iline);
4961 nasm_free(m->paramlen);
4962 l->finishes->in_progress = 0;
4964 } else
4965 free_mmacro(m);
4967 istk->expansion = l->next;
4968 nasm_free(l);
4969 list->downlevel(LIST_MACRO);
4972 while (1) { /* until we get a line we can use */
4974 if (istk->expansion) { /* from a macro expansion */
4975 char *p;
4976 Line *l = istk->expansion;
4977 if (istk->mstk)
4978 istk->mstk->lineno++;
4979 tline = l->first;
4980 istk->expansion = l->next;
4981 nasm_free(l);
4982 p = detoken(tline, false);
4983 list->line(LIST_MACRO, p);
4984 nasm_free(p);
4985 break;
4987 line = read_line();
4988 if (line) { /* from the current input file */
4989 line = prepreproc(line);
4990 tline = tokenize(line);
4991 nasm_free(line);
4992 break;
4995 * The current file has ended; work down the istk
4998 Include *i = istk;
4999 fclose(i->fp);
5000 if (i->conds) {
5001 /* nasm_error can't be conditionally suppressed */
5002 nasm_error(ERR_FATAL,
5003 "expected `%%endif' before end of file");
5005 /* only set line and file name if there's a next node */
5006 if (i->next) {
5007 src_set_linnum(i->lineno);
5008 nasm_free(src_set_fname(i->fname));
5010 istk = i->next;
5011 list->downlevel(LIST_INCLUDE);
5012 nasm_free(i);
5013 if (!istk)
5014 return NULL;
5015 if (istk->expansion && istk->expansion->finishes)
5016 break;
5021 * We must expand MMacro parameters and MMacro-local labels
5022 * _before_ we plunge into directive processing, to cope
5023 * with things like `%define something %1' such as STRUC
5024 * uses. Unless we're _defining_ a MMacro, in which case
5025 * those tokens should be left alone to go into the
5026 * definition; and unless we're in a non-emitting
5027 * condition, in which case we don't want to meddle with
5028 * anything.
5030 if (!defining && !(istk->conds && !emitting(istk->conds->state))
5031 && !(istk->mstk && !istk->mstk->in_progress)) {
5032 tline = expand_mmac_params(tline);
5036 * Check the line to see if it's a preprocessor directive.
5038 if (do_directive(tline) == DIRECTIVE_FOUND) {
5039 continue;
5040 } else if (defining) {
5042 * We're defining a multi-line macro. We emit nothing
5043 * at all, and just
5044 * shove the tokenized line on to the macro definition.
5046 Line *l = nasm_malloc(sizeof(Line));
5047 l->next = defining->expansion;
5048 l->first = tline;
5049 l->finishes = NULL;
5050 defining->expansion = l;
5051 continue;
5052 } else if (istk->conds && !emitting(istk->conds->state)) {
5054 * We're in a non-emitting branch of a condition block.
5055 * Emit nothing at all, not even a blank line: when we
5056 * emerge from the condition we'll give a line-number
5057 * directive so we keep our place correctly.
5059 free_tlist(tline);
5060 continue;
5061 } else if (istk->mstk && !istk->mstk->in_progress) {
5063 * We're in a %rep block which has been terminated, so
5064 * we're walking through to the %endrep without
5065 * emitting anything. Emit nothing at all, not even a
5066 * blank line: when we emerge from the %rep block we'll
5067 * give a line-number directive so we keep our place
5068 * correctly.
5070 free_tlist(tline);
5071 continue;
5072 } else {
5073 tline = expand_smacro(tline);
5074 if (!expand_mmacro(tline)) {
5076 * De-tokenize the line again, and emit it.
5078 line = detoken(tline, true);
5079 free_tlist(tline);
5080 break;
5081 } else {
5082 continue; /* expand_mmacro calls free_tlist */
5087 return line;
5090 static void pp_cleanup(int pass)
5092 if (defining) {
5093 if (defining->name) {
5094 error(ERR_NONFATAL,
5095 "end of file while still defining macro `%s'",
5096 defining->name);
5097 } else {
5098 error(ERR_NONFATAL, "end of file while still in %%rep");
5101 free_mmacro(defining);
5102 defining = NULL;
5104 while (cstk)
5105 ctx_pop();
5106 free_macros();
5107 while (istk) {
5108 Include *i = istk;
5109 istk = istk->next;
5110 fclose(i->fp);
5111 nasm_free(i->fname);
5112 nasm_free(i);
5114 while (cstk)
5115 ctx_pop();
5116 nasm_free(src_set_fname(NULL));
5117 if (pass == 0) {
5118 IncPath *i;
5119 free_llist(predef);
5120 delete_Blocks();
5121 while ((i = ipath)) {
5122 ipath = i->next;
5123 if (i->path)
5124 nasm_free(i->path);
5125 nasm_free(i);
5130 void pp_include_path(char *path)
5132 IncPath *i;
5134 i = nasm_malloc(sizeof(IncPath));
5135 i->path = path ? nasm_strdup(path) : NULL;
5136 i->next = NULL;
5138 if (ipath) {
5139 IncPath *j = ipath;
5140 while (j->next)
5141 j = j->next;
5142 j->next = i;
5143 } else {
5144 ipath = i;
5148 void pp_pre_include(char *fname)
5150 Token *inc, *space, *name;
5151 Line *l;
5153 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
5154 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
5155 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
5157 l = nasm_malloc(sizeof(Line));
5158 l->next = predef;
5159 l->first = inc;
5160 l->finishes = NULL;
5161 predef = l;
5164 void pp_pre_define(char *definition)
5166 Token *def, *space;
5167 Line *l;
5168 char *equals;
5170 equals = strchr(definition, '=');
5171 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
5172 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
5173 if (equals)
5174 *equals = ' ';
5175 space->next = tokenize(definition);
5176 if (equals)
5177 *equals = '=';
5179 l = nasm_malloc(sizeof(Line));
5180 l->next = predef;
5181 l->first = def;
5182 l->finishes = NULL;
5183 predef = l;
5186 void pp_pre_undefine(char *definition)
5188 Token *def, *space;
5189 Line *l;
5191 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
5192 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
5193 space->next = tokenize(definition);
5195 l = nasm_malloc(sizeof(Line));
5196 l->next = predef;
5197 l->first = def;
5198 l->finishes = NULL;
5199 predef = l;
5203 * Added by Keith Kanios:
5205 * This function is used to assist with "runtime" preprocessor
5206 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
5208 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5209 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5212 void pp_runtime(char *definition)
5214 Token *def;
5216 def = tokenize(definition);
5217 if (do_directive(def) == NO_DIRECTIVE_FOUND)
5218 free_tlist(def);
5222 void pp_extra_stdmac(macros_t *macros)
5224 extrastdmac = macros;
5227 static void make_tok_num(Token * tok, int64_t val)
5229 char numbuf[20];
5230 snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
5231 tok->text = nasm_strdup(numbuf);
5232 tok->type = TOK_NUMBER;
5235 Preproc nasmpp = {
5236 pp_reset,
5237 pp_getline,
5238 pp_cleanup