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