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
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
46 * read_line gets raw text from stdmacpos, or predef, or current input file
47 * tokenize converts to tokens
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
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.
117 * The context stack is composed of a linked list of these.
122 struct hash_table localmac;
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
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.
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,
150 TOK_PREPROC_Q, TOK_PREPROC_QQ,
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 {
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
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.
193 EXP_NONE = 0, EXP_PREDEF,
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.
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;
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 */
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.
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;
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.
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.
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.)
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)
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"
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,
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.
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
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;
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,
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))))
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);
510 list_for_each(t, token) {
512 printf("'%s' ", t->text);
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);
531 error(ERR_NONFATAL, "NUL character in `%s' directive",
532 pp_directives[directive]);
538 * In-place reverse a list of tokens.
540 static Token *reverse_tokens(Token *t)
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 */
570 j = ARRAY_SIZE(tasm_directives);
571 q = nasm_skip_word(p);
578 m = nasm_stricmp(p, tasm_directives[k]);
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.
586 line = nasm_malloc(len + 2);
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");
597 memcpy(line + 1, p, len + 1);
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
617 static char *prepreproc(char *line)
620 char *fname, *oldline;
622 if (line[0] == '#' && line[1] == ' ') {
625 lineno = atoi(fname);
626 fname += strspn(fname, "0123456789 ");
629 fnlen = strcspn(fname, "\"");
630 line = nasm_malloc(20 + fnlen);
631 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
634 if (tasm_compatible_mode)
635 return check_tasm_directive(line);
640 * Free a linked list of tokens.
642 static void free_tlist(Token * list)
645 list = delete_Token(list);
649 * Free a linked list of lines.
651 static void free_llist(Line * list)
654 list_for_each_safe(l, tmp, list) {
655 free_tlist(l->first);
663 static void free_expdef(ExpDef * ed)
666 free_tlist(ed->dlist);
667 nasm_free(ed->defaults);
668 free_llist(ed->line);
675 static void free_expinv(ExpInv * ei)
677 if (ei->name != NULL)
679 if (ei->label_text != NULL)
680 nasm_free(ei->label_text);
685 * Free all currently defined macros, and free the hash tables
687 static void free_smacro_table(struct hash_table *smt)
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) {
697 free_tlist(s->expansion);
704 static void free_expdef_table(struct hash_table *edt)
708 struct hash_tbl_node *it = NULL;
711 while ((ed = hash_iterate(edt, &it, &key)) != NULL) {
712 nasm_free((void *)key);
713 list_for_each_safe(ed ,tmp, ed)
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)
742 free_smacro_table(&c->localmac);
748 * Search for a key in the hash index; adding it if necessary
749 * (in which case we initialize the data pointer to NULL.)
752 hash_findi_add(struct hash_table *hash, const char *str)
754 struct hash_insert hi;
758 r = hash_findi(hash, str, &hi);
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
772 hash_findix(struct hash_table *hash, const char *str)
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)
787 const unsigned char *p = stdmacpos;
796 len += pp_directives_len[c - 0x80] + 1;
801 line = nasm_malloc(len + 1);
803 while ((c = *stdmacpos++)) {
805 memcpy(q, pp_directives[c - 0x80], pp_directives_len[c - 0x80]);
806 q += pp_directives_len[c - 0x80];
816 /* This was the last of the standard macro chain... */
818 if (any_extrastdmac) {
819 stdmacpos = extrastdmac;
820 any_extrastdmac = false;
821 } else if (do_predef) {
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
833 list_for_each(pd, predef) {
836 list_for_each(t, pd->first) {
837 *tail = new_Token(NULL, t->type, t->text, 0);
838 tail = &(*tail)->next;
843 ei = new_ExpInv(EXP_PREDEF, NULL);
846 ei->prev = istk->expansion;
847 istk->expansion = ei;
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
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();
876 * regular read from a file
879 buffer = nasm_malloc(BUF_DELTA);
883 q = fgets(p, bufsize - (p - buffer), istk->fp);
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')) {
898 * Also convert backslash-LF line continuation sequences into
899 * nothing at all (for Unix)
901 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
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) {
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'))
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);
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)
951 enum pp_token_type type;
953 Token *t, **tail = &list;
956 if ((defining != NULL) && (defining->ignoring == true)) {
964 if (*p == '+' && !nasm_isdigit(p[1])) {
967 } else if (nasm_isdigit(*p) ||
968 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
972 while (nasm_isdigit(*p));
973 type = TOK_PREPROC_ID;
974 } else if (*p == '{') {
976 while (*p && *p != '}') {
983 type = TOK_PREPROC_ID;
984 } else if (*p == '[') {
986 line += 2; /* Skip the leading %[ */
988 while (lvl && (c = *p++)) {
1000 p = nasm_skip_string(p - 1) + 1;
1010 error(ERR_NONFATAL, "unterminated %[ construct");
1011 type = TOK_INDIRECT;
1012 } else if (*p == '?') {
1013 type = TOK_PREPROC_Q; /* %? */
1016 type = TOK_PREPROC_QQ; /* %?? */
1019 } else if (*p == '!') {
1020 type = TOK_PREPROC_ID;
1025 } while (isidchar(*p));
1026 } else if (*p == '\'' || *p == '\"' || *p == '`') {
1027 p = nasm_skip_string(p);
1031 error(ERR_NONFATAL|ERR_PASS1, "unterminated %! string");
1033 /* %! without string or identifier */
1034 type = TOK_OTHER; /* Legacy behavior... */
1036 } else if (isidchar(*p) ||
1037 ((*p == '!' || *p == '%' || *p == '$') &&
1042 while (isidchar(*p));
1043 type = TOK_PREPROC_ID;
1049 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
1052 while (*p && isidchar(*p))
1054 } else if (*p == '\'' || *p == '"' || *p == '`') {
1059 p = nasm_skip_string(p);
1063 } else if(verbose) {
1064 error(ERR_WARNING|ERR_PASS1, "unterminated string");
1065 /* Handling unterminated strings by UNV */
1068 } else if (p[0] == '$' && p[1] == '$') {
1069 type = TOK_OTHER; /* TOKEN_BASE */
1071 } else if (isnumstart(*p)) {
1072 bool is_hex = false;
1073 bool is_float = false;
1089 if (!is_hex && (c == 'e' || c == 'E')) {
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
1099 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
1101 } else if (c == 'P' || c == 'p') {
1103 if (*p == '+' || *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.
1122 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
1123 (!is_hex && (*r == 'e' || *r == 'E')) ||
1124 (*r == 'p' || *r == 'P')) {
1128 break; /* Terminate the token */
1132 p--; /* Point to first character beyond number */
1134 if (p == line+1 && *line == '$') {
1135 type = TOK_OTHER; /* TOKEN_HERE */
1137 if (has_e && !is_hex) {
1138 /* 1e13 is floating-point, but 1e13h is not */
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 == ';') {
1157 } else if (*p == ';') {
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.
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] == '^')) {
1185 /* Handling unterminated string by UNV */
1188 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1189 t->text[p-line] = *line;
1193 if (type != TOK_COMMENT) {
1194 *tail = t = new_Token(NULL, type, line, p - line);
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 */
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));
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
1238 nasm_free(b->chunk);
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)
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;
1264 freeTokens = t->next;
1268 if (type == TOK_WHITESPACE || !text) {
1272 txtlen = strlen(text);
1273 t->text = nasm_malloc(txtlen+1);
1274 memcpy(t->text, text, txtlen);
1275 t->text[txtlen] = '\0';
1280 static Token *copy_Token(Token * tline)
1282 Token *t, *tt, *first = NULL, *prev = NULL;
1284 for (tt = tline; tt != NULL; tt = tt->next) {
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;
1292 freeTokens = t->next;
1294 t->text = tt->text ? nasm_strdup(tt->text) : NULL;
1295 t->a.mac = tt->a.mac;
1296 t->a.len = tt->a.len;
1308 static Token *delete_Token(Token * t)
1310 Token *next = t->next;
1312 t->next = freeTokens;
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)
1329 list_for_each(t, tlist) {
1330 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
1335 if (*v == '\'' || *v == '\"' || *v == '`') {
1336 size_t len = nasm_unquote(v, NULL);
1337 size_t clen = strlen(v);
1340 error(ERR_NONFATAL | ERR_PASS1,
1341 "NUL character in %! string");
1347 char *p = getenv(v);
1349 error(ERR_NONFATAL | ERR_PASS1,
1350 "nonexistent environment variable `%s'", v);
1353 t->text = nasm_strdup(p);
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] == '$') {
1364 Context *ctx = get_ctx(t->text, &q, false);
1367 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
1368 p = nasm_strcat(buffer, q);
1374 /* Expand %? and %?? directives */
1375 if ((istk->expansion != NULL) &&
1376 ((t->type == TOK_PREPROC_Q) ||
1377 (t->type == TOK_PREPROC_QQ))) {
1379 for (ei = istk->expansion; ei != NULL; ei = ei->prev){
1380 if (ei->type == EXP_MMACRO) {
1382 if (t->type == TOK_PREPROC_Q) {
1383 t->text = nasm_strdup(ei->name);
1385 t->text = nasm_strdup(ei->def->name);
1392 if (t->type == TOK_WHITESPACE)
1395 len += strlen(t->text);
1398 p = line = nasm_malloc(len + 1);
1400 list_for_each(t, tlist) {
1401 if (t->type == TOK_WHITESPACE) {
1403 } else if (t->text) {
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;
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;
1445 ei->unique = ++unique;
1447 if ((istk->mmac_depth < 1) &&
1448 (istk->expansion == 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);
1458 if ((istk->expansion == NULL) ||
1459 (ei->type == EXP_MMACRO)) {
1462 ei->relno = istk->expansion->lineno;
1464 ei->relno -= (ed->linecount + 1);
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
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;
1482 char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
1486 *tlineptr = tline ? tline->next : NULL;
1487 } while (tline && (tline->type == TOK_WHITESPACE ||
1488 tline->type == TOK_COMMENT));
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;
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);
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) {
1520 tokval->t_integer = readnum(tline->text, &rn_error);
1521 tokval->t_charptr = tline->text;
1523 return tokval->t_type = TOKEN_ERRNUM;
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) {
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;
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
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 $
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,
1622 if (!name || name[0] != '%' || name[1] != '$')
1626 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1633 while (ctx && *name == '$') {
1639 error(ERR_NONFATAL, "`%s': context stack is only"
1640 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
1651 /* Search for this smacro in found context */
1652 m = hash_findix(&ctx->localmac, name);
1654 if (!mstrcmp(m->name, name, m->casesense))
1665 * Check to see if a file is already in a string list
1667 static bool in_list(const StrList *list, const char *str)
1670 if (!strcmp(list->str, str))
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,
1689 IncPath *ip = ipath;
1690 int len = strlen(file);
1691 size_t prefix_len = 0;
1695 sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
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)) {
1717 prefix_len = strlen(prefix);
1719 /* -MG given and file not found */
1720 if (dhead && !in_list(*dhead, file)) {
1721 sl = nasm_malloc(len+1+sizeof sl->next);
1723 strcpy(sl->str, file);
1731 error(ERR_FATAL, "unable to open include file `%s'", file);
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
1748 * Note that this is also called with nparam zero to resolve
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.
1757 smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
1760 struct hash_table *smtbl;
1764 smtbl = &ctx->localmac;
1765 } else if (name[0] == '%' && name[1] == '$') {
1767 ctx = get_ctx(name, &name, false);
1769 return false; /* got to return _something_ */
1770 smtbl = &ctx->localmac;
1774 m = (SMacro *) hash_findix(smtbl, name);
1777 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
1778 (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
1780 if (nparam == (int) m->nparam || nparam == -1)
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;
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);
1813 if (tok_is_(t, "{"))
1815 (*params)[(*nparam)++] = t;
1816 while (tok_isnt_(t, brace ? "}" : ","))
1818 if (t) { /* got a comma/brace */
1822 * Now we've found the closing brace, look further
1826 if (tok_isnt_(t, ",")) {
1828 "braces do not enclose all of macro parameter");
1829 while (tok_isnt_(t, ","))
1833 t = t->next; /* eat the comma */
1840 * Determine whether one of the various `if' conditions is true or
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);
1849 Token *t, *tt, **tptr, *origline;
1850 struct tokenval tokval;
1852 enum pp_token_type needtype;
1859 j = false; /* have we matched yet? */
1864 if (tline->type != TOK_ID) {
1866 "`%s' expects context identifiers", pp_directives[ct]);
1867 free_tlist(origline);
1870 if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name))
1872 tline = tline->next;
1877 j = false; /* have we matched yet? */
1880 if (!tline || (tline->type != TOK_ID &&
1881 (tline->type != TOK_PREPROC_ID ||
1882 tline->text[1] != '$'))) {
1884 "`%s' expects macro identifiers", pp_directives[ct]);
1887 if (smacro_defined(NULL, tline->text, 0, NULL, true))
1889 tline = tline->next;
1894 tline = expand_smacro(tline);
1895 j = false; /* have we matched yet? */
1898 if (!tline || (tline->type != TOK_ID &&
1899 tline->type != TOK_STRING &&
1900 (tline->type != TOK_PREPROC_ID ||
1901 tline->text[1] != '!'))) {
1903 "`%s' expects environment variable names",
1908 if (tline->type == TOK_PREPROC_ID)
1909 p += 2; /* Skip leading %! */
1910 if (*p == '\'' || *p == '\"' || *p == '`')
1911 nasm_unquote_cstr(p, ct);
1914 tline = tline->next;
1920 tline = expand_smacro(tline);
1922 while (tok_isnt_(tt, ","))
1926 "`%s' expects two comma-separated arguments",
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",
1938 if (t->type == TOK_WHITESPACE) {
1942 if (tt->type == TOK_WHITESPACE) {
1946 if (tt->type != t->type) {
1947 j = false; /* found mismatching tokens */
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);
1959 if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
1963 } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
1964 j = false; /* found mismatching tokens */
1971 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1972 j = false; /* trailing gunk on one end or other */
1978 ExpDef searching, *ed;
1981 tline = expand_id(tline);
1982 if (!tok_type_(tline, TOK_ID)) {
1984 "`%s' expects a macro name", pp_directives[ct]);
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);
1994 } else if (!tok_type_(tline, TOK_NUMBER)) {
1996 "`%s' expects a parameter count or nothing",
1999 searching.nparam_min = searching.nparam_max =
2000 readnum(tline->text, &j);
2003 "unable to parse parameter count `%s'",
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))
2012 "`%s' expects a parameter count after `-'",
2015 searching.nparam_max = readnum(tline->text, &j);
2018 "unable to parse parameter count `%s'",
2020 if (searching.nparam_min > searching.nparam_max)
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)) {
2039 if (tline && tline->next)
2040 error(ERR_WARNING|ERR_PASS1,
2041 "trailing garbage after %%ifmacro ignored");
2042 nasm_free(searching.name);
2051 needtype = TOK_NUMBER;
2054 needtype = TOK_STRING;
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] == '+') &&
2067 j = tok_type_(t, needtype);
2071 t = tline = expand_smacro(tline);
2072 while (tok_type_(t, TOK_WHITESPACE))
2077 t = t->next; /* Skip the actual token */
2078 while (tok_type_(t, TOK_WHITESPACE))
2080 j = !t; /* Should be nothing left */
2085 t = tline = expand_smacro(tline);
2086 while (tok_type_(t, TOK_WHITESPACE))
2089 j = !t; /* Should be empty */
2093 t = tline = expand_smacro(tline);
2095 tokval.t_type = TOKEN_INVALID;
2096 evalresult = evaluate(ppscan, tptr, &tokval,
2097 NULL, pass | CRITICAL, error, NULL);
2101 error(ERR_WARNING|ERR_PASS1,
2102 "trailing garbage after expression ignored");
2103 if (!is_simple(evalresult)) {
2105 "non-constant value given to `%s'", pp_directives[ct]);
2108 j = reloc_value(evalresult) != 0;
2113 "preprocessor directive `%s' not yet implemented",
2118 free_tlist(origline);
2119 return j ^ PP_NEGATIVE(ct);
2122 free_tlist(origline);
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)) {
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 */
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);
2156 smtbl = ctx ? &ctx->localmac : &smacros;
2157 smhead = (SMacro **) hash_findi_add(smtbl, mname);
2158 smac = nasm_zalloc(sizeof(SMacro));
2159 smac->next = *smhead;
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);
2183 * We now have a macro name... go hunt for it.
2186 while ((s = *sp) != NULL) {
2187 if (!mstrcmp(s->name, mname, s->casesense)) {
2190 free_tlist(s->expansion);
2200 * Parse a mmacro specification.
2202 static bool parse_mmacro_spec(Token *tline, ExpDef *def, const char *directive)
2206 tline = tline->next;
2208 tline = expand_id(tline);
2209 if (!tok_type_(tline, TOK_ID)) {
2210 error(ERR_NONFATAL, "`%s' expects a macro name", directive);
2214 def->name = nasm_strdup(tline->text);
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);
2224 if (!tok_type_(tline, TOK_NUMBER)) {
2225 error(ERR_NONFATAL, "`%s' expects a parameter count", directive);
2227 def->nparam_min = def->nparam_max =
2228 readnum(tline->text, &err);
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)) {
2239 "`%s' expects a parameter count after `-'", directive);
2241 def->nparam_max = readnum(tline->text, &err);
2243 error(ERR_NONFATAL, "unable to parse parameter count `%s'",
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;
2255 if (tline && tok_type_(tline->next, TOK_ID) &&
2256 !nasm_stricmp(tline->next->text, ".nolist")) {
2257 tline = tline->next;
2262 * Handle default parameters.
2264 if (tline && tline->next) {
2265 def->dlist = tline->next;
2267 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
2270 def->defaults = NULL;
2274 if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
2276 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MDP,
2277 "too many default macro parameters");
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
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;
2322 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
2323 struct tokenval tokval;
2325 ExpDef *ed, *eed, **edhead;
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);
2343 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2344 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2346 return NO_DIRECTIVE_FOUND; /* didn't get it */
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
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 */
2365 StackPointer = "ebp";
2368 } else if (nasm_stricmp(tline->text, "flat64") == 0) {
2369 /* All subsequent ARG directives are for a 64-bit stack */
2371 StackPointer = "rbp";
2374 } else if (nasm_stricmp(tline->text, "large") == 0) {
2375 /* All subsequent ARG directives are for a 16-bit stack,
2376 * far function call.
2379 StackPointer = "bp";
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.
2387 StackPointer = "bp";
2391 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
2392 free_tlist(origline);
2393 return DIRECTIVE_FOUND;
2395 free_tlist(origline);
2396 return DIRECTIVE_FOUND;
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
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;
2421 /* Find the argument size type */
2422 tline = tline->next;
2423 if (!tline || tline->type != TOK_OTHER
2424 || tline->text[0] != ':') {
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);
2443 "Invalid size type for `%%arg' missing directive");
2445 free_tlist(origline);
2446 return DIRECTIVE_FOUND;
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));
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] == ',');
2465 free_tlist(origline);
2466 return DIRECTIVE_FOUND;
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;
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) {
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] != ':') {
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) {
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);
2519 "Invalid size type for `%%local' missing directive");
2521 free_tlist(origline);
2522 return DIRECTIVE_FOUND;
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;
2551 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2553 error(ERR_WARNING|ERR_PASS1,
2554 "trailing garbage after `%%clear' ignored");
2557 free_tlist(origline);
2558 return DIRECTIVE_FOUND;
2561 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2562 t = tline->next = expand_smacro(tline->next);
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_ */
2571 error(ERR_WARNING|ERR_PASS1,
2572 "trailing garbage after `%%depend' ignored");
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);
2581 deptail = &sl->next;
2583 free_tlist(origline);
2584 return DIRECTIVE_FOUND;
2587 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2588 t = tline->next = expand_smacro(tline->next);
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_ */
2598 error(ERR_WARNING|ERR_PASS1,
2599 "trailing garbage after `%%include' ignored");
2601 if (t->type != TOK_INTERNAL_STRING)
2602 nasm_unquote_cstr(p, i);
2603 inc = nasm_zalloc(sizeof(Include));
2605 inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
2607 /* -MG given but file not found */
2610 inc->fname = src_set_fname(nasm_strdup(p));
2611 inc->lineno = src_set_linnum(0);
2613 inc->expansion = NULL;
2615 list->uplevel(LIST_INCLUDE);
2617 free_tlist(origline);
2618 return DIRECTIVE_FOUND;
2621 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2623 static macros_t *use_pkg;
2624 const char *pkg_macro = NULL;
2626 tline = tline->next;
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_ */
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);
2644 error(ERR_NONFATAL, "unknown `%%use' package: %s", tline->text);
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;
2657 if (defining != NULL) return NO_DIRECTIVE_FOUND;
2658 tline = tline->next;
2660 tline = expand_id(tline);
2662 if (!tok_type_(tline, TOK_ID)) {
2663 error(ERR_NONFATAL, "`%s' expects a context identifier",
2665 free_tlist(origline);
2666 return DIRECTIVE_FOUND; /* but we did _something_ */
2669 error(ERR_WARNING|ERR_PASS1,
2670 "trailing garbage after `%s' ignored",
2672 p = nasm_strdup(tline->text);
2674 p = NULL; /* Anonymous */
2678 ctx = nasm_zalloc(sizeof(Context));
2680 hash_init(&ctx->localmac, HASH_SMALL);
2682 ctx->number = unique++;
2687 error(ERR_NONFATAL, "`%s': context stack is empty",
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, "
2693 cstk->name ? cstk->name : "anonymous", p);
2698 nasm_free(cstk->name);
2704 free_tlist(origline);
2705 return DIRECTIVE_FOUND;
2707 severity = ERR_FATAL;
2710 severity = ERR_NONFATAL;
2713 severity = ERR_WARNING|ERR_WARN_USER;
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;
2726 t = tline ? tline->next : NULL;
2728 if (tok_type_(tline, TOK_STRING) && !t) {
2729 /* The line contains only a quoted string */
2731 nasm_unquote(p, NULL); /* Ignore NUL character truncation */
2732 error(severity, "%s", p);
2734 /* Not a quoted string, or more than a quoted string */
2735 p = detoken(tline, false);
2736 error(severity, "%s", p);
2739 free_tlist(origline);
2740 return DIRECTIVE_FOUND;
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)) {
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);
2764 ed->ignoring = ((ed->state == COND_IF_TRUE) ? false : true);
2765 ed->prev = defining;
2767 free_tlist(origline);
2768 return DIRECTIVE_FOUND;
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) {
2781 defining->state = COND_DONE;
2782 defining->ignoring = true;
2787 defining->ignoring = true;
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;
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 */
2810 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2811 defining->ignoring = ((defining->state == COND_IF_TRUE) ? false : true);
2814 free_tlist(origline);
2815 return DIRECTIVE_FOUND;
2818 if (defining != NULL) {
2819 if ((defining->type != EXP_IF) || (defining->def_depth > 0)) {
2820 return NO_DIRECTIVE_FOUND;
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) {
2832 defining->state = COND_ELSE_FALSE;
2833 defining->ignoring = true;
2837 defining->ignoring = true;
2841 defining->state = COND_ELSE_TRUE;
2842 defining->ignoring = false;
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;
2853 free_tlist(origline);
2854 return DIRECTIVE_FOUND;
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;
2864 return NO_DIRECTIVE_FOUND;
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;
2875 defining = ed->prev;
2876 ed->prev = expansions;
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;
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);
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])) {
2903 return DIRECTIVE_FOUND;
2907 ed->max_depth = (ed->max_depth + 1);
2908 ed->ignoring = false;
2909 ed->prev = defining;
2912 eed = (ExpDef *) hash_findix(&expdefs, ed->name);
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;
2923 free_tlist(origline);
2924 return DIRECTIVE_FOUND;
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;
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;
2946 defining = ed->prev;
2947 ed->prev = expansions;
2950 free_tlist(origline);
2951 return DIRECTIVE_FOUND;
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) {
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;
2976 error(ERR_NONFATAL, "`%%exitmacro' not within `%%macro' block");
2978 free_tlist(origline);
2979 return DIRECTIVE_FOUND;
2983 if (defining != NULL) return NO_DIRECTIVE_FOUND;
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) {
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",
3012 free_tlist(origline);
3013 free_tlist(spec.dlist);
3014 return DIRECTIVE_FOUND;
3018 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3019 if (tline->next && tline->next->type == TOK_WHITESPACE)
3020 tline = tline->next;
3022 free_tlist(origline);
3023 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
3024 return DIRECTIVE_FOUND;
3026 t = expand_smacro(tline->next);
3028 free_tlist(origline);
3031 tokval.t_type = TOKEN_INVALID;
3033 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3036 return DIRECTIVE_FOUND;
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) {
3050 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
3051 } else if (ei->nparam == 0) {
3053 "`%%rotate' invoked within macro without parameters");
3055 int rotate = ei->rotate + reloc_value(evalresult);
3057 rotate %= (int)ei->nparam;
3059 rotate += ei->nparam;
3060 ei->rotate = rotate;
3062 return DIRECTIVE_FOUND;
3065 if (defining != NULL) {
3066 if (defining->type == EXP_REP) {
3067 defining->def_depth ++;
3069 return NO_DIRECTIVE_FOUND;
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) {
3080 tline = tline->next;
3081 } while (tok_type_(tline, TOK_WHITESPACE));
3085 t = expand_smacro(tline);
3087 tokval.t_type = TOKEN_INVALID;
3089 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3091 free_tlist(origline);
3092 return DIRECTIVE_FOUND;
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");
3108 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
3111 free_tlist(origline);
3112 ed = new_ExpDef(EXP_REP);
3113 ed->nolist = nolist;
3116 ed->max_depth = (count - 1);
3117 ed->ignoring = false;
3118 ed->prev = defining;
3120 return DIRECTIVE_FOUND;
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;
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.
3150 defining = ed->prev;
3151 ed->prev = expansions;
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;
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) {
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;
3187 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
3189 free_tlist(origline);
3190 return DIRECTIVE_FOUND;
3196 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3197 casesense = (i == PP_DEFINE || i == PP_XDEFINE);
3199 tline = tline->next;
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",
3207 free_tlist(origline);
3208 return DIRECTIVE_FOUND;
3211 ctx = get_ctx(tline->text, &mname, false);
3213 param_start = tline = tline->next;
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;
3229 error(ERR_NONFATAL, "parameter identifier expected");
3230 free_tlist(origline);
3231 return DIRECTIVE_FOUND;
3233 if (tline->type != TOK_ID) {
3235 "`%s': parameter identifier expected",
3237 free_tlist(origline);
3238 return DIRECTIVE_FOUND;
3240 tline->type = TOK_SMAC_PARAM + nparam++;
3241 tline = tline->next;
3243 if (tok_is_(tline, ",")) {
3244 tline = tline->next;
3246 if (!tok_is_(tline, ")")) {
3248 "`)' expected to terminate macro template");
3249 free_tlist(origline);
3250 return DIRECTIVE_FOUND;
3256 tline = tline->next;
3258 if (tok_type_(tline, TOK_WHITESPACE))
3259 last = tline, tline = tline->next;
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))
3271 t->next = macro_start;
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
3283 define_smacro(ctx, mname, casesense, nparam, macro_start);
3284 free_tlist(origline);
3285 return DIRECTIVE_FOUND;
3288 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3289 tline = tline->next;
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;
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;
3312 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3313 casesense = (i == PP_DEFSTR);
3315 tline = tline->next;
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",
3323 free_tlist(origline);
3324 return DIRECTIVE_FOUND;
3327 ctx = get_ctx(tline->text, &mname, false);
3329 tline = expand_smacro(tline->next);
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;
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;
3352 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3353 casesense = (i == PP_DEFTOK);
3355 tline = tline->next;
3357 tline = expand_id(tline);
3358 if (!tline || (tline->type != TOK_ID &&
3359 (tline->type != TOK_PREPROC_ID ||
3360 tline->text[1] != '$'))) {
3362 "`%s' expects a macro identifier as first parameter",
3364 free_tlist(origline);
3365 return DIRECTIVE_FOUND;
3367 ctx = get_ctx(tline->text, &mname, false);
3369 tline = expand_smacro(tline->next);
3373 while (tok_type_(t, TOK_WHITESPACE))
3375 /* t should now point to the string */
3376 if (!tok_type_(t, TOK_STRING)) {
3378 "`%s` requires string as second parameter",
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);
3400 free_tlist(origline);
3401 return DIRECTIVE_FOUND;
3404 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3407 StrList *xsl = NULL;
3408 StrList **xst = &xsl;
3412 tline = tline->next;
3414 tline = expand_id(tline);
3415 if (!tline || (tline->type != TOK_ID &&
3416 (tline->type != TOK_PREPROC_ID ||
3417 tline->text[1] != '$'))) {
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);
3425 tline = expand_smacro(tline->next);
3429 while (tok_type_(t, TOK_WHITESPACE))
3432 if (!t || (t->type != TOK_STRING &&
3433 t->type != TOK_INTERNAL_STRING)) {
3434 error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
3436 free_tlist(origline);
3437 return DIRECTIVE_FOUND; /* but we did _something_ */
3440 error(ERR_WARNING|ERR_PASS1,
3441 "trailing garbage after `%%pathsearch' ignored");
3443 if (t->type != TOK_INTERNAL_STRING)
3444 nasm_unquote(p, NULL);
3446 fp = inc_fopen(p, &xsl, &xst, true);
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;
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);
3464 free_tlist(origline);
3465 return DIRECTIVE_FOUND;
3469 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3472 tline = tline->next;
3474 tline = expand_id(tline);
3475 if (!tline || (tline->type != TOK_ID &&
3476 (tline->type != TOK_PREPROC_ID ||
3477 tline->text[1] != '$'))) {
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);
3485 tline = expand_smacro(tline->next);
3489 while (tok_type_(t, TOK_WHITESPACE))
3491 /* t should now point to the string */
3492 if (!tok_type_(t, TOK_STRING)) {
3494 "`%%strlen` requires string as second parameter");
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);
3510 free_tlist(origline);
3511 return DIRECTIVE_FOUND;
3514 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3517 tline = tline->next;
3519 tline = expand_id(tline);
3520 if (!tline || (tline->type != TOK_ID &&
3521 (tline->type != TOK_PREPROC_ID ||
3522 tline->text[1] != '$'))) {
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);
3530 tline = expand_smacro(tline->next);
3534 list_for_each(t, tline) {
3536 case TOK_WHITESPACE:
3539 len += t->a.len = nasm_unquote(t->text, NULL);
3542 if (!strcmp(t->text, ",")) /* permit comma separators */
3544 /* else fall through */
3547 "non-string passed to `%%strcat' (%d)", t->type);
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);
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);
3570 define_smacro(ctx, mname, casesense, 0, macro_start);
3572 free_tlist(origline);
3573 return DIRECTIVE_FOUND;
3576 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3578 int64_t start, count;
3583 tline = tline->next;
3585 tline = expand_id(tline);
3586 if (!tline || (tline->type != TOK_ID &&
3587 (tline->type != TOK_PREPROC_ID ||
3588 tline->text[1] != '$'))) {
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);
3596 tline = expand_smacro(tline->next);
3599 if (tline) /* skip expanded id */
3601 while (tok_type_(t, TOK_WHITESPACE))
3604 /* t should now point to the string */
3605 if (!tok_type_(t, TOK_STRING)) {
3607 "`%%substr` requires string as second parameter");
3609 free_tlist(origline);
3610 return DIRECTIVE_FOUND;
3615 tokval.t_type = TOKEN_INVALID;
3616 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3620 free_tlist(origline);
3621 return DIRECTIVE_FOUND;
3622 } else if (!is_simple(evalresult)) {
3623 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3625 free_tlist(origline);
3626 return DIRECTIVE_FOUND;
3628 start = evalresult->value - 1;
3630 while (tok_type_(tt, TOK_WHITESPACE))
3633 count = 1; /* Backwards compatibility: one character */
3635 tokval.t_type = TOKEN_INVALID;
3636 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3640 free_tlist(origline);
3641 return DIRECTIVE_FOUND;
3642 } else if (!is_simple(evalresult)) {
3643 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
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 */
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);
3673 free_tlist(origline);
3674 return DIRECTIVE_FOUND;
3679 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3680 casesense = (i == PP_ASSIGN);
3682 tline = tline->next;
3684 tline = expand_id(tline);
3685 if (!tline || (tline->type != TOK_ID &&
3686 (tline->type != TOK_PREPROC_ID ||
3687 tline->text[1] != '$'))) {
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);
3696 tline = expand_smacro(tline->next);
3701 tokval.t_type = TOKEN_INVALID;
3703 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3706 free_tlist(origline);
3707 return DIRECTIVE_FOUND;
3711 error(ERR_WARNING|ERR_PASS1,
3712 "trailing garbage after expression ignored");
3714 if (!is_simple(evalresult)) {
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;
3735 if (defining != NULL) return NO_DIRECTIVE_FOUND;
3737 * Syntax is `%line nnn[+mmm] [filename]'
3739 tline = tline->next;
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);
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;
3763 nasm_free(src_set_fname(detoken(tline, false)));
3765 free_tlist(origline);
3766 return DIRECTIVE_FOUND;
3769 if (defining != NULL) {
3770 if (defining->type == EXP_WHILE) {
3771 defining->def_depth ++;
3773 return NO_DIRECTIVE_FOUND;
3776 if ((istk->expansion != NULL) &&
3777 (istk->expansion->emitting == false)) {
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);
3789 ed->max_depth = DEADMAN_LIMIT;
3790 ed->ignoring = ((ed->state == COND_IF_TRUE) ? false : true);
3791 if (ed->ignoring == false) {
3794 } else if (l != NULL) {
3795 delete_Token(l->first);
3799 ed->prev = defining;
3801 free_tlist(origline);
3802 return DIRECTIVE_FOUND;
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;
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;
3824 defining = ed->prev;
3825 if (ed->ignoring == false) {
3826 ed->prev = expansions;
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;
3836 free_tlist(origline);
3837 return DIRECTIVE_FOUND;
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) {
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;
3864 error(ERR_NONFATAL, "`%%exitwhile' not within `%%while' block");
3866 free_tlist(origline);
3867 return DIRECTIVE_FOUND;
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;
3880 free_tlist(origline);
3881 return DIRECTIVE_FOUND;
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;
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;
3899 defining = ed->prev;
3901 free_tlist(origline);
3902 return DIRECTIVE_FOUND;
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;
3911 if (tline == NULL) {
3912 error(ERR_NONFATAL, "`%%final' expects at least one parameter");
3915 l->first = copy_Token(tline);
3919 free_tlist(origline);
3920 return DIRECTIVE_FOUND;
3924 "preprocessor directive `%s' not yet implemented",
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
3935 static int find_cc(Token * t)
3941 return -1; /* Probably a %+ without a space */
3944 if (t->type != TOK_ID)
3948 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
3952 j = ARRAY_SIZE(conditions);
3955 m = nasm_stricmp(t->text, conditions[k]);
3970 static bool paste_tokens(Token **head, const struct tokseq_match *m,
3971 int mnum, bool handle_paste_tokens)
3973 Token **tail, *t, *tt;
3975 bool did_paste = false;
3979 /* Now handle token pasting... */
3982 while ((t = *tail) && (tt = t->next)) {
3984 case TOK_WHITESPACE:
3985 if (tt->type == TOK_WHITESPACE) {
3986 /* Zap adjacent whitespace tokens */
3987 t->next = delete_Token(tt);
3989 /* Do not advance paste_head here */
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 */
4004 while (tok_type_(tt, TOK_WHITESPACE))
4005 tt = t->next = delete_Token(tt);
4007 tmp = nasm_strcat(t->text, tt->text);
4009 tt = delete_Token(tt);
4010 t = *tail = tokenize(tmp);
4016 t->next = tt; /* Attach the remaining token chain */
4023 /* else fall through */
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
4032 for (i = 0; i < mnum; i++) {
4033 if (PP_CONCAT_MASK(t->type) & m[i].mask_head) {
4037 while (tt && (PP_CONCAT_MASK(tt->type) & m[i].mask_tail)) {
4038 len += strlen(tt->text);
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);
4052 p = strchr(p, '\0');
4053 t = delete_Token(t);
4055 t = *tail = tokenize(tmp);
4061 t->next = tt; /* Attach the remaining token chain */
4069 if (i >= mnum) { /* no match */
4071 if (!tok_type_(t->next, TOK_WHITESPACE))
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;
4089 pos = strchr(tline->text, ':');
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
4100 if (lst == 0 || fst == 0)
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)))
4108 fst = fst < 0 ? fst + (int)ei->nparam + 1: fst;
4109 lst = lst < 0 ? lst + (int)ei->nparam + 1: lst;
4111 /* counted from zero */
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;
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;
4126 t = new_Token(NULL, tm->type, tm->text, 0);
4127 *tt = t, tt = &t->next;
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;
4135 t = new_Token(NULL, tm->type, tm->text, 0);
4136 *tt = t, tt = &t->next;
4144 error(ERR_NONFATAL, "`%%{%s}': macro parameters out of range",
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;
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] == '%')) {
4169 int type = 0, cc; /* type = 0 to placate optimisers */
4176 tline = tline->next;
4178 for (ei = istk->expansion; ei != NULL; ei = ei->prev) {
4179 if (ei->type == EXP_MMACRO) {
4184 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
4186 pos = strchr(t->text, ':');
4188 switch (t->text[1]) {
4190 * We have to make a substitution of one of the
4191 * forms %1, %-1, %+1, %%foo, %0.
4194 if ((strlen(t->text) > 2) && (t->text[2] == '0')) {
4196 text = nasm_strdup(ei->label_text);
4199 snprintf(tmpbuf, sizeof(tmpbuf), "%d", ei->nparam);
4200 text = nasm_strdup(tmpbuf);
4205 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
4207 text = nasm_strcat(tmpbuf, t->text + 2);
4210 n = atoi(t->text + 2) - 1;
4211 if (n >= ei->nparam)
4215 n = (n + ei->rotate) % ei->nparam;
4221 "macro parameter %d is not a condition code",
4226 if (inverse_ccs[cc] == -1) {
4228 "condition code `%s' is not invertible",
4232 text = nasm_strdup(conditions[inverse_ccs[cc]]);
4236 n = atoi(t->text + 2) - 1;
4237 if (n >= ei->nparam)
4241 n = (n + ei->rotate) % ei->nparam;
4247 "macro parameter %d is not a condition code",
4252 text = nasm_strdup(conditions[cc]);
4256 n = atoi(t->text + 1) - 1;
4257 if (n >= ei->nparam)
4261 n = (n + ei->rotate) % ei->nparam;
4265 for (i = 0; i < ei->paramlen[n]; i++) {
4266 *tail = new_Token(NULL, tt->type, tt->text, 0);
4267 tail = &(*tail)->next;
4271 text = NULL; /* we've done it here */
4276 * seems we have a parameters range here
4278 Token *head, **last;
4279 head = expand_mmac_params_range(ei, t, &last);
4300 } else if (tline->type == TOK_INDIRECT) {
4302 tline = tline->next;
4303 tt = tokenize(t->text);
4304 tt = expand_mmac_params(tt);
4305 tt = expand_smacro(tt);
4308 tt->a.mac = NULL; /* Necessary? */
4316 tline = tline->next;
4324 paste_tokens(&thead, pp_concat_match,
4325 ARRAY_SIZE(pp_concat_match),
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;
4345 unsigned int nparam, sparam;
4347 Token *org_tline = tline;
4350 int deadman = DEADMAN_LIMIT;
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
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 */
4373 while (tline) { /* main token loop */
4375 error(ERR_NONFATAL, "interminable macro recursion");
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;
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
4395 list_for_each(m, head)
4396 if (!mstrcmp(m->name, mname, m->casesense))
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)) {
4412 src_get(&num, &file);
4413 tline->text = nasm_quote(file, strlen(file));
4414 tline->type = TOK_STRING;
4418 if (!strcmp("__LINE__", m->name)) {
4419 nasm_free(tline->text);
4420 make_tok_num(tline, src_get_linnum());
4423 if (!strcmp("__BITS__", m->name)) {
4424 nasm_free(tline->text);
4425 make_tok_num(tline, globalbits);
4428 tline = delete_Token(tline);
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
4440 /*tline = tline->next;
4441 skip_white_(tline); */
4444 while (tok_type_(t, TOK_SMAC_END)) {
4445 t->a.mac->in_progress = false;
4447 t = tline->next = delete_Token(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.)
4463 sparam = PARAM_DELTA;
4464 params = nasm_malloc(sparam * sizeof(Token *));
4465 params[0] = tline->next;
4466 paramsize = nasm_malloc(sparam * sizeof(int));
4468 while (true) { /* parameter loop */
4470 * For some unusual expansions
4471 * which concatenates function call
4474 while (tok_type_(t, TOK_SMAC_END)) {
4475 t->a.mac->in_progress = false;
4477 t = tline->next = delete_Token(t);
4483 "macro call expects terminating `)'");
4486 if (tline->type == TOK_WHITESPACE
4488 if (paramsize[nparam])
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;
4508 continue; /* parameter loop */
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) {
4522 continue; /* parameter loop */
4524 if (ch == '(' && !brackets)
4526 if (ch == ')' && brackets <= 0)
4532 error(ERR_NONFATAL, "braces do not "
4533 "enclose all of macro parameter");
4535 paramsize[nparam] += white + 1;
4537 } /* parameter loop */
4539 while (m && (m->nparam != nparam ||
4540 mstrcmp(m->name, mname,
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)
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
4560 nasm_free(paramsize);
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.
4574 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
4576 m->in_progress = true;
4578 list_for_each(t, m->expansion) {
4579 if (t->type >= TOK_SMAC_PARAM) {
4580 Token *pcopy = tline, **ptail = &pcopy;
4584 ttt = params[t->type - TOK_SMAC_PARAM];
4585 i = paramsize[t->type - TOK_SMAC_PARAM];
4587 pt = *ptail = new_Token(tline, ttt->type,
4593 } else if (t->type == TOK_PREPROC_Q) {
4594 tt = new_Token(tline, TOK_ID, mname, 0);
4596 } else if (t->type == TOK_PREPROC_QQ) {
4597 tt = new_Token(tline, TOK_ID, m->name, 0);
4600 tt = new_Token(tline, t->type, t->text, 0);
4606 * Having done that, get rid of the macro call, and clean
4607 * up the parameters.
4610 nasm_free(paramsize);
4613 continue; /* main token loop */
4618 if (tline->type == TOK_SMAC_END) {
4619 tline->a.mac->in_progress = false;
4620 tline = delete_Token(tline);
4623 tline = tline->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).
4638 if (paste_tokens(&thead, pp_concat_match,
4639 ARRAY_SIZE(pp_concat_match),
4642 * If we concatenated something, *and* we had previously expanded
4643 * an actual macro, scan the lines again for macros...
4654 *org_tline = *thead;
4655 /* since we just gave text to org_line, don't free it */
4657 delete_Token(thead);
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;
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:
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
4691 static Token *expand_id(Token * tline)
4693 Token *cur, *oldnext = NULL;
4695 if (!tline || !tline->next)
4700 (cur->next->type == TOK_ID ||
4701 cur->next->type == TOK_PREPROC_ID
4702 || cur->next->type == TOK_NUMBER))
4705 /* If identifier consists of just one token, don't expand */
4710 oldnext = cur->next; /* Detach the tail past identifier */
4711 cur->next = NULL; /* so that expand_smacro stops here */
4714 tline = expand_smacro(tline);
4717 /* expand_smacro possibly changhed tline; re-scan for EOL */
4719 while (cur && cur->next)
4722 cur->next = oldnext;
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)
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))
4757 * OK, we have a potential macro. Count and demarcate the
4760 count_mmac_params(tline->next, &nparam, ¶ms);
4763 * So we know how many parameters we've got. Find the ExpDef
4764 * structure that handles this number.
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) {
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];
4784 * If we've gone over the maximum parameter count (and
4785 * we're in Plus mode), ignore parameters beyond
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));
4797 params[nparam] = NULL;
4798 *params_array = params;
4802 * This one wasn't right: look for the next one with the
4805 list_for_each(ed, ed->next)
4806 if (!mstrcmp(ed->name, tline->text, ed->casesense))
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);
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;
4834 int i, nparam, *paramlen;
4839 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4840 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
4842 ed = is_mmacro(t, ¶ms);
4848 * We have an id which isn't a macro call. We'll assume
4849 * it might be a label; we'll also check to see if a
4850 * colon follows it. Then, if there's another id after
4851 * that lot, we'll check it again for macro-hood.
4855 if (tok_type_(t, TOK_WHITESPACE))
4856 last = t, t = t->next;
4857 if (tok_is_(t, ":")) {
4859 last = t, t = t->next;
4860 if (tok_type_(t, TOK_WHITESPACE))
4861 last = t, t = t->next;
4863 if (!tok_type_(t, TOK_ID) || !(ed = is_mmacro(t, ¶ms)))
4871 * Fix up the parameters: this involves stripping leading and
4872 * trailing whitespace, then stripping braces if they are
4875 for (nparam = 0; params[nparam]; nparam++) ;
4876 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
4878 for (i = 0; params[i]; i++) {
4880 int comma = (!ed->plus || i < nparam - 1);
4884 if (tok_is_(t, "{"))
4885 t = t->next, brace = true, comma = false;
4889 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
4890 break; /* ... because we have hit a comma */
4891 if (comma && t->type == TOK_WHITESPACE
4892 && tok_is_(t->next, ","))
4893 break; /* ... or a space then a comma */
4894 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
4895 break; /* ... or a brace */
4901 if (ed->cur_depth >= ed->max_depth) {
4902 if (ed->max_depth > 1) {
4904 "reached maximum macro recursion depth of %i for %s",
4905 ed->max_depth,ed->name);
4913 * OK, we have found a ExpDef structure representing a
4914 * previously defined mmacro. Create an expansion invocation
4915 * and point it back to the expansion definition. Substitution of
4916 * parameter tokens and macro-local tokens doesn't get done
4917 * until the single-line macro substitution process; this is
4918 * because delaying them allows us to change the semantics
4919 * later through %rotate.
4921 ei = new_ExpInv(EXP_MMACRO, ed);
4922 ei->name = nasm_strdup(mname);
4923 //ei->label = label;
4924 //ei->label_text = detoken(label, false);
4925 ei->current = ed->line;
4926 ei->emitting = true;
4927 //ei->iline = tline;
4928 ei->params = params;
4929 ei->nparam = nparam;
4931 ei->paramlen = paramlen;
4934 ei->prev = istk->expansion;
4935 istk->expansion = ei;
4938 * Special case: detect %00 on first invocation; if found,
4939 * avoid emitting any labels that precede the mmacro call.
4940 * ed->prepend is set to -1 when %00 is detected, else 1.
4942 if (ed->prepend == 0) {
4943 for (l = ed->line; l != NULL; l = l->next) {
4944 for (t = l->first; t != NULL; t = t->next) {
4945 if ((t->type == TOK_PREPROC_ID) &&
4946 (strlen(t->text) == 3) &&
4947 (t->text[1] == '0') && (t->text[2] == '0')) {
4952 if (dont_prepend < 0) {
4956 ed->prepend = ((dont_prepend < 0) ? -1 : 1);
4960 * If we had a label, push it on as the first line of
4961 * the macro expansion.
4963 if (label != NULL) {
4964 if (ed->prepend < 0) {
4965 ei->label_text = detoken(label, false);
4967 if (dont_prepend == 0) {
4969 while (t->next != NULL) {
4972 t->next = new_Token(NULL, TOK_OTHER, ":", 0);
4975 l->first = copy_Token(label);
4976 l->next = ei->current;
4981 list->uplevel(ed->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
4987 /* The function that actually does the error reporting */
4988 static void verror(int severity, const char *fmt, va_list arg)
4992 vsnprintf(buff, sizeof(buff), fmt, arg);
4994 if (istk && istk->mmac_depth > 0) {
4995 ExpInv *ei = istk->expansion;
4996 int lineno = ei->lineno;
4998 if (ei->type == EXP_MMACRO)
5000 lineno += ei->relno;
5003 nasm_error(severity, "(%s:%d) %s", ei->def->name,
5006 nasm_error(severity, "%s", buff);
5010 * Since preprocessor always operate only on the line that didn't
5011 * arrived yet, we should always use ERR_OFFBY1.
5013 static void error(int severity, const char *fmt, ...)
5017 verror(severity, fmt, arg);
5022 * Because %else etc are evaluated in the state context
5023 * of the previous branch, errors might get lost with error():
5024 * %if 0 ... %else trailing garbage ... %endif
5025 * So %else etc should report errors with this function.
5027 static void error_precond(int severity, const char *fmt, ...)
5031 /* Only ignore the error if it's really in a dead branch */
5032 if ((istk != NULL) &&
5033 (istk->expansion != NULL) &&
5034 (istk->expansion->type == EXP_IF) &&
5035 (istk->expansion->def->state == COND_NEVER))
5039 verror(severity, fmt, arg);
5044 pp_reset(char *file, int apass, ListGen * listgen, StrList **deplist)
5049 istk = nasm_zalloc(sizeof(Include));
5050 istk->fp = fopen(file, "r");
5051 src_set_fname(nasm_strdup(file));
5055 error(ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'",
5060 nested_mac_count = 0;
5061 nested_rep_count = 0;
5064 if (tasm_compatible_mode) {
5065 stdmacpos = nasm_stdmac;
5067 stdmacpos = nasm_stdmac_after_tasm;
5069 any_extrastdmac = extrastdmac && *extrastdmac;
5074 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
5075 * The caller, however, will also pass in 3 for preprocess-only so
5076 * we can set __PASS__ accordingly.
5078 pass = apass > 2 ? 2 : apass;
5080 dephead = deptail = deplist;
5082 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
5084 strcpy(sl->str, file);
5086 deptail = &sl->next;
5090 * Define the __PASS__ macro. This is defined here unlike
5091 * all the other builtins, because it is special -- it varies between
5094 t = nasm_zalloc(sizeof(*t));
5095 make_tok_num(t, apass);
5096 define_smacro(NULL, "__PASS__", true, 0, t);
5099 static char *pp_getline(void)
5110 * Fetch a tokenized line, either from the expansion
5111 * buffer or from the input file.
5115 while (1) { /* until we get a line we can use */
5117 * Fetch a tokenized line from the expansion buffer
5119 if (istk->expansion != NULL) {
5120 ei = istk->expansion;
5121 if (ei->current != NULL) {
5122 if (ei->emitting == false) {
5127 ei->current = l->next;
5129 tline = copy_Token(l->first);
5130 if (((ei->type == EXP_REP) ||
5131 (ei->type == EXP_MMACRO) ||
5132 (ei->type == EXP_WHILE))
5133 && (ei->def->nolist == false)) {
5134 char *p = detoken(tline, false);
5135 list->line(LIST_MACRO, p);
5138 if (ei->linnum > -1) {
5139 src_set_linnum(src_get_linnum() + 1);
5142 } else if ((ei->type == EXP_REP) &&
5143 (ei->def->cur_depth < ei->def->max_depth)) {
5144 ei->def->cur_depth ++;
5145 ei->current = ei->def->line;
5148 } else if ((ei->type == EXP_WHILE) &&
5149 (ei->def->cur_depth < ei->def->max_depth)) {
5150 ei->current = ei->def->line;
5152 tline = copy_Token(ei->current->first);
5153 j = if_condition(tline, PP_WHILE);
5155 j = (((j < 0) ? COND_NEVER : j) ? COND_IF_TRUE : COND_IF_FALSE);
5156 if (j == COND_IF_TRUE) {
5157 ei->current = ei->current->next;
5158 ei->def->cur_depth ++;
5160 ei->emitting = false;
5162 ei->def->cur_depth = ei->def->max_depth;
5166 istk->expansion = ei->prev;
5169 if ((ei->emitting == true) &&
5170 (ed->max_depth == DEADMAN_LIMIT) &&
5171 (ed->cur_depth == DEADMAN_LIMIT)
5173 error(ERR_FATAL, "runaway expansion detected, aborting");
5175 if (ed->cur_depth > 0) {
5177 } else if (ed->type != EXP_MMACRO) {
5178 expansions = ed->prev;
5181 if ((ei->type == EXP_REP) ||
5182 (ei->type == EXP_MMACRO) ||
5183 (ei->type == EXP_WHILE)) {
5184 list->downlevel(LIST_MACRO);
5185 if (ei->type == EXP_MMACRO) {
5190 if (ei->linnum > -1) {
5191 src_set_linnum(ei->linnum);
5199 * Read in line from input and tokenize
5202 if (line) { /* from the current input file */
5203 line = prepreproc(line);
5204 tline = tokenize(line);
5210 * The current file has ended; work down the istk
5215 if (i->expansion != NULL) {
5217 "end of file while still in an expansion");
5219 /* only set line and file name if there's a next node */
5221 src_set_linnum(i->lineno);
5222 nasm_free(src_set_fname(nasm_strdup(i->fname)));
5224 if ((i->next == NULL) && (finals != NULL)) {
5226 ei = new_ExpInv(EXP_FINAL, NULL);
5227 ei->emitting = true;
5228 ei->current = finals;
5229 istk->expansion = ei;
5234 list->downlevel(LIST_INCLUDE);
5237 if (finals != NULL) {
5247 if (defining == NULL) {
5248 tline = expand_mmac_params(tline);
5252 * Check the line to see if it's a preprocessor directive.
5254 if (do_directive(tline) == DIRECTIVE_FOUND) {
5256 } else if (defining != NULL) {
5258 * We're defining an expansion. We emit nothing at all,
5259 * and just shove the tokenized line on to the definition.
5261 if (defining->ignoring == false) {
5262 Line *l = new_Line();
5264 if (defining->line == NULL) {
5268 defining->last->next = l;
5274 defining->linecount++;
5276 } else if ((istk->expansion != NULL) &&
5277 (istk->expansion->emitting != true)) {
5279 * We're in a non-emitting branch of an expansion.
5280 * Emit nothing at all, not even a blank line: when we
5281 * emerge from the expansion we'll give a line-number
5282 * directive so we keep our place correctly.
5287 tline = expand_smacro(tline);
5288 if (expand_mmacro(tline) != true) {
5290 * De-tokenize the line again, and emit it.
5292 line = detoken(tline, true);
5303 static void pp_cleanup(int pass)
5305 if (defining != NULL) {
5306 error(ERR_NONFATAL, "end of file while still defining an expansion");
5307 while (defining != NULL) {
5308 ExpDef *ed = defining;
5309 defining = ed->prev;
5314 while (cstk != NULL)
5317 while (istk != NULL) {
5321 nasm_free(i->fname);
5322 while (i->expansion != NULL) {
5323 ExpInv *ei = i->expansion;
5324 i->expansion = ei->prev;
5331 nasm_free(src_set_fname(NULL));
5336 while ((i = ipath)) {
5345 void pp_include_path(char *path)
5347 IncPath *i = nasm_zalloc(sizeof(IncPath));
5350 i->path = nasm_strdup(path);
5362 void pp_pre_include(char *fname)
5364 Token *inc, *space, *name;
5367 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
5368 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
5369 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
5377 void pp_pre_define(char *definition)
5383 equals = strchr(definition, '=');
5384 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
5385 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
5388 space->next = tokenize(definition);
5398 void pp_pre_undefine(char *definition)
5403 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
5404 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
5405 space->next = tokenize(definition);
5414 * This function is used to assist with "runtime" preprocessor
5415 * directives, e.g. pp_runtime("%define __BITS__ 64");
5417 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5418 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5421 void pp_runtime(char *definition)
5425 def = tokenize(definition);
5426 if (do_directive(def) == NO_DIRECTIVE_FOUND)
5431 void pp_extra_stdmac(macros_t *macros)
5433 extrastdmac = macros;
5436 static void make_tok_num(Token * tok, int64_t val)
5439 snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
5440 tok->text = nasm_strdup(numbuf);
5441 tok->type = TOK_NUMBER;