Merge branch 'master' into new-preproc
[nasm.git] / preproc.c
blob8c4b173ce0e587093280dab2875ef93d0538a27e
1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2011 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
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 ExpDef ExpDef;
86 typedef struct ExpInv ExpInv;
87 typedef struct Context Context;
88 typedef struct Token Token;
89 typedef struct Blocks Blocks;
90 typedef struct Line Line;
91 typedef struct Include Include;
92 typedef struct IncPath IncPath;
95 * Note on the storage of both SMacro and MMacros: the hash table
96 * indexes them case-insensitively, and we then have to go through a
97 * linked list of potential case aliases (and, for MMacros, parameter
98 * ranges); this is to preserve the matching semantics of the earlier
99 * code. If the number of case aliases for a specific macro is a
100 * performance issue, you may want to reconsider your coding style.
104 * Store the definition of a single-line macro.
106 struct SMacro {
107 SMacro *next;
108 char *name;
109 Token *expansion;
110 unsigned int nparam;
111 bool casesense;
112 bool in_progress;
116 * The context stack is composed of a linked list of these.
118 struct Context {
119 Context *next;
120 char *name;
121 struct hash_table localmac;
122 uint32_t number;
126 * This is the internal form which we break input lines up into.
127 * Typically stored in linked lists.
129 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
130 * necessarily used as-is, but is intended to denote the number of
131 * the substituted parameter. So in the definition
133 * %define a(x,y) ( (x) & ~(y) )
135 * the token representing `x' will have its type changed to
136 * TOK_SMAC_PARAM, but the one representing `y' will be
137 * TOK_SMAC_PARAM+1.
139 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
140 * which doesn't need quotes around it. Used in the pre-include
141 * mechanism as an alternative to trying to find a sensible type of
142 * quote to use on the filename we were passed.
144 enum pp_token_type {
145 TOK_NONE = 0,
146 TOK_WHITESPACE,
147 TOK_COMMENT,
148 TOK_ID,
149 TOK_PREPROC_ID,
150 TOK_STRING,
151 TOK_NUMBER,
152 TOK_FLOAT,
153 TOK_SMAC_END,
154 TOK_OTHER,
155 TOK_INTERNAL_STRING,
156 TOK_PREPROC_Q,
157 TOK_PREPROC_QQ,
158 TOK_PASTE, /* %+ */
159 TOK_INDIRECT, /* %[...] */
160 TOK_SMAC_PARAM, /* MUST BE LAST IN THE LIST!!! */
161 TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
164 #define PP_CONCAT_MASK(x) (1 << (x))
166 struct tokseq_match {
167 int mask_head;
168 int mask_tail;
171 struct Token {
172 Token *next;
173 char *text;
174 union {
175 SMacro *mac; /* associated macro for TOK_SMAC_END */
176 size_t len; /* scratch length field */
177 } a; /* Auxiliary data */
178 enum pp_token_type type;
182 * Expansion definitions are stored as a linked list of
183 * these, which is essentially a container to allow several linked
184 * lists of Tokens.
186 * Note that in this module, linked lists are treated as stacks
187 * wherever possible. For this reason, Lines are _pushed_ on to the
188 * `last' field in ExpDef structures, so that the linked list,
189 * if walked, would emit the expansion lines in the proper order.
191 struct Line {
192 Line *next;
193 Token *first;
197 * Expansion Types
199 enum pp_exp_type {
200 EXP_NONE = 0,
201 EXP_PREDEF,
202 EXP_MMACRO,
203 EXP_REP,
204 EXP_IF,
205 EXP_WHILE,
206 EXP_COMMENT,
207 EXP_FINAL,
208 EXP_MAX = INT_MAX /* Keep compiler from reducing the range */
212 * Store the definition of an expansion, in which is any
213 * preprocessor directive that has an ending pair.
215 * This design allows for arbitrary expansion/recursion depth,
216 * upto the DEADMAN_LIMIT.
218 * The `next' field is used for storing ExpDef in hash tables; the
219 * `prev' field is for the global `expansions` linked-list.
221 struct ExpDef {
222 ExpDef *prev; /* previous definition */
223 ExpDef *next; /* next in hash table */
224 enum pp_exp_type type; /* expansion type */
225 char *name; /* definition name */
226 int nparam_min;
227 int nparam_max;
228 bool casesense;
229 bool plus; /* is the last parameter greedy? */
230 bool nolist; /* is this expansion listing-inhibited? */
231 Token *dlist; /* all defaults as one list */
232 Token **defaults; /* parameter default pointers */
233 int ndefs; /* number of default parameters */
235 int prepend; /* label prepend state */
236 Line *label;
237 Line *line;
238 Line *last;
239 int linecount; /* number of lines within expansion */
241 int64_t def_depth; /* current number of definition pairs deep */
242 int64_t cur_depth; /* current number of expansions */
243 int64_t max_depth; /* maximum number of expansions allowed */
245 int state; /* condition state */
246 bool ignoring; /* ignoring definition lines */
250 * Store the invocation of an expansion.
252 * The `prev' field is for the `istk->expansion` linked-list.
254 * When an expansion is being expanded, `params', `iline', `nparam',
255 * `paramlen', `rotate' and `unique' are local to the invocation.
257 struct ExpInv {
258 ExpInv *prev; /* previous invocation */
259 ExpDef *def; /* pointer to expansion definition */
260 char *name; /* invocation name */
261 Line *label; /* pointer to label */
262 char *label_text; /* pointer to label text */
263 Line *current; /* pointer to current line in invocation */
265 Token **params; /* actual parameters */
266 Token *iline; /* invocation line */
267 int *paramlen;
268 unsigned int nparam;
269 unsigned int rotate;
271 uint64_t unique;
272 int lineno; /* current line number in expansion */
273 int linnum; /* line number at invocation */
274 int relno; /* relative line number at invocation */
275 enum pp_exp_type type; /* expansion type */
276 bool emitting;
280 * To handle an arbitrary level of file inclusion, we maintain a
281 * stack (ie linked list) of these things.
283 struct Include {
284 Include *next;
285 FILE *fp;
286 ExpInv *expansion;
287 char *fname;
288 int lineno;
289 int lineinc;
290 int mmac_depth;
294 * Include search path. This is simply a list of strings which get
295 * prepended, in turn, to the name of an include file, in an
296 * attempt to find the file if it's not in the current directory.
298 struct IncPath {
299 IncPath *next;
300 char *path;
304 * Conditional assembly: we maintain a separate stack of these for
305 * each level of file inclusion. (The only reason we keep the
306 * stacks separate is to ensure that a stray `%endif' in a file
307 * included from within the true branch of a `%if' won't terminate
308 * it and cause confusion: instead, rightly, it'll cause an error.)
310 enum {
312 * These states are for use just after %if or %elif: IF_TRUE
313 * means the condition has evaluated to truth so we are
314 * currently emitting, whereas IF_FALSE means we are not
315 * currently emitting but will start doing so if a %else comes
316 * up. In these states, all directives are admissible: %elif,
317 * %else and %endif. (And of course %if.)
319 COND_IF_TRUE,
320 COND_IF_FALSE,
322 * These states come up after a %else: ELSE_TRUE means we're
323 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
324 * any %elif or %else will cause an error.
326 COND_ELSE_TRUE,
327 COND_ELSE_FALSE,
329 * These states mean that we're not emitting now, and also that
330 * nothing until %endif will be emitted at all. COND_DONE is
331 * used when we've had our moment of emission
332 * and have now started seeing %elifs. COND_NEVER is used when
333 * the condition construct in question is contained within a
334 * non-emitting branch of a larger condition construct,
335 * or if there is an error.
337 COND_DONE,
338 COND_NEVER
342 * These defines are used as the possible return values for do_directive
344 #define NO_DIRECTIVE_FOUND 0
345 #define DIRECTIVE_FOUND 1
348 * This define sets the upper limit for smacro and expansions
350 #define DEADMAN_LIMIT (1 << 20)
352 /* max reps */
353 #define REP_LIMIT ((INT64_C(1) << 62))
356 * Condition codes. Note that we use c_ prefix not C_ because C_ is
357 * used in nasm.h for the "real" condition codes. At _this_ level,
358 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
359 * ones, so we need a different enum...
361 static const char * const conditions[] = {
362 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
363 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
364 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
366 enum pp_conds {
367 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
368 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
369 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
370 c_none = -1
372 static const enum pp_conds inverse_ccs[] = {
373 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
374 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,
375 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
378 /* For TASM compatibility we need to be able to recognise TASM compatible
379 * conditional compilation directives. Using the NASM pre-processor does
380 * not work, so we look for them specifically from the following list and
381 * then jam in the equivalent NASM directive into the input stream.
384 enum {
385 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
386 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
389 static const char * const tasm_directives[] = {
390 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
391 "ifndef", "include", "local"
394 static int StackSize = 4;
395 static char *StackPointer = "ebp";
396 static int ArgOffset = 8;
397 static int LocalOffset = 0;
399 static Context *cstk;
400 static Include *istk;
401 static IncPath *ipath;
403 static int pass; /* HACK: pass 0 = generate dependencies only */
404 static StrList **dephead, **deptail; /* Dependency list */
406 static uint64_t unique; /* unique identifier numbers */
408 static Line *predef;
409 static bool do_predef;
411 static ListGen *list;
414 * The current set of expansion definitions we have defined.
416 static struct hash_table expdefs;
419 * The current set of single-line macros we have defined.
421 static struct hash_table smacros;
424 * Linked List of all active expansion definitions
426 struct ExpDef *expansions;
429 * The expansion we are currently defining
431 static ExpDef *defining;
433 static uint64_t nested_mac_count;
434 static uint64_t nested_rep_count;
437 * Linked-list of lines to preprocess, prior to cleanup
439 static Line *finals;
440 static bool in_final = false;
443 * The number of macro parameters to allocate space for at a time.
445 #define PARAM_DELTA 16
448 * The standard macro set: defined in macros.c in the array nasm_stdmac.
449 * This gives our position in the macro set, when we're processing it.
451 static macros_t *stdmacpos;
454 * The extra standard macros that come from the object format, if
455 * any.
457 static macros_t *extrastdmac;
458 static bool any_extrastdmac;
461 * Tokens are allocated in blocks to improve speed
463 #define TOKEN_BLOCKSIZE 4096
464 static Token *freeTokens;
465 struct Blocks {
466 Blocks *next;
467 void *chunk;
470 static Blocks blocks;
473 * Forward declarations.
475 static Token *expand_mmac_params(Token * tline);
476 static Token *expand_smacro(Token * tline);
477 static Token *expand_id(Token * tline);
478 static Context *get_ctx(const char *name, const char **namep);
479 static void make_tok_num(Token * tok, int64_t val);
480 static void error(int severity, const char *fmt, ...);
481 static void error_precond(int severity, const char *fmt, ...);
482 static void *new_Block(size_t size);
483 static void delete_Blocks(void);
484 static Token *new_Token(Token * next, enum pp_token_type type,
485 const char *text, int txtlen);
486 static Token *copy_Token(Token * tline);
487 static Token *delete_Token(Token * t);
488 static Line *new_Line(void);
489 static ExpDef *new_ExpDef(int exp_type);
490 static ExpInv *new_ExpInv(int exp_type, ExpDef *ed);
493 * Macros for safe checking of token pointers, avoid *(NULL)
495 #define tok_type_(x,t) ((x) && (x)->type == (t))
496 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
497 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
498 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
501 * A few helpers for single macros
504 /* We might be not smacro parameter at all */
505 static bool is_smacro_param(Token *t)
507 return t->type >= TOK_SMAC_PARAM;
510 /* smacro parameters are counted in a special way */
511 static int smacro_get_param_idx(Token *t)
513 return t->type - TOK_SMAC_PARAM;
516 /* encode smacro parameter index */
517 static int smacro_set_param_idx(Token *t, unsigned int index)
519 return t->type = TOK_SMAC_PARAM + index;
522 #ifdef NASM_TRACE
524 #define stringify(x) #x
526 #define nasm_trace(msg, ...) printf("(%s:%d): " msg "\n", __func__, __LINE__, ##__VA_ARGS__)
527 #define nasm_dump_token(t) nasm_raw_dump_token(t, __FILE__, __LINE__, __func__);
528 #define nasm_dump_stream(t) nasm_raw_dump_stream(t, __FILE__, __LINE__, __func__);
530 /* FIXME: we really need some compound type here instead of inplace code */
531 static const char *nasm_get_tok_type_str(enum pp_token_type type)
533 #define SWITCH_TOK_NAME(type) \
534 case (type): \
535 return stringify(type)
537 switch (type) {
538 SWITCH_TOK_NAME(TOK_NONE);
539 SWITCH_TOK_NAME(TOK_WHITESPACE);
540 SWITCH_TOK_NAME(TOK_COMMENT);
541 SWITCH_TOK_NAME(TOK_ID);
542 SWITCH_TOK_NAME(TOK_PREPROC_ID);
543 SWITCH_TOK_NAME(TOK_STRING);
544 SWITCH_TOK_NAME(TOK_NUMBER);
545 SWITCH_TOK_NAME(TOK_FLOAT);
546 SWITCH_TOK_NAME(TOK_SMAC_END);
547 SWITCH_TOK_NAME(TOK_OTHER);
548 SWITCH_TOK_NAME(TOK_INTERNAL_STRING);
549 SWITCH_TOK_NAME(TOK_PREPROC_Q);
550 SWITCH_TOK_NAME(TOK_PREPROC_QQ);
551 SWITCH_TOK_NAME(TOK_PASTE);
552 SWITCH_TOK_NAME(TOK_INDIRECT);
553 SWITCH_TOK_NAME(TOK_SMAC_PARAM);
554 SWITCH_TOK_NAME(TOK_MAX);
557 return NULL;
560 static void nasm_raw_dump_token(Token *token, const char *file, int line, const char *func)
562 printf("---[%s (%s:%d): %p]---\n", func, file, line, (void *)token);
563 if (token) {
564 Token *t;
565 list_for_each(t, token) {
566 if (t->text)
567 printf("'%s'(%s) ", t->text,
568 nasm_get_tok_type_str(t->type));
570 printf("\n\n");
574 static void nasm_raw_dump_stream(Token *token, const char *file, int line, const char *func)
576 printf("---[%s (%s:%d): %p]---\n", func, file, line, (void *)token);
577 if (token) {
578 Token *t;
579 list_for_each(t, token)
580 printf("%s", t->text ? t->text : " ");
581 printf("\n\n");
585 #else
586 #define nasm_trace(msg, ...)
587 #define nasm_dump_token(t)
588 #define nasm_dump_stream(t)
589 #endif
592 * nasm_unquote with error if the string contains NUL characters.
593 * If the string contains NUL characters, issue an error and return
594 * the C len, i.e. truncate at the NUL.
596 static size_t nasm_unquote_cstr(char *qstr, enum preproc_token directive)
598 size_t len = nasm_unquote(qstr, NULL);
599 size_t clen = strlen(qstr);
601 if (len != clen)
602 error(ERR_NONFATAL, "NUL character in `%s' directive",
603 pp_directives[directive]);
605 return clen;
609 * In-place reverse a list of tokens.
611 static Token *reverse_tokens(Token *t)
613 Token *prev, *next;
615 list_reverse(t, prev, next);
617 return t;
621 * Handle TASM specific directives, which do not contain a % in
622 * front of them. We do it here because I could not find any other
623 * place to do it for the moment, and it is a hack (ideally it would
624 * be nice to be able to use the NASM pre-processor to do it).
626 static char *check_tasm_directive(char *line)
628 int32_t i, j, k, m, len;
629 char *p, *q, *oldline, oldchar;
631 p = nasm_skip_spaces(line);
633 /* Binary search for the directive name */
634 i = -1;
635 j = ARRAY_SIZE(tasm_directives);
636 q = nasm_skip_word(p);
637 len = q - p;
638 if (len) {
639 oldchar = p[len];
640 p[len] = 0;
641 while (j - i > 1) {
642 k = (j + i) / 2;
643 m = nasm_stricmp(p, tasm_directives[k]);
644 if (m == 0) {
645 /* We have found a directive, so jam a % in front of it
646 * so that NASM will then recognise it as one if it's own.
648 p[len] = oldchar;
649 len = strlen(p);
650 oldline = line;
651 line = nasm_malloc(len + 2);
652 line[0] = '%';
653 if (k == TM_IFDIFI) {
655 * NASM does not recognise IFDIFI, so we convert
656 * it to %if 0. This is not used in NASM
657 * compatible code, but does need to parse for the
658 * TASM macro package.
660 strcpy(line + 1, "if 0");
661 } else {
662 memcpy(line + 1, p, len + 1);
664 nasm_free(oldline);
665 return line;
666 } else if (m < 0) {
667 j = k;
668 } else
669 i = k;
671 p[len] = oldchar;
673 return line;
677 * The pre-preprocessing stage... This function translates line
678 * number indications as they emerge from GNU cpp (`# lineno "file"
679 * flags') into NASM preprocessor line number indications (`%line
680 * lineno file').
682 static char *prepreproc(char *line)
684 int lineno, fnlen;
685 char *fname, *oldline;
687 if (line[0] == '#' && line[1] == ' ') {
688 oldline = line;
689 fname = oldline + 2;
690 lineno = atoi(fname);
691 fname += strspn(fname, "0123456789 ");
692 if (*fname == '"')
693 fname++;
694 fnlen = strcspn(fname, "\"");
695 line = nasm_malloc(20 + fnlen);
696 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
697 nasm_free(oldline);
699 if (tasm_compatible_mode)
700 return check_tasm_directive(line);
701 return line;
705 * Free a linked list of tokens.
707 static void free_tlist(Token * list)
709 while (list)
710 list = delete_Token(list);
714 * Free a linked list of lines.
716 static void free_llist(Line * list)
718 Line *l, *tmp;
719 list_for_each_safe(l, tmp, list) {
720 free_tlist(l->first);
721 nasm_free(l);
726 * Free an ExpDef
728 static void free_expdef(ExpDef * ed)
730 nasm_free(ed->name);
731 free_tlist(ed->dlist);
732 nasm_free(ed->defaults);
733 free_llist(ed->line);
734 nasm_free(ed);
738 * Free an ExpInv
740 static void free_expinv(ExpInv * ei)
742 nasm_free(ei->name);
743 nasm_free(ei->label_text);
744 nasm_free(ei);
748 * Free all currently defined macros, and free the hash tables
750 static void free_smacro_table(struct hash_table *smt)
752 SMacro *s, *tmp;
753 const char *key;
754 struct hash_tbl_node *it = NULL;
756 while ((s = hash_iterate(smt, &it, &key)) != NULL) {
757 nasm_free((void *)key);
758 list_for_each_safe(s, tmp, s) {
759 nasm_free(s->name);
760 free_tlist(s->expansion);
761 nasm_free(s);
764 hash_free(smt);
767 static void free_expdef_table(struct hash_table *edt)
769 ExpDef *ed, *tmp;
770 const char *key;
771 struct hash_tbl_node *it = NULL;
773 it = NULL;
774 while ((ed = hash_iterate(edt, &it, &key)) != NULL) {
775 nasm_free((void *)key);
776 list_for_each_safe(ed ,tmp, ed)
777 free_expdef(ed);
779 hash_free(edt);
782 static void free_macros(void)
784 free_smacro_table(&smacros);
785 free_expdef_table(&expdefs);
789 * Initialize the hash tables
791 static void init_macros(void)
793 hash_init(&smacros, HASH_LARGE);
794 hash_init(&expdefs, HASH_LARGE);
798 * Pop the context stack.
800 static void ctx_pop(void)
802 Context *c = cstk;
804 cstk = cstk->next;
805 free_smacro_table(&c->localmac);
806 nasm_free(c->name);
807 nasm_free(c);
811 * Search for a key in the hash index; adding it if necessary
812 * (in which case we initialize the data pointer to NULL.)
814 static void **
815 hash_findi_add(struct hash_table *hash, const char *str)
817 struct hash_insert hi;
818 void **r;
819 char *strx;
821 r = hash_findi(hash, str, &hi);
822 if (r)
823 return r;
825 strx = nasm_strdup(str); /* Use a more efficient allocator here? */
826 return hash_add(&hi, strx, NULL);
830 * Like hash_findi, but returns the data element rather than a pointer
831 * to it. Used only when not adding a new element, hence no third
832 * argument.
834 static void *
835 hash_findix(struct hash_table *hash, const char *str)
837 void **p;
839 p = hash_findi(hash, str, NULL);
840 return p ? *p : NULL;
844 * read line from standard macros set,
845 * if there no more left -- return NULL
847 static char *line_from_stdmac(void)
849 unsigned char c;
850 const unsigned char *p = stdmacpos;
851 char *line, *q;
852 size_t len = 0;
854 if (!stdmacpos)
855 return NULL;
857 while ((c = *p++)) {
858 if (c >= 0x80)
859 len += pp_directives_len[c - 0x80] + 1;
860 else
861 len++;
864 line = nasm_malloc(len + 1);
865 q = line;
866 while ((c = *stdmacpos++)) {
867 if (c >= 0x80) {
868 memcpy(q, pp_directives[c - 0x80], pp_directives_len[c - 0x80]);
869 q += pp_directives_len[c - 0x80];
870 *q++ = ' ';
871 } else {
872 *q++ = c;
875 stdmacpos = p;
876 *q = '\0';
878 if (!*stdmacpos) {
879 /* This was the last of the standard macro chain... */
880 stdmacpos = NULL;
881 if (any_extrastdmac) {
882 stdmacpos = extrastdmac;
883 any_extrastdmac = false;
884 } else if (do_predef) {
885 ExpInv *ei;
886 Line *pd, *l;
887 Token *head, **tail, *t;
890 * Nasty hack: here we push the contents of
891 * `predef' on to the top-level expansion stack,
892 * since this is the most convenient way to
893 * implement the pre-include and pre-define
894 * features.
896 list_for_each(pd, predef) {
897 head = NULL;
898 tail = &head;
899 list_for_each(t, pd->first) {
900 *tail = new_Token(NULL, t->type, t->text, 0);
901 tail = &(*tail)->next;
904 l = new_Line();
905 l->first = head;
906 ei = new_ExpInv(EXP_PREDEF, NULL);
907 ei->current = l;
908 ei->emitting = true;
909 ei->prev = istk->expansion;
910 istk->expansion = ei;
912 do_predef = false;
916 return line;
919 #define BUF_DELTA 512
921 * Read a line from the top file in istk, handling multiple CR/LFs
922 * at the end of the line read, and handling spurious ^Zs. Will
923 * return lines from the standard macro set if this has not already
924 * been done.
926 static char *read_line(void)
928 char *buffer, *p, *q;
929 int bufsize, continued_count;
932 * standart macros set (predefined) goes first
934 p = line_from_stdmac();
935 if (p)
936 return p;
939 * regular read from a file
941 bufsize = BUF_DELTA;
942 buffer = nasm_malloc(BUF_DELTA);
943 p = buffer;
944 continued_count = 0;
945 while (1) {
946 q = fgets(p, bufsize - (p - buffer), istk->fp);
947 if (!q)
948 break;
949 p += strlen(p);
950 if (p > buffer && p[-1] == '\n') {
952 * Convert backslash-CRLF line continuation sequences into
953 * nothing at all (for DOS and Windows)
955 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
956 p -= 3;
957 *p = 0;
958 continued_count++;
961 * Also convert backslash-LF line continuation sequences into
962 * nothing at all (for Unix)
964 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
965 p -= 2;
966 *p = 0;
967 continued_count++;
968 } else {
969 break;
972 if (p - buffer > bufsize - 10) {
973 int32_t offset = p - buffer;
974 bufsize += BUF_DELTA;
975 buffer = nasm_realloc(buffer, bufsize);
976 p = buffer + offset; /* prevent stale-pointer problems */
980 if (!q && p == buffer) {
981 nasm_free(buffer);
982 return NULL;
985 src_set_linnum(src_get_linnum() + istk->lineinc +
986 (continued_count * istk->lineinc));
989 * Play safe: remove CRs as well as LFs, if any of either are
990 * present at the end of the line.
992 while (--p >= buffer && (*p == '\n' || *p == '\r'))
993 *p = '\0';
996 * Handle spurious ^Z, which may be inserted into source files
997 * by some file transfer utilities.
999 buffer[strcspn(buffer, "\032")] = '\0';
1001 list->line(LIST_READ, buffer);
1003 return buffer;
1007 * Tokenize a line of text. This is a very simple process since we
1008 * don't need to parse the value out of e.g. numeric tokens: we
1009 * simply split one string into many.
1011 static Token *tokenize(char *line)
1013 char c, *p = line;
1014 enum pp_token_type type;
1015 Token *list = NULL;
1016 Token *t, **tail = &list;
1017 bool verbose = true;
1019 nasm_trace("Tokenize for '%s'", line);
1021 if ((defining != NULL) && (defining->ignoring == true)) {
1022 verbose = false;
1025 while (*line) {
1026 p = line;
1027 if (*p == '%') {
1028 p++;
1029 if (*p == '+' && !nasm_isdigit(p[1])) {
1030 p++;
1031 type = TOK_PASTE;
1032 } else if (nasm_isdigit(*p) ||
1033 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
1034 do {
1035 p++;
1037 while (nasm_isdigit(*p));
1038 type = TOK_PREPROC_ID;
1039 } else if (*p == '{') {
1040 p++;
1041 while (*p && *p != '}') {
1042 p[-1] = *p;
1043 p++;
1045 p[-1] = '\0';
1046 if (*p)
1047 p++;
1048 type = TOK_PREPROC_ID;
1049 } else if (*p == '[') {
1050 int lvl = 1;
1051 line += 2; /* Skip the leading %[ */
1052 p++;
1053 while (lvl && (c = *p++)) {
1054 switch (c) {
1055 case ']':
1056 lvl--;
1057 break;
1058 case '%':
1059 if (*p == '[')
1060 lvl++;
1061 break;
1062 case '\'':
1063 case '\"':
1064 case '`':
1065 p = nasm_skip_string(p - 1) + 1;
1066 break;
1067 default:
1068 break;
1071 p--;
1072 if (*p)
1073 *p++ = '\0';
1074 if (lvl && verbose)
1075 error(ERR_NONFATAL, "unterminated %[ construct");
1076 type = TOK_INDIRECT;
1077 } else if (*p == '?') {
1078 type = TOK_PREPROC_Q; /* %? */
1079 p++;
1080 if (*p == '?') {
1081 type = TOK_PREPROC_QQ; /* %?? */
1082 p++;
1084 } else if (*p == '!') {
1085 type = TOK_PREPROC_ID;
1086 p++;
1087 if (isidchar(*p)) {
1088 do {
1089 p++;
1090 } while (isidchar(*p));
1091 } else if (*p == '\'' || *p == '\"' || *p == '`') {
1092 p = nasm_skip_string(p);
1093 if (*p)
1094 p++;
1095 else if(verbose)
1096 error(ERR_NONFATAL|ERR_PASS1, "unterminated %! string");
1097 } else {
1098 /* %! without string or identifier */
1099 type = TOK_OTHER; /* Legacy behavior... */
1101 } else if (isidchar(*p) ||
1102 ((*p == '!' || *p == '%' || *p == '$') &&
1103 isidchar(p[1]))) {
1104 do {
1105 p++;
1107 while (isidchar(*p));
1108 type = TOK_PREPROC_ID;
1109 } else {
1110 type = TOK_OTHER;
1111 if (*p == '%')
1112 p++;
1114 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
1115 type = TOK_ID;
1116 p++;
1117 while (*p && isidchar(*p))
1118 p++;
1119 } else if (*p == '\'' || *p == '"' || *p == '`') {
1121 * A string token.
1123 type = TOK_STRING;
1124 p = nasm_skip_string(p);
1126 if (*p) {
1127 p++;
1128 } else if(verbose) {
1129 error(ERR_WARNING|ERR_PASS1, "unterminated string");
1130 /* Handling unterminated strings by UNV */
1131 /* type = -1; */
1133 } else if (p[0] == '$' && p[1] == '$') {
1134 type = TOK_OTHER; /* TOKEN_BASE */
1135 p += 2;
1136 } else if (isnumstart(*p)) {
1137 bool is_hex = false;
1138 bool is_float = false;
1139 bool has_e = false;
1140 char c, *r;
1143 * A numeric token.
1146 if (*p == '$') {
1147 p++;
1148 is_hex = true;
1151 for (;;) {
1152 c = *p++;
1154 if (!is_hex && (c == 'e' || c == 'E')) {
1155 has_e = true;
1156 if (*p == '+' || *p == '-') {
1158 * e can only be followed by +/- if it is either a
1159 * prefixed hex number or a floating-point number
1161 p++;
1162 is_float = true;
1164 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
1165 is_hex = true;
1166 } else if (c == 'P' || c == 'p') {
1167 is_float = true;
1168 if (*p == '+' || *p == '-')
1169 p++;
1170 } else if (isnumchar(c) || c == '_')
1171 ; /* just advance */
1172 else if (c == '.') {
1174 * we need to deal with consequences of the legacy
1175 * parser, like "1.nolist" being two tokens
1176 * (TOK_NUMBER, TOK_ID) here; at least give it
1177 * a shot for now. In the future, we probably need
1178 * a flex-based scanner with proper pattern matching
1179 * to do it as well as it can be done. Nothing in
1180 * the world is going to help the person who wants
1181 * 0x123.p16 interpreted as two tokens, though.
1183 r = p;
1184 while (*r == '_')
1185 r++;
1187 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
1188 (!is_hex && (*r == 'e' || *r == 'E')) ||
1189 (*r == 'p' || *r == 'P')) {
1190 p = r;
1191 is_float = true;
1192 } else
1193 break; /* Terminate the token */
1194 } else
1195 break;
1197 p--; /* Point to first character beyond number */
1199 if (p == line+1 && *line == '$') {
1200 type = TOK_OTHER; /* TOKEN_HERE */
1201 } else {
1202 if (has_e && !is_hex) {
1203 /* 1e13 is floating-point, but 1e13h is not */
1204 is_float = true;
1207 type = is_float ? TOK_FLOAT : TOK_NUMBER;
1209 } else if (nasm_isspace(*p)) {
1210 type = TOK_WHITESPACE;
1211 p = nasm_skip_spaces(p);
1213 * Whitespace just before end-of-line is discarded by
1214 * pretending it's a comment; whitespace just before a
1215 * comment gets lumped into the comment.
1217 if (!*p || *p == ';') {
1218 type = TOK_COMMENT;
1219 while (*p)
1220 p++;
1222 } else if (*p == ';') {
1223 type = TOK_COMMENT;
1224 while (*p)
1225 p++;
1226 } else {
1228 * Anything else is an operator of some kind. We check
1229 * for all the double-character operators (>>, <<, //,
1230 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1231 * else is a single-character operator.
1233 type = TOK_OTHER;
1234 if ((p[0] == '>' && p[1] == '>') ||
1235 (p[0] == '<' && p[1] == '<') ||
1236 (p[0] == '/' && p[1] == '/') ||
1237 (p[0] == '<' && p[1] == '=') ||
1238 (p[0] == '>' && p[1] == '=') ||
1239 (p[0] == '=' && p[1] == '=') ||
1240 (p[0] == '!' && p[1] == '=') ||
1241 (p[0] == '<' && p[1] == '>') ||
1242 (p[0] == '&' && p[1] == '&') ||
1243 (p[0] == '|' && p[1] == '|') ||
1244 (p[0] == '^' && p[1] == '^')) {
1245 p++;
1247 p++;
1250 /* Handling unterminated string by UNV */
1251 /*if (type == -1)
1253 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1254 t->text[p-line] = *line;
1255 tail = &t->next;
1257 else */
1258 if (type != TOK_COMMENT) {
1259 *tail = t = new_Token(NULL, type, line, p - line);
1260 tail = &t->next;
1262 line = p;
1265 nasm_dump_token(list);
1267 return list;
1271 * this function allocates a new managed block of memory and
1272 * returns a pointer to the block. The managed blocks are
1273 * deleted only all at once by the delete_Blocks function.
1275 static void *new_Block(size_t size)
1277 Blocks *b = &blocks;
1279 /* first, get to the end of the linked list */
1280 while (b->next)
1281 b = b->next;
1283 /* now allocate the requested chunk */
1284 b->chunk = nasm_malloc(size);
1286 /* now allocate a new block for the next request */
1287 b->next = nasm_zalloc(sizeof(Blocks));
1289 return b->chunk;
1293 * this function deletes all managed blocks of memory
1295 static void delete_Blocks(void)
1297 Blocks *a, *b = &blocks;
1300 * keep in mind that the first block, pointed to by blocks
1301 * is a static and not dynamically allocated, so we don't
1302 * free it.
1304 while (b) {
1305 nasm_free(b->chunk);
1306 a = b;
1307 b = b->next;
1308 if (a != &blocks)
1309 nasm_free(a);
1314 * this function creates a new Token and passes a pointer to it
1315 * back to the caller. It sets the type and text elements, and
1316 * also the a.mac and next elements to NULL.
1318 static Token *new_Token(Token * next, enum pp_token_type type,
1319 const char *text, int txtlen)
1321 Token *t;
1322 int i;
1324 if (!freeTokens) {
1325 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
1326 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
1327 freeTokens[i].next = &freeTokens[i + 1];
1328 freeTokens[i].next = NULL;
1330 t = freeTokens;
1331 freeTokens = t->next;
1332 t->next = next;
1333 t->a.mac = NULL;
1334 t->type = type;
1335 if (type == TOK_WHITESPACE || !text) {
1336 t->text = NULL;
1337 } else {
1338 if (txtlen == 0)
1339 txtlen = strlen(text);
1340 t->text = nasm_malloc(txtlen+1);
1341 memcpy(t->text, text, txtlen);
1342 t->text[txtlen] = '\0';
1344 return t;
1347 static Token *copy_Token(Token * tline)
1349 Token *t, *tt, *first = NULL, *prev = NULL;
1350 int i;
1351 for (tt = tline; tt != NULL; tt = tt->next) {
1352 if (!freeTokens) {
1353 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
1354 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
1355 freeTokens[i].next = &freeTokens[i + 1];
1356 freeTokens[i].next = NULL;
1358 t = freeTokens;
1359 freeTokens = t->next;
1360 t->next = NULL;
1361 t->text = tt->text ? nasm_strdup(tt->text) : NULL;
1362 t->a.mac = tt->a.mac;
1363 t->a.len = tt->a.len;
1364 t->type = tt->type;
1365 if (prev != NULL) {
1366 prev->next = t;
1367 } else {
1368 first = t;
1370 prev = t;
1372 return first;
1375 static Token *delete_Token(Token * t)
1377 Token *next = t->next;
1378 nasm_free(t->text);
1379 t->next = freeTokens;
1380 freeTokens = t;
1381 return next;
1385 * Convert a line of tokens back into text.
1386 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1387 * will be transformed into ..@ctxnum.xxx
1389 static char *detoken(Token * tlist, bool expand_locals)
1391 Token *t;
1392 char *line, *p;
1393 const char *q;
1394 int len = 0;
1396 list_for_each(t, tlist) {
1397 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
1398 char *v;
1399 char *q = t->text;
1401 v = t->text + 2;
1402 if (*v == '\'' || *v == '\"' || *v == '`') {
1403 size_t len = nasm_unquote(v, NULL);
1404 size_t clen = strlen(v);
1406 if (len != clen) {
1407 error(ERR_NONFATAL | ERR_PASS1,
1408 "NUL character in %! string");
1409 v = NULL;
1413 if (v) {
1414 char *p = getenv(v);
1415 if (!p) {
1416 error(ERR_NONFATAL | ERR_PASS1,
1417 "nonexistent environment variable `%s'", v);
1418 p = "";
1420 t->text = nasm_strdup(p);
1422 nasm_free(q);
1425 /* Expand local macros here and not during preprocessing */
1426 if (expand_locals &&
1427 t->type == TOK_PREPROC_ID && t->text &&
1428 t->text[0] == '%' && t->text[1] == '$') {
1429 const char *q;
1430 char *p;
1431 Context *ctx = get_ctx(t->text, &q);
1432 if (ctx) {
1433 char buffer[40];
1434 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
1435 p = nasm_strcat(buffer, q);
1436 nasm_free(t->text);
1437 t->text = p;
1441 /* Expand %? and %?? directives */
1442 if ((istk->expansion != NULL) &&
1443 ((t->type == TOK_PREPROC_Q) ||
1444 (t->type == TOK_PREPROC_QQ))) {
1445 ExpInv *ei;
1446 for (ei = istk->expansion; ei != NULL; ei = ei->prev){
1447 if (ei->type == EXP_MMACRO) {
1448 nasm_free(t->text);
1449 if (t->type == TOK_PREPROC_Q) {
1450 t->text = nasm_strdup(ei->name);
1451 } else {
1452 t->text = nasm_strdup(ei->def->name);
1454 break;
1459 if (t->type == TOK_WHITESPACE)
1460 len++;
1461 else if (t->text)
1462 len += strlen(t->text);
1465 p = line = nasm_malloc(len + 1);
1467 list_for_each(t, tlist) {
1468 if (t->type == TOK_WHITESPACE) {
1469 *p++ = ' ';
1470 } else if (t->text) {
1471 q = t->text;
1472 while (*q)
1473 *p++ = *q++;
1476 *p = '\0';
1478 return line;
1482 * Initialize a new Line
1484 static inline Line *new_Line(void)
1486 return (Line *)nasm_zalloc(sizeof(Line));
1491 * Initialize a new Expansion Definition
1493 static ExpDef *new_ExpDef(int exp_type)
1495 ExpDef *ed = (ExpDef*)nasm_zalloc(sizeof(ExpDef));
1496 ed->type = exp_type;
1497 ed->casesense = true;
1498 ed->state = COND_NEVER;
1500 return ed;
1505 * Initialize a new Expansion Instance
1507 static ExpInv *new_ExpInv(int exp_type, ExpDef *ed)
1509 ExpInv *ei = (ExpInv*)nasm_zalloc(sizeof(ExpInv));
1510 ei->type = exp_type;
1511 ei->def = ed;
1512 ei->unique = ++unique;
1514 if ((istk->mmac_depth < 1) &&
1515 (istk->expansion == NULL) &&
1516 (ed != NULL) &&
1517 (ed->type != EXP_MMACRO) &&
1518 (ed->type != EXP_REP) &&
1519 (ed->type != EXP_WHILE)) {
1520 ei->linnum = src_get_linnum();
1521 src_set_linnum(ei->linnum - ed->linecount - 1);
1522 } else {
1523 ei->linnum = -1;
1525 if ((istk->expansion == NULL) ||
1526 (ei->type == EXP_MMACRO)) {
1527 ei->relno = 0;
1528 } else {
1529 ei->relno = istk->expansion->lineno;
1530 if (ed != NULL) {
1531 ei->relno -= (ed->linecount + 1);
1534 return ei;
1538 * A scanner, suitable for use by the expression evaluator, which
1539 * operates on a line of Tokens. Expects a pointer to a pointer to
1540 * the first token in the line to be passed in as its private_data
1541 * field.
1543 * FIX: This really needs to be unified with stdscan.
1545 static int ppscan(void *private_data, struct tokenval *tokval)
1547 Token **tlineptr = private_data;
1548 Token *tline;
1549 char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
1551 do {
1552 tline = *tlineptr;
1553 *tlineptr = tline ? tline->next : NULL;
1554 } while (tline && (tline->type == TOK_WHITESPACE ||
1555 tline->type == TOK_COMMENT));
1557 if (!tline)
1558 return tokval->t_type = TOKEN_EOS;
1560 tokval->t_charptr = tline->text;
1562 if (tline->text[0] == '$' && !tline->text[1])
1563 return tokval->t_type = TOKEN_HERE;
1564 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
1565 return tokval->t_type = TOKEN_BASE;
1567 if (tline->type == TOK_ID) {
1568 p = tokval->t_charptr = tline->text;
1569 if (p[0] == '$') {
1570 tokval->t_charptr++;
1571 return tokval->t_type = TOKEN_ID;
1574 for (r = p, s = ourcopy; *r; r++) {
1575 if (r >= p+MAX_KEYWORD)
1576 return tokval->t_type = TOKEN_ID; /* Not a keyword */
1577 *s++ = nasm_tolower(*r);
1579 *s = '\0';
1580 /* right, so we have an identifier sitting in temp storage. now,
1581 * is it actually a register or instruction name, or what? */
1582 return nasm_token_hash(ourcopy, tokval);
1585 if (tline->type == TOK_NUMBER) {
1586 bool rn_error;
1587 tokval->t_integer = readnum(tline->text, &rn_error);
1588 tokval->t_charptr = tline->text;
1589 if (rn_error)
1590 return tokval->t_type = TOKEN_ERRNUM;
1591 else
1592 return tokval->t_type = TOKEN_NUM;
1595 if (tline->type == TOK_FLOAT) {
1596 return tokval->t_type = TOKEN_FLOAT;
1599 if (tline->type == TOK_STRING) {
1600 char bq, *ep;
1602 bq = tline->text[0];
1603 tokval->t_charptr = tline->text;
1604 tokval->t_inttwo = nasm_unquote(tline->text, &ep);
1606 if (ep[0] != bq || ep[1] != '\0')
1607 return tokval->t_type = TOKEN_ERRSTR;
1608 else
1609 return tokval->t_type = TOKEN_STR;
1612 if (tline->type == TOK_OTHER) {
1613 if (!strcmp(tline->text, "<<"))
1614 return tokval->t_type = TOKEN_SHL;
1615 if (!strcmp(tline->text, ">>"))
1616 return tokval->t_type = TOKEN_SHR;
1617 if (!strcmp(tline->text, "//"))
1618 return tokval->t_type = TOKEN_SDIV;
1619 if (!strcmp(tline->text, "%%"))
1620 return tokval->t_type = TOKEN_SMOD;
1621 if (!strcmp(tline->text, "=="))
1622 return tokval->t_type = TOKEN_EQ;
1623 if (!strcmp(tline->text, "<>"))
1624 return tokval->t_type = TOKEN_NE;
1625 if (!strcmp(tline->text, "!="))
1626 return tokval->t_type = TOKEN_NE;
1627 if (!strcmp(tline->text, "<="))
1628 return tokval->t_type = TOKEN_LE;
1629 if (!strcmp(tline->text, ">="))
1630 return tokval->t_type = TOKEN_GE;
1631 if (!strcmp(tline->text, "&&"))
1632 return tokval->t_type = TOKEN_DBL_AND;
1633 if (!strcmp(tline->text, "^^"))
1634 return tokval->t_type = TOKEN_DBL_XOR;
1635 if (!strcmp(tline->text, "||"))
1636 return tokval->t_type = TOKEN_DBL_OR;
1640 * We have no other options: just return the first character of
1641 * the token text.
1643 return tokval->t_type = tline->text[0];
1647 * Compare a string to the name of an existing macro; this is a
1648 * simple wrapper which calls either strcmp or nasm_stricmp
1649 * depending on the value of the `casesense' parameter.
1651 static int mstrcmp(const char *p, const char *q, bool casesense)
1653 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
1657 * Compare a string to the name of an existing macro; this is a
1658 * simple wrapper which calls either strcmp or nasm_stricmp
1659 * depending on the value of the `casesense' parameter.
1661 static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
1663 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
1667 * Return the Context structure associated with a %$ token. Return
1668 * NULL, having _already_ reported an error condition, if the
1669 * context stack isn't deep enough for the supplied number of $
1670 * signs.
1672 * If "namep" is non-NULL, set it to the pointer to the macro name
1673 * tail, i.e. the part beyond %$...
1675 static Context *get_ctx(const char *name, const char **namep)
1677 Context *ctx;
1678 int i;
1680 if (namep)
1681 *namep = name;
1683 if (!name || name[0] != '%' || name[1] != '$')
1684 return NULL;
1686 if (!cstk) {
1687 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1688 return NULL;
1691 name += 2;
1692 ctx = cstk;
1693 i = 0;
1694 while (ctx && *name == '$') {
1695 name++;
1696 i++;
1697 ctx = ctx->next;
1700 if (!ctx) {
1701 error(ERR_NONFATAL, "`%s': context stack is only"
1702 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
1703 return NULL;
1706 if (namep)
1707 *namep = name;
1709 return ctx;
1713 * Check to see if a file is already in a string list
1715 static bool in_list(const StrList *list, const char *str)
1717 while (list) {
1718 if (!strcmp(list->str, str))
1719 return true;
1720 list = list->next;
1722 return false;
1726 * Open an include file. This routine must always return a valid
1727 * file pointer if it returns - it's responsible for throwing an
1728 * ERR_FATAL and bombing out completely if not. It should also try
1729 * the include path one by one until it finds the file or reaches
1730 * the end of the path.
1732 static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
1733 bool missing_ok)
1735 FILE *fp;
1736 char *prefix = "";
1737 IncPath *ip = ipath;
1738 int len = strlen(file);
1739 size_t prefix_len = 0;
1740 StrList *sl;
1742 while (1) {
1743 sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
1744 sl->next = NULL;
1745 memcpy(sl->str, prefix, prefix_len);
1746 memcpy(sl->str+prefix_len, file, len+1);
1747 fp = fopen(sl->str, "r");
1748 if (fp && dhead && !in_list(*dhead, sl->str)) {
1749 **dtail = sl;
1750 *dtail = &sl->next;
1751 } else {
1752 nasm_free(sl);
1754 if (fp)
1755 return fp;
1756 if (!ip) {
1757 if (!missing_ok)
1758 break;
1759 prefix = NULL;
1760 } else {
1761 prefix = ip->path;
1762 ip = ip->next;
1764 if (prefix) {
1765 prefix_len = strlen(prefix);
1766 } else {
1767 /* -MG given and file not found */
1768 if (dhead && !in_list(*dhead, file)) {
1769 sl = nasm_malloc(len+1+sizeof sl->next);
1770 sl->next = NULL;
1771 strcpy(sl->str, file);
1772 **dtail = sl;
1773 *dtail = &sl->next;
1775 return NULL;
1779 error(ERR_FATAL, "unable to open include file `%s'", file);
1780 return NULL;
1784 * Determine if we should warn on defining a single-line macro of
1785 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1786 * return true if _any_ single-line macro of that name is defined.
1787 * Otherwise, will return true if a single-line macro with either
1788 * `nparam' or no parameters is defined.
1790 * If a macro with precisely the right number of parameters is
1791 * defined, or nparam is -1, the address of the definition structure
1792 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1793 * is NULL, no action will be taken regarding its contents, and no
1794 * error will occur.
1796 * Note that this is also called with nparam zero to resolve
1797 * `ifdef'.
1799 * If you already know which context macro belongs to, you can pass
1800 * the context pointer as first parameter; if you won't but name begins
1801 * with %$ the context will be automatically computed. If all_contexts
1802 * is true, macro will be searched in outer contexts as well.
1804 static bool
1805 smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
1806 bool nocase)
1808 struct hash_table *smtbl;
1809 SMacro *m;
1811 if (ctx) {
1812 smtbl = &ctx->localmac;
1813 } else if (name[0] == '%' && name[1] == '$') {
1814 if (cstk)
1815 ctx = get_ctx(name, &name);
1816 if (!ctx)
1817 return false; /* got to return _something_ */
1818 smtbl = &ctx->localmac;
1819 } else {
1820 smtbl = &smacros;
1822 m = (SMacro *) hash_findix(smtbl, name);
1824 while (m) {
1825 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
1826 (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
1827 if (defn) {
1828 if (nparam == (int) m->nparam || nparam == -1)
1829 *defn = m;
1830 else
1831 *defn = NULL;
1833 return true;
1835 m = m->next;
1838 return false;
1842 * Count and mark off the parameters in a multi-line macro call.
1843 * This is called both from within the multi-line macro expansion
1844 * code, and also to mark off the default parameters when provided
1845 * in a %macro definition line.
1847 static void count_mmac_params(Token * t, int *nparam, Token *** params)
1849 int paramsize, brace;
1851 *nparam = paramsize = 0;
1852 *params = NULL;
1853 while (t) {
1854 /* +1: we need space for the final NULL */
1855 if (*nparam+1 >= paramsize) {
1856 paramsize += PARAM_DELTA;
1857 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1859 skip_white_(t);
1860 brace = false;
1861 if (tok_is_(t, "{"))
1862 brace = true;
1863 (*params)[(*nparam)++] = t;
1864 while (tok_isnt_(t, brace ? "}" : ","))
1865 t = t->next;
1866 if (t) { /* got a comma/brace */
1867 t = t->next;
1868 if (brace) {
1870 * Now we've found the closing brace, look further
1871 * for the comma.
1873 skip_white_(t);
1874 if (tok_isnt_(t, ",")) {
1875 error(ERR_NONFATAL,
1876 "braces do not enclose all of macro parameter");
1877 while (tok_isnt_(t, ","))
1878 t = t->next;
1880 if (t)
1881 t = t->next; /* eat the comma */
1888 * Determine whether one of the various `if' conditions is true or
1889 * not.
1891 * We must free the tline we get passed.
1893 static bool if_condition(Token * tline, enum preproc_token ct)
1895 enum pp_conditional i = PP_COND(ct);
1896 bool j;
1897 Token *t, *tt, **tptr, *origline;
1898 struct tokenval tokval;
1899 expr *evalresult;
1900 enum pp_token_type needtype;
1901 char *p;
1903 origline = tline;
1905 switch (i) {
1906 case PPC_IFCTX:
1907 j = false; /* have we matched yet? */
1908 while (true) {
1909 skip_white_(tline);
1910 if (!tline)
1911 break;
1912 if (tline->type != TOK_ID) {
1913 error(ERR_NONFATAL,
1914 "`%s' expects context identifiers", pp_directives[ct]);
1915 free_tlist(origline);
1916 return -1;
1918 if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name))
1919 j = true;
1920 tline = tline->next;
1922 break;
1924 case PPC_IFDEF:
1925 j = false; /* have we matched yet? */
1926 skip_white_(tline);
1927 do {
1928 if (!tline || (tline->type != TOK_ID &&
1929 (tline->type != TOK_PREPROC_ID ||
1930 tline->text[1] != '$'))) {
1931 error(ERR_NONFATAL,
1932 "`%s' expects macro identifiers", pp_directives[ct]);
1933 goto fail;
1935 if (smacro_defined(NULL, tline->text, 0, NULL, true))
1936 j = true;
1937 tline = tline->next;
1938 skip_white_(tline);
1939 } while (tline);
1940 break;
1942 case PPC_IFENV:
1943 tline = expand_smacro(tline);
1944 j = false; /* have we matched yet? */
1945 skip_white_(tline);
1946 do {
1947 if (!tline || (tline->type != TOK_ID &&
1948 tline->type != TOK_STRING &&
1949 (tline->type != TOK_PREPROC_ID ||
1950 tline->text[1] != '!'))) {
1951 error(ERR_NONFATAL,
1952 "`%s' expects environment variable names",
1953 pp_directives[ct]);
1954 goto fail;
1956 p = tline->text;
1957 if (tline->type == TOK_PREPROC_ID)
1958 p += 2; /* Skip leading %! */
1959 if (*p == '\'' || *p == '\"' || *p == '`')
1960 nasm_unquote_cstr(p, ct);
1961 if (getenv(p))
1962 j = true;
1963 tline = tline->next;
1964 skip_white_(tline);
1965 } while (tline);
1966 break;
1968 case PPC_IFIDN:
1969 case PPC_IFIDNI:
1970 tline = expand_smacro(tline);
1971 t = tt = tline;
1972 while (tok_isnt_(tt, ","))
1973 tt = tt->next;
1974 if (!tt) {
1975 error(ERR_NONFATAL,
1976 "`%s' expects two comma-separated arguments",
1977 pp_directives[ct]);
1978 goto fail;
1980 tt = tt->next;
1981 j = true; /* assume equality unless proved not */
1982 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1983 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1984 error(ERR_NONFATAL, "`%s': more than one comma on line",
1985 pp_directives[ct]);
1986 goto fail;
1988 if (t->type == TOK_WHITESPACE) {
1989 t = t->next;
1990 continue;
1992 if (tt->type == TOK_WHITESPACE) {
1993 tt = tt->next;
1994 continue;
1996 if (tt->type != t->type) {
1997 j = false; /* found mismatching tokens */
1998 break;
2000 /* When comparing strings, need to unquote them first */
2001 if (t->type == TOK_STRING) {
2002 size_t l1 = nasm_unquote(t->text, NULL);
2003 size_t l2 = nasm_unquote(tt->text, NULL);
2005 if (l1 != l2) {
2006 j = false;
2007 break;
2009 if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
2010 j = false;
2011 break;
2013 } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
2014 j = false; /* found mismatching tokens */
2015 break;
2018 t = t->next;
2019 tt = tt->next;
2021 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
2022 j = false; /* trailing gunk on one end or other */
2023 break;
2025 case PPC_IFMACRO:
2027 bool found = false;
2028 ExpDef searching, *ed;
2030 skip_white_(tline);
2031 tline = expand_id(tline);
2032 if (!tok_type_(tline, TOK_ID)) {
2033 error(ERR_NONFATAL,
2034 "`%s' expects a macro name", pp_directives[ct]);
2035 goto fail;
2037 memset(&searching, 0, sizeof(searching));
2038 searching.name = nasm_strdup(tline->text);
2039 searching.casesense = true;
2040 searching.nparam_max = INT_MAX;
2041 tline = expand_smacro(tline->next);
2042 skip_white_(tline);
2043 if (!tline) {
2044 } else if (!tok_type_(tline, TOK_NUMBER)) {
2045 error(ERR_NONFATAL,
2046 "`%s' expects a parameter count or nothing",
2047 pp_directives[ct]);
2048 } else {
2049 searching.nparam_min = searching.nparam_max =
2050 readnum(tline->text, &j);
2051 if (j)
2052 error(ERR_NONFATAL,
2053 "unable to parse parameter count `%s'",
2054 tline->text);
2056 if (tline && tok_is_(tline->next, "-")) {
2057 tline = tline->next->next;
2058 if (tok_is_(tline, "*"))
2059 searching.nparam_max = INT_MAX;
2060 else if (!tok_type_(tline, TOK_NUMBER))
2061 error(ERR_NONFATAL,
2062 "`%s' expects a parameter count after `-'",
2063 pp_directives[ct]);
2064 else {
2065 searching.nparam_max = readnum(tline->text, &j);
2066 if (j)
2067 error(ERR_NONFATAL,
2068 "unable to parse parameter count `%s'",
2069 tline->text);
2070 if (searching.nparam_min > searching.nparam_max)
2071 error(ERR_NONFATAL,
2072 "minimum parameter count exceeds maximum");
2075 if (tline && tok_is_(tline->next, "+")) {
2076 tline = tline->next;
2077 searching.plus = true;
2079 ed = (ExpDef *) hash_findix(&expdefs, searching.name);
2080 while (ed != NULL) {
2081 if (!strcmp(ed->name, searching.name) &&
2082 (ed->nparam_min <= searching.nparam_max || searching.plus) &&
2083 (searching.nparam_min <= ed->nparam_max || ed->plus)) {
2084 found = true;
2085 break;
2087 ed = ed->next;
2089 if (tline && tline->next)
2090 error(ERR_WARNING|ERR_PASS1,
2091 "trailing garbage after %%ifmacro ignored");
2092 nasm_free(searching.name);
2093 j = found;
2094 break;
2097 case PPC_IFID:
2098 needtype = TOK_ID;
2099 goto iftype;
2100 case PPC_IFNUM:
2101 needtype = TOK_NUMBER;
2102 goto iftype;
2103 case PPC_IFSTR:
2104 needtype = TOK_STRING;
2105 goto iftype;
2107 iftype:
2108 t = tline = expand_smacro(tline);
2110 while (tok_type_(t, TOK_WHITESPACE) ||
2111 (needtype == TOK_NUMBER &&
2112 tok_type_(t, TOK_OTHER) &&
2113 (t->text[0] == '-' || t->text[0] == '+') &&
2114 !t->text[1]))
2115 t = t->next;
2117 j = tok_type_(t, needtype);
2118 break;
2120 case PPC_IFTOKEN:
2121 t = tline = expand_smacro(tline);
2122 while (tok_type_(t, TOK_WHITESPACE))
2123 t = t->next;
2125 j = false;
2126 if (t) {
2127 t = t->next; /* Skip the actual token */
2128 while (tok_type_(t, TOK_WHITESPACE))
2129 t = t->next;
2130 j = !t; /* Should be nothing left */
2132 break;
2134 case PPC_IFEMPTY:
2135 t = tline = expand_smacro(tline);
2136 while (tok_type_(t, TOK_WHITESPACE))
2137 t = t->next;
2139 j = !t; /* Should be empty */
2140 break;
2142 case PPC_IF:
2143 t = tline = expand_smacro(tline);
2144 tptr = &t;
2145 tokval.t_type = TOKEN_INVALID;
2146 evalresult = evaluate(ppscan, tptr, &tokval,
2147 NULL, pass | CRITICAL, error, NULL);
2148 if (!evalresult)
2149 return -1;
2150 if (tokval.t_type)
2151 error(ERR_WARNING|ERR_PASS1,
2152 "trailing garbage after expression ignored");
2153 if (!is_simple(evalresult)) {
2154 error(ERR_NONFATAL,
2155 "non-constant value given to `%s'", pp_directives[ct]);
2156 goto fail;
2158 j = reloc_value(evalresult) != 0;
2159 break;
2161 default:
2162 error(ERR_FATAL,
2163 "preprocessor directive `%s' not yet implemented",
2164 pp_directives[ct]);
2165 goto fail;
2168 free_tlist(origline);
2169 return j ^ PP_NEGATIVE(ct);
2171 fail:
2172 free_tlist(origline);
2173 return -1;
2177 * Common code for defining an smacro
2179 static bool define_smacro(Context *ctx, const char *mname, bool casesense,
2180 int nparam, Token *expansion)
2182 SMacro *smac, **smhead;
2183 struct hash_table *smtbl;
2185 if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
2186 if (!smac) {
2187 error(ERR_WARNING|ERR_PASS1,
2188 "single-line macro `%s' defined both with and"
2189 " without parameters", mname);
2191 * Some instances of the old code considered this a failure,
2192 * some others didn't. What is the right thing to do here?
2194 free_tlist(expansion);
2195 return false; /* Failure */
2196 } else {
2198 * We're redefining, so we have to take over an
2199 * existing SMacro structure. This means freeing
2200 * what was already in it.
2202 nasm_free(smac->name);
2203 free_tlist(smac->expansion);
2205 } else {
2206 smtbl = ctx ? &ctx->localmac : &smacros;
2207 smhead = (SMacro **) hash_findi_add(smtbl, mname);
2208 smac = nasm_zalloc(sizeof(SMacro));
2209 smac->next = *smhead;
2210 *smhead = smac;
2212 smac->name = nasm_strdup(mname);
2213 smac->casesense = casesense;
2214 smac->nparam = nparam;
2215 smac->expansion = expansion;
2216 smac->in_progress = false;
2217 return true; /* Success */
2221 * Undefine an smacro
2223 static void undef_smacro(Context *ctx, const char *mname)
2225 SMacro **smhead, *s, **sp;
2226 struct hash_table *smtbl;
2228 smtbl = ctx ? &ctx->localmac : &smacros;
2229 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
2231 if (smhead) {
2233 * We now have a macro name... go hunt for it.
2235 sp = smhead;
2236 while ((s = *sp) != NULL) {
2237 if (!mstrcmp(s->name, mname, s->casesense)) {
2238 *sp = s->next;
2239 nasm_free(s->name);
2240 free_tlist(s->expansion);
2241 nasm_free(s);
2242 } else {
2243 sp = &s->next;
2250 * Parse a mmacro specification.
2252 static bool parse_mmacro_spec(Token *tline, ExpDef *def, const char *directive)
2254 bool err;
2256 tline = tline->next;
2257 skip_white_(tline);
2258 tline = expand_id(tline);
2259 if (!tok_type_(tline, TOK_ID)) {
2260 error(ERR_NONFATAL, "`%s' expects a macro name", directive);
2261 return false;
2264 def->name = nasm_strdup(tline->text);
2265 def->plus = false;
2266 def->nolist = false;
2267 // def->in_progress = 0;
2268 // def->rep_nest = NULL;
2269 def->nparam_min = 0;
2270 def->nparam_max = 0;
2272 tline = expand_smacro(tline->next);
2273 skip_white_(tline);
2274 if (!tok_type_(tline, TOK_NUMBER)) {
2275 error(ERR_NONFATAL, "`%s' expects a parameter count", directive);
2276 } else {
2277 def->nparam_min = def->nparam_max =
2278 readnum(tline->text, &err);
2279 if (err)
2280 error(ERR_NONFATAL,
2281 "unable to parse parameter count `%s'", tline->text);
2283 if (tline && tok_is_(tline->next, "-")) {
2284 tline = tline->next->next;
2285 if (tok_is_(tline, "*")) {
2286 def->nparam_max = INT_MAX;
2287 } else if (!tok_type_(tline, TOK_NUMBER)) {
2288 error(ERR_NONFATAL,
2289 "`%s' expects a parameter count after `-'", directive);
2290 } else {
2291 def->nparam_max = readnum(tline->text, &err);
2292 if (err) {
2293 error(ERR_NONFATAL, "unable to parse parameter count `%s'",
2294 tline->text);
2296 if (def->nparam_min > def->nparam_max) {
2297 error(ERR_NONFATAL, "minimum parameter count exceeds maximum");
2301 if (tline && tok_is_(tline->next, "+")) {
2302 tline = tline->next;
2303 def->plus = true;
2305 if (tline && tok_type_(tline->next, TOK_ID) &&
2306 !nasm_stricmp(tline->next->text, ".nolist")) {
2307 tline = tline->next;
2308 def->nolist = true;
2312 * Handle default parameters.
2314 if (tline && tline->next) {
2315 def->dlist = tline->next;
2316 tline->next = NULL;
2317 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
2318 } else {
2319 def->dlist = NULL;
2320 def->defaults = NULL;
2322 def->line = NULL;
2324 if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
2325 !def->plus)
2326 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MDP,
2327 "too many default macro parameters");
2329 return true;
2334 * Decode a size directive
2336 static int parse_size(const char *str) {
2337 static const char *size_names[] =
2338 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
2339 static const int sizes[] =
2340 { 0, 1, 4, 16, 8, 10, 2, 32 };
2342 return sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1];
2346 * find and process preprocessor directive in passed line
2347 * Find out if a line contains a preprocessor directive, and deal
2348 * with it if so.
2350 * If a directive _is_ found, it is the responsibility of this routine
2351 * (and not the caller) to free_tlist() the line.
2353 * @param tline a pointer to the current tokeninzed line linked list
2354 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2357 static int do_directive(Token * tline)
2359 enum preproc_token i;
2360 int j;
2361 bool err;
2362 int nparam;
2363 bool nolist;
2364 bool casesense;
2365 int k, m;
2366 int offset;
2367 char *p, *pp;
2368 const char *mname;
2369 Include *inc;
2370 Context *ctx;
2371 Line *l;
2372 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
2373 struct tokenval tokval;
2374 expr *evalresult;
2375 ExpDef *ed, *eed, **edhead;
2376 ExpInv *ei, *eei;
2377 int64_t count;
2378 size_t len;
2379 int severity;
2381 origline = tline;
2383 skip_white_(tline);
2384 if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
2385 (tline->text[1] == '%' || tline->text[1] == '$'
2386 || tline->text[1] == '!'))
2387 return NO_DIRECTIVE_FOUND;
2389 i = pp_token_hash(tline->text);
2391 switch (i) {
2392 case PP_INVALID:
2393 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2394 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2395 tline->text);
2396 return NO_DIRECTIVE_FOUND; /* didn't get it */
2398 case PP_STACKSIZE:
2399 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2400 /* Directive to tell NASM what the default stack size is. The
2401 * default is for a 16-bit stack, and this can be overriden with
2402 * %stacksize large.
2404 tline = tline->next;
2405 if (tline && tline->type == TOK_WHITESPACE)
2406 tline = tline->next;
2407 if (!tline || tline->type != TOK_ID) {
2408 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
2409 free_tlist(origline);
2410 return DIRECTIVE_FOUND;
2412 if (nasm_stricmp(tline->text, "flat") == 0) {
2413 /* All subsequent ARG directives are for a 32-bit stack */
2414 StackSize = 4;
2415 StackPointer = "ebp";
2416 ArgOffset = 8;
2417 LocalOffset = 0;
2418 } else if (nasm_stricmp(tline->text, "flat64") == 0) {
2419 /* All subsequent ARG directives are for a 64-bit stack */
2420 StackSize = 8;
2421 StackPointer = "rbp";
2422 ArgOffset = 16;
2423 LocalOffset = 0;
2424 } else if (nasm_stricmp(tline->text, "large") == 0) {
2425 /* All subsequent ARG directives are for a 16-bit stack,
2426 * far function call.
2428 StackSize = 2;
2429 StackPointer = "bp";
2430 ArgOffset = 4;
2431 LocalOffset = 0;
2432 } else if (nasm_stricmp(tline->text, "small") == 0) {
2433 /* All subsequent ARG directives are for a 16-bit stack,
2434 * far function call. We don't support near functions.
2436 StackSize = 2;
2437 StackPointer = "bp";
2438 ArgOffset = 6;
2439 LocalOffset = 0;
2440 } else {
2441 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
2442 free_tlist(origline);
2443 return DIRECTIVE_FOUND;
2445 free_tlist(origline);
2446 return DIRECTIVE_FOUND;
2448 case PP_ARG:
2449 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2450 /* TASM like ARG directive to define arguments to functions, in
2451 * the following form:
2453 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2455 offset = ArgOffset;
2456 do {
2457 char *arg, directive[256];
2458 int size = StackSize;
2460 /* Find the argument name */
2461 tline = tline->next;
2462 if (tline && tline->type == TOK_WHITESPACE)
2463 tline = tline->next;
2464 if (!tline || tline->type != TOK_ID) {
2465 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
2466 free_tlist(origline);
2467 return DIRECTIVE_FOUND;
2469 arg = tline->text;
2471 /* Find the argument size type */
2472 tline = tline->next;
2473 if (!tline || tline->type != TOK_OTHER
2474 || tline->text[0] != ':') {
2475 error(ERR_NONFATAL,
2476 "Syntax error processing `%%arg' directive");
2477 free_tlist(origline);
2478 return DIRECTIVE_FOUND;
2480 tline = tline->next;
2481 if (!tline || tline->type != TOK_ID) {
2482 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
2483 free_tlist(origline);
2484 return DIRECTIVE_FOUND;
2487 /* Allow macro expansion of type parameter */
2488 tt = tokenize(tline->text);
2489 tt = expand_smacro(tt);
2490 size = parse_size(tt->text);
2491 if (!size) {
2492 error(ERR_NONFATAL,
2493 "Invalid size type for `%%arg' missing directive");
2494 free_tlist(tt);
2495 free_tlist(origline);
2496 return DIRECTIVE_FOUND;
2498 free_tlist(tt);
2500 /* Round up to even stack slots */
2501 size = ALIGN(size, StackSize);
2503 /* Now define the macro for the argument */
2504 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
2505 arg, StackPointer, offset);
2506 do_directive(tokenize(directive));
2507 offset += size;
2509 /* Move to the next argument in the list */
2510 tline = tline->next;
2511 if (tline && tline->type == TOK_WHITESPACE)
2512 tline = tline->next;
2513 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2514 ArgOffset = offset;
2515 free_tlist(origline);
2516 return DIRECTIVE_FOUND;
2518 case PP_LOCAL:
2519 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2520 /* TASM like LOCAL directive to define local variables for a
2521 * function, in the following form:
2523 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2525 * The '= LocalSize' at the end is ignored by NASM, but is
2526 * required by TASM to define the local parameter size (and used
2527 * by the TASM macro package).
2529 offset = LocalOffset;
2530 do {
2531 char *local, directive[256];
2532 int size = StackSize;
2534 /* Find the argument name */
2535 tline = tline->next;
2536 if (tline && tline->type == TOK_WHITESPACE)
2537 tline = tline->next;
2538 if (!tline || tline->type != TOK_ID) {
2539 error(ERR_NONFATAL,
2540 "`%%local' missing argument parameter");
2541 free_tlist(origline);
2542 return DIRECTIVE_FOUND;
2544 local = tline->text;
2546 /* Find the argument size type */
2547 tline = tline->next;
2548 if (!tline || tline->type != TOK_OTHER
2549 || tline->text[0] != ':') {
2550 error(ERR_NONFATAL,
2551 "Syntax error processing `%%local' directive");
2552 free_tlist(origline);
2553 return DIRECTIVE_FOUND;
2555 tline = tline->next;
2556 if (!tline || tline->type != TOK_ID) {
2557 error(ERR_NONFATAL,
2558 "`%%local' missing size type parameter");
2559 free_tlist(origline);
2560 return DIRECTIVE_FOUND;
2563 /* Allow macro expansion of type parameter */
2564 tt = tokenize(tline->text);
2565 tt = expand_smacro(tt);
2566 size = parse_size(tt->text);
2567 if (!size) {
2568 error(ERR_NONFATAL,
2569 "Invalid size type for `%%local' missing directive");
2570 free_tlist(tt);
2571 free_tlist(origline);
2572 return DIRECTIVE_FOUND;
2574 free_tlist(tt);
2576 /* Round up to even stack slots */
2577 size = ALIGN(size, StackSize);
2579 offset += size; /* Negative offset, increment before */
2581 /* Now define the macro for the argument */
2582 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
2583 local, StackPointer, offset);
2584 do_directive(tokenize(directive));
2586 /* Now define the assign to setup the enter_c macro correctly */
2587 snprintf(directive, sizeof(directive),
2588 "%%assign %%$localsize %%$localsize+%d", size);
2589 do_directive(tokenize(directive));
2591 /* Move to the next argument in the list */
2592 tline = tline->next;
2593 if (tline && tline->type == TOK_WHITESPACE)
2594 tline = tline->next;
2595 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2596 LocalOffset = offset;
2597 free_tlist(origline);
2598 return DIRECTIVE_FOUND;
2600 case PP_CLEAR:
2601 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2602 if (tline->next)
2603 error(ERR_WARNING|ERR_PASS1,
2604 "trailing garbage after `%%clear' ignored");
2605 free_macros();
2606 init_macros();
2607 free_tlist(origline);
2608 return DIRECTIVE_FOUND;
2610 case PP_DEPEND:
2611 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2612 t = tline->next = expand_smacro(tline->next);
2613 skip_white_(t);
2614 if (!t || (t->type != TOK_STRING &&
2615 t->type != TOK_INTERNAL_STRING)) {
2616 error(ERR_NONFATAL, "`%%depend' expects a file name");
2617 free_tlist(origline);
2618 return DIRECTIVE_FOUND; /* but we did _something_ */
2620 if (t->next)
2621 error(ERR_WARNING|ERR_PASS1,
2622 "trailing garbage after `%%depend' ignored");
2623 p = t->text;
2624 if (t->type != TOK_INTERNAL_STRING)
2625 nasm_unquote_cstr(p, i);
2626 if (dephead && !in_list(*dephead, p)) {
2627 StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next);
2628 sl->next = NULL;
2629 strcpy(sl->str, p);
2630 *deptail = sl;
2631 deptail = &sl->next;
2633 free_tlist(origline);
2634 return DIRECTIVE_FOUND;
2636 case PP_INCLUDE:
2637 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2638 t = tline->next = expand_smacro(tline->next);
2639 skip_white_(t);
2641 if (!t || (t->type != TOK_STRING &&
2642 t->type != TOK_INTERNAL_STRING)) {
2643 error(ERR_NONFATAL, "`%%include' expects a file name");
2644 free_tlist(origline);
2645 return DIRECTIVE_FOUND; /* but we did _something_ */
2647 if (t->next)
2648 error(ERR_WARNING|ERR_PASS1,
2649 "trailing garbage after `%%include' ignored");
2650 p = t->text;
2651 if (t->type != TOK_INTERNAL_STRING)
2652 nasm_unquote_cstr(p, i);
2653 inc = nasm_zalloc(sizeof(Include));
2654 inc->next = istk;
2655 inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
2656 if (!inc->fp) {
2657 /* -MG given but file not found */
2658 nasm_free(inc);
2659 } else {
2660 inc->fname = src_set_fname(nasm_strdup(p));
2661 inc->lineno = src_set_linnum(0);
2662 inc->lineinc = 1;
2663 inc->expansion = NULL;
2664 istk = inc;
2665 list->uplevel(LIST_INCLUDE);
2667 free_tlist(origline);
2668 return DIRECTIVE_FOUND;
2670 case PP_USE:
2671 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2673 static macros_t *use_pkg;
2674 const char *pkg_macro = NULL;
2676 tline = tline->next;
2677 skip_white_(tline);
2678 tline = expand_id(tline);
2680 if (!tline || (tline->type != TOK_STRING &&
2681 tline->type != TOK_INTERNAL_STRING &&
2682 tline->type != TOK_ID)) {
2683 error(ERR_NONFATAL, "`%%use' expects a package name");
2684 free_tlist(origline);
2685 return DIRECTIVE_FOUND; /* but we did _something_ */
2687 if (tline->next)
2688 error(ERR_WARNING|ERR_PASS1,
2689 "trailing garbage after `%%use' ignored");
2690 if (tline->type == TOK_STRING)
2691 nasm_unquote_cstr(tline->text, i);
2692 use_pkg = nasm_stdmac_find_package(tline->text);
2693 if (!use_pkg)
2694 error(ERR_NONFATAL, "unknown `%%use' package: %s", tline->text);
2695 else
2696 pkg_macro = (char *)use_pkg + 1; /* The first string will be <%define>__USE_*__ */
2697 if (use_pkg && ! smacro_defined(NULL, pkg_macro, 0, NULL, true)) {
2698 /* Not already included, go ahead and include it */
2699 stdmacpos = use_pkg;
2701 free_tlist(origline);
2702 return DIRECTIVE_FOUND;
2704 case PP_PUSH:
2705 case PP_REPL:
2706 case PP_POP:
2707 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2708 tline = tline->next;
2709 skip_white_(tline);
2710 tline = expand_id(tline);
2711 if (tline) {
2712 if (!tok_type_(tline, TOK_ID)) {
2713 error(ERR_NONFATAL, "`%s' expects a context identifier",
2714 pp_directives[i]);
2715 free_tlist(origline);
2716 return DIRECTIVE_FOUND; /* but we did _something_ */
2718 if (tline->next)
2719 error(ERR_WARNING|ERR_PASS1,
2720 "trailing garbage after `%s' ignored",
2721 pp_directives[i]);
2722 p = nasm_strdup(tline->text);
2723 } else {
2724 p = NULL; /* Anonymous */
2727 if (i == PP_PUSH) {
2728 ctx = nasm_zalloc(sizeof(Context));
2729 ctx->next = cstk;
2730 hash_init(&ctx->localmac, HASH_SMALL);
2731 ctx->name = p;
2732 ctx->number = unique++;
2733 cstk = ctx;
2734 } else {
2735 /* %pop or %repl */
2736 if (!cstk) {
2737 error(ERR_NONFATAL, "`%s': context stack is empty",
2738 pp_directives[i]);
2739 } else if (i == PP_POP) {
2740 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
2741 error(ERR_NONFATAL, "`%%pop' in wrong context: %s, "
2742 "expected %s",
2743 cstk->name ? cstk->name : "anonymous", p);
2744 else
2745 ctx_pop();
2746 } else {
2747 /* i == PP_REPL */
2748 nasm_free(cstk->name);
2749 cstk->name = p;
2750 p = NULL;
2752 nasm_free(p);
2754 free_tlist(origline);
2755 return DIRECTIVE_FOUND;
2756 case PP_FATAL:
2757 severity = ERR_FATAL;
2758 goto issue_error;
2759 case PP_ERROR:
2760 severity = ERR_NONFATAL;
2761 goto issue_error;
2762 case PP_WARNING:
2763 severity = ERR_WARNING|ERR_WARN_USER;
2764 goto issue_error;
2766 issue_error:
2767 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2769 /* Only error out if this is the final pass */
2770 if (pass != 2 && i != PP_FATAL)
2771 return DIRECTIVE_FOUND;
2773 tline->next = expand_smacro(tline->next);
2774 tline = tline->next;
2775 skip_white_(tline);
2776 t = tline ? tline->next : NULL;
2777 skip_white_(t);
2778 if (tok_type_(tline, TOK_STRING) && !t) {
2779 /* The line contains only a quoted string */
2780 p = tline->text;
2781 nasm_unquote(p, NULL); /* Ignore NUL character truncation */
2782 error(severity, "%s", p);
2783 } else {
2784 /* Not a quoted string, or more than a quoted string */
2785 p = detoken(tline, false);
2786 error(severity, "%s", p);
2787 nasm_free(p);
2789 free_tlist(origline);
2790 return DIRECTIVE_FOUND;
2793 CASE_PP_IF:
2794 if (defining != NULL) {
2795 if (defining->type == EXP_IF) {
2796 defining->def_depth ++;
2798 return NO_DIRECTIVE_FOUND;
2800 if ((istk->expansion != NULL) &&
2801 (istk->expansion->emitting == false)) {
2802 j = COND_NEVER;
2803 } else {
2804 j = if_condition(tline->next, i);
2805 tline->next = NULL; /* it got freed */
2806 j = (((j < 0) ? COND_NEVER : j) ? COND_IF_TRUE : COND_IF_FALSE);
2808 ed = new_ExpDef(EXP_IF);
2809 ed->state = j;
2810 ed->ignoring = ((ed->state == COND_IF_TRUE) ? false : true);
2811 ed->prev = defining;
2812 defining = ed;
2813 free_tlist(origline);
2814 return DIRECTIVE_FOUND;
2816 CASE_PP_ELIF:
2817 if (defining != NULL) {
2818 if ((defining->type != EXP_IF) || (defining->def_depth > 0)) {
2819 return NO_DIRECTIVE_FOUND;
2822 if ((defining == NULL) || (defining->type != EXP_IF)) {
2823 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
2825 switch (defining->state) {
2826 case COND_IF_TRUE:
2827 defining->state = COND_DONE;
2828 defining->ignoring = true;
2829 break;
2831 case COND_DONE:
2832 case COND_NEVER:
2833 defining->ignoring = true;
2834 break;
2836 case COND_ELSE_TRUE:
2837 case COND_ELSE_FALSE:
2838 error_precond(ERR_WARNING|ERR_PASS1,
2839 "`%%elif' after `%%else' ignored");
2840 defining->state = COND_NEVER;
2841 defining->ignoring = true;
2842 break;
2844 case COND_IF_FALSE:
2846 * IMPORTANT: In the case of %if, we will already have
2847 * called expand_mmac_params(); however, if we're
2848 * processing an %elif we must have been in a
2849 * non-emitting mode, which would have inhibited
2850 * the normal invocation of expand_mmac_params().
2851 * Therefore, we have to do it explicitly here.
2853 j = if_condition(expand_mmac_params(tline->next), i);
2854 tline->next = NULL; /* it got freed */
2855 defining->state =
2856 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2857 defining->ignoring = ((defining->state == COND_IF_TRUE) ? false : true);
2858 break;
2860 free_tlist(origline);
2861 return DIRECTIVE_FOUND;
2863 case PP_ELSE:
2864 if (defining != NULL) {
2865 if ((defining->type != EXP_IF) || (defining->def_depth > 0)) {
2866 return NO_DIRECTIVE_FOUND;
2869 if (tline->next)
2870 error_precond(ERR_WARNING|ERR_PASS1,
2871 "trailing garbage after `%%else' ignored");
2872 if ((defining == NULL) || (defining->type != EXP_IF)) {
2873 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
2875 switch (defining->state) {
2876 case COND_IF_TRUE:
2877 case COND_DONE:
2878 defining->state = COND_ELSE_FALSE;
2879 defining->ignoring = true;
2880 break;
2882 case COND_NEVER:
2883 defining->ignoring = true;
2884 break;
2886 case COND_IF_FALSE:
2887 defining->state = COND_ELSE_TRUE;
2888 defining->ignoring = false;
2889 break;
2891 case COND_ELSE_TRUE:
2892 case COND_ELSE_FALSE:
2893 error_precond(ERR_WARNING|ERR_PASS1,
2894 "`%%else' after `%%else' ignored.");
2895 defining->state = COND_NEVER;
2896 defining->ignoring = true;
2897 break;
2899 free_tlist(origline);
2900 return DIRECTIVE_FOUND;
2902 case PP_ENDIF:
2903 if (defining != NULL) {
2904 if (defining->type == EXP_IF) {
2905 if (defining->def_depth > 0) {
2906 defining->def_depth --;
2907 return NO_DIRECTIVE_FOUND;
2909 } else {
2910 return NO_DIRECTIVE_FOUND;
2913 if (tline->next)
2914 error_precond(ERR_WARNING|ERR_PASS1,
2915 "trailing garbage after `%%endif' ignored");
2916 if ((defining == NULL) || (defining->type != EXP_IF)) {
2917 error(ERR_NONFATAL, "`%%endif': no matching `%%if'");
2918 return DIRECTIVE_FOUND;
2920 ed = defining;
2921 defining = ed->prev;
2922 ed->prev = expansions;
2923 expansions = ed;
2924 ei = new_ExpInv(EXP_IF, ed);
2925 ei->current = ed->line;
2926 ei->emitting = true;
2927 ei->prev = istk->expansion;
2928 istk->expansion = ei;
2929 free_tlist(origline);
2930 return DIRECTIVE_FOUND;
2932 case PP_RMACRO:
2933 case PP_IRMACRO:
2934 case PP_MACRO:
2935 case PP_IMACRO:
2936 if (defining != NULL) {
2937 if (defining->type == EXP_MMACRO) {
2938 defining->def_depth ++;
2940 return NO_DIRECTIVE_FOUND;
2942 ed = new_ExpDef(EXP_MMACRO);
2943 ed->max_depth =
2944 (i == PP_RMACRO) || (i == PP_IRMACRO) ? DEADMAN_LIMIT : 0;
2945 ed->casesense = (i == PP_MACRO) || (i == PP_RMACRO);
2946 if (!parse_mmacro_spec(tline, ed, pp_directives[i])) {
2947 nasm_free(ed);
2948 ed = NULL;
2949 return DIRECTIVE_FOUND;
2951 ed->def_depth = 0;
2952 ed->cur_depth = 0;
2953 ed->max_depth = (ed->max_depth + 1);
2954 ed->ignoring = false;
2955 ed->prev = defining;
2956 defining = ed;
2958 eed = (ExpDef *) hash_findix(&expdefs, ed->name);
2959 while (eed) {
2960 if (!strcmp(eed->name, ed->name) &&
2961 (eed->nparam_min <= ed->nparam_max || ed->plus) &&
2962 (ed->nparam_min <= eed->nparam_max || eed->plus)) {
2963 error(ERR_WARNING|ERR_PASS1,
2964 "redefining multi-line macro `%s'", ed->name);
2965 return DIRECTIVE_FOUND;
2967 eed = eed->next;
2969 free_tlist(origline);
2970 return DIRECTIVE_FOUND;
2972 case PP_ENDM:
2973 case PP_ENDMACRO:
2974 if (defining != NULL) {
2975 if (defining->type == EXP_MMACRO) {
2976 if (defining->def_depth > 0) {
2977 defining->def_depth --;
2978 return NO_DIRECTIVE_FOUND;
2980 } else {
2981 return NO_DIRECTIVE_FOUND;
2984 if (!(defining) || (defining->type != EXP_MMACRO)) {
2985 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2986 return DIRECTIVE_FOUND;
2988 edhead = (ExpDef **) hash_findi_add(&expdefs, defining->name);
2989 defining->next = *edhead;
2990 *edhead = defining;
2991 ed = defining;
2992 defining = ed->prev;
2993 ed->prev = expansions;
2994 expansions = ed;
2995 ed = NULL;
2996 free_tlist(origline);
2997 return DIRECTIVE_FOUND;
2999 case PP_EXITMACRO:
3000 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3002 * We must search along istk->expansion until we hit a
3003 * macro invocation. Then we disable the emitting state(s)
3004 * between exitmacro and endmacro.
3006 for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
3007 if(ei->type == EXP_MMACRO) {
3008 break;
3012 if (ei != NULL) {
3014 * Set all invocations leading back to the macro
3015 * invocation to a non-emitting state.
3017 for (eei = istk->expansion; eei != ei; eei = eei->prev) {
3018 eei->emitting = false;
3020 eei->emitting = false;
3021 } else {
3022 error(ERR_NONFATAL, "`%%exitmacro' not within `%%macro' block");
3024 free_tlist(origline);
3025 return DIRECTIVE_FOUND;
3027 case PP_UNMACRO:
3028 case PP_UNIMACRO:
3029 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3031 ExpDef **ed_p;
3032 ExpDef spec;
3034 spec.casesense = (i == PP_UNMACRO);
3035 if (!parse_mmacro_spec(tline, &spec, pp_directives[i])) {
3036 return DIRECTIVE_FOUND;
3038 ed_p = (ExpDef **) hash_findi(&expdefs, spec.name, NULL);
3039 while (ed_p && *ed_p) {
3040 ed = *ed_p;
3041 if (ed->casesense == spec.casesense &&
3042 !mstrcmp(ed->name, spec.name, spec.casesense) &&
3043 ed->nparam_min == spec.nparam_min &&
3044 ed->nparam_max == spec.nparam_max &&
3045 ed->plus == spec.plus) {
3046 if (ed->cur_depth > 0) {
3047 error(ERR_NONFATAL, "`%s' ignored on active macro",
3048 pp_directives[i]);
3049 break;
3050 } else {
3051 *ed_p = ed->next;
3052 free_expdef(ed);
3054 } else {
3055 ed_p = &ed->next;
3058 free_tlist(origline);
3059 free_tlist(spec.dlist);
3060 return DIRECTIVE_FOUND;
3063 case PP_ROTATE:
3064 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3065 if (tline->next && tline->next->type == TOK_WHITESPACE)
3066 tline = tline->next;
3067 if (!tline->next) {
3068 free_tlist(origline);
3069 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
3070 return DIRECTIVE_FOUND;
3072 t = expand_smacro(tline->next);
3073 tline->next = NULL;
3074 free_tlist(origline);
3075 tline = t;
3076 tptr = &t;
3077 tokval.t_type = TOKEN_INVALID;
3078 evalresult =
3079 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3080 free_tlist(tline);
3081 if (!evalresult)
3082 return DIRECTIVE_FOUND;
3083 if (tokval.t_type)
3084 error(ERR_WARNING|ERR_PASS1,
3085 "trailing garbage after expression ignored");
3086 if (!is_simple(evalresult)) {
3087 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
3088 return DIRECTIVE_FOUND;
3090 for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
3091 if (ei->type == EXP_MMACRO) {
3092 break;
3095 if (ei == NULL) {
3096 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
3097 } else if (ei->nparam == 0) {
3098 error(ERR_NONFATAL,
3099 "`%%rotate' invoked within macro without parameters");
3100 } else {
3101 int rotate = ei->rotate + reloc_value(evalresult);
3103 rotate %= (int)ei->nparam;
3104 if (rotate < 0)
3105 rotate += ei->nparam;
3106 ei->rotate = rotate;
3108 return DIRECTIVE_FOUND;
3110 case PP_REP:
3111 if (defining != NULL) {
3112 if (defining->type == EXP_REP) {
3113 defining->def_depth ++;
3115 return NO_DIRECTIVE_FOUND;
3117 nolist = false;
3118 do {
3119 tline = tline->next;
3120 } while (tok_type_(tline, TOK_WHITESPACE));
3122 if (tok_type_(tline, TOK_ID) &&
3123 nasm_stricmp(tline->text, ".nolist") == 0) {
3124 nolist = true;
3125 do {
3126 tline = tline->next;
3127 } while (tok_type_(tline, TOK_WHITESPACE));
3130 if (tline) {
3131 t = expand_smacro(tline);
3132 tptr = &t;
3133 tokval.t_type = TOKEN_INVALID;
3134 evalresult =
3135 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3136 if (!evalresult) {
3137 free_tlist(origline);
3138 return DIRECTIVE_FOUND;
3140 if (tokval.t_type)
3141 error(ERR_WARNING|ERR_PASS1,
3142 "trailing garbage after expression ignored");
3143 if (!is_simple(evalresult)) {
3144 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
3145 return DIRECTIVE_FOUND;
3147 count = reloc_value(evalresult);
3148 if (count >= REP_LIMIT) {
3149 error(ERR_NONFATAL, "`%%rep' value exceeds limit");
3150 count = 0;
3151 } else
3152 count++;
3153 } else {
3154 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
3155 count = 0;
3157 free_tlist(origline);
3158 ed = new_ExpDef(EXP_REP);
3159 ed->nolist = nolist;
3160 ed->def_depth = 0;
3161 ed->cur_depth = 1;
3162 ed->max_depth = (count - 1);
3163 ed->ignoring = false;
3164 ed->prev = defining;
3165 defining = ed;
3166 return DIRECTIVE_FOUND;
3168 case PP_ENDREP:
3169 if (defining != NULL) {
3170 if (defining->type == EXP_REP) {
3171 if (defining->def_depth > 0) {
3172 defining->def_depth --;
3173 return NO_DIRECTIVE_FOUND;
3175 } else {
3176 return NO_DIRECTIVE_FOUND;
3179 if ((defining == NULL) || (defining->type != EXP_REP)) {
3180 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
3181 return DIRECTIVE_FOUND;
3185 * Now we have a "macro" defined - although it has no name
3186 * and we won't be entering it in the hash tables - we must
3187 * push a macro-end marker for it on to istk->expansion.
3188 * After that, it will take care of propagating itself (a
3189 * macro-end marker line for a macro which is really a %rep
3190 * block will cause the macro to be re-expanded, complete
3191 * with another macro-end marker to ensure the process
3192 * continues) until the whole expansion is forcibly removed
3193 * from istk->expansion by a %exitrep.
3195 ed = defining;
3196 defining = ed->prev;
3197 ed->prev = expansions;
3198 expansions = ed;
3199 ei = new_ExpInv(EXP_REP, ed);
3200 ei->current = ed->line;
3201 ei->emitting = ((ed->max_depth > 0) ? true : false);
3202 list->uplevel(ed->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
3203 ei->prev = istk->expansion;
3204 istk->expansion = ei;
3205 free_tlist(origline);
3206 return DIRECTIVE_FOUND;
3208 case PP_EXITREP:
3209 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3211 * We must search along istk->expansion until we hit a
3212 * rep invocation. Then we disable the emitting state(s)
3213 * between exitrep and endrep.
3215 for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
3216 if (ei->type == EXP_REP) {
3217 break;
3221 if (ei != NULL) {
3223 * Set all invocations leading back to the rep
3224 * invocation to a non-emitting state.
3226 for (eei = istk->expansion; eei != ei; eei = eei->prev) {
3227 eei->emitting = false;
3229 eei->emitting = false;
3230 eei->current = NULL;
3231 eei->def->cur_depth = eei->def->max_depth;
3232 } else {
3233 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
3235 free_tlist(origline);
3236 return DIRECTIVE_FOUND;
3238 case PP_XDEFINE:
3239 case PP_IXDEFINE:
3240 case PP_DEFINE:
3241 case PP_IDEFINE:
3242 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3243 casesense = (i == PP_DEFINE || i == PP_XDEFINE);
3245 tline = tline->next;
3246 skip_white_(tline);
3247 tline = expand_id(tline);
3248 if (!tline || (tline->type != TOK_ID &&
3249 (tline->type != TOK_PREPROC_ID ||
3250 tline->text[1] != '$'))) {
3251 error(ERR_NONFATAL, "`%s' expects a macro identifier",
3252 pp_directives[i]);
3253 free_tlist(origline);
3254 return DIRECTIVE_FOUND;
3257 ctx = get_ctx(tline->text, &mname);
3258 last = tline;
3259 param_start = tline = tline->next;
3260 nparam = 0;
3262 /* Expand the macro definition now for %xdefine and %ixdefine */
3263 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
3264 tline = expand_smacro(tline);
3266 if (tok_is_(tline, "(")) {
3268 * This macro has parameters.
3271 tline = tline->next;
3272 while (1) {
3273 skip_white_(tline);
3274 if (!tline) {
3275 error(ERR_NONFATAL, "parameter identifier expected");
3276 free_tlist(origline);
3277 return DIRECTIVE_FOUND;
3279 if (tline->type != TOK_ID) {
3280 error(ERR_NONFATAL,
3281 "`%s': parameter identifier expected",
3282 tline->text);
3283 free_tlist(origline);
3284 return DIRECTIVE_FOUND;
3287 smacro_set_param_idx(tline, nparam);
3288 nparam++;
3290 tline = tline->next;
3291 skip_white_(tline);
3292 if (tok_is_(tline, ",")) {
3293 tline = tline->next;
3294 } else {
3295 if (!tok_is_(tline, ")")) {
3296 error(ERR_NONFATAL,
3297 "`)' expected to terminate macro template");
3298 free_tlist(origline);
3299 return DIRECTIVE_FOUND;
3301 break;
3304 last = tline;
3305 tline = tline->next;
3307 if (tok_type_(tline, TOK_WHITESPACE))
3308 last = tline, tline = tline->next;
3309 macro_start = NULL;
3310 last->next = NULL;
3311 t = tline;
3312 while (t) {
3313 if (t->type == TOK_ID) {
3314 list_for_each(tt, param_start)
3315 if (is_smacro_param(tt) &&
3316 !strcmp(tt->text, t->text))
3317 t->type = tt->type;
3319 tt = t->next;
3320 t->next = macro_start;
3321 macro_start = t;
3322 t = tt;
3325 * Good. We now have a macro name, a parameter count, and a
3326 * token list (in reverse order) for an expansion. We ought
3327 * to be OK just to create an SMacro, store it, and let
3328 * free_tlist have the rest of the line (which we have
3329 * carefully re-terminated after chopping off the expansion
3330 * from the end).
3332 define_smacro(ctx, mname, casesense, nparam, macro_start);
3333 free_tlist(origline);
3334 return DIRECTIVE_FOUND;
3336 case PP_UNDEF:
3337 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3338 tline = tline->next;
3339 skip_white_(tline);
3340 tline = expand_id(tline);
3341 if (!tline || (tline->type != TOK_ID &&
3342 (tline->type != TOK_PREPROC_ID ||
3343 tline->text[1] != '$'))) {
3344 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
3345 free_tlist(origline);
3346 return DIRECTIVE_FOUND;
3348 if (tline->next) {
3349 error(ERR_WARNING|ERR_PASS1,
3350 "trailing garbage after macro name ignored");
3353 /* Find the context that symbol belongs to */
3354 ctx = get_ctx(tline->text, &mname);
3355 undef_smacro(ctx, mname);
3356 free_tlist(origline);
3357 return DIRECTIVE_FOUND;
3359 case PP_DEFSTR:
3360 case PP_IDEFSTR:
3361 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3362 casesense = (i == PP_DEFSTR);
3364 tline = tline->next;
3365 skip_white_(tline);
3366 tline = expand_id(tline);
3367 if (!tline || (tline->type != TOK_ID &&
3368 (tline->type != TOK_PREPROC_ID ||
3369 tline->text[1] != '$'))) {
3370 error(ERR_NONFATAL, "`%s' expects a macro identifier",
3371 pp_directives[i]);
3372 free_tlist(origline);
3373 return DIRECTIVE_FOUND;
3376 ctx = get_ctx(tline->text, &mname);
3377 last = tline;
3378 tline = expand_smacro(tline->next);
3379 last->next = NULL;
3381 while (tok_type_(tline, TOK_WHITESPACE))
3382 tline = delete_Token(tline);
3384 p = detoken(tline, false);
3385 macro_start = nasm_zalloc(sizeof(*macro_start));
3386 macro_start->text = nasm_quote(p, strlen(p));
3387 macro_start->type = TOK_STRING;
3388 nasm_free(p);
3391 * We now have a macro name, an implicit parameter count of
3392 * zero, and a string token to use as an expansion. Create
3393 * and store an SMacro.
3395 define_smacro(ctx, mname, casesense, 0, macro_start);
3396 free_tlist(origline);
3397 return DIRECTIVE_FOUND;
3399 case PP_DEFTOK:
3400 case PP_IDEFTOK:
3401 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3402 casesense = (i == PP_DEFTOK);
3404 tline = tline->next;
3405 skip_white_(tline);
3406 tline = expand_id(tline);
3407 if (!tline || (tline->type != TOK_ID &&
3408 (tline->type != TOK_PREPROC_ID ||
3409 tline->text[1] != '$'))) {
3410 error(ERR_NONFATAL,
3411 "`%s' expects a macro identifier as first parameter",
3412 pp_directives[i]);
3413 free_tlist(origline);
3414 return DIRECTIVE_FOUND;
3416 ctx = get_ctx(tline->text, &mname);
3417 last = tline;
3418 tline = expand_smacro(tline->next);
3419 last->next = NULL;
3421 t = tline;
3422 while (tok_type_(t, TOK_WHITESPACE))
3423 t = t->next;
3424 /* t should now point to the string */
3425 if (!tok_type_(t, TOK_STRING)) {
3426 error(ERR_NONFATAL,
3427 "`%s` requires string as second parameter",
3428 pp_directives[i]);
3429 free_tlist(tline);
3430 free_tlist(origline);
3431 return DIRECTIVE_FOUND;
3435 * Convert the string to a token stream. Note that smacros
3436 * are stored with the token stream reversed, so we have to
3437 * reverse the output of tokenize().
3439 nasm_unquote_cstr(t->text, i);
3440 macro_start = reverse_tokens(tokenize(t->text));
3443 * We now have a macro name, an implicit parameter count of
3444 * zero, and a numeric token to use as an expansion. Create
3445 * and store an SMacro.
3447 define_smacro(ctx, mname, casesense, 0, macro_start);
3448 free_tlist(tline);
3449 free_tlist(origline);
3450 return DIRECTIVE_FOUND;
3452 case PP_PATHSEARCH:
3453 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3455 FILE *fp;
3456 StrList *xsl = NULL;
3457 StrList **xst = &xsl;
3459 casesense = true;
3461 tline = tline->next;
3462 skip_white_(tline);
3463 tline = expand_id(tline);
3464 if (!tline || (tline->type != TOK_ID &&
3465 (tline->type != TOK_PREPROC_ID ||
3466 tline->text[1] != '$'))) {
3467 error(ERR_NONFATAL,
3468 "`%%pathsearch' expects a macro identifier as first parameter");
3469 free_tlist(origline);
3470 return DIRECTIVE_FOUND;
3472 ctx = get_ctx(tline->text, &mname);
3473 last = tline;
3474 tline = expand_smacro(tline->next);
3475 last->next = NULL;
3477 t = tline;
3478 while (tok_type_(t, TOK_WHITESPACE))
3479 t = t->next;
3481 if (!t || (t->type != TOK_STRING &&
3482 t->type != TOK_INTERNAL_STRING)) {
3483 error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
3484 free_tlist(tline);
3485 free_tlist(origline);
3486 return DIRECTIVE_FOUND; /* but we did _something_ */
3488 if (t->next)
3489 error(ERR_WARNING|ERR_PASS1,
3490 "trailing garbage after `%%pathsearch' ignored");
3491 p = t->text;
3492 if (t->type != TOK_INTERNAL_STRING)
3493 nasm_unquote(p, NULL);
3495 fp = inc_fopen(p, &xsl, &xst, true);
3496 if (fp) {
3497 p = xsl->str;
3498 fclose(fp); /* Don't actually care about the file */
3500 macro_start = nasm_zalloc(sizeof(*macro_start));
3501 macro_start->text = nasm_quote(p, strlen(p));
3502 macro_start->type = TOK_STRING;
3503 nasm_free(xsl);
3506 * We now have a macro name, an implicit parameter count of
3507 * zero, and a string token to use as an expansion. Create
3508 * and store an SMacro.
3510 define_smacro(ctx, mname, casesense, 0, macro_start);
3511 free_tlist(tline);
3512 free_tlist(origline);
3513 return DIRECTIVE_FOUND;
3516 case PP_STRLEN:
3517 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3518 casesense = true;
3520 tline = tline->next;
3521 skip_white_(tline);
3522 tline = expand_id(tline);
3523 if (!tline || (tline->type != TOK_ID &&
3524 (tline->type != TOK_PREPROC_ID ||
3525 tline->text[1] != '$'))) {
3526 error(ERR_NONFATAL,
3527 "`%%strlen' expects a macro identifier as first parameter");
3528 free_tlist(origline);
3529 return DIRECTIVE_FOUND;
3531 ctx = get_ctx(tline->text, &mname);
3532 last = tline;
3533 tline = expand_smacro(tline->next);
3534 last->next = NULL;
3536 t = tline;
3537 while (tok_type_(t, TOK_WHITESPACE))
3538 t = t->next;
3539 /* t should now point to the string */
3540 if (!tok_type_(t, TOK_STRING)) {
3541 error(ERR_NONFATAL,
3542 "`%%strlen` requires string as second parameter");
3543 free_tlist(tline);
3544 free_tlist(origline);
3545 return DIRECTIVE_FOUND;
3548 macro_start = nasm_zalloc(sizeof(*macro_start));
3549 make_tok_num(macro_start, nasm_unquote(t->text, NULL));
3552 * We now have a macro name, an implicit parameter count of
3553 * zero, and a numeric token to use as an expansion. Create
3554 * and store an SMacro.
3556 define_smacro(ctx, mname, casesense, 0, macro_start);
3557 free_tlist(tline);
3558 free_tlist(origline);
3559 return DIRECTIVE_FOUND;
3561 case PP_STRCAT:
3562 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3563 casesense = true;
3565 tline = tline->next;
3566 skip_white_(tline);
3567 tline = expand_id(tline);
3568 if (!tline || (tline->type != TOK_ID &&
3569 (tline->type != TOK_PREPROC_ID ||
3570 tline->text[1] != '$'))) {
3571 error(ERR_NONFATAL,
3572 "`%%strcat' expects a macro identifier as first parameter");
3573 free_tlist(origline);
3574 return DIRECTIVE_FOUND;
3576 ctx = get_ctx(tline->text, &mname);
3577 last = tline;
3578 tline = expand_smacro(tline->next);
3579 last->next = NULL;
3581 len = 0;
3582 list_for_each(t, tline) {
3583 switch (t->type) {
3584 case TOK_WHITESPACE:
3585 break;
3586 case TOK_STRING:
3587 len += t->a.len = nasm_unquote(t->text, NULL);
3588 break;
3589 case TOK_OTHER:
3590 if (!strcmp(t->text, ",")) /* permit comma separators */
3591 break;
3592 /* else fall through */
3593 default:
3594 error(ERR_NONFATAL,
3595 "non-string passed to `%%strcat' (%d)", t->type);
3596 free_tlist(tline);
3597 free_tlist(origline);
3598 return DIRECTIVE_FOUND;
3602 p = pp = nasm_malloc(len);
3603 list_for_each(t, tline) {
3604 if (t->type == TOK_STRING) {
3605 memcpy(p, t->text, t->a.len);
3606 p += t->a.len;
3611 * We now have a macro name, an implicit parameter count of
3612 * zero, and a numeric token to use as an expansion. Create
3613 * and store an SMacro.
3615 macro_start = new_Token(NULL, TOK_STRING, NULL, 0);
3616 macro_start->text = nasm_quote(pp, len);
3617 nasm_free(pp);
3618 define_smacro(ctx, mname, casesense, 0, macro_start);
3619 free_tlist(tline);
3620 free_tlist(origline);
3621 return DIRECTIVE_FOUND;
3623 case PP_SUBSTR:
3624 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3626 int64_t start, count;
3627 size_t len;
3629 casesense = true;
3631 tline = tline->next;
3632 skip_white_(tline);
3633 tline = expand_id(tline);
3634 if (!tline || (tline->type != TOK_ID &&
3635 (tline->type != TOK_PREPROC_ID ||
3636 tline->text[1] != '$'))) {
3637 error(ERR_NONFATAL,
3638 "`%%substr' expects a macro identifier as first parameter");
3639 free_tlist(origline);
3640 return DIRECTIVE_FOUND;
3642 ctx = get_ctx(tline->text, &mname);
3643 last = tline;
3644 tline = expand_smacro(tline->next);
3645 last->next = NULL;
3647 if (tline) /* skip expanded id */
3648 t = tline->next;
3649 while (tok_type_(t, TOK_WHITESPACE))
3650 t = t->next;
3652 /* t should now point to the string */
3653 if (!tok_type_(t, TOK_STRING)) {
3654 error(ERR_NONFATAL,
3655 "`%%substr` requires string as second parameter");
3656 free_tlist(tline);
3657 free_tlist(origline);
3658 return DIRECTIVE_FOUND;
3661 tt = t->next;
3662 tptr = &tt;
3663 tokval.t_type = TOKEN_INVALID;
3664 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3665 pass, error, NULL);
3666 if (!evalresult) {
3667 free_tlist(tline);
3668 free_tlist(origline);
3669 return DIRECTIVE_FOUND;
3670 } else if (!is_simple(evalresult)) {
3671 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3672 free_tlist(tline);
3673 free_tlist(origline);
3674 return DIRECTIVE_FOUND;
3676 start = evalresult->value - 1;
3678 while (tok_type_(tt, TOK_WHITESPACE))
3679 tt = tt->next;
3680 if (!tt) {
3681 count = 1; /* Backwards compatibility: one character */
3682 } else {
3683 tokval.t_type = TOKEN_INVALID;
3684 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3685 pass, error, NULL);
3686 if (!evalresult) {
3687 free_tlist(tline);
3688 free_tlist(origline);
3689 return DIRECTIVE_FOUND;
3690 } else if (!is_simple(evalresult)) {
3691 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3692 free_tlist(tline);
3693 free_tlist(origline);
3694 return DIRECTIVE_FOUND;
3696 count = evalresult->value;
3699 len = nasm_unquote(t->text, NULL);
3700 /* make start and count being in range */
3701 if (start < 0)
3702 start = 0;
3703 if (count < 0)
3704 count = len + count + 1 - start;
3705 if (start + count > (int64_t)len)
3706 count = len - start;
3707 if (!len || count < 0 || start >=(int64_t)len)
3708 start = -1, count = 0; /* empty string */
3710 macro_start = nasm_zalloc(sizeof(*macro_start));
3711 macro_start->text = nasm_quote((start < 0) ? "" : t->text + start, count);
3712 macro_start->type = TOK_STRING;
3715 * We now have a macro name, an implicit parameter count of
3716 * zero, and a numeric token to use as an expansion. Create
3717 * and store an SMacro.
3719 define_smacro(ctx, mname, casesense, 0, macro_start);
3720 free_tlist(tline);
3721 free_tlist(origline);
3722 return DIRECTIVE_FOUND;
3725 case PP_ASSIGN:
3726 case PP_IASSIGN:
3727 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3728 casesense = (i == PP_ASSIGN);
3730 tline = tline->next;
3731 skip_white_(tline);
3732 tline = expand_id(tline);
3733 if (!tline || (tline->type != TOK_ID &&
3734 (tline->type != TOK_PREPROC_ID ||
3735 tline->text[1] != '$'))) {
3736 error(ERR_NONFATAL,
3737 "`%%%sassign' expects a macro identifier",
3738 (i == PP_IASSIGN ? "i" : ""));
3739 free_tlist(origline);
3740 return DIRECTIVE_FOUND;
3742 ctx = get_ctx(tline->text, &mname);
3743 last = tline;
3744 tline = expand_smacro(tline->next);
3745 last->next = NULL;
3747 t = tline;
3748 tptr = &t;
3749 tokval.t_type = TOKEN_INVALID;
3750 evalresult =
3751 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3752 free_tlist(tline);
3753 if (!evalresult) {
3754 free_tlist(origline);
3755 return DIRECTIVE_FOUND;
3758 if (tokval.t_type)
3759 error(ERR_WARNING|ERR_PASS1,
3760 "trailing garbage after expression ignored");
3762 if (!is_simple(evalresult)) {
3763 error(ERR_NONFATAL,
3764 "non-constant value given to `%%%sassign'",
3765 (i == PP_IASSIGN ? "i" : ""));
3766 free_tlist(origline);
3767 return DIRECTIVE_FOUND;
3770 macro_start = nasm_zalloc(sizeof(*macro_start));
3771 make_tok_num(macro_start, reloc_value(evalresult));
3774 * We now have a macro name, an implicit parameter count of
3775 * zero, and a numeric token to use as an expansion. Create
3776 * and store an SMacro.
3778 define_smacro(ctx, mname, casesense, 0, macro_start);
3779 free_tlist(origline);
3780 return DIRECTIVE_FOUND;
3782 case PP_LINE:
3783 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3785 * Syntax is `%line nnn[+mmm] [filename]'
3787 tline = tline->next;
3788 skip_white_(tline);
3789 if (!tok_type_(tline, TOK_NUMBER)) {
3790 error(ERR_NONFATAL, "`%%line' expects line number");
3791 free_tlist(origline);
3792 return DIRECTIVE_FOUND;
3794 k = readnum(tline->text, &err);
3795 m = 1;
3796 tline = tline->next;
3797 if (tok_is_(tline, "+")) {
3798 tline = tline->next;
3799 if (!tok_type_(tline, TOK_NUMBER)) {
3800 error(ERR_NONFATAL, "`%%line' expects line increment");
3801 free_tlist(origline);
3802 return DIRECTIVE_FOUND;
3804 m = readnum(tline->text, &err);
3805 tline = tline->next;
3807 skip_white_(tline);
3808 src_set_linnum(k);
3809 istk->lineinc = m;
3810 if (tline) {
3811 nasm_free(src_set_fname(detoken(tline, false)));
3813 free_tlist(origline);
3814 return DIRECTIVE_FOUND;
3816 case PP_WHILE:
3817 if (defining != NULL) {
3818 if (defining->type == EXP_WHILE) {
3819 defining->def_depth ++;
3821 return NO_DIRECTIVE_FOUND;
3823 l = NULL;
3824 if ((istk->expansion != NULL) &&
3825 (istk->expansion->emitting == false)) {
3826 j = COND_NEVER;
3827 } else {
3828 l = new_Line();
3829 l->first = copy_Token(tline->next);
3830 j = if_condition(tline->next, i);
3831 tline->next = NULL; /* it got freed */
3832 j = (((j < 0) ? COND_NEVER : j) ? COND_IF_TRUE : COND_IF_FALSE);
3834 ed = new_ExpDef(EXP_WHILE);
3835 ed->state = j;
3836 ed->cur_depth = 1;
3837 ed->max_depth = DEADMAN_LIMIT;
3838 ed->ignoring = ((ed->state == COND_IF_TRUE) ? false : true);
3839 if (ed->ignoring == false) {
3840 ed->line = l;
3841 ed->last = l;
3842 } else if (l != NULL) {
3843 delete_Token(l->first);
3844 nasm_free(l);
3845 l = NULL;
3847 ed->prev = defining;
3848 defining = ed;
3849 free_tlist(origline);
3850 return DIRECTIVE_FOUND;
3852 case PP_ENDWHILE:
3853 if (defining != NULL) {
3854 if (defining->type == EXP_WHILE) {
3855 if (defining->def_depth > 0) {
3856 defining->def_depth --;
3857 return NO_DIRECTIVE_FOUND;
3859 } else {
3860 return NO_DIRECTIVE_FOUND;
3863 if (tline->next != NULL) {
3864 error_precond(ERR_WARNING|ERR_PASS1,
3865 "trailing garbage after `%%endwhile' ignored");
3867 if ((defining == NULL) || (defining->type != EXP_WHILE)) {
3868 error(ERR_NONFATAL, "`%%endwhile': no matching `%%while'");
3869 return DIRECTIVE_FOUND;
3871 ed = defining;
3872 defining = ed->prev;
3873 if (ed->ignoring == false) {
3874 ed->prev = expansions;
3875 expansions = ed;
3876 ei = new_ExpInv(EXP_WHILE, ed);
3877 ei->current = ed->line->next;
3878 ei->emitting = true;
3879 ei->prev = istk->expansion;
3880 istk->expansion = ei;
3881 } else {
3882 nasm_free(ed);
3884 free_tlist(origline);
3885 return DIRECTIVE_FOUND;
3887 case PP_EXITWHILE:
3888 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3890 * We must search along istk->expansion until we hit a
3891 * while invocation. Then we disable the emitting state(s)
3892 * between exitwhile and endwhile.
3894 for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
3895 if (ei->type == EXP_WHILE) {
3896 break;
3900 if (ei != NULL) {
3902 * Set all invocations leading back to the while
3903 * invocation to a non-emitting state.
3905 for (eei = istk->expansion; eei != ei; eei = eei->prev) {
3906 eei->emitting = false;
3908 eei->emitting = false;
3909 eei->current = NULL;
3910 eei->def->cur_depth = eei->def->max_depth;
3911 } else {
3912 error(ERR_NONFATAL, "`%%exitwhile' not within `%%while' block");
3914 free_tlist(origline);
3915 return DIRECTIVE_FOUND;
3917 case PP_COMMENT:
3918 if (defining != NULL) {
3919 if (defining->type == EXP_COMMENT) {
3920 defining->def_depth ++;
3922 return NO_DIRECTIVE_FOUND;
3924 ed = new_ExpDef(EXP_COMMENT);
3925 ed->ignoring = true;
3926 ed->prev = defining;
3927 defining = ed;
3928 free_tlist(origline);
3929 return DIRECTIVE_FOUND;
3931 case PP_ENDCOMMENT:
3932 if (defining != NULL) {
3933 if (defining->type == EXP_COMMENT) {
3934 if (defining->def_depth > 0) {
3935 defining->def_depth --;
3936 return NO_DIRECTIVE_FOUND;
3938 } else {
3939 return NO_DIRECTIVE_FOUND;
3942 if ((defining == NULL) || (defining->type != EXP_COMMENT)) {
3943 error(ERR_NONFATAL, "`%%endcomment': no matching `%%comment'");
3944 return DIRECTIVE_FOUND;
3946 ed = defining;
3947 defining = ed->prev;
3948 nasm_free(ed);
3949 free_tlist(origline);
3950 return DIRECTIVE_FOUND;
3952 case PP_FINAL:
3953 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3954 if (in_final != false) {
3955 error(ERR_FATAL, "`%%final' cannot be used recursively");
3957 tline = tline->next;
3958 skip_white_(tline);
3959 if (tline == NULL) {
3960 error(ERR_NONFATAL, "`%%final' expects at least one parameter");
3961 } else {
3962 l = new_Line();
3963 l->first = copy_Token(tline);
3964 l->next = finals;
3965 finals = l;
3967 free_tlist(origline);
3968 return DIRECTIVE_FOUND;
3970 default:
3971 error(ERR_FATAL,
3972 "preprocessor directive `%s' not yet implemented",
3973 pp_directives[i]);
3974 return DIRECTIVE_FOUND;
3979 * Ensure that a macro parameter contains a condition code and
3980 * nothing else. Return the condition code index if so, or -1
3981 * otherwise.
3983 static int find_cc(Token * t)
3985 Token *tt;
3986 int i, j, k, m;
3988 if (!t)
3989 return -1; /* Probably a %+ without a space */
3991 skip_white_(t);
3992 if (t->type != TOK_ID)
3993 return -1;
3994 tt = t->next;
3995 skip_white_(tt);
3996 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
3997 return -1;
3999 i = -1;
4000 j = ARRAY_SIZE(conditions);
4001 while (j - i > 1) {
4002 k = (j + i) / 2;
4003 m = nasm_stricmp(t->text, conditions[k]);
4004 if (m == 0) {
4005 i = k;
4006 j = -2;
4007 break;
4008 } else if (m < 0) {
4009 j = k;
4010 } else
4011 i = k;
4013 if (j != -2)
4014 return -1;
4015 return i;
4018 static bool paste_tokens(Token **head, const struct tokseq_match *m,
4019 int mnum, bool handle_paste_tokens)
4021 Token **tail, *t, *tt;
4022 Token **paste_head;
4023 bool did_paste = false;
4024 char *tmp;
4025 int i;
4027 nasm_dump_stream(*head);
4028 nasm_dump_token(*head);
4030 /* Now handle token pasting... */
4031 paste_head = NULL;
4032 tail = head;
4033 while ((t = *tail) && (tt = t->next)) {
4034 switch (t->type) {
4035 case TOK_WHITESPACE:
4036 if (tt->type == TOK_WHITESPACE) {
4037 /* Zap adjacent whitespace tokens */
4038 t->next = delete_Token(tt);
4039 } else {
4040 /* Do not advance paste_head here */
4041 tail = &t->next;
4043 break;
4044 case TOK_PASTE: /* %+ */
4045 if (handle_paste_tokens) {
4046 /* Zap %+ and whitespace tokens to the right */
4047 while (t && (t->type == TOK_WHITESPACE ||
4048 t->type == TOK_PASTE))
4049 t = *tail = delete_Token(t);
4050 if (!t) { /* Dangling %+ term */
4051 if (paste_head)
4052 (*paste_head)->next = NULL;
4053 else
4054 *head = NULL;
4055 return did_paste;
4057 tail = paste_head;
4058 t = *tail;
4059 tt = t->next;
4060 while (tok_type_(tt, TOK_WHITESPACE))
4061 tt = t->next = delete_Token(tt);
4062 if (tt) {
4063 tmp = nasm_strcat(t->text, tt->text);
4064 delete_Token(t);
4065 tt = delete_Token(tt);
4066 t = *tail = tokenize(tmp);
4067 nasm_free(tmp);
4068 while (t->next) {
4069 tail = &t->next;
4070 t = t->next;
4072 t->next = tt; /* Attach the remaining token chain */
4073 did_paste = true;
4075 paste_head = tail;
4076 tail = &t->next;
4077 break;
4079 /* else fall through */
4080 default:
4082 * Concatenation of tokens might look nontrivial
4083 * but in real it's pretty simple -- the caller
4084 * prepares the masks of token types to be concatenated
4085 * and we simply find matched sequences and slip
4086 * them together
4088 for (i = 0; i < mnum; i++) {
4089 if (PP_CONCAT_MASK(t->type) & m[i].mask_head) {
4090 size_t len = 0;
4091 char *tmp, *p;
4093 while (tt && (PP_CONCAT_MASK(tt->type) & m[i].mask_tail)) {
4094 len += strlen(tt->text);
4095 tt = tt->next;
4098 nasm_dump_token(tt);
4101 * Now tt points to the first token after
4102 * the potential paste area...
4104 if (tt != t->next) {
4105 /* We have at least two tokens... */
4106 len += strlen(t->text);
4107 p = tmp = nasm_malloc(len+1);
4108 while (t != tt) {
4109 strcpy(p, t->text);
4110 p = strchr(p, '\0');
4111 t = delete_Token(t);
4113 t = *tail = tokenize(tmp);
4114 nasm_free(tmp);
4115 while (t->next) {
4116 tail = &t->next;
4117 t = t->next;
4119 t->next = tt; /* Attach the remaining token chain */
4120 did_paste = true;
4122 paste_head = tail;
4123 tail = &t->next;
4124 break;
4127 if (i >= mnum) { /* no match */
4128 tail = &t->next;
4129 if (!tok_type_(t->next, TOK_WHITESPACE))
4130 paste_head = tail;
4132 break;
4135 return did_paste;
4139 * expands to a list of tokens from %{x:y}
4141 static Token *expand_mmac_params_range(ExpInv *ei, Token *tline, Token ***last)
4143 Token *t = tline, **tt, *tm, *head;
4144 char *pos;
4145 int fst, lst, j, i;
4147 pos = strchr(tline->text, ':');
4148 nasm_assert(pos);
4150 lst = atoi(pos + 1);
4151 fst = atoi(tline->text + 1);
4154 * only macros params are accounted so
4155 * if someone passes %0 -- we reject such
4156 * value(s)
4158 if (lst == 0 || fst == 0)
4159 goto err;
4161 /* the values should be sane */
4162 if ((fst > (int)ei->nparam || fst < (-(int)ei->nparam)) ||
4163 (lst > (int)ei->nparam || lst < (-(int)ei->nparam)))
4164 goto err;
4166 fst = fst < 0 ? fst + (int)ei->nparam + 1: fst;
4167 lst = lst < 0 ? lst + (int)ei->nparam + 1: lst;
4169 /* counted from zero */
4170 fst--, lst--;
4173 * it will be at least one token
4175 tm = ei->params[(fst + ei->rotate) % ei->nparam];
4176 t = new_Token(NULL, tm->type, tm->text, 0);
4177 head = t, tt = &t->next;
4178 if (fst < lst) {
4179 for (i = fst + 1; i <= lst; i++) {
4180 t = new_Token(NULL, TOK_OTHER, ",", 0);
4181 *tt = t, tt = &t->next;
4182 j = (i + ei->rotate) % ei->nparam;
4183 tm = ei->params[j];
4184 t = new_Token(NULL, tm->type, tm->text, 0);
4185 *tt = t, tt = &t->next;
4187 } else {
4188 for (i = fst - 1; i >= lst; i--) {
4189 t = new_Token(NULL, TOK_OTHER, ",", 0);
4190 *tt = t, tt = &t->next;
4191 j = (i + ei->rotate) % ei->nparam;
4192 tm = ei->params[j];
4193 t = new_Token(NULL, tm->type, tm->text, 0);
4194 *tt = t, tt = &t->next;
4198 *last = tt;
4199 return head;
4201 err:
4202 error(ERR_NONFATAL, "`%%{%s}': macro parameters out of range",
4203 &tline->text[1]);
4204 return tline;
4208 * Expand MMacro-local things: parameter references (%0, %n, %+n,
4209 * %-n) and MMacro-local identifiers (%%foo) as well as
4210 * macro indirection (%[...]) and range (%{..:..}).
4212 static Token *expand_mmac_params(Token * tline)
4214 Token *t, *tt, **tail, *thead;
4215 bool changed = false;
4216 char *pos;
4218 tail = &thead;
4219 thead = NULL;
4221 nasm_dump_stream(tline);
4223 while (tline) {
4224 if (tline->type == TOK_PREPROC_ID &&
4225 (((tline->text[1] == '+' || tline->text[1] == '-') && tline->text[2]) ||
4226 (tline->text[1] >= '0' && tline->text[1] <= '9') ||
4227 tline->text[1] == '%')) {
4228 char *text = NULL;
4229 int type = 0, cc; /* type = 0 to placate optimisers */
4230 char tmpbuf[30];
4231 unsigned int n;
4232 int i;
4233 ExpInv *ei;
4235 t = tline;
4236 tline = tline->next;
4238 for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
4239 if (ei->type == EXP_MMACRO) {
4240 break;
4243 if (ei == NULL) {
4244 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
4245 } else {
4246 pos = strchr(t->text, ':');
4247 if (!pos) {
4248 switch (t->text[1]) {
4250 * We have to make a substitution of one of the
4251 * forms %1, %-1, %+1, %%foo, %0.
4253 case '0':
4254 if ((strlen(t->text) > 2) && (t->text[2] == '0')) {
4255 type = TOK_ID;
4256 text = nasm_strdup(ei->label_text);
4257 } else {
4258 type = TOK_NUMBER;
4259 snprintf(tmpbuf, sizeof(tmpbuf), "%d", ei->nparam);
4260 text = nasm_strdup(tmpbuf);
4262 break;
4263 case '%':
4264 type = TOK_ID;
4265 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
4266 ei->unique);
4267 text = nasm_strcat(tmpbuf, t->text + 2);
4268 break;
4269 case '-':
4270 n = atoi(t->text + 2) - 1;
4271 if (n >= ei->nparam)
4272 tt = NULL;
4273 else {
4274 if (ei->nparam > 1)
4275 n = (n + ei->rotate) % ei->nparam;
4276 tt = ei->params[n];
4278 cc = find_cc(tt);
4279 if (cc == -1) {
4280 error(ERR_NONFATAL,
4281 "macro parameter %d is not a condition code",
4282 n + 1);
4283 text = NULL;
4284 } else {
4285 type = TOK_ID;
4286 if (inverse_ccs[cc] == -1) {
4287 error(ERR_NONFATAL,
4288 "condition code `%s' is not invertible",
4289 conditions[cc]);
4290 text = NULL;
4291 } else
4292 text = nasm_strdup(conditions[inverse_ccs[cc]]);
4294 break;
4295 case '+':
4296 n = atoi(t->text + 2) - 1;
4297 if (n >= ei->nparam)
4298 tt = NULL;
4299 else {
4300 if (ei->nparam > 1)
4301 n = (n + ei->rotate) % ei->nparam;
4302 tt = ei->params[n];
4304 cc = find_cc(tt);
4305 if (cc == -1) {
4306 error(ERR_NONFATAL,
4307 "macro parameter %d is not a condition code",
4308 n + 1);
4309 text = NULL;
4310 } else {
4311 type = TOK_ID;
4312 text = nasm_strdup(conditions[cc]);
4314 break;
4315 default:
4316 n = atoi(t->text + 1) - 1;
4317 if (n >= ei->nparam)
4318 tt = NULL;
4319 else {
4320 if (ei->nparam > 1)
4321 n = (n + ei->rotate) % ei->nparam;
4322 tt = ei->params[n];
4324 if (tt) {
4325 for (i = 0; i < ei->paramlen[n]; i++) {
4326 *tail = new_Token(NULL, tt->type, tt->text, 0);
4327 tail = &(*tail)->next;
4328 tt = tt->next;
4331 text = NULL; /* we've done it here */
4332 break;
4334 } else {
4336 * seems we have a parameters range here
4338 Token *head, **last;
4339 head = expand_mmac_params_range(ei, t, &last);
4340 if (head != t) {
4341 *tail = head;
4342 *last = tline;
4343 tline = head;
4344 text = NULL;
4348 if (!text) {
4349 delete_Token(t);
4350 } else {
4351 *tail = t;
4352 tail = &t->next;
4353 t->type = type;
4354 nasm_free(t->text);
4355 t->text = text;
4356 t->a.mac = NULL;
4358 changed = true;
4359 continue;
4360 } else if (tline->type == TOK_INDIRECT) {
4361 t = tline;
4362 tline = tline->next;
4363 tt = tokenize(t->text);
4364 tt = expand_mmac_params(tt);
4365 tt = expand_smacro(tt);
4366 *tail = tt;
4367 while (tt) {
4368 tt->a.mac = NULL; /* Necessary? */
4369 tail = &tt->next;
4370 tt = tt->next;
4372 delete_Token(t);
4373 changed = true;
4374 } else {
4375 t = *tail = tline;
4376 tline = tline->next;
4377 t->a.mac = NULL;
4378 tail = &t->next;
4381 *tail = NULL;
4383 if (changed) {
4384 const struct tokseq_match t[] = {
4386 PP_CONCAT_MASK(TOK_ID) |
4387 PP_CONCAT_MASK(TOK_FLOAT), /* head */
4388 PP_CONCAT_MASK(TOK_ID) |
4389 PP_CONCAT_MASK(TOK_NUMBER) |
4390 PP_CONCAT_MASK(TOK_FLOAT) |
4391 PP_CONCAT_MASK(TOK_OTHER) /* tail */
4394 PP_CONCAT_MASK(TOK_NUMBER), /* head */
4395 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
4398 paste_tokens(&thead, t, ARRAY_SIZE(t), false);
4401 nasm_dump_token(thead);
4403 return thead;
4407 * Expand all single-line macro calls made in the given line.
4408 * Return the expanded version of the line. The original is deemed
4409 * to be destroyed in the process. (In reality we'll just move
4410 * Tokens from input to output a lot of the time, rather than
4411 * actually bothering to destroy and replicate.)
4414 static Token *expand_smacro(Token * tline)
4416 Token *t, *tt, *mstart, **tail, *thead;
4417 SMacro *head = NULL, *m;
4418 Token **params;
4419 int *paramsize;
4420 unsigned int nparam, sparam;
4421 int brackets;
4422 Token *org_tline = tline;
4423 Context *ctx;
4424 const char *mname;
4425 int deadman = DEADMAN_LIMIT;
4426 bool expanded;
4429 * Trick: we should avoid changing the start token pointer since it can
4430 * be contained in "next" field of other token. Because of this
4431 * we allocate a copy of first token and work with it; at the end of
4432 * routine we copy it back
4434 if (org_tline) {
4435 tline = new_Token(org_tline->next, org_tline->type,
4436 org_tline->text, 0);
4437 tline->a.mac = org_tline->a.mac;
4438 nasm_free(org_tline->text);
4439 org_tline->text = NULL;
4442 expanded = true; /* Always expand %+ at least once */
4444 again:
4445 thead = NULL;
4446 tail = &thead;
4448 while (tline) { /* main token loop */
4449 if (!--deadman) {
4450 error(ERR_NONFATAL, "interminable macro recursion");
4451 goto err;
4454 if ((mname = tline->text)) {
4455 /* if this token is a local macro, look in local context */
4456 if (tline->type == TOK_ID) {
4457 head = (SMacro *)hash_findix(&smacros, mname);
4458 } else if (tline->type == TOK_PREPROC_ID) {
4459 ctx = get_ctx(mname, &mname);
4460 head = ctx ? (SMacro *)hash_findix(&ctx->localmac, mname) : NULL;
4461 } else
4462 head = NULL;
4465 * We've hit an identifier. As in is_mmacro below, we first
4466 * check whether the identifier is a single-line macro at
4467 * all, then think about checking for parameters if
4468 * necessary.
4470 list_for_each(m, head) {
4471 if (!mstrcmp(m->name, mname, m->casesense))
4472 break;
4474 if (m) {
4475 mstart = tline;
4476 params = NULL;
4477 paramsize = NULL;
4478 if (m->nparam == 0) {
4480 * Simple case: the macro is parameterless. Discard the
4481 * one token that the macro call took, and push the
4482 * expansion back on the to-do stack.
4484 if (!m->expansion) {
4485 if (!strcmp("__FILE__", m->name)) {
4486 int32_t num = 0;
4487 char *file = NULL;
4488 src_get(&num, &file);
4489 tline->text = nasm_quote(file, strlen(file));
4490 tline->type = TOK_STRING;
4491 nasm_free(file);
4492 continue;
4494 if (!strcmp("__LINE__", m->name)) {
4495 nasm_free(tline->text);
4496 make_tok_num(tline, src_get_linnum());
4497 continue;
4499 if (!strcmp("__BITS__", m->name)) {
4500 nasm_free(tline->text);
4501 make_tok_num(tline, globalbits);
4502 continue;
4504 tline = delete_Token(tline);
4505 continue;
4507 } else {
4509 * Complicated case: at least one macro with this name
4510 * exists and takes parameters. We must find the
4511 * parameters in the call, count them, find the SMacro
4512 * that corresponds to that form of the macro call, and
4513 * substitute for the parameters when we expand. What a
4514 * pain.
4516 /*tline = tline->next;
4517 skip_white_(tline); */
4518 do {
4519 t = tline->next;
4520 while (tok_type_(t, TOK_SMAC_END)) {
4521 t->a.mac->in_progress = false;
4522 t->text = NULL;
4523 t = tline->next = delete_Token(t);
4525 tline = t;
4526 } while (tok_type_(tline, TOK_WHITESPACE));
4527 if (!tok_is_(tline, "(")) {
4529 * This macro wasn't called with parameters: ignore
4530 * the call. (Behaviour borrowed from gnu cpp.)
4532 tline = mstart;
4533 m = NULL;
4534 } else {
4535 int paren = 0;
4536 int white = 0;
4537 brackets = 0;
4538 nparam = 0;
4539 sparam = PARAM_DELTA;
4540 params = nasm_malloc(sparam * sizeof(Token *));
4541 params[0] = tline->next;
4542 paramsize = nasm_malloc(sparam * sizeof(int));
4543 paramsize[0] = 0;
4544 while (true) { /* parameter loop */
4546 * For some unusual expansions
4547 * which concatenates function call
4549 t = tline->next;
4550 while (tok_type_(t, TOK_SMAC_END)) {
4551 t->a.mac->in_progress = false;
4552 t->text = NULL;
4553 t = tline->next = delete_Token(t);
4555 tline = t;
4557 if (!tline) {
4558 error(ERR_NONFATAL,
4559 "macro call expects terminating `)'");
4560 break;
4562 if (tline->type == TOK_WHITESPACE
4563 && brackets <= 0) {
4564 if (paramsize[nparam])
4565 white++;
4566 else
4567 params[nparam] = tline->next;
4568 continue; /* parameter loop */
4570 if (tline->type == TOK_OTHER
4571 && tline->text[1] == 0) {
4572 char ch = tline->text[0];
4573 if (ch == ',' && !paren && brackets <= 0) {
4574 if (++nparam >= sparam) {
4575 sparam += PARAM_DELTA;
4576 params = nasm_realloc(params,
4577 sparam * sizeof(Token *));
4578 paramsize = nasm_realloc(paramsize,
4579 sparam * sizeof(int));
4581 params[nparam] = tline->next;
4582 paramsize[nparam] = 0;
4583 white = 0;
4584 continue; /* parameter loop */
4586 if (ch == '{' &&
4587 (brackets > 0 || (brackets == 0 &&
4588 !paramsize[nparam])))
4590 if (!(brackets++)) {
4591 params[nparam] = tline->next;
4592 continue; /* parameter loop */
4595 if (ch == '}' && brackets > 0)
4596 if (--brackets == 0) {
4597 brackets = -1;
4598 continue; /* parameter loop */
4600 if (ch == '(' && !brackets)
4601 paren++;
4602 if (ch == ')' && brackets <= 0)
4603 if (--paren < 0)
4604 break;
4606 if (brackets < 0) {
4607 brackets = 0;
4608 error(ERR_NONFATAL, "braces do not "
4609 "enclose all of macro parameter");
4611 paramsize[nparam] += white + 1;
4612 white = 0;
4613 } /* parameter loop */
4614 nparam++;
4615 while (m && (m->nparam != nparam ||
4616 mstrcmp(m->name, mname,
4617 m->casesense)))
4618 m = m->next;
4619 if (!m)
4620 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
4621 "macro `%s' exists, "
4622 "but not taking %d parameters",
4623 mstart->text, nparam);
4626 if (m && m->in_progress)
4627 m = NULL;
4628 if (!m) { /* in progess or didn't find '(' or wrong nparam */
4630 * Design question: should we handle !tline, which
4631 * indicates missing ')' here, or expand those
4632 * macros anyway, which requires the (t) test a few
4633 * lines down?
4635 nasm_free(params);
4636 nasm_free(paramsize);
4637 tline = mstart;
4638 } else {
4640 * Expand the macro: we are placed on the last token of the
4641 * call, so that we can easily split the call from the
4642 * following tokens. We also start by pushing an SMAC_END
4643 * token for the cycle removal.
4645 t = tline;
4646 if (t) {
4647 tline = t->next;
4648 t->next = NULL;
4650 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
4651 tt->a.mac = m;
4652 m->in_progress = true;
4653 tline = tt;
4654 list_for_each(t, m->expansion) {
4655 if (is_smacro_param(t)) {
4656 Token *pcopy = tline, **ptail = &pcopy;
4657 Token *ttt;
4658 int i, idx;
4660 idx = smacro_get_param_idx(t);
4661 ttt = params[idx];
4664 * We need smacro paramters appended.
4666 for (i = paramsize[idx]; i > 0; i--) {
4667 *ptail = new_Token(tline, ttt->type, ttt->text, 0);
4668 ptail = &(*ptail)->next;
4669 ttt = ttt->next;
4672 tline = pcopy;
4673 } else if (t->type == TOK_PREPROC_Q) {
4674 tt = new_Token(tline, TOK_ID, mname, 0);
4675 tline = tt;
4676 } else if (t->type == TOK_PREPROC_QQ) {
4677 tt = new_Token(tline, TOK_ID, m->name, 0);
4678 tline = tt;
4679 } else {
4680 tt = new_Token(tline, t->type, t->text, 0);
4681 tline = tt;
4686 * Having done that, get rid of the macro call, and clean
4687 * up the parameters.
4689 nasm_free(params);
4690 nasm_free(paramsize);
4691 free_tlist(mstart);
4692 expanded = true;
4693 continue; /* main token loop */
4698 if (tline->type == TOK_SMAC_END) {
4699 tline->a.mac->in_progress = false;
4700 tline = delete_Token(tline);
4701 } else {
4702 t = *tail = tline;
4703 tline = tline->next;
4704 t->a.mac = NULL;
4705 t->next = NULL;
4706 tail = &t->next;
4711 * Now scan the entire line and look for successive TOK_IDs that resulted
4712 * after expansion (they can't be produced by tokenize()). The successive
4713 * TOK_IDs should be concatenated.
4714 * Also we look for %+ tokens and concatenate the tokens before and after
4715 * them (without white spaces in between).
4717 if (expanded) {
4718 const struct tokseq_match t[] = {
4720 PP_CONCAT_MASK(TOK_ID) |
4721 PP_CONCAT_MASK(TOK_PREPROC_ID), /* head */
4722 PP_CONCAT_MASK(TOK_ID) |
4723 PP_CONCAT_MASK(TOK_PREPROC_ID) |
4724 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
4727 if (paste_tokens(&thead, t, ARRAY_SIZE(t), true)) {
4729 * If we concatenated something, *and* we had previously expanded
4730 * an actual macro, scan the lines again for macros...
4732 tline = thead;
4733 expanded = false;
4734 goto again;
4738 err:
4739 if (org_tline) {
4740 if (thead) {
4741 *org_tline = *thead;
4742 /* since we just gave text to org_line, don't free it */
4743 thead->text = NULL;
4744 delete_Token(thead);
4745 } else {
4746 /* the expression expanded to empty line;
4747 we can't return NULL for some reasons
4748 we just set the line to a single WHITESPACE token. */
4749 memset(org_tline, 0, sizeof(*org_tline));
4750 org_tline->text = NULL;
4751 org_tline->type = TOK_WHITESPACE;
4753 thead = org_tline;
4756 return thead;
4760 * Similar to expand_smacro but used exclusively with macro identifiers
4761 * right before they are fetched in. The reason is that there can be
4762 * identifiers consisting of several subparts. We consider that if there
4763 * are more than one element forming the name, user wants a expansion,
4764 * otherwise it will be left as-is. Example:
4766 * %define %$abc cde
4768 * the identifier %$abc will be left as-is so that the handler for %define
4769 * will suck it and define the corresponding value. Other case:
4771 * %define _%$abc cde
4773 * In this case user wants name to be expanded *before* %define starts
4774 * working, so we'll expand %$abc into something (if it has a value;
4775 * otherwise it will be left as-is) then concatenate all successive
4776 * PP_IDs into one.
4778 static Token *expand_id(Token * tline)
4780 Token *cur, *oldnext = NULL;
4782 if (!tline || !tline->next)
4783 return tline;
4785 cur = tline;
4786 while (cur->next &&
4787 (cur->next->type == TOK_ID ||
4788 cur->next->type == TOK_PREPROC_ID ||
4789 cur->next->type == TOK_NUMBER))
4790 cur = cur->next;
4792 /* If identifier consists of just one token, don't expand */
4793 if (cur == tline)
4794 return tline;
4796 if (cur) {
4797 oldnext = cur->next; /* Detach the tail past identifier */
4798 cur->next = NULL; /* so that expand_smacro stops here */
4801 tline = expand_smacro(tline);
4803 if (cur) {
4804 /* expand_smacro possibly changhed tline; re-scan for EOL */
4805 cur = tline;
4806 while (cur && cur->next)
4807 cur = cur->next;
4808 if (cur)
4809 cur->next = oldnext;
4812 return tline;
4816 * Determine whether the given line constitutes a multi-line macro
4817 * call, and return the ExpDef structure called if so. Doesn't have
4818 * to check for an initial label - that's taken care of in
4819 * expand_mmacro - but must check numbers of parameters. Guaranteed
4820 * to be called with tline->type == TOK_ID, so the putative macro
4821 * name is easy to find.
4823 static ExpDef *is_mmacro(Token * tline, Token *** params_array)
4825 ExpDef *head, *ed;
4826 Token **params;
4827 int nparam;
4829 head = (ExpDef *) hash_findix(&expdefs, tline->text);
4832 * Efficiency: first we see if any macro exists with the given
4833 * name. If not, we can return NULL immediately. _Then_ we
4834 * count the parameters, and then we look further along the
4835 * list if necessary to find the proper ExpDef.
4837 list_for_each(ed, head) {
4838 if (!mstrcmp(ed->name, tline->text, ed->casesense))
4839 break;
4841 if (!ed)
4842 return NULL;
4845 * OK, we have a potential macro. Count and demarcate the
4846 * parameters.
4848 count_mmac_params(tline->next, &nparam, &params);
4851 * So we know how many parameters we've got. Find the ExpDef
4852 * structure that handles this number.
4854 while (ed) {
4855 if (ed->nparam_min <= nparam
4856 && (ed->plus || nparam <= ed->nparam_max)) {
4858 * It's right, and we can use it. Add its default
4859 * parameters to the end of our list if necessary.
4861 if (ed->defaults && nparam < ed->nparam_min + ed->ndefs) {
4862 params =
4863 nasm_realloc(params,
4864 ((ed->nparam_min + ed->ndefs +
4865 1) * sizeof(*params)));
4866 while (nparam < ed->nparam_min + ed->ndefs) {
4867 params[nparam] = ed->defaults[nparam - ed->nparam_min];
4868 nparam++;
4872 * If we've gone over the maximum parameter count (and
4873 * we're in Plus mode), ignore parameters beyond
4874 * nparam_max.
4876 if (ed->plus && nparam > ed->nparam_max)
4877 nparam = ed->nparam_max;
4879 * Then terminate the parameter list, and leave.
4881 if (!params) { /* need this special case */
4882 params = nasm_malloc(sizeof(*params));
4883 nparam = 0;
4885 params[nparam] = NULL;
4886 *params_array = params;
4887 return ed;
4890 * This one wasn't right: look for the next one with the
4891 * same name.
4893 list_for_each(ed, ed->next) {
4894 if (!mstrcmp(ed->name, tline->text, ed->casesense))
4895 break;
4900 * After all that, we didn't find one with the right number of
4901 * parameters. Issue a warning, and fail to expand the macro.
4903 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
4904 "macro `%s' exists, but not taking %d parameters",
4905 tline->text, nparam);
4906 nasm_free(params);
4907 return NULL;
4911 * Expand the multi-line macro call made by the given line, if
4912 * there is one to be expanded. If there is, push the expansion on
4913 * istk->expansion and return true. Otherwise return false.
4915 static bool expand_mmacro(Token * tline)
4917 Token *label = NULL;
4918 int dont_prepend = 0;
4919 Token **params, *t;
4920 Line *l = NULL;
4921 ExpDef *ed;
4922 ExpInv *ei;
4923 int i, nparam, *paramlen;
4924 const char *mname;
4926 t = tline;
4927 skip_white_(t);
4928 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4929 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
4930 return false;
4931 ed = is_mmacro(t, &params);
4932 if (ed != NULL) {
4933 mname = t->text;
4934 } else {
4935 Token *last;
4937 * We have an id which isn't a macro call. We'll assume
4938 * it might be a label; we'll also check to see if a
4939 * colon follows it. Then, if there's another id after
4940 * that lot, we'll check it again for macro-hood.
4942 label = last = t;
4943 t = t->next;
4944 if (tok_type_(t, TOK_WHITESPACE))
4945 last = t, t = t->next;
4946 if (tok_is_(t, ":")) {
4947 dont_prepend = 1;
4948 last = t, t = t->next;
4949 if (tok_type_(t, TOK_WHITESPACE))
4950 last = t, t = t->next;
4952 if (!tok_type_(t, TOK_ID) || !(ed = is_mmacro(t, &params)))
4953 return false;
4954 last->next = NULL;
4955 mname = t->text;
4956 tline = t;
4960 * Fix up the parameters: this involves stripping leading and
4961 * trailing whitespace, then stripping braces if they are
4962 * present.
4964 for (nparam = 0; params[nparam]; nparam++)
4966 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
4968 for (i = 0; params[i]; i++) {
4969 int brace = false;
4970 int comma = (!ed->plus || i < nparam - 1);
4972 t = params[i];
4973 skip_white_(t);
4974 if (tok_is_(t, "{"))
4975 t = t->next, brace = true, comma = false;
4976 params[i] = t;
4977 paramlen[i] = 0;
4978 while (t) {
4979 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
4980 break; /* ... because we have hit a comma */
4981 if (comma && t->type == TOK_WHITESPACE
4982 && tok_is_(t->next, ","))
4983 break; /* ... or a space then a comma */
4984 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
4985 break; /* ... or a brace */
4986 t = t->next;
4987 paramlen[i]++;
4991 if (ed->cur_depth >= ed->max_depth) {
4992 if (ed->max_depth > 1) {
4993 error(ERR_WARNING,
4994 "reached maximum macro recursion depth of %i for %s",
4995 ed->max_depth,ed->name);
4997 return false;
4998 } else {
4999 ed->cur_depth ++;
5003 * OK, we have found a ExpDef structure representing a
5004 * previously defined mmacro. Create an expansion invocation
5005 * and point it back to the expansion definition. Substitution of
5006 * parameter tokens and macro-local tokens doesn't get done
5007 * until the single-line macro substitution process; this is
5008 * because delaying them allows us to change the semantics
5009 * later through %rotate.
5011 ei = new_ExpInv(EXP_MMACRO, ed);
5012 ei->name = nasm_strdup(mname);
5013 //ei->label = label;
5014 //ei->label_text = detoken(label, false);
5015 ei->current = ed->line;
5016 ei->emitting = true;
5017 //ei->iline = tline;
5018 ei->params = params;
5019 ei->nparam = nparam;
5020 ei->rotate = 0;
5021 ei->paramlen = paramlen;
5022 ei->lineno = 0;
5024 ei->prev = istk->expansion;
5025 istk->expansion = ei;
5028 * Special case: detect %00 on first invocation; if found,
5029 * avoid emitting any labels that precede the mmacro call.
5030 * ed->prepend is set to -1 when %00 is detected, else 1.
5032 if (ed->prepend == 0) {
5033 for (l = ed->line; l != NULL; l = l->next) {
5034 for (t = l->first; t != NULL; t = t->next) {
5035 if ((t->type == TOK_PREPROC_ID) &&
5036 (strlen(t->text) == 3) &&
5037 (t->text[1] == '0') && (t->text[2] == '0')) {
5038 dont_prepend = -1;
5039 break;
5042 if (dont_prepend < 0)
5043 break;
5045 ed->prepend = ((dont_prepend < 0) ? -1 : 1);
5049 * If we had a label, push it on as the first line of
5050 * the macro expansion.
5052 if (label != NULL) {
5053 if (ed->prepend < 0) {
5054 ei->label_text = detoken(label, false);
5055 } else {
5056 if (dont_prepend == 0) {
5057 t = label;
5058 while (t->next != NULL) {
5059 t = t->next;
5061 t->next = new_Token(NULL, TOK_OTHER, ":", 0);
5063 l = new_Line();
5064 l->first = copy_Token(label);
5065 l->next = ei->current;
5066 ei->current = l;
5070 list->uplevel(ed->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
5072 istk->mmac_depth++;
5073 return true;
5076 /* The function that actually does the error reporting */
5077 static void verror(int severity, const char *fmt, va_list arg)
5079 char buff[1024];
5081 vsnprintf(buff, sizeof(buff), fmt, arg);
5083 if (istk && istk->mmac_depth > 0) {
5084 ExpInv *ei = istk->expansion;
5085 int lineno = ei->lineno;
5086 while (ei) {
5087 if (ei->type == EXP_MMACRO)
5088 break;
5089 lineno += ei->relno;
5090 ei = ei->prev;
5092 nasm_error(severity, "(%s:%d) %s", ei->def->name,
5093 lineno, buff);
5094 } else {
5095 nasm_error(severity, "%s", buff);
5100 * Since preprocessor always operate only on the line that didn't
5101 * arrived yet, we should always use ERR_OFFBY1.
5103 static void error(int severity, const char *fmt, ...)
5105 va_list arg;
5106 va_start(arg, fmt);
5107 verror(severity, fmt, arg);
5108 va_end(arg);
5112 * Because %else etc are evaluated in the state context
5113 * of the previous branch, errors might get lost with error():
5114 * %if 0 ... %else trailing garbage ... %endif
5115 * So %else etc should report errors with this function.
5117 static void error_precond(int severity, const char *fmt, ...)
5119 va_list arg;
5121 /* Only ignore the error if it's really in a dead branch */
5122 if ((istk != NULL) &&
5123 (istk->expansion != NULL) &&
5124 (istk->expansion->type == EXP_IF) &&
5125 (istk->expansion->def->state == COND_NEVER))
5126 return;
5128 va_start(arg, fmt);
5129 verror(severity, fmt, arg);
5130 va_end(arg);
5133 static void
5134 pp_reset(char *file, int apass, ListGen * listgen, StrList **deplist)
5136 Token *t;
5138 cstk = NULL;
5139 istk = nasm_zalloc(sizeof(Include));
5140 istk->fp = fopen(file, "r");
5141 src_set_fname(nasm_strdup(file));
5142 src_set_linnum(0);
5143 istk->lineinc = 1;
5144 if (!istk->fp)
5145 error(ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'",
5146 file);
5147 defining = NULL;
5148 finals = NULL;
5149 in_final = false;
5150 nested_mac_count = 0;
5151 nested_rep_count = 0;
5152 init_macros();
5153 unique = 0;
5154 if (tasm_compatible_mode)
5155 stdmacpos = nasm_stdmac;
5156 else
5157 stdmacpos = nasm_stdmac_after_tasm;
5158 any_extrastdmac = extrastdmac && *extrastdmac;
5159 do_predef = true;
5160 list = listgen;
5163 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
5164 * The caller, however, will also pass in 3 for preprocess-only so
5165 * we can set __PASS__ accordingly.
5167 pass = apass > 2 ? 2 : apass;
5169 dephead = deptail = deplist;
5170 if (deplist) {
5171 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
5172 sl->next = NULL;
5173 strcpy(sl->str, file);
5174 *deptail = sl;
5175 deptail = &sl->next;
5179 * Define the __PASS__ macro. This is defined here unlike
5180 * all the other builtins, because it is special -- it varies between
5181 * passes.
5183 t = nasm_zalloc(sizeof(*t));
5184 make_tok_num(t, apass);
5185 define_smacro(NULL, "__PASS__", true, 0, t);
5188 static char *pp_getline(void)
5190 char *line;
5191 Token *tline;
5192 ExpDef *ed;
5193 ExpInv *ei;
5194 Line *l;
5195 int j;
5197 while (1) {
5199 * Fetch a tokenized line, either from the expansion
5200 * buffer or from the input file.
5202 tline = NULL;
5204 while (1) { /* until we get a line we can use */
5206 * Fetch a tokenized line from the expansion buffer
5208 if (istk->expansion != NULL) {
5209 ei = istk->expansion;
5210 if (ei->current != NULL) {
5211 if (ei->emitting == false) {
5212 ei->current = NULL;
5213 continue;
5215 l = ei->current;
5216 ei->current = l->next;
5217 ei->lineno++;
5218 tline = copy_Token(l->first);
5219 if (((ei->type == EXP_REP) ||
5220 (ei->type == EXP_MMACRO) ||
5221 (ei->type == EXP_WHILE))
5222 && (ei->def->nolist == false)) {
5223 char *p = detoken(tline, false);
5224 list->line(LIST_MACRO, p);
5225 nasm_free(p);
5227 if (ei->linnum > -1) {
5228 src_set_linnum(src_get_linnum() + 1);
5230 break;
5231 } else if ((ei->type == EXP_REP) &&
5232 (ei->def->cur_depth < ei->def->max_depth)) {
5233 ei->def->cur_depth ++;
5234 ei->current = ei->def->line;
5235 ei->lineno = 0;
5236 continue;
5237 } else if ((ei->type == EXP_WHILE) &&
5238 (ei->def->cur_depth < ei->def->max_depth)) {
5239 ei->current = ei->def->line;
5240 ei->lineno = 0;
5241 tline = copy_Token(ei->current->first);
5242 j = if_condition(tline, PP_WHILE);
5243 tline = NULL;
5244 j = (((j < 0) ? COND_NEVER : j) ? COND_IF_TRUE : COND_IF_FALSE);
5245 if (j == COND_IF_TRUE) {
5246 ei->current = ei->current->next;
5247 ei->def->cur_depth ++;
5248 } else {
5249 ei->emitting = false;
5250 ei->current = NULL;
5251 ei->def->cur_depth = ei->def->max_depth;
5253 continue;
5254 } else {
5255 istk->expansion = ei->prev;
5256 ed = ei->def;
5257 if (ed != NULL) {
5258 if ((ei->emitting == true) &&
5259 (ed->max_depth == DEADMAN_LIMIT) &&
5260 (ed->cur_depth == DEADMAN_LIMIT)
5262 error(ERR_FATAL, "runaway expansion detected, aborting");
5264 if (ed->cur_depth > 0) {
5265 ed->cur_depth --;
5266 } else if (ed->type != EXP_MMACRO) {
5267 expansions = ed->prev;
5268 free_expdef(ed);
5270 if ((ei->type == EXP_REP) ||
5271 (ei->type == EXP_MMACRO) ||
5272 (ei->type == EXP_WHILE)) {
5273 list->downlevel(LIST_MACRO);
5274 if (ei->type == EXP_MMACRO) {
5275 istk->mmac_depth--;
5279 if (ei->linnum > -1) {
5280 src_set_linnum(ei->linnum);
5282 free_expinv(ei);
5283 continue;
5288 * Read in line from input and tokenize
5290 line = read_line();
5291 if (line) { /* from the current input file */
5292 line = prepreproc(line);
5293 tline = tokenize(line);
5294 nasm_free(line);
5295 break;
5299 * The current file has ended; work down the istk
5302 Include *i = istk;
5303 fclose(i->fp);
5304 if (i->expansion != NULL) {
5305 error(ERR_FATAL,
5306 "end of file while still in an expansion");
5308 /* only set line and file name if there's a next node */
5309 if (i->next) {
5310 src_set_linnum(i->lineno);
5311 nasm_free(src_set_fname(nasm_strdup(i->fname)));
5313 if ((i->next == NULL) && (finals != NULL)) {
5314 in_final = true;
5315 ei = new_ExpInv(EXP_FINAL, NULL);
5316 ei->emitting = true;
5317 ei->current = finals;
5318 istk->expansion = ei;
5319 finals = NULL;
5320 continue;
5322 istk = i->next;
5323 list->downlevel(LIST_INCLUDE);
5324 nasm_free(i);
5325 if (istk == NULL) {
5326 if (finals != NULL)
5327 in_final = true;
5328 else
5329 return NULL;
5331 continue;
5335 if (defining == NULL)
5336 tline = expand_mmac_params(tline);
5339 * Check the line to see if it's a preprocessor directive.
5341 if (do_directive(tline) == DIRECTIVE_FOUND) {
5342 continue;
5343 } else if (defining != NULL) {
5345 * We're defining an expansion. We emit nothing at all,
5346 * and just shove the tokenized line on to the definition.
5348 if (defining->ignoring == false) {
5349 Line *l = new_Line();
5350 l->first = tline;
5351 if (defining->line == NULL) {
5352 defining->line = l;
5353 defining->last = l;
5354 } else {
5355 defining->last->next = l;
5356 defining->last = l;
5358 } else {
5359 free_tlist(tline);
5361 defining->linecount++;
5362 continue;
5363 } else if ((istk->expansion != NULL) &&
5364 (istk->expansion->emitting != true)) {
5366 * We're in a non-emitting branch of an expansion.
5367 * Emit nothing at all, not even a blank line: when we
5368 * emerge from the expansion we'll give a line-number
5369 * directive so we keep our place correctly.
5371 free_tlist(tline);
5372 continue;
5373 } else {
5374 tline = expand_smacro(tline);
5375 if (expand_mmacro(tline) != true) {
5377 * De-tokenize the line again, and emit it.
5379 line = detoken(tline, true);
5380 free_tlist(tline);
5381 break;
5382 } else {
5383 continue;
5387 return line;
5390 static void pp_cleanup(int pass)
5392 if (defining != NULL) {
5393 error(ERR_NONFATAL, "end of file while still defining an expansion");
5394 while (defining != NULL) {
5395 ExpDef *ed = defining;
5396 defining = ed->prev;
5397 free_expdef(ed);
5399 defining = NULL;
5401 while (cstk != NULL)
5402 ctx_pop();
5403 free_macros();
5404 while (istk != NULL) {
5405 Include *i = istk;
5406 istk = istk->next;
5407 fclose(i->fp);
5408 nasm_free(i->fname);
5409 while (i->expansion != NULL) {
5410 ExpInv *ei = i->expansion;
5411 i->expansion = ei->prev;
5412 free_expinv(ei);
5414 nasm_free(i);
5416 while (cstk)
5417 ctx_pop();
5418 nasm_free(src_set_fname(NULL));
5419 if (pass == 0) {
5420 IncPath *i;
5421 free_llist(predef);
5422 delete_Blocks();
5423 while ((i = ipath)) {
5424 ipath = i->next;
5425 nasm_free(i->path);
5426 nasm_free(i);
5431 void pp_include_path(char *path)
5433 IncPath *i = nasm_zalloc(sizeof(IncPath));
5435 if (path)
5436 i->path = nasm_strdup(path);
5438 if (ipath) {
5439 IncPath *j = ipath;
5440 while (j->next)
5441 j = j->next;
5442 j->next = i;
5443 } else {
5444 ipath = i;
5448 void pp_pre_include(char *fname)
5450 Token *inc, *space, *name;
5451 Line *l;
5453 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
5454 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
5455 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
5457 l = new_Line();
5458 l->next = predef;
5459 l->first = inc;
5460 predef = l;
5463 void pp_pre_define(char *definition)
5465 Token *def, *space;
5466 Line *l;
5467 char *equals;
5469 equals = strchr(definition, '=');
5470 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
5471 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
5472 if (equals)
5473 *equals = ' ';
5474 space->next = tokenize(definition);
5475 if (equals)
5476 *equals = '=';
5478 l = new_Line();
5479 l->next = predef;
5480 l->first = def;
5481 predef = l;
5484 void pp_pre_undefine(char *definition)
5486 Token *def, *space;
5487 Line *l;
5489 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
5490 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
5491 space->next = tokenize(definition);
5493 l = new_Line();
5494 l->next = predef;
5495 l->first = def;
5496 predef = l;
5500 * This function is used to assist with "runtime" preprocessor
5501 * directives, e.g. pp_runtime("%define __BITS__ 64");
5503 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5504 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5507 void pp_runtime(char *definition)
5509 Token *def;
5511 def = tokenize(definition);
5512 if (do_directive(def) == NO_DIRECTIVE_FOUND)
5513 free_tlist(def);
5517 void pp_extra_stdmac(macros_t *macros)
5519 extrastdmac = macros;
5522 static void make_tok_num(Token * tok, int64_t val)
5524 char numbuf[20];
5525 snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
5526 tok->text = nasm_strdup(numbuf);
5527 tok->type = TOK_NUMBER;
5530 struct preproc_ops nasmpp = {
5531 pp_reset,
5532 pp_getline,
5533 pp_cleanup