nasm.nsi: use LZMA compression
[nasm.git] / preproc.c
blob028cbf2bcdf7e9e8e99c88c86b80131310c1d87c
1 /* ----------------------------------------------------------------------- *
2 *
3 * Copyright 1996-2009 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation, Inc.,
10 * 51 Franklin St, Fifth Floor, Boston MA 02110-1301, USA; version 2.1,
11 * or, at your option, any later version, incorporated herein by
12 * reference.
14 * Patches submitted to this file are required to be dual licensed
15 * under the LGPL 2.1+ and the 2-clause BSD license:
17 * Copyright 1996-2009 the NASM Authors - All rights reserved.
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following
21 * conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above
26 * copyright notice, this list of conditions and the following
27 * disclaimer in the documentation and/or other materials provided
28 * with the distribution.
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
31 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
32 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
35 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
37 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
41 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
42 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 * ----------------------------------------------------------------------- */
47 * preproc.c macro preprocessor for the Netwide Assembler
50 /* Typical flow of text through preproc
52 * pp_getline gets tokenized lines, either
54 * from a macro expansion
56 * or
57 * {
58 * read_line gets raw text from stdmacpos, or predef, or current input file
59 * tokenize converts to tokens
60 * }
62 * expand_mmac_params is used to expand %1 etc., unless a macro is being
63 * defined or a false conditional is being processed
64 * (%0, %1, %+1, %-1, %%foo
66 * do_directive checks for directives
68 * expand_smacro is used to expand single line macros
70 * expand_mmacro is used to expand multi-line macros
72 * detoken is used to convert the line back to text
75 #include "compiler.h"
77 #include <stdio.h>
78 #include <stdarg.h>
79 #include <stdlib.h>
80 #include <stddef.h>
81 #include <string.h>
82 #include <ctype.h>
83 #include <limits.h>
84 #include <inttypes.h>
86 #include "nasm.h"
87 #include "nasmlib.h"
88 #include "preproc.h"
89 #include "hashtbl.h"
90 #include "quote.h"
91 #include "stdscan.h"
92 #include "tokens.h"
93 #include "tables.h"
95 typedef struct SMacro SMacro;
96 typedef struct MMacro MMacro;
97 typedef struct Context Context;
98 typedef struct Token Token;
99 typedef struct Blocks Blocks;
100 typedef struct Line Line;
101 typedef struct Include Include;
102 typedef struct Cond Cond;
103 typedef struct IncPath IncPath;
106 * Note on the storage of both SMacro and MMacros: the hash table
107 * indexes them case-insensitively, and we then have to go through a
108 * linked list of potential case aliases (and, for MMacros, parameter
109 * ranges); this is to preserve the matching semantics of the earlier
110 * code. If the number of case aliases for a specific macro is a
111 * performance issue, you may want to reconsider your coding style.
115 * Store the definition of a single-line macro.
117 struct SMacro {
118 SMacro *next;
119 char *name;
120 bool casesense;
121 bool in_progress;
122 unsigned int nparam;
123 Token *expansion;
127 * Store the definition of a multi-line macro. This is also used to
128 * store the interiors of `%rep...%endrep' blocks, which are
129 * effectively self-re-invoking multi-line macros which simply
130 * don't have a name or bother to appear in the hash tables. %rep
131 * blocks are signified by having a NULL `name' field.
133 * In a MMacro describing a `%rep' block, the `in_progress' field
134 * isn't merely boolean, but gives the number of repeats left to
135 * run.
137 * The `next' field is used for storing MMacros in hash tables; the
138 * `next_active' field is for stacking them on istk entries.
140 * When a MMacro is being expanded, `params', `iline', `nparam',
141 * `paramlen', `rotate' and `unique' are local to the invocation.
143 struct MMacro {
144 MMacro *next;
145 char *name;
146 int nparam_min, nparam_max;
147 bool casesense;
148 bool plus; /* is the last parameter greedy? */
149 bool nolist; /* is this macro listing-inhibited? */
150 int64_t in_progress;
151 Token *dlist; /* All defaults as one list */
152 Token **defaults; /* Parameter default pointers */
153 int ndefs; /* number of default parameters */
154 Line *expansion;
156 MMacro *next_active;
157 MMacro *rep_nest; /* used for nesting %rep */
158 Token **params; /* actual parameters */
159 Token *iline; /* invocation line */
160 unsigned int nparam, rotate;
161 int *paramlen;
162 uint64_t unique;
163 int lineno; /* Current line number on expansion */
167 * The context stack is composed of a linked list of these.
169 struct Context {
170 Context *next;
171 char *name;
172 struct hash_table localmac;
173 uint32_t number;
177 * This is the internal form which we break input lines up into.
178 * Typically stored in linked lists.
180 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
181 * necessarily used as-is, but is intended to denote the number of
182 * the substituted parameter. So in the definition
184 * %define a(x,y) ( (x) & ~(y) )
186 * the token representing `x' will have its type changed to
187 * TOK_SMAC_PARAM, but the one representing `y' will be
188 * TOK_SMAC_PARAM+1.
190 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
191 * which doesn't need quotes around it. Used in the pre-include
192 * mechanism as an alternative to trying to find a sensible type of
193 * quote to use on the filename we were passed.
195 enum pp_token_type {
196 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID,
197 TOK_PREPROC_ID, TOK_STRING,
198 TOK_NUMBER, TOK_FLOAT, TOK_SMAC_END, TOK_OTHER,
199 TOK_INTERNAL_STRING,
200 TOK_PREPROC_Q, TOK_PREPROC_QQ,
201 TOK_PASTE, /* %+ */
202 TOK_INDIRECT, /* %[...] */
203 TOK_SMAC_PARAM, /* MUST BE LAST IN THE LIST!!! */
204 TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
207 struct Token {
208 Token *next;
209 char *text;
210 union {
211 SMacro *mac; /* associated macro for TOK_SMAC_END */
212 size_t len; /* scratch length field */
213 } a; /* Auxiliary data */
214 enum pp_token_type type;
218 * Multi-line macro definitions are stored as a linked list of
219 * these, which is essentially a container to allow several linked
220 * lists of Tokens.
222 * Note that in this module, linked lists are treated as stacks
223 * wherever possible. For this reason, Lines are _pushed_ on to the
224 * `expansion' field in MMacro structures, so that the linked list,
225 * if walked, would give the macro lines in reverse order; this
226 * means that we can walk the list when expanding a macro, and thus
227 * push the lines on to the `expansion' field in _istk_ in reverse
228 * order (so that when popped back off they are in the right
229 * order). It may seem cockeyed, and it relies on my design having
230 * an even number of steps in, but it works...
232 * Some of these structures, rather than being actual lines, are
233 * markers delimiting the end of the expansion of a given macro.
234 * This is for use in the cycle-tracking and %rep-handling code.
235 * Such structures have `finishes' non-NULL, and `first' NULL. All
236 * others have `finishes' NULL, but `first' may still be NULL if
237 * the line is blank.
239 struct Line {
240 Line *next;
241 MMacro *finishes;
242 Token *first;
246 * To handle an arbitrary level of file inclusion, we maintain a
247 * stack (ie linked list) of these things.
249 struct Include {
250 Include *next;
251 FILE *fp;
252 Cond *conds;
253 Line *expansion;
254 char *fname;
255 int lineno, lineinc;
256 MMacro *mstk; /* stack of active macros/reps */
260 * Include search path. This is simply a list of strings which get
261 * prepended, in turn, to the name of an include file, in an
262 * attempt to find the file if it's not in the current directory.
264 struct IncPath {
265 IncPath *next;
266 char *path;
270 * Conditional assembly: we maintain a separate stack of these for
271 * each level of file inclusion. (The only reason we keep the
272 * stacks separate is to ensure that a stray `%endif' in a file
273 * included from within the true branch of a `%if' won't terminate
274 * it and cause confusion: instead, rightly, it'll cause an error.)
276 struct Cond {
277 Cond *next;
278 int state;
280 enum {
282 * These states are for use just after %if or %elif: IF_TRUE
283 * means the condition has evaluated to truth so we are
284 * currently emitting, whereas IF_FALSE means we are not
285 * currently emitting but will start doing so if a %else comes
286 * up. In these states, all directives are admissible: %elif,
287 * %else and %endif. (And of course %if.)
289 COND_IF_TRUE, COND_IF_FALSE,
291 * These states come up after a %else: ELSE_TRUE means we're
292 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
293 * any %elif or %else will cause an error.
295 COND_ELSE_TRUE, COND_ELSE_FALSE,
297 * These states mean that we're not emitting now, and also that
298 * nothing until %endif will be emitted at all. COND_DONE is
299 * used when we've had our moment of emission
300 * and have now started seeing %elifs. COND_NEVER is used when
301 * the condition construct in question is contained within a
302 * non-emitting branch of a larger condition construct,
303 * or if there is an error.
305 COND_DONE, COND_NEVER
307 #define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
310 * These defines are used as the possible return values for do_directive
312 #define NO_DIRECTIVE_FOUND 0
313 #define DIRECTIVE_FOUND 1
316 * Condition codes. Note that we use c_ prefix not C_ because C_ is
317 * used in nasm.h for the "real" condition codes. At _this_ level,
318 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
319 * ones, so we need a different enum...
321 static const char * const conditions[] = {
322 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
323 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
324 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
326 enum pp_conds {
327 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
328 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
329 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
330 c_none = -1
332 static const enum pp_conds inverse_ccs[] = {
333 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
334 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,
335 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
339 * Directive names.
341 /* If this is a an IF, ELIF, ELSE or ENDIF keyword */
342 static int is_condition(enum preproc_token arg)
344 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
347 /* For TASM compatibility we need to be able to recognise TASM compatible
348 * conditional compilation directives. Using the NASM pre-processor does
349 * not work, so we look for them specifically from the following list and
350 * then jam in the equivalent NASM directive into the input stream.
353 enum {
354 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
355 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
358 static const char * const tasm_directives[] = {
359 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
360 "ifndef", "include", "local"
363 static int StackSize = 4;
364 static char *StackPointer = "ebp";
365 static int ArgOffset = 8;
366 static int LocalOffset = 0;
368 static Context *cstk;
369 static Include *istk;
370 static IncPath *ipath = NULL;
372 static efunc _error; /* Pointer to client-provided error reporting function */
373 static evalfunc evaluate;
375 static int pass; /* HACK: pass 0 = generate dependencies only */
376 static StrList **dephead, **deptail; /* Dependency list */
378 static uint64_t unique; /* unique identifier numbers */
380 static Line *predef = NULL;
381 static bool do_predef;
383 static ListGen *list;
386 * The current set of multi-line macros we have defined.
388 static struct hash_table mmacros;
391 * The current set of single-line macros we have defined.
393 static struct hash_table smacros;
396 * The multi-line macro we are currently defining, or the %rep
397 * block we are currently reading, if any.
399 static MMacro *defining;
401 static uint64_t nested_mac_count;
402 static uint64_t nested_rep_count;
405 * The number of macro parameters to allocate space for at a time.
407 #define PARAM_DELTA 16
410 * The standard macro set: defined in macros.c in the array nasm_stdmac.
411 * This gives our position in the macro set, when we're processing it.
413 static macros_t *stdmacpos;
416 * The extra standard macros that come from the object format, if
417 * any.
419 static macros_t *extrastdmac = NULL;
420 static bool any_extrastdmac;
423 * Tokens are allocated in blocks to improve speed
425 #define TOKEN_BLOCKSIZE 4096
426 static Token *freeTokens = NULL;
427 struct Blocks {
428 Blocks *next;
429 void *chunk;
432 static Blocks blocks = { NULL, NULL };
435 * Forward declarations.
437 static Token *expand_mmac_params(Token * tline);
438 static Token *expand_smacro(Token * tline);
439 static Token *expand_id(Token * tline);
440 static Context *get_ctx(const char *name, const char **namep,
441 bool all_contexts);
442 static void make_tok_num(Token * tok, int64_t val);
443 static void error(int severity, const char *fmt, ...);
444 static void error_precond(int severity, const char *fmt, ...);
445 static void *new_Block(size_t size);
446 static void delete_Blocks(void);
447 static Token *new_Token(Token * next, enum pp_token_type type,
448 const char *text, int txtlen);
449 static Token *delete_Token(Token * t);
452 * Macros for safe checking of token pointers, avoid *(NULL)
454 #define tok_type_(x,t) ((x) && (x)->type == (t))
455 #define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
456 #define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
457 #define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
459 /* Handle TASM specific directives, which do not contain a % in
460 * front of them. We do it here because I could not find any other
461 * place to do it for the moment, and it is a hack (ideally it would
462 * be nice to be able to use the NASM pre-processor to do it).
464 static char *check_tasm_directive(char *line)
466 int32_t i, j, k, m, len;
467 char *p = line, *oldline, oldchar;
469 /* Skip whitespace */
470 while (nasm_isspace(*p) && *p != 0)
471 p++;
473 /* Binary search for the directive name */
474 i = -1;
475 j = elements(tasm_directives);
476 len = 0;
477 while (!nasm_isspace(p[len]) && p[len] != 0)
478 len++;
479 if (len) {
480 oldchar = p[len];
481 p[len] = 0;
482 while (j - i > 1) {
483 k = (j + i) / 2;
484 m = nasm_stricmp(p, tasm_directives[k]);
485 if (m == 0) {
486 /* We have found a directive, so jam a % in front of it
487 * so that NASM will then recognise it as one if it's own.
489 p[len] = oldchar;
490 len = strlen(p);
491 oldline = line;
492 line = nasm_malloc(len + 2);
493 line[0] = '%';
494 if (k == TM_IFDIFI) {
496 * NASM does not recognise IFDIFI, so we convert
497 * it to %if 0. This is not used in NASM
498 * compatible code, but does need to parse for the
499 * TASM macro package.
501 strcpy(line + 1, "if 0");
502 } else {
503 memcpy(line + 1, p, len + 1);
505 nasm_free(oldline);
506 return line;
507 } else if (m < 0) {
508 j = k;
509 } else
510 i = k;
512 p[len] = oldchar;
514 return line;
518 * The pre-preprocessing stage... This function translates line
519 * number indications as they emerge from GNU cpp (`# lineno "file"
520 * flags') into NASM preprocessor line number indications (`%line
521 * lineno file').
523 static char *prepreproc(char *line)
525 int lineno, fnlen;
526 char *fname, *oldline;
528 if (line[0] == '#' && line[1] == ' ') {
529 oldline = line;
530 fname = oldline + 2;
531 lineno = atoi(fname);
532 fname += strspn(fname, "0123456789 ");
533 if (*fname == '"')
534 fname++;
535 fnlen = strcspn(fname, "\"");
536 line = nasm_malloc(20 + fnlen);
537 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
538 nasm_free(oldline);
540 if (tasm_compatible_mode)
541 return check_tasm_directive(line);
542 return line;
546 * Free a linked list of tokens.
548 static void free_tlist(Token * list)
550 while (list) {
551 list = delete_Token(list);
556 * Free a linked list of lines.
558 static void free_llist(Line * list)
560 Line *l;
561 while (list) {
562 l = list;
563 list = list->next;
564 free_tlist(l->first);
565 nasm_free(l);
570 * Free an MMacro
572 static void free_mmacro(MMacro * m)
574 nasm_free(m->name);
575 free_tlist(m->dlist);
576 nasm_free(m->defaults);
577 free_llist(m->expansion);
578 nasm_free(m);
582 * Free all currently defined macros, and free the hash tables
584 static void free_smacro_table(struct hash_table *smt)
586 SMacro *s;
587 const char *key;
588 struct hash_tbl_node *it = NULL;
590 while ((s = hash_iterate(smt, &it, &key)) != NULL) {
591 nasm_free((void *)key);
592 while (s) {
593 SMacro *ns = s->next;
594 nasm_free(s->name);
595 free_tlist(s->expansion);
596 nasm_free(s);
597 s = ns;
600 hash_free(smt);
603 static void free_mmacro_table(struct hash_table *mmt)
605 MMacro *m;
606 const char *key;
607 struct hash_tbl_node *it = NULL;
609 it = NULL;
610 while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
611 nasm_free((void *)key);
612 while (m) {
613 MMacro *nm = m->next;
614 free_mmacro(m);
615 m = nm;
618 hash_free(mmt);
621 static void free_macros(void)
623 free_smacro_table(&smacros);
624 free_mmacro_table(&mmacros);
628 * Initialize the hash tables
630 static void init_macros(void)
632 hash_init(&smacros, HASH_LARGE);
633 hash_init(&mmacros, HASH_LARGE);
637 * Pop the context stack.
639 static void ctx_pop(void)
641 Context *c = cstk;
643 cstk = cstk->next;
644 free_smacro_table(&c->localmac);
645 nasm_free(c->name);
646 nasm_free(c);
650 * Search for a key in the hash index; adding it if necessary
651 * (in which case we initialize the data pointer to NULL.)
653 static void **
654 hash_findi_add(struct hash_table *hash, const char *str)
656 struct hash_insert hi;
657 void **r;
658 char *strx;
660 r = hash_findi(hash, str, &hi);
661 if (r)
662 return r;
664 strx = nasm_strdup(str); /* Use a more efficient allocator here? */
665 return hash_add(&hi, strx, NULL);
669 * Like hash_findi, but returns the data element rather than a pointer
670 * to it. Used only when not adding a new element, hence no third
671 * argument.
673 static void *
674 hash_findix(struct hash_table *hash, const char *str)
676 void **p;
678 p = hash_findi(hash, str, NULL);
679 return p ? *p : NULL;
682 #define BUF_DELTA 512
684 * Read a line from the top file in istk, handling multiple CR/LFs
685 * at the end of the line read, and handling spurious ^Zs. Will
686 * return lines from the standard macro set if this has not already
687 * been done.
689 static char *read_line(void)
691 char *buffer, *p, *q;
692 int bufsize, continued_count;
694 if (stdmacpos) {
695 unsigned char c;
696 const unsigned char *p = stdmacpos;
697 char *ret, *q;
698 size_t len = 0;
699 while ((c = *p++)) {
700 if (c >= 0x80)
701 len += pp_directives_len[c-0x80]+1;
702 else
703 len++;
705 ret = nasm_malloc(len+1);
706 q = ret;
707 while ((c = *stdmacpos++)) {
708 if (c >= 0x80) {
709 memcpy(q, pp_directives[c-0x80], pp_directives_len[c-0x80]);
710 q += pp_directives_len[c-0x80];
711 *q++ = ' ';
712 } else {
713 *q++ = c;
716 stdmacpos = p;
717 *q = '\0';
719 if (!*stdmacpos) {
720 /* This was the last of the standard macro chain... */
721 stdmacpos = NULL;
722 if (any_extrastdmac) {
723 stdmacpos = extrastdmac;
724 any_extrastdmac = false;
725 } else if (do_predef) {
726 Line *pd, *l;
727 Token *head, **tail, *t;
730 * Nasty hack: here we push the contents of
731 * `predef' on to the top-level expansion stack,
732 * since this is the most convenient way to
733 * implement the pre-include and pre-define
734 * features.
736 for (pd = predef; pd; pd = pd->next) {
737 head = NULL;
738 tail = &head;
739 for (t = pd->first; t; t = t->next) {
740 *tail = new_Token(NULL, t->type, t->text, 0);
741 tail = &(*tail)->next;
743 l = nasm_malloc(sizeof(Line));
744 l->next = istk->expansion;
745 l->first = head;
746 l->finishes = NULL;
747 istk->expansion = l;
749 do_predef = false;
752 return ret;
755 bufsize = BUF_DELTA;
756 buffer = nasm_malloc(BUF_DELTA);
757 p = buffer;
758 continued_count = 0;
759 while (1) {
760 q = fgets(p, bufsize - (p - buffer), istk->fp);
761 if (!q)
762 break;
763 p += strlen(p);
764 if (p > buffer && p[-1] == '\n') {
765 /* Convert backslash-CRLF line continuation sequences into
766 nothing at all (for DOS and Windows) */
767 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
768 p -= 3;
769 *p = 0;
770 continued_count++;
772 /* Also convert backslash-LF line continuation sequences into
773 nothing at all (for Unix) */
774 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
775 p -= 2;
776 *p = 0;
777 continued_count++;
778 } else {
779 break;
782 if (p - buffer > bufsize - 10) {
783 int32_t offset = p - buffer;
784 bufsize += BUF_DELTA;
785 buffer = nasm_realloc(buffer, bufsize);
786 p = buffer + offset; /* prevent stale-pointer problems */
790 if (!q && p == buffer) {
791 nasm_free(buffer);
792 return NULL;
795 src_set_linnum(src_get_linnum() + istk->lineinc +
796 (continued_count * istk->lineinc));
799 * Play safe: remove CRs as well as LFs, if any of either are
800 * present at the end of the line.
802 while (--p >= buffer && (*p == '\n' || *p == '\r'))
803 *p = '\0';
806 * Handle spurious ^Z, which may be inserted into source files
807 * by some file transfer utilities.
809 buffer[strcspn(buffer, "\032")] = '\0';
811 list->line(LIST_READ, buffer);
813 return buffer;
817 * Tokenize a line of text. This is a very simple process since we
818 * don't need to parse the value out of e.g. numeric tokens: we
819 * simply split one string into many.
821 static Token *tokenize(char *line)
823 char c, *p = line;
824 enum pp_token_type type;
825 Token *list = NULL;
826 Token *t, **tail = &list;
828 while (*line) {
829 p = line;
830 if (*p == '%') {
831 p++;
832 if (*p == '+' && !nasm_isdigit(p[1])) {
833 p++;
834 type = TOK_PASTE;
835 } else if (nasm_isdigit(*p) ||
836 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
837 do {
838 p++;
840 while (nasm_isdigit(*p));
841 type = TOK_PREPROC_ID;
842 } else if (*p == '{') {
843 p++;
844 while (*p && *p != '}') {
845 p[-1] = *p;
846 p++;
848 p[-1] = '\0';
849 if (*p)
850 p++;
851 type = TOK_PREPROC_ID;
852 } else if (*p == '[') {
853 int lvl = 1;
854 line += 2; /* Skip the leading %[ */
855 p++;
856 while (lvl && (c = *p++)) {
857 switch (c) {
858 case ']':
859 lvl--;
860 break;
861 case '%':
862 if (*p == '[')
863 lvl++;
864 break;
865 case '\'':
866 case '\"':
867 case '`':
868 p = nasm_skip_string(p)+1;
869 break;
870 default:
871 break;
874 p--;
875 if (*p)
876 *p++ = '\0';
877 if (lvl)
878 error(ERR_NONFATAL, "unterminated %[ construct");
879 type = TOK_INDIRECT;
880 } else if (*p == '?') {
881 type = TOK_PREPROC_Q; /* %? */
882 p++;
883 if (*p == '?') {
884 type = TOK_PREPROC_QQ; /* %?? */
885 p++;
887 } else if (isidchar(*p) ||
888 ((*p == '!' || *p == '%' || *p == '$') &&
889 isidchar(p[1]))) {
890 do {
891 p++;
893 while (isidchar(*p));
894 type = TOK_PREPROC_ID;
895 } else {
896 type = TOK_OTHER;
897 if (*p == '%')
898 p++;
900 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
901 type = TOK_ID;
902 p++;
903 while (*p && isidchar(*p))
904 p++;
905 } else if (*p == '\'' || *p == '"' || *p == '`') {
907 * A string token.
909 type = TOK_STRING;
910 p = nasm_skip_string(p);
912 if (*p) {
913 p++;
914 } else {
915 error(ERR_WARNING|ERR_PASS1, "unterminated string");
916 /* Handling unterminated strings by UNV */
917 /* type = -1; */
919 } else if (p[0] == '$' && p[1] == '$') {
920 type = TOK_OTHER; /* TOKEN_BASE */
921 p += 2;
922 } else if (isnumstart(*p)) {
923 bool is_hex = false;
924 bool is_float = false;
925 bool has_e = false;
926 char c, *r;
929 * A numeric token.
932 if (*p == '$') {
933 p++;
934 is_hex = true;
937 for (;;) {
938 c = *p++;
940 if (!is_hex && (c == 'e' || c == 'E')) {
941 has_e = true;
942 if (*p == '+' || *p == '-') {
943 /* e can only be followed by +/- if it is either a
944 prefixed hex number or a floating-point number */
945 p++;
946 is_float = true;
948 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
949 is_hex = true;
950 } else if (c == 'P' || c == 'p') {
951 is_float = true;
952 if (*p == '+' || *p == '-')
953 p++;
954 } else if (isnumchar(c) || c == '_')
955 ; /* just advance */
956 else if (c == '.') {
957 /* we need to deal with consequences of the legacy
958 parser, like "1.nolist" being two tokens
959 (TOK_NUMBER, TOK_ID) here; at least give it
960 a shot for now. In the future, we probably need
961 a flex-based scanner with proper pattern matching
962 to do it as well as it can be done. Nothing in
963 the world is going to help the person who wants
964 0x123.p16 interpreted as two tokens, though. */
965 r = p;
966 while (*r == '_')
967 r++;
969 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
970 (!is_hex && (*r == 'e' || *r == 'E')) ||
971 (*r == 'p' || *r == 'P')) {
972 p = r;
973 is_float = true;
974 } else
975 break; /* Terminate the token */
976 } else
977 break;
979 p--; /* Point to first character beyond number */
981 if (p == line+1 && *line == '$') {
982 type = TOK_OTHER; /* TOKEN_HERE */
983 } else {
984 if (has_e && !is_hex) {
985 /* 1e13 is floating-point, but 1e13h is not */
986 is_float = true;
989 type = is_float ? TOK_FLOAT : TOK_NUMBER;
991 } else if (nasm_isspace(*p)) {
992 type = TOK_WHITESPACE;
993 p++;
994 while (*p && nasm_isspace(*p))
995 p++;
997 * Whitespace just before end-of-line is discarded by
998 * pretending it's a comment; whitespace just before a
999 * comment gets lumped into the comment.
1001 if (!*p || *p == ';') {
1002 type = TOK_COMMENT;
1003 while (*p)
1004 p++;
1006 } else if (*p == ';') {
1007 type = TOK_COMMENT;
1008 while (*p)
1009 p++;
1010 } else {
1012 * Anything else is an operator of some kind. We check
1013 * for all the double-character operators (>>, <<, //,
1014 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
1015 * else is a single-character operator.
1017 type = TOK_OTHER;
1018 if ((p[0] == '>' && p[1] == '>') ||
1019 (p[0] == '<' && p[1] == '<') ||
1020 (p[0] == '/' && p[1] == '/') ||
1021 (p[0] == '<' && p[1] == '=') ||
1022 (p[0] == '>' && p[1] == '=') ||
1023 (p[0] == '=' && p[1] == '=') ||
1024 (p[0] == '!' && p[1] == '=') ||
1025 (p[0] == '<' && p[1] == '>') ||
1026 (p[0] == '&' && p[1] == '&') ||
1027 (p[0] == '|' && p[1] == '|') ||
1028 (p[0] == '^' && p[1] == '^')) {
1029 p++;
1031 p++;
1034 /* Handling unterminated string by UNV */
1035 /*if (type == -1)
1037 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1038 t->text[p-line] = *line;
1039 tail = &t->next;
1041 else */
1042 if (type != TOK_COMMENT) {
1043 *tail = t = new_Token(NULL, type, line, p - line);
1044 tail = &t->next;
1046 line = p;
1048 return list;
1052 * this function allocates a new managed block of memory and
1053 * returns a pointer to the block. The managed blocks are
1054 * deleted only all at once by the delete_Blocks function.
1056 static void *new_Block(size_t size)
1058 Blocks *b = &blocks;
1060 /* first, get to the end of the linked list */
1061 while (b->next)
1062 b = b->next;
1063 /* now allocate the requested chunk */
1064 b->chunk = nasm_malloc(size);
1066 /* now allocate a new block for the next request */
1067 b->next = nasm_malloc(sizeof(Blocks));
1068 /* and initialize the contents of the new block */
1069 b->next->next = NULL;
1070 b->next->chunk = NULL;
1071 return b->chunk;
1075 * this function deletes all managed blocks of memory
1077 static void delete_Blocks(void)
1079 Blocks *a, *b = &blocks;
1082 * keep in mind that the first block, pointed to by blocks
1083 * is a static and not dynamically allocated, so we don't
1084 * free it.
1086 while (b) {
1087 if (b->chunk)
1088 nasm_free(b->chunk);
1089 a = b;
1090 b = b->next;
1091 if (a != &blocks)
1092 nasm_free(a);
1097 * this function creates a new Token and passes a pointer to it
1098 * back to the caller. It sets the type and text elements, and
1099 * also the a.mac and next elements to NULL.
1101 static Token *new_Token(Token * next, enum pp_token_type type,
1102 const char *text, int txtlen)
1104 Token *t;
1105 int i;
1107 if (freeTokens == NULL) {
1108 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
1109 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
1110 freeTokens[i].next = &freeTokens[i + 1];
1111 freeTokens[i].next = NULL;
1113 t = freeTokens;
1114 freeTokens = t->next;
1115 t->next = next;
1116 t->a.mac = NULL;
1117 t->type = type;
1118 if (type == TOK_WHITESPACE || text == NULL) {
1119 t->text = NULL;
1120 } else {
1121 if (txtlen == 0)
1122 txtlen = strlen(text);
1123 t->text = nasm_malloc(txtlen+1);
1124 memcpy(t->text, text, txtlen);
1125 t->text[txtlen] = '\0';
1127 return t;
1130 static Token *delete_Token(Token * t)
1132 Token *next = t->next;
1133 nasm_free(t->text);
1134 t->next = freeTokens;
1135 freeTokens = t;
1136 return next;
1140 * Convert a line of tokens back into text.
1141 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1142 * will be transformed into ..@ctxnum.xxx
1144 static char *detoken(Token * tlist, bool expand_locals)
1146 Token *t;
1147 int len;
1148 char *line, *p;
1149 const char *q;
1151 len = 0;
1152 for (t = tlist; t; t = t->next) {
1153 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
1154 char *p = getenv(t->text + 2);
1155 nasm_free(t->text);
1156 if (p)
1157 t->text = nasm_strdup(p);
1158 else
1159 t->text = NULL;
1161 /* Expand local macros here and not during preprocessing */
1162 if (expand_locals &&
1163 t->type == TOK_PREPROC_ID && t->text &&
1164 t->text[0] == '%' && t->text[1] == '$') {
1165 const char *q;
1166 char *p;
1167 Context *ctx = get_ctx(t->text, &q, false);
1168 if (ctx) {
1169 char buffer[40];
1170 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
1171 p = nasm_strcat(buffer, q);
1172 nasm_free(t->text);
1173 t->text = p;
1176 if (t->type == TOK_WHITESPACE) {
1177 len++;
1178 } else if (t->text) {
1179 len += strlen(t->text);
1182 p = line = nasm_malloc(len + 1);
1183 for (t = tlist; t; t = t->next) {
1184 if (t->type == TOK_WHITESPACE) {
1185 *p++ = ' ';
1186 } else if (t->text) {
1187 q = t->text;
1188 while (*q)
1189 *p++ = *q++;
1192 *p = '\0';
1193 return line;
1197 * A scanner, suitable for use by the expression evaluator, which
1198 * operates on a line of Tokens. Expects a pointer to a pointer to
1199 * the first token in the line to be passed in as its private_data
1200 * field.
1202 * FIX: This really needs to be unified with stdscan.
1204 static int ppscan(void *private_data, struct tokenval *tokval)
1206 Token **tlineptr = private_data;
1207 Token *tline;
1208 char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
1210 do {
1211 tline = *tlineptr;
1212 *tlineptr = tline ? tline->next : NULL;
1214 while (tline && (tline->type == TOK_WHITESPACE ||
1215 tline->type == TOK_COMMENT));
1217 if (!tline)
1218 return tokval->t_type = TOKEN_EOS;
1220 tokval->t_charptr = tline->text;
1222 if (tline->text[0] == '$' && !tline->text[1])
1223 return tokval->t_type = TOKEN_HERE;
1224 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
1225 return tokval->t_type = TOKEN_BASE;
1227 if (tline->type == TOK_ID) {
1228 p = tokval->t_charptr = tline->text;
1229 if (p[0] == '$') {
1230 tokval->t_charptr++;
1231 return tokval->t_type = TOKEN_ID;
1234 for (r = p, s = ourcopy; *r; r++) {
1235 if (r >= p+MAX_KEYWORD)
1236 return tokval->t_type = TOKEN_ID; /* Not a keyword */
1237 *s++ = nasm_tolower(*r);
1239 *s = '\0';
1240 /* right, so we have an identifier sitting in temp storage. now,
1241 * is it actually a register or instruction name, or what? */
1242 return nasm_token_hash(ourcopy, tokval);
1245 if (tline->type == TOK_NUMBER) {
1246 bool rn_error;
1247 tokval->t_integer = readnum(tline->text, &rn_error);
1248 tokval->t_charptr = tline->text;
1249 if (rn_error)
1250 return tokval->t_type = TOKEN_ERRNUM;
1251 else
1252 return tokval->t_type = TOKEN_NUM;
1255 if (tline->type == TOK_FLOAT) {
1256 return tokval->t_type = TOKEN_FLOAT;
1259 if (tline->type == TOK_STRING) {
1260 char bq, *ep;
1262 bq = tline->text[0];
1263 tokval->t_charptr = tline->text;
1264 tokval->t_inttwo = nasm_unquote(tline->text, &ep);
1266 if (ep[0] != bq || ep[1] != '\0')
1267 return tokval->t_type = TOKEN_ERRSTR;
1268 else
1269 return tokval->t_type = TOKEN_STR;
1272 if (tline->type == TOK_OTHER) {
1273 if (!strcmp(tline->text, "<<"))
1274 return tokval->t_type = TOKEN_SHL;
1275 if (!strcmp(tline->text, ">>"))
1276 return tokval->t_type = TOKEN_SHR;
1277 if (!strcmp(tline->text, "//"))
1278 return tokval->t_type = TOKEN_SDIV;
1279 if (!strcmp(tline->text, "%%"))
1280 return tokval->t_type = TOKEN_SMOD;
1281 if (!strcmp(tline->text, "=="))
1282 return tokval->t_type = TOKEN_EQ;
1283 if (!strcmp(tline->text, "<>"))
1284 return tokval->t_type = TOKEN_NE;
1285 if (!strcmp(tline->text, "!="))
1286 return tokval->t_type = TOKEN_NE;
1287 if (!strcmp(tline->text, "<="))
1288 return tokval->t_type = TOKEN_LE;
1289 if (!strcmp(tline->text, ">="))
1290 return tokval->t_type = TOKEN_GE;
1291 if (!strcmp(tline->text, "&&"))
1292 return tokval->t_type = TOKEN_DBL_AND;
1293 if (!strcmp(tline->text, "^^"))
1294 return tokval->t_type = TOKEN_DBL_XOR;
1295 if (!strcmp(tline->text, "||"))
1296 return tokval->t_type = TOKEN_DBL_OR;
1300 * We have no other options: just return the first character of
1301 * the token text.
1303 return tokval->t_type = tline->text[0];
1307 * Compare a string to the name of an existing macro; this is a
1308 * simple wrapper which calls either strcmp or nasm_stricmp
1309 * depending on the value of the `casesense' parameter.
1311 static int mstrcmp(const char *p, const char *q, bool casesense)
1313 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
1317 * Compare a string to the name of an existing macro; this is a
1318 * simple wrapper which calls either strcmp or nasm_stricmp
1319 * depending on the value of the `casesense' parameter.
1321 static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
1323 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
1327 * Return the Context structure associated with a %$ token. Return
1328 * NULL, having _already_ reported an error condition, if the
1329 * context stack isn't deep enough for the supplied number of $
1330 * signs.
1331 * If all_contexts == true, contexts that enclose current are
1332 * also scanned for such smacro, until it is found; if not -
1333 * only the context that directly results from the number of $'s
1334 * in variable's name.
1336 * If "namep" is non-NULL, set it to the pointer to the macro name
1337 * tail, i.e. the part beyond %$...
1339 static Context *get_ctx(const char *name, const char **namep,
1340 bool all_contexts)
1342 Context *ctx;
1343 SMacro *m;
1344 int i;
1346 if (namep)
1347 *namep = name;
1349 if (!name || name[0] != '%' || name[1] != '$')
1350 return NULL;
1352 if (!cstk) {
1353 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1354 return NULL;
1357 name += 2;
1358 ctx = cstk;
1359 i = 0;
1360 while (ctx && *name == '$') {
1361 name++;
1362 i++;
1363 ctx = ctx->next;
1365 if (!ctx) {
1366 error(ERR_NONFATAL, "`%s': context stack is only"
1367 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
1368 return NULL;
1371 if (namep)
1372 *namep = name;
1374 if (!all_contexts)
1375 return ctx;
1377 do {
1378 /* Search for this smacro in found context */
1379 m = hash_findix(&ctx->localmac, name);
1380 while (m) {
1381 if (!mstrcmp(m->name, name, m->casesense))
1382 return ctx;
1383 m = m->next;
1385 ctx = ctx->next;
1387 while (ctx);
1388 return NULL;
1392 * Check to see if a file is already in a string list
1394 static bool in_list(const StrList *list, const char *str)
1396 while (list) {
1397 if (!strcmp(list->str, str))
1398 return true;
1399 list = list->next;
1401 return false;
1405 * Open an include file. This routine must always return a valid
1406 * file pointer if it returns - it's responsible for throwing an
1407 * ERR_FATAL and bombing out completely if not. It should also try
1408 * the include path one by one until it finds the file or reaches
1409 * the end of the path.
1411 static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
1412 bool missing_ok)
1414 FILE *fp;
1415 char *prefix = "";
1416 IncPath *ip = ipath;
1417 int len = strlen(file);
1418 size_t prefix_len = 0;
1419 StrList *sl;
1421 while (1) {
1422 sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
1423 memcpy(sl->str, prefix, prefix_len);
1424 memcpy(sl->str+prefix_len, file, len+1);
1425 fp = fopen(sl->str, "r");
1426 if (fp && dhead && !in_list(*dhead, sl->str)) {
1427 sl->next = NULL;
1428 **dtail = sl;
1429 *dtail = &sl->next;
1430 } else {
1431 nasm_free(sl);
1433 if (fp)
1434 return fp;
1435 if (!ip) {
1436 if (!missing_ok)
1437 break;
1438 prefix = NULL;
1439 } else {
1440 prefix = ip->path;
1441 ip = ip->next;
1443 if (prefix) {
1444 prefix_len = strlen(prefix);
1445 } else {
1446 /* -MG given and file not found */
1447 if (dhead && !in_list(*dhead, file)) {
1448 sl = nasm_malloc(len+1+sizeof sl->next);
1449 sl->next = NULL;
1450 strcpy(sl->str, file);
1451 **dtail = sl;
1452 *dtail = &sl->next;
1454 return NULL;
1458 error(ERR_FATAL, "unable to open include file `%s'", file);
1459 return NULL; /* never reached - placate compilers */
1463 * Determine if we should warn on defining a single-line macro of
1464 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
1465 * return true if _any_ single-line macro of that name is defined.
1466 * Otherwise, will return true if a single-line macro with either
1467 * `nparam' or no parameters is defined.
1469 * If a macro with precisely the right number of parameters is
1470 * defined, or nparam is -1, the address of the definition structure
1471 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
1472 * is NULL, no action will be taken regarding its contents, and no
1473 * error will occur.
1475 * Note that this is also called with nparam zero to resolve
1476 * `ifdef'.
1478 * If you already know which context macro belongs to, you can pass
1479 * the context pointer as first parameter; if you won't but name begins
1480 * with %$ the context will be automatically computed. If all_contexts
1481 * is true, macro will be searched in outer contexts as well.
1483 static bool
1484 smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
1485 bool nocase)
1487 struct hash_table *smtbl;
1488 SMacro *m;
1490 if (ctx) {
1491 smtbl = &ctx->localmac;
1492 } else if (name[0] == '%' && name[1] == '$') {
1493 if (cstk)
1494 ctx = get_ctx(name, &name, false);
1495 if (!ctx)
1496 return false; /* got to return _something_ */
1497 smtbl = &ctx->localmac;
1498 } else {
1499 smtbl = &smacros;
1501 m = (SMacro *) hash_findix(smtbl, name);
1503 while (m) {
1504 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
1505 (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
1506 if (defn) {
1507 if (nparam == (int) m->nparam || nparam == -1)
1508 *defn = m;
1509 else
1510 *defn = NULL;
1512 return true;
1514 m = m->next;
1517 return false;
1521 * Count and mark off the parameters in a multi-line macro call.
1522 * This is called both from within the multi-line macro expansion
1523 * code, and also to mark off the default parameters when provided
1524 * in a %macro definition line.
1526 static void count_mmac_params(Token * t, int *nparam, Token *** params)
1528 int paramsize, brace;
1530 *nparam = paramsize = 0;
1531 *params = NULL;
1532 while (t) {
1533 /* +1: we need space for the final NULL */
1534 if (*nparam+1 >= paramsize) {
1535 paramsize += PARAM_DELTA;
1536 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1538 skip_white_(t);
1539 brace = false;
1540 if (tok_is_(t, "{"))
1541 brace = true;
1542 (*params)[(*nparam)++] = t;
1543 while (tok_isnt_(t, brace ? "}" : ","))
1544 t = t->next;
1545 if (t) { /* got a comma/brace */
1546 t = t->next;
1547 if (brace) {
1549 * Now we've found the closing brace, look further
1550 * for the comma.
1552 skip_white_(t);
1553 if (tok_isnt_(t, ",")) {
1554 error(ERR_NONFATAL,
1555 "braces do not enclose all of macro parameter");
1556 while (tok_isnt_(t, ","))
1557 t = t->next;
1559 if (t)
1560 t = t->next; /* eat the comma */
1567 * Determine whether one of the various `if' conditions is true or
1568 * not.
1570 * We must free the tline we get passed.
1572 static bool if_condition(Token * tline, enum preproc_token ct)
1574 enum pp_conditional i = PP_COND(ct);
1575 bool j;
1576 Token *t, *tt, **tptr, *origline;
1577 struct tokenval tokval;
1578 expr *evalresult;
1579 enum pp_token_type needtype;
1581 origline = tline;
1583 switch (i) {
1584 case PPC_IFCTX:
1585 j = false; /* have we matched yet? */
1586 while (true) {
1587 skip_white_(tline);
1588 if (!tline)
1589 break;
1590 if (tline->type != TOK_ID) {
1591 error(ERR_NONFATAL,
1592 "`%s' expects context identifiers", pp_directives[ct]);
1593 free_tlist(origline);
1594 return -1;
1596 if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name))
1597 j = true;
1598 tline = tline->next;
1600 break;
1602 case PPC_IFDEF:
1603 j = false; /* have we matched yet? */
1604 while (tline) {
1605 skip_white_(tline);
1606 if (!tline || (tline->type != TOK_ID &&
1607 (tline->type != TOK_PREPROC_ID ||
1608 tline->text[1] != '$'))) {
1609 error(ERR_NONFATAL,
1610 "`%s' expects macro identifiers", pp_directives[ct]);
1611 goto fail;
1613 if (smacro_defined(NULL, tline->text, 0, NULL, true))
1614 j = true;
1615 tline = tline->next;
1617 break;
1619 case PPC_IFIDN:
1620 case PPC_IFIDNI:
1621 tline = expand_smacro(tline);
1622 t = tt = tline;
1623 while (tok_isnt_(tt, ","))
1624 tt = tt->next;
1625 if (!tt) {
1626 error(ERR_NONFATAL,
1627 "`%s' expects two comma-separated arguments",
1628 pp_directives[ct]);
1629 goto fail;
1631 tt = tt->next;
1632 j = true; /* assume equality unless proved not */
1633 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1634 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1635 error(ERR_NONFATAL, "`%s': more than one comma on line",
1636 pp_directives[ct]);
1637 goto fail;
1639 if (t->type == TOK_WHITESPACE) {
1640 t = t->next;
1641 continue;
1643 if (tt->type == TOK_WHITESPACE) {
1644 tt = tt->next;
1645 continue;
1647 if (tt->type != t->type) {
1648 j = false; /* found mismatching tokens */
1649 break;
1651 /* When comparing strings, need to unquote them first */
1652 if (t->type == TOK_STRING) {
1653 size_t l1 = nasm_unquote(t->text, NULL);
1654 size_t l2 = nasm_unquote(tt->text, NULL);
1656 if (l1 != l2) {
1657 j = false;
1658 break;
1660 if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
1661 j = false;
1662 break;
1664 } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
1665 j = false; /* found mismatching tokens */
1666 break;
1669 t = t->next;
1670 tt = tt->next;
1672 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
1673 j = false; /* trailing gunk on one end or other */
1674 break;
1676 case PPC_IFMACRO:
1678 bool found = false;
1679 MMacro searching, *mmac;
1681 skip_white_(tline);
1682 tline = expand_id(tline);
1683 if (!tok_type_(tline, TOK_ID)) {
1684 error(ERR_NONFATAL,
1685 "`%s' expects a macro name", pp_directives[ct]);
1686 goto fail;
1688 searching.name = nasm_strdup(tline->text);
1689 searching.casesense = true;
1690 searching.plus = false;
1691 searching.nolist = false;
1692 searching.in_progress = 0;
1693 searching.rep_nest = NULL;
1694 searching.nparam_min = 0;
1695 searching.nparam_max = INT_MAX;
1696 tline = expand_smacro(tline->next);
1697 skip_white_(tline);
1698 if (!tline) {
1699 } else if (!tok_type_(tline, TOK_NUMBER)) {
1700 error(ERR_NONFATAL,
1701 "`%s' expects a parameter count or nothing",
1702 pp_directives[ct]);
1703 } else {
1704 searching.nparam_min = searching.nparam_max =
1705 readnum(tline->text, &j);
1706 if (j)
1707 error(ERR_NONFATAL,
1708 "unable to parse parameter count `%s'",
1709 tline->text);
1711 if (tline && tok_is_(tline->next, "-")) {
1712 tline = tline->next->next;
1713 if (tok_is_(tline, "*"))
1714 searching.nparam_max = INT_MAX;
1715 else if (!tok_type_(tline, TOK_NUMBER))
1716 error(ERR_NONFATAL,
1717 "`%s' expects a parameter count after `-'",
1718 pp_directives[ct]);
1719 else {
1720 searching.nparam_max = readnum(tline->text, &j);
1721 if (j)
1722 error(ERR_NONFATAL,
1723 "unable to parse parameter count `%s'",
1724 tline->text);
1725 if (searching.nparam_min > searching.nparam_max)
1726 error(ERR_NONFATAL,
1727 "minimum parameter count exceeds maximum");
1730 if (tline && tok_is_(tline->next, "+")) {
1731 tline = tline->next;
1732 searching.plus = true;
1734 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
1735 while (mmac) {
1736 if (!strcmp(mmac->name, searching.name) &&
1737 (mmac->nparam_min <= searching.nparam_max
1738 || searching.plus)
1739 && (searching.nparam_min <= mmac->nparam_max
1740 || mmac->plus)) {
1741 found = true;
1742 break;
1744 mmac = mmac->next;
1746 if(tline && tline->next)
1747 error(ERR_WARNING|ERR_PASS1,
1748 "trailing garbage after %%ifmacro ignored");
1749 nasm_free(searching.name);
1750 j = found;
1751 break;
1754 case PPC_IFID:
1755 needtype = TOK_ID;
1756 goto iftype;
1757 case PPC_IFNUM:
1758 needtype = TOK_NUMBER;
1759 goto iftype;
1760 case PPC_IFSTR:
1761 needtype = TOK_STRING;
1762 goto iftype;
1764 iftype:
1765 t = tline = expand_smacro(tline);
1767 while (tok_type_(t, TOK_WHITESPACE) ||
1768 (needtype == TOK_NUMBER &&
1769 tok_type_(t, TOK_OTHER) &&
1770 (t->text[0] == '-' || t->text[0] == '+') &&
1771 !t->text[1]))
1772 t = t->next;
1774 j = tok_type_(t, needtype);
1775 break;
1777 case PPC_IFTOKEN:
1778 t = tline = expand_smacro(tline);
1779 while (tok_type_(t, TOK_WHITESPACE))
1780 t = t->next;
1782 j = false;
1783 if (t) {
1784 t = t->next; /* Skip the actual token */
1785 while (tok_type_(t, TOK_WHITESPACE))
1786 t = t->next;
1787 j = !t; /* Should be nothing left */
1789 break;
1791 case PPC_IFEMPTY:
1792 t = tline = expand_smacro(tline);
1793 while (tok_type_(t, TOK_WHITESPACE))
1794 t = t->next;
1796 j = !t; /* Should be empty */
1797 break;
1799 case PPC_IF:
1800 t = tline = expand_smacro(tline);
1801 tptr = &t;
1802 tokval.t_type = TOKEN_INVALID;
1803 evalresult = evaluate(ppscan, tptr, &tokval,
1804 NULL, pass | CRITICAL, error, NULL);
1805 if (!evalresult)
1806 return -1;
1807 if (tokval.t_type)
1808 error(ERR_WARNING|ERR_PASS1,
1809 "trailing garbage after expression ignored");
1810 if (!is_simple(evalresult)) {
1811 error(ERR_NONFATAL,
1812 "non-constant value given to `%s'", pp_directives[ct]);
1813 goto fail;
1815 j = reloc_value(evalresult) != 0;
1816 break;
1818 default:
1819 error(ERR_FATAL,
1820 "preprocessor directive `%s' not yet implemented",
1821 pp_directives[ct]);
1822 goto fail;
1825 free_tlist(origline);
1826 return j ^ PP_NEGATIVE(ct);
1828 fail:
1829 free_tlist(origline);
1830 return -1;
1834 * Common code for defining an smacro
1836 static bool define_smacro(Context *ctx, const char *mname, bool casesense,
1837 int nparam, Token *expansion)
1839 SMacro *smac, **smhead;
1840 struct hash_table *smtbl;
1842 if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
1843 if (!smac) {
1844 error(ERR_WARNING|ERR_PASS1,
1845 "single-line macro `%s' defined both with and"
1846 " without parameters", mname);
1848 /* Some instances of the old code considered this a failure,
1849 some others didn't. What is the right thing to do here? */
1850 free_tlist(expansion);
1851 return false; /* Failure */
1852 } else {
1854 * We're redefining, so we have to take over an
1855 * existing SMacro structure. This means freeing
1856 * what was already in it.
1858 nasm_free(smac->name);
1859 free_tlist(smac->expansion);
1861 } else {
1862 smtbl = ctx ? &ctx->localmac : &smacros;
1863 smhead = (SMacro **) hash_findi_add(smtbl, mname);
1864 smac = nasm_malloc(sizeof(SMacro));
1865 smac->next = *smhead;
1866 *smhead = smac;
1868 smac->name = nasm_strdup(mname);
1869 smac->casesense = casesense;
1870 smac->nparam = nparam;
1871 smac->expansion = expansion;
1872 smac->in_progress = false;
1873 return true; /* Success */
1877 * Undefine an smacro
1879 static void undef_smacro(Context *ctx, const char *mname)
1881 SMacro **smhead, *s, **sp;
1882 struct hash_table *smtbl;
1884 smtbl = ctx ? &ctx->localmac : &smacros;
1885 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
1887 if (smhead) {
1889 * We now have a macro name... go hunt for it.
1891 sp = smhead;
1892 while ((s = *sp) != NULL) {
1893 if (!mstrcmp(s->name, mname, s->casesense)) {
1894 *sp = s->next;
1895 nasm_free(s->name);
1896 free_tlist(s->expansion);
1897 nasm_free(s);
1898 } else {
1899 sp = &s->next;
1906 * Parse a mmacro specification.
1908 static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
1910 bool err;
1912 tline = tline->next;
1913 skip_white_(tline);
1914 tline = expand_id(tline);
1915 if (!tok_type_(tline, TOK_ID)) {
1916 error(ERR_NONFATAL, "`%s' expects a macro name", directive);
1917 return false;
1920 def->name = nasm_strdup(tline->text);
1921 def->plus = false;
1922 def->nolist = false;
1923 def->in_progress = 0;
1924 def->rep_nest = NULL;
1925 def->nparam_min = 0;
1926 def->nparam_max = 0;
1928 tline = expand_smacro(tline->next);
1929 skip_white_(tline);
1930 if (!tok_type_(tline, TOK_NUMBER)) {
1931 error(ERR_NONFATAL, "`%s' expects a parameter count", directive);
1932 } else {
1933 def->nparam_min = def->nparam_max =
1934 readnum(tline->text, &err);
1935 if (err)
1936 error(ERR_NONFATAL,
1937 "unable to parse parameter count `%s'", tline->text);
1939 if (tline && tok_is_(tline->next, "-")) {
1940 tline = tline->next->next;
1941 if (tok_is_(tline, "*")) {
1942 def->nparam_max = INT_MAX;
1943 } else if (!tok_type_(tline, TOK_NUMBER)) {
1944 error(ERR_NONFATAL,
1945 "`%s' expects a parameter count after `-'", directive);
1946 } else {
1947 def->nparam_max = readnum(tline->text, &err);
1948 if (err) {
1949 error(ERR_NONFATAL, "unable to parse parameter count `%s'",
1950 tline->text);
1952 if (def->nparam_min > def->nparam_max) {
1953 error(ERR_NONFATAL, "minimum parameter count exceeds maximum");
1957 if (tline && tok_is_(tline->next, "+")) {
1958 tline = tline->next;
1959 def->plus = true;
1961 if (tline && tok_type_(tline->next, TOK_ID) &&
1962 !nasm_stricmp(tline->next->text, ".nolist")) {
1963 tline = tline->next;
1964 def->nolist = true;
1968 * Handle default parameters.
1970 if (tline && tline->next) {
1971 def->dlist = tline->next;
1972 tline->next = NULL;
1973 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
1974 } else {
1975 def->dlist = NULL;
1976 def->defaults = NULL;
1978 def->expansion = NULL;
1980 if(def->defaults &&
1981 def->ndefs > def->nparam_max - def->nparam_min &&
1982 !def->plus)
1983 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MDP,
1984 "too many default macro parameters");
1986 return true;
1991 * Decode a size directive
1993 static int parse_size(const char *str) {
1994 static const char *size_names[] =
1995 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
1996 static const int sizes[] =
1997 { 0, 1, 4, 16, 8, 10, 2, 32 };
1999 return sizes[bsii(str, size_names, elements(size_names))+1];
2003 * find and process preprocessor directive in passed line
2004 * Find out if a line contains a preprocessor directive, and deal
2005 * with it if so.
2007 * If a directive _is_ found, it is the responsibility of this routine
2008 * (and not the caller) to free_tlist() the line.
2010 * @param tline a pointer to the current tokeninzed line linked list
2011 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
2014 static int do_directive(Token * tline)
2016 enum preproc_token i;
2017 int j;
2018 bool err;
2019 int nparam;
2020 bool nolist;
2021 bool casesense;
2022 int k, m;
2023 int offset;
2024 char *p, *pp;
2025 const char *mname;
2026 Include *inc;
2027 Context *ctx;
2028 Cond *cond;
2029 MMacro *mmac, **mmhead;
2030 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
2031 Line *l;
2032 struct tokenval tokval;
2033 expr *evalresult;
2034 MMacro *tmp_defining; /* Used when manipulating rep_nest */
2035 int64_t count;
2036 size_t len;
2037 int severity;
2039 origline = tline;
2041 skip_white_(tline);
2042 if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
2043 (tline->text[1] == '%' || tline->text[1] == '$'
2044 || tline->text[1] == '!'))
2045 return NO_DIRECTIVE_FOUND;
2047 i = pp_token_hash(tline->text);
2050 * If we're in a non-emitting branch of a condition construct,
2051 * or walking to the end of an already terminated %rep block,
2052 * we should ignore all directives except for condition
2053 * directives.
2055 if (((istk->conds && !emitting(istk->conds->state)) ||
2056 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
2057 return NO_DIRECTIVE_FOUND;
2061 * If we're defining a macro or reading a %rep block, we should
2062 * ignore all directives except for %macro/%imacro (which nest),
2063 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2064 * If we're in a %rep block, another %rep nests, so should be let through.
2066 if (defining && i != PP_MACRO && i != PP_IMACRO &&
2067 i != PP_ENDMACRO && i != PP_ENDM &&
2068 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
2069 return NO_DIRECTIVE_FOUND;
2072 if (defining) {
2073 if (i == PP_MACRO || i == PP_IMACRO) {
2074 nested_mac_count++;
2075 return NO_DIRECTIVE_FOUND;
2076 } else if (nested_mac_count > 0) {
2077 if (i == PP_ENDMACRO) {
2078 nested_mac_count--;
2079 return NO_DIRECTIVE_FOUND;
2082 if (!defining->name) {
2083 if (i == PP_REP) {
2084 nested_rep_count++;
2085 return NO_DIRECTIVE_FOUND;
2086 } else if (nested_rep_count > 0) {
2087 if (i == PP_ENDREP) {
2088 nested_rep_count--;
2089 return NO_DIRECTIVE_FOUND;
2095 switch (i) {
2096 case PP_INVALID:
2097 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2098 tline->text);
2099 return NO_DIRECTIVE_FOUND; /* didn't get it */
2101 case PP_STACKSIZE:
2102 /* Directive to tell NASM what the default stack size is. The
2103 * default is for a 16-bit stack, and this can be overriden with
2104 * %stacksize large.
2105 * the following form:
2107 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2109 tline = tline->next;
2110 if (tline && tline->type == TOK_WHITESPACE)
2111 tline = tline->next;
2112 if (!tline || tline->type != TOK_ID) {
2113 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
2114 free_tlist(origline);
2115 return DIRECTIVE_FOUND;
2117 if (nasm_stricmp(tline->text, "flat") == 0) {
2118 /* All subsequent ARG directives are for a 32-bit stack */
2119 StackSize = 4;
2120 StackPointer = "ebp";
2121 ArgOffset = 8;
2122 LocalOffset = 0;
2123 } else if (nasm_stricmp(tline->text, "flat64") == 0) {
2124 /* All subsequent ARG directives are for a 64-bit stack */
2125 StackSize = 8;
2126 StackPointer = "rbp";
2127 ArgOffset = 8;
2128 LocalOffset = 0;
2129 } else if (nasm_stricmp(tline->text, "large") == 0) {
2130 /* All subsequent ARG directives are for a 16-bit stack,
2131 * far function call.
2133 StackSize = 2;
2134 StackPointer = "bp";
2135 ArgOffset = 4;
2136 LocalOffset = 0;
2137 } else if (nasm_stricmp(tline->text, "small") == 0) {
2138 /* All subsequent ARG directives are for a 16-bit stack,
2139 * far function call. We don't support near functions.
2141 StackSize = 2;
2142 StackPointer = "bp";
2143 ArgOffset = 6;
2144 LocalOffset = 0;
2145 } else {
2146 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
2147 free_tlist(origline);
2148 return DIRECTIVE_FOUND;
2150 free_tlist(origline);
2151 return DIRECTIVE_FOUND;
2153 case PP_ARG:
2154 /* TASM like ARG directive to define arguments to functions, in
2155 * the following form:
2157 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2159 offset = ArgOffset;
2160 do {
2161 char *arg, directive[256];
2162 int size = StackSize;
2164 /* Find the argument name */
2165 tline = tline->next;
2166 if (tline && tline->type == TOK_WHITESPACE)
2167 tline = tline->next;
2168 if (!tline || tline->type != TOK_ID) {
2169 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
2170 free_tlist(origline);
2171 return DIRECTIVE_FOUND;
2173 arg = tline->text;
2175 /* Find the argument size type */
2176 tline = tline->next;
2177 if (!tline || tline->type != TOK_OTHER
2178 || tline->text[0] != ':') {
2179 error(ERR_NONFATAL,
2180 "Syntax error processing `%%arg' directive");
2181 free_tlist(origline);
2182 return DIRECTIVE_FOUND;
2184 tline = tline->next;
2185 if (!tline || tline->type != TOK_ID) {
2186 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
2187 free_tlist(origline);
2188 return DIRECTIVE_FOUND;
2191 /* Allow macro expansion of type parameter */
2192 tt = tokenize(tline->text);
2193 tt = expand_smacro(tt);
2194 size = parse_size(tt->text);
2195 if (!size) {
2196 error(ERR_NONFATAL,
2197 "Invalid size type for `%%arg' missing directive");
2198 free_tlist(tt);
2199 free_tlist(origline);
2200 return DIRECTIVE_FOUND;
2202 free_tlist(tt);
2204 /* Round up to even stack slots */
2205 size = (size+StackSize-1) & ~(StackSize-1);
2207 /* Now define the macro for the argument */
2208 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
2209 arg, StackPointer, offset);
2210 do_directive(tokenize(directive));
2211 offset += size;
2213 /* Move to the next argument in the list */
2214 tline = tline->next;
2215 if (tline && tline->type == TOK_WHITESPACE)
2216 tline = tline->next;
2217 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2218 ArgOffset = offset;
2219 free_tlist(origline);
2220 return DIRECTIVE_FOUND;
2222 case PP_LOCAL:
2223 /* TASM like LOCAL directive to define local variables for a
2224 * function, in the following form:
2226 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2228 * The '= LocalSize' at the end is ignored by NASM, but is
2229 * required by TASM to define the local parameter size (and used
2230 * by the TASM macro package).
2232 offset = LocalOffset;
2233 do {
2234 char *local, directive[256];
2235 int size = StackSize;
2237 /* Find the argument name */
2238 tline = tline->next;
2239 if (tline && tline->type == TOK_WHITESPACE)
2240 tline = tline->next;
2241 if (!tline || tline->type != TOK_ID) {
2242 error(ERR_NONFATAL,
2243 "`%%local' missing argument parameter");
2244 free_tlist(origline);
2245 return DIRECTIVE_FOUND;
2247 local = tline->text;
2249 /* Find the argument size type */
2250 tline = tline->next;
2251 if (!tline || tline->type != TOK_OTHER
2252 || tline->text[0] != ':') {
2253 error(ERR_NONFATAL,
2254 "Syntax error processing `%%local' directive");
2255 free_tlist(origline);
2256 return DIRECTIVE_FOUND;
2258 tline = tline->next;
2259 if (!tline || tline->type != TOK_ID) {
2260 error(ERR_NONFATAL,
2261 "`%%local' missing size type parameter");
2262 free_tlist(origline);
2263 return DIRECTIVE_FOUND;
2266 /* Allow macro expansion of type parameter */
2267 tt = tokenize(tline->text);
2268 tt = expand_smacro(tt);
2269 size = parse_size(tt->text);
2270 if (!size) {
2271 error(ERR_NONFATAL,
2272 "Invalid size type for `%%local' missing directive");
2273 free_tlist(tt);
2274 free_tlist(origline);
2275 return DIRECTIVE_FOUND;
2277 free_tlist(tt);
2279 /* Round up to even stack slots */
2280 size = (size+StackSize-1) & ~(StackSize-1);
2282 offset += size; /* Negative offset, increment before */
2284 /* Now define the macro for the argument */
2285 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
2286 local, StackPointer, offset);
2287 do_directive(tokenize(directive));
2289 /* Now define the assign to setup the enter_c macro correctly */
2290 snprintf(directive, sizeof(directive),
2291 "%%assign %%$localsize %%$localsize+%d", size);
2292 do_directive(tokenize(directive));
2294 /* Move to the next argument in the list */
2295 tline = tline->next;
2296 if (tline && tline->type == TOK_WHITESPACE)
2297 tline = tline->next;
2298 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2299 LocalOffset = offset;
2300 free_tlist(origline);
2301 return DIRECTIVE_FOUND;
2303 case PP_CLEAR:
2304 if (tline->next)
2305 error(ERR_WARNING|ERR_PASS1,
2306 "trailing garbage after `%%clear' ignored");
2307 free_macros();
2308 init_macros();
2309 free_tlist(origline);
2310 return DIRECTIVE_FOUND;
2312 case PP_DEPEND:
2313 t = tline->next = expand_smacro(tline->next);
2314 skip_white_(t);
2315 if (!t || (t->type != TOK_STRING &&
2316 t->type != TOK_INTERNAL_STRING)) {
2317 error(ERR_NONFATAL, "`%%depend' expects a file name");
2318 free_tlist(origline);
2319 return DIRECTIVE_FOUND; /* but we did _something_ */
2321 if (t->next)
2322 error(ERR_WARNING|ERR_PASS1,
2323 "trailing garbage after `%%depend' ignored");
2324 p = t->text;
2325 if (t->type != TOK_INTERNAL_STRING)
2326 nasm_unquote(p, NULL);
2327 if (dephead && !in_list(*dephead, p)) {
2328 StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next);
2329 sl->next = NULL;
2330 strcpy(sl->str, p);
2331 *deptail = sl;
2332 deptail = &sl->next;
2334 free_tlist(origline);
2335 return DIRECTIVE_FOUND;
2337 case PP_INCLUDE:
2338 t = tline->next = expand_smacro(tline->next);
2339 skip_white_(t);
2341 if (!t || (t->type != TOK_STRING &&
2342 t->type != TOK_INTERNAL_STRING)) {
2343 error(ERR_NONFATAL, "`%%include' expects a file name");
2344 free_tlist(origline);
2345 return DIRECTIVE_FOUND; /* but we did _something_ */
2347 if (t->next)
2348 error(ERR_WARNING|ERR_PASS1,
2349 "trailing garbage after `%%include' ignored");
2350 p = t->text;
2351 if (t->type != TOK_INTERNAL_STRING)
2352 nasm_unquote(p, NULL);
2353 inc = nasm_malloc(sizeof(Include));
2354 inc->next = istk;
2355 inc->conds = NULL;
2356 inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
2357 if (!inc->fp) {
2358 /* -MG given but file not found */
2359 nasm_free(inc);
2360 } else {
2361 inc->fname = src_set_fname(nasm_strdup(p));
2362 inc->lineno = src_set_linnum(0);
2363 inc->lineinc = 1;
2364 inc->expansion = NULL;
2365 inc->mstk = NULL;
2366 istk = inc;
2367 list->uplevel(LIST_INCLUDE);
2369 free_tlist(origline);
2370 return DIRECTIVE_FOUND;
2372 case PP_USE:
2374 static macros_t *use_pkg;
2375 const char *pkg_macro;
2377 tline = tline->next;
2378 skip_white_(tline);
2379 tline = expand_id(tline);
2381 if (!tline || (tline->type != TOK_STRING &&
2382 tline->type != TOK_INTERNAL_STRING &&
2383 tline->type != TOK_ID)) {
2384 error(ERR_NONFATAL, "`%%use' expects a package name");
2385 free_tlist(origline);
2386 return DIRECTIVE_FOUND; /* but we did _something_ */
2388 if (tline->next)
2389 error(ERR_WARNING|ERR_PASS1,
2390 "trailing garbage after `%%use' ignored");
2391 if (tline->type == TOK_STRING)
2392 nasm_unquote(tline->text, NULL);
2393 use_pkg = nasm_stdmac_find_package(tline->text);
2394 if (!use_pkg)
2395 error(ERR_NONFATAL, "unknown `%%use' package: %s", tline->text);
2396 /* The first string will be <%define>__USE_*__ */
2397 pkg_macro = (char *)use_pkg + 1;
2398 if (!smacro_defined(NULL, pkg_macro, 0, NULL, true)) {
2399 /* Not already included, go ahead and include it */
2400 stdmacpos = use_pkg;
2402 free_tlist(origline);
2403 return DIRECTIVE_FOUND;
2405 case PP_PUSH:
2406 case PP_REPL:
2407 case PP_POP:
2408 tline = tline->next;
2409 skip_white_(tline);
2410 tline = expand_id(tline);
2411 if (tline) {
2412 if (!tok_type_(tline, TOK_ID)) {
2413 error(ERR_NONFATAL, "`%s' expects a context identifier",
2414 pp_directives[i]);
2415 free_tlist(origline);
2416 return DIRECTIVE_FOUND; /* but we did _something_ */
2418 if (tline->next)
2419 error(ERR_WARNING|ERR_PASS1,
2420 "trailing garbage after `%s' ignored",
2421 pp_directives[i]);
2422 p = nasm_strdup(tline->text);
2423 } else {
2424 p = NULL; /* Anonymous */
2427 if (i == PP_PUSH) {
2428 ctx = nasm_malloc(sizeof(Context));
2429 ctx->next = cstk;
2430 hash_init(&ctx->localmac, HASH_SMALL);
2431 ctx->name = p;
2432 ctx->number = unique++;
2433 cstk = ctx;
2434 } else {
2435 /* %pop or %repl */
2436 if (!cstk) {
2437 error(ERR_NONFATAL, "`%s': context stack is empty",
2438 pp_directives[i]);
2439 } else if (i == PP_POP) {
2440 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
2441 error(ERR_NONFATAL, "`%%pop' in wrong context: %s, "
2442 "expected %s",
2443 cstk->name ? cstk->name : "anonymous", p);
2444 else
2445 ctx_pop();
2446 } else {
2447 /* i == PP_REPL */
2448 nasm_free(cstk->name);
2449 cstk->name = p;
2450 p = NULL;
2452 nasm_free(p);
2454 free_tlist(origline);
2455 return DIRECTIVE_FOUND;
2456 case PP_FATAL:
2457 severity = ERR_FATAL|ERR_NO_SEVERITY;
2458 goto issue_error;
2459 case PP_ERROR:
2460 severity = ERR_NONFATAL|ERR_NO_SEVERITY;
2461 goto issue_error;
2462 case PP_WARNING:
2463 severity = ERR_WARNING|ERR_NO_SEVERITY|ERR_WARN_USER;
2464 goto issue_error;
2466 issue_error:
2468 /* Only error out if this is the final pass */
2469 if (pass != 2 && i != PP_FATAL)
2470 return DIRECTIVE_FOUND;
2472 tline->next = expand_smacro(tline->next);
2473 tline = tline->next;
2474 skip_white_(tline);
2475 t = tline ? tline->next : NULL;
2476 skip_white_(t);
2477 if (tok_type_(tline, TOK_STRING) && !t) {
2478 /* The line contains only a quoted string */
2479 p = tline->text;
2480 nasm_unquote(p, NULL);
2481 error(severity, "%s: %s", pp_directives[i], p);
2482 } else {
2483 /* Not a quoted string, or more than a quoted string */
2484 p = detoken(tline, false);
2485 error(severity, "%s: %s", pp_directives[i], p);
2486 nasm_free(p);
2488 free_tlist(origline);
2489 return DIRECTIVE_FOUND;
2492 CASE_PP_IF:
2493 if (istk->conds && !emitting(istk->conds->state))
2494 j = COND_NEVER;
2495 else {
2496 j = if_condition(tline->next, i);
2497 tline->next = NULL; /* it got freed */
2498 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2500 cond = nasm_malloc(sizeof(Cond));
2501 cond->next = istk->conds;
2502 cond->state = j;
2503 istk->conds = cond;
2504 free_tlist(origline);
2505 return DIRECTIVE_FOUND;
2507 CASE_PP_ELIF:
2508 if (!istk->conds)
2509 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
2510 switch(istk->conds->state) {
2511 case COND_IF_TRUE:
2512 istk->conds->state = COND_DONE;
2513 break;
2515 case COND_DONE:
2516 case COND_NEVER:
2517 break;
2519 case COND_ELSE_TRUE:
2520 case COND_ELSE_FALSE:
2521 error_precond(ERR_WARNING|ERR_PASS1,
2522 "`%%elif' after `%%else' ignored");
2523 istk->conds->state = COND_NEVER;
2524 break;
2526 case COND_IF_FALSE:
2528 * IMPORTANT: In the case of %if, we will already have
2529 * called expand_mmac_params(); however, if we're
2530 * processing an %elif we must have been in a
2531 * non-emitting mode, which would have inhibited
2532 * the normal invocation of expand_mmac_params().
2533 * Therefore, we have to do it explicitly here.
2535 j = if_condition(expand_mmac_params(tline->next), i);
2536 tline->next = NULL; /* it got freed */
2537 istk->conds->state =
2538 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2539 break;
2541 free_tlist(origline);
2542 return DIRECTIVE_FOUND;
2544 case PP_ELSE:
2545 if (tline->next)
2546 error_precond(ERR_WARNING|ERR_PASS1,
2547 "trailing garbage after `%%else' ignored");
2548 if (!istk->conds)
2549 error(ERR_FATAL, "`%%else': no matching `%%if'");
2550 switch(istk->conds->state) {
2551 case COND_IF_TRUE:
2552 case COND_DONE:
2553 istk->conds->state = COND_ELSE_FALSE;
2554 break;
2556 case COND_NEVER:
2557 break;
2559 case COND_IF_FALSE:
2560 istk->conds->state = COND_ELSE_TRUE;
2561 break;
2563 case COND_ELSE_TRUE:
2564 case COND_ELSE_FALSE:
2565 error_precond(ERR_WARNING|ERR_PASS1,
2566 "`%%else' after `%%else' ignored.");
2567 istk->conds->state = COND_NEVER;
2568 break;
2570 free_tlist(origline);
2571 return DIRECTIVE_FOUND;
2573 case PP_ENDIF:
2574 if (tline->next)
2575 error_precond(ERR_WARNING|ERR_PASS1,
2576 "trailing garbage after `%%endif' ignored");
2577 if (!istk->conds)
2578 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2579 cond = istk->conds;
2580 istk->conds = cond->next;
2581 nasm_free(cond);
2582 free_tlist(origline);
2583 return DIRECTIVE_FOUND;
2585 case PP_MACRO:
2586 case PP_IMACRO:
2587 if (defining) {
2588 error(ERR_FATAL,
2589 "`%%%smacro': already defining a macro",
2590 (i == PP_IMACRO ? "i" : ""));
2591 return DIRECTIVE_FOUND;
2593 defining = nasm_malloc(sizeof(MMacro));
2594 defining->casesense = (i == PP_MACRO);
2595 if (!parse_mmacro_spec(tline, defining, pp_directives[i])) {
2596 nasm_free(defining);
2597 defining = NULL;
2598 return DIRECTIVE_FOUND;
2601 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
2602 while (mmac) {
2603 if (!strcmp(mmac->name, defining->name) &&
2604 (mmac->nparam_min <= defining->nparam_max
2605 || defining->plus)
2606 && (defining->nparam_min <= mmac->nparam_max
2607 || mmac->plus)) {
2608 error(ERR_WARNING|ERR_PASS1,
2609 "redefining multi-line macro `%s'", defining->name);
2610 return DIRECTIVE_FOUND;
2612 mmac = mmac->next;
2614 free_tlist(origline);
2615 return DIRECTIVE_FOUND;
2617 case PP_ENDM:
2618 case PP_ENDMACRO:
2619 if (! (defining && defining->name)) {
2620 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2621 return DIRECTIVE_FOUND;
2623 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
2624 defining->next = *mmhead;
2625 *mmhead = defining;
2626 defining = NULL;
2627 free_tlist(origline);
2628 return DIRECTIVE_FOUND;
2630 case PP_UNMACRO:
2631 case PP_UNIMACRO:
2633 MMacro **mmac_p;
2634 MMacro spec;
2636 spec.casesense = (i == PP_UNMACRO);
2637 if (!parse_mmacro_spec(tline, &spec, pp_directives[i])) {
2638 return DIRECTIVE_FOUND;
2640 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
2641 while (mmac_p && *mmac_p) {
2642 mmac = *mmac_p;
2643 if (mmac->casesense == spec.casesense &&
2644 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
2645 mmac->nparam_min == spec.nparam_min &&
2646 mmac->nparam_max == spec.nparam_max &&
2647 mmac->plus == spec.plus) {
2648 *mmac_p = mmac->next;
2649 free_mmacro(mmac);
2650 } else {
2651 mmac_p = &mmac->next;
2654 free_tlist(origline);
2655 free_tlist(spec.dlist);
2656 return DIRECTIVE_FOUND;
2659 case PP_ROTATE:
2660 if (tline->next && tline->next->type == TOK_WHITESPACE)
2661 tline = tline->next;
2662 if (tline->next == NULL) {
2663 free_tlist(origline);
2664 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2665 return DIRECTIVE_FOUND;
2667 t = expand_smacro(tline->next);
2668 tline->next = NULL;
2669 free_tlist(origline);
2670 tline = t;
2671 tptr = &t;
2672 tokval.t_type = TOKEN_INVALID;
2673 evalresult =
2674 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2675 free_tlist(tline);
2676 if (!evalresult)
2677 return DIRECTIVE_FOUND;
2678 if (tokval.t_type)
2679 error(ERR_WARNING|ERR_PASS1,
2680 "trailing garbage after expression ignored");
2681 if (!is_simple(evalresult)) {
2682 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2683 return DIRECTIVE_FOUND;
2685 mmac = istk->mstk;
2686 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2687 mmac = mmac->next_active;
2688 if (!mmac) {
2689 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2690 } else if (mmac->nparam == 0) {
2691 error(ERR_NONFATAL,
2692 "`%%rotate' invoked within macro without parameters");
2693 } else {
2694 int rotate = mmac->rotate + reloc_value(evalresult);
2696 rotate %= (int)mmac->nparam;
2697 if (rotate < 0)
2698 rotate += mmac->nparam;
2700 mmac->rotate = rotate;
2702 return DIRECTIVE_FOUND;
2704 case PP_REP:
2705 nolist = false;
2706 do {
2707 tline = tline->next;
2708 } while (tok_type_(tline, TOK_WHITESPACE));
2710 if (tok_type_(tline, TOK_ID) &&
2711 nasm_stricmp(tline->text, ".nolist") == 0) {
2712 nolist = true;
2713 do {
2714 tline = tline->next;
2715 } while (tok_type_(tline, TOK_WHITESPACE));
2718 if (tline) {
2719 t = expand_smacro(tline);
2720 tptr = &t;
2721 tokval.t_type = TOKEN_INVALID;
2722 evalresult =
2723 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2724 if (!evalresult) {
2725 free_tlist(origline);
2726 return DIRECTIVE_FOUND;
2728 if (tokval.t_type)
2729 error(ERR_WARNING|ERR_PASS1,
2730 "trailing garbage after expression ignored");
2731 if (!is_simple(evalresult)) {
2732 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2733 return DIRECTIVE_FOUND;
2735 count = reloc_value(evalresult) + 1;
2736 } else {
2737 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
2738 count = 0;
2740 free_tlist(origline);
2742 tmp_defining = defining;
2743 defining = nasm_malloc(sizeof(MMacro));
2744 defining->name = NULL; /* flags this macro as a %rep block */
2745 defining->casesense = false;
2746 defining->plus = false;
2747 defining->nolist = nolist;
2748 defining->in_progress = count;
2749 defining->nparam_min = defining->nparam_max = 0;
2750 defining->defaults = NULL;
2751 defining->dlist = NULL;
2752 defining->expansion = NULL;
2753 defining->next_active = istk->mstk;
2754 defining->rep_nest = tmp_defining;
2755 return DIRECTIVE_FOUND;
2757 case PP_ENDREP:
2758 if (!defining || defining->name) {
2759 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2760 return DIRECTIVE_FOUND;
2764 * Now we have a "macro" defined - although it has no name
2765 * and we won't be entering it in the hash tables - we must
2766 * push a macro-end marker for it on to istk->expansion.
2767 * After that, it will take care of propagating itself (a
2768 * macro-end marker line for a macro which is really a %rep
2769 * block will cause the macro to be re-expanded, complete
2770 * with another macro-end marker to ensure the process
2771 * continues) until the whole expansion is forcibly removed
2772 * from istk->expansion by a %exitrep.
2774 l = nasm_malloc(sizeof(Line));
2775 l->next = istk->expansion;
2776 l->finishes = defining;
2777 l->first = NULL;
2778 istk->expansion = l;
2780 istk->mstk = defining;
2782 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2783 tmp_defining = defining;
2784 defining = defining->rep_nest;
2785 free_tlist(origline);
2786 return DIRECTIVE_FOUND;
2788 case PP_EXITREP:
2790 * We must search along istk->expansion until we hit a
2791 * macro-end marker for a macro with no name. Then we set
2792 * its `in_progress' flag to 0.
2794 for (l = istk->expansion; l; l = l->next)
2795 if (l->finishes && !l->finishes->name)
2796 break;
2798 if (l)
2799 l->finishes->in_progress = 1;
2800 else
2801 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2802 free_tlist(origline);
2803 return DIRECTIVE_FOUND;
2805 case PP_XDEFINE:
2806 case PP_IXDEFINE:
2807 case PP_DEFINE:
2808 case PP_IDEFINE:
2809 casesense = (i == PP_DEFINE || i == PP_XDEFINE);
2811 tline = tline->next;
2812 skip_white_(tline);
2813 tline = expand_id(tline);
2814 if (!tline || (tline->type != TOK_ID &&
2815 (tline->type != TOK_PREPROC_ID ||
2816 tline->text[1] != '$'))) {
2817 error(ERR_NONFATAL, "`%s' expects a macro identifier",
2818 pp_directives[i]);
2819 free_tlist(origline);
2820 return DIRECTIVE_FOUND;
2823 ctx = get_ctx(tline->text, &mname, false);
2824 last = tline;
2825 param_start = tline = tline->next;
2826 nparam = 0;
2828 /* Expand the macro definition now for %xdefine and %ixdefine */
2829 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2830 tline = expand_smacro(tline);
2832 if (tok_is_(tline, "(")) {
2834 * This macro has parameters.
2837 tline = tline->next;
2838 while (1) {
2839 skip_white_(tline);
2840 if (!tline) {
2841 error(ERR_NONFATAL, "parameter identifier expected");
2842 free_tlist(origline);
2843 return DIRECTIVE_FOUND;
2845 if (tline->type != TOK_ID) {
2846 error(ERR_NONFATAL,
2847 "`%s': parameter identifier expected",
2848 tline->text);
2849 free_tlist(origline);
2850 return DIRECTIVE_FOUND;
2852 tline->type = TOK_SMAC_PARAM + nparam++;
2853 tline = tline->next;
2854 skip_white_(tline);
2855 if (tok_is_(tline, ",")) {
2856 tline = tline->next;
2857 } else {
2858 if (!tok_is_(tline, ")")) {
2859 error(ERR_NONFATAL,
2860 "`)' expected to terminate macro template");
2861 free_tlist(origline);
2862 return DIRECTIVE_FOUND;
2864 break;
2867 last = tline;
2868 tline = tline->next;
2870 if (tok_type_(tline, TOK_WHITESPACE))
2871 last = tline, tline = tline->next;
2872 macro_start = NULL;
2873 last->next = NULL;
2874 t = tline;
2875 while (t) {
2876 if (t->type == TOK_ID) {
2877 for (tt = param_start; tt; tt = tt->next)
2878 if (tt->type >= TOK_SMAC_PARAM &&
2879 !strcmp(tt->text, t->text))
2880 t->type = tt->type;
2882 tt = t->next;
2883 t->next = macro_start;
2884 macro_start = t;
2885 t = tt;
2888 * Good. We now have a macro name, a parameter count, and a
2889 * token list (in reverse order) for an expansion. We ought
2890 * to be OK just to create an SMacro, store it, and let
2891 * free_tlist have the rest of the line (which we have
2892 * carefully re-terminated after chopping off the expansion
2893 * from the end).
2895 define_smacro(ctx, mname, casesense, nparam, macro_start);
2896 free_tlist(origline);
2897 return DIRECTIVE_FOUND;
2899 case PP_UNDEF:
2900 tline = tline->next;
2901 skip_white_(tline);
2902 tline = expand_id(tline);
2903 if (!tline || (tline->type != TOK_ID &&
2904 (tline->type != TOK_PREPROC_ID ||
2905 tline->text[1] != '$'))) {
2906 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2907 free_tlist(origline);
2908 return DIRECTIVE_FOUND;
2910 if (tline->next) {
2911 error(ERR_WARNING|ERR_PASS1,
2912 "trailing garbage after macro name ignored");
2915 /* Find the context that symbol belongs to */
2916 ctx = get_ctx(tline->text, &mname, false);
2917 undef_smacro(ctx, mname);
2918 free_tlist(origline);
2919 return DIRECTIVE_FOUND;
2921 case PP_DEFSTR:
2922 case PP_IDEFSTR:
2923 casesense = (i == PP_DEFSTR);
2925 tline = tline->next;
2926 skip_white_(tline);
2927 tline = expand_id(tline);
2928 if (!tline || (tline->type != TOK_ID &&
2929 (tline->type != TOK_PREPROC_ID ||
2930 tline->text[1] != '$'))) {
2931 error(ERR_NONFATAL, "`%s' expects a macro identifier",
2932 pp_directives[i]);
2933 free_tlist(origline);
2934 return DIRECTIVE_FOUND;
2937 ctx = get_ctx(tline->text, &mname, false);
2938 last = tline;
2939 tline = expand_smacro(tline->next);
2940 last->next = NULL;
2942 while (tok_type_(tline, TOK_WHITESPACE))
2943 tline = delete_Token(tline);
2945 p = detoken(tline, false);
2946 macro_start = nasm_malloc(sizeof(*macro_start));
2947 macro_start->next = NULL;
2948 macro_start->text = nasm_quote(p, strlen(p));
2949 macro_start->type = TOK_STRING;
2950 macro_start->a.mac = NULL;
2951 nasm_free(p);
2954 * We now have a macro name, an implicit parameter count of
2955 * zero, and a string token to use as an expansion. Create
2956 * and store an SMacro.
2958 define_smacro(ctx, mname, casesense, 0, macro_start);
2959 free_tlist(origline);
2960 return DIRECTIVE_FOUND;
2962 case PP_PATHSEARCH:
2964 FILE *fp;
2965 StrList *xsl = NULL;
2966 StrList **xst = &xsl;
2968 casesense = true;
2970 tline = tline->next;
2971 skip_white_(tline);
2972 tline = expand_id(tline);
2973 if (!tline || (tline->type != TOK_ID &&
2974 (tline->type != TOK_PREPROC_ID ||
2975 tline->text[1] != '$'))) {
2976 error(ERR_NONFATAL,
2977 "`%%pathsearch' expects a macro identifier as first parameter");
2978 free_tlist(origline);
2979 return DIRECTIVE_FOUND;
2981 ctx = get_ctx(tline->text, &mname, false);
2982 last = tline;
2983 tline = expand_smacro(tline->next);
2984 last->next = NULL;
2986 t = tline;
2987 while (tok_type_(t, TOK_WHITESPACE))
2988 t = t->next;
2990 if (!t || (t->type != TOK_STRING &&
2991 t->type != TOK_INTERNAL_STRING)) {
2992 error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
2993 free_tlist(tline);
2994 free_tlist(origline);
2995 return DIRECTIVE_FOUND; /* but we did _something_ */
2997 if (t->next)
2998 error(ERR_WARNING|ERR_PASS1,
2999 "trailing garbage after `%%pathsearch' ignored");
3000 p = t->text;
3001 if (t->type != TOK_INTERNAL_STRING)
3002 nasm_unquote(p, NULL);
3004 fp = inc_fopen(p, &xsl, &xst, true);
3005 if (fp) {
3006 p = xsl->str;
3007 fclose(fp); /* Don't actually care about the file */
3009 macro_start = nasm_malloc(sizeof(*macro_start));
3010 macro_start->next = NULL;
3011 macro_start->text = nasm_quote(p, strlen(p));
3012 macro_start->type = TOK_STRING;
3013 macro_start->a.mac = NULL;
3014 if (xsl)
3015 nasm_free(xsl);
3018 * We now have a macro name, an implicit parameter count of
3019 * zero, and a string token to use as an expansion. Create
3020 * and store an SMacro.
3022 define_smacro(ctx, mname, casesense, 0, macro_start);
3023 free_tlist(tline);
3024 free_tlist(origline);
3025 return DIRECTIVE_FOUND;
3028 case PP_STRLEN:
3029 casesense = true;
3031 tline = tline->next;
3032 skip_white_(tline);
3033 tline = expand_id(tline);
3034 if (!tline || (tline->type != TOK_ID &&
3035 (tline->type != TOK_PREPROC_ID ||
3036 tline->text[1] != '$'))) {
3037 error(ERR_NONFATAL,
3038 "`%%strlen' expects a macro identifier as first parameter");
3039 free_tlist(origline);
3040 return DIRECTIVE_FOUND;
3042 ctx = get_ctx(tline->text, &mname, false);
3043 last = tline;
3044 tline = expand_smacro(tline->next);
3045 last->next = NULL;
3047 t = tline;
3048 while (tok_type_(t, TOK_WHITESPACE))
3049 t = t->next;
3050 /* t should now point to the string */
3051 if (t->type != TOK_STRING) {
3052 error(ERR_NONFATAL,
3053 "`%%strlen` requires string as second parameter");
3054 free_tlist(tline);
3055 free_tlist(origline);
3056 return DIRECTIVE_FOUND;
3059 macro_start = nasm_malloc(sizeof(*macro_start));
3060 macro_start->next = NULL;
3061 make_tok_num(macro_start, nasm_unquote(t->text, NULL));
3062 macro_start->a.mac = NULL;
3065 * We now have a macro name, an implicit parameter count of
3066 * zero, and a numeric token to use as an expansion. Create
3067 * and store an SMacro.
3069 define_smacro(ctx, mname, casesense, 0, macro_start);
3070 free_tlist(tline);
3071 free_tlist(origline);
3072 return DIRECTIVE_FOUND;
3074 case PP_STRCAT:
3075 casesense = true;
3077 tline = tline->next;
3078 skip_white_(tline);
3079 tline = expand_id(tline);
3080 if (!tline || (tline->type != TOK_ID &&
3081 (tline->type != TOK_PREPROC_ID ||
3082 tline->text[1] != '$'))) {
3083 error(ERR_NONFATAL,
3084 "`%%strcat' expects a macro identifier as first parameter");
3085 free_tlist(origline);
3086 return DIRECTIVE_FOUND;
3088 ctx = get_ctx(tline->text, &mname, false);
3089 last = tline;
3090 tline = expand_smacro(tline->next);
3091 last->next = NULL;
3093 len = 0;
3094 for (t = tline; t; t = t->next) {
3095 switch (t->type) {
3096 case TOK_WHITESPACE:
3097 break;
3098 case TOK_STRING:
3099 len += t->a.len = nasm_unquote(t->text, NULL);
3100 break;
3101 case TOK_OTHER:
3102 if (!strcmp(t->text, ",")) /* permit comma separators */
3103 break;
3104 /* else fall through */
3105 default:
3106 error(ERR_NONFATAL,
3107 "non-string passed to `%%strcat' (%d)", t->type);
3108 free_tlist(tline);
3109 free_tlist(origline);
3110 return DIRECTIVE_FOUND;
3114 p = pp = nasm_malloc(len);
3115 t = tline;
3116 for (t = tline; t; t = t->next) {
3117 if (t->type == TOK_STRING) {
3118 memcpy(p, t->text, t->a.len);
3119 p += t->a.len;
3124 * We now have a macro name, an implicit parameter count of
3125 * zero, and a numeric token to use as an expansion. Create
3126 * and store an SMacro.
3128 macro_start = new_Token(NULL, TOK_STRING, NULL, 0);
3129 macro_start->text = nasm_quote(pp, len);
3130 nasm_free(pp);
3131 define_smacro(ctx, mname, casesense, 0, macro_start);
3132 free_tlist(tline);
3133 free_tlist(origline);
3134 return DIRECTIVE_FOUND;
3136 case PP_SUBSTR:
3138 int64_t a1, a2;
3139 size_t len;
3141 casesense = true;
3143 tline = tline->next;
3144 skip_white_(tline);
3145 tline = expand_id(tline);
3146 if (!tline || (tline->type != TOK_ID &&
3147 (tline->type != TOK_PREPROC_ID ||
3148 tline->text[1] != '$'))) {
3149 error(ERR_NONFATAL,
3150 "`%%substr' expects a macro identifier as first parameter");
3151 free_tlist(origline);
3152 return DIRECTIVE_FOUND;
3154 ctx = get_ctx(tline->text, &mname, false);
3155 last = tline;
3156 tline = expand_smacro(tline->next);
3157 last->next = NULL;
3159 t = tline->next;
3160 while (tok_type_(t, TOK_WHITESPACE))
3161 t = t->next;
3163 /* t should now point to the string */
3164 if (t->type != TOK_STRING) {
3165 error(ERR_NONFATAL,
3166 "`%%substr` requires string as second parameter");
3167 free_tlist(tline);
3168 free_tlist(origline);
3169 return DIRECTIVE_FOUND;
3172 tt = t->next;
3173 tptr = &tt;
3174 tokval.t_type = TOKEN_INVALID;
3175 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3176 pass, error, NULL);
3177 if (!evalresult) {
3178 free_tlist(tline);
3179 free_tlist(origline);
3180 return DIRECTIVE_FOUND;
3181 } else if (!is_simple(evalresult)) {
3182 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3183 free_tlist(tline);
3184 free_tlist(origline);
3185 return DIRECTIVE_FOUND;
3187 a1 = evalresult->value-1;
3189 while (tok_type_(tt, TOK_WHITESPACE))
3190 tt = tt->next;
3191 if (!tt) {
3192 a2 = 1; /* Backwards compatibility: one character */
3193 } else {
3194 tokval.t_type = TOKEN_INVALID;
3195 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3196 pass, error, NULL);
3197 if (!evalresult) {
3198 free_tlist(tline);
3199 free_tlist(origline);
3200 return DIRECTIVE_FOUND;
3201 } else if (!is_simple(evalresult)) {
3202 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3203 free_tlist(tline);
3204 free_tlist(origline);
3205 return DIRECTIVE_FOUND;
3207 a2 = evalresult->value;
3210 len = nasm_unquote(t->text, NULL);
3211 if (a2 < 0)
3212 a2 = a2+1+len-a1;
3213 if (a1+a2 > (int64_t)len)
3214 a2 = len-a1;
3216 macro_start = nasm_malloc(sizeof(*macro_start));
3217 macro_start->next = NULL;
3218 macro_start->text = nasm_quote((a1 < 0) ? "" : t->text+a1, a2);
3219 macro_start->type = TOK_STRING;
3220 macro_start->a.mac = NULL;
3223 * We now have a macro name, an implicit parameter count of
3224 * zero, and a numeric token to use as an expansion. Create
3225 * and store an SMacro.
3227 define_smacro(ctx, mname, casesense, 0, macro_start);
3228 free_tlist(tline);
3229 free_tlist(origline);
3230 return DIRECTIVE_FOUND;
3233 case PP_ASSIGN:
3234 case PP_IASSIGN:
3235 casesense = (i == PP_ASSIGN);
3237 tline = tline->next;
3238 skip_white_(tline);
3239 tline = expand_id(tline);
3240 if (!tline || (tline->type != TOK_ID &&
3241 (tline->type != TOK_PREPROC_ID ||
3242 tline->text[1] != '$'))) {
3243 error(ERR_NONFATAL,
3244 "`%%%sassign' expects a macro identifier",
3245 (i == PP_IASSIGN ? "i" : ""));
3246 free_tlist(origline);
3247 return DIRECTIVE_FOUND;
3249 ctx = get_ctx(tline->text, &mname, false);
3250 last = tline;
3251 tline = expand_smacro(tline->next);
3252 last->next = NULL;
3254 t = tline;
3255 tptr = &t;
3256 tokval.t_type = TOKEN_INVALID;
3257 evalresult =
3258 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3259 free_tlist(tline);
3260 if (!evalresult) {
3261 free_tlist(origline);
3262 return DIRECTIVE_FOUND;
3265 if (tokval.t_type)
3266 error(ERR_WARNING|ERR_PASS1,
3267 "trailing garbage after expression ignored");
3269 if (!is_simple(evalresult)) {
3270 error(ERR_NONFATAL,
3271 "non-constant value given to `%%%sassign'",
3272 (i == PP_IASSIGN ? "i" : ""));
3273 free_tlist(origline);
3274 return DIRECTIVE_FOUND;
3277 macro_start = nasm_malloc(sizeof(*macro_start));
3278 macro_start->next = NULL;
3279 make_tok_num(macro_start, reloc_value(evalresult));
3280 macro_start->a.mac = NULL;
3283 * We now have a macro name, an implicit parameter count of
3284 * zero, and a numeric token to use as an expansion. Create
3285 * and store an SMacro.
3287 define_smacro(ctx, mname, casesense, 0, macro_start);
3288 free_tlist(origline);
3289 return DIRECTIVE_FOUND;
3291 case PP_LINE:
3293 * Syntax is `%line nnn[+mmm] [filename]'
3295 tline = tline->next;
3296 skip_white_(tline);
3297 if (!tok_type_(tline, TOK_NUMBER)) {
3298 error(ERR_NONFATAL, "`%%line' expects line number");
3299 free_tlist(origline);
3300 return DIRECTIVE_FOUND;
3302 k = readnum(tline->text, &err);
3303 m = 1;
3304 tline = tline->next;
3305 if (tok_is_(tline, "+")) {
3306 tline = tline->next;
3307 if (!tok_type_(tline, TOK_NUMBER)) {
3308 error(ERR_NONFATAL, "`%%line' expects line increment");
3309 free_tlist(origline);
3310 return DIRECTIVE_FOUND;
3312 m = readnum(tline->text, &err);
3313 tline = tline->next;
3315 skip_white_(tline);
3316 src_set_linnum(k);
3317 istk->lineinc = m;
3318 if (tline) {
3319 nasm_free(src_set_fname(detoken(tline, false)));
3321 free_tlist(origline);
3322 return DIRECTIVE_FOUND;
3324 default:
3325 error(ERR_FATAL,
3326 "preprocessor directive `%s' not yet implemented",
3327 pp_directives[i]);
3328 return DIRECTIVE_FOUND;
3333 * Ensure that a macro parameter contains a condition code and
3334 * nothing else. Return the condition code index if so, or -1
3335 * otherwise.
3337 static int find_cc(Token * t)
3339 Token *tt;
3340 int i, j, k, m;
3342 if (!t)
3343 return -1; /* Probably a %+ without a space */
3345 skip_white_(t);
3346 if (t->type != TOK_ID)
3347 return -1;
3348 tt = t->next;
3349 skip_white_(tt);
3350 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
3351 return -1;
3353 i = -1;
3354 j = elements(conditions);
3355 while (j - i > 1) {
3356 k = (j + i) / 2;
3357 m = nasm_stricmp(t->text, conditions[k]);
3358 if (m == 0) {
3359 i = k;
3360 j = -2;
3361 break;
3362 } else if (m < 0) {
3363 j = k;
3364 } else
3365 i = k;
3367 if (j != -2)
3368 return -1;
3369 return i;
3372 static bool paste_tokens(Token **head, bool handle_paste_tokens)
3374 Token **tail, *t, *tt;
3375 Token **paste_head;
3376 bool did_paste = false;
3377 char *tmp;
3379 /* Now handle token pasting... */
3380 paste_head = NULL;
3381 tail = head;
3382 while ((t = *tail) && (tt = t->next)) {
3383 switch (t->type) {
3384 case TOK_WHITESPACE:
3385 if (tt->type == TOK_WHITESPACE) {
3386 /* Zap adjacent whitespace tokens */
3387 t->next = delete_Token(tt);
3388 } else {
3389 /* Do not advance paste_head here */
3390 tail = &t->next;
3392 break;
3393 case TOK_ID:
3394 case TOK_PREPROC_ID:
3395 case TOK_NUMBER:
3396 case TOK_FLOAT:
3398 size_t len = 0;
3399 char *tmp, *p;
3401 while (tt && (tt->type == TOK_ID || tt->type == TOK_PREPROC_ID ||
3402 tt->type == TOK_NUMBER || tt->type == TOK_FLOAT ||
3403 tt->type == TOK_OTHER)) {
3404 len += strlen(tt->text);
3405 tt = tt->next;
3408 /* Now tt points to the first token after the potential
3409 paste area... */
3410 if (tt != t->next) {
3411 /* We have at least two tokens... */
3412 len += strlen(t->text);
3413 p = tmp = nasm_malloc(len+1);
3415 while (t != tt) {
3416 strcpy(p, t->text);
3417 p = strchr(p, '\0');
3418 t = delete_Token(t);
3421 t = *tail = tokenize(tmp);
3422 nasm_free(tmp);
3424 while (t->next) {
3425 tail = &t->next;
3426 t = t->next;
3428 t->next = tt; /* Attach the remaining token chain */
3430 did_paste = true;
3432 paste_head = tail;
3433 tail = &t->next;
3434 break;
3436 case TOK_PASTE: /* %+ */
3437 if (handle_paste_tokens) {
3438 /* Zap %+ and whitespace tokens to the right */
3439 while (t && (t->type == TOK_WHITESPACE ||
3440 t->type == TOK_PASTE))
3441 t = *tail = delete_Token(t);
3442 if (!paste_head || !t)
3443 break; /* Nothing to paste with */
3444 tail = paste_head;
3445 t = *tail;
3446 tt = t->next;
3447 while (tok_type_(tt, TOK_WHITESPACE))
3448 tt = t->next = delete_Token(tt);
3450 if (tt) {
3451 tmp = nasm_strcat(t->text, tt->text);
3452 delete_Token(t);
3453 tt = delete_Token(tt);
3454 t = *tail = tokenize(tmp);
3455 nasm_free(tmp);
3456 while (t->next) {
3457 tail = &t->next;
3458 t = t->next;
3460 t->next = tt; /* Attach the remaining token chain */
3461 did_paste = true;
3463 paste_head = tail;
3464 tail = &t->next;
3465 break;
3467 /* else fall through */
3468 default:
3469 tail = paste_head = &t->next;
3470 break;
3473 return did_paste;
3476 * Expand MMacro-local things: parameter references (%0, %n, %+n,
3477 * %-n) and MMacro-local identifiers (%%foo) as well as
3478 * macro indirection (%[...]).
3480 static Token *expand_mmac_params(Token * tline)
3482 Token *t, *tt, **tail, *thead;
3483 bool changed = false;
3485 tail = &thead;
3486 thead = NULL;
3488 while (tline) {
3489 if (tline->type == TOK_PREPROC_ID &&
3490 (((tline->text[1] == '+' || tline->text[1] == '-')
3491 && tline->text[2]) || tline->text[1] == '%'
3492 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
3493 char *text = NULL;
3494 int type = 0, cc; /* type = 0 to placate optimisers */
3495 char tmpbuf[30];
3496 unsigned int n;
3497 int i;
3498 MMacro *mac;
3500 t = tline;
3501 tline = tline->next;
3503 mac = istk->mstk;
3504 while (mac && !mac->name) /* avoid mistaking %reps for macros */
3505 mac = mac->next_active;
3506 if (!mac)
3507 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
3508 else
3509 switch (t->text[1]) {
3511 * We have to make a substitution of one of the
3512 * forms %1, %-1, %+1, %%foo, %0.
3514 case '0':
3515 type = TOK_NUMBER;
3516 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
3517 text = nasm_strdup(tmpbuf);
3518 break;
3519 case '%':
3520 type = TOK_ID;
3521 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
3522 mac->unique);
3523 text = nasm_strcat(tmpbuf, t->text + 2);
3524 break;
3525 case '-':
3526 n = atoi(t->text + 2) - 1;
3527 if (n >= mac->nparam)
3528 tt = NULL;
3529 else {
3530 if (mac->nparam > 1)
3531 n = (n + mac->rotate) % mac->nparam;
3532 tt = mac->params[n];
3534 cc = find_cc(tt);
3535 if (cc == -1) {
3536 error(ERR_NONFATAL,
3537 "macro parameter %d is not a condition code",
3538 n + 1);
3539 text = NULL;
3540 } else {
3541 type = TOK_ID;
3542 if (inverse_ccs[cc] == -1) {
3543 error(ERR_NONFATAL,
3544 "condition code `%s' is not invertible",
3545 conditions[cc]);
3546 text = NULL;
3547 } else
3548 text = nasm_strdup(conditions[inverse_ccs[cc]]);
3550 break;
3551 case '+':
3552 n = atoi(t->text + 2) - 1;
3553 if (n >= mac->nparam)
3554 tt = NULL;
3555 else {
3556 if (mac->nparam > 1)
3557 n = (n + mac->rotate) % mac->nparam;
3558 tt = mac->params[n];
3560 cc = find_cc(tt);
3561 if (cc == -1) {
3562 error(ERR_NONFATAL,
3563 "macro parameter %d is not a condition code",
3564 n + 1);
3565 text = NULL;
3566 } else {
3567 type = TOK_ID;
3568 text = nasm_strdup(conditions[cc]);
3570 break;
3571 default:
3572 n = atoi(t->text + 1) - 1;
3573 if (n >= mac->nparam)
3574 tt = NULL;
3575 else {
3576 if (mac->nparam > 1)
3577 n = (n + mac->rotate) % mac->nparam;
3578 tt = mac->params[n];
3580 if (tt) {
3581 for (i = 0; i < mac->paramlen[n]; i++) {
3582 *tail = new_Token(NULL, tt->type, tt->text, 0);
3583 tail = &(*tail)->next;
3584 tt = tt->next;
3587 text = NULL; /* we've done it here */
3588 break;
3590 if (!text) {
3591 delete_Token(t);
3592 } else {
3593 *tail = t;
3594 tail = &t->next;
3595 t->type = type;
3596 nasm_free(t->text);
3597 t->text = text;
3598 t->a.mac = NULL;
3600 changed = true;
3601 continue;
3602 } else if (tline->type == TOK_INDIRECT) {
3603 t = tline;
3604 tline = tline->next;
3605 tt = tokenize(t->text);
3606 tt = expand_mmac_params(tt);
3607 tt = expand_smacro(tt);
3608 *tail = tt;
3609 while (tt) {
3610 tt->a.mac = NULL; /* Necessary? */
3611 tail = &tt->next;
3612 tt = tt->next;
3614 delete_Token(t);
3615 changed = true;
3616 } else {
3617 t = *tail = tline;
3618 tline = tline->next;
3619 t->a.mac = NULL;
3620 tail = &t->next;
3623 *tail = NULL;
3625 if (changed)
3626 paste_tokens(&thead, true);
3628 return thead;
3632 * Expand all single-line macro calls made in the given line.
3633 * Return the expanded version of the line. The original is deemed
3634 * to be destroyed in the process. (In reality we'll just move
3635 * Tokens from input to output a lot of the time, rather than
3636 * actually bothering to destroy and replicate.)
3638 #define DEADMAN_LIMIT (1 << 20)
3640 static Token *expand_smacro(Token * tline)
3642 Token *t, *tt, *mstart, **tail, *thead;
3643 struct hash_table *smtbl;
3644 SMacro *head = NULL, *m;
3645 Token **params;
3646 int *paramsize;
3647 unsigned int nparam, sparam;
3648 int brackets;
3649 Token *org_tline = tline;
3650 Context *ctx;
3651 const char *mname;
3652 int deadman = DEADMAN_LIMIT;
3653 bool expanded;
3656 * Trick: we should avoid changing the start token pointer since it can
3657 * be contained in "next" field of other token. Because of this
3658 * we allocate a copy of first token and work with it; at the end of
3659 * routine we copy it back
3661 if (org_tline) {
3662 tline =
3663 new_Token(org_tline->next, org_tline->type, org_tline->text,
3665 tline->a.mac = org_tline->a.mac;
3666 nasm_free(org_tline->text);
3667 org_tline->text = NULL;
3670 again:
3671 tail = &thead;
3672 thead = NULL;
3673 expanded = false;
3675 while (tline) { /* main token loop */
3676 if (!--deadman) {
3677 error(ERR_NONFATAL, "interminable macro recursion");
3678 break;
3681 if ((mname = tline->text)) {
3682 /* if this token is a local macro, look in local context */
3683 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
3684 ctx = get_ctx(mname, &mname, true);
3685 else
3686 ctx = NULL;
3687 smtbl = ctx ? &ctx->localmac : &smacros;
3688 head = (SMacro *) hash_findix(smtbl, mname);
3691 * We've hit an identifier. As in is_mmacro below, we first
3692 * check whether the identifier is a single-line macro at
3693 * all, then think about checking for parameters if
3694 * necessary.
3696 for (m = head; m; m = m->next)
3697 if (!mstrcmp(m->name, mname, m->casesense))
3698 break;
3699 if (m) {
3700 mstart = tline;
3701 params = NULL;
3702 paramsize = NULL;
3703 if (m->nparam == 0) {
3705 * Simple case: the macro is parameterless. Discard the
3706 * one token that the macro call took, and push the
3707 * expansion back on the to-do stack.
3709 if (!m->expansion) {
3710 if (!strcmp("__FILE__", m->name)) {
3711 int32_t num = 0;
3712 char *file = NULL;
3713 src_get(&num, &file);
3714 tline->text = nasm_quote(file, strlen(file));
3715 tline->type = TOK_STRING;
3716 nasm_free(file);
3717 continue;
3719 if (!strcmp("__LINE__", m->name)) {
3720 nasm_free(tline->text);
3721 make_tok_num(tline, src_get_linnum());
3722 continue;
3724 if (!strcmp("__BITS__", m->name)) {
3725 nasm_free(tline->text);
3726 make_tok_num(tline, globalbits);
3727 continue;
3729 tline = delete_Token(tline);
3730 continue;
3732 } else {
3734 * Complicated case: at least one macro with this name
3735 * exists and takes parameters. We must find the
3736 * parameters in the call, count them, find the SMacro
3737 * that corresponds to that form of the macro call, and
3738 * substitute for the parameters when we expand. What a
3739 * pain.
3741 /*tline = tline->next;
3742 skip_white_(tline); */
3743 do {
3744 t = tline->next;
3745 while (tok_type_(t, TOK_SMAC_END)) {
3746 t->a.mac->in_progress = false;
3747 t->text = NULL;
3748 t = tline->next = delete_Token(t);
3750 tline = t;
3751 } while (tok_type_(tline, TOK_WHITESPACE));
3752 if (!tok_is_(tline, "(")) {
3754 * This macro wasn't called with parameters: ignore
3755 * the call. (Behaviour borrowed from gnu cpp.)
3757 tline = mstart;
3758 m = NULL;
3759 } else {
3760 int paren = 0;
3761 int white = 0;
3762 brackets = 0;
3763 nparam = 0;
3764 sparam = PARAM_DELTA;
3765 params = nasm_malloc(sparam * sizeof(Token *));
3766 params[0] = tline->next;
3767 paramsize = nasm_malloc(sparam * sizeof(int));
3768 paramsize[0] = 0;
3769 while (true) { /* parameter loop */
3771 * For some unusual expansions
3772 * which concatenates function call
3774 t = tline->next;
3775 while (tok_type_(t, TOK_SMAC_END)) {
3776 t->a.mac->in_progress = false;
3777 t->text = NULL;
3778 t = tline->next = delete_Token(t);
3780 tline = t;
3782 if (!tline) {
3783 error(ERR_NONFATAL,
3784 "macro call expects terminating `)'");
3785 break;
3787 if (tline->type == TOK_WHITESPACE
3788 && brackets <= 0) {
3789 if (paramsize[nparam])
3790 white++;
3791 else
3792 params[nparam] = tline->next;
3793 continue; /* parameter loop */
3795 if (tline->type == TOK_OTHER
3796 && tline->text[1] == 0) {
3797 char ch = tline->text[0];
3798 if (ch == ',' && !paren && brackets <= 0) {
3799 if (++nparam >= sparam) {
3800 sparam += PARAM_DELTA;
3801 params = nasm_realloc(params,
3802 sparam *
3803 sizeof(Token
3804 *));
3805 paramsize =
3806 nasm_realloc(paramsize,
3807 sparam *
3808 sizeof(int));
3810 params[nparam] = tline->next;
3811 paramsize[nparam] = 0;
3812 white = 0;
3813 continue; /* parameter loop */
3815 if (ch == '{' &&
3816 (brackets > 0 || (brackets == 0 &&
3817 !paramsize[nparam])))
3819 if (!(brackets++)) {
3820 params[nparam] = tline->next;
3821 continue; /* parameter loop */
3824 if (ch == '}' && brackets > 0)
3825 if (--brackets == 0) {
3826 brackets = -1;
3827 continue; /* parameter loop */
3829 if (ch == '(' && !brackets)
3830 paren++;
3831 if (ch == ')' && brackets <= 0)
3832 if (--paren < 0)
3833 break;
3835 if (brackets < 0) {
3836 brackets = 0;
3837 error(ERR_NONFATAL, "braces do not "
3838 "enclose all of macro parameter");
3840 paramsize[nparam] += white + 1;
3841 white = 0;
3842 } /* parameter loop */
3843 nparam++;
3844 while (m && (m->nparam != nparam ||
3845 mstrcmp(m->name, mname,
3846 m->casesense)))
3847 m = m->next;
3848 if (!m)
3849 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
3850 "macro `%s' exists, "
3851 "but not taking %d parameters",
3852 mstart->text, nparam);
3855 if (m && m->in_progress)
3856 m = NULL;
3857 if (!m) { /* in progess or didn't find '(' or wrong nparam */
3859 * Design question: should we handle !tline, which
3860 * indicates missing ')' here, or expand those
3861 * macros anyway, which requires the (t) test a few
3862 * lines down?
3864 nasm_free(params);
3865 nasm_free(paramsize);
3866 tline = mstart;
3867 } else {
3869 * Expand the macro: we are placed on the last token of the
3870 * call, so that we can easily split the call from the
3871 * following tokens. We also start by pushing an SMAC_END
3872 * token for the cycle removal.
3874 t = tline;
3875 if (t) {
3876 tline = t->next;
3877 t->next = NULL;
3879 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
3880 tt->a.mac = m;
3881 m->in_progress = true;
3882 tline = tt;
3883 for (t = m->expansion; t; t = t->next) {
3884 if (t->type >= TOK_SMAC_PARAM) {
3885 Token *pcopy = tline, **ptail = &pcopy;
3886 Token *ttt, *pt;
3887 int i;
3889 ttt = params[t->type - TOK_SMAC_PARAM];
3890 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3891 --i >= 0;) {
3892 pt = *ptail =
3893 new_Token(tline, ttt->type, ttt->text,
3895 ptail = &pt->next;
3896 ttt = ttt->next;
3898 tline = pcopy;
3899 } else if (t->type == TOK_PREPROC_Q) {
3900 tt = new_Token(tline, TOK_ID, mname, 0);
3901 tline = tt;
3902 } else if (t->type == TOK_PREPROC_QQ) {
3903 tt = new_Token(tline, TOK_ID, m->name, 0);
3904 tline = tt;
3905 } else {
3906 tt = new_Token(tline, t->type, t->text, 0);
3907 tline = tt;
3912 * Having done that, get rid of the macro call, and clean
3913 * up the parameters.
3915 nasm_free(params);
3916 nasm_free(paramsize);
3917 free_tlist(mstart);
3918 expanded = true;
3919 continue; /* main token loop */
3924 if (tline->type == TOK_SMAC_END) {
3925 tline->a.mac->in_progress = false;
3926 tline = delete_Token(tline);
3927 } else {
3928 t = *tail = tline;
3929 tline = tline->next;
3930 t->a.mac = NULL;
3931 t->next = NULL;
3932 tail = &t->next;
3937 * Now scan the entire line and look for successive TOK_IDs that resulted
3938 * after expansion (they can't be produced by tokenize()). The successive
3939 * TOK_IDs should be concatenated.
3940 * Also we look for %+ tokens and concatenate the tokens before and after
3941 * them (without white spaces in between).
3943 if (expanded && paste_tokens(&thead, true)) {
3944 /* If we concatenated something, re-scan the line for macros */
3945 tline = thead;
3946 goto again;
3949 if (org_tline) {
3950 if (thead) {
3951 *org_tline = *thead;
3952 /* since we just gave text to org_line, don't free it */
3953 thead->text = NULL;
3954 delete_Token(thead);
3955 } else {
3956 /* the expression expanded to empty line;
3957 we can't return NULL for some reasons
3958 we just set the line to a single WHITESPACE token. */
3959 memset(org_tline, 0, sizeof(*org_tline));
3960 org_tline->text = NULL;
3961 org_tline->type = TOK_WHITESPACE;
3963 thead = org_tline;
3966 return thead;
3970 * Similar to expand_smacro but used exclusively with macro identifiers
3971 * right before they are fetched in. The reason is that there can be
3972 * identifiers consisting of several subparts. We consider that if there
3973 * are more than one element forming the name, user wants a expansion,
3974 * otherwise it will be left as-is. Example:
3976 * %define %$abc cde
3978 * the identifier %$abc will be left as-is so that the handler for %define
3979 * will suck it and define the corresponding value. Other case:
3981 * %define _%$abc cde
3983 * In this case user wants name to be expanded *before* %define starts
3984 * working, so we'll expand %$abc into something (if it has a value;
3985 * otherwise it will be left as-is) then concatenate all successive
3986 * PP_IDs into one.
3988 static Token *expand_id(Token * tline)
3990 Token *cur, *oldnext = NULL;
3992 if (!tline || !tline->next)
3993 return tline;
3995 cur = tline;
3996 while (cur->next &&
3997 (cur->next->type == TOK_ID ||
3998 cur->next->type == TOK_PREPROC_ID
3999 || cur->next->type == TOK_NUMBER))
4000 cur = cur->next;
4002 /* If identifier consists of just one token, don't expand */
4003 if (cur == tline)
4004 return tline;
4006 if (cur) {
4007 oldnext = cur->next; /* Detach the tail past identifier */
4008 cur->next = NULL; /* so that expand_smacro stops here */
4011 tline = expand_smacro(tline);
4013 if (cur) {
4014 /* expand_smacro possibly changhed tline; re-scan for EOL */
4015 cur = tline;
4016 while (cur && cur->next)
4017 cur = cur->next;
4018 if (cur)
4019 cur->next = oldnext;
4022 return tline;
4026 * Determine whether the given line constitutes a multi-line macro
4027 * call, and return the MMacro structure called if so. Doesn't have
4028 * to check for an initial label - that's taken care of in
4029 * expand_mmacro - but must check numbers of parameters. Guaranteed
4030 * to be called with tline->type == TOK_ID, so the putative macro
4031 * name is easy to find.
4033 static MMacro *is_mmacro(Token * tline, Token *** params_array)
4035 MMacro *head, *m;
4036 Token **params;
4037 int nparam;
4039 head = (MMacro *) hash_findix(&mmacros, tline->text);
4042 * Efficiency: first we see if any macro exists with the given
4043 * name. If not, we can return NULL immediately. _Then_ we
4044 * count the parameters, and then we look further along the
4045 * list if necessary to find the proper MMacro.
4047 for (m = head; m; m = m->next)
4048 if (!mstrcmp(m->name, tline->text, m->casesense))
4049 break;
4050 if (!m)
4051 return NULL;
4054 * OK, we have a potential macro. Count and demarcate the
4055 * parameters.
4057 count_mmac_params(tline->next, &nparam, &params);
4060 * So we know how many parameters we've got. Find the MMacro
4061 * structure that handles this number.
4063 while (m) {
4064 if (m->nparam_min <= nparam
4065 && (m->plus || nparam <= m->nparam_max)) {
4067 * This one is right. Just check if cycle removal
4068 * prohibits us using it before we actually celebrate...
4070 if (m->in_progress) {
4071 #if 0
4072 error(ERR_NONFATAL,
4073 "self-reference in multi-line macro `%s'", m->name);
4074 #endif
4075 nasm_free(params);
4076 return NULL;
4079 * It's right, and we can use it. Add its default
4080 * parameters to the end of our list if necessary.
4082 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
4083 params =
4084 nasm_realloc(params,
4085 ((m->nparam_min + m->ndefs +
4086 1) * sizeof(*params)));
4087 while (nparam < m->nparam_min + m->ndefs) {
4088 params[nparam] = m->defaults[nparam - m->nparam_min];
4089 nparam++;
4093 * If we've gone over the maximum parameter count (and
4094 * we're in Plus mode), ignore parameters beyond
4095 * nparam_max.
4097 if (m->plus && nparam > m->nparam_max)
4098 nparam = m->nparam_max;
4100 * Then terminate the parameter list, and leave.
4102 if (!params) { /* need this special case */
4103 params = nasm_malloc(sizeof(*params));
4104 nparam = 0;
4106 params[nparam] = NULL;
4107 *params_array = params;
4108 return m;
4111 * This one wasn't right: look for the next one with the
4112 * same name.
4114 for (m = m->next; m; m = m->next)
4115 if (!mstrcmp(m->name, tline->text, m->casesense))
4116 break;
4120 * After all that, we didn't find one with the right number of
4121 * parameters. Issue a warning, and fail to expand the macro.
4123 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
4124 "macro `%s' exists, but not taking %d parameters",
4125 tline->text, nparam);
4126 nasm_free(params);
4127 return NULL;
4131 * Expand the multi-line macro call made by the given line, if
4132 * there is one to be expanded. If there is, push the expansion on
4133 * istk->expansion and return 1. Otherwise return 0.
4135 static int expand_mmacro(Token * tline)
4137 Token *startline = tline;
4138 Token *label = NULL;
4139 int dont_prepend = 0;
4140 Token **params, *t, *mtok, *tt;
4141 MMacro *m;
4142 Line *l, *ll;
4143 int i, nparam, *paramlen;
4144 const char *mname;
4146 t = tline;
4147 skip_white_(t);
4148 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
4149 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
4150 return 0;
4151 mtok = t;
4152 m = is_mmacro(t, &params);
4153 if (m) {
4154 mname = t->text;
4155 } else {
4156 Token *last;
4158 * We have an id which isn't a macro call. We'll assume
4159 * it might be a label; we'll also check to see if a
4160 * colon follows it. Then, if there's another id after
4161 * that lot, we'll check it again for macro-hood.
4163 label = last = t;
4164 t = t->next;
4165 if (tok_type_(t, TOK_WHITESPACE))
4166 last = t, t = t->next;
4167 if (tok_is_(t, ":")) {
4168 dont_prepend = 1;
4169 last = t, t = t->next;
4170 if (tok_type_(t, TOK_WHITESPACE))
4171 last = t, t = t->next;
4173 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
4174 return 0;
4175 last->next = NULL;
4176 mname = t->text;
4177 tline = t;
4181 * Fix up the parameters: this involves stripping leading and
4182 * trailing whitespace, then stripping braces if they are
4183 * present.
4185 for (nparam = 0; params[nparam]; nparam++) ;
4186 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
4188 for (i = 0; params[i]; i++) {
4189 int brace = false;
4190 int comma = (!m->plus || i < nparam - 1);
4192 t = params[i];
4193 skip_white_(t);
4194 if (tok_is_(t, "{"))
4195 t = t->next, brace = true, comma = false;
4196 params[i] = t;
4197 paramlen[i] = 0;
4198 while (t) {
4199 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
4200 break; /* ... because we have hit a comma */
4201 if (comma && t->type == TOK_WHITESPACE
4202 && tok_is_(t->next, ","))
4203 break; /* ... or a space then a comma */
4204 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
4205 break; /* ... or a brace */
4206 t = t->next;
4207 paramlen[i]++;
4212 * OK, we have a MMacro structure together with a set of
4213 * parameters. We must now go through the expansion and push
4214 * copies of each Line on to istk->expansion. Substitution of
4215 * parameter tokens and macro-local tokens doesn't get done
4216 * until the single-line macro substitution process; this is
4217 * because delaying them allows us to change the semantics
4218 * later through %rotate.
4220 * First, push an end marker on to istk->expansion, mark this
4221 * macro as in progress, and set up its invocation-specific
4222 * variables.
4224 ll = nasm_malloc(sizeof(Line));
4225 ll->next = istk->expansion;
4226 ll->finishes = m;
4227 ll->first = NULL;
4228 istk->expansion = ll;
4230 m->in_progress = true;
4231 m->params = params;
4232 m->iline = tline;
4233 m->nparam = nparam;
4234 m->rotate = 0;
4235 m->paramlen = paramlen;
4236 m->unique = unique++;
4237 m->lineno = 0;
4239 m->next_active = istk->mstk;
4240 istk->mstk = m;
4242 for (l = m->expansion; l; l = l->next) {
4243 Token **tail;
4245 ll = nasm_malloc(sizeof(Line));
4246 ll->finishes = NULL;
4247 ll->next = istk->expansion;
4248 istk->expansion = ll;
4249 tail = &ll->first;
4251 for (t = l->first; t; t = t->next) {
4252 Token *x = t;
4253 switch (t->type) {
4254 case TOK_PREPROC_Q:
4255 tt = *tail = new_Token(NULL, TOK_ID, mname, 0);
4256 break;
4257 case TOK_PREPROC_QQ:
4258 tt = *tail = new_Token(NULL, TOK_ID, m->name, 0);
4259 break;
4260 case TOK_PREPROC_ID:
4261 if (t->text[1] == '0' && t->text[2] == '0') {
4262 dont_prepend = -1;
4263 x = label;
4264 if (!x)
4265 continue;
4267 /* fall through */
4268 default:
4269 tt = *tail = new_Token(NULL, x->type, x->text, 0);
4270 break;
4272 tail = &tt->next;
4274 *tail = NULL;
4278 * If we had a label, push it on as the first line of
4279 * the macro expansion.
4281 if (label) {
4282 if (dont_prepend < 0)
4283 free_tlist(startline);
4284 else {
4285 ll = nasm_malloc(sizeof(Line));
4286 ll->finishes = NULL;
4287 ll->next = istk->expansion;
4288 istk->expansion = ll;
4289 ll->first = startline;
4290 if (!dont_prepend) {
4291 while (label->next)
4292 label = label->next;
4293 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
4298 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
4300 return 1;
4303 /* The function that actually does the error reporting */
4304 static void verror(int severity, const char *fmt, va_list arg)
4306 char buff[1024];
4308 vsnprintf(buff, sizeof(buff), fmt, arg);
4310 if (istk && istk->mstk && istk->mstk->name)
4311 _error(severity, "(%s:%d) %s", istk->mstk->name,
4312 istk->mstk->lineno, buff);
4313 else
4314 _error(severity, "%s", buff);
4318 * Since preprocessor always operate only on the line that didn't
4319 * arrived yet, we should always use ERR_OFFBY1.
4321 static void error(int severity, const char *fmt, ...)
4323 va_list arg;
4325 /* If we're in a dead branch of IF or something like it, ignore the error */
4326 if (istk && istk->conds && !emitting(istk->conds->state))
4327 return;
4329 va_start(arg, fmt);
4330 verror(severity, fmt, arg);
4331 va_end(arg);
4335 * Because %else etc are evaluated in the state context
4336 * of the previous branch, errors might get lost with error():
4337 * %if 0 ... %else trailing garbage ... %endif
4338 * So %else etc should report errors with this function.
4340 static void error_precond(int severity, const char *fmt, ...)
4342 va_list arg;
4344 /* Only ignore the error if it's really in a dead branch */
4345 if (istk && istk->conds && istk->conds->state == COND_NEVER)
4346 return;
4348 va_start(arg, fmt);
4349 verror(severity, fmt, arg);
4350 va_end(arg);
4353 static void
4354 pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
4355 ListGen * listgen, StrList **deplist)
4357 Token *t;
4359 _error = errfunc;
4360 cstk = NULL;
4361 istk = nasm_malloc(sizeof(Include));
4362 istk->next = NULL;
4363 istk->conds = NULL;
4364 istk->expansion = NULL;
4365 istk->mstk = NULL;
4366 istk->fp = fopen(file, "r");
4367 istk->fname = NULL;
4368 src_set_fname(nasm_strdup(file));
4369 src_set_linnum(0);
4370 istk->lineinc = 1;
4371 if (!istk->fp)
4372 error(ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'",
4373 file);
4374 defining = NULL;
4375 nested_mac_count = 0;
4376 nested_rep_count = 0;
4377 init_macros();
4378 unique = 0;
4379 if (tasm_compatible_mode) {
4380 stdmacpos = nasm_stdmac;
4381 } else {
4382 stdmacpos = nasm_stdmac_after_tasm;
4384 any_extrastdmac = extrastdmac && *extrastdmac;
4385 do_predef = true;
4386 list = listgen;
4387 evaluate = eval;
4390 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4391 * The caller, however, will also pass in 3 for preprocess-only so
4392 * we can set __PASS__ accordingly.
4394 pass = apass > 2 ? 2 : apass;
4396 dephead = deptail = deplist;
4397 if (deplist) {
4398 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
4399 sl->next = NULL;
4400 strcpy(sl->str, file);
4401 *deptail = sl;
4402 deptail = &sl->next;
4406 * Define the __PASS__ macro. This is defined here unlike
4407 * all the other builtins, because it is special -- it varies between
4408 * passes.
4410 t = nasm_malloc(sizeof(*t));
4411 t->next = NULL;
4412 make_tok_num(t, apass);
4413 t->a.mac = NULL;
4414 define_smacro(NULL, "__PASS__", true, 0, t);
4417 static char *pp_getline(void)
4419 char *line;
4420 Token *tline;
4422 while (1) {
4424 * Fetch a tokenized line, either from the macro-expansion
4425 * buffer or from the input file.
4427 tline = NULL;
4428 while (istk->expansion && istk->expansion->finishes) {
4429 Line *l = istk->expansion;
4430 if (!l->finishes->name && l->finishes->in_progress > 1) {
4431 Line *ll;
4434 * This is a macro-end marker for a macro with no
4435 * name, which means it's not really a macro at all
4436 * but a %rep block, and the `in_progress' field is
4437 * more than 1, meaning that we still need to
4438 * repeat. (1 means the natural last repetition; 0
4439 * means termination by %exitrep.) We have
4440 * therefore expanded up to the %endrep, and must
4441 * push the whole block on to the expansion buffer
4442 * again. We don't bother to remove the macro-end
4443 * marker: we'd only have to generate another one
4444 * if we did.
4446 l->finishes->in_progress--;
4447 for (l = l->finishes->expansion; l; l = l->next) {
4448 Token *t, *tt, **tail;
4450 ll = nasm_malloc(sizeof(Line));
4451 ll->next = istk->expansion;
4452 ll->finishes = NULL;
4453 ll->first = NULL;
4454 tail = &ll->first;
4456 for (t = l->first; t; t = t->next) {
4457 if (t->text || t->type == TOK_WHITESPACE) {
4458 tt = *tail =
4459 new_Token(NULL, t->type, t->text, 0);
4460 tail = &tt->next;
4464 istk->expansion = ll;
4466 } else {
4468 * Check whether a `%rep' was started and not ended
4469 * within this macro expansion. This can happen and
4470 * should be detected. It's a fatal error because
4471 * I'm too confused to work out how to recover
4472 * sensibly from it.
4474 if (defining) {
4475 if (defining->name)
4476 error(ERR_PANIC,
4477 "defining with name in expansion");
4478 else if (istk->mstk->name)
4479 error(ERR_FATAL,
4480 "`%%rep' without `%%endrep' within"
4481 " expansion of macro `%s'",
4482 istk->mstk->name);
4486 * FIXME: investigate the relationship at this point between
4487 * istk->mstk and l->finishes
4490 MMacro *m = istk->mstk;
4491 istk->mstk = m->next_active;
4492 if (m->name) {
4494 * This was a real macro call, not a %rep, and
4495 * therefore the parameter information needs to
4496 * be freed.
4498 nasm_free(m->params);
4499 free_tlist(m->iline);
4500 nasm_free(m->paramlen);
4501 l->finishes->in_progress = false;
4502 } else
4503 free_mmacro(m);
4505 istk->expansion = l->next;
4506 nasm_free(l);
4507 list->downlevel(LIST_MACRO);
4510 while (1) { /* until we get a line we can use */
4512 if (istk->expansion) { /* from a macro expansion */
4513 char *p;
4514 Line *l = istk->expansion;
4515 if (istk->mstk)
4516 istk->mstk->lineno++;
4517 tline = l->first;
4518 istk->expansion = l->next;
4519 nasm_free(l);
4520 p = detoken(tline, false);
4521 list->line(LIST_MACRO, p);
4522 nasm_free(p);
4523 break;
4525 line = read_line();
4526 if (line) { /* from the current input file */
4527 line = prepreproc(line);
4528 tline = tokenize(line);
4529 nasm_free(line);
4530 break;
4533 * The current file has ended; work down the istk
4536 Include *i = istk;
4537 fclose(i->fp);
4538 if (i->conds)
4539 error(ERR_FATAL,
4540 "expected `%%endif' before end of file");
4541 /* only set line and file name if there's a next node */
4542 if (i->next) {
4543 src_set_linnum(i->lineno);
4544 nasm_free(src_set_fname(i->fname));
4546 istk = i->next;
4547 list->downlevel(LIST_INCLUDE);
4548 nasm_free(i);
4549 if (!istk)
4550 return NULL;
4551 if (istk->expansion && istk->expansion->finishes)
4552 break;
4557 * We must expand MMacro parameters and MMacro-local labels
4558 * _before_ we plunge into directive processing, to cope
4559 * with things like `%define something %1' such as STRUC
4560 * uses. Unless we're _defining_ a MMacro, in which case
4561 * those tokens should be left alone to go into the
4562 * definition; and unless we're in a non-emitting
4563 * condition, in which case we don't want to meddle with
4564 * anything.
4566 if (!defining && !(istk->conds && !emitting(istk->conds->state))
4567 && !(istk->mstk && !istk->mstk->in_progress)) {
4568 tline = expand_mmac_params(tline);
4572 * Check the line to see if it's a preprocessor directive.
4574 if (do_directive(tline) == DIRECTIVE_FOUND) {
4575 continue;
4576 } else if (defining) {
4578 * We're defining a multi-line macro. We emit nothing
4579 * at all, and just
4580 * shove the tokenized line on to the macro definition.
4582 Line *l = nasm_malloc(sizeof(Line));
4583 l->next = defining->expansion;
4584 l->first = tline;
4585 l->finishes = NULL;
4586 defining->expansion = l;
4587 continue;
4588 } else if (istk->conds && !emitting(istk->conds->state)) {
4590 * We're in a non-emitting branch of a condition block.
4591 * Emit nothing at all, not even a blank line: when we
4592 * emerge from the condition we'll give a line-number
4593 * directive so we keep our place correctly.
4595 free_tlist(tline);
4596 continue;
4597 } else if (istk->mstk && !istk->mstk->in_progress) {
4599 * We're in a %rep block which has been terminated, so
4600 * we're walking through to the %endrep without
4601 * emitting anything. Emit nothing at all, not even a
4602 * blank line: when we emerge from the %rep block we'll
4603 * give a line-number directive so we keep our place
4604 * correctly.
4606 free_tlist(tline);
4607 continue;
4608 } else {
4609 tline = expand_smacro(tline);
4610 if (!expand_mmacro(tline)) {
4612 * De-tokenize the line again, and emit it.
4614 line = detoken(tline, true);
4615 free_tlist(tline);
4616 break;
4617 } else {
4618 continue; /* expand_mmacro calls free_tlist */
4623 return line;
4626 static void pp_cleanup(int pass)
4628 if (defining) {
4629 if(defining->name) {
4630 error(ERR_NONFATAL,
4631 "end of file while still defining macro `%s'",
4632 defining->name);
4633 } else {
4634 error(ERR_NONFATAL, "end of file while still in %%rep");
4637 free_mmacro(defining);
4639 while (cstk)
4640 ctx_pop();
4641 free_macros();
4642 while (istk) {
4643 Include *i = istk;
4644 istk = istk->next;
4645 fclose(i->fp);
4646 nasm_free(i->fname);
4647 nasm_free(i);
4649 while (cstk)
4650 ctx_pop();
4651 nasm_free(src_set_fname(NULL));
4652 if (pass == 0) {
4653 IncPath *i;
4654 free_llist(predef);
4655 delete_Blocks();
4656 while ((i = ipath)) {
4657 ipath = i->next;
4658 if (i->path)
4659 nasm_free(i->path);
4660 nasm_free(i);
4665 void pp_include_path(char *path)
4667 IncPath *i;
4669 i = nasm_malloc(sizeof(IncPath));
4670 i->path = path ? nasm_strdup(path) : NULL;
4671 i->next = NULL;
4673 if (ipath != NULL) {
4674 IncPath *j = ipath;
4675 while (j->next != NULL)
4676 j = j->next;
4677 j->next = i;
4678 } else {
4679 ipath = i;
4683 void pp_pre_include(char *fname)
4685 Token *inc, *space, *name;
4686 Line *l;
4688 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
4689 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
4690 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
4692 l = nasm_malloc(sizeof(Line));
4693 l->next = predef;
4694 l->first = inc;
4695 l->finishes = NULL;
4696 predef = l;
4699 void pp_pre_define(char *definition)
4701 Token *def, *space;
4702 Line *l;
4703 char *equals;
4705 equals = strchr(definition, '=');
4706 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4707 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
4708 if (equals)
4709 *equals = ' ';
4710 space->next = tokenize(definition);
4711 if (equals)
4712 *equals = '=';
4714 l = nasm_malloc(sizeof(Line));
4715 l->next = predef;
4716 l->first = def;
4717 l->finishes = NULL;
4718 predef = l;
4721 void pp_pre_undefine(char *definition)
4723 Token *def, *space;
4724 Line *l;
4726 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4727 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
4728 space->next = tokenize(definition);
4730 l = nasm_malloc(sizeof(Line));
4731 l->next = predef;
4732 l->first = def;
4733 l->finishes = NULL;
4734 predef = l;
4738 * Added by Keith Kanios:
4740 * This function is used to assist with "runtime" preprocessor
4741 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4743 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4744 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4747 void pp_runtime(char *definition)
4749 Token *def;
4751 def = tokenize(definition);
4752 if(do_directive(def) == NO_DIRECTIVE_FOUND)
4753 free_tlist(def);
4757 void pp_extra_stdmac(macros_t *macros)
4759 extrastdmac = macros;
4762 static void make_tok_num(Token * tok, int64_t val)
4764 char numbuf[20];
4765 snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
4766 tok->text = nasm_strdup(numbuf);
4767 tok->type = TOK_NUMBER;
4770 Preproc nasmpp = {
4771 pp_reset,
4772 pp_getline,
4773 pp_cleanup