preproc.c: Support multiple matches in paste_tokens
[nasm.git] / preproc.c
blobea3efc5456d49043105f5b5b2d492d60a8ac85cf
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 && *p != '}') {
918 p[-1] = *p;
919 p++;
921 p[-1] = '\0';
922 if (*p)
923 p++;
924 type = TOK_PREPROC_ID;
925 } else if (*p == '[') {
926 int lvl = 1;
927 line += 2; /* Skip the leading %[ */
928 p++;
929 while (lvl && (c = *p++)) {
930 switch (c) {
931 case ']':
932 lvl--;
933 break;
934 case '%':
935 if (*p == '[')
936 lvl++;
937 break;
938 case '\'':
939 case '\"':
940 case '`':
941 p = nasm_skip_string(p - 1) + 1;
942 break;
943 default:
944 break;
947 p--;
948 if (*p)
949 *p++ = '\0';
950 if (lvl)
951 error(ERR_NONFATAL, "unterminated %[ construct");
952 type = TOK_INDIRECT;
953 } else if (*p == '?') {
954 type = TOK_PREPROC_Q; /* %? */
955 p++;
956 if (*p == '?') {
957 type = TOK_PREPROC_QQ; /* %?? */
958 p++;
960 } else if (*p == '!') {
961 type = TOK_PREPROC_ID;
962 p++;
963 if (isidchar(*p)) {
964 do {
965 p++;
966 } while (isidchar(*p));
967 } else if (*p == '\'' || *p == '\"' || *p == '`') {
968 p = nasm_skip_string(p);
969 if (*p)
970 p++;
971 else
972 error(ERR_NONFATAL|ERR_PASS1, "unterminated %! string");
973 } else {
974 /* %! without string or identifier */
975 type = TOK_OTHER; /* Legacy behavior... */
977 } else if (isidchar(*p) ||
978 ((*p == '!' || *p == '%' || *p == '$') &&
979 isidchar(p[1]))) {
980 do {
981 p++;
983 while (isidchar(*p));
984 type = TOK_PREPROC_ID;
985 } else {
986 type = TOK_OTHER;
987 if (*p == '%')
988 p++;
990 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
991 type = TOK_ID;
992 p++;
993 while (*p && isidchar(*p))
994 p++;
995 } else if (*p == '\'' || *p == '"' || *p == '`') {
997 * A string token.
999 type = TOK_STRING;
1000 p = nasm_skip_string(p);
1002 if (*p) {
1003 p++;
1004 } else {
1005 error(ERR_WARNING|ERR_PASS1, "unterminated string");
1006 /* Handling unterminated strings by UNV */
1007 /* type = -1; */
1009 } else if (p[0] == '$' && p[1] == '$') {
1010 type = TOK_OTHER; /* TOKEN_BASE */
1011 p += 2;
1012 } else if (isnumstart(*p)) {
1013 bool is_hex = false;
1014 bool is_float = false;
1015 bool has_e = false;
1016 char c, *r;
1019 * A numeric token.
1022 if (*p == '$') {
1023 p++;
1024 is_hex = true;
1027 for (;;) {
1028 c = *p++;
1030 if (!is_hex && (c == 'e' || c == 'E')) {
1031 has_e = true;
1032 if (*p == '+' || *p == '-') {
1034 * e can only be followed by +/- if it is either a
1035 * prefixed hex number or a floating-point number
1037 p++;
1038 is_float = true;
1040 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
1041 is_hex = true;
1042 } else if (c == 'P' || c == 'p') {
1043 is_float = true;
1044 if (*p == '+' || *p == '-')
1045 p++;
1046 } else if (isnumchar(c) || c == '_')
1047 ; /* just advance */
1048 else if (c == '.') {
1050 * we need to deal with consequences of the legacy
1051 * parser, like "1.nolist" being two tokens
1052 * (TOK_NUMBER, TOK_ID) here; at least give it
1053 * a shot for now. In the future, we probably need
1054 * a flex-based scanner with proper pattern matching
1055 * to do it as well as it can be done. Nothing in
1056 * the world is going to help the person who wants
1057 * 0x123.p16 interpreted as two tokens, though.
1059 r = p;
1060 while (*r == '_')
1061 r++;
1063 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
1064 (!is_hex && (*r == 'e' || *r == 'E')) ||
1065 (*r == 'p' || *r == 'P')) {
1066 p = r;
1067 is_float = true;
1068 } else
1069 break; /* Terminate the token */
1070 } else
1071 break;
1073 p--; /* Point to first character beyond number */
1075 if (p == line+1 && *line == '$') {
1076 type = TOK_OTHER; /* TOKEN_HERE */
1077 } else {
1078 if (has_e && !is_hex) {
1079 /* 1e13 is floating-point, but 1e13h is not */
1080 is_float = true;
1083 type = is_float ? TOK_FLOAT : TOK_NUMBER;
1085 } else if (nasm_isspace(*p)) {
1086 type = TOK_WHITESPACE;
1087 p = nasm_skip_spaces(p);
1089 * Whitespace just before end-of-line is discarded by
1090 * pretending it's a comment; whitespace just before a
1091 * comment gets lumped into the comment.
1093 if (!*p || *p == ';') {
1094 type = TOK_COMMENT;
1095 while (*p)
1096 p++;
1098 } else if (*p == ';') {
1099 type = TOK_COMMENT;
1100 while (*p)
1101 p++;
1102 } else {
1104 * Anything else is an operator of some kind. We check
1105 * for all the double-character operators (>>, <<, //,
1106 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1107 * else is a single-character operator.
1109 type = TOK_OTHER;
1110 if ((p[0] == '>' && p[1] == '>') ||
1111 (p[0] == '<' && p[1] == '<') ||
1112 (p[0] == '/' && p[1] == '/') ||
1113 (p[0] == '<' && p[1] == '=') ||
1114 (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++;
1123 p++;
1126 /* Handling unterminated string by UNV */
1127 /*if (type == -1)
1129 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1130 t->text[p-line] = *line;
1131 tail = &t->next;
1133 else */
1134 if (type != TOK_COMMENT) {
1135 *tail = t = new_Token(NULL, type, line, p - line);
1136 tail = &t->next;
1138 line = p;
1140 return list;
1144 * this function allocates a new managed block of memory and
1145 * returns a pointer to the block. The managed blocks are
1146 * deleted only all at once by the delete_Blocks function.
1148 static void *new_Block(size_t size)
1150 Blocks *b = &blocks;
1152 /* first, get to the end of the linked list */
1153 while (b->next)
1154 b = b->next;
1155 /* now allocate the requested chunk */
1156 b->chunk = nasm_malloc(size);
1158 /* now allocate a new block for the next request */
1159 b->next = nasm_malloc(sizeof(Blocks));
1160 /* and initialize the contents of the new block */
1161 b->next->next = NULL;
1162 b->next->chunk = NULL;
1163 return b->chunk;
1167 * this function deletes all managed blocks of memory
1169 static void delete_Blocks(void)
1171 Blocks *a, *b = &blocks;
1174 * keep in mind that the first block, pointed to by blocks
1175 * is a static and not dynamically allocated, so we don't
1176 * free it.
1178 while (b) {
1179 if (b->chunk)
1180 nasm_free(b->chunk);
1181 a = b;
1182 b = b->next;
1183 if (a != &blocks)
1184 nasm_free(a);
1189 * this function creates a new Token and passes a pointer to it
1190 * back to the caller. It sets the type and text elements, and
1191 * also the a.mac and next elements to NULL.
1193 static Token *new_Token(Token * next, enum pp_token_type type,
1194 const char *text, int txtlen)
1196 Token *t;
1197 int i;
1199 if (!freeTokens) {
1200 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
1201 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
1202 freeTokens[i].next = &freeTokens[i + 1];
1203 freeTokens[i].next = NULL;
1205 t = freeTokens;
1206 freeTokens = t->next;
1207 t->next = next;
1208 t->a.mac = NULL;
1209 t->type = type;
1210 if (type == TOK_WHITESPACE || !text) {
1211 t->text = NULL;
1212 } else {
1213 if (txtlen == 0)
1214 txtlen = strlen(text);
1215 t->text = nasm_malloc(txtlen+1);
1216 memcpy(t->text, text, txtlen);
1217 t->text[txtlen] = '\0';
1219 return t;
1222 static Token *delete_Token(Token * t)
1224 Token *next = t->next;
1225 nasm_free(t->text);
1226 t->next = freeTokens;
1227 freeTokens = t;
1228 return next;
1232 * Convert a line of tokens back into text.
1233 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1234 * will be transformed into ..@ctxnum.xxx
1236 static char *detoken(Token * tlist, bool expand_locals)
1238 Token *t;
1239 char *line, *p;
1240 const char *q;
1241 int len = 0;
1243 list_for_each(t, tlist) {
1244 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
1245 char *v;
1246 char *q = t->text;
1248 v = t->text + 2;
1249 if (*v == '\'' || *v == '\"' || *v == '`') {
1250 size_t len = nasm_unquote(v, NULL);
1251 size_t clen = strlen(v);
1253 if (len != clen) {
1254 error(ERR_NONFATAL | ERR_PASS1,
1255 "NUL character in %! string");
1256 v = NULL;
1260 if (v) {
1261 char *p = getenv(v);
1262 if (!p) {
1263 error(ERR_NONFATAL | ERR_PASS1,
1264 "nonexistent environment variable `%s'", v);
1265 p = "";
1267 t->text = nasm_strdup(p);
1269 nasm_free(q);
1272 /* Expand local macros here and not during preprocessing */
1273 if (expand_locals &&
1274 t->type == TOK_PREPROC_ID && t->text &&
1275 t->text[0] == '%' && t->text[1] == '$') {
1276 const char *q;
1277 char *p;
1278 Context *ctx = get_ctx(t->text, &q, false);
1279 if (ctx) {
1280 char buffer[40];
1281 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
1282 p = nasm_strcat(buffer, q);
1283 nasm_free(t->text);
1284 t->text = p;
1287 if (t->type == TOK_WHITESPACE)
1288 len++;
1289 else if (t->text)
1290 len += strlen(t->text);
1293 p = line = nasm_malloc(len + 1);
1295 list_for_each(t, tlist) {
1296 if (t->type == TOK_WHITESPACE) {
1297 *p++ = ' ';
1298 } else if (t->text) {
1299 q = t->text;
1300 while (*q)
1301 *p++ = *q++;
1304 *p = '\0';
1306 return line;
1310 * A scanner, suitable for use by the expression evaluator, which
1311 * operates on a line of Tokens. Expects a pointer to a pointer to
1312 * the first token in the line to be passed in as its private_data
1313 * field.
1315 * FIX: This really needs to be unified with stdscan.
1317 static int ppscan(void *private_data, struct tokenval *tokval)
1319 Token **tlineptr = private_data;
1320 Token *tline;
1321 char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
1323 do {
1324 tline = *tlineptr;
1325 *tlineptr = tline ? tline->next : NULL;
1326 } while (tline && (tline->type == TOK_WHITESPACE ||
1327 tline->type == TOK_COMMENT));
1329 if (!tline)
1330 return tokval->t_type = TOKEN_EOS;
1332 tokval->t_charptr = tline->text;
1334 if (tline->text[0] == '$' && !tline->text[1])
1335 return tokval->t_type = TOKEN_HERE;
1336 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
1337 return tokval->t_type = TOKEN_BASE;
1339 if (tline->type == TOK_ID) {
1340 p = tokval->t_charptr = tline->text;
1341 if (p[0] == '$') {
1342 tokval->t_charptr++;
1343 return tokval->t_type = TOKEN_ID;
1346 for (r = p, s = ourcopy; *r; r++) {
1347 if (r >= p+MAX_KEYWORD)
1348 return tokval->t_type = TOKEN_ID; /* Not a keyword */
1349 *s++ = nasm_tolower(*r);
1351 *s = '\0';
1352 /* right, so we have an identifier sitting in temp storage. now,
1353 * is it actually a register or instruction name, or what? */
1354 return nasm_token_hash(ourcopy, tokval);
1357 if (tline->type == TOK_NUMBER) {
1358 bool rn_error;
1359 tokval->t_integer = readnum(tline->text, &rn_error);
1360 tokval->t_charptr = tline->text;
1361 if (rn_error)
1362 return tokval->t_type = TOKEN_ERRNUM;
1363 else
1364 return tokval->t_type = TOKEN_NUM;
1367 if (tline->type == TOK_FLOAT) {
1368 return tokval->t_type = TOKEN_FLOAT;
1371 if (tline->type == TOK_STRING) {
1372 char bq, *ep;
1374 bq = tline->text[0];
1375 tokval->t_charptr = tline->text;
1376 tokval->t_inttwo = nasm_unquote(tline->text, &ep);
1378 if (ep[0] != bq || ep[1] != '\0')
1379 return tokval->t_type = TOKEN_ERRSTR;
1380 else
1381 return tokval->t_type = TOKEN_STR;
1384 if (tline->type == TOK_OTHER) {
1385 if (!strcmp(tline->text, "<<"))
1386 return tokval->t_type = TOKEN_SHL;
1387 if (!strcmp(tline->text, ">>"))
1388 return tokval->t_type = TOKEN_SHR;
1389 if (!strcmp(tline->text, "//"))
1390 return tokval->t_type = TOKEN_SDIV;
1391 if (!strcmp(tline->text, "%%"))
1392 return tokval->t_type = TOKEN_SMOD;
1393 if (!strcmp(tline->text, "=="))
1394 return tokval->t_type = TOKEN_EQ;
1395 if (!strcmp(tline->text, "<>"))
1396 return tokval->t_type = TOKEN_NE;
1397 if (!strcmp(tline->text, "!="))
1398 return tokval->t_type = TOKEN_NE;
1399 if (!strcmp(tline->text, "<="))
1400 return tokval->t_type = TOKEN_LE;
1401 if (!strcmp(tline->text, ">="))
1402 return tokval->t_type = TOKEN_GE;
1403 if (!strcmp(tline->text, "&&"))
1404 return tokval->t_type = TOKEN_DBL_AND;
1405 if (!strcmp(tline->text, "^^"))
1406 return tokval->t_type = TOKEN_DBL_XOR;
1407 if (!strcmp(tline->text, "||"))
1408 return tokval->t_type = TOKEN_DBL_OR;
1412 * We have no other options: just return the first character of
1413 * the token text.
1415 return tokval->t_type = tline->text[0];
1419 * Compare a string to the name of an existing macro; this is a
1420 * simple wrapper which calls either strcmp or nasm_stricmp
1421 * depending on the value of the `casesense' parameter.
1423 static int mstrcmp(const char *p, const char *q, bool casesense)
1425 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
1429 * Compare a string to the name of an existing macro; this is a
1430 * simple wrapper which calls either strcmp or nasm_stricmp
1431 * depending on the value of the `casesense' parameter.
1433 static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
1435 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
1439 * Return the Context structure associated with a %$ token. Return
1440 * NULL, having _already_ reported an error condition, if the
1441 * context stack isn't deep enough for the supplied number of $
1442 * signs.
1443 * If all_contexts == true, contexts that enclose current are
1444 * also scanned for such smacro, until it is found; if not -
1445 * only the context that directly results from the number of $'s
1446 * in variable's name.
1448 * If "namep" is non-NULL, set it to the pointer to the macro name
1449 * tail, i.e. the part beyond %$...
1451 static Context *get_ctx(const char *name, const char **namep,
1452 bool all_contexts)
1454 Context *ctx;
1455 SMacro *m;
1456 int i;
1458 if (namep)
1459 *namep = name;
1461 if (!name || name[0] != '%' || name[1] != '$')
1462 return NULL;
1464 if (!cstk) {
1465 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1466 return NULL;
1469 name += 2;
1470 ctx = cstk;
1471 i = 0;
1472 while (ctx && *name == '$') {
1473 name++;
1474 i++;
1475 ctx = ctx->next;
1477 if (!ctx) {
1478 error(ERR_NONFATAL, "`%s': context stack is only"
1479 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
1480 return NULL;
1483 if (namep)
1484 *namep = name;
1486 if (!all_contexts)
1487 return ctx;
1490 * NOTE: In 2.10 we will not need lookup in extarnal
1491 * contexts, so this is a gentle way to inform users
1492 * about their source code need to be updated
1495 /* first round -- check the current context */
1496 m = hash_findix(&ctx->localmac, name);
1497 while (m) {
1498 if (!mstrcmp(m->name, name, m->casesense))
1499 return ctx;
1500 m = m->next;
1503 /* second round - external contexts */
1504 while ((ctx = ctx->next)) {
1505 /* Search for this smacro in found context */
1506 m = hash_findix(&ctx->localmac, name);
1507 while (m) {
1508 if (!mstrcmp(m->name, name, m->casesense)) {
1509 /* NOTE: deprecated as of 2.10 */
1510 static int once = 0;
1511 if (!once) {
1512 error(ERR_WARNING, "context-local macro expansion"
1513 " fall-through (automatic searching of outer"
1514 " contexts) will be deprecated starting in"
1515 " NASM 2.10, please see the NASM Manual for"
1516 " more information");
1517 once = 1;
1519 error(ERR_WARNING, "`%s': context-local macro expansion fall-through", name);
1520 return ctx;
1522 m = m->next;
1526 return NULL;
1530 * Check to see if a file is already in a string list
1532 static bool in_list(const StrList *list, const char *str)
1534 while (list) {
1535 if (!strcmp(list->str, str))
1536 return true;
1537 list = list->next;
1539 return false;
1543 * Open an include file. This routine must always return a valid
1544 * file pointer if it returns - it's responsible for throwing an
1545 * ERR_FATAL and bombing out completely if not. It should also try
1546 * the include path one by one until it finds the file or reaches
1547 * the end of the path.
1549 static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
1550 bool missing_ok)
1552 FILE *fp;
1553 char *prefix = "";
1554 IncPath *ip = ipath;
1555 int len = strlen(file);
1556 size_t prefix_len = 0;
1557 StrList *sl;
1559 while (1) {
1560 sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
1561 memcpy(sl->str, prefix, prefix_len);
1562 memcpy(sl->str+prefix_len, file, len+1);
1563 fp = fopen(sl->str, "r");
1564 if (fp && dhead && !in_list(*dhead, sl->str)) {
1565 sl->next = NULL;
1566 **dtail = sl;
1567 *dtail = &sl->next;
1568 } else {
1569 nasm_free(sl);
1571 if (fp)
1572 return fp;
1573 if (!ip) {
1574 if (!missing_ok)
1575 break;
1576 prefix = NULL;
1577 } else {
1578 prefix = ip->path;
1579 ip = ip->next;
1581 if (prefix) {
1582 prefix_len = strlen(prefix);
1583 } else {
1584 /* -MG given and file not found */
1585 if (dhead && !in_list(*dhead, file)) {
1586 sl = nasm_malloc(len+1+sizeof sl->next);
1587 sl->next = NULL;
1588 strcpy(sl->str, file);
1589 **dtail = sl;
1590 *dtail = &sl->next;
1592 return NULL;
1596 error(ERR_FATAL, "unable to open include file `%s'", file);
1597 return NULL;
1601 * Determine if we should warn on defining a single-line macro of
1602 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1603 * return true if _any_ single-line macro of that name is defined.
1604 * Otherwise, will return true if a single-line macro with either
1605 * `nparam' or no parameters is defined.
1607 * If a macro with precisely the right number of parameters is
1608 * defined, or nparam is -1, the address of the definition structure
1609 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1610 * is NULL, no action will be taken regarding its contents, and no
1611 * error will occur.
1613 * Note that this is also called with nparam zero to resolve
1614 * `ifdef'.
1616 * If you already know which context macro belongs to, you can pass
1617 * the context pointer as first parameter; if you won't but name begins
1618 * with %$ the context will be automatically computed. If all_contexts
1619 * is true, macro will be searched in outer contexts as well.
1621 static bool
1622 smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
1623 bool nocase)
1625 struct hash_table *smtbl;
1626 SMacro *m;
1628 if (ctx) {
1629 smtbl = &ctx->localmac;
1630 } else if (name[0] == '%' && name[1] == '$') {
1631 if (cstk)
1632 ctx = get_ctx(name, &name, false);
1633 if (!ctx)
1634 return false; /* got to return _something_ */
1635 smtbl = &ctx->localmac;
1636 } else {
1637 smtbl = &smacros;
1639 m = (SMacro *) hash_findix(smtbl, name);
1641 while (m) {
1642 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
1643 (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
1644 if (defn) {
1645 if (nparam == (int) m->nparam || nparam == -1)
1646 *defn = m;
1647 else
1648 *defn = NULL;
1650 return true;
1652 m = m->next;
1655 return false;
1659 * Count and mark off the parameters in a multi-line macro call.
1660 * This is called both from within the multi-line macro expansion
1661 * code, and also to mark off the default parameters when provided
1662 * in a %macro definition line.
1664 static void count_mmac_params(Token * t, int *nparam, Token *** params)
1666 int paramsize, brace;
1668 *nparam = paramsize = 0;
1669 *params = NULL;
1670 while (t) {
1671 /* +1: we need space for the final NULL */
1672 if (*nparam+1 >= paramsize) {
1673 paramsize += PARAM_DELTA;
1674 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1676 skip_white_(t);
1677 brace = false;
1678 if (tok_is_(t, "{"))
1679 brace = true;
1680 (*params)[(*nparam)++] = t;
1681 while (tok_isnt_(t, brace ? "}" : ","))
1682 t = t->next;
1683 if (t) { /* got a comma/brace */
1684 t = t->next;
1685 if (brace) {
1687 * Now we've found the closing brace, look further
1688 * for the comma.
1690 skip_white_(t);
1691 if (tok_isnt_(t, ",")) {
1692 error(ERR_NONFATAL,
1693 "braces do not enclose all of macro parameter");
1694 while (tok_isnt_(t, ","))
1695 t = t->next;
1697 if (t)
1698 t = t->next; /* eat the comma */
1705 * Determine whether one of the various `if' conditions is true or
1706 * not.
1708 * We must free the tline we get passed.
1710 static bool if_condition(Token * tline, enum preproc_token ct)
1712 enum pp_conditional i = PP_COND(ct);
1713 bool j;
1714 Token *t, *tt, **tptr, *origline;
1715 struct tokenval tokval;
1716 expr *evalresult;
1717 enum pp_token_type needtype;
1718 char *p;
1720 origline = tline;
1722 switch (i) {
1723 case PPC_IFCTX:
1724 j = false; /* have we matched yet? */
1725 while (true) {
1726 skip_white_(tline);
1727 if (!tline)
1728 break;
1729 if (tline->type != TOK_ID) {
1730 error(ERR_NONFATAL,
1731 "`%s' expects context identifiers", pp_directives[ct]);
1732 free_tlist(origline);
1733 return -1;
1735 if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name))
1736 j = true;
1737 tline = tline->next;
1739 break;
1741 case PPC_IFDEF:
1742 j = false; /* have we matched yet? */
1743 while (tline) {
1744 skip_white_(tline);
1745 if (!tline || (tline->type != TOK_ID &&
1746 (tline->type != TOK_PREPROC_ID ||
1747 tline->text[1] != '$'))) {
1748 error(ERR_NONFATAL,
1749 "`%s' expects macro identifiers", pp_directives[ct]);
1750 goto fail;
1752 if (smacro_defined(NULL, tline->text, 0, NULL, true))
1753 j = true;
1754 tline = tline->next;
1756 break;
1758 case PPC_IFENV:
1759 tline = expand_smacro(tline);
1760 j = false; /* have we matched yet? */
1761 while (tline) {
1762 skip_white_(tline);
1763 if (!tline || (tline->type != TOK_ID &&
1764 tline->type != TOK_STRING &&
1765 (tline->type != TOK_PREPROC_ID ||
1766 tline->text[1] != '!'))) {
1767 error(ERR_NONFATAL,
1768 "`%s' expects environment variable names",
1769 pp_directives[ct]);
1770 goto fail;
1772 p = tline->text;
1773 if (tline->type == TOK_PREPROC_ID)
1774 p += 2; /* Skip leading %! */
1775 if (*p == '\'' || *p == '\"' || *p == '`')
1776 nasm_unquote_cstr(p, ct);
1777 if (getenv(p))
1778 j = true;
1779 tline = tline->next;
1781 break;
1783 case PPC_IFIDN:
1784 case PPC_IFIDNI:
1785 tline = expand_smacro(tline);
1786 t = tt = tline;
1787 while (tok_isnt_(tt, ","))
1788 tt = tt->next;
1789 if (!tt) {
1790 error(ERR_NONFATAL,
1791 "`%s' expects two comma-separated arguments",
1792 pp_directives[ct]);
1793 goto fail;
1795 tt = tt->next;
1796 j = true; /* assume equality unless proved not */
1797 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1798 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1799 error(ERR_NONFATAL, "`%s': more than one comma on line",
1800 pp_directives[ct]);
1801 goto fail;
1803 if (t->type == TOK_WHITESPACE) {
1804 t = t->next;
1805 continue;
1807 if (tt->type == TOK_WHITESPACE) {
1808 tt = tt->next;
1809 continue;
1811 if (tt->type != t->type) {
1812 j = false; /* found mismatching tokens */
1813 break;
1815 /* When comparing strings, need to unquote them first */
1816 if (t->type == TOK_STRING) {
1817 size_t l1 = nasm_unquote(t->text, NULL);
1818 size_t l2 = nasm_unquote(tt->text, NULL);
1820 if (l1 != l2) {
1821 j = false;
1822 break;
1824 if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
1825 j = false;
1826 break;
1828 } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
1829 j = false; /* found mismatching tokens */
1830 break;
1833 t = t->next;
1834 tt = tt->next;
1836 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1837 j = false; /* trailing gunk on one end or other */
1838 break;
1840 case PPC_IFMACRO:
1842 bool found = false;
1843 MMacro searching, *mmac;
1845 skip_white_(tline);
1846 tline = expand_id(tline);
1847 if (!tok_type_(tline, TOK_ID)) {
1848 error(ERR_NONFATAL,
1849 "`%s' expects a macro name", pp_directives[ct]);
1850 goto fail;
1852 searching.name = nasm_strdup(tline->text);
1853 searching.casesense = true;
1854 searching.plus = false;
1855 searching.nolist = false;
1856 searching.in_progress = 0;
1857 searching.max_depth = 0;
1858 searching.rep_nest = NULL;
1859 searching.nparam_min = 0;
1860 searching.nparam_max = INT_MAX;
1861 tline = expand_smacro(tline->next);
1862 skip_white_(tline);
1863 if (!tline) {
1864 } else if (!tok_type_(tline, TOK_NUMBER)) {
1865 error(ERR_NONFATAL,
1866 "`%s' expects a parameter count or nothing",
1867 pp_directives[ct]);
1868 } else {
1869 searching.nparam_min = searching.nparam_max =
1870 readnum(tline->text, &j);
1871 if (j)
1872 error(ERR_NONFATAL,
1873 "unable to parse parameter count `%s'",
1874 tline->text);
1876 if (tline && tok_is_(tline->next, "-")) {
1877 tline = tline->next->next;
1878 if (tok_is_(tline, "*"))
1879 searching.nparam_max = INT_MAX;
1880 else if (!tok_type_(tline, TOK_NUMBER))
1881 error(ERR_NONFATAL,
1882 "`%s' expects a parameter count after `-'",
1883 pp_directives[ct]);
1884 else {
1885 searching.nparam_max = readnum(tline->text, &j);
1886 if (j)
1887 error(ERR_NONFATAL,
1888 "unable to parse parameter count `%s'",
1889 tline->text);
1890 if (searching.nparam_min > searching.nparam_max)
1891 error(ERR_NONFATAL,
1892 "minimum parameter count exceeds maximum");
1895 if (tline && tok_is_(tline->next, "+")) {
1896 tline = tline->next;
1897 searching.plus = true;
1899 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
1900 while (mmac) {
1901 if (!strcmp(mmac->name, searching.name) &&
1902 (mmac->nparam_min <= searching.nparam_max
1903 || searching.plus)
1904 && (searching.nparam_min <= mmac->nparam_max
1905 || mmac->plus)) {
1906 found = true;
1907 break;
1909 mmac = mmac->next;
1911 if (tline && tline->next)
1912 error(ERR_WARNING|ERR_PASS1,
1913 "trailing garbage after %%ifmacro ignored");
1914 nasm_free(searching.name);
1915 j = found;
1916 break;
1919 case PPC_IFID:
1920 needtype = TOK_ID;
1921 goto iftype;
1922 case PPC_IFNUM:
1923 needtype = TOK_NUMBER;
1924 goto iftype;
1925 case PPC_IFSTR:
1926 needtype = TOK_STRING;
1927 goto iftype;
1929 iftype:
1930 t = tline = expand_smacro(tline);
1932 while (tok_type_(t, TOK_WHITESPACE) ||
1933 (needtype == TOK_NUMBER &&
1934 tok_type_(t, TOK_OTHER) &&
1935 (t->text[0] == '-' || t->text[0] == '+') &&
1936 !t->text[1]))
1937 t = t->next;
1939 j = tok_type_(t, needtype);
1940 break;
1942 case PPC_IFTOKEN:
1943 t = tline = expand_smacro(tline);
1944 while (tok_type_(t, TOK_WHITESPACE))
1945 t = t->next;
1947 j = false;
1948 if (t) {
1949 t = t->next; /* Skip the actual token */
1950 while (tok_type_(t, TOK_WHITESPACE))
1951 t = t->next;
1952 j = !t; /* Should be nothing left */
1954 break;
1956 case PPC_IFEMPTY:
1957 t = tline = expand_smacro(tline);
1958 while (tok_type_(t, TOK_WHITESPACE))
1959 t = t->next;
1961 j = !t; /* Should be empty */
1962 break;
1964 case PPC_IF:
1965 t = tline = expand_smacro(tline);
1966 tptr = &t;
1967 tokval.t_type = TOKEN_INVALID;
1968 evalresult = evaluate(ppscan, tptr, &tokval,
1969 NULL, pass | CRITICAL, error, NULL);
1970 if (!evalresult)
1971 return -1;
1972 if (tokval.t_type)
1973 error(ERR_WARNING|ERR_PASS1,
1974 "trailing garbage after expression ignored");
1975 if (!is_simple(evalresult)) {
1976 error(ERR_NONFATAL,
1977 "non-constant value given to `%s'", pp_directives[ct]);
1978 goto fail;
1980 j = reloc_value(evalresult) != 0;
1981 break;
1983 default:
1984 error(ERR_FATAL,
1985 "preprocessor directive `%s' not yet implemented",
1986 pp_directives[ct]);
1987 goto fail;
1990 free_tlist(origline);
1991 return j ^ PP_NEGATIVE(ct);
1993 fail:
1994 free_tlist(origline);
1995 return -1;
1999 * Common code for defining an smacro
2001 static bool define_smacro(Context *ctx, const char *mname, bool casesense,
2002 int nparam, Token *expansion)
2004 SMacro *smac, **smhead;
2005 struct hash_table *smtbl;
2007 if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
2008 if (!smac) {
2009 error(ERR_WARNING|ERR_PASS1,
2010 "single-line macro `%s' defined both with and"
2011 " without parameters", mname);
2013 * Some instances of the old code considered this a failure,
2014 * some others didn't. What is the right thing to do here?
2016 free_tlist(expansion);
2017 return false; /* Failure */
2018 } else {
2020 * We're redefining, so we have to take over an
2021 * existing SMacro structure. This means freeing
2022 * what was already in it.
2024 nasm_free(smac->name);
2025 free_tlist(smac->expansion);
2027 } else {
2028 smtbl = ctx ? &ctx->localmac : &smacros;
2029 smhead = (SMacro **) hash_findi_add(smtbl, mname);
2030 smac = nasm_malloc(sizeof(SMacro));
2031 smac->next = *smhead;
2032 *smhead = smac;
2034 smac->name = nasm_strdup(mname);
2035 smac->casesense = casesense;
2036 smac->nparam = nparam;
2037 smac->expansion = expansion;
2038 smac->in_progress = false;
2039 return true; /* Success */
2043 * Undefine an smacro
2045 static void undef_smacro(Context *ctx, const char *mname)
2047 SMacro **smhead, *s, **sp;
2048 struct hash_table *smtbl;
2050 smtbl = ctx ? &ctx->localmac : &smacros;
2051 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
2053 if (smhead) {
2055 * We now have a macro name... go hunt for it.
2057 sp = smhead;
2058 while ((s = *sp) != NULL) {
2059 if (!mstrcmp(s->name, mname, s->casesense)) {
2060 *sp = s->next;
2061 nasm_free(s->name);
2062 free_tlist(s->expansion);
2063 nasm_free(s);
2064 } else {
2065 sp = &s->next;
2072 * Parse a mmacro specification.
2074 static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
2076 bool err;
2078 tline = tline->next;
2079 skip_white_(tline);
2080 tline = expand_id(tline);
2081 if (!tok_type_(tline, TOK_ID)) {
2082 error(ERR_NONFATAL, "`%s' expects a macro name", directive);
2083 return false;
2086 def->prev = NULL;
2087 def->name = nasm_strdup(tline->text);
2088 def->plus = false;
2089 def->nolist = false;
2090 def->in_progress = 0;
2091 def->rep_nest = NULL;
2092 def->nparam_min = 0;
2093 def->nparam_max = 0;
2095 tline = expand_smacro(tline->next);
2096 skip_white_(tline);
2097 if (!tok_type_(tline, TOK_NUMBER)) {
2098 error(ERR_NONFATAL, "`%s' expects a parameter count", directive);
2099 } else {
2100 def->nparam_min = def->nparam_max =
2101 readnum(tline->text, &err);
2102 if (err)
2103 error(ERR_NONFATAL,
2104 "unable to parse parameter count `%s'", tline->text);
2106 if (tline && tok_is_(tline->next, "-")) {
2107 tline = tline->next->next;
2108 if (tok_is_(tline, "*")) {
2109 def->nparam_max = INT_MAX;
2110 } else if (!tok_type_(tline, TOK_NUMBER)) {
2111 error(ERR_NONFATAL,
2112 "`%s' expects a parameter count after `-'", directive);
2113 } else {
2114 def->nparam_max = readnum(tline->text, &err);
2115 if (err) {
2116 error(ERR_NONFATAL, "unable to parse parameter count `%s'",
2117 tline->text);
2119 if (def->nparam_min > def->nparam_max) {
2120 error(ERR_NONFATAL, "minimum parameter count exceeds maximum");
2124 if (tline && tok_is_(tline->next, "+")) {
2125 tline = tline->next;
2126 def->plus = true;
2128 if (tline && tok_type_(tline->next, TOK_ID) &&
2129 !nasm_stricmp(tline->next->text, ".nolist")) {
2130 tline = tline->next;
2131 def->nolist = true;
2135 * Handle default parameters.
2137 if (tline && tline->next) {
2138 def->dlist = tline->next;
2139 tline->next = NULL;
2140 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
2141 } else {
2142 def->dlist = NULL;
2143 def->defaults = NULL;
2145 def->expansion = NULL;
2147 if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
2148 !def->plus)
2149 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MDP,
2150 "too many default macro parameters");
2152 return true;
2157 * Decode a size directive
2159 static int parse_size(const char *str) {
2160 static const char *size_names[] =
2161 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2162 static const int sizes[] =
2163 { 0, 1, 4, 16, 8, 10, 2, 32 };
2165 return sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1];
2169 * find and process preprocessor directive in passed line
2170 * Find out if a line contains a preprocessor directive, and deal
2171 * with it if so.
2173 * If a directive _is_ found, it is the responsibility of this routine
2174 * (and not the caller) to free_tlist() the line.
2176 * @param tline a pointer to the current tokeninzed line linked list
2177 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2180 static int do_directive(Token * tline)
2182 enum preproc_token i;
2183 int j;
2184 bool err;
2185 int nparam;
2186 bool nolist;
2187 bool casesense;
2188 int k, m;
2189 int offset;
2190 char *p, *pp;
2191 const char *mname;
2192 Include *inc;
2193 Context *ctx;
2194 Cond *cond;
2195 MMacro *mmac, **mmhead;
2196 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
2197 Line *l;
2198 struct tokenval tokval;
2199 expr *evalresult;
2200 MMacro *tmp_defining; /* Used when manipulating rep_nest */
2201 int64_t count;
2202 size_t len;
2203 int severity;
2205 origline = tline;
2207 skip_white_(tline);
2208 if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
2209 (tline->text[1] == '%' || tline->text[1] == '$'
2210 || tline->text[1] == '!'))
2211 return NO_DIRECTIVE_FOUND;
2213 i = pp_token_hash(tline->text);
2216 * FIXME: We zap execution of PP_RMACRO, PP_IRMACRO, PP_EXITMACRO
2217 * since they are known to be buggy at moment, we need to fix them
2218 * in future release (2.09-2.10)
2220 if (i == PP_RMACRO || i == PP_RMACRO || i == PP_EXITMACRO) {
2221 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2222 tline->text);
2223 return NO_DIRECTIVE_FOUND;
2227 * If we're in a non-emitting branch of a condition construct,
2228 * or walking to the end of an already terminated %rep block,
2229 * we should ignore all directives except for condition
2230 * directives.
2232 if (((istk->conds && !emitting(istk->conds->state)) ||
2233 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
2234 return NO_DIRECTIVE_FOUND;
2238 * If we're defining a macro or reading a %rep block, we should
2239 * ignore all directives except for %macro/%imacro (which nest),
2240 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2241 * If we're in a %rep block, another %rep nests, so should be let through.
2243 if (defining && i != PP_MACRO && i != PP_IMACRO &&
2244 i != PP_RMACRO && i != PP_IRMACRO &&
2245 i != PP_ENDMACRO && i != PP_ENDM &&
2246 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
2247 return NO_DIRECTIVE_FOUND;
2250 if (defining) {
2251 if (i == PP_MACRO || i == PP_IMACRO ||
2252 i == PP_RMACRO || i == PP_IRMACRO) {
2253 nested_mac_count++;
2254 return NO_DIRECTIVE_FOUND;
2255 } else if (nested_mac_count > 0) {
2256 if (i == PP_ENDMACRO) {
2257 nested_mac_count--;
2258 return NO_DIRECTIVE_FOUND;
2261 if (!defining->name) {
2262 if (i == PP_REP) {
2263 nested_rep_count++;
2264 return NO_DIRECTIVE_FOUND;
2265 } else if (nested_rep_count > 0) {
2266 if (i == PP_ENDREP) {
2267 nested_rep_count--;
2268 return NO_DIRECTIVE_FOUND;
2274 switch (i) {
2275 case PP_INVALID:
2276 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2277 tline->text);
2278 return NO_DIRECTIVE_FOUND; /* didn't get it */
2280 case PP_STACKSIZE:
2281 /* Directive to tell NASM what the default stack size is. The
2282 * default is for a 16-bit stack, and this can be overriden with
2283 * %stacksize large.
2285 tline = tline->next;
2286 if (tline && tline->type == TOK_WHITESPACE)
2287 tline = tline->next;
2288 if (!tline || tline->type != TOK_ID) {
2289 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
2290 free_tlist(origline);
2291 return DIRECTIVE_FOUND;
2293 if (nasm_stricmp(tline->text, "flat") == 0) {
2294 /* All subsequent ARG directives are for a 32-bit stack */
2295 StackSize = 4;
2296 StackPointer = "ebp";
2297 ArgOffset = 8;
2298 LocalOffset = 0;
2299 } else if (nasm_stricmp(tline->text, "flat64") == 0) {
2300 /* All subsequent ARG directives are for a 64-bit stack */
2301 StackSize = 8;
2302 StackPointer = "rbp";
2303 ArgOffset = 16;
2304 LocalOffset = 0;
2305 } else if (nasm_stricmp(tline->text, "large") == 0) {
2306 /* All subsequent ARG directives are for a 16-bit stack,
2307 * far function call.
2309 StackSize = 2;
2310 StackPointer = "bp";
2311 ArgOffset = 4;
2312 LocalOffset = 0;
2313 } else if (nasm_stricmp(tline->text, "small") == 0) {
2314 /* All subsequent ARG directives are for a 16-bit stack,
2315 * far function call. We don't support near functions.
2317 StackSize = 2;
2318 StackPointer = "bp";
2319 ArgOffset = 6;
2320 LocalOffset = 0;
2321 } else {
2322 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
2323 free_tlist(origline);
2324 return DIRECTIVE_FOUND;
2326 free_tlist(origline);
2327 return DIRECTIVE_FOUND;
2329 case PP_ARG:
2330 /* TASM like ARG directive to define arguments to functions, in
2331 * the following form:
2333 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2335 offset = ArgOffset;
2336 do {
2337 char *arg, directive[256];
2338 int size = StackSize;
2340 /* Find the argument name */
2341 tline = tline->next;
2342 if (tline && tline->type == TOK_WHITESPACE)
2343 tline = tline->next;
2344 if (!tline || tline->type != TOK_ID) {
2345 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
2346 free_tlist(origline);
2347 return DIRECTIVE_FOUND;
2349 arg = tline->text;
2351 /* Find the argument size type */
2352 tline = tline->next;
2353 if (!tline || tline->type != TOK_OTHER
2354 || tline->text[0] != ':') {
2355 error(ERR_NONFATAL,
2356 "Syntax error processing `%%arg' directive");
2357 free_tlist(origline);
2358 return DIRECTIVE_FOUND;
2360 tline = tline->next;
2361 if (!tline || tline->type != TOK_ID) {
2362 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
2363 free_tlist(origline);
2364 return DIRECTIVE_FOUND;
2367 /* Allow macro expansion of type parameter */
2368 tt = tokenize(tline->text);
2369 tt = expand_smacro(tt);
2370 size = parse_size(tt->text);
2371 if (!size) {
2372 error(ERR_NONFATAL,
2373 "Invalid size type for `%%arg' missing directive");
2374 free_tlist(tt);
2375 free_tlist(origline);
2376 return DIRECTIVE_FOUND;
2378 free_tlist(tt);
2380 /* Round up to even stack slots */
2381 size = ALIGN(size, StackSize);
2383 /* Now define the macro for the argument */
2384 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
2385 arg, StackPointer, offset);
2386 do_directive(tokenize(directive));
2387 offset += size;
2389 /* Move to the next argument in the list */
2390 tline = tline->next;
2391 if (tline && tline->type == TOK_WHITESPACE)
2392 tline = tline->next;
2393 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2394 ArgOffset = offset;
2395 free_tlist(origline);
2396 return DIRECTIVE_FOUND;
2398 case PP_LOCAL:
2399 /* TASM like LOCAL directive to define local variables for a
2400 * function, in the following form:
2402 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2404 * The '= LocalSize' at the end is ignored by NASM, but is
2405 * required by TASM to define the local parameter size (and used
2406 * by the TASM macro package).
2408 offset = LocalOffset;
2409 do {
2410 char *local, directive[256];
2411 int size = StackSize;
2413 /* Find the argument name */
2414 tline = tline->next;
2415 if (tline && tline->type == TOK_WHITESPACE)
2416 tline = tline->next;
2417 if (!tline || tline->type != TOK_ID) {
2418 error(ERR_NONFATAL,
2419 "`%%local' missing argument parameter");
2420 free_tlist(origline);
2421 return DIRECTIVE_FOUND;
2423 local = tline->text;
2425 /* Find the argument size type */
2426 tline = tline->next;
2427 if (!tline || tline->type != TOK_OTHER
2428 || tline->text[0] != ':') {
2429 error(ERR_NONFATAL,
2430 "Syntax error processing `%%local' directive");
2431 free_tlist(origline);
2432 return DIRECTIVE_FOUND;
2434 tline = tline->next;
2435 if (!tline || tline->type != TOK_ID) {
2436 error(ERR_NONFATAL,
2437 "`%%local' missing size type parameter");
2438 free_tlist(origline);
2439 return DIRECTIVE_FOUND;
2442 /* Allow macro expansion of type parameter */
2443 tt = tokenize(tline->text);
2444 tt = expand_smacro(tt);
2445 size = parse_size(tt->text);
2446 if (!size) {
2447 error(ERR_NONFATAL,
2448 "Invalid size type for `%%local' missing directive");
2449 free_tlist(tt);
2450 free_tlist(origline);
2451 return DIRECTIVE_FOUND;
2453 free_tlist(tt);
2455 /* Round up to even stack slots */
2456 size = ALIGN(size, StackSize);
2458 offset += size; /* Negative offset, increment before */
2460 /* Now define the macro for the argument */
2461 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
2462 local, StackPointer, offset);
2463 do_directive(tokenize(directive));
2465 /* Now define the assign to setup the enter_c macro correctly */
2466 snprintf(directive, sizeof(directive),
2467 "%%assign %%$localsize %%$localsize+%d", size);
2468 do_directive(tokenize(directive));
2470 /* Move to the next argument in the list */
2471 tline = tline->next;
2472 if (tline && tline->type == TOK_WHITESPACE)
2473 tline = tline->next;
2474 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2475 LocalOffset = offset;
2476 free_tlist(origline);
2477 return DIRECTIVE_FOUND;
2479 case PP_CLEAR:
2480 if (tline->next)
2481 error(ERR_WARNING|ERR_PASS1,
2482 "trailing garbage after `%%clear' ignored");
2483 free_macros();
2484 init_macros();
2485 free_tlist(origline);
2486 return DIRECTIVE_FOUND;
2488 case PP_DEPEND:
2489 t = tline->next = expand_smacro(tline->next);
2490 skip_white_(t);
2491 if (!t || (t->type != TOK_STRING &&
2492 t->type != TOK_INTERNAL_STRING)) {
2493 error(ERR_NONFATAL, "`%%depend' expects a file name");
2494 free_tlist(origline);
2495 return DIRECTIVE_FOUND; /* but we did _something_ */
2497 if (t->next)
2498 error(ERR_WARNING|ERR_PASS1,
2499 "trailing garbage after `%%depend' ignored");
2500 p = t->text;
2501 if (t->type != TOK_INTERNAL_STRING)
2502 nasm_unquote_cstr(p, i);
2503 if (dephead && !in_list(*dephead, p)) {
2504 StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next);
2505 sl->next = NULL;
2506 strcpy(sl->str, p);
2507 *deptail = sl;
2508 deptail = &sl->next;
2510 free_tlist(origline);
2511 return DIRECTIVE_FOUND;
2513 case PP_INCLUDE:
2514 t = tline->next = expand_smacro(tline->next);
2515 skip_white_(t);
2517 if (!t || (t->type != TOK_STRING &&
2518 t->type != TOK_INTERNAL_STRING)) {
2519 error(ERR_NONFATAL, "`%%include' expects a file name");
2520 free_tlist(origline);
2521 return DIRECTIVE_FOUND; /* but we did _something_ */
2523 if (t->next)
2524 error(ERR_WARNING|ERR_PASS1,
2525 "trailing garbage after `%%include' ignored");
2526 p = t->text;
2527 if (t->type != TOK_INTERNAL_STRING)
2528 nasm_unquote_cstr(p, i);
2529 inc = nasm_malloc(sizeof(Include));
2530 inc->next = istk;
2531 inc->conds = NULL;
2532 inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
2533 if (!inc->fp) {
2534 /* -MG given but file not found */
2535 nasm_free(inc);
2536 } else {
2537 inc->fname = src_set_fname(nasm_strdup(p));
2538 inc->lineno = src_set_linnum(0);
2539 inc->lineinc = 1;
2540 inc->expansion = NULL;
2541 inc->mstk = NULL;
2542 istk = inc;
2543 list->uplevel(LIST_INCLUDE);
2545 free_tlist(origline);
2546 return DIRECTIVE_FOUND;
2548 case PP_USE:
2550 static macros_t *use_pkg;
2551 const char *pkg_macro = NULL;
2553 tline = tline->next;
2554 skip_white_(tline);
2555 tline = expand_id(tline);
2557 if (!tline || (tline->type != TOK_STRING &&
2558 tline->type != TOK_INTERNAL_STRING &&
2559 tline->type != TOK_ID)) {
2560 error(ERR_NONFATAL, "`%%use' expects a package name");
2561 free_tlist(origline);
2562 return DIRECTIVE_FOUND; /* but we did _something_ */
2564 if (tline->next)
2565 error(ERR_WARNING|ERR_PASS1,
2566 "trailing garbage after `%%use' ignored");
2567 if (tline->type == TOK_STRING)
2568 nasm_unquote_cstr(tline->text, i);
2569 use_pkg = nasm_stdmac_find_package(tline->text);
2570 if (!use_pkg)
2571 error(ERR_NONFATAL, "unknown `%%use' package: %s", tline->text);
2572 else
2573 pkg_macro = (char *)use_pkg + 1; /* The first string will be <%define>__USE_*__ */
2574 if (use_pkg && ! smacro_defined(NULL, pkg_macro, 0, NULL, true)) {
2575 /* Not already included, go ahead and include it */
2576 stdmacpos = use_pkg;
2578 free_tlist(origline);
2579 return DIRECTIVE_FOUND;
2581 case PP_PUSH:
2582 case PP_REPL:
2583 case PP_POP:
2584 tline = tline->next;
2585 skip_white_(tline);
2586 tline = expand_id(tline);
2587 if (tline) {
2588 if (!tok_type_(tline, TOK_ID)) {
2589 error(ERR_NONFATAL, "`%s' expects a context identifier",
2590 pp_directives[i]);
2591 free_tlist(origline);
2592 return DIRECTIVE_FOUND; /* but we did _something_ */
2594 if (tline->next)
2595 error(ERR_WARNING|ERR_PASS1,
2596 "trailing garbage after `%s' ignored",
2597 pp_directives[i]);
2598 p = nasm_strdup(tline->text);
2599 } else {
2600 p = NULL; /* Anonymous */
2603 if (i == PP_PUSH) {
2604 ctx = nasm_malloc(sizeof(Context));
2605 ctx->next = cstk;
2606 hash_init(&ctx->localmac, HASH_SMALL);
2607 ctx->name = p;
2608 ctx->number = unique++;
2609 cstk = ctx;
2610 } else {
2611 /* %pop or %repl */
2612 if (!cstk) {
2613 error(ERR_NONFATAL, "`%s': context stack is empty",
2614 pp_directives[i]);
2615 } else if (i == PP_POP) {
2616 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
2617 error(ERR_NONFATAL, "`%%pop' in wrong context: %s, "
2618 "expected %s",
2619 cstk->name ? cstk->name : "anonymous", p);
2620 else
2621 ctx_pop();
2622 } else {
2623 /* i == PP_REPL */
2624 nasm_free(cstk->name);
2625 cstk->name = p;
2626 p = NULL;
2628 nasm_free(p);
2630 free_tlist(origline);
2631 return DIRECTIVE_FOUND;
2632 case PP_FATAL:
2633 severity = ERR_FATAL;
2634 goto issue_error;
2635 case PP_ERROR:
2636 severity = ERR_NONFATAL;
2637 goto issue_error;
2638 case PP_WARNING:
2639 severity = ERR_WARNING|ERR_WARN_USER;
2640 goto issue_error;
2642 issue_error:
2644 /* Only error out if this is the final pass */
2645 if (pass != 2 && i != PP_FATAL)
2646 return DIRECTIVE_FOUND;
2648 tline->next = expand_smacro(tline->next);
2649 tline = tline->next;
2650 skip_white_(tline);
2651 t = tline ? tline->next : NULL;
2652 skip_white_(t);
2653 if (tok_type_(tline, TOK_STRING) && !t) {
2654 /* The line contains only a quoted string */
2655 p = tline->text;
2656 nasm_unquote(p, NULL); /* Ignore NUL character truncation */
2657 error(severity, "%s", p);
2658 } else {
2659 /* Not a quoted string, or more than a quoted string */
2660 p = detoken(tline, false);
2661 error(severity, "%s", p);
2662 nasm_free(p);
2664 free_tlist(origline);
2665 return DIRECTIVE_FOUND;
2668 CASE_PP_IF:
2669 if (istk->conds && !emitting(istk->conds->state))
2670 j = COND_NEVER;
2671 else {
2672 j = if_condition(tline->next, i);
2673 tline->next = NULL; /* it got freed */
2674 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2676 cond = nasm_malloc(sizeof(Cond));
2677 cond->next = istk->conds;
2678 cond->state = j;
2679 istk->conds = cond;
2680 if(istk->mstk)
2681 istk->mstk->condcnt ++;
2682 free_tlist(origline);
2683 return DIRECTIVE_FOUND;
2685 CASE_PP_ELIF:
2686 if (!istk->conds)
2687 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
2688 switch(istk->conds->state) {
2689 case COND_IF_TRUE:
2690 istk->conds->state = COND_DONE;
2691 break;
2693 case COND_DONE:
2694 case COND_NEVER:
2695 break;
2697 case COND_ELSE_TRUE:
2698 case COND_ELSE_FALSE:
2699 error_precond(ERR_WARNING|ERR_PASS1,
2700 "`%%elif' after `%%else' ignored");
2701 istk->conds->state = COND_NEVER;
2702 break;
2704 case COND_IF_FALSE:
2706 * IMPORTANT: In the case of %if, we will already have
2707 * called expand_mmac_params(); however, if we're
2708 * processing an %elif we must have been in a
2709 * non-emitting mode, which would have inhibited
2710 * the normal invocation of expand_mmac_params().
2711 * Therefore, we have to do it explicitly here.
2713 j = if_condition(expand_mmac_params(tline->next), i);
2714 tline->next = NULL; /* it got freed */
2715 istk->conds->state =
2716 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2717 break;
2719 free_tlist(origline);
2720 return DIRECTIVE_FOUND;
2722 case PP_ELSE:
2723 if (tline->next)
2724 error_precond(ERR_WARNING|ERR_PASS1,
2725 "trailing garbage after `%%else' ignored");
2726 if (!istk->conds)
2727 error(ERR_FATAL, "`%%else': no matching `%%if'");
2728 switch(istk->conds->state) {
2729 case COND_IF_TRUE:
2730 case COND_DONE:
2731 istk->conds->state = COND_ELSE_FALSE;
2732 break;
2734 case COND_NEVER:
2735 break;
2737 case COND_IF_FALSE:
2738 istk->conds->state = COND_ELSE_TRUE;
2739 break;
2741 case COND_ELSE_TRUE:
2742 case COND_ELSE_FALSE:
2743 error_precond(ERR_WARNING|ERR_PASS1,
2744 "`%%else' after `%%else' ignored.");
2745 istk->conds->state = COND_NEVER;
2746 break;
2748 free_tlist(origline);
2749 return DIRECTIVE_FOUND;
2751 case PP_ENDIF:
2752 if (tline->next)
2753 error_precond(ERR_WARNING|ERR_PASS1,
2754 "trailing garbage after `%%endif' ignored");
2755 if (!istk->conds)
2756 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2757 cond = istk->conds;
2758 istk->conds = cond->next;
2759 nasm_free(cond);
2760 if(istk->mstk)
2761 istk->mstk->condcnt --;
2762 free_tlist(origline);
2763 return DIRECTIVE_FOUND;
2765 case PP_RMACRO:
2766 case PP_IRMACRO:
2767 case PP_MACRO:
2768 case PP_IMACRO:
2769 if (defining) {
2770 error(ERR_FATAL, "`%s': already defining a macro",
2771 pp_directives[i]);
2772 return DIRECTIVE_FOUND;
2774 defining = nasm_malloc(sizeof(MMacro));
2775 defining->max_depth =
2776 (i == PP_RMACRO) || (i == PP_IRMACRO) ? DEADMAN_LIMIT : 0;
2777 defining->casesense = (i == PP_MACRO) || (i == PP_RMACRO);
2778 if (!parse_mmacro_spec(tline, defining, pp_directives[i])) {
2779 nasm_free(defining);
2780 defining = NULL;
2781 return DIRECTIVE_FOUND;
2784 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
2785 while (mmac) {
2786 if (!strcmp(mmac->name, defining->name) &&
2787 (mmac->nparam_min <= defining->nparam_max
2788 || defining->plus)
2789 && (defining->nparam_min <= mmac->nparam_max
2790 || mmac->plus)) {
2791 error(ERR_WARNING|ERR_PASS1,
2792 "redefining multi-line macro `%s'", defining->name);
2793 return DIRECTIVE_FOUND;
2795 mmac = mmac->next;
2797 free_tlist(origline);
2798 return DIRECTIVE_FOUND;
2800 case PP_ENDM:
2801 case PP_ENDMACRO:
2802 if (! (defining && defining->name)) {
2803 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2804 return DIRECTIVE_FOUND;
2806 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
2807 defining->next = *mmhead;
2808 *mmhead = defining;
2809 defining = NULL;
2810 free_tlist(origline);
2811 return DIRECTIVE_FOUND;
2813 case PP_EXITMACRO:
2815 * We must search along istk->expansion until we hit a
2816 * macro-end marker for a macro with a name. Then we
2817 * bypass all lines between exitmacro and endmacro.
2819 list_for_each(l, istk->expansion)
2820 if (l->finishes && l->finishes->name)
2821 break;
2823 if (l) {
2825 * Remove all conditional entries relative to this
2826 * macro invocation. (safe to do in this context)
2828 for ( ; l->finishes->condcnt > 0; l->finishes->condcnt --) {
2829 cond = istk->conds;
2830 istk->conds = cond->next;
2831 nasm_free(cond);
2833 istk->expansion = l;
2834 } else {
2835 error(ERR_NONFATAL, "`%%exitmacro' not within `%%macro' block");
2837 free_tlist(origline);
2838 return DIRECTIVE_FOUND;
2840 case PP_UNMACRO:
2841 case PP_UNIMACRO:
2843 MMacro **mmac_p;
2844 MMacro spec;
2846 spec.casesense = (i == PP_UNMACRO);
2847 if (!parse_mmacro_spec(tline, &spec, pp_directives[i])) {
2848 return DIRECTIVE_FOUND;
2850 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
2851 while (mmac_p && *mmac_p) {
2852 mmac = *mmac_p;
2853 if (mmac->casesense == spec.casesense &&
2854 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
2855 mmac->nparam_min == spec.nparam_min &&
2856 mmac->nparam_max == spec.nparam_max &&
2857 mmac->plus == spec.plus) {
2858 *mmac_p = mmac->next;
2859 free_mmacro(mmac);
2860 } else {
2861 mmac_p = &mmac->next;
2864 free_tlist(origline);
2865 free_tlist(spec.dlist);
2866 return DIRECTIVE_FOUND;
2869 case PP_ROTATE:
2870 if (tline->next && tline->next->type == TOK_WHITESPACE)
2871 tline = tline->next;
2872 if (!tline->next) {
2873 free_tlist(origline);
2874 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2875 return DIRECTIVE_FOUND;
2877 t = expand_smacro(tline->next);
2878 tline->next = NULL;
2879 free_tlist(origline);
2880 tline = t;
2881 tptr = &t;
2882 tokval.t_type = TOKEN_INVALID;
2883 evalresult =
2884 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2885 free_tlist(tline);
2886 if (!evalresult)
2887 return DIRECTIVE_FOUND;
2888 if (tokval.t_type)
2889 error(ERR_WARNING|ERR_PASS1,
2890 "trailing garbage after expression ignored");
2891 if (!is_simple(evalresult)) {
2892 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2893 return DIRECTIVE_FOUND;
2895 mmac = istk->mstk;
2896 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2897 mmac = mmac->next_active;
2898 if (!mmac) {
2899 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2900 } else if (mmac->nparam == 0) {
2901 error(ERR_NONFATAL,
2902 "`%%rotate' invoked within macro without parameters");
2903 } else {
2904 int rotate = mmac->rotate + reloc_value(evalresult);
2906 rotate %= (int)mmac->nparam;
2907 if (rotate < 0)
2908 rotate += mmac->nparam;
2910 mmac->rotate = rotate;
2912 return DIRECTIVE_FOUND;
2914 case PP_REP:
2915 nolist = false;
2916 do {
2917 tline = tline->next;
2918 } while (tok_type_(tline, TOK_WHITESPACE));
2920 if (tok_type_(tline, TOK_ID) &&
2921 nasm_stricmp(tline->text, ".nolist") == 0) {
2922 nolist = true;
2923 do {
2924 tline = tline->next;
2925 } while (tok_type_(tline, TOK_WHITESPACE));
2928 if (tline) {
2929 t = expand_smacro(tline);
2930 tptr = &t;
2931 tokval.t_type = TOKEN_INVALID;
2932 evalresult =
2933 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2934 if (!evalresult) {
2935 free_tlist(origline);
2936 return DIRECTIVE_FOUND;
2938 if (tokval.t_type)
2939 error(ERR_WARNING|ERR_PASS1,
2940 "trailing garbage after expression ignored");
2941 if (!is_simple(evalresult)) {
2942 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2943 return DIRECTIVE_FOUND;
2945 count = reloc_value(evalresult);
2946 if (count >= REP_LIMIT) {
2947 error(ERR_NONFATAL, "`%%rep' value exceeds limit");
2948 count = 0;
2949 } else
2950 count++;
2951 } else {
2952 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
2953 count = 0;
2955 free_tlist(origline);
2957 tmp_defining = defining;
2958 defining = nasm_malloc(sizeof(MMacro));
2959 defining->prev = NULL;
2960 defining->name = NULL; /* flags this macro as a %rep block */
2961 defining->casesense = false;
2962 defining->plus = false;
2963 defining->nolist = nolist;
2964 defining->in_progress = count;
2965 defining->max_depth = 0;
2966 defining->nparam_min = defining->nparam_max = 0;
2967 defining->defaults = NULL;
2968 defining->dlist = NULL;
2969 defining->expansion = NULL;
2970 defining->next_active = istk->mstk;
2971 defining->rep_nest = tmp_defining;
2972 return DIRECTIVE_FOUND;
2974 case PP_ENDREP:
2975 if (!defining || defining->name) {
2976 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2977 return DIRECTIVE_FOUND;
2981 * Now we have a "macro" defined - although it has no name
2982 * and we won't be entering it in the hash tables - we must
2983 * push a macro-end marker for it on to istk->expansion.
2984 * After that, it will take care of propagating itself (a
2985 * macro-end marker line for a macro which is really a %rep
2986 * block will cause the macro to be re-expanded, complete
2987 * with another macro-end marker to ensure the process
2988 * continues) until the whole expansion is forcibly removed
2989 * from istk->expansion by a %exitrep.
2991 l = nasm_malloc(sizeof(Line));
2992 l->next = istk->expansion;
2993 l->finishes = defining;
2994 l->first = NULL;
2995 istk->expansion = l;
2997 istk->mstk = defining;
2999 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
3000 tmp_defining = defining;
3001 defining = defining->rep_nest;
3002 free_tlist(origline);
3003 return DIRECTIVE_FOUND;
3005 case PP_EXITREP:
3007 * We must search along istk->expansion until we hit a
3008 * macro-end marker for a macro with no name. Then we set
3009 * its `in_progress' flag to 0.
3011 list_for_each(l, istk->expansion)
3012 if (l->finishes && !l->finishes->name)
3013 break;
3015 if (l)
3016 l->finishes->in_progress = 1;
3017 else
3018 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
3019 free_tlist(origline);
3020 return DIRECTIVE_FOUND;
3022 case PP_XDEFINE:
3023 case PP_IXDEFINE:
3024 case PP_DEFINE:
3025 case PP_IDEFINE:
3026 casesense = (i == PP_DEFINE || i == PP_XDEFINE);
3028 tline = tline->next;
3029 skip_white_(tline);
3030 tline = expand_id(tline);
3031 if (!tline || (tline->type != TOK_ID &&
3032 (tline->type != TOK_PREPROC_ID ||
3033 tline->text[1] != '$'))) {
3034 error(ERR_NONFATAL, "`%s' expects a macro identifier",
3035 pp_directives[i]);
3036 free_tlist(origline);
3037 return DIRECTIVE_FOUND;
3040 ctx = get_ctx(tline->text, &mname, false);
3041 last = tline;
3042 param_start = tline = tline->next;
3043 nparam = 0;
3045 /* Expand the macro definition now for %xdefine and %ixdefine */
3046 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
3047 tline = expand_smacro(tline);
3049 if (tok_is_(tline, "(")) {
3051 * This macro has parameters.
3054 tline = tline->next;
3055 while (1) {
3056 skip_white_(tline);
3057 if (!tline) {
3058 error(ERR_NONFATAL, "parameter identifier expected");
3059 free_tlist(origline);
3060 return DIRECTIVE_FOUND;
3062 if (tline->type != TOK_ID) {
3063 error(ERR_NONFATAL,
3064 "`%s': parameter identifier expected",
3065 tline->text);
3066 free_tlist(origline);
3067 return DIRECTIVE_FOUND;
3069 tline->type = TOK_SMAC_PARAM + nparam++;
3070 tline = tline->next;
3071 skip_white_(tline);
3072 if (tok_is_(tline, ",")) {
3073 tline = tline->next;
3074 } else {
3075 if (!tok_is_(tline, ")")) {
3076 error(ERR_NONFATAL,
3077 "`)' expected to terminate macro template");
3078 free_tlist(origline);
3079 return DIRECTIVE_FOUND;
3081 break;
3084 last = tline;
3085 tline = tline->next;
3087 if (tok_type_(tline, TOK_WHITESPACE))
3088 last = tline, tline = tline->next;
3089 macro_start = NULL;
3090 last->next = NULL;
3091 t = tline;
3092 while (t) {
3093 if (t->type == TOK_ID) {
3094 list_for_each(tt, param_start)
3095 if (tt->type >= TOK_SMAC_PARAM &&
3096 !strcmp(tt->text, t->text))
3097 t->type = tt->type;
3099 tt = t->next;
3100 t->next = macro_start;
3101 macro_start = t;
3102 t = tt;
3105 * Good. We now have a macro name, a parameter count, and a
3106 * token list (in reverse order) for an expansion. We ought
3107 * to be OK just to create an SMacro, store it, and let
3108 * free_tlist have the rest of the line (which we have
3109 * carefully re-terminated after chopping off the expansion
3110 * from the end).
3112 define_smacro(ctx, mname, casesense, nparam, macro_start);
3113 free_tlist(origline);
3114 return DIRECTIVE_FOUND;
3116 case PP_UNDEF:
3117 tline = tline->next;
3118 skip_white_(tline);
3119 tline = expand_id(tline);
3120 if (!tline || (tline->type != TOK_ID &&
3121 (tline->type != TOK_PREPROC_ID ||
3122 tline->text[1] != '$'))) {
3123 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
3124 free_tlist(origline);
3125 return DIRECTIVE_FOUND;
3127 if (tline->next) {
3128 error(ERR_WARNING|ERR_PASS1,
3129 "trailing garbage after macro name ignored");
3132 /* Find the context that symbol belongs to */
3133 ctx = get_ctx(tline->text, &mname, false);
3134 undef_smacro(ctx, mname);
3135 free_tlist(origline);
3136 return DIRECTIVE_FOUND;
3138 case PP_DEFSTR:
3139 case PP_IDEFSTR:
3140 casesense = (i == PP_DEFSTR);
3142 tline = tline->next;
3143 skip_white_(tline);
3144 tline = expand_id(tline);
3145 if (!tline || (tline->type != TOK_ID &&
3146 (tline->type != TOK_PREPROC_ID ||
3147 tline->text[1] != '$'))) {
3148 error(ERR_NONFATAL, "`%s' expects a macro identifier",
3149 pp_directives[i]);
3150 free_tlist(origline);
3151 return DIRECTIVE_FOUND;
3154 ctx = get_ctx(tline->text, &mname, false);
3155 last = tline;
3156 tline = expand_smacro(tline->next);
3157 last->next = NULL;
3159 while (tok_type_(tline, TOK_WHITESPACE))
3160 tline = delete_Token(tline);
3162 p = detoken(tline, false);
3163 macro_start = nasm_malloc(sizeof(*macro_start));
3164 macro_start->next = NULL;
3165 macro_start->text = nasm_quote(p, strlen(p));
3166 macro_start->type = TOK_STRING;
3167 macro_start->a.mac = NULL;
3168 nasm_free(p);
3171 * We now have a macro name, an implicit parameter count of
3172 * zero, and a string token to use as an expansion. Create
3173 * and store an SMacro.
3175 define_smacro(ctx, mname, casesense, 0, macro_start);
3176 free_tlist(origline);
3177 return DIRECTIVE_FOUND;
3179 case PP_DEFTOK:
3180 case PP_IDEFTOK:
3181 casesense = (i == PP_DEFTOK);
3183 tline = tline->next;
3184 skip_white_(tline);
3185 tline = expand_id(tline);
3186 if (!tline || (tline->type != TOK_ID &&
3187 (tline->type != TOK_PREPROC_ID ||
3188 tline->text[1] != '$'))) {
3189 error(ERR_NONFATAL,
3190 "`%s' expects a macro identifier as first parameter",
3191 pp_directives[i]);
3192 free_tlist(origline);
3193 return DIRECTIVE_FOUND;
3195 ctx = get_ctx(tline->text, &mname, false);
3196 last = tline;
3197 tline = expand_smacro(tline->next);
3198 last->next = NULL;
3200 t = tline;
3201 while (tok_type_(t, TOK_WHITESPACE))
3202 t = t->next;
3203 /* t should now point to the string */
3204 if (!tok_type_(t, TOK_STRING)) {
3205 error(ERR_NONFATAL,
3206 "`%s` requires string as second parameter",
3207 pp_directives[i]);
3208 free_tlist(tline);
3209 free_tlist(origline);
3210 return DIRECTIVE_FOUND;
3214 * Convert the string to a token stream. Note that smacros
3215 * are stored with the token stream reversed, so we have to
3216 * reverse the output of tokenize().
3218 nasm_unquote_cstr(t->text, i);
3219 macro_start = reverse_tokens(tokenize(t->text));
3222 * We now have a macro name, an implicit parameter count of
3223 * zero, and a numeric token to use as an expansion. Create
3224 * and store an SMacro.
3226 define_smacro(ctx, mname, casesense, 0, macro_start);
3227 free_tlist(tline);
3228 free_tlist(origline);
3229 return DIRECTIVE_FOUND;
3231 case PP_PATHSEARCH:
3233 FILE *fp;
3234 StrList *xsl = NULL;
3235 StrList **xst = &xsl;
3237 casesense = true;
3239 tline = tline->next;
3240 skip_white_(tline);
3241 tline = expand_id(tline);
3242 if (!tline || (tline->type != TOK_ID &&
3243 (tline->type != TOK_PREPROC_ID ||
3244 tline->text[1] != '$'))) {
3245 error(ERR_NONFATAL,
3246 "`%%pathsearch' expects a macro identifier as first parameter");
3247 free_tlist(origline);
3248 return DIRECTIVE_FOUND;
3250 ctx = get_ctx(tline->text, &mname, false);
3251 last = tline;
3252 tline = expand_smacro(tline->next);
3253 last->next = NULL;
3255 t = tline;
3256 while (tok_type_(t, TOK_WHITESPACE))
3257 t = t->next;
3259 if (!t || (t->type != TOK_STRING &&
3260 t->type != TOK_INTERNAL_STRING)) {
3261 error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
3262 free_tlist(tline);
3263 free_tlist(origline);
3264 return DIRECTIVE_FOUND; /* but we did _something_ */
3266 if (t->next)
3267 error(ERR_WARNING|ERR_PASS1,
3268 "trailing garbage after `%%pathsearch' ignored");
3269 p = t->text;
3270 if (t->type != TOK_INTERNAL_STRING)
3271 nasm_unquote(p, NULL);
3273 fp = inc_fopen(p, &xsl, &xst, true);
3274 if (fp) {
3275 p = xsl->str;
3276 fclose(fp); /* Don't actually care about the file */
3278 macro_start = nasm_malloc(sizeof(*macro_start));
3279 macro_start->next = NULL;
3280 macro_start->text = nasm_quote(p, strlen(p));
3281 macro_start->type = TOK_STRING;
3282 macro_start->a.mac = NULL;
3283 if (xsl)
3284 nasm_free(xsl);
3287 * We now have a macro name, an implicit parameter count of
3288 * zero, and a string token to use as an expansion. Create
3289 * and store an SMacro.
3291 define_smacro(ctx, mname, casesense, 0, macro_start);
3292 free_tlist(tline);
3293 free_tlist(origline);
3294 return DIRECTIVE_FOUND;
3297 case PP_STRLEN:
3298 casesense = true;
3300 tline = tline->next;
3301 skip_white_(tline);
3302 tline = expand_id(tline);
3303 if (!tline || (tline->type != TOK_ID &&
3304 (tline->type != TOK_PREPROC_ID ||
3305 tline->text[1] != '$'))) {
3306 error(ERR_NONFATAL,
3307 "`%%strlen' expects a macro identifier as first parameter");
3308 free_tlist(origline);
3309 return DIRECTIVE_FOUND;
3311 ctx = get_ctx(tline->text, &mname, false);
3312 last = tline;
3313 tline = expand_smacro(tline->next);
3314 last->next = NULL;
3316 t = tline;
3317 while (tok_type_(t, TOK_WHITESPACE))
3318 t = t->next;
3319 /* t should now point to the string */
3320 if (!tok_type_(t, TOK_STRING)) {
3321 error(ERR_NONFATAL,
3322 "`%%strlen` requires string as second parameter");
3323 free_tlist(tline);
3324 free_tlist(origline);
3325 return DIRECTIVE_FOUND;
3328 macro_start = nasm_malloc(sizeof(*macro_start));
3329 macro_start->next = NULL;
3330 make_tok_num(macro_start, nasm_unquote(t->text, NULL));
3331 macro_start->a.mac = NULL;
3334 * We now have a macro name, an implicit parameter count of
3335 * zero, and a numeric token to use as an expansion. Create
3336 * and store an SMacro.
3338 define_smacro(ctx, mname, casesense, 0, macro_start);
3339 free_tlist(tline);
3340 free_tlist(origline);
3341 return DIRECTIVE_FOUND;
3343 case PP_STRCAT:
3344 casesense = true;
3346 tline = tline->next;
3347 skip_white_(tline);
3348 tline = expand_id(tline);
3349 if (!tline || (tline->type != TOK_ID &&
3350 (tline->type != TOK_PREPROC_ID ||
3351 tline->text[1] != '$'))) {
3352 error(ERR_NONFATAL,
3353 "`%%strcat' expects a macro identifier as first parameter");
3354 free_tlist(origline);
3355 return DIRECTIVE_FOUND;
3357 ctx = get_ctx(tline->text, &mname, false);
3358 last = tline;
3359 tline = expand_smacro(tline->next);
3360 last->next = NULL;
3362 len = 0;
3363 list_for_each(t, tline) {
3364 switch (t->type) {
3365 case TOK_WHITESPACE:
3366 break;
3367 case TOK_STRING:
3368 len += t->a.len = nasm_unquote(t->text, NULL);
3369 break;
3370 case TOK_OTHER:
3371 if (!strcmp(t->text, ",")) /* permit comma separators */
3372 break;
3373 /* else fall through */
3374 default:
3375 error(ERR_NONFATAL,
3376 "non-string passed to `%%strcat' (%d)", t->type);
3377 free_tlist(tline);
3378 free_tlist(origline);
3379 return DIRECTIVE_FOUND;
3383 p = pp = nasm_malloc(len);
3384 list_for_each(t, tline) {
3385 if (t->type == TOK_STRING) {
3386 memcpy(p, t->text, t->a.len);
3387 p += t->a.len;
3392 * We now have a macro name, an implicit parameter count of
3393 * zero, and a numeric token to use as an expansion. Create
3394 * and store an SMacro.
3396 macro_start = new_Token(NULL, TOK_STRING, NULL, 0);
3397 macro_start->text = nasm_quote(pp, len);
3398 nasm_free(pp);
3399 define_smacro(ctx, mname, casesense, 0, macro_start);
3400 free_tlist(tline);
3401 free_tlist(origline);
3402 return DIRECTIVE_FOUND;
3404 case PP_SUBSTR:
3406 int64_t start, count;
3407 size_t len;
3409 casesense = true;
3411 tline = tline->next;
3412 skip_white_(tline);
3413 tline = expand_id(tline);
3414 if (!tline || (tline->type != TOK_ID &&
3415 (tline->type != TOK_PREPROC_ID ||
3416 tline->text[1] != '$'))) {
3417 error(ERR_NONFATAL,
3418 "`%%substr' expects a macro identifier as first parameter");
3419 free_tlist(origline);
3420 return DIRECTIVE_FOUND;
3422 ctx = get_ctx(tline->text, &mname, false);
3423 last = tline;
3424 tline = expand_smacro(tline->next);
3425 last->next = NULL;
3427 if (tline) /* skip expanded id */
3428 t = tline->next;
3429 while (tok_type_(t, TOK_WHITESPACE))
3430 t = t->next;
3432 /* t should now point to the string */
3433 if (!tok_type_(t, TOK_STRING)) {
3434 error(ERR_NONFATAL,
3435 "`%%substr` requires string as second parameter");
3436 free_tlist(tline);
3437 free_tlist(origline);
3438 return DIRECTIVE_FOUND;
3441 tt = t->next;
3442 tptr = &tt;
3443 tokval.t_type = TOKEN_INVALID;
3444 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3445 pass, error, NULL);
3446 if (!evalresult) {
3447 free_tlist(tline);
3448 free_tlist(origline);
3449 return DIRECTIVE_FOUND;
3450 } else if (!is_simple(evalresult)) {
3451 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3452 free_tlist(tline);
3453 free_tlist(origline);
3454 return DIRECTIVE_FOUND;
3456 start = evalresult->value - 1;
3458 while (tok_type_(tt, TOK_WHITESPACE))
3459 tt = tt->next;
3460 if (!tt) {
3461 count = 1; /* Backwards compatibility: one character */
3462 } else {
3463 tokval.t_type = TOKEN_INVALID;
3464 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3465 pass, error, NULL);
3466 if (!evalresult) {
3467 free_tlist(tline);
3468 free_tlist(origline);
3469 return DIRECTIVE_FOUND;
3470 } else if (!is_simple(evalresult)) {
3471 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3472 free_tlist(tline);
3473 free_tlist(origline);
3474 return DIRECTIVE_FOUND;
3476 count = evalresult->value;
3479 len = nasm_unquote(t->text, NULL);
3481 /* make start and count being in range */
3482 if (start < 0)
3483 start = 0;
3484 if (count < 0)
3485 count = len + count + 1 - start;
3486 if (start + count > (int64_t)len)
3487 count = len - start;
3488 if (!len || count < 0 || start >=(int64_t)len)
3489 start = -1, count = 0; /* empty string */
3491 macro_start = nasm_malloc(sizeof(*macro_start));
3492 macro_start->next = NULL;
3493 macro_start->text = nasm_quote((start < 0) ? "" : t->text + start, count);
3494 macro_start->type = TOK_STRING;
3495 macro_start->a.mac = NULL;
3498 * We now have a macro name, an implicit parameter count of
3499 * zero, and a numeric token to use as an expansion. Create
3500 * and store an SMacro.
3502 define_smacro(ctx, mname, casesense, 0, macro_start);
3503 free_tlist(tline);
3504 free_tlist(origline);
3505 return DIRECTIVE_FOUND;
3508 case PP_ASSIGN:
3509 case PP_IASSIGN:
3510 casesense = (i == PP_ASSIGN);
3512 tline = tline->next;
3513 skip_white_(tline);
3514 tline = expand_id(tline);
3515 if (!tline || (tline->type != TOK_ID &&
3516 (tline->type != TOK_PREPROC_ID ||
3517 tline->text[1] != '$'))) {
3518 error(ERR_NONFATAL,
3519 "`%%%sassign' expects a macro identifier",
3520 (i == PP_IASSIGN ? "i" : ""));
3521 free_tlist(origline);
3522 return DIRECTIVE_FOUND;
3524 ctx = get_ctx(tline->text, &mname, false);
3525 last = tline;
3526 tline = expand_smacro(tline->next);
3527 last->next = NULL;
3529 t = tline;
3530 tptr = &t;
3531 tokval.t_type = TOKEN_INVALID;
3532 evalresult =
3533 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3534 free_tlist(tline);
3535 if (!evalresult) {
3536 free_tlist(origline);
3537 return DIRECTIVE_FOUND;
3540 if (tokval.t_type)
3541 error(ERR_WARNING|ERR_PASS1,
3542 "trailing garbage after expression ignored");
3544 if (!is_simple(evalresult)) {
3545 error(ERR_NONFATAL,
3546 "non-constant value given to `%%%sassign'",
3547 (i == PP_IASSIGN ? "i" : ""));
3548 free_tlist(origline);
3549 return DIRECTIVE_FOUND;
3552 macro_start = nasm_malloc(sizeof(*macro_start));
3553 macro_start->next = NULL;
3554 make_tok_num(macro_start, reloc_value(evalresult));
3555 macro_start->a.mac = NULL;
3558 * We now have a macro name, an implicit parameter count of
3559 * zero, and a numeric token to use as an expansion. Create
3560 * and store an SMacro.
3562 define_smacro(ctx, mname, casesense, 0, macro_start);
3563 free_tlist(origline);
3564 return DIRECTIVE_FOUND;
3566 case PP_LINE:
3568 * Syntax is `%line nnn[+mmm] [filename]'
3570 tline = tline->next;
3571 skip_white_(tline);
3572 if (!tok_type_(tline, TOK_NUMBER)) {
3573 error(ERR_NONFATAL, "`%%line' expects line number");
3574 free_tlist(origline);
3575 return DIRECTIVE_FOUND;
3577 k = readnum(tline->text, &err);
3578 m = 1;
3579 tline = tline->next;
3580 if (tok_is_(tline, "+")) {
3581 tline = tline->next;
3582 if (!tok_type_(tline, TOK_NUMBER)) {
3583 error(ERR_NONFATAL, "`%%line' expects line increment");
3584 free_tlist(origline);
3585 return DIRECTIVE_FOUND;
3587 m = readnum(tline->text, &err);
3588 tline = tline->next;
3590 skip_white_(tline);
3591 src_set_linnum(k);
3592 istk->lineinc = m;
3593 if (tline) {
3594 nasm_free(src_set_fname(detoken(tline, false)));
3596 free_tlist(origline);
3597 return DIRECTIVE_FOUND;
3599 default:
3600 error(ERR_FATAL,
3601 "preprocessor directive `%s' not yet implemented",
3602 pp_directives[i]);
3603 return DIRECTIVE_FOUND;
3608 * Ensure that a macro parameter contains a condition code and
3609 * nothing else. Return the condition code index if so, or -1
3610 * otherwise.
3612 static int find_cc(Token * t)
3614 Token *tt;
3615 int i, j, k, m;
3617 if (!t)
3618 return -1; /* Probably a %+ without a space */
3620 skip_white_(t);
3621 if (t->type != TOK_ID)
3622 return -1;
3623 tt = t->next;
3624 skip_white_(tt);
3625 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
3626 return -1;
3628 i = -1;
3629 j = ARRAY_SIZE(conditions);
3630 while (j - i > 1) {
3631 k = (j + i) / 2;
3632 m = nasm_stricmp(t->text, conditions[k]);
3633 if (m == 0) {
3634 i = k;
3635 j = -2;
3636 break;
3637 } else if (m < 0) {
3638 j = k;
3639 } else
3640 i = k;
3642 if (j != -2)
3643 return -1;
3644 return i;
3647 static bool paste_tokens(Token **head, const struct tokseq_match *m,
3648 int mnum, bool handle_paste_tokens)
3650 Token **tail, *t, *tt;
3651 Token **paste_head;
3652 bool did_paste = false;
3653 char *tmp;
3654 int i;
3656 /* Now handle token pasting... */
3657 paste_head = NULL;
3658 tail = head;
3659 while ((t = *tail) && (tt = t->next)) {
3660 switch (t->type) {
3661 case TOK_WHITESPACE:
3662 if (tt->type == TOK_WHITESPACE) {
3663 /* Zap adjacent whitespace tokens */
3664 t->next = delete_Token(tt);
3665 } else {
3666 /* Do not advance paste_head here */
3667 tail = &t->next;
3669 break;
3670 case TOK_PASTE: /* %+ */
3671 if (handle_paste_tokens) {
3672 /* Zap %+ and whitespace tokens to the right */
3673 while (t && (t->type == TOK_WHITESPACE ||
3674 t->type == TOK_PASTE))
3675 t = *tail = delete_Token(t);
3676 if (!paste_head || !t)
3677 break; /* Nothing to paste with */
3678 tail = paste_head;
3679 t = *tail;
3680 tt = t->next;
3681 while (tok_type_(tt, TOK_WHITESPACE))
3682 tt = t->next = delete_Token(tt);
3683 if (tt) {
3684 tmp = nasm_strcat(t->text, tt->text);
3685 delete_Token(t);
3686 tt = delete_Token(tt);
3687 t = *tail = tokenize(tmp);
3688 nasm_free(tmp);
3689 while (t->next) {
3690 tail = &t->next;
3691 t = t->next;
3693 t->next = tt; /* Attach the remaining token chain */
3694 did_paste = true;
3696 paste_head = tail;
3697 tail = &t->next;
3698 break;
3700 /* else fall through */
3701 default:
3703 * Concatenation of tokens might look nontrivial
3704 * but in real it's pretty simple -- the caller
3705 * prepares the masks of token types to be concatenated
3706 * and we simply find matched sequences and slip
3707 * them together
3709 for (i = 0; i < mnum; i++) {
3710 if (PP_CONCAT_MASK(t->type) & m[i].mask_head) {
3711 size_t len = 0;
3712 char *tmp, *p;
3714 while (tt && (PP_CONCAT_MASK(tt->type) & m[i].mask_tail)) {
3715 len += strlen(tt->text);
3716 tt = tt->next;
3720 * Now tt points to the first token after
3721 * the potential paste area...
3723 if (tt != t->next) {
3724 /* We have at least two tokens... */
3725 len += strlen(t->text);
3726 p = tmp = nasm_malloc(len+1);
3727 while (t != tt) {
3728 strcpy(p, t->text);
3729 p = strchr(p, '\0');
3730 t = delete_Token(t);
3732 t = *tail = tokenize(tmp);
3733 nasm_free(tmp);
3734 while (t->next) {
3735 tail = &t->next;
3736 t = t->next;
3738 t->next = tt; /* Attach the remaining token chain */
3739 did_paste = true;
3741 paste_head = tail;
3742 tail = &t->next;
3743 break;
3746 if (i >= mnum) { /* no match */
3747 tail = &t->next;
3748 if (!tok_type_(t->next, TOK_WHITESPACE))
3749 paste_head = tail;
3751 break;
3754 return did_paste;
3758 * expands to a list of tokens from %{x:y}
3760 static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
3762 Token *t = tline, **tt, *tm, *head;
3763 char *pos;
3764 int fst, lst, j, i;
3766 pos = strchr(tline->text, ':');
3767 nasm_assert(pos);
3769 lst = atoi(pos + 1);
3770 fst = atoi(tline->text + 1);
3773 * only macros params are accounted so
3774 * if someone passes %0 -- we reject such
3775 * value(s)
3777 if (lst == 0 || fst == 0)
3778 goto err;
3780 /* the values should be sane */
3781 if ((fst > (int)mac->nparam || fst < (-(int)mac->nparam)) ||
3782 (lst > (int)mac->nparam || lst < (-(int)mac->nparam)))
3783 goto err;
3785 fst = fst < 0 ? fst + (int)mac->nparam + 1: fst;
3786 lst = lst < 0 ? lst + (int)mac->nparam + 1: lst;
3788 /* counted from zero */
3789 fst--, lst--;
3792 * it will be at least one token
3794 tm = mac->params[(fst + mac->rotate) % mac->nparam];
3795 t = new_Token(NULL, tm->type, tm->text, 0);
3796 head = t, tt = &t->next;
3797 if (fst < lst) {
3798 for (i = fst + 1; i <= lst; i++) {
3799 t = new_Token(NULL, TOK_OTHER, ",", 0);
3800 *tt = t, tt = &t->next;
3801 j = (i + mac->rotate) % mac->nparam;
3802 tm = mac->params[j];
3803 t = new_Token(NULL, tm->type, tm->text, 0);
3804 *tt = t, tt = &t->next;
3806 } else {
3807 for (i = fst - 1; i >= lst; i--) {
3808 t = new_Token(NULL, TOK_OTHER, ",", 0);
3809 *tt = t, tt = &t->next;
3810 j = (i + mac->rotate) % mac->nparam;
3811 tm = mac->params[j];
3812 t = new_Token(NULL, tm->type, tm->text, 0);
3813 *tt = t, tt = &t->next;
3817 *last = tt;
3818 return head;
3820 err:
3821 error(ERR_NONFATAL, "`%%{%s}': macro parameters out of range",
3822 &tline->text[1]);
3823 return tline;
3827 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3828 * %-n) and MMacro-local identifiers (%%foo) as well as
3829 * macro indirection (%[...]) and range (%{..:..}).
3831 static Token *expand_mmac_params(Token * tline)
3833 Token *t, *tt, **tail, *thead;
3834 bool changed = false;
3835 char *pos;
3837 tail = &thead;
3838 thead = NULL;
3840 while (tline) {
3841 if (tline->type == TOK_PREPROC_ID &&
3842 (((tline->text[1] == '+' || tline->text[1] == '-') && tline->text[2]) ||
3843 (tline->text[1] >= '0' && tline->text[1] <= '9') ||
3844 tline->text[1] == '%')) {
3845 char *text = NULL;
3846 int type = 0, cc; /* type = 0 to placate optimisers */
3847 char tmpbuf[30];
3848 unsigned int n;
3849 int i;
3850 MMacro *mac;
3852 t = tline;
3853 tline = tline->next;
3855 mac = istk->mstk;
3856 while (mac && !mac->name) /* avoid mistaking %reps for macros */
3857 mac = mac->next_active;
3858 if (!mac) {
3859 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
3860 } else {
3861 pos = strchr(t->text, ':');
3862 if (!pos) {
3863 switch (t->text[1]) {
3865 * We have to make a substitution of one of the
3866 * forms %1, %-1, %+1, %%foo, %0.
3868 case '0':
3869 type = TOK_NUMBER;
3870 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
3871 text = nasm_strdup(tmpbuf);
3872 break;
3873 case '%':
3874 type = TOK_ID;
3875 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
3876 mac->unique);
3877 text = nasm_strcat(tmpbuf, t->text + 2);
3878 break;
3879 case '-':
3880 n = atoi(t->text + 2) - 1;
3881 if (n >= mac->nparam)
3882 tt = NULL;
3883 else {
3884 if (mac->nparam > 1)
3885 n = (n + mac->rotate) % mac->nparam;
3886 tt = mac->params[n];
3888 cc = find_cc(tt);
3889 if (cc == -1) {
3890 error(ERR_NONFATAL,
3891 "macro parameter %d is not a condition code",
3892 n + 1);
3893 text = NULL;
3894 } else {
3895 type = TOK_ID;
3896 if (inverse_ccs[cc] == -1) {
3897 error(ERR_NONFATAL,
3898 "condition code `%s' is not invertible",
3899 conditions[cc]);
3900 text = NULL;
3901 } else
3902 text = nasm_strdup(conditions[inverse_ccs[cc]]);
3904 break;
3905 case '+':
3906 n = atoi(t->text + 2) - 1;
3907 if (n >= mac->nparam)
3908 tt = NULL;
3909 else {
3910 if (mac->nparam > 1)
3911 n = (n + mac->rotate) % mac->nparam;
3912 tt = mac->params[n];
3914 cc = find_cc(tt);
3915 if (cc == -1) {
3916 error(ERR_NONFATAL,
3917 "macro parameter %d is not a condition code",
3918 n + 1);
3919 text = NULL;
3920 } else {
3921 type = TOK_ID;
3922 text = nasm_strdup(conditions[cc]);
3924 break;
3925 default:
3926 n = atoi(t->text + 1) - 1;
3927 if (n >= mac->nparam)
3928 tt = NULL;
3929 else {
3930 if (mac->nparam > 1)
3931 n = (n + mac->rotate) % mac->nparam;
3932 tt = mac->params[n];
3934 if (tt) {
3935 for (i = 0; i < mac->paramlen[n]; i++) {
3936 *tail = new_Token(NULL, tt->type, tt->text, 0);
3937 tail = &(*tail)->next;
3938 tt = tt->next;
3941 text = NULL; /* we've done it here */
3942 break;
3944 } else {
3946 * seems we have a parameters range here
3948 Token *head, **last;
3949 head = expand_mmac_params_range(mac, t, &last);
3950 if (head != t) {
3951 *tail = head;
3952 *last = tline;
3953 tline = head;
3954 text = NULL;
3958 if (!text) {
3959 delete_Token(t);
3960 } else {
3961 *tail = t;
3962 tail = &t->next;
3963 t->type = type;
3964 nasm_free(t->text);
3965 t->text = text;
3966 t->a.mac = NULL;
3968 changed = true;
3969 continue;
3970 } else if (tline->type == TOK_INDIRECT) {
3971 t = tline;
3972 tline = tline->next;
3973 tt = tokenize(t->text);
3974 tt = expand_mmac_params(tt);
3975 tt = expand_smacro(tt);
3976 *tail = tt;
3977 while (tt) {
3978 tt->a.mac = NULL; /* Necessary? */
3979 tail = &tt->next;
3980 tt = tt->next;
3982 delete_Token(t);
3983 changed = true;
3984 } else {
3985 t = *tail = tline;
3986 tline = tline->next;
3987 t->a.mac = NULL;
3988 tail = &t->next;
3991 *tail = NULL;
3993 if (changed) {
3994 const struct tokseq_match t[] = {
3996 PP_CONCAT_MASK(TOK_ID) |
3997 PP_CONCAT_MASK(TOK_FLOAT), /* head */
3998 PP_CONCAT_MASK(TOK_ID) |
3999 PP_CONCAT_MASK(TOK_NUMBER) |
4000 PP_CONCAT_MASK(TOK_FLOAT) |
4001 PP_CONCAT_MASK(TOK_OTHER) /* tail */
4004 PP_CONCAT_MASK(TOK_NUMBER), /* head */
4005 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
4008 paste_tokens(&thead, t, ARRAY_SIZE(t), false);
4011 return thead;
4015 * Expand all single-line macro calls made in the given line.
4016 * Return the expanded version of the line. The original is deemed
4017 * to be destroyed in the process. (In reality we'll just move
4018 * Tokens from input to output a lot of the time, rather than
4019 * actually bothering to destroy and replicate.)
4022 static Token *expand_smacro(Token * tline)
4024 Token *t, *tt, *mstart, **tail, *thead;
4025 SMacro *head = NULL, *m;
4026 Token **params;
4027 int *paramsize;
4028 unsigned int nparam, sparam;
4029 int brackets;
4030 Token *org_tline = tline;
4031 Context *ctx;
4032 const char *mname;
4033 int deadman = DEADMAN_LIMIT;
4034 bool expanded;
4037 * Trick: we should avoid changing the start token pointer since it can
4038 * be contained in "next" field of other token. Because of this
4039 * we allocate a copy of first token and work with it; at the end of
4040 * routine we copy it back
4042 if (org_tline) {
4043 tline = new_Token(org_tline->next, org_tline->type,
4044 org_tline->text, 0);
4045 tline->a.mac = org_tline->a.mac;
4046 nasm_free(org_tline->text);
4047 org_tline->text = NULL;
4050 expanded = true; /* Always expand %+ at least once */
4052 again:
4053 thead = NULL;
4054 tail = &thead;
4056 while (tline) { /* main token loop */
4057 if (!--deadman) {
4058 error(ERR_NONFATAL, "interminable macro recursion");
4059 goto err;
4062 if ((mname = tline->text)) {
4063 /* if this token is a local macro, look in local context */
4064 if (tline->type == TOK_ID) {
4065 head = (SMacro *)hash_findix(&smacros, mname);
4066 } else if (tline->type == TOK_PREPROC_ID) {
4067 ctx = get_ctx(mname, &mname, true);
4068 head = ctx ? (SMacro *)hash_findix(&ctx->localmac, mname) : NULL;
4069 } else
4070 head = NULL;
4073 * We've hit an identifier. As in is_mmacro below, we first
4074 * check whether the identifier is a single-line macro at
4075 * all, then think about checking for parameters if
4076 * necessary.
4078 list_for_each(m, head)
4079 if (!mstrcmp(m->name, mname, m->casesense))
4080 break;
4081 if (m) {
4082 mstart = tline;
4083 params = NULL;
4084 paramsize = NULL;
4085 if (m->nparam == 0) {
4087 * Simple case: the macro is parameterless. Discard the
4088 * one token that the macro call took, and push the
4089 * expansion back on the to-do stack.
4091 if (!m->expansion) {
4092 if (!strcmp("__FILE__", m->name)) {
4093 int32_t num = 0;
4094 char *file = NULL;
4095 src_get(&num, &file);
4096 tline->text = nasm_quote(file, strlen(file));
4097 tline->type = TOK_STRING;
4098 nasm_free(file);
4099 continue;
4101 if (!strcmp("__LINE__", m->name)) {
4102 nasm_free(tline->text);
4103 make_tok_num(tline, src_get_linnum());
4104 continue;
4106 if (!strcmp("__BITS__", m->name)) {
4107 nasm_free(tline->text);
4108 make_tok_num(tline, globalbits);
4109 continue;
4111 tline = delete_Token(tline);
4112 continue;
4114 } else {
4116 * Complicated case: at least one macro with this name
4117 * exists and takes parameters. We must find the
4118 * parameters in the call, count them, find the SMacro
4119 * that corresponds to that form of the macro call, and
4120 * substitute for the parameters when we expand. What a
4121 * pain.
4123 /*tline = tline->next;
4124 skip_white_(tline); */
4125 do {
4126 t = tline->next;
4127 while (tok_type_(t, TOK_SMAC_END)) {
4128 t->a.mac->in_progress = false;
4129 t->text = NULL;
4130 t = tline->next = delete_Token(t);
4132 tline = t;
4133 } while (tok_type_(tline, TOK_WHITESPACE));
4134 if (!tok_is_(tline, "(")) {
4136 * This macro wasn't called with parameters: ignore
4137 * the call. (Behaviour borrowed from gnu cpp.)
4139 tline = mstart;
4140 m = NULL;
4141 } else {
4142 int paren = 0;
4143 int white = 0;
4144 brackets = 0;
4145 nparam = 0;
4146 sparam = PARAM_DELTA;
4147 params = nasm_malloc(sparam * sizeof(Token *));
4148 params[0] = tline->next;
4149 paramsize = nasm_malloc(sparam * sizeof(int));
4150 paramsize[0] = 0;
4151 while (true) { /* parameter loop */
4153 * For some unusual expansions
4154 * which concatenates function call
4156 t = tline->next;
4157 while (tok_type_(t, TOK_SMAC_END)) {
4158 t->a.mac->in_progress = false;
4159 t->text = NULL;
4160 t = tline->next = delete_Token(t);
4162 tline = t;
4164 if (!tline) {
4165 error(ERR_NONFATAL,
4166 "macro call expects terminating `)'");
4167 break;
4169 if (tline->type == TOK_WHITESPACE
4170 && brackets <= 0) {
4171 if (paramsize[nparam])
4172 white++;
4173 else
4174 params[nparam] = tline->next;
4175 continue; /* parameter loop */
4177 if (tline->type == TOK_OTHER
4178 && tline->text[1] == 0) {
4179 char ch = tline->text[0];
4180 if (ch == ',' && !paren && brackets <= 0) {
4181 if (++nparam >= sparam) {
4182 sparam += PARAM_DELTA;
4183 params = nasm_realloc(params,
4184 sparam * sizeof(Token *));
4185 paramsize = nasm_realloc(paramsize,
4186 sparam * sizeof(int));
4188 params[nparam] = tline->next;
4189 paramsize[nparam] = 0;
4190 white = 0;
4191 continue; /* parameter loop */
4193 if (ch == '{' &&
4194 (brackets > 0 || (brackets == 0 &&
4195 !paramsize[nparam])))
4197 if (!(brackets++)) {
4198 params[nparam] = tline->next;
4199 continue; /* parameter loop */
4202 if (ch == '}' && brackets > 0)
4203 if (--brackets == 0) {
4204 brackets = -1;
4205 continue; /* parameter loop */
4207 if (ch == '(' && !brackets)
4208 paren++;
4209 if (ch == ')' && brackets <= 0)
4210 if (--paren < 0)
4211 break;
4213 if (brackets < 0) {
4214 brackets = 0;
4215 error(ERR_NONFATAL, "braces do not "
4216 "enclose all of macro parameter");
4218 paramsize[nparam] += white + 1;
4219 white = 0;
4220 } /* parameter loop */
4221 nparam++;
4222 while (m && (m->nparam != nparam ||
4223 mstrcmp(m->name, mname,
4224 m->casesense)))
4225 m = m->next;
4226 if (!m)
4227 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
4228 "macro `%s' exists, "
4229 "but not taking %d parameters",
4230 mstart->text, nparam);
4233 if (m && m->in_progress)
4234 m = NULL;
4235 if (!m) { /* in progess or didn't find '(' or wrong nparam */
4237 * Design question: should we handle !tline, which
4238 * indicates missing ')' here, or expand those
4239 * macros anyway, which requires the (t) test a few
4240 * lines down?
4242 nasm_free(params);
4243 nasm_free(paramsize);
4244 tline = mstart;
4245 } else {
4247 * Expand the macro: we are placed on the last token of the
4248 * call, so that we can easily split the call from the
4249 * following tokens. We also start by pushing an SMAC_END
4250 * token for the cycle removal.
4252 t = tline;
4253 if (t) {
4254 tline = t->next;
4255 t->next = NULL;
4257 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
4258 tt->a.mac = m;
4259 m->in_progress = true;
4260 tline = tt;
4261 list_for_each(t, m->expansion) {
4262 if (t->type >= TOK_SMAC_PARAM) {
4263 Token *pcopy = tline, **ptail = &pcopy;
4264 Token *ttt, *pt;
4265 int i;
4267 ttt = params[t->type - TOK_SMAC_PARAM];
4268 i = paramsize[t->type - TOK_SMAC_PARAM];
4269 while (--i >= 0) {
4270 pt = *ptail = new_Token(tline, ttt->type,
4271 ttt->text, 0);
4272 ptail = &pt->next;
4273 ttt = ttt->next;
4275 tline = pcopy;
4276 } else if (t->type == TOK_PREPROC_Q) {
4277 tt = new_Token(tline, TOK_ID, mname, 0);
4278 tline = tt;
4279 } else if (t->type == TOK_PREPROC_QQ) {
4280 tt = new_Token(tline, TOK_ID, m->name, 0);
4281 tline = tt;
4282 } else {
4283 tt = new_Token(tline, t->type, t->text, 0);
4284 tline = tt;
4289 * Having done that, get rid of the macro call, and clean
4290 * up the parameters.
4292 nasm_free(params);
4293 nasm_free(paramsize);
4294 free_tlist(mstart);
4295 expanded = true;
4296 continue; /* main token loop */
4301 if (tline->type == TOK_SMAC_END) {
4302 tline->a.mac->in_progress = false;
4303 tline = delete_Token(tline);
4304 } else {
4305 t = *tail = tline;
4306 tline = tline->next;
4307 t->a.mac = NULL;
4308 t->next = NULL;
4309 tail = &t->next;
4314 * Now scan the entire line and look for successive TOK_IDs that resulted
4315 * after expansion (they can't be produced by tokenize()). The successive
4316 * TOK_IDs should be concatenated.
4317 * Also we look for %+ tokens and concatenate the tokens before and after
4318 * them (without white spaces in between).
4320 if (expanded) {
4321 const struct tokseq_match t[] = {
4323 PP_CONCAT_MASK(TOK_ID) |
4324 PP_CONCAT_MASK(TOK_PREPROC_ID), /* head */
4325 PP_CONCAT_MASK(TOK_ID) |
4326 PP_CONCAT_MASK(TOK_PREPROC_ID) |
4327 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
4330 if (paste_tokens(&thead, t, ARRAY_SIZE(t), true)) {
4332 * If we concatenated something, *and* we had previously expanded
4333 * an actual macro, scan the lines again for macros...
4335 tline = thead;
4336 expanded = false;
4337 goto again;
4341 err:
4342 if (org_tline) {
4343 if (thead) {
4344 *org_tline = *thead;
4345 /* since we just gave text to org_line, don't free it */
4346 thead->text = NULL;
4347 delete_Token(thead);
4348 } else {
4349 /* the expression expanded to empty line;
4350 we can't return NULL for some reasons
4351 we just set the line to a single WHITESPACE token. */
4352 memset(org_tline, 0, sizeof(*org_tline));
4353 org_tline->text = NULL;
4354 org_tline->type = TOK_WHITESPACE;
4356 thead = org_tline;
4359 return thead;
4363 * Similar to expand_smacro but used exclusively with macro identifiers
4364 * right before they are fetched in. The reason is that there can be
4365 * identifiers consisting of several subparts. We consider that if there
4366 * are more than one element forming the name, user wants a expansion,
4367 * otherwise it will be left as-is. Example:
4369 * %define %$abc cde
4371 * the identifier %$abc will be left as-is so that the handler for %define
4372 * will suck it and define the corresponding value. Other case:
4374 * %define _%$abc cde
4376 * In this case user wants name to be expanded *before* %define starts
4377 * working, so we'll expand %$abc into something (if it has a value;
4378 * otherwise it will be left as-is) then concatenate all successive
4379 * PP_IDs into one.
4381 static Token *expand_id(Token * tline)
4383 Token *cur, *oldnext = NULL;
4385 if (!tline || !tline->next)
4386 return tline;
4388 cur = tline;
4389 while (cur->next &&
4390 (cur->next->type == TOK_ID ||
4391 cur->next->type == TOK_PREPROC_ID
4392 || cur->next->type == TOK_NUMBER))
4393 cur = cur->next;
4395 /* If identifier consists of just one token, don't expand */
4396 if (cur == tline)
4397 return tline;
4399 if (cur) {
4400 oldnext = cur->next; /* Detach the tail past identifier */
4401 cur->next = NULL; /* so that expand_smacro stops here */
4404 tline = expand_smacro(tline);
4406 if (cur) {
4407 /* expand_smacro possibly changhed tline; re-scan for EOL */
4408 cur = tline;
4409 while (cur && cur->next)
4410 cur = cur->next;
4411 if (cur)
4412 cur->next = oldnext;
4415 return tline;
4419 * Determine whether the given line constitutes a multi-line macro
4420 * call, and return the MMacro structure called if so. Doesn't have
4421 * to check for an initial label - that's taken care of in
4422 * expand_mmacro - but must check numbers of parameters. Guaranteed
4423 * to be called with tline->type == TOK_ID, so the putative macro
4424 * name is easy to find.
4426 static MMacro *is_mmacro(Token * tline, Token *** params_array)
4428 MMacro *head, *m;
4429 Token **params;
4430 int nparam;
4432 head = (MMacro *) hash_findix(&mmacros, tline->text);
4435 * Efficiency: first we see if any macro exists with the given
4436 * name. If not, we can return NULL immediately. _Then_ we
4437 * count the parameters, and then we look further along the
4438 * list if necessary to find the proper MMacro.
4440 list_for_each(m, head)
4441 if (!mstrcmp(m->name, tline->text, m->casesense))
4442 break;
4443 if (!m)
4444 return NULL;
4447 * OK, we have a potential macro. Count and demarcate the
4448 * parameters.
4450 count_mmac_params(tline->next, &nparam, &params);
4453 * So we know how many parameters we've got. Find the MMacro
4454 * structure that handles this number.
4456 while (m) {
4457 if (m->nparam_min <= nparam
4458 && (m->plus || nparam <= m->nparam_max)) {
4460 * This one is right. Just check if cycle removal
4461 * prohibits us using it before we actually celebrate...
4463 if (m->in_progress > m->max_depth) {
4464 if (m->max_depth > 0) {
4465 error(ERR_WARNING,
4466 "reached maximum recursion depth of %i",
4467 m->max_depth);
4469 nasm_free(params);
4470 return NULL;
4473 * It's right, and we can use it. Add its default
4474 * parameters to the end of our list if necessary.
4476 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
4477 params =
4478 nasm_realloc(params,
4479 ((m->nparam_min + m->ndefs +
4480 1) * sizeof(*params)));
4481 while (nparam < m->nparam_min + m->ndefs) {
4482 params[nparam] = m->defaults[nparam - m->nparam_min];
4483 nparam++;
4487 * If we've gone over the maximum parameter count (and
4488 * we're in Plus mode), ignore parameters beyond
4489 * nparam_max.
4491 if (m->plus && nparam > m->nparam_max)
4492 nparam = m->nparam_max;
4494 * Then terminate the parameter list, and leave.
4496 if (!params) { /* need this special case */
4497 params = nasm_malloc(sizeof(*params));
4498 nparam = 0;
4500 params[nparam] = NULL;
4501 *params_array = params;
4502 return m;
4505 * This one wasn't right: look for the next one with the
4506 * same name.
4508 list_for_each(m, m->next)
4509 if (!mstrcmp(m->name, tline->text, m->casesense))
4510 break;
4514 * After all that, we didn't find one with the right number of
4515 * parameters. Issue a warning, and fail to expand the macro.
4517 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
4518 "macro `%s' exists, but not taking %d parameters",
4519 tline->text, nparam);
4520 nasm_free(params);
4521 return NULL;
4526 * Save MMacro invocation specific fields in
4527 * preparation for a recursive macro expansion
4529 static void push_mmacro(MMacro *m)
4531 MMacroInvocation *i;
4533 i = nasm_malloc(sizeof(MMacroInvocation));
4534 i->prev = m->prev;
4535 i->params = m->params;
4536 i->iline = m->iline;
4537 i->nparam = m->nparam;
4538 i->rotate = m->rotate;
4539 i->paramlen = m->paramlen;
4540 i->unique = m->unique;
4541 i->condcnt = m->condcnt;
4542 m->prev = i;
4547 * Restore MMacro invocation specific fields that were
4548 * saved during a previous recursive macro expansion
4550 static void pop_mmacro(MMacro *m)
4552 MMacroInvocation *i;
4554 if (m->prev) {
4555 i = m->prev;
4556 m->prev = i->prev;
4557 m->params = i->params;
4558 m->iline = i->iline;
4559 m->nparam = i->nparam;
4560 m->rotate = i->rotate;
4561 m->paramlen = i->paramlen;
4562 m->unique = i->unique;
4563 m->condcnt = i->condcnt;
4564 nasm_free(i);
4570 * Expand the multi-line macro call made by the given line, if
4571 * there is one to be expanded. If there is, push the expansion on
4572 * istk->expansion and return 1. Otherwise return 0.
4574 static int expand_mmacro(Token * tline)
4576 Token *startline = tline;
4577 Token *label = NULL;
4578 int dont_prepend = 0;
4579 Token **params, *t, *mtok, *tt;
4580 MMacro *m;
4581 Line *l, *ll;
4582 int i, nparam, *paramlen;
4583 const char *mname;
4585 t = tline;
4586 skip_white_(t);
4587 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4588 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
4589 return 0;
4590 mtok = t;
4591 m = is_mmacro(t, &params);
4592 if (m) {
4593 mname = t->text;
4594 } else {
4595 Token *last;
4597 * We have an id which isn't a macro call. We'll assume
4598 * it might be a label; we'll also check to see if a
4599 * colon follows it. Then, if there's another id after
4600 * that lot, we'll check it again for macro-hood.
4602 label = last = t;
4603 t = t->next;
4604 if (tok_type_(t, TOK_WHITESPACE))
4605 last = t, t = t->next;
4606 if (tok_is_(t, ":")) {
4607 dont_prepend = 1;
4608 last = t, t = t->next;
4609 if (tok_type_(t, TOK_WHITESPACE))
4610 last = t, t = t->next;
4612 if (!tok_type_(t, TOK_ID) || !(m = is_mmacro(t, &params)))
4613 return 0;
4614 last->next = NULL;
4615 mname = t->text;
4616 tline = t;
4620 * Fix up the parameters: this involves stripping leading and
4621 * trailing whitespace, then stripping braces if they are
4622 * present.
4624 for (nparam = 0; params[nparam]; nparam++) ;
4625 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
4627 for (i = 0; params[i]; i++) {
4628 int brace = false;
4629 int comma = (!m->plus || i < nparam - 1);
4631 t = params[i];
4632 skip_white_(t);
4633 if (tok_is_(t, "{"))
4634 t = t->next, brace = true, comma = false;
4635 params[i] = t;
4636 paramlen[i] = 0;
4637 while (t) {
4638 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
4639 break; /* ... because we have hit a comma */
4640 if (comma && t->type == TOK_WHITESPACE
4641 && tok_is_(t->next, ","))
4642 break; /* ... or a space then a comma */
4643 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
4644 break; /* ... or a brace */
4645 t = t->next;
4646 paramlen[i]++;
4651 * OK, we have a MMacro structure together with a set of
4652 * parameters. We must now go through the expansion and push
4653 * copies of each Line on to istk->expansion. Substitution of
4654 * parameter tokens and macro-local tokens doesn't get done
4655 * until the single-line macro substitution process; this is
4656 * because delaying them allows us to change the semantics
4657 * later through %rotate.
4659 * First, push an end marker on to istk->expansion, mark this
4660 * macro as in progress, and set up its invocation-specific
4661 * variables.
4663 ll = nasm_malloc(sizeof(Line));
4664 ll->next = istk->expansion;
4665 ll->finishes = m;
4666 ll->first = NULL;
4667 istk->expansion = ll;
4670 * Save the previous MMacro expansion in the case of
4671 * macro recursion
4673 if (m->max_depth && m->in_progress)
4674 push_mmacro(m);
4676 m->in_progress ++;
4677 m->params = params;
4678 m->iline = tline;
4679 m->nparam = nparam;
4680 m->rotate = 0;
4681 m->paramlen = paramlen;
4682 m->unique = unique++;
4683 m->lineno = 0;
4684 m->condcnt = 0;
4686 m->next_active = istk->mstk;
4687 istk->mstk = m;
4689 list_for_each(l, m->expansion) {
4690 Token **tail;
4692 ll = nasm_malloc(sizeof(Line));
4693 ll->finishes = NULL;
4694 ll->next = istk->expansion;
4695 istk->expansion = ll;
4696 tail = &ll->first;
4698 list_for_each(t, l->first) {
4699 Token *x = t;
4700 switch (t->type) {
4701 case TOK_PREPROC_Q:
4702 tt = *tail = new_Token(NULL, TOK_ID, mname, 0);
4703 break;
4704 case TOK_PREPROC_QQ:
4705 tt = *tail = new_Token(NULL, TOK_ID, m->name, 0);
4706 break;
4707 case TOK_PREPROC_ID:
4708 if (t->text[1] == '0' && t->text[2] == '0') {
4709 dont_prepend = -1;
4710 x = label;
4711 if (!x)
4712 continue;
4714 /* fall through */
4715 default:
4716 tt = *tail = new_Token(NULL, x->type, x->text, 0);
4717 break;
4719 tail = &tt->next;
4721 *tail = NULL;
4725 * If we had a label, push it on as the first line of
4726 * the macro expansion.
4728 if (label) {
4729 if (dont_prepend < 0)
4730 free_tlist(startline);
4731 else {
4732 ll = nasm_malloc(sizeof(Line));
4733 ll->finishes = NULL;
4734 ll->next = istk->expansion;
4735 istk->expansion = ll;
4736 ll->first = startline;
4737 if (!dont_prepend) {
4738 while (label->next)
4739 label = label->next;
4740 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
4745 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
4747 return 1;
4750 /* The function that actually does the error reporting */
4751 static void verror(int severity, const char *fmt, va_list arg)
4753 char buff[1024];
4754 MMacro *mmac = NULL;
4755 int delta = 0;
4757 vsnprintf(buff, sizeof(buff), fmt, arg);
4759 /* get %macro name */
4760 if (istk && istk->mstk) {
4761 mmac = istk->mstk;
4762 /* but %rep blocks should be skipped */
4763 while (mmac && !mmac->name)
4764 mmac = mmac->next_active, delta++;
4767 if (mmac)
4768 nasm_error(severity, "(%s:%d) %s",
4769 mmac->name, mmac->lineno - delta, buff);
4770 else
4771 nasm_error(severity, "%s", buff);
4775 * Since preprocessor always operate only on the line that didn't
4776 * arrived yet, we should always use ERR_OFFBY1.
4778 static void error(int severity, const char *fmt, ...)
4780 va_list arg;
4782 /* If we're in a dead branch of IF or something like it, ignore the error */
4783 if (istk && istk->conds && !emitting(istk->conds->state))
4784 return;
4786 va_start(arg, fmt);
4787 verror(severity, fmt, arg);
4788 va_end(arg);
4792 * Because %else etc are evaluated in the state context
4793 * of the previous branch, errors might get lost with error():
4794 * %if 0 ... %else trailing garbage ... %endif
4795 * So %else etc should report errors with this function.
4797 static void error_precond(int severity, const char *fmt, ...)
4799 va_list arg;
4801 /* Only ignore the error if it's really in a dead branch */
4802 if (istk && istk->conds && istk->conds->state == COND_NEVER)
4803 return;
4805 va_start(arg, fmt);
4806 verror(severity, fmt, arg);
4807 va_end(arg);
4810 static void
4811 pp_reset(char *file, int apass, ListGen * listgen, StrList **deplist)
4813 Token *t;
4815 cstk = NULL;
4816 istk = nasm_malloc(sizeof(Include));
4817 istk->next = NULL;
4818 istk->conds = NULL;
4819 istk->expansion = NULL;
4820 istk->mstk = NULL;
4821 istk->fp = fopen(file, "r");
4822 istk->fname = NULL;
4823 src_set_fname(nasm_strdup(file));
4824 src_set_linnum(0);
4825 istk->lineinc = 1;
4826 if (!istk->fp)
4827 error(ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'",
4828 file);
4829 defining = NULL;
4830 nested_mac_count = 0;
4831 nested_rep_count = 0;
4832 init_macros();
4833 unique = 0;
4834 if (tasm_compatible_mode) {
4835 stdmacpos = nasm_stdmac;
4836 } else {
4837 stdmacpos = nasm_stdmac_after_tasm;
4839 any_extrastdmac = extrastdmac && *extrastdmac;
4840 do_predef = true;
4841 list = listgen;
4844 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4845 * The caller, however, will also pass in 3 for preprocess-only so
4846 * we can set __PASS__ accordingly.
4848 pass = apass > 2 ? 2 : apass;
4850 dephead = deptail = deplist;
4851 if (deplist) {
4852 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
4853 sl->next = NULL;
4854 strcpy(sl->str, file);
4855 *deptail = sl;
4856 deptail = &sl->next;
4860 * Define the __PASS__ macro. This is defined here unlike
4861 * all the other builtins, because it is special -- it varies between
4862 * passes.
4864 t = nasm_malloc(sizeof(*t));
4865 t->next = NULL;
4866 make_tok_num(t, apass);
4867 t->a.mac = NULL;
4868 define_smacro(NULL, "__PASS__", true, 0, t);
4871 static char *pp_getline(void)
4873 char *line;
4874 Token *tline;
4876 while (1) {
4878 * Fetch a tokenized line, either from the macro-expansion
4879 * buffer or from the input file.
4881 tline = NULL;
4882 while (istk->expansion && istk->expansion->finishes) {
4883 Line *l = istk->expansion;
4884 if (!l->finishes->name && l->finishes->in_progress > 1) {
4885 Line *ll;
4888 * This is a macro-end marker for a macro with no
4889 * name, which means it's not really a macro at all
4890 * but a %rep block, and the `in_progress' field is
4891 * more than 1, meaning that we still need to
4892 * repeat. (1 means the natural last repetition; 0
4893 * means termination by %exitrep.) We have
4894 * therefore expanded up to the %endrep, and must
4895 * push the whole block on to the expansion buffer
4896 * again. We don't bother to remove the macro-end
4897 * marker: we'd only have to generate another one
4898 * if we did.
4900 l->finishes->in_progress--;
4901 list_for_each(l, l->finishes->expansion) {
4902 Token *t, *tt, **tail;
4904 ll = nasm_malloc(sizeof(Line));
4905 ll->next = istk->expansion;
4906 ll->finishes = NULL;
4907 ll->first = NULL;
4908 tail = &ll->first;
4910 list_for_each(t, l->first) {
4911 if (t->text || t->type == TOK_WHITESPACE) {
4912 tt = *tail = new_Token(NULL, t->type, t->text, 0);
4913 tail = &tt->next;
4917 istk->expansion = ll;
4919 } else {
4921 * Check whether a `%rep' was started and not ended
4922 * within this macro expansion. This can happen and
4923 * should be detected. It's a fatal error because
4924 * I'm too confused to work out how to recover
4925 * sensibly from it.
4927 if (defining) {
4928 if (defining->name)
4929 error(ERR_PANIC,
4930 "defining with name in expansion");
4931 else if (istk->mstk->name)
4932 error(ERR_FATAL,
4933 "`%%rep' without `%%endrep' within"
4934 " expansion of macro `%s'",
4935 istk->mstk->name);
4939 * FIXME: investigate the relationship at this point between
4940 * istk->mstk and l->finishes
4943 MMacro *m = istk->mstk;
4944 istk->mstk = m->next_active;
4945 if (m->name) {
4947 * This was a real macro call, not a %rep, and
4948 * therefore the parameter information needs to
4949 * be freed.
4951 if (m->prev) {
4952 pop_mmacro(m);
4953 l->finishes->in_progress --;
4954 } else {
4955 nasm_free(m->params);
4956 free_tlist(m->iline);
4957 nasm_free(m->paramlen);
4958 l->finishes->in_progress = 0;
4960 } else
4961 free_mmacro(m);
4963 istk->expansion = l->next;
4964 nasm_free(l);
4965 list->downlevel(LIST_MACRO);
4968 while (1) { /* until we get a line we can use */
4970 if (istk->expansion) { /* from a macro expansion */
4971 char *p;
4972 Line *l = istk->expansion;
4973 if (istk->mstk)
4974 istk->mstk->lineno++;
4975 tline = l->first;
4976 istk->expansion = l->next;
4977 nasm_free(l);
4978 p = detoken(tline, false);
4979 list->line(LIST_MACRO, p);
4980 nasm_free(p);
4981 break;
4983 line = read_line();
4984 if (line) { /* from the current input file */
4985 line = prepreproc(line);
4986 tline = tokenize(line);
4987 nasm_free(line);
4988 break;
4991 * The current file has ended; work down the istk
4994 Include *i = istk;
4995 fclose(i->fp);
4996 if (i->conds) {
4997 /* nasm_error can't be conditionally suppressed */
4998 nasm_error(ERR_FATAL,
4999 "expected `%%endif' before end of file");
5001 /* only set line and file name if there's a next node */
5002 if (i->next) {
5003 src_set_linnum(i->lineno);
5004 nasm_free(src_set_fname(i->fname));
5006 istk = i->next;
5007 list->downlevel(LIST_INCLUDE);
5008 nasm_free(i);
5009 if (!istk)
5010 return NULL;
5011 if (istk->expansion && istk->expansion->finishes)
5012 break;
5017 * We must expand MMacro parameters and MMacro-local labels
5018 * _before_ we plunge into directive processing, to cope
5019 * with things like `%define something %1' such as STRUC
5020 * uses. Unless we're _defining_ a MMacro, in which case
5021 * those tokens should be left alone to go into the
5022 * definition; and unless we're in a non-emitting
5023 * condition, in which case we don't want to meddle with
5024 * anything.
5026 if (!defining && !(istk->conds && !emitting(istk->conds->state))
5027 && !(istk->mstk && !istk->mstk->in_progress)) {
5028 tline = expand_mmac_params(tline);
5032 * Check the line to see if it's a preprocessor directive.
5034 if (do_directive(tline) == DIRECTIVE_FOUND) {
5035 continue;
5036 } else if (defining) {
5038 * We're defining a multi-line macro. We emit nothing
5039 * at all, and just
5040 * shove the tokenized line on to the macro definition.
5042 Line *l = nasm_malloc(sizeof(Line));
5043 l->next = defining->expansion;
5044 l->first = tline;
5045 l->finishes = NULL;
5046 defining->expansion = l;
5047 continue;
5048 } else if (istk->conds && !emitting(istk->conds->state)) {
5050 * We're in a non-emitting branch of a condition block.
5051 * Emit nothing at all, not even a blank line: when we
5052 * emerge from the condition we'll give a line-number
5053 * directive so we keep our place correctly.
5055 free_tlist(tline);
5056 continue;
5057 } else if (istk->mstk && !istk->mstk->in_progress) {
5059 * We're in a %rep block which has been terminated, so
5060 * we're walking through to the %endrep without
5061 * emitting anything. Emit nothing at all, not even a
5062 * blank line: when we emerge from the %rep block we'll
5063 * give a line-number directive so we keep our place
5064 * correctly.
5066 free_tlist(tline);
5067 continue;
5068 } else {
5069 tline = expand_smacro(tline);
5070 if (!expand_mmacro(tline)) {
5072 * De-tokenize the line again, and emit it.
5074 line = detoken(tline, true);
5075 free_tlist(tline);
5076 break;
5077 } else {
5078 continue; /* expand_mmacro calls free_tlist */
5083 return line;
5086 static void pp_cleanup(int pass)
5088 if (defining) {
5089 if (defining->name) {
5090 error(ERR_NONFATAL,
5091 "end of file while still defining macro `%s'",
5092 defining->name);
5093 } else {
5094 error(ERR_NONFATAL, "end of file while still in %%rep");
5097 free_mmacro(defining);
5098 defining = NULL;
5100 while (cstk)
5101 ctx_pop();
5102 free_macros();
5103 while (istk) {
5104 Include *i = istk;
5105 istk = istk->next;
5106 fclose(i->fp);
5107 nasm_free(i->fname);
5108 nasm_free(i);
5110 while (cstk)
5111 ctx_pop();
5112 nasm_free(src_set_fname(NULL));
5113 if (pass == 0) {
5114 IncPath *i;
5115 free_llist(predef);
5116 delete_Blocks();
5117 while ((i = ipath)) {
5118 ipath = i->next;
5119 if (i->path)
5120 nasm_free(i->path);
5121 nasm_free(i);
5126 void pp_include_path(char *path)
5128 IncPath *i;
5130 i = nasm_malloc(sizeof(IncPath));
5131 i->path = path ? nasm_strdup(path) : NULL;
5132 i->next = NULL;
5134 if (ipath) {
5135 IncPath *j = ipath;
5136 while (j->next)
5137 j = j->next;
5138 j->next = i;
5139 } else {
5140 ipath = i;
5144 void pp_pre_include(char *fname)
5146 Token *inc, *space, *name;
5147 Line *l;
5149 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
5150 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
5151 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
5153 l = nasm_malloc(sizeof(Line));
5154 l->next = predef;
5155 l->first = inc;
5156 l->finishes = NULL;
5157 predef = l;
5160 void pp_pre_define(char *definition)
5162 Token *def, *space;
5163 Line *l;
5164 char *equals;
5166 equals = strchr(definition, '=');
5167 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
5168 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
5169 if (equals)
5170 *equals = ' ';
5171 space->next = tokenize(definition);
5172 if (equals)
5173 *equals = '=';
5175 l = nasm_malloc(sizeof(Line));
5176 l->next = predef;
5177 l->first = def;
5178 l->finishes = NULL;
5179 predef = l;
5182 void pp_pre_undefine(char *definition)
5184 Token *def, *space;
5185 Line *l;
5187 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
5188 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
5189 space->next = tokenize(definition);
5191 l = nasm_malloc(sizeof(Line));
5192 l->next = predef;
5193 l->first = def;
5194 l->finishes = NULL;
5195 predef = l;
5199 * Added by Keith Kanios:
5201 * This function is used to assist with "runtime" preprocessor
5202 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
5204 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5205 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5208 void pp_runtime(char *definition)
5210 Token *def;
5212 def = tokenize(definition);
5213 if (do_directive(def) == NO_DIRECTIVE_FOUND)
5214 free_tlist(def);
5218 void pp_extra_stdmac(macros_t *macros)
5220 extrastdmac = macros;
5223 static void make_tok_num(Token * tok, int64_t val)
5225 char numbuf[20];
5226 snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
5227 tok->text = nasm_strdup(numbuf);
5228 tok->type = TOK_NUMBER;
5231 Preproc nasmpp = {
5232 pp_reset,
5233 pp_getline,
5234 pp_cleanup