blob: 885b3a985f11da6ce6532f10c8e44eef056d09f9 [file] [log] [blame]
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07001/* ----------------------------------------------------------------------- *
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002 *
3 * Copyright 1996-2010 The NASM Authors - All Rights Reserved
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07004 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07007 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000010 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -070011 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
Cyrill Gorcunovaccda192010-02-16 10:27:56 +030017 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -070018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * ----------------------------------------------------------------------- */
33
34/*
35 * preproc.c macro preprocessor for the Netwide Assembler
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000036 */
37
H. Peter Anvin4836e332002-04-30 20:56:43 +000038/* Typical flow of text through preproc
39 *
Keith Kaniosb7a89542007-04-12 02:40:54 +000040 * pp_getline gets tokenized lines, either
H. Peter Anvin4836e332002-04-30 20:56:43 +000041 *
42 * from a macro expansion
43 *
44 * or
45 * {
46 * read_line gets raw text from stdmacpos, or predef, or current input file
Keith Kaniosb7a89542007-04-12 02:40:54 +000047 * tokenize converts to tokens
H. Peter Anvin4836e332002-04-30 20:56:43 +000048 * }
49 *
50 * expand_mmac_params is used to expand %1 etc., unless a macro is being
51 * defined or a false conditional is being processed
52 * (%0, %1, %+1, %-1, %%foo
53 *
54 * do_directive checks for directives
55 *
56 * expand_smacro is used to expand single line macros
57 *
58 * expand_mmacro is used to expand multi-line macros
59 *
60 * detoken is used to convert the line back to text
61 */
H. Peter Anvineba20a72002-04-30 20:53:55 +000062
H. Peter Anvinfe501952007-10-02 21:53:51 -070063#include "compiler.h"
64
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000065#include <stdio.h>
H. Peter Anvinaf535c12002-04-30 20:59:21 +000066#include <stdarg.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000067#include <stdlib.h>
68#include <stddef.h>
69#include <string.h>
70#include <ctype.h>
H. Peter Anvin76690a12002-04-30 20:52:49 +000071#include <limits.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000072#include <inttypes.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000073
74#include "nasm.h"
75#include "nasmlib.h"
H. Peter Anvin4169a472007-09-12 01:29:43 +000076#include "preproc.h"
H. Peter Anvin97a23472007-09-16 17:57:25 -070077#include "hashtbl.h"
H. Peter Anvin8cad14b2008-06-01 17:23:51 -070078#include "quote.h"
H. Peter Anvinc2df2822007-10-24 15:29:28 -070079#include "stdscan.h"
H. Peter Anvindbb640b2009-07-18 18:57:16 -070080#include "eval.h"
H. Peter Anvinc2df2822007-10-24 15:29:28 -070081#include "tokens.h"
H. Peter Anvina4835d42008-05-20 14:21:29 -070082#include "tables.h"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000083
84typedef struct SMacro SMacro;
85typedef struct MMacro MMacro;
Keith Kanios891775e2009-07-11 06:08:54 -050086typedef struct MMacroInvocation MMacroInvocation;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000087typedef struct Context Context;
88typedef struct Token Token;
H. Peter Anvince616072002-04-30 21:02:23 +000089typedef struct Blocks Blocks;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000090typedef struct Line Line;
91typedef struct Include Include;
92typedef struct Cond Cond;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000093typedef struct IncPath IncPath;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000094
95/*
H. Peter Anvin97a23472007-09-16 17:57:25 -070096 * Note on the storage of both SMacro and MMacros: the hash table
97 * indexes them case-insensitively, and we then have to go through a
98 * linked list of potential case aliases (and, for MMacros, parameter
99 * ranges); this is to preserve the matching semantics of the earlier
100 * code. If the number of case aliases for a specific macro is a
101 * performance issue, you may want to reconsider your coding style.
102 */
103
104/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000105 * Store the definition of a single-line macro.
106 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000107struct SMacro {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000108 SMacro *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000109 char *name;
H. Peter Anvin70055962007-10-11 00:05:31 -0700110 bool casesense;
H. Peter Anvin16ed4382007-10-11 10:06:19 -0700111 bool in_progress;
H. Peter Anvin70055962007-10-11 00:05:31 -0700112 unsigned int nparam;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000113 Token *expansion;
114};
115
116/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000117 * Store the definition of a multi-line macro. This is also used to
118 * store the interiors of `%rep...%endrep' blocks, which are
119 * effectively self-re-invoking multi-line macros which simply
120 * don't have a name or bother to appear in the hash tables. %rep
121 * blocks are signified by having a NULL `name' field.
122 *
123 * In a MMacro describing a `%rep' block, the `in_progress' field
124 * isn't merely boolean, but gives the number of repeats left to
125 * run.
126 *
127 * The `next' field is used for storing MMacros in hash tables; the
128 * `next_active' field is for stacking them on istk entries.
129 *
130 * When a MMacro is being expanded, `params', `iline', `nparam',
131 * `paramlen', `rotate' and `unique' are local to the invocation.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000132 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000133struct MMacro {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000134 MMacro *next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300135 MMacroInvocation *prev; /* previous invocation */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000136 char *name;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -0700137 int nparam_min, nparam_max;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700138 bool casesense;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300139 bool plus; /* is the last parameter greedy? */
140 bool nolist; /* is this macro listing-inhibited? */
141 int64_t in_progress; /* is this macro currently being expanded? */
142 int32_t max_depth; /* maximum number of recursive expansions allowed */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000143 Token *dlist; /* All defaults as one list */
144 Token **defaults; /* Parameter default pointers */
145 int ndefs; /* number of default parameters */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000146 Line *expansion;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000147
148 MMacro *next_active;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000149 MMacro *rep_nest; /* used for nesting %rep */
150 Token **params; /* actual parameters */
151 Token *iline; /* invocation line */
H. Peter Anvin25a99342007-09-22 17:45:45 -0700152 unsigned int nparam, rotate;
153 int *paramlen;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700154 uint64_t unique;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000155 int lineno; /* Current line number on expansion */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300156 uint64_t condcnt; /* number of if blocks... */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000157};
158
Keith Kanios891775e2009-07-11 06:08:54 -0500159
160/* Store the definition of a multi-line macro, as defined in a
161 * previous recursive macro expansion.
162 */
163struct MMacroInvocation {
H. Peter Anvin89cee572009-07-15 09:16:54 -0400164 MMacroInvocation *prev; /* previous invocation */
165 Token **params; /* actual parameters */
166 Token *iline; /* invocation line */
Keith Kanios891775e2009-07-11 06:08:54 -0500167 unsigned int nparam, rotate;
168 int *paramlen;
169 uint64_t unique;
Keith Kanios3c0d91f2009-10-25 13:28:03 -0500170 uint64_t condcnt;
Keith Kanios891775e2009-07-11 06:08:54 -0500171};
172
173
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000174/*
175 * The context stack is composed of a linked list of these.
176 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000177struct Context {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000178 Context *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000179 char *name;
H. Peter Anvin166c2472008-05-28 12:28:58 -0700180 struct hash_table localmac;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000181 uint32_t number;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000182};
183
184/*
185 * This is the internal form which we break input lines up into.
186 * Typically stored in linked lists.
187 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000188 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
189 * necessarily used as-is, but is intended to denote the number of
190 * the substituted parameter. So in the definition
191 *
192 * %define a(x,y) ( (x) & ~(y) )
H. Peter Anvin70653092007-10-19 14:42:29 -0700193 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000194 * the token representing `x' will have its type changed to
195 * TOK_SMAC_PARAM, but the one representing `y' will be
196 * TOK_SMAC_PARAM+1.
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000197 *
198 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
199 * which doesn't need quotes around it. Used in the pre-include
200 * mechanism as an alternative to trying to find a sensible type of
201 * quote to use on the filename we were passed.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000202 */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000203enum pp_token_type {
204 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID,
205 TOK_PREPROC_ID, TOK_STRING,
H. Peter Anvin6c81f0a2008-05-25 21:46:17 -0700206 TOK_NUMBER, TOK_FLOAT, TOK_SMAC_END, TOK_OTHER,
207 TOK_INTERNAL_STRING,
208 TOK_PREPROC_Q, TOK_PREPROC_QQ,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300209 TOK_PASTE, /* %+ */
210 TOK_INDIRECT, /* %[...] */
211 TOK_SMAC_PARAM, /* MUST BE LAST IN THE LIST!!! */
212 TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000213};
214
H. Peter Anvine2c80182005-01-15 22:15:51 +0000215struct Token {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000216 Token *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000217 char *text;
H. Peter Anvinf26e0972008-07-01 21:26:27 -0700218 union {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300219 SMacro *mac; /* associated macro for TOK_SMAC_END */
220 size_t len; /* scratch length field */
221 } a; /* Auxiliary data */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000222 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000223};
224
225/*
226 * Multi-line macro definitions are stored as a linked list of
227 * these, which is essentially a container to allow several linked
228 * lists of Tokens.
H. Peter Anvin70653092007-10-19 14:42:29 -0700229 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000230 * Note that in this module, linked lists are treated as stacks
231 * wherever possible. For this reason, Lines are _pushed_ on to the
232 * `expansion' field in MMacro structures, so that the linked list,
233 * if walked, would give the macro lines in reverse order; this
234 * means that we can walk the list when expanding a macro, and thus
235 * push the lines on to the `expansion' field in _istk_ in reverse
236 * order (so that when popped back off they are in the right
237 * order). It may seem cockeyed, and it relies on my design having
238 * an even number of steps in, but it works...
239 *
240 * Some of these structures, rather than being actual lines, are
241 * markers delimiting the end of the expansion of a given macro.
H. Peter Anvin76690a12002-04-30 20:52:49 +0000242 * This is for use in the cycle-tracking and %rep-handling code.
243 * Such structures have `finishes' non-NULL, and `first' NULL. All
244 * others have `finishes' NULL, but `first' may still be NULL if
245 * the line is blank.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000246 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000247struct Line {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000248 Line *next;
249 MMacro *finishes;
250 Token *first;
251};
252
253/*
254 * To handle an arbitrary level of file inclusion, we maintain a
255 * stack (ie linked list) of these things.
256 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000257struct Include {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000258 Include *next;
259 FILE *fp;
260 Cond *conds;
261 Line *expansion;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000262 char *fname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000263 int lineno, lineinc;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300264 MMacro *mstk; /* stack of active macros/reps */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000265};
266
267/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000268 * Include search path. This is simply a list of strings which get
269 * prepended, in turn, to the name of an include file, in an
270 * attempt to find the file if it's not in the current directory.
271 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000272struct IncPath {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000273 IncPath *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000274 char *path;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000275};
276
277/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000278 * Conditional assembly: we maintain a separate stack of these for
279 * each level of file inclusion. (The only reason we keep the
280 * stacks separate is to ensure that a stray `%endif' in a file
281 * included from within the true branch of a `%if' won't terminate
282 * it and cause confusion: instead, rightly, it'll cause an error.)
283 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000284struct Cond {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000285 Cond *next;
286 int state;
287};
H. Peter Anvine2c80182005-01-15 22:15:51 +0000288enum {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000289 /*
290 * These states are for use just after %if or %elif: IF_TRUE
291 * means the condition has evaluated to truth so we are
292 * currently emitting, whereas IF_FALSE means we are not
293 * currently emitting but will start doing so if a %else comes
294 * up. In these states, all directives are admissible: %elif,
295 * %else and %endif. (And of course %if.)
296 */
297 COND_IF_TRUE, COND_IF_FALSE,
298 /*
299 * These states come up after a %else: ELSE_TRUE means we're
300 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
301 * any %elif or %else will cause an error.
302 */
303 COND_ELSE_TRUE, COND_ELSE_FALSE,
304 /*
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200305 * These states mean that we're not emitting now, and also that
306 * nothing until %endif will be emitted at all. COND_DONE is
307 * used when we've had our moment of emission
308 * and have now started seeing %elifs. COND_NEVER is used when
309 * the condition construct in question is contained within a
310 * non-emitting branch of a larger condition construct,
311 * or if there is an error.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000312 */
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200313 COND_DONE, COND_NEVER
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000314};
315#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
316
H. Peter Anvin70653092007-10-19 14:42:29 -0700317/*
Ed Beroset3ab3f412002-06-11 03:31:49 +0000318 * These defines are used as the possible return values for do_directive
319 */
320#define NO_DIRECTIVE_FOUND 0
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300321#define DIRECTIVE_FOUND 1
Ed Beroset3ab3f412002-06-11 03:31:49 +0000322
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000323/*
Keith Kanios852f1ee2009-07-12 00:19:55 -0500324 * This define sets the upper limit for smacro and recursive mmacro
325 * expansions
326 */
327#define DEADMAN_LIMIT (1 << 20)
328
329/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000330 * Condition codes. Note that we use c_ prefix not C_ because C_ is
331 * used in nasm.h for the "real" condition codes. At _this_ level,
332 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
333 * ones, so we need a different enum...
334 */
H. Peter Anvin476d2862007-10-02 22:04:15 -0700335static const char * const conditions[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000336 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
337 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
H. Peter Anvince9be342007-09-12 00:22:29 +0000338 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000339};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700340enum pp_conds {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000341 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
342 c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
H. Peter Anvin476d2862007-10-02 22:04:15 -0700343 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
344 c_none = -1
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000345};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700346static const enum pp_conds inverse_ccs[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000347 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
348 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,
H. Peter Anvince9be342007-09-12 00:22:29 +0000349 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000350};
351
H. Peter Anvin76690a12002-04-30 20:52:49 +0000352/*
353 * Directive names.
354 */
H. Peter Anvin65747262002-05-07 00:10:05 +0000355/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
H. Peter Anvin9bf0aa72007-09-12 02:12:07 +0000356static int is_condition(enum preproc_token arg)
H. Peter Anvin65747262002-05-07 00:10:05 +0000357{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000358 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
H. Peter Anvin65747262002-05-07 00:10:05 +0000359}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000360
361/* For TASM compatibility we need to be able to recognise TASM compatible
362 * conditional compilation directives. Using the NASM pre-processor does
363 * not work, so we look for them specifically from the following list and
364 * then jam in the equivalent NASM directive into the input stream.
365 */
366
H. Peter Anvine2c80182005-01-15 22:15:51 +0000367enum {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000368 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
369 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
370};
371
H. Peter Anvin476d2862007-10-02 22:04:15 -0700372static const char * const tasm_directives[] = {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000373 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
374 "ifndef", "include", "local"
375};
376
377static int StackSize = 4;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000378static char *StackPointer = "ebp";
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000379static int ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -0800380static int LocalOffset = 0;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000381
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000382static Context *cstk;
383static Include *istk;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000384static IncPath *ipath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000385
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300386static int pass; /* HACK: pass 0 = generate dependencies only */
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700387static StrList **dephead, **deptail; /* Dependency list */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000388
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300389static uint64_t unique; /* unique identifier numbers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000390
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000391static Line *predef = NULL;
H. Peter Anvind2456592008-06-19 15:04:18 -0700392static bool do_predef;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000393
394static ListGen *list;
395
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000396/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000397 * The current set of multi-line macros we have defined.
398 */
H. Peter Anvin166c2472008-05-28 12:28:58 -0700399static struct hash_table mmacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000400
401/*
402 * The current set of single-line macros we have defined.
403 */
H. Peter Anvin166c2472008-05-28 12:28:58 -0700404static struct hash_table smacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000405
406/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000407 * The multi-line macro we are currently defining, or the %rep
408 * block we are currently reading, if any.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000409 */
410static MMacro *defining;
411
Charles Crayned4200be2008-07-12 16:42:33 -0700412static uint64_t nested_mac_count;
413static uint64_t nested_rep_count;
414
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000415/*
416 * The number of macro parameters to allocate space for at a time.
417 */
418#define PARAM_DELTA 16
419
420/*
H. Peter Anvina4835d42008-05-20 14:21:29 -0700421 * The standard macro set: defined in macros.c in the array nasm_stdmac.
422 * This gives our position in the macro set, when we're processing it.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000423 */
H. Peter Anvina70547f2008-07-19 21:44:26 -0700424static macros_t *stdmacpos;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000425
426/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000427 * The extra standard macros that come from the object format, if
428 * any.
429 */
H. Peter Anvina70547f2008-07-19 21:44:26 -0700430static macros_t *extrastdmac = NULL;
H. Peter Anvincfb71762008-06-20 15:20:16 -0700431static bool any_extrastdmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000432
433/*
H. Peter Anvin734b1882002-04-30 21:01:08 +0000434 * Tokens are allocated in blocks to improve speed
435 */
436#define TOKEN_BLOCKSIZE 4096
437static Token *freeTokens = NULL;
H. Peter Anvince616072002-04-30 21:02:23 +0000438struct Blocks {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000439 Blocks *next;
440 void *chunk;
H. Peter Anvince616072002-04-30 21:02:23 +0000441};
442
443static Blocks blocks = { NULL, NULL };
H. Peter Anvin734b1882002-04-30 21:01:08 +0000444
445/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000446 * Forward declarations.
447 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000448static Token *expand_mmac_params(Token * tline);
449static Token *expand_smacro(Token * tline);
450static Token *expand_id(Token * tline);
H. Peter Anvinf8ad5322009-02-21 17:55:08 -0800451static Context *get_ctx(const char *name, const char **namep,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300452 bool all_contexts);
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700453static void make_tok_num(Token * tok, int64_t val);
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000454static void error(int severity, const char *fmt, ...);
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200455static void error_precond(int severity, const char *fmt, ...);
H. Peter Anvince616072002-04-30 21:02:23 +0000456static void *new_Block(size_t size);
457static void delete_Blocks(void);
H. Peter Anvinc751e862008-06-09 10:18:45 -0700458static Token *new_Token(Token * next, enum pp_token_type type,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300459 const char *text, int txtlen);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000460static Token *delete_Token(Token * t);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000461
462/*
463 * Macros for safe checking of token pointers, avoid *(NULL)
464 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300465#define tok_type_(x,t) ((x) && (x)->type == (t))
466#define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
467#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
468#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
H. Peter Anvin76690a12002-04-30 20:52:49 +0000469
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300470/*
H. Peter Anvin077fb932010-07-20 14:56:30 -0700471 * nasm_unquote with error if the string contains NUL characters.
472 * If the string contains NUL characters, issue an error and return
473 * the C len, i.e. truncate at the NUL.
474 */
475static size_t nasm_unquote_cstr(char *qstr, enum preproc_token directive)
476{
477 size_t len = nasm_unquote(qstr, NULL);
478 size_t clen = strlen(qstr);
479
480 if (len != clen)
481 error(ERR_NONFATAL, "NUL character in `%s' directive",
482 pp_directives[directive]);
483
484 return clen;
485}
486
487/*
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300488 * Handle TASM specific directives, which do not contain a % in
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000489 * front of them. We do it here because I could not find any other
490 * place to do it for the moment, and it is a hack (ideally it would
491 * be nice to be able to use the NASM pre-processor to do it).
492 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000493static char *check_tasm_directive(char *line)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000494{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000495 int32_t i, j, k, m, len;
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400496 char *p, *q, *oldline, oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000497
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400498 p = nasm_skip_spaces(line);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000499
500 /* Binary search for the directive name */
501 i = -1;
Cyrill Gorcunova7319242010-06-03 22:04:36 +0400502 j = ARRAY_SIZE(tasm_directives);
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400503 q = nasm_skip_word(p);
504 len = q - p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000505 if (len) {
506 oldchar = p[len];
507 p[len] = 0;
508 while (j - i > 1) {
509 k = (j + i) / 2;
510 m = nasm_stricmp(p, tasm_directives[k]);
511 if (m == 0) {
512 /* We have found a directive, so jam a % in front of it
513 * so that NASM will then recognise it as one if it's own.
514 */
515 p[len] = oldchar;
516 len = strlen(p);
517 oldline = line;
518 line = nasm_malloc(len + 2);
519 line[0] = '%';
520 if (k == TM_IFDIFI) {
H. Peter Anvin18f48792009-06-27 15:56:27 -0700521 /*
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300522 * NASM does not recognise IFDIFI, so we convert
523 * it to %if 0. This is not used in NASM
524 * compatible code, but does need to parse for the
525 * TASM macro package.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000526 */
H. Peter Anvin18f48792009-06-27 15:56:27 -0700527 strcpy(line + 1, "if 0");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000528 } else {
529 memcpy(line + 1, p, len + 1);
530 }
531 nasm_free(oldline);
532 return line;
533 } else if (m < 0) {
534 j = k;
535 } else
536 i = k;
537 }
538 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000539 }
540 return line;
541}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000542
H. Peter Anvin76690a12002-04-30 20:52:49 +0000543/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000544 * The pre-preprocessing stage... This function translates line
545 * number indications as they emerge from GNU cpp (`# lineno "file"
546 * flags') into NASM preprocessor line number indications (`%line
547 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000548 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000549static char *prepreproc(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000550{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000551 int lineno, fnlen;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000552 char *fname, *oldline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000553
H. Peter Anvine2c80182005-01-15 22:15:51 +0000554 if (line[0] == '#' && line[1] == ' ') {
555 oldline = line;
556 fname = oldline + 2;
557 lineno = atoi(fname);
558 fname += strspn(fname, "0123456789 ");
559 if (*fname == '"')
560 fname++;
561 fnlen = strcspn(fname, "\"");
562 line = nasm_malloc(20 + fnlen);
563 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
564 nasm_free(oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000565 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000566 if (tasm_compatible_mode)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000567 return check_tasm_directive(line);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000568 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000569}
570
571/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000572 * Free a linked list of tokens.
573 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000574static void free_tlist(Token * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000575{
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400576 while (list)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000577 list = delete_Token(list);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000578}
579
580/*
581 * Free a linked list of lines.
582 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000583static void free_llist(Line * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000584{
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400585 Line *l, *tmp;
586 list_for_each_safe(l, tmp, list) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000587 free_tlist(l->first);
588 nasm_free(l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000589 }
590}
591
592/*
H. Peter Anvineba20a72002-04-30 20:53:55 +0000593 * Free an MMacro
594 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000595static void free_mmacro(MMacro * m)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000596{
H. Peter Anvin734b1882002-04-30 21:01:08 +0000597 nasm_free(m->name);
598 free_tlist(m->dlist);
599 nasm_free(m->defaults);
600 free_llist(m->expansion);
601 nasm_free(m);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000602}
603
604/*
H. Peter Anvin97a23472007-09-16 17:57:25 -0700605 * Free all currently defined macros, and free the hash tables
606 */
H. Peter Anvin072771e2008-05-22 13:17:51 -0700607static void free_smacro_table(struct hash_table *smt)
H. Peter Anvin97a23472007-09-16 17:57:25 -0700608{
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400609 SMacro *s, *tmp;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700610 const char *key;
611 struct hash_tbl_node *it = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -0700612
H. Peter Anvin072771e2008-05-22 13:17:51 -0700613 while ((s = hash_iterate(smt, &it, &key)) != NULL) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300614 nasm_free((void *)key);
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400615 list_for_each_safe(s, tmp, s) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300616 nasm_free(s->name);
617 free_tlist(s->expansion);
618 nasm_free(s);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300619 }
H. Peter Anvin97a23472007-09-16 17:57:25 -0700620 }
H. Peter Anvin072771e2008-05-22 13:17:51 -0700621 hash_free(smt);
622}
623
624static void free_mmacro_table(struct hash_table *mmt)
625{
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400626 MMacro *m, *tmp;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700627 const char *key;
628 struct hash_tbl_node *it = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -0700629
630 it = NULL;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700631 while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300632 nasm_free((void *)key);
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400633 list_for_each_safe(m ,tmp, m)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300634 free_mmacro(m);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700635 }
H. Peter Anvin072771e2008-05-22 13:17:51 -0700636 hash_free(mmt);
637}
638
639static void free_macros(void)
640{
H. Peter Anvin166c2472008-05-28 12:28:58 -0700641 free_smacro_table(&smacros);
642 free_mmacro_table(&mmacros);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700643}
644
645/*
646 * Initialize the hash tables
647 */
648static void init_macros(void)
649{
H. Peter Anvin166c2472008-05-28 12:28:58 -0700650 hash_init(&smacros, HASH_LARGE);
651 hash_init(&mmacros, HASH_LARGE);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700652}
653
654/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000655 * Pop the context stack.
656 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000657static void ctx_pop(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000658{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000659 Context *c = cstk;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000660
661 cstk = cstk->next;
H. Peter Anvin166c2472008-05-28 12:28:58 -0700662 free_smacro_table(&c->localmac);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000663 nasm_free(c->name);
664 nasm_free(c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000665}
666
H. Peter Anvin072771e2008-05-22 13:17:51 -0700667/*
668 * Search for a key in the hash index; adding it if necessary
669 * (in which case we initialize the data pointer to NULL.)
670 */
671static void **
672hash_findi_add(struct hash_table *hash, const char *str)
673{
674 struct hash_insert hi;
675 void **r;
676 char *strx;
677
678 r = hash_findi(hash, str, &hi);
679 if (r)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300680 return r;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700681
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300682 strx = nasm_strdup(str); /* Use a more efficient allocator here? */
H. Peter Anvin072771e2008-05-22 13:17:51 -0700683 return hash_add(&hi, strx, NULL);
684}
685
686/*
687 * Like hash_findi, but returns the data element rather than a pointer
688 * to it. Used only when not adding a new element, hence no third
689 * argument.
690 */
691static void *
692hash_findix(struct hash_table *hash, const char *str)
693{
694 void **p;
695
696 p = hash_findi(hash, str, NULL);
697 return p ? *p : NULL;
698}
699
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +0400700/*
701 * read line from standart macros set,
702 * if there no more left -- return NULL
703 */
704static char *line_from_stdmac(void)
705{
706 unsigned char c;
707 const unsigned char *p = stdmacpos;
708 char *line, *q;
709 size_t len = 0;
710
711 if (!stdmacpos)
712 return NULL;
713
714 while ((c = *p++)) {
715 if (c >= 0x80)
716 len += pp_directives_len[c - 0x80] + 1;
717 else
718 len++;
719 }
720
721 line = nasm_malloc(len + 1);
722 q = line;
723 while ((c = *stdmacpos++)) {
724 if (c >= 0x80) {
725 memcpy(q, pp_directives[c - 0x80], pp_directives_len[c - 0x80]);
726 q += pp_directives_len[c - 0x80];
727 *q++ = ' ';
728 } else {
729 *q++ = c;
730 }
731 }
732 stdmacpos = p;
733 *q = '\0';
734
735 if (!*stdmacpos) {
736 /* This was the last of the standard macro chain... */
737 stdmacpos = NULL;
738 if (any_extrastdmac) {
739 stdmacpos = extrastdmac;
740 any_extrastdmac = false;
741 } else if (do_predef) {
742 Line *pd, *l;
743 Token *head, **tail, *t;
744
745 /*
746 * Nasty hack: here we push the contents of
747 * `predef' on to the top-level expansion stack,
748 * since this is the most convenient way to
749 * implement the pre-include and pre-define
750 * features.
751 */
752 list_for_each(pd, predef) {
753 head = NULL;
754 tail = &head;
755 list_for_each(t, pd->first) {
756 *tail = new_Token(NULL, t->type, t->text, 0);
757 tail = &(*tail)->next;
758 }
759
760 l = nasm_malloc(sizeof(Line));
761 l->next = istk->expansion;
762 l->first = head;
763 l->finishes = NULL;
764
765 istk->expansion = l;
766 }
767 do_predef = false;
768 }
769 }
770
771 return line;
772}
773
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000774#define BUF_DELTA 512
775/*
776 * Read a line from the top file in istk, handling multiple CR/LFs
777 * at the end of the line read, and handling spurious ^Zs. Will
778 * return lines from the standard macro set if this has not already
779 * been done.
780 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000781static char *read_line(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000782{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000783 char *buffer, *p, *q;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000784 int bufsize, continued_count;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000785
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +0400786 /*
787 * standart macros set (predefined) goes first
788 */
789 p = line_from_stdmac();
790 if (p)
791 return p;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700792
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +0400793 /*
794 * regular read from a file
795 */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000796 bufsize = BUF_DELTA;
797 buffer = nasm_malloc(BUF_DELTA);
798 p = buffer;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000799 continued_count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000800 while (1) {
801 q = fgets(p, bufsize - (p - buffer), istk->fp);
802 if (!q)
803 break;
804 p += strlen(p);
805 if (p > buffer && p[-1] == '\n') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300806 /*
807 * Convert backslash-CRLF line continuation sequences into
808 * nothing at all (for DOS and Windows)
809 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000810 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
811 p -= 3;
812 *p = 0;
813 continued_count++;
814 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300815 /*
816 * Also convert backslash-LF line continuation sequences into
817 * nothing at all (for Unix)
818 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000819 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
820 p -= 2;
821 *p = 0;
822 continued_count++;
823 } else {
824 break;
825 }
826 }
827 if (p - buffer > bufsize - 10) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000828 int32_t offset = p - buffer;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000829 bufsize += BUF_DELTA;
830 buffer = nasm_realloc(buffer, bufsize);
831 p = buffer + offset; /* prevent stale-pointer problems */
832 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000833 }
834
H. Peter Anvine2c80182005-01-15 22:15:51 +0000835 if (!q && p == buffer) {
836 nasm_free(buffer);
837 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000838 }
839
H. Peter Anvine2c80182005-01-15 22:15:51 +0000840 src_set_linnum(src_get_linnum() + istk->lineinc +
841 (continued_count * istk->lineinc));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000842
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000843 /*
844 * Play safe: remove CRs as well as LFs, if any of either are
845 * present at the end of the line.
846 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000847 while (--p >= buffer && (*p == '\n' || *p == '\r'))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000848 *p = '\0';
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000849
850 /*
851 * Handle spurious ^Z, which may be inserted into source files
852 * by some file transfer utilities.
853 */
854 buffer[strcspn(buffer, "\032")] = '\0';
855
H. Peter Anvin734b1882002-04-30 21:01:08 +0000856 list->line(LIST_READ, buffer);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000857
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000858 return buffer;
859}
860
861/*
Keith Kaniosb7a89542007-04-12 02:40:54 +0000862 * Tokenize a line of text. This is a very simple process since we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000863 * don't need to parse the value out of e.g. numeric tokens: we
864 * simply split one string into many.
865 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000866static Token *tokenize(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000867{
H. Peter Anvinca544db2008-10-19 19:30:11 -0700868 char c, *p = line;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000869 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000870 Token *list = NULL;
871 Token *t, **tail = &list;
872
H. Peter Anvine2c80182005-01-15 22:15:51 +0000873 while (*line) {
874 p = line;
875 if (*p == '%') {
876 p++;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300877 if (*p == '+' && !nasm_isdigit(p[1])) {
878 p++;
879 type = TOK_PASTE;
880 } else if (nasm_isdigit(*p) ||
881 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000882 do {
883 p++;
884 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700885 while (nasm_isdigit(*p));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000886 type = TOK_PREPROC_ID;
887 } else if (*p == '{') {
888 p++;
889 while (*p && *p != '}') {
890 p[-1] = *p;
891 p++;
892 }
893 p[-1] = '\0';
894 if (*p)
895 p++;
896 type = TOK_PREPROC_ID;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300897 } else if (*p == '[') {
898 int lvl = 1;
899 line += 2; /* Skip the leading %[ */
900 p++;
901 while (lvl && (c = *p++)) {
902 switch (c) {
903 case ']':
904 lvl--;
905 break;
906 case '%':
907 if (*p == '[')
908 lvl++;
909 break;
910 case '\'':
911 case '\"':
912 case '`':
Cyrill Gorcunovc6360a72010-07-13 13:32:19 +0400913 p = nasm_skip_string(p - 1) + 1;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300914 break;
915 default:
916 break;
917 }
918 }
919 p--;
920 if (*p)
921 *p++ = '\0';
922 if (lvl)
923 error(ERR_NONFATAL, "unterminated %[ construct");
924 type = TOK_INDIRECT;
925 } else if (*p == '?') {
926 type = TOK_PREPROC_Q; /* %? */
927 p++;
928 if (*p == '?') {
929 type = TOK_PREPROC_QQ; /* %?? */
930 p++;
931 }
H. Peter Anvin077fb932010-07-20 14:56:30 -0700932 } else if (*p == '!') {
933 type = TOK_PREPROC_ID;
934 p++;
935 if (isidchar(*p)) {
936 do {
937 p++;
938 }
939 while (isidchar(*p));
940 } else if (*p == '\'' || *p == '\"' || *p == '`') {
941 p = nasm_skip_string(p);
942 if (*p)
943 p++;
944 else
945 error(ERR_NONFATAL|ERR_PASS1, "unterminated %! string");
946 } else {
947 /* %! without string or identifier */
948 type = TOK_OTHER; /* Legacy behavior... */
949 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000950 } else if (isidchar(*p) ||
951 ((*p == '!' || *p == '%' || *p == '$') &&
952 isidchar(p[1]))) {
953 do {
954 p++;
955 }
956 while (isidchar(*p));
957 type = TOK_PREPROC_ID;
958 } else {
959 type = TOK_OTHER;
960 if (*p == '%')
961 p++;
962 }
963 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
964 type = TOK_ID;
965 p++;
966 while (*p && isidchar(*p))
967 p++;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700968 } else if (*p == '\'' || *p == '"' || *p == '`') {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000969 /*
970 * A string token.
971 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000972 type = TOK_STRING;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300973 p = nasm_skip_string(p);
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000974
H. Peter Anvine2c80182005-01-15 22:15:51 +0000975 if (*p) {
976 p++;
977 } else {
H. Peter Anvin917a3492008-09-24 09:14:49 -0700978 error(ERR_WARNING|ERR_PASS1, "unterminated string");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000979 /* Handling unterminated strings by UNV */
980 /* type = -1; */
981 }
Victor van den Elzenfb5f2512009-04-17 16:17:59 +0200982 } else if (p[0] == '$' && p[1] == '$') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300983 type = TOK_OTHER; /* TOKEN_BASE */
Victor van den Elzenfb5f2512009-04-17 16:17:59 +0200984 p += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000985 } else if (isnumstart(*p)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300986 bool is_hex = false;
987 bool is_float = false;
988 bool has_e = false;
989 char c, *r;
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700990
H. Peter Anvine2c80182005-01-15 22:15:51 +0000991 /*
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700992 * A numeric token.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000993 */
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700994
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300995 if (*p == '$') {
996 p++;
997 is_hex = true;
998 }
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700999
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001000 for (;;) {
1001 c = *p++;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001002
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001003 if (!is_hex && (c == 'e' || c == 'E')) {
1004 has_e = true;
1005 if (*p == '+' || *p == '-') {
1006 /*
1007 * e can only be followed by +/- if it is either a
1008 * prefixed hex number or a floating-point number
1009 */
1010 p++;
1011 is_float = true;
1012 }
1013 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
1014 is_hex = true;
1015 } else if (c == 'P' || c == 'p') {
1016 is_float = true;
1017 if (*p == '+' || *p == '-')
1018 p++;
1019 } else if (isnumchar(c) || c == '_')
1020 ; /* just advance */
1021 else if (c == '.') {
1022 /*
1023 * we need to deal with consequences of the legacy
1024 * parser, like "1.nolist" being two tokens
1025 * (TOK_NUMBER, TOK_ID) here; at least give it
1026 * a shot for now. In the future, we probably need
1027 * a flex-based scanner with proper pattern matching
1028 * to do it as well as it can be done. Nothing in
1029 * the world is going to help the person who wants
1030 * 0x123.p16 interpreted as two tokens, though.
1031 */
1032 r = p;
1033 while (*r == '_')
1034 r++;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001035
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001036 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
1037 (!is_hex && (*r == 'e' || *r == 'E')) ||
1038 (*r == 'p' || *r == 'P')) {
1039 p = r;
1040 is_float = true;
1041 } else
1042 break; /* Terminate the token */
1043 } else
1044 break;
1045 }
1046 p--; /* Point to first character beyond number */
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001047
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001048 if (p == line+1 && *line == '$') {
1049 type = TOK_OTHER; /* TOKEN_HERE */
1050 } else {
1051 if (has_e && !is_hex) {
1052 /* 1e13 is floating-point, but 1e13h is not */
1053 is_float = true;
1054 }
H. Peter Anvind784a082009-04-20 14:01:18 -07001055
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001056 type = is_float ? TOK_FLOAT : TOK_NUMBER;
1057 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001058 } else if (nasm_isspace(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001059 type = TOK_WHITESPACE;
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +04001060 p = nasm_skip_spaces(p);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001061 /*
1062 * Whitespace just before end-of-line is discarded by
1063 * pretending it's a comment; whitespace just before a
1064 * comment gets lumped into the comment.
1065 */
1066 if (!*p || *p == ';') {
1067 type = TOK_COMMENT;
1068 while (*p)
1069 p++;
1070 }
1071 } else if (*p == ';') {
1072 type = TOK_COMMENT;
1073 while (*p)
1074 p++;
1075 } else {
1076 /*
1077 * Anything else is an operator of some kind. We check
1078 * for all the double-character operators (>>, <<, //,
1079 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001080 * else is a single-character operator.
H. Peter Anvine2c80182005-01-15 22:15:51 +00001081 */
1082 type = TOK_OTHER;
1083 if ((p[0] == '>' && p[1] == '>') ||
1084 (p[0] == '<' && p[1] == '<') ||
1085 (p[0] == '/' && p[1] == '/') ||
1086 (p[0] == '<' && p[1] == '=') ||
1087 (p[0] == '>' && p[1] == '=') ||
1088 (p[0] == '=' && p[1] == '=') ||
1089 (p[0] == '!' && p[1] == '=') ||
1090 (p[0] == '<' && p[1] == '>') ||
1091 (p[0] == '&' && p[1] == '&') ||
1092 (p[0] == '|' && p[1] == '|') ||
1093 (p[0] == '^' && p[1] == '^')) {
1094 p++;
1095 }
1096 p++;
1097 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001098
H. Peter Anvine2c80182005-01-15 22:15:51 +00001099 /* Handling unterminated string by UNV */
1100 /*if (type == -1)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001101 {
1102 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1103 t->text[p-line] = *line;
1104 tail = &t->next;
1105 }
1106 else */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001107 if (type != TOK_COMMENT) {
1108 *tail = t = new_Token(NULL, type, line, p - line);
1109 tail = &t->next;
1110 }
1111 line = p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001112 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001113 return list;
1114}
1115
H. Peter Anvince616072002-04-30 21:02:23 +00001116/*
1117 * this function allocates a new managed block of memory and
H. Peter Anvin70653092007-10-19 14:42:29 -07001118 * returns a pointer to the block. The managed blocks are
H. Peter Anvince616072002-04-30 21:02:23 +00001119 * deleted only all at once by the delete_Blocks function.
1120 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001121static void *new_Block(size_t size)
H. Peter Anvince616072002-04-30 21:02:23 +00001122{
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001123 Blocks *b = &blocks;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001124
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001125 /* first, get to the end of the linked list */
1126 while (b->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001127 b = b->next;
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001128 /* now allocate the requested chunk */
1129 b->chunk = nasm_malloc(size);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001130
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001131 /* now allocate a new block for the next request */
1132 b->next = nasm_malloc(sizeof(Blocks));
1133 /* and initialize the contents of the new block */
1134 b->next->next = NULL;
1135 b->next->chunk = NULL;
1136 return b->chunk;
H. Peter Anvince616072002-04-30 21:02:23 +00001137}
1138
1139/*
1140 * this function deletes all managed blocks of memory
1141 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001142static void delete_Blocks(void)
H. Peter Anvince616072002-04-30 21:02:23 +00001143{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001144 Blocks *a, *b = &blocks;
H. Peter Anvince616072002-04-30 21:02:23 +00001145
H. Peter Anvin70653092007-10-19 14:42:29 -07001146 /*
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001147 * keep in mind that the first block, pointed to by blocks
H. Peter Anvin70653092007-10-19 14:42:29 -07001148 * is a static and not dynamically allocated, so we don't
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001149 * free it.
1150 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001151 while (b) {
1152 if (b->chunk)
1153 nasm_free(b->chunk);
1154 a = b;
1155 b = b->next;
1156 if (a != &blocks)
1157 nasm_free(a);
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001158 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001159}
H. Peter Anvin734b1882002-04-30 21:01:08 +00001160
1161/*
H. Peter Anvin70653092007-10-19 14:42:29 -07001162 * this function creates a new Token and passes a pointer to it
H. Peter Anvin734b1882002-04-30 21:01:08 +00001163 * back to the caller. It sets the type and text elements, and
H. Peter Anvinf26e0972008-07-01 21:26:27 -07001164 * also the a.mac and next elements to NULL.
H. Peter Anvin734b1882002-04-30 21:01:08 +00001165 */
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001166static Token *new_Token(Token * next, enum pp_token_type type,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001167 const char *text, int txtlen)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001168{
1169 Token *t;
1170 int i;
1171
H. Peter Anvin89cee572009-07-15 09:16:54 -04001172 if (!freeTokens) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001173 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
1174 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
1175 freeTokens[i].next = &freeTokens[i + 1];
1176 freeTokens[i].next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001177 }
1178 t = freeTokens;
1179 freeTokens = t->next;
1180 t->next = next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07001181 t->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001182 t->type = type;
H. Peter Anvin89cee572009-07-15 09:16:54 -04001183 if (type == TOK_WHITESPACE || !text) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001184 t->text = NULL;
1185 } else {
1186 if (txtlen == 0)
1187 txtlen = strlen(text);
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001188 t->text = nasm_malloc(txtlen+1);
1189 memcpy(t->text, text, txtlen);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001190 t->text[txtlen] = '\0';
H. Peter Anvin734b1882002-04-30 21:01:08 +00001191 }
1192 return t;
1193}
1194
H. Peter Anvine2c80182005-01-15 22:15:51 +00001195static Token *delete_Token(Token * t)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001196{
1197 Token *next = t->next;
1198 nasm_free(t->text);
H. Peter Anvin788e6c12002-04-30 21:02:01 +00001199 t->next = freeTokens;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001200 freeTokens = t;
1201 return next;
1202}
1203
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001204/*
1205 * Convert a line of tokens back into text.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001206 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1207 * will be transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001208 */
H. Peter Anvin9e200162008-06-04 17:23:14 -07001209static char *detoken(Token * tlist, bool expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001210{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001211 Token *t;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001212 char *line, *p;
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001213 const char *q;
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001214 int len = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001215
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001216 list_for_each(t, tlist) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001217 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
H. Peter Anvin077fb932010-07-20 14:56:30 -07001218 char *v;
1219 char *q = t->text;
1220
1221 v = t->text + 2;
1222 if (*v == '\'' || *v == '\"' || *v == '`') {
1223 size_t len = nasm_unquote(v, NULL);
1224 size_t clen = strlen(v);
1225
1226 if (len != clen) {
1227 error(ERR_NONFATAL | ERR_PASS1,
1228 "NUL character in %! string");
1229 v = NULL;
1230 }
H. Peter Anvin5b00bf42010-07-13 11:43:06 -07001231 }
H. Peter Anvin077fb932010-07-20 14:56:30 -07001232
1233 if (v) {
1234 char *p = getenv(v);
1235 if (!p) {
1236 error(ERR_NONFATAL | ERR_PASS1,
1237 "nonexistent environment variable `%s'", v);
1238 p = "";
1239 }
1240 t->text = nasm_strdup(p);
1241 }
1242 nasm_free(q);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001243 }
H. Peter Anvin077fb932010-07-20 14:56:30 -07001244
H. Peter Anvine2c80182005-01-15 22:15:51 +00001245 /* Expand local macros here and not during preprocessing */
1246 if (expand_locals &&
1247 t->type == TOK_PREPROC_ID && t->text &&
1248 t->text[0] == '%' && t->text[1] == '$') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001249 const char *q;
1250 char *p;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001251 Context *ctx = get_ctx(t->text, &q, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001252 if (ctx) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001253 char buffer[40];
Keith Kanios93f2e9a2007-04-14 00:10:59 +00001254 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001255 p = nasm_strcat(buffer, q);
1256 nasm_free(t->text);
1257 t->text = p;
1258 }
1259 }
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001260 if (t->type == TOK_WHITESPACE)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001261 len++;
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001262 else if (t->text)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001263 len += strlen(t->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001264 }
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001265
H. Peter Anvin734b1882002-04-30 21:01:08 +00001266 p = line = nasm_malloc(len + 1);
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001267
1268 list_for_each(t, tlist) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001269 if (t->type == TOK_WHITESPACE) {
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001270 *p++ = ' ';
H. Peter Anvine2c80182005-01-15 22:15:51 +00001271 } else if (t->text) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001272 q = t->text;
1273 while (*q)
1274 *p++ = *q++;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001275 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001276 }
1277 *p = '\0';
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001278
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001279 return line;
1280}
1281
1282/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001283 * A scanner, suitable for use by the expression evaluator, which
1284 * operates on a line of Tokens. Expects a pointer to a pointer to
1285 * the first token in the line to be passed in as its private_data
1286 * field.
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001287 *
1288 * FIX: This really needs to be unified with stdscan.
H. Peter Anvin76690a12002-04-30 20:52:49 +00001289 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001290static int ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001291{
H. Peter Anvin76690a12002-04-30 20:52:49 +00001292 Token **tlineptr = private_data;
1293 Token *tline;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001294 char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001295
H. Peter Anvine2c80182005-01-15 22:15:51 +00001296 do {
1297 tline = *tlineptr;
1298 *tlineptr = tline ? tline->next : NULL;
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04001299 } while (tline && (tline->type == TOK_WHITESPACE ||
1300 tline->type == TOK_COMMENT));
H. Peter Anvin76690a12002-04-30 20:52:49 +00001301
1302 if (!tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001303 return tokval->t_type = TOKEN_EOS;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001304
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001305 tokval->t_charptr = tline->text;
1306
H. Peter Anvin76690a12002-04-30 20:52:49 +00001307 if (tline->text[0] == '$' && !tline->text[1])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001308 return tokval->t_type = TOKEN_HERE;
H. Peter Anvin7cf897e2002-05-30 21:30:33 +00001309 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001310 return tokval->t_type = TOKEN_BASE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001311
H. Peter Anvine2c80182005-01-15 22:15:51 +00001312 if (tline->type == TOK_ID) {
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001313 p = tokval->t_charptr = tline->text;
1314 if (p[0] == '$') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001315 tokval->t_charptr++;
1316 return tokval->t_type = TOKEN_ID;
1317 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001318
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001319 for (r = p, s = ourcopy; *r; r++) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001320 if (r >= p+MAX_KEYWORD)
1321 return tokval->t_type = TOKEN_ID; /* Not a keyword */
H. Peter Anvinac8f8fc2008-06-11 15:49:41 -07001322 *s++ = nasm_tolower(*r);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001323 }
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001324 *s = '\0';
1325 /* right, so we have an identifier sitting in temp storage. now,
1326 * is it actually a register or instruction name, or what? */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001327 return nasm_token_hash(ourcopy, tokval);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001328 }
1329
H. Peter Anvine2c80182005-01-15 22:15:51 +00001330 if (tline->type == TOK_NUMBER) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001331 bool rn_error;
1332 tokval->t_integer = readnum(tline->text, &rn_error);
1333 tokval->t_charptr = tline->text;
1334 if (rn_error)
1335 return tokval->t_type = TOKEN_ERRNUM;
1336 else
1337 return tokval->t_type = TOKEN_NUM;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001338 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001339
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001340 if (tline->type == TOK_FLOAT) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001341 return tokval->t_type = TOKEN_FLOAT;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001342 }
1343
H. Peter Anvine2c80182005-01-15 22:15:51 +00001344 if (tline->type == TOK_STRING) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001345 char bq, *ep;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001346
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001347 bq = tline->text[0];
H. Peter Anvin11627042008-06-09 20:45:19 -07001348 tokval->t_charptr = tline->text;
1349 tokval->t_inttwo = nasm_unquote(tline->text, &ep);
H. Peter Anvind2456592008-06-19 15:04:18 -07001350
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001351 if (ep[0] != bq || ep[1] != '\0')
1352 return tokval->t_type = TOKEN_ERRSTR;
1353 else
1354 return tokval->t_type = TOKEN_STR;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001355 }
1356
H. Peter Anvine2c80182005-01-15 22:15:51 +00001357 if (tline->type == TOK_OTHER) {
1358 if (!strcmp(tline->text, "<<"))
1359 return tokval->t_type = TOKEN_SHL;
1360 if (!strcmp(tline->text, ">>"))
1361 return tokval->t_type = TOKEN_SHR;
1362 if (!strcmp(tline->text, "//"))
1363 return tokval->t_type = TOKEN_SDIV;
1364 if (!strcmp(tline->text, "%%"))
1365 return tokval->t_type = TOKEN_SMOD;
1366 if (!strcmp(tline->text, "=="))
1367 return tokval->t_type = TOKEN_EQ;
1368 if (!strcmp(tline->text, "<>"))
1369 return tokval->t_type = TOKEN_NE;
1370 if (!strcmp(tline->text, "!="))
1371 return tokval->t_type = TOKEN_NE;
1372 if (!strcmp(tline->text, "<="))
1373 return tokval->t_type = TOKEN_LE;
1374 if (!strcmp(tline->text, ">="))
1375 return tokval->t_type = TOKEN_GE;
1376 if (!strcmp(tline->text, "&&"))
1377 return tokval->t_type = TOKEN_DBL_AND;
1378 if (!strcmp(tline->text, "^^"))
1379 return tokval->t_type = TOKEN_DBL_XOR;
1380 if (!strcmp(tline->text, "||"))
1381 return tokval->t_type = TOKEN_DBL_OR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001382 }
1383
1384 /*
1385 * We have no other options: just return the first character of
1386 * the token text.
1387 */
1388 return tokval->t_type = tline->text[0];
1389}
1390
1391/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001392 * Compare a string to the name of an existing macro; this is a
1393 * simple wrapper which calls either strcmp or nasm_stricmp
1394 * depending on the value of the `casesense' parameter.
1395 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001396static int mstrcmp(const char *p, const char *q, bool casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001397{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001398 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001399}
1400
1401/*
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001402 * Compare a string to the name of an existing macro; this is a
1403 * simple wrapper which calls either strcmp or nasm_stricmp
1404 * depending on the value of the `casesense' parameter.
1405 */
1406static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
1407{
1408 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
1409}
1410
1411/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001412 * Return the Context structure associated with a %$ token. Return
1413 * NULL, having _already_ reported an error condition, if the
1414 * context stack isn't deep enough for the supplied number of $
1415 * signs.
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001416 * If all_contexts == true, contexts that enclose current are
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001417 * also scanned for such smacro, until it is found; if not -
1418 * only the context that directly results from the number of $'s
1419 * in variable's name.
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001420 *
1421 * If "namep" is non-NULL, set it to the pointer to the macro name
1422 * tail, i.e. the part beyond %$...
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001423 */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001424static Context *get_ctx(const char *name, const char **namep,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001425 bool all_contexts)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001426{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001427 Context *ctx;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001428 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001429 int i;
1430
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001431 if (namep)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001432 *namep = name;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001433
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001434 if (!name || name[0] != '%' || name[1] != '$')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001435 return NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001436
H. Peter Anvine2c80182005-01-15 22:15:51 +00001437 if (!cstk) {
1438 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1439 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001440 }
1441
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001442 name += 2;
1443 ctx = cstk;
1444 i = 0;
1445 while (ctx && *name == '$') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001446 name++;
1447 i++;
1448 ctx = ctx->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001449 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001450 if (!ctx) {
1451 error(ERR_NONFATAL, "`%s': context stack is only"
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001452 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001453 return NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001454 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001455
1456 if (namep)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001457 *namep = name;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001458
Keith Kaniosfe55e912010-08-09 00:55:44 -05001459 if (!all_contexts) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001460 return ctx;
Keith Kaniosfe55e912010-08-09 00:55:44 -05001461 } else {
1462 error(ERR_WARNING, "context-local label expansion"
1463 " to outer contexts will be deprecated"
1464 " starting in NASM 2.10, please update your"
1465 " code accordingly");
1466 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001467
H. Peter Anvine2c80182005-01-15 22:15:51 +00001468 do {
1469 /* Search for this smacro in found context */
H. Peter Anvin166c2472008-05-28 12:28:58 -07001470 m = hash_findix(&ctx->localmac, name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001471 while (m) {
1472 if (!mstrcmp(m->name, name, m->casesense))
1473 return ctx;
1474 m = m->next;
1475 }
1476 ctx = ctx->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001477 }
1478 while (ctx);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001479 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001480}
1481
1482/*
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001483 * Check to see if a file is already in a string list
1484 */
1485static bool in_list(const StrList *list, const char *str)
1486{
1487 while (list) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001488 if (!strcmp(list->str, str))
1489 return true;
1490 list = list->next;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001491 }
1492 return false;
1493}
1494
1495/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001496 * Open an include file. This routine must always return a valid
1497 * file pointer if it returns - it's responsible for throwing an
1498 * ERR_FATAL and bombing out completely if not. It should also try
1499 * the include path one by one until it finds the file or reaches
1500 * the end of the path.
1501 */
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07001502static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001503 bool missing_ok)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001504{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001505 FILE *fp;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001506 char *prefix = "";
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001507 IncPath *ip = ipath;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001508 int len = strlen(file);
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001509 size_t prefix_len = 0;
1510 StrList *sl;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001511
H. Peter Anvine2c80182005-01-15 22:15:51 +00001512 while (1) {
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001513 sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001514 memcpy(sl->str, prefix, prefix_len);
1515 memcpy(sl->str+prefix_len, file, len+1);
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001516 fp = fopen(sl->str, "r");
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001517 if (fp && dhead && !in_list(*dhead, sl->str)) {
1518 sl->next = NULL;
1519 **dtail = sl;
1520 *dtail = &sl->next;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001521 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001522 nasm_free(sl);
1523 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001524 if (fp)
1525 return fp;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001526 if (!ip) {
1527 if (!missing_ok)
1528 break;
1529 prefix = NULL;
1530 } else {
1531 prefix = ip->path;
1532 ip = ip->next;
1533 }
1534 if (prefix) {
1535 prefix_len = strlen(prefix);
1536 } else {
1537 /* -MG given and file not found */
1538 if (dhead && !in_list(*dhead, file)) {
1539 sl = nasm_malloc(len+1+sizeof sl->next);
1540 sl->next = NULL;
1541 strcpy(sl->str, file);
1542 **dtail = sl;
1543 *dtail = &sl->next;
1544 }
1545 return NULL;
1546 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001547 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001548
H. Peter Anvin734b1882002-04-30 21:01:08 +00001549 error(ERR_FATAL, "unable to open include file `%s'", file);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001550 return NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001551}
1552
1553/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001554 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001555 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001556 * return true if _any_ single-line macro of that name is defined.
1557 * Otherwise, will return true if a single-line macro with either
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001558 * `nparam' or no parameters is defined.
1559 *
1560 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001561 * defined, or nparam is -1, the address of the definition structure
1562 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001563 * is NULL, no action will be taken regarding its contents, and no
1564 * error will occur.
1565 *
1566 * Note that this is also called with nparam zero to resolve
1567 * `ifdef'.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001568 *
1569 * If you already know which context macro belongs to, you can pass
1570 * the context pointer as first parameter; if you won't but name begins
1571 * with %$ the context will be automatically computed. If all_contexts
1572 * is true, macro will be searched in outer contexts as well.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001573 */
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001574static bool
H. Peter Anvinb2a5fda2008-06-19 21:42:42 -07001575smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001576 bool nocase)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001577{
H. Peter Anvin166c2472008-05-28 12:28:58 -07001578 struct hash_table *smtbl;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001579 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001580
H. Peter Anvin97a23472007-09-16 17:57:25 -07001581 if (ctx) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001582 smtbl = &ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001583 } else if (name[0] == '%' && name[1] == '$') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001584 if (cstk)
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001585 ctx = get_ctx(name, &name, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001586 if (!ctx)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001587 return false; /* got to return _something_ */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001588 smtbl = &ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001589 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001590 smtbl = &smacros;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001591 }
H. Peter Anvin166c2472008-05-28 12:28:58 -07001592 m = (SMacro *) hash_findix(smtbl, name);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001593
H. Peter Anvine2c80182005-01-15 22:15:51 +00001594 while (m) {
1595 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
Charles Crayne192d5b52007-10-18 19:02:42 -07001596 (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001597 if (defn) {
Charles Crayne192d5b52007-10-18 19:02:42 -07001598 if (nparam == (int) m->nparam || nparam == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001599 *defn = m;
1600 else
1601 *defn = NULL;
1602 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001603 return true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001604 }
1605 m = m->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001606 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001607
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001608 return false;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001609}
1610
1611/*
1612 * Count and mark off the parameters in a multi-line macro call.
1613 * This is called both from within the multi-line macro expansion
1614 * code, and also to mark off the default parameters when provided
1615 * in a %macro definition line.
1616 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001617static void count_mmac_params(Token * t, int *nparam, Token *** params)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001618{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001619 int paramsize, brace;
1620
1621 *nparam = paramsize = 0;
1622 *params = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001623 while (t) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001624 /* +1: we need space for the final NULL */
H. Peter Anvin91fb6f12008-09-01 10:56:33 -07001625 if (*nparam+1 >= paramsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001626 paramsize += PARAM_DELTA;
1627 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1628 }
1629 skip_white_(t);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001630 brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001631 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001632 brace = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001633 (*params)[(*nparam)++] = t;
1634 while (tok_isnt_(t, brace ? "}" : ","))
1635 t = t->next;
1636 if (t) { /* got a comma/brace */
1637 t = t->next;
1638 if (brace) {
1639 /*
1640 * Now we've found the closing brace, look further
1641 * for the comma.
1642 */
1643 skip_white_(t);
1644 if (tok_isnt_(t, ",")) {
1645 error(ERR_NONFATAL,
1646 "braces do not enclose all of macro parameter");
1647 while (tok_isnt_(t, ","))
1648 t = t->next;
1649 }
1650 if (t)
1651 t = t->next; /* eat the comma */
1652 }
1653 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001654 }
1655}
1656
1657/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001658 * Determine whether one of the various `if' conditions is true or
1659 * not.
1660 *
1661 * We must free the tline we get passed.
1662 */
H. Peter Anvin70055962007-10-11 00:05:31 -07001663static bool if_condition(Token * tline, enum preproc_token ct)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001664{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001665 enum pp_conditional i = PP_COND(ct);
H. Peter Anvin70055962007-10-11 00:05:31 -07001666 bool j;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001667 Token *t, *tt, **tptr, *origline;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001668 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001669 expr *evalresult;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001670 enum pp_token_type needtype;
H. Peter Anvin077fb932010-07-20 14:56:30 -07001671 char *p;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001672
1673 origline = tline;
1674
H. Peter Anvine2c80182005-01-15 22:15:51 +00001675 switch (i) {
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001676 case PPC_IFCTX:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001677 j = false; /* have we matched yet? */
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001678 while (true) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001679 skip_white_(tline);
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001680 if (!tline)
1681 break;
1682 if (tline->type != TOK_ID) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001683 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001684 "`%s' expects context identifiers", pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001685 free_tlist(origline);
1686 return -1;
1687 }
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001688 if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001689 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001690 tline = tline->next;
1691 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001692 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001693
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001694 case PPC_IFDEF:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001695 j = false; /* have we matched yet? */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001696 while (tline) {
1697 skip_white_(tline);
1698 if (!tline || (tline->type != TOK_ID &&
1699 (tline->type != TOK_PREPROC_ID ||
1700 tline->text[1] != '$'))) {
1701 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001702 "`%s' expects macro identifiers", pp_directives[ct]);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001703 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001704 }
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001705 if (smacro_defined(NULL, tline->text, 0, NULL, true))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001706 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001707 tline = tline->next;
1708 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001709 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001710
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07001711 case PPC_IFENV:
1712 tline = expand_smacro(tline);
1713 j = false; /* have we matched yet? */
1714 while (tline) {
1715 skip_white_(tline);
1716 if (!tline || (tline->type != TOK_ID &&
H. Peter Anvin077fb932010-07-20 14:56:30 -07001717 tline->type != TOK_STRING &&
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07001718 (tline->type != TOK_PREPROC_ID ||
H. Peter Anvin077fb932010-07-20 14:56:30 -07001719 tline->text[1] != '!'))) {
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07001720 error(ERR_NONFATAL,
1721 "`%s' expects environment variable names",
1722 pp_directives[ct]);
1723 goto fail;
1724 }
H. Peter Anvin077fb932010-07-20 14:56:30 -07001725 p = tline->text;
1726 if (tline->type == TOK_PREPROC_ID)
1727 p += 2; /* Skip leading %! */
1728 if (*p == '\'' || *p == '\"' || *p == '`')
1729 nasm_unquote_cstr(p, ct);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07001730 if (getenv(p))
1731 j = true;
1732 tline = tline->next;
1733 }
1734 break;
1735
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001736 case PPC_IFIDN:
1737 case PPC_IFIDNI:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001738 tline = expand_smacro(tline);
1739 t = tt = tline;
1740 while (tok_isnt_(tt, ","))
1741 tt = tt->next;
1742 if (!tt) {
1743 error(ERR_NONFATAL,
1744 "`%s' expects two comma-separated arguments",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001745 pp_directives[ct]);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001746 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001747 }
1748 tt = tt->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001749 j = true; /* assume equality unless proved not */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001750 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1751 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1752 error(ERR_NONFATAL, "`%s': more than one comma on line",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001753 pp_directives[ct]);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001754 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001755 }
1756 if (t->type == TOK_WHITESPACE) {
1757 t = t->next;
1758 continue;
1759 }
1760 if (tt->type == TOK_WHITESPACE) {
1761 tt = tt->next;
1762 continue;
1763 }
1764 if (tt->type != t->type) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001765 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001766 break;
1767 }
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001768 /* When comparing strings, need to unquote them first */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001769 if (t->type == TOK_STRING) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001770 size_t l1 = nasm_unquote(t->text, NULL);
1771 size_t l2 = nasm_unquote(tt->text, NULL);
H. Peter Anvind2456592008-06-19 15:04:18 -07001772
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001773 if (l1 != l2) {
1774 j = false;
1775 break;
1776 }
1777 if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
1778 j = false;
1779 break;
1780 }
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001781 } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001782 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001783 break;
1784 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001785
H. Peter Anvine2c80182005-01-15 22:15:51 +00001786 t = t->next;
1787 tt = tt->next;
1788 }
1789 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001790 j = false; /* trailing gunk on one end or other */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001791 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001792
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001793 case PPC_IFMACRO:
H. Peter Anvin89cee572009-07-15 09:16:54 -04001794 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001795 bool found = false;
1796 MMacro searching, *mmac;
H. Peter Anvin65747262002-05-07 00:10:05 +00001797
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001798 skip_white_(tline);
1799 tline = expand_id(tline);
1800 if (!tok_type_(tline, TOK_ID)) {
1801 error(ERR_NONFATAL,
1802 "`%s' expects a macro name", pp_directives[ct]);
1803 goto fail;
1804 }
1805 searching.name = nasm_strdup(tline->text);
1806 searching.casesense = true;
1807 searching.plus = false;
1808 searching.nolist = false;
1809 searching.in_progress = 0;
1810 searching.max_depth = 0;
1811 searching.rep_nest = NULL;
1812 searching.nparam_min = 0;
1813 searching.nparam_max = INT_MAX;
1814 tline = expand_smacro(tline->next);
1815 skip_white_(tline);
1816 if (!tline) {
1817 } else if (!tok_type_(tline, TOK_NUMBER)) {
1818 error(ERR_NONFATAL,
1819 "`%s' expects a parameter count or nothing",
1820 pp_directives[ct]);
1821 } else {
1822 searching.nparam_min = searching.nparam_max =
1823 readnum(tline->text, &j);
1824 if (j)
1825 error(ERR_NONFATAL,
1826 "unable to parse parameter count `%s'",
1827 tline->text);
1828 }
1829 if (tline && tok_is_(tline->next, "-")) {
1830 tline = tline->next->next;
1831 if (tok_is_(tline, "*"))
1832 searching.nparam_max = INT_MAX;
1833 else if (!tok_type_(tline, TOK_NUMBER))
1834 error(ERR_NONFATAL,
1835 "`%s' expects a parameter count after `-'",
1836 pp_directives[ct]);
1837 else {
1838 searching.nparam_max = readnum(tline->text, &j);
1839 if (j)
1840 error(ERR_NONFATAL,
1841 "unable to parse parameter count `%s'",
1842 tline->text);
1843 if (searching.nparam_min > searching.nparam_max)
1844 error(ERR_NONFATAL,
1845 "minimum parameter count exceeds maximum");
1846 }
1847 }
1848 if (tline && tok_is_(tline->next, "+")) {
1849 tline = tline->next;
1850 searching.plus = true;
1851 }
1852 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
1853 while (mmac) {
1854 if (!strcmp(mmac->name, searching.name) &&
1855 (mmac->nparam_min <= searching.nparam_max
1856 || searching.plus)
1857 && (searching.nparam_min <= mmac->nparam_max
1858 || mmac->plus)) {
1859 found = true;
1860 break;
1861 }
1862 mmac = mmac->next;
1863 }
1864 if (tline && tline->next)
1865 error(ERR_WARNING|ERR_PASS1,
1866 "trailing garbage after %%ifmacro ignored");
1867 nasm_free(searching.name);
1868 j = found;
1869 break;
H. Peter Anvin89cee572009-07-15 09:16:54 -04001870 }
H. Peter Anvin65747262002-05-07 00:10:05 +00001871
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001872 case PPC_IFID:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001873 needtype = TOK_ID;
1874 goto iftype;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001875 case PPC_IFNUM:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001876 needtype = TOK_NUMBER;
1877 goto iftype;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001878 case PPC_IFSTR:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001879 needtype = TOK_STRING;
1880 goto iftype;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001881
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001882iftype:
1883 t = tline = expand_smacro(tline);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001884
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001885 while (tok_type_(t, TOK_WHITESPACE) ||
1886 (needtype == TOK_NUMBER &&
1887 tok_type_(t, TOK_OTHER) &&
1888 (t->text[0] == '-' || t->text[0] == '+') &&
1889 !t->text[1]))
1890 t = t->next;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001891
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001892 j = tok_type_(t, needtype);
1893 break;
H. Peter Anvincbf768d2008-02-16 16:41:25 -08001894
1895 case PPC_IFTOKEN:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001896 t = tline = expand_smacro(tline);
1897 while (tok_type_(t, TOK_WHITESPACE))
1898 t = t->next;
H. Peter Anvincbf768d2008-02-16 16:41:25 -08001899
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001900 j = false;
1901 if (t) {
1902 t = t->next; /* Skip the actual token */
1903 while (tok_type_(t, TOK_WHITESPACE))
1904 t = t->next;
1905 j = !t; /* Should be nothing left */
1906 }
1907 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001908
H. Peter Anvin134b9462008-02-16 17:01:40 -08001909 case PPC_IFEMPTY:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001910 t = tline = expand_smacro(tline);
1911 while (tok_type_(t, TOK_WHITESPACE))
1912 t = t->next;
H. Peter Anvin134b9462008-02-16 17:01:40 -08001913
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001914 j = !t; /* Should be empty */
1915 break;
H. Peter Anvin134b9462008-02-16 17:01:40 -08001916
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001917 case PPC_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001918 t = tline = expand_smacro(tline);
1919 tptr = &t;
1920 tokval.t_type = TOKEN_INVALID;
1921 evalresult = evaluate(ppscan, tptr, &tokval,
1922 NULL, pass | CRITICAL, error, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001923 if (!evalresult)
1924 return -1;
1925 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07001926 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001927 "trailing garbage after expression ignored");
1928 if (!is_simple(evalresult)) {
1929 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001930 "non-constant value given to `%s'", pp_directives[ct]);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001931 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001932 }
Chuck Crayne60ae75d2007-05-02 01:59:16 +00001933 j = reloc_value(evalresult) != 0;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001934 break;
H. Peter Anvin95e28822007-09-12 04:20:08 +00001935
H. Peter Anvine2c80182005-01-15 22:15:51 +00001936 default:
1937 error(ERR_FATAL,
1938 "preprocessor directive `%s' not yet implemented",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001939 pp_directives[ct]);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001940 goto fail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001941 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001942
1943 free_tlist(origline);
1944 return j ^ PP_NEGATIVE(ct);
H. Peter Anvin70653092007-10-19 14:42:29 -07001945
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001946fail:
1947 free_tlist(origline);
1948 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001949}
1950
1951/*
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001952 * Common code for defining an smacro
1953 */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001954static bool define_smacro(Context *ctx, const char *mname, bool casesense,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001955 int nparam, Token *expansion)
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001956{
1957 SMacro *smac, **smhead;
H. Peter Anvin166c2472008-05-28 12:28:58 -07001958 struct hash_table *smtbl;
H. Peter Anvin70653092007-10-19 14:42:29 -07001959
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001960 if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001961 if (!smac) {
1962 error(ERR_WARNING|ERR_PASS1,
1963 "single-line macro `%s' defined both with and"
1964 " without parameters", mname);
1965 /*
1966 * Some instances of the old code considered this a failure,
1967 * some others didn't. What is the right thing to do here?
1968 */
1969 free_tlist(expansion);
1970 return false; /* Failure */
1971 } else {
1972 /*
1973 * We're redefining, so we have to take over an
1974 * existing SMacro structure. This means freeing
1975 * what was already in it.
1976 */
1977 nasm_free(smac->name);
1978 free_tlist(smac->expansion);
1979 }
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001980 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001981 smtbl = ctx ? &ctx->localmac : &smacros;
1982 smhead = (SMacro **) hash_findi_add(smtbl, mname);
1983 smac = nasm_malloc(sizeof(SMacro));
1984 smac->next = *smhead;
1985 *smhead = smac;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001986 }
1987 smac->name = nasm_strdup(mname);
1988 smac->casesense = casesense;
1989 smac->nparam = nparam;
1990 smac->expansion = expansion;
1991 smac->in_progress = false;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001992 return true; /* Success */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001993}
1994
1995/*
1996 * Undefine an smacro
1997 */
1998static void undef_smacro(Context *ctx, const char *mname)
1999{
2000 SMacro **smhead, *s, **sp;
H. Peter Anvin166c2472008-05-28 12:28:58 -07002001 struct hash_table *smtbl;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002002
H. Peter Anvin166c2472008-05-28 12:28:58 -07002003 smtbl = ctx ? &ctx->localmac : &smacros;
2004 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
H. Peter Anvin70653092007-10-19 14:42:29 -07002005
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002006 if (smhead) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002007 /*
2008 * We now have a macro name... go hunt for it.
2009 */
2010 sp = smhead;
2011 while ((s = *sp) != NULL) {
2012 if (!mstrcmp(s->name, mname, s->casesense)) {
2013 *sp = s->next;
2014 nasm_free(s->name);
2015 free_tlist(s->expansion);
2016 nasm_free(s);
2017 } else {
2018 sp = &s->next;
2019 }
2020 }
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002021 }
2022}
2023
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002024/*
H. Peter Anvina26433d2008-07-16 14:40:01 -07002025 * Parse a mmacro specification.
2026 */
2027static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
2028{
2029 bool err;
2030
2031 tline = tline->next;
2032 skip_white_(tline);
2033 tline = expand_id(tline);
2034 if (!tok_type_(tline, TOK_ID)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002035 error(ERR_NONFATAL, "`%s' expects a macro name", directive);
2036 return false;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002037 }
Victor van den Elzenb916ede2008-07-23 15:14:22 +02002038
H. Peter Anvin89cee572009-07-15 09:16:54 -04002039 def->prev = NULL;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002040 def->name = nasm_strdup(tline->text);
2041 def->plus = false;
2042 def->nolist = false;
2043 def->in_progress = 0;
2044 def->rep_nest = NULL;
Victor van den Elzenb916ede2008-07-23 15:14:22 +02002045 def->nparam_min = 0;
2046 def->nparam_max = 0;
2047
H. Peter Anvina26433d2008-07-16 14:40:01 -07002048 tline = expand_smacro(tline->next);
2049 skip_white_(tline);
2050 if (!tok_type_(tline, TOK_NUMBER)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002051 error(ERR_NONFATAL, "`%s' expects a parameter count", directive);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002052 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002053 def->nparam_min = def->nparam_max =
2054 readnum(tline->text, &err);
2055 if (err)
2056 error(ERR_NONFATAL,
2057 "unable to parse parameter count `%s'", tline->text);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002058 }
2059 if (tline && tok_is_(tline->next, "-")) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002060 tline = tline->next->next;
2061 if (tok_is_(tline, "*")) {
2062 def->nparam_max = INT_MAX;
2063 } else if (!tok_type_(tline, TOK_NUMBER)) {
2064 error(ERR_NONFATAL,
2065 "`%s' expects a parameter count after `-'", directive);
2066 } else {
2067 def->nparam_max = readnum(tline->text, &err);
2068 if (err) {
2069 error(ERR_NONFATAL, "unable to parse parameter count `%s'",
2070 tline->text);
2071 }
2072 if (def->nparam_min > def->nparam_max) {
2073 error(ERR_NONFATAL, "minimum parameter count exceeds maximum");
2074 }
2075 }
H. Peter Anvina26433d2008-07-16 14:40:01 -07002076 }
2077 if (tline && tok_is_(tline->next, "+")) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002078 tline = tline->next;
2079 def->plus = true;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002080 }
2081 if (tline && tok_type_(tline->next, TOK_ID) &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002082 !nasm_stricmp(tline->next->text, ".nolist")) {
2083 tline = tline->next;
2084 def->nolist = true;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002085 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002086
H. Peter Anvina26433d2008-07-16 14:40:01 -07002087 /*
2088 * Handle default parameters.
2089 */
2090 if (tline && tline->next) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002091 def->dlist = tline->next;
2092 tline->next = NULL;
2093 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002094 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002095 def->dlist = NULL;
2096 def->defaults = NULL;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002097 }
2098 def->expansion = NULL;
2099
H. Peter Anvin89cee572009-07-15 09:16:54 -04002100 if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002101 !def->plus)
2102 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MDP,
2103 "too many default macro parameters");
Victor van den Elzenb916ede2008-07-23 15:14:22 +02002104
H. Peter Anvina26433d2008-07-16 14:40:01 -07002105 return true;
2106}
2107
2108
2109/*
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002110 * Decode a size directive
2111 */
2112static int parse_size(const char *str) {
2113 static const char *size_names[] =
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002114 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002115 static const int sizes[] =
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002116 { 0, 1, 4, 16, 8, 10, 2, 32 };
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002117
Cyrill Gorcunova7319242010-06-03 22:04:36 +04002118 return sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1];
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002119}
2120
Ed Beroset3ab3f412002-06-11 03:31:49 +00002121/**
2122 * find and process preprocessor directive in passed line
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002123 * Find out if a line contains a preprocessor directive, and deal
2124 * with it if so.
H. Peter Anvin70653092007-10-19 14:42:29 -07002125 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00002126 * If a directive _is_ found, it is the responsibility of this routine
2127 * (and not the caller) to free_tlist() the line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002128 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00002129 * @param tline a pointer to the current tokeninzed line linked list
2130 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
H. Peter Anvin70653092007-10-19 14:42:29 -07002131 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002132 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002133static int do_directive(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002134{
H. Peter Anvin4169a472007-09-12 01:29:43 +00002135 enum preproc_token i;
2136 int j;
H. Peter Anvin70055962007-10-11 00:05:31 -07002137 bool err;
2138 int nparam;
2139 bool nolist;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002140 bool casesense;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -07002141 int k, m;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002142 int offset;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002143 char *p, *pp;
2144 const char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002145 Include *inc;
2146 Context *ctx;
2147 Cond *cond;
H. Peter Anvin97a23472007-09-16 17:57:25 -07002148 MMacro *mmac, **mmhead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002149 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
2150 Line *l;
2151 struct tokenval tokval;
2152 expr *evalresult;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002153 MMacro *tmp_defining; /* Used when manipulating rep_nest */
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002154 int64_t count;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07002155 size_t len;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002156 int severity;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002157
2158 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002159
H. Peter Anvineba20a72002-04-30 20:53:55 +00002160 skip_white_(tline);
H. Peter Anvinf2936d72008-06-04 15:11:23 -07002161 if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00002162 (tline->text[1] == '%' || tline->text[1] == '$'
2163 || tline->text[1] == '!'))
2164 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002165
H. Peter Anvin4169a472007-09-12 01:29:43 +00002166 i = pp_token_hash(tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002167
2168 /*
Cyrill Gorcunovf09116f2010-02-28 11:52:53 +03002169 * FIXME: We zap execution of PP_RMACRO, PP_IRMACRO, PP_EXITMACRO
2170 * since they are known to be buggy at moment, we need to fix them
2171 * in future release (2.09-2.10)
2172 */
2173 if (i == PP_RMACRO || i == PP_RMACRO || i == PP_EXITMACRO) {
2174 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2175 tline->text);
2176 return NO_DIRECTIVE_FOUND;
2177 }
2178
2179 /*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002180 * If we're in a non-emitting branch of a condition construct,
H. Peter Anvin76690a12002-04-30 20:52:49 +00002181 * or walking to the end of an already terminated %rep block,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002182 * we should ignore all directives except for condition
2183 * directives.
2184 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00002185 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00002186 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
2187 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002188 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002189
2190 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002191 * If we're defining a macro or reading a %rep block, we should
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02002192 * ignore all directives except for %macro/%imacro (which nest),
2193 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2194 * If we're in a %rep block, another %rep nests, so should be let through.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002195 */
2196 if (defining && i != PP_MACRO && i != PP_IMACRO &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002197 i != PP_RMACRO && i != PP_IRMACRO &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00002198 i != PP_ENDMACRO && i != PP_ENDM &&
2199 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
2200 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002201 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002202
Charles Crayned4200be2008-07-12 16:42:33 -07002203 if (defining) {
Keith Kanios852f1ee2009-07-12 00:19:55 -05002204 if (i == PP_MACRO || i == PP_IMACRO ||
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002205 i == PP_RMACRO || i == PP_IRMACRO) {
Charles Crayned4200be2008-07-12 16:42:33 -07002206 nested_mac_count++;
2207 return NO_DIRECTIVE_FOUND;
2208 } else if (nested_mac_count > 0) {
2209 if (i == PP_ENDMACRO) {
2210 nested_mac_count--;
2211 return NO_DIRECTIVE_FOUND;
2212 }
2213 }
2214 if (!defining->name) {
2215 if (i == PP_REP) {
2216 nested_rep_count++;
2217 return NO_DIRECTIVE_FOUND;
2218 } else if (nested_rep_count > 0) {
2219 if (i == PP_ENDREP) {
2220 nested_rep_count--;
2221 return NO_DIRECTIVE_FOUND;
2222 }
2223 }
2224 }
2225 }
2226
H. Peter Anvin4169a472007-09-12 01:29:43 +00002227 switch (i) {
2228 case PP_INVALID:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002229 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2230 tline->text);
2231 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002232
H. Peter Anvine2c80182005-01-15 22:15:51 +00002233 case PP_STACKSIZE:
2234 /* Directive to tell NASM what the default stack size is. The
2235 * default is for a 16-bit stack, and this can be overriden with
2236 * %stacksize large.
H. Peter Anvine2c80182005-01-15 22:15:51 +00002237 */
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, "`%%stacksize' missing size parameter");
2243 free_tlist(origline);
2244 return DIRECTIVE_FOUND;
2245 }
2246 if (nasm_stricmp(tline->text, "flat") == 0) {
2247 /* All subsequent ARG directives are for a 32-bit stack */
2248 StackSize = 4;
2249 StackPointer = "ebp";
2250 ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002251 LocalOffset = 0;
Charles Crayne7eaf9192007-11-08 22:11:14 -08002252 } else if (nasm_stricmp(tline->text, "flat64") == 0) {
2253 /* All subsequent ARG directives are for a 64-bit stack */
2254 StackSize = 8;
2255 StackPointer = "rbp";
Per Jessen53252e02010-02-11 00:16:59 +03002256 ArgOffset = 16;
Charles Crayne7eaf9192007-11-08 22:11:14 -08002257 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002258 } else if (nasm_stricmp(tline->text, "large") == 0) {
2259 /* All subsequent ARG directives are for a 16-bit stack,
2260 * far function call.
2261 */
2262 StackSize = 2;
2263 StackPointer = "bp";
2264 ArgOffset = 4;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002265 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002266 } else if (nasm_stricmp(tline->text, "small") == 0) {
2267 /* All subsequent ARG directives are for a 16-bit stack,
2268 * far function call. We don't support near functions.
2269 */
2270 StackSize = 2;
2271 StackPointer = "bp";
2272 ArgOffset = 6;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002273 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002274 } else {
2275 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
2276 free_tlist(origline);
2277 return DIRECTIVE_FOUND;
2278 }
2279 free_tlist(origline);
2280 return DIRECTIVE_FOUND;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002281
H. Peter Anvine2c80182005-01-15 22:15:51 +00002282 case PP_ARG:
2283 /* TASM like ARG directive to define arguments to functions, in
2284 * the following form:
2285 *
2286 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2287 */
2288 offset = ArgOffset;
2289 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002290 char *arg, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00002291 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002292
H. Peter Anvine2c80182005-01-15 22:15:51 +00002293 /* Find the argument name */
2294 tline = tline->next;
2295 if (tline && tline->type == TOK_WHITESPACE)
2296 tline = tline->next;
2297 if (!tline || tline->type != TOK_ID) {
2298 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
2299 free_tlist(origline);
2300 return DIRECTIVE_FOUND;
2301 }
2302 arg = tline->text;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002303
H. Peter Anvine2c80182005-01-15 22:15:51 +00002304 /* Find the argument size type */
2305 tline = tline->next;
2306 if (!tline || tline->type != TOK_OTHER
2307 || tline->text[0] != ':') {
2308 error(ERR_NONFATAL,
2309 "Syntax error processing `%%arg' directive");
2310 free_tlist(origline);
2311 return DIRECTIVE_FOUND;
2312 }
2313 tline = tline->next;
2314 if (!tline || tline->type != TOK_ID) {
2315 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
2316 free_tlist(origline);
2317 return DIRECTIVE_FOUND;
2318 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002319
H. Peter Anvine2c80182005-01-15 22:15:51 +00002320 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002321 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002322 tt = expand_smacro(tt);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002323 size = parse_size(tt->text);
2324 if (!size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002325 error(ERR_NONFATAL,
2326 "Invalid size type for `%%arg' missing directive");
2327 free_tlist(tt);
2328 free_tlist(origline);
2329 return DIRECTIVE_FOUND;
2330 }
2331 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002332
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002333 /* Round up to even stack slots */
2334 size = ALIGN(size, StackSize);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002335
H. Peter Anvine2c80182005-01-15 22:15:51 +00002336 /* Now define the macro for the argument */
2337 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
2338 arg, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002339 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00002340 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002341
H. Peter Anvine2c80182005-01-15 22:15:51 +00002342 /* Move to the next argument in the list */
2343 tline = tline->next;
2344 if (tline && tline->type == TOK_WHITESPACE)
2345 tline = tline->next;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002346 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002347 ArgOffset = offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002348 free_tlist(origline);
2349 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002350
H. Peter Anvine2c80182005-01-15 22:15:51 +00002351 case PP_LOCAL:
2352 /* TASM like LOCAL directive to define local variables for a
2353 * function, in the following form:
2354 *
2355 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2356 *
2357 * The '= LocalSize' at the end is ignored by NASM, but is
2358 * required by TASM to define the local parameter size (and used
2359 * by the TASM macro package).
2360 */
2361 offset = LocalOffset;
2362 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002363 char *local, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00002364 int size = StackSize;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002365
H. Peter Anvine2c80182005-01-15 22:15:51 +00002366 /* Find the argument name */
2367 tline = tline->next;
2368 if (tline && tline->type == TOK_WHITESPACE)
2369 tline = tline->next;
2370 if (!tline || tline->type != TOK_ID) {
2371 error(ERR_NONFATAL,
2372 "`%%local' missing argument parameter");
2373 free_tlist(origline);
2374 return DIRECTIVE_FOUND;
2375 }
2376 local = tline->text;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002377
H. Peter Anvine2c80182005-01-15 22:15:51 +00002378 /* Find the argument size type */
2379 tline = tline->next;
2380 if (!tline || tline->type != TOK_OTHER
2381 || tline->text[0] != ':') {
2382 error(ERR_NONFATAL,
2383 "Syntax error processing `%%local' directive");
2384 free_tlist(origline);
2385 return DIRECTIVE_FOUND;
2386 }
2387 tline = tline->next;
2388 if (!tline || tline->type != TOK_ID) {
2389 error(ERR_NONFATAL,
2390 "`%%local' missing size type parameter");
2391 free_tlist(origline);
2392 return DIRECTIVE_FOUND;
2393 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002394
H. Peter Anvine2c80182005-01-15 22:15:51 +00002395 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002396 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002397 tt = expand_smacro(tt);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002398 size = parse_size(tt->text);
2399 if (!size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002400 error(ERR_NONFATAL,
2401 "Invalid size type for `%%local' missing directive");
2402 free_tlist(tt);
2403 free_tlist(origline);
2404 return DIRECTIVE_FOUND;
2405 }
2406 free_tlist(tt);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002407
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002408 /* Round up to even stack slots */
2409 size = ALIGN(size, StackSize);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002410
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002411 offset += size; /* Negative offset, increment before */
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002412
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002413 /* Now define the macro for the argument */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002414 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
2415 local, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002416 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002417
H. Peter Anvine2c80182005-01-15 22:15:51 +00002418 /* Now define the assign to setup the enter_c macro correctly */
2419 snprintf(directive, sizeof(directive),
2420 "%%assign %%$localsize %%$localsize+%d", size);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002421 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002422
H. Peter Anvine2c80182005-01-15 22:15:51 +00002423 /* Move to the next argument in the list */
2424 tline = tline->next;
2425 if (tline && tline->type == TOK_WHITESPACE)
2426 tline = tline->next;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002427 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002428 LocalOffset = offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002429 free_tlist(origline);
2430 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002431
H. Peter Anvine2c80182005-01-15 22:15:51 +00002432 case PP_CLEAR:
2433 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002434 error(ERR_WARNING|ERR_PASS1,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002435 "trailing garbage after `%%clear' ignored");
2436 free_macros();
2437 init_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00002438 free_tlist(origline);
2439 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002440
H. Peter Anvin418ca702008-05-30 10:42:30 -07002441 case PP_DEPEND:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002442 t = tline->next = expand_smacro(tline->next);
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002443 skip_white_(t);
2444 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002445 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin418ca702008-05-30 10:42:30 -07002446 error(ERR_NONFATAL, "`%%depend' expects a file name");
2447 free_tlist(origline);
2448 return DIRECTIVE_FOUND; /* but we did _something_ */
2449 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002450 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002451 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin418ca702008-05-30 10:42:30 -07002452 "trailing garbage after `%%depend' ignored");
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002453 p = t->text;
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002454 if (t->type != TOK_INTERNAL_STRING)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002455 nasm_unquote_cstr(p, i);
2456 if (dephead && !in_list(*dephead, p)) {
2457 StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next);
2458 sl->next = NULL;
2459 strcpy(sl->str, p);
2460 *deptail = sl;
2461 deptail = &sl->next;
2462 }
2463 free_tlist(origline);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002464 return DIRECTIVE_FOUND;
2465
2466 case PP_INCLUDE:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002467 t = tline->next = expand_smacro(tline->next);
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002468 skip_white_(t);
H. Peter Anvind2456592008-06-19 15:04:18 -07002469
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002470 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002471 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002472 error(ERR_NONFATAL, "`%%include' expects a file name");
2473 free_tlist(origline);
2474 return DIRECTIVE_FOUND; /* but we did _something_ */
2475 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002476 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002477 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002478 "trailing garbage after `%%include' ignored");
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002479 p = t->text;
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002480 if (t->type != TOK_INTERNAL_STRING)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002481 nasm_unquote_cstr(p, i);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002482 inc = nasm_malloc(sizeof(Include));
2483 inc->next = istk;
2484 inc->conds = NULL;
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07002485 inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002486 if (!inc->fp) {
2487 /* -MG given but file not found */
2488 nasm_free(inc);
2489 } else {
2490 inc->fname = src_set_fname(nasm_strdup(p));
2491 inc->lineno = src_set_linnum(0);
2492 inc->lineinc = 1;
2493 inc->expansion = NULL;
2494 inc->mstk = NULL;
2495 istk = inc;
2496 list->uplevel(LIST_INCLUDE);
2497 }
2498 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002499 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002500
H. Peter Anvind2456592008-06-19 15:04:18 -07002501 case PP_USE:
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002502 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002503 static macros_t *use_pkg;
2504 const char *pkg_macro = NULL;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002505
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002506 tline = tline->next;
2507 skip_white_(tline);
2508 tline = expand_id(tline);
H. Peter Anvind2456592008-06-19 15:04:18 -07002509
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002510 if (!tline || (tline->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002511 tline->type != TOK_INTERNAL_STRING &&
2512 tline->type != TOK_ID)) {
H. Peter Anvin926fc402008-06-19 16:26:12 -07002513 error(ERR_NONFATAL, "`%%use' expects a package name");
H. Peter Anvind2456592008-06-19 15:04:18 -07002514 free_tlist(origline);
2515 return DIRECTIVE_FOUND; /* but we did _something_ */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002516 }
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002517 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002518 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvind2456592008-06-19 15:04:18 -07002519 "trailing garbage after `%%use' ignored");
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002520 if (tline->type == TOK_STRING)
2521 nasm_unquote_cstr(tline->text, i);
2522 use_pkg = nasm_stdmac_find_package(tline->text);
2523 if (!use_pkg)
2524 error(ERR_NONFATAL, "unknown `%%use' package: %s", tline->text);
2525 else
2526 pkg_macro = (char *)use_pkg + 1; /* The first string will be <%define>__USE_*__ */
Victor van den Elzen35eb2ea2010-03-10 22:33:48 +01002527 if (use_pkg && ! smacro_defined(NULL, pkg_macro, 0, NULL, true)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002528 /* Not already included, go ahead and include it */
2529 stdmacpos = use_pkg;
2530 }
2531 free_tlist(origline);
H. Peter Anvind2456592008-06-19 15:04:18 -07002532 return DIRECTIVE_FOUND;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002533 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002534 case PP_PUSH:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002535 case PP_REPL:
H. Peter Anvin42b56392008-10-24 16:24:21 -07002536 case PP_POP:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002537 tline = tline->next;
2538 skip_white_(tline);
2539 tline = expand_id(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002540 if (tline) {
2541 if (!tok_type_(tline, TOK_ID)) {
2542 error(ERR_NONFATAL, "`%s' expects a context identifier",
2543 pp_directives[i]);
2544 free_tlist(origline);
2545 return DIRECTIVE_FOUND; /* but we did _something_ */
2546 }
2547 if (tline->next)
2548 error(ERR_WARNING|ERR_PASS1,
2549 "trailing garbage after `%s' ignored",
2550 pp_directives[i]);
2551 p = nasm_strdup(tline->text);
2552 } else {
2553 p = NULL; /* Anonymous */
2554 }
H. Peter Anvin42b56392008-10-24 16:24:21 -07002555
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002556 if (i == PP_PUSH) {
2557 ctx = nasm_malloc(sizeof(Context));
2558 ctx->next = cstk;
2559 hash_init(&ctx->localmac, HASH_SMALL);
2560 ctx->name = p;
2561 ctx->number = unique++;
2562 cstk = ctx;
2563 } else {
2564 /* %pop or %repl */
2565 if (!cstk) {
2566 error(ERR_NONFATAL, "`%s': context stack is empty",
2567 pp_directives[i]);
2568 } else if (i == PP_POP) {
2569 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
2570 error(ERR_NONFATAL, "`%%pop' in wrong context: %s, "
2571 "expected %s",
2572 cstk->name ? cstk->name : "anonymous", p);
2573 else
2574 ctx_pop();
2575 } else {
2576 /* i == PP_REPL */
2577 nasm_free(cstk->name);
2578 cstk->name = p;
2579 p = NULL;
2580 }
2581 nasm_free(p);
2582 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002583 free_tlist(origline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002584 return DIRECTIVE_FOUND;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002585 case PP_FATAL:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002586 severity = ERR_FATAL;
2587 goto issue_error;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002588 case PP_ERROR:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002589 severity = ERR_NONFATAL;
2590 goto issue_error;
H. Peter Anvin7df04172008-06-10 18:27:38 -07002591 case PP_WARNING:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002592 severity = ERR_WARNING|ERR_WARN_USER;
2593 goto issue_error;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002594
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002595issue_error:
H. Peter Anvin7df04172008-06-10 18:27:38 -07002596 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002597 /* Only error out if this is the final pass */
2598 if (pass != 2 && i != PP_FATAL)
2599 return DIRECTIVE_FOUND;
2600
2601 tline->next = expand_smacro(tline->next);
2602 tline = tline->next;
2603 skip_white_(tline);
2604 t = tline ? tline->next : NULL;
2605 skip_white_(t);
2606 if (tok_type_(tline, TOK_STRING) && !t) {
2607 /* The line contains only a quoted string */
2608 p = tline->text;
2609 nasm_unquote(p, NULL); /* Ignore NUL character truncation */
2610 error(severity, "%s", p);
2611 } else {
2612 /* Not a quoted string, or more than a quoted string */
2613 p = detoken(tline, false);
2614 error(severity, "%s", p);
2615 nasm_free(p);
2616 }
2617 free_tlist(origline);
2618 return DIRECTIVE_FOUND;
H. Peter Anvin7df04172008-06-10 18:27:38 -07002619 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002620
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002621 CASE_PP_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002622 if (istk->conds && !emitting(istk->conds->state))
2623 j = COND_NEVER;
2624 else {
2625 j = if_condition(tline->next, i);
2626 tline->next = NULL; /* it got freed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002627 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2628 }
2629 cond = nasm_malloc(sizeof(Cond));
2630 cond->next = istk->conds;
2631 cond->state = j;
2632 istk->conds = cond;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002633 if(istk->mstk)
Keith Kanios3c0d91f2009-10-25 13:28:03 -05002634 istk->mstk->condcnt ++;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002635 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002636 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002637
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002638 CASE_PP_ELIF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002639 if (!istk->conds)
H. Peter Anvin4169a472007-09-12 01:29:43 +00002640 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002641 switch(istk->conds->state) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002642 case COND_IF_TRUE:
2643 istk->conds->state = COND_DONE;
2644 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002645
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002646 case COND_DONE:
2647 case COND_NEVER:
2648 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002649
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002650 case COND_ELSE_TRUE:
2651 case COND_ELSE_FALSE:
2652 error_precond(ERR_WARNING|ERR_PASS1,
2653 "`%%elif' after `%%else' ignored");
2654 istk->conds->state = COND_NEVER;
2655 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002656
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002657 case COND_IF_FALSE:
2658 /*
2659 * IMPORTANT: In the case of %if, we will already have
2660 * called expand_mmac_params(); however, if we're
2661 * processing an %elif we must have been in a
2662 * non-emitting mode, which would have inhibited
2663 * the normal invocation of expand_mmac_params().
2664 * Therefore, we have to do it explicitly here.
2665 */
2666 j = if_condition(expand_mmac_params(tline->next), i);
2667 tline->next = NULL; /* it got freed */
2668 istk->conds->state =
2669 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2670 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002671 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002672 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002673 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002674
H. Peter Anvine2c80182005-01-15 22:15:51 +00002675 case PP_ELSE:
2676 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002677 error_precond(ERR_WARNING|ERR_PASS1,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002678 "trailing garbage after `%%else' ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00002679 if (!istk->conds)
2680 error(ERR_FATAL, "`%%else': no matching `%%if'");
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002681 switch(istk->conds->state) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002682 case COND_IF_TRUE:
2683 case COND_DONE:
2684 istk->conds->state = COND_ELSE_FALSE;
2685 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002686
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002687 case COND_NEVER:
2688 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002689
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002690 case COND_IF_FALSE:
2691 istk->conds->state = COND_ELSE_TRUE;
2692 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002693
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002694 case COND_ELSE_TRUE:
2695 case COND_ELSE_FALSE:
2696 error_precond(ERR_WARNING|ERR_PASS1,
2697 "`%%else' after `%%else' ignored.");
2698 istk->conds->state = COND_NEVER;
2699 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002700 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002701 free_tlist(origline);
2702 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002703
H. Peter Anvine2c80182005-01-15 22:15:51 +00002704 case PP_ENDIF:
2705 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002706 error_precond(ERR_WARNING|ERR_PASS1,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002707 "trailing garbage after `%%endif' ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00002708 if (!istk->conds)
2709 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2710 cond = istk->conds;
2711 istk->conds = cond->next;
2712 nasm_free(cond);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002713 if(istk->mstk)
Keith Kanios3c0d91f2009-10-25 13:28:03 -05002714 istk->mstk->condcnt --;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002715 free_tlist(origline);
2716 return DIRECTIVE_FOUND;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002717
H. Peter Anvindb8f96e2009-07-15 09:07:29 -04002718 case PP_RMACRO:
2719 case PP_IRMACRO:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002720 case PP_MACRO:
2721 case PP_IMACRO:
H. Peter Anvina26433d2008-07-16 14:40:01 -07002722 if (defining) {
H. Peter Anvindb8f96e2009-07-15 09:07:29 -04002723 error(ERR_FATAL, "`%s': already defining a macro",
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002724 pp_directives[i]);
2725 return DIRECTIVE_FOUND;
2726 }
2727 defining = nasm_malloc(sizeof(MMacro));
2728 defining->max_depth =
2729 (i == PP_RMACRO) || (i == PP_IRMACRO) ? DEADMAN_LIMIT : 0;
2730 defining->casesense = (i == PP_MACRO) || (i == PP_RMACRO);
2731 if (!parse_mmacro_spec(tline, defining, pp_directives[i])) {
2732 nasm_free(defining);
2733 defining = NULL;
2734 return DIRECTIVE_FOUND;
2735 }
H. Peter Anvina26433d2008-07-16 14:40:01 -07002736
H. Peter Anvin166c2472008-05-28 12:28:58 -07002737 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002738 while (mmac) {
2739 if (!strcmp(mmac->name, defining->name) &&
2740 (mmac->nparam_min <= defining->nparam_max
2741 || defining->plus)
2742 && (defining->nparam_min <= mmac->nparam_max
2743 || mmac->plus)) {
H. Peter Anvin917a3492008-09-24 09:14:49 -07002744 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002745 "redefining multi-line macro `%s'", defining->name);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002746 return DIRECTIVE_FOUND;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002747 }
2748 mmac = mmac->next;
2749 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002750 free_tlist(origline);
2751 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002752
H. Peter Anvine2c80182005-01-15 22:15:51 +00002753 case PP_ENDM:
2754 case PP_ENDMACRO:
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02002755 if (! (defining && defining->name)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002756 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2757 return DIRECTIVE_FOUND;
2758 }
Keith Kanios852f1ee2009-07-12 00:19:55 -05002759 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002760 defining->next = *mmhead;
Keith Kanios852f1ee2009-07-12 00:19:55 -05002761 *mmhead = defining;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002762 defining = NULL;
2763 free_tlist(origline);
2764 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002765
H. Peter Anvin89cee572009-07-15 09:16:54 -04002766 case PP_EXITMACRO:
Keith Kanios852f1ee2009-07-12 00:19:55 -05002767 /*
2768 * We must search along istk->expansion until we hit a
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002769 * macro-end marker for a macro with a name. Then we
Keith Kanios3c0d91f2009-10-25 13:28:03 -05002770 * bypass all lines between exitmacro and endmacro.
Keith Kanios852f1ee2009-07-12 00:19:55 -05002771 */
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04002772 list_for_each(l, istk->expansion)
Keith Kanios852f1ee2009-07-12 00:19:55 -05002773 if (l->finishes && l->finishes->name)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002774 break;
Keith Kanios852f1ee2009-07-12 00:19:55 -05002775
2776 if (l) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002777 /*
2778 * Remove all conditional entries relative to this
2779 * macro invocation. (safe to do in this context)
2780 */
Keith Kanios3c0d91f2009-10-25 13:28:03 -05002781 for ( ; l->finishes->condcnt > 0; l->finishes->condcnt --) {
2782 cond = istk->conds;
2783 istk->conds = cond->next;
2784 nasm_free(cond);
2785 }
2786 istk->expansion = l;
Keith Kanios852f1ee2009-07-12 00:19:55 -05002787 } else {
2788 error(ERR_NONFATAL, "`%%exitmacro' not within `%%macro' block");
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002789 }
Keith Kanios852f1ee2009-07-12 00:19:55 -05002790 free_tlist(origline);
2791 return DIRECTIVE_FOUND;
2792
H. Peter Anvina26433d2008-07-16 14:40:01 -07002793 case PP_UNMACRO:
2794 case PP_UNIMACRO:
2795 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002796 MMacro **mmac_p;
2797 MMacro spec;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002798
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002799 spec.casesense = (i == PP_UNMACRO);
2800 if (!parse_mmacro_spec(tline, &spec, pp_directives[i])) {
2801 return DIRECTIVE_FOUND;
2802 }
H. Peter Anvina26433d2008-07-16 14:40:01 -07002803 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
2804 while (mmac_p && *mmac_p) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002805 mmac = *mmac_p;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002806 if (mmac->casesense == spec.casesense &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002807 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
H. Peter Anvina26433d2008-07-16 14:40:01 -07002808 mmac->nparam_min == spec.nparam_min &&
2809 mmac->nparam_max == spec.nparam_max &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002810 mmac->plus == spec.plus) {
2811 *mmac_p = mmac->next;
2812 free_mmacro(mmac);
2813 } else {
2814 mmac_p = &mmac->next;
2815 }
2816 }
2817 free_tlist(origline);
2818 free_tlist(spec.dlist);
2819 return DIRECTIVE_FOUND;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002820 }
2821
H. Peter Anvine2c80182005-01-15 22:15:51 +00002822 case PP_ROTATE:
2823 if (tline->next && tline->next->type == TOK_WHITESPACE)
2824 tline = tline->next;
H. Peter Anvin89cee572009-07-15 09:16:54 -04002825 if (!tline->next) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002826 free_tlist(origline);
2827 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2828 return DIRECTIVE_FOUND;
2829 }
2830 t = expand_smacro(tline->next);
2831 tline->next = NULL;
2832 free_tlist(origline);
2833 tline = t;
2834 tptr = &t;
2835 tokval.t_type = TOKEN_INVALID;
2836 evalresult =
2837 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2838 free_tlist(tline);
2839 if (!evalresult)
2840 return DIRECTIVE_FOUND;
2841 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002842 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002843 "trailing garbage after expression ignored");
2844 if (!is_simple(evalresult)) {
2845 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2846 return DIRECTIVE_FOUND;
2847 }
2848 mmac = istk->mstk;
2849 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2850 mmac = mmac->next_active;
2851 if (!mmac) {
2852 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2853 } else if (mmac->nparam == 0) {
2854 error(ERR_NONFATAL,
2855 "`%%rotate' invoked within macro without parameters");
2856 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002857 int rotate = mmac->rotate + reloc_value(evalresult);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002858
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002859 rotate %= (int)mmac->nparam;
2860 if (rotate < 0)
2861 rotate += mmac->nparam;
H. Peter Anvin70653092007-10-19 14:42:29 -07002862
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002863 mmac->rotate = rotate;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002864 }
2865 return DIRECTIVE_FOUND;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002866
H. Peter Anvine2c80182005-01-15 22:15:51 +00002867 case PP_REP:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002868 nolist = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002869 do {
2870 tline = tline->next;
2871 } while (tok_type_(tline, TOK_WHITESPACE));
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002872
H. Peter Anvine2c80182005-01-15 22:15:51 +00002873 if (tok_type_(tline, TOK_ID) &&
2874 nasm_stricmp(tline->text, ".nolist") == 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002875 nolist = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002876 do {
2877 tline = tline->next;
2878 } while (tok_type_(tline, TOK_WHITESPACE));
2879 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002880
H. Peter Anvine2c80182005-01-15 22:15:51 +00002881 if (tline) {
2882 t = expand_smacro(tline);
2883 tptr = &t;
2884 tokval.t_type = TOKEN_INVALID;
2885 evalresult =
2886 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2887 if (!evalresult) {
2888 free_tlist(origline);
2889 return DIRECTIVE_FOUND;
2890 }
2891 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002892 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002893 "trailing garbage after expression ignored");
2894 if (!is_simple(evalresult)) {
2895 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2896 return DIRECTIVE_FOUND;
2897 }
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002898 count = reloc_value(evalresult) + 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002899 } else {
2900 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002901 count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002902 }
2903 free_tlist(origline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002904
H. Peter Anvine2c80182005-01-15 22:15:51 +00002905 tmp_defining = defining;
2906 defining = nasm_malloc(sizeof(MMacro));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002907 defining->prev = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002908 defining->name = NULL; /* flags this macro as a %rep block */
H. Peter Anvin70055962007-10-11 00:05:31 -07002909 defining->casesense = false;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002910 defining->plus = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002911 defining->nolist = nolist;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002912 defining->in_progress = count;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002913 defining->max_depth = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002914 defining->nparam_min = defining->nparam_max = 0;
2915 defining->defaults = NULL;
2916 defining->dlist = NULL;
2917 defining->expansion = NULL;
2918 defining->next_active = istk->mstk;
2919 defining->rep_nest = tmp_defining;
2920 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002921
H. Peter Anvine2c80182005-01-15 22:15:51 +00002922 case PP_ENDREP:
2923 if (!defining || defining->name) {
2924 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2925 return DIRECTIVE_FOUND;
2926 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002927
H. Peter Anvine2c80182005-01-15 22:15:51 +00002928 /*
2929 * Now we have a "macro" defined - although it has no name
2930 * and we won't be entering it in the hash tables - we must
2931 * push a macro-end marker for it on to istk->expansion.
2932 * After that, it will take care of propagating itself (a
2933 * macro-end marker line for a macro which is really a %rep
2934 * block will cause the macro to be re-expanded, complete
2935 * with another macro-end marker to ensure the process
2936 * continues) until the whole expansion is forcibly removed
2937 * from istk->expansion by a %exitrep.
2938 */
2939 l = nasm_malloc(sizeof(Line));
2940 l->next = istk->expansion;
2941 l->finishes = defining;
2942 l->first = NULL;
2943 istk->expansion = l;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002944
H. Peter Anvine2c80182005-01-15 22:15:51 +00002945 istk->mstk = defining;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002946
H. Peter Anvine2c80182005-01-15 22:15:51 +00002947 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2948 tmp_defining = defining;
2949 defining = defining->rep_nest;
2950 free_tlist(origline);
2951 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002952
H. Peter Anvine2c80182005-01-15 22:15:51 +00002953 case PP_EXITREP:
2954 /*
2955 * We must search along istk->expansion until we hit a
2956 * macro-end marker for a macro with no name. Then we set
2957 * its `in_progress' flag to 0.
2958 */
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04002959 list_for_each(l, istk->expansion)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002960 if (l->finishes && !l->finishes->name)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002961 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002962
H. Peter Anvine2c80182005-01-15 22:15:51 +00002963 if (l)
Charles Crayned4200be2008-07-12 16:42:33 -07002964 l->finishes->in_progress = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002965 else
2966 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2967 free_tlist(origline);
2968 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002969
H. Peter Anvine2c80182005-01-15 22:15:51 +00002970 case PP_XDEFINE:
2971 case PP_IXDEFINE:
2972 case PP_DEFINE:
2973 case PP_IDEFINE:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002974 casesense = (i == PP_DEFINE || i == PP_XDEFINE);
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002975
H. Peter Anvine2c80182005-01-15 22:15:51 +00002976 tline = tline->next;
2977 skip_white_(tline);
2978 tline = expand_id(tline);
2979 if (!tline || (tline->type != TOK_ID &&
2980 (tline->type != TOK_PREPROC_ID ||
2981 tline->text[1] != '$'))) {
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002982 error(ERR_NONFATAL, "`%s' expects a macro identifier",
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002983 pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002984 free_tlist(origline);
2985 return DIRECTIVE_FOUND;
2986 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002987
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002988 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002989 last = tline;
2990 param_start = tline = tline->next;
2991 nparam = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002992
H. Peter Anvine2c80182005-01-15 22:15:51 +00002993 /* Expand the macro definition now for %xdefine and %ixdefine */
2994 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2995 tline = expand_smacro(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002996
H. Peter Anvine2c80182005-01-15 22:15:51 +00002997 if (tok_is_(tline, "(")) {
2998 /*
2999 * This macro has parameters.
3000 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003001
H. Peter Anvine2c80182005-01-15 22:15:51 +00003002 tline = tline->next;
3003 while (1) {
3004 skip_white_(tline);
3005 if (!tline) {
3006 error(ERR_NONFATAL, "parameter identifier expected");
3007 free_tlist(origline);
3008 return DIRECTIVE_FOUND;
3009 }
3010 if (tline->type != TOK_ID) {
3011 error(ERR_NONFATAL,
3012 "`%s': parameter identifier expected",
3013 tline->text);
3014 free_tlist(origline);
3015 return DIRECTIVE_FOUND;
3016 }
3017 tline->type = TOK_SMAC_PARAM + nparam++;
3018 tline = tline->next;
3019 skip_white_(tline);
3020 if (tok_is_(tline, ",")) {
3021 tline = tline->next;
H. Peter Anvinca348b62008-07-23 10:49:26 -04003022 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003023 if (!tok_is_(tline, ")")) {
3024 error(ERR_NONFATAL,
3025 "`)' expected to terminate macro template");
3026 free_tlist(origline);
3027 return DIRECTIVE_FOUND;
3028 }
3029 break;
3030 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003031 }
3032 last = tline;
3033 tline = tline->next;
3034 }
3035 if (tok_type_(tline, TOK_WHITESPACE))
3036 last = tline, tline = tline->next;
3037 macro_start = NULL;
3038 last->next = NULL;
3039 t = tline;
3040 while (t) {
3041 if (t->type == TOK_ID) {
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04003042 list_for_each(tt, param_start)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003043 if (tt->type >= TOK_SMAC_PARAM &&
3044 !strcmp(tt->text, t->text))
3045 t->type = tt->type;
3046 }
3047 tt = t->next;
3048 t->next = macro_start;
3049 macro_start = t;
3050 t = tt;
3051 }
3052 /*
3053 * Good. We now have a macro name, a parameter count, and a
3054 * token list (in reverse order) for an expansion. We ought
3055 * to be OK just to create an SMacro, store it, and let
3056 * free_tlist have the rest of the line (which we have
3057 * carefully re-terminated after chopping off the expansion
3058 * from the end).
3059 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003060 define_smacro(ctx, mname, casesense, nparam, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003061 free_tlist(origline);
3062 return DIRECTIVE_FOUND;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003063
H. Peter Anvine2c80182005-01-15 22:15:51 +00003064 case PP_UNDEF:
3065 tline = tline->next;
3066 skip_white_(tline);
3067 tline = expand_id(tline);
3068 if (!tline || (tline->type != TOK_ID &&
3069 (tline->type != TOK_PREPROC_ID ||
3070 tline->text[1] != '$'))) {
3071 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
3072 free_tlist(origline);
3073 return DIRECTIVE_FOUND;
3074 }
3075 if (tline->next) {
H. Peter Anvin917a3492008-09-24 09:14:49 -07003076 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003077 "trailing garbage after macro name ignored");
3078 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003079
H. Peter Anvine2c80182005-01-15 22:15:51 +00003080 /* Find the context that symbol belongs to */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003081 ctx = get_ctx(tline->text, &mname, false);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003082 undef_smacro(ctx, mname);
3083 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003084 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003085
H. Peter Anvin9e200162008-06-04 17:23:14 -07003086 case PP_DEFSTR:
3087 case PP_IDEFSTR:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003088 casesense = (i == PP_DEFSTR);
H. Peter Anvin9e200162008-06-04 17:23:14 -07003089
3090 tline = tline->next;
3091 skip_white_(tline);
3092 tline = expand_id(tline);
3093 if (!tline || (tline->type != TOK_ID &&
3094 (tline->type != TOK_PREPROC_ID ||
3095 tline->text[1] != '$'))) {
3096 error(ERR_NONFATAL, "`%s' expects a macro identifier",
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003097 pp_directives[i]);
H. Peter Anvin9e200162008-06-04 17:23:14 -07003098 free_tlist(origline);
3099 return DIRECTIVE_FOUND;
3100 }
3101
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003102 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvin9e200162008-06-04 17:23:14 -07003103 last = tline;
3104 tline = expand_smacro(tline->next);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003105 last->next = NULL;
H. Peter Anvin9e200162008-06-04 17:23:14 -07003106
3107 while (tok_type_(tline, TOK_WHITESPACE))
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003108 tline = delete_Token(tline);
H. Peter Anvin9e200162008-06-04 17:23:14 -07003109
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003110 p = detoken(tline, false);
H. Peter Anvin9e200162008-06-04 17:23:14 -07003111 macro_start = nasm_malloc(sizeof(*macro_start));
3112 macro_start->next = NULL;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003113 macro_start->text = nasm_quote(p, strlen(p));
3114 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003115 macro_start->a.mac = NULL;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003116 nasm_free(p);
H. Peter Anvin9e200162008-06-04 17:23:14 -07003117
3118 /*
3119 * We now have a macro name, an implicit parameter count of
3120 * zero, and a string token to use as an expansion. Create
3121 * and store an SMacro.
3122 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003123 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvin9e200162008-06-04 17:23:14 -07003124 free_tlist(origline);
3125 return DIRECTIVE_FOUND;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003126
H. Peter Anvin2f55bda2009-07-14 15:04:04 -04003127 case PP_DEFTOK:
3128 case PP_IDEFTOK:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003129 casesense = (i == PP_DEFTOK);
3130
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003131 tline = tline->next;
3132 skip_white_(tline);
3133 tline = expand_id(tline);
3134 if (!tline || (tline->type != TOK_ID &&
3135 (tline->type != TOK_PREPROC_ID ||
3136 tline->text[1] != '$'))) {
3137 error(ERR_NONFATAL,
3138 "`%s' expects a macro identifier as first parameter",
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003139 pp_directives[i]);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003140 free_tlist(origline);
3141 return DIRECTIVE_FOUND;
3142 }
3143 ctx = get_ctx(tline->text, &mname, false);
3144 last = tline;
3145 tline = expand_smacro(tline->next);
3146 last->next = NULL;
3147
3148 t = tline;
3149 while (tok_type_(t, TOK_WHITESPACE))
3150 t = t->next;
3151 /* t should now point to the string */
3152 if (t->type != TOK_STRING) {
3153 error(ERR_NONFATAL,
3154 "`%s` requires string as second parameter",
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003155 pp_directives[i]);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003156 free_tlist(tline);
3157 free_tlist(origline);
3158 return DIRECTIVE_FOUND;
3159 }
3160
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003161 nasm_unquote_cstr(t->text, i);
3162 macro_start = tokenize(t->text);
3163
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003164 /*
3165 * We now have a macro name, an implicit parameter count of
3166 * zero, and a numeric token to use as an expansion. Create
3167 * and store an SMacro.
3168 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003169 define_smacro(ctx, mname, casesense, 0, macro_start);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003170 free_tlist(tline);
3171 free_tlist(origline);
3172 return DIRECTIVE_FOUND;
H. Peter Anvin9e200162008-06-04 17:23:14 -07003173
H. Peter Anvin418ca702008-05-30 10:42:30 -07003174 case PP_PATHSEARCH:
3175 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003176 FILE *fp;
3177 StrList *xsl = NULL;
3178 StrList **xst = &xsl;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003179
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003180 casesense = true;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003181
3182 tline = tline->next;
3183 skip_white_(tline);
3184 tline = expand_id(tline);
3185 if (!tline || (tline->type != TOK_ID &&
3186 (tline->type != TOK_PREPROC_ID ||
3187 tline->text[1] != '$'))) {
3188 error(ERR_NONFATAL,
3189 "`%%pathsearch' expects a macro identifier as first parameter");
3190 free_tlist(origline);
3191 return DIRECTIVE_FOUND;
3192 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003193 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003194 last = tline;
3195 tline = expand_smacro(tline->next);
3196 last->next = NULL;
3197
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003198 t = tline;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003199 while (tok_type_(t, TOK_WHITESPACE))
3200 t = t->next;
3201
3202 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003203 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin418ca702008-05-30 10:42:30 -07003204 error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003205 free_tlist(tline);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003206 free_tlist(origline);
3207 return DIRECTIVE_FOUND; /* but we did _something_ */
3208 }
3209 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07003210 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin418ca702008-05-30 10:42:30 -07003211 "trailing garbage after `%%pathsearch' ignored");
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003212 p = t->text;
H. Peter Anvin427cc912008-06-01 21:43:03 -07003213 if (t->type != TOK_INTERNAL_STRING)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003214 nasm_unquote(p, NULL);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003215
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003216 fp = inc_fopen(p, &xsl, &xst, true);
3217 if (fp) {
3218 p = xsl->str;
3219 fclose(fp); /* Don't actually care about the file */
3220 }
H. Peter Anvin418ca702008-05-30 10:42:30 -07003221 macro_start = nasm_malloc(sizeof(*macro_start));
3222 macro_start->next = NULL;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003223 macro_start->text = nasm_quote(p, strlen(p));
3224 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003225 macro_start->a.mac = NULL;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003226 if (xsl)
3227 nasm_free(xsl);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003228
3229 /*
3230 * We now have a macro name, an implicit parameter count of
3231 * zero, and a string token to use as an expansion. Create
3232 * and store an SMacro.
3233 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003234 define_smacro(ctx, mname, casesense, 0, macro_start);
3235 free_tlist(tline);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003236 free_tlist(origline);
3237 return DIRECTIVE_FOUND;
3238 }
3239
H. Peter Anvine2c80182005-01-15 22:15:51 +00003240 case PP_STRLEN:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003241 casesense = true;
H. Peter Anvin70653092007-10-19 14:42:29 -07003242
H. Peter Anvine2c80182005-01-15 22:15:51 +00003243 tline = tline->next;
3244 skip_white_(tline);
3245 tline = expand_id(tline);
3246 if (!tline || (tline->type != TOK_ID &&
3247 (tline->type != TOK_PREPROC_ID ||
3248 tline->text[1] != '$'))) {
3249 error(ERR_NONFATAL,
3250 "`%%strlen' expects a macro identifier as first parameter");
3251 free_tlist(origline);
3252 return DIRECTIVE_FOUND;
3253 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003254 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003255 last = tline;
3256 tline = expand_smacro(tline->next);
3257 last->next = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003258
H. Peter Anvine2c80182005-01-15 22:15:51 +00003259 t = tline;
3260 while (tok_type_(t, TOK_WHITESPACE))
3261 t = t->next;
3262 /* t should now point to the string */
Cyrill Gorcunov4e1d5ab2010-07-23 18:51:51 +04003263 if (!tok_type_(t, TOK_STRING)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003264 error(ERR_NONFATAL,
3265 "`%%strlen` requires string as second parameter");
3266 free_tlist(tline);
3267 free_tlist(origline);
3268 return DIRECTIVE_FOUND;
3269 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003270
H. Peter Anvine2c80182005-01-15 22:15:51 +00003271 macro_start = nasm_malloc(sizeof(*macro_start));
3272 macro_start->next = NULL;
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003273 make_tok_num(macro_start, nasm_unquote(t->text, NULL));
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003274 macro_start->a.mac = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003275
H. Peter Anvine2c80182005-01-15 22:15:51 +00003276 /*
3277 * We now have a macro name, an implicit parameter count of
3278 * zero, and a numeric token to use as an expansion. Create
3279 * and store an SMacro.
3280 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003281 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003282 free_tlist(tline);
3283 free_tlist(origline);
3284 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003285
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003286 case PP_STRCAT:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003287 casesense = true;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003288
3289 tline = tline->next;
3290 skip_white_(tline);
3291 tline = expand_id(tline);
3292 if (!tline || (tline->type != TOK_ID &&
3293 (tline->type != TOK_PREPROC_ID ||
3294 tline->text[1] != '$'))) {
3295 error(ERR_NONFATAL,
3296 "`%%strcat' expects a macro identifier as first parameter");
3297 free_tlist(origline);
3298 return DIRECTIVE_FOUND;
3299 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003300 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003301 last = tline;
3302 tline = expand_smacro(tline->next);
3303 last->next = NULL;
3304
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003305 len = 0;
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04003306 list_for_each(t, tline) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003307 switch (t->type) {
3308 case TOK_WHITESPACE:
3309 break;
3310 case TOK_STRING:
3311 len += t->a.len = nasm_unquote(t->text, NULL);
3312 break;
3313 case TOK_OTHER:
3314 if (!strcmp(t->text, ",")) /* permit comma separators */
3315 break;
3316 /* else fall through */
3317 default:
3318 error(ERR_NONFATAL,
3319 "non-string passed to `%%strcat' (%d)", t->type);
3320 free_tlist(tline);
3321 free_tlist(origline);
3322 return DIRECTIVE_FOUND;
3323 }
3324 }
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003325
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003326 p = pp = nasm_malloc(len);
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04003327 list_for_each(t, tline) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003328 if (t->type == TOK_STRING) {
3329 memcpy(p, t->text, t->a.len);
3330 p += t->a.len;
3331 }
3332 }
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003333
3334 /*
3335 * We now have a macro name, an implicit parameter count of
3336 * zero, and a numeric token to use as an expansion. Create
3337 * and store an SMacro.
3338 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003339 macro_start = new_Token(NULL, TOK_STRING, NULL, 0);
3340 macro_start->text = nasm_quote(pp, len);
3341 nasm_free(pp);
3342 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003343 free_tlist(tline);
3344 free_tlist(origline);
3345 return DIRECTIVE_FOUND;
3346
H. Peter Anvine2c80182005-01-15 22:15:51 +00003347 case PP_SUBSTR:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003348 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003349 int64_t a1, a2;
3350 size_t len;
H. Peter Anvind2456592008-06-19 15:04:18 -07003351
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003352 casesense = true;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003353
H. Peter Anvine2c80182005-01-15 22:15:51 +00003354 tline = tline->next;
3355 skip_white_(tline);
3356 tline = expand_id(tline);
3357 if (!tline || (tline->type != TOK_ID &&
3358 (tline->type != TOK_PREPROC_ID ||
3359 tline->text[1] != '$'))) {
3360 error(ERR_NONFATAL,
3361 "`%%substr' expects a macro identifier as first parameter");
3362 free_tlist(origline);
3363 return DIRECTIVE_FOUND;
3364 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003365 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003366 last = tline;
3367 tline = expand_smacro(tline->next);
3368 last->next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003369
H. Peter Anvine2c80182005-01-15 22:15:51 +00003370 t = tline->next;
3371 while (tok_type_(t, TOK_WHITESPACE))
3372 t = t->next;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003373
H. Peter Anvine2c80182005-01-15 22:15:51 +00003374 /* t should now point to the string */
3375 if (t->type != TOK_STRING) {
3376 error(ERR_NONFATAL,
3377 "`%%substr` requires string as second parameter");
3378 free_tlist(tline);
3379 free_tlist(origline);
3380 return DIRECTIVE_FOUND;
3381 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003382
H. Peter Anvine2c80182005-01-15 22:15:51 +00003383 tt = t->next;
3384 tptr = &tt;
3385 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003386 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003387 pass, error, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003388 if (!evalresult) {
3389 free_tlist(tline);
3390 free_tlist(origline);
3391 return DIRECTIVE_FOUND;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003392 } else if (!is_simple(evalresult)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003393 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3394 free_tlist(tline);
3395 free_tlist(origline);
3396 return DIRECTIVE_FOUND;
3397 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003398 a1 = evalresult->value-1;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003399
3400 while (tok_type_(tt, TOK_WHITESPACE))
3401 tt = tt->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003402 if (!tt) {
3403 a2 = 1; /* Backwards compatibility: one character */
3404 } else {
3405 tokval.t_type = TOKEN_INVALID;
3406 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3407 pass, error, NULL);
3408 if (!evalresult) {
3409 free_tlist(tline);
3410 free_tlist(origline);
3411 return DIRECTIVE_FOUND;
3412 } else if (!is_simple(evalresult)) {
3413 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3414 free_tlist(tline);
3415 free_tlist(origline);
3416 return DIRECTIVE_FOUND;
3417 }
3418 a2 = evalresult->value;
3419 }
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003420
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003421 len = nasm_unquote(t->text, NULL);
3422 if (a2 < 0)
3423 a2 = a2+1+len-a1;
3424 if (a1+a2 > (int64_t)len)
3425 a2 = len-a1;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003426
H. Peter Anvine2c80182005-01-15 22:15:51 +00003427 macro_start = nasm_malloc(sizeof(*macro_start));
3428 macro_start->next = NULL;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003429 macro_start->text = nasm_quote((a1 < 0) ? "" : t->text+a1, a2);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003430 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003431 macro_start->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003432
H. Peter Anvine2c80182005-01-15 22:15:51 +00003433 /*
3434 * We now have a macro name, an implicit parameter count of
3435 * zero, and a numeric token to use as an expansion. Create
3436 * and store an SMacro.
3437 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003438 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003439 free_tlist(tline);
3440 free_tlist(origline);
3441 return DIRECTIVE_FOUND;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003442 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003443
H. Peter Anvine2c80182005-01-15 22:15:51 +00003444 case PP_ASSIGN:
3445 case PP_IASSIGN:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003446 casesense = (i == PP_ASSIGN);
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003447
H. Peter Anvine2c80182005-01-15 22:15:51 +00003448 tline = tline->next;
3449 skip_white_(tline);
3450 tline = expand_id(tline);
3451 if (!tline || (tline->type != TOK_ID &&
3452 (tline->type != TOK_PREPROC_ID ||
3453 tline->text[1] != '$'))) {
3454 error(ERR_NONFATAL,
3455 "`%%%sassign' expects a macro identifier",
3456 (i == PP_IASSIGN ? "i" : ""));
3457 free_tlist(origline);
3458 return DIRECTIVE_FOUND;
3459 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003460 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003461 last = tline;
3462 tline = expand_smacro(tline->next);
3463 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003464
H. Peter Anvine2c80182005-01-15 22:15:51 +00003465 t = tline;
3466 tptr = &t;
3467 tokval.t_type = TOKEN_INVALID;
3468 evalresult =
3469 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3470 free_tlist(tline);
3471 if (!evalresult) {
3472 free_tlist(origline);
3473 return DIRECTIVE_FOUND;
3474 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003475
H. Peter Anvine2c80182005-01-15 22:15:51 +00003476 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07003477 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003478 "trailing garbage after expression ignored");
H. Peter Anvin734b1882002-04-30 21:01:08 +00003479
H. Peter Anvine2c80182005-01-15 22:15:51 +00003480 if (!is_simple(evalresult)) {
3481 error(ERR_NONFATAL,
3482 "non-constant value given to `%%%sassign'",
3483 (i == PP_IASSIGN ? "i" : ""));
3484 free_tlist(origline);
3485 return DIRECTIVE_FOUND;
3486 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003487
H. Peter Anvine2c80182005-01-15 22:15:51 +00003488 macro_start = nasm_malloc(sizeof(*macro_start));
3489 macro_start->next = NULL;
3490 make_tok_num(macro_start, reloc_value(evalresult));
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003491 macro_start->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003492
H. Peter Anvine2c80182005-01-15 22:15:51 +00003493 /*
3494 * We now have a macro name, an implicit parameter count of
3495 * zero, and a numeric token to use as an expansion. Create
3496 * and store an SMacro.
3497 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003498 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003499 free_tlist(origline);
3500 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003501
H. Peter Anvine2c80182005-01-15 22:15:51 +00003502 case PP_LINE:
3503 /*
3504 * Syntax is `%line nnn[+mmm] [filename]'
3505 */
3506 tline = tline->next;
3507 skip_white_(tline);
3508 if (!tok_type_(tline, TOK_NUMBER)) {
3509 error(ERR_NONFATAL, "`%%line' expects line number");
3510 free_tlist(origline);
3511 return DIRECTIVE_FOUND;
3512 }
H. Peter Anvin70055962007-10-11 00:05:31 -07003513 k = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003514 m = 1;
3515 tline = tline->next;
3516 if (tok_is_(tline, "+")) {
3517 tline = tline->next;
3518 if (!tok_type_(tline, TOK_NUMBER)) {
3519 error(ERR_NONFATAL, "`%%line' expects line increment");
3520 free_tlist(origline);
3521 return DIRECTIVE_FOUND;
3522 }
H. Peter Anvin70055962007-10-11 00:05:31 -07003523 m = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003524 tline = tline->next;
3525 }
3526 skip_white_(tline);
3527 src_set_linnum(k);
3528 istk->lineinc = m;
3529 if (tline) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003530 nasm_free(src_set_fname(detoken(tline, false)));
H. Peter Anvine2c80182005-01-15 22:15:51 +00003531 }
3532 free_tlist(origline);
3533 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003534
H. Peter Anvine2c80182005-01-15 22:15:51 +00003535 default:
3536 error(ERR_FATAL,
3537 "preprocessor directive `%s' not yet implemented",
H. Peter Anvin4169a472007-09-12 01:29:43 +00003538 pp_directives[i]);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003539 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003540 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003541}
3542
3543/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00003544 * Ensure that a macro parameter contains a condition code and
3545 * nothing else. Return the condition code index if so, or -1
3546 * otherwise.
3547 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003548static int find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003549{
H. Peter Anvin76690a12002-04-30 20:52:49 +00003550 Token *tt;
3551 int i, j, k, m;
3552
H. Peter Anvin25a99342007-09-22 17:45:45 -07003553 if (!t)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003554 return -1; /* Probably a %+ without a space */
H. Peter Anvin25a99342007-09-22 17:45:45 -07003555
H. Peter Anvineba20a72002-04-30 20:53:55 +00003556 skip_white_(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003557 if (t->type != TOK_ID)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003558 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003559 tt = t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003560 skip_white_(tt);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003561 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003562 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003563
3564 i = -1;
Cyrill Gorcunova7319242010-06-03 22:04:36 +04003565 j = ARRAY_SIZE(conditions);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003566 while (j - i > 1) {
3567 k = (j + i) / 2;
3568 m = nasm_stricmp(t->text, conditions[k]);
3569 if (m == 0) {
3570 i = k;
3571 j = -2;
3572 break;
3573 } else if (m < 0) {
3574 j = k;
3575 } else
3576 i = k;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003577 }
3578 if (j != -2)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003579 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003580 return i;
3581}
3582
H. Peter Anvind784a082009-04-20 14:01:18 -07003583static bool paste_tokens(Token **head, bool handle_paste_tokens)
3584{
3585 Token **tail, *t, *tt;
3586 Token **paste_head;
3587 bool did_paste = false;
3588 char *tmp;
3589
3590 /* Now handle token pasting... */
3591 paste_head = NULL;
3592 tail = head;
3593 while ((t = *tail) && (tt = t->next)) {
3594 switch (t->type) {
3595 case TOK_WHITESPACE:
3596 if (tt->type == TOK_WHITESPACE) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003597 /* Zap adjacent whitespace tokens */
H. Peter Anvind784a082009-04-20 14:01:18 -07003598 t->next = delete_Token(tt);
3599 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003600 /* Do not advance paste_head here */
3601 tail = &t->next;
3602 }
H. Peter Anvind784a082009-04-20 14:01:18 -07003603 break;
3604 case TOK_ID:
H. Peter Anvind784a082009-04-20 14:01:18 -07003605 case TOK_NUMBER:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003606 case TOK_FLOAT:
3607 {
3608 size_t len = 0;
3609 char *tmp, *p;
H. Peter Anvind784a082009-04-20 14:01:18 -07003610
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003611 while (tt && (tt->type == TOK_ID || tt->type == TOK_PREPROC_ID ||
3612 tt->type == TOK_NUMBER || tt->type == TOK_FLOAT ||
3613 tt->type == TOK_OTHER)) {
3614 len += strlen(tt->text);
3615 tt = tt->next;
3616 }
H. Peter Anvind784a082009-04-20 14:01:18 -07003617
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003618 /*
3619 * Now tt points to the first token after
3620 * the potential paste area...
3621 */
3622 if (tt != t->next) {
3623 /* We have at least two tokens... */
3624 len += strlen(t->text);
3625 p = tmp = nasm_malloc(len+1);
H. Peter Anvind784a082009-04-20 14:01:18 -07003626
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003627 while (t != tt) {
3628 strcpy(p, t->text);
3629 p = strchr(p, '\0');
3630 t = delete_Token(t);
3631 }
H. Peter Anvind784a082009-04-20 14:01:18 -07003632
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003633 t = *tail = tokenize(tmp);
3634 nasm_free(tmp);
H. Peter Anvind784a082009-04-20 14:01:18 -07003635
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003636 while (t->next) {
3637 tail = &t->next;
3638 t = t->next;
3639 }
3640 t->next = tt; /* Attach the remaining token chain */
H. Peter Anvind784a082009-04-20 14:01:18 -07003641
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003642 did_paste = true;
3643 }
3644 paste_head = tail;
3645 tail = &t->next;
3646 break;
3647 }
3648 case TOK_PASTE: /* %+ */
3649 if (handle_paste_tokens) {
3650 /* Zap %+ and whitespace tokens to the right */
3651 while (t && (t->type == TOK_WHITESPACE ||
3652 t->type == TOK_PASTE))
3653 t = *tail = delete_Token(t);
3654 if (!paste_head || !t)
3655 break; /* Nothing to paste with */
3656 tail = paste_head;
3657 t = *tail;
3658 tt = t->next;
3659 while (tok_type_(tt, TOK_WHITESPACE))
3660 tt = t->next = delete_Token(tt);
H. Peter Anvind784a082009-04-20 14:01:18 -07003661
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003662 if (tt) {
3663 tmp = nasm_strcat(t->text, tt->text);
3664 delete_Token(t);
3665 tt = delete_Token(tt);
3666 t = *tail = tokenize(tmp);
3667 nasm_free(tmp);
3668 while (t->next) {
3669 tail = &t->next;
3670 t = t->next;
3671 }
3672 t->next = tt; /* Attach the remaining token chain */
3673 did_paste = true;
3674 }
3675 paste_head = tail;
3676 tail = &t->next;
3677 break;
3678 }
3679 /* else fall through */
3680 default:
Cyrill Gorcunovadabc152010-07-10 02:11:41 +04003681 tail = &t->next;
3682 if (!tok_type_(t->next, TOK_WHITESPACE))
3683 paste_head = tail;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003684 break;
H. Peter Anvind784a082009-04-20 14:01:18 -07003685 }
3686 }
3687 return did_paste;
3688}
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003689
3690/*
3691 * expands to a list of tokens from %{x:y}
3692 */
3693static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
3694{
3695 Token *t = tline, **tt, *tm, *head;
3696 char *pos;
3697 int fst, lst, j, i;
3698
3699 pos = strchr(tline->text, ':');
3700 nasm_assert(pos);
3701
3702 lst = atoi(pos + 1);
3703 fst = atoi(tline->text + 1);
3704
3705 /*
3706 * only macros params are accounted so
3707 * if someone passes %0 -- we reject such
3708 * value(s)
3709 */
3710 if (lst == 0 || fst == 0)
3711 goto err;
3712
3713 /* the values should be sane */
Cyrill Gorcunov2f403752010-06-05 10:47:10 +04003714 if ((fst > (int)mac->nparam || fst < (-(int)mac->nparam)) ||
3715 (lst > (int)mac->nparam || lst < (-(int)mac->nparam)))
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003716 goto err;
3717
Cyrill Gorcunovefb35832010-06-20 01:52:19 +04003718 fst = fst < 0 ? fst + (int)mac->nparam + 1: fst;
3719 lst = lst < 0 ? lst + (int)mac->nparam + 1: lst;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003720
3721 /* counted from zero */
3722 fst--, lst--;
3723
3724 /*
3725 * it will be at least one token
3726 */
3727 tm = mac->params[(fst + mac->rotate) % mac->nparam];
3728 t = new_Token(NULL, tm->type, tm->text, 0);
3729 head = t, tt = &t->next;
3730 if (fst < lst) {
3731 for (i = fst + 1; i <= lst; i++) {
3732 t = new_Token(NULL, TOK_OTHER, ",", 0);
3733 *tt = t, tt = &t->next;
3734 j = (i + mac->rotate) % mac->nparam;
3735 tm = mac->params[j];
3736 t = new_Token(NULL, tm->type, tm->text, 0);
3737 *tt = t, tt = &t->next;
3738 }
3739 } else {
3740 for (i = fst - 1; i >= lst; i--) {
3741 t = new_Token(NULL, TOK_OTHER, ",", 0);
3742 *tt = t, tt = &t->next;
3743 j = (i + mac->rotate) % mac->nparam;
3744 tm = mac->params[j];
3745 t = new_Token(NULL, tm->type, tm->text, 0);
3746 *tt = t, tt = &t->next;
3747 }
3748 }
3749
3750 *last = tt;
3751 return head;
3752
3753err:
3754 error(ERR_NONFATAL, "`%%{%s}': macro parameters out of range",
3755 &tline->text[1]);
3756 return tline;
3757}
3758
H. Peter Anvin76690a12002-04-30 20:52:49 +00003759/*
3760 * Expand MMacro-local things: parameter references (%0, %n, %+n,
H. Peter Anvin67c63722008-10-26 23:49:00 -07003761 * %-n) and MMacro-local identifiers (%%foo) as well as
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003762 * macro indirection (%[...]) and range (%{..:..}).
H. Peter Anvin76690a12002-04-30 20:52:49 +00003763 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003764static Token *expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003765{
H. Peter Anvin734b1882002-04-30 21:01:08 +00003766 Token *t, *tt, **tail, *thead;
H. Peter Anvin6125b622009-04-08 14:02:25 -07003767 bool changed = false;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003768 char *pos;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003769
3770 tail = &thead;
3771 thead = NULL;
3772
H. Peter Anvine2c80182005-01-15 22:15:51 +00003773 while (tline) {
3774 if (tline->type == TOK_PREPROC_ID &&
Cyrill Gorcunovca611192010-06-04 09:22:12 +04003775 (((tline->text[1] == '+' || tline->text[1] == '-') && tline->text[2]) ||
3776 (tline->text[1] >= '0' && tline->text[1] <= '9') ||
3777 tline->text[1] == '%')) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003778 char *text = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003779 int type = 0, cc; /* type = 0 to placate optimisers */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003780 char tmpbuf[30];
H. Peter Anvin25a99342007-09-22 17:45:45 -07003781 unsigned int n;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003782 int i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003783 MMacro *mac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003784
H. Peter Anvine2c80182005-01-15 22:15:51 +00003785 t = tline;
3786 tline = tline->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003787
H. Peter Anvine2c80182005-01-15 22:15:51 +00003788 mac = istk->mstk;
3789 while (mac && !mac->name) /* avoid mistaking %reps for macros */
3790 mac = mac->next_active;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003791 if (!mac) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003792 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003793 } else {
3794 pos = strchr(t->text, ':');
3795 if (!pos) {
3796 switch (t->text[1]) {
3797 /*
3798 * We have to make a substitution of one of the
3799 * forms %1, %-1, %+1, %%foo, %0.
3800 */
3801 case '0':
3802 type = TOK_NUMBER;
3803 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
3804 text = nasm_strdup(tmpbuf);
3805 break;
3806 case '%':
H. Peter Anvine2c80182005-01-15 22:15:51 +00003807 type = TOK_ID;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003808 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
3809 mac->unique);
3810 text = nasm_strcat(tmpbuf, t->text + 2);
3811 break;
3812 case '-':
3813 n = atoi(t->text + 2) - 1;
3814 if (n >= mac->nparam)
3815 tt = NULL;
3816 else {
3817 if (mac->nparam > 1)
3818 n = (n + mac->rotate) % mac->nparam;
3819 tt = mac->params[n];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003820 }
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003821 cc = find_cc(tt);
3822 if (cc == -1) {
3823 error(ERR_NONFATAL,
3824 "macro parameter %d is not a condition code",
3825 n + 1);
3826 text = NULL;
3827 } else {
3828 type = TOK_ID;
3829 if (inverse_ccs[cc] == -1) {
3830 error(ERR_NONFATAL,
3831 "condition code `%s' is not invertible",
3832 conditions[cc]);
3833 text = NULL;
3834 } else
3835 text = nasm_strdup(conditions[inverse_ccs[cc]]);
3836 }
3837 break;
3838 case '+':
3839 n = atoi(t->text + 2) - 1;
3840 if (n >= mac->nparam)
3841 tt = NULL;
3842 else {
3843 if (mac->nparam > 1)
3844 n = (n + mac->rotate) % mac->nparam;
3845 tt = mac->params[n];
3846 }
3847 cc = find_cc(tt);
3848 if (cc == -1) {
3849 error(ERR_NONFATAL,
3850 "macro parameter %d is not a condition code",
3851 n + 1);
3852 text = NULL;
3853 } else {
3854 type = TOK_ID;
3855 text = nasm_strdup(conditions[cc]);
3856 }
3857 break;
3858 default:
3859 n = atoi(t->text + 1) - 1;
3860 if (n >= mac->nparam)
3861 tt = NULL;
3862 else {
3863 if (mac->nparam > 1)
3864 n = (n + mac->rotate) % mac->nparam;
3865 tt = mac->params[n];
3866 }
3867 if (tt) {
3868 for (i = 0; i < mac->paramlen[n]; i++) {
3869 *tail = new_Token(NULL, tt->type, tt->text, 0);
3870 tail = &(*tail)->next;
3871 tt = tt->next;
3872 }
3873 }
3874 text = NULL; /* we've done it here */
3875 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003876 }
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003877 } else {
3878 /*
3879 * seems we have a parameters range here
3880 */
3881 Token *head, **last;
3882 head = expand_mmac_params_range(mac, t, &last);
3883 if (head != t) {
3884 *tail = head;
3885 *last = tline;
3886 tline = head;
3887 text = NULL;
3888 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003889 }
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003890 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003891 if (!text) {
3892 delete_Token(t);
3893 } else {
3894 *tail = t;
3895 tail = &t->next;
3896 t->type = type;
3897 nasm_free(t->text);
3898 t->text = text;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003899 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003900 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003901 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003902 continue;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003903 } else if (tline->type == TOK_INDIRECT) {
3904 t = tline;
3905 tline = tline->next;
3906 tt = tokenize(t->text);
3907 tt = expand_mmac_params(tt);
3908 tt = expand_smacro(tt);
3909 *tail = tt;
3910 while (tt) {
3911 tt->a.mac = NULL; /* Necessary? */
3912 tail = &tt->next;
3913 tt = tt->next;
3914 }
3915 delete_Token(t);
3916 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003917 } else {
3918 t = *tail = tline;
3919 tline = tline->next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003920 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003921 tail = &t->next;
3922 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003923 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00003924 *tail = NULL;
H. Peter Anvin67c63722008-10-26 23:49:00 -07003925
H. Peter Anvind784a082009-04-20 14:01:18 -07003926 if (changed)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003927 paste_tokens(&thead, false);
H. Peter Anvin6125b622009-04-08 14:02:25 -07003928
H. Peter Anvin76690a12002-04-30 20:52:49 +00003929 return thead;
3930}
3931
3932/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003933 * Expand all single-line macro calls made in the given line.
3934 * Return the expanded version of the line. The original is deemed
3935 * to be destroyed in the process. (In reality we'll just move
3936 * Tokens from input to output a lot of the time, rather than
3937 * actually bothering to destroy and replicate.)
3938 */
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003939
H. Peter Anvine2c80182005-01-15 22:15:51 +00003940static Token *expand_smacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003941{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003942 Token *t, *tt, *mstart, **tail, *thead;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003943 SMacro *head = NULL, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003944 Token **params;
3945 int *paramsize;
H. Peter Anvin25a99342007-09-22 17:45:45 -07003946 unsigned int nparam, sparam;
H. Peter Anvind784a082009-04-20 14:01:18 -07003947 int brackets;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003948 Token *org_tline = tline;
3949 Context *ctx;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003950 const char *mname;
H. Peter Anvin2a15e692007-11-19 13:14:59 -08003951 int deadman = DEADMAN_LIMIT;
H. Peter Anvin8287daf2009-07-07 16:00:58 -07003952 bool expanded;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003953
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003954 /*
3955 * Trick: we should avoid changing the start token pointer since it can
3956 * be contained in "next" field of other token. Because of this
3957 * we allocate a copy of first token and work with it; at the end of
3958 * routine we copy it back
3959 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003960 if (org_tline) {
Cyrill Gorcunoved4a8052010-04-09 15:40:35 +04003961 tline = new_Token(org_tline->next, org_tline->type,
3962 org_tline->text, 0);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003963 tline->a.mac = org_tline->a.mac;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003964 nasm_free(org_tline->text);
3965 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003966 }
3967
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003968 expanded = true; /* Always expand %+ at least once */
H. Peter Anvin8287daf2009-07-07 16:00:58 -07003969
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003970again:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003971 thead = NULL;
Cyrill Gorcunoved4a8052010-04-09 15:40:35 +04003972 tail = &thead;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003973
H. Peter Anvine2c80182005-01-15 22:15:51 +00003974 while (tline) { /* main token loop */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003975 if (!--deadman) {
3976 error(ERR_NONFATAL, "interminable macro recursion");
Cyrill Gorcunovbd38c8f2009-11-21 11:11:23 +03003977 goto err;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003978 }
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003979
H. Peter Anvine2c80182005-01-15 22:15:51 +00003980 if ((mname = tline->text)) {
3981 /* if this token is a local macro, look in local context */
Cyrill Gorcunovc56d9ad2010-02-11 15:12:19 +03003982 if (tline->type == TOK_ID) {
3983 head = (SMacro *)hash_findix(&smacros, mname);
3984 } else if (tline->type == TOK_PREPROC_ID) {
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003985 ctx = get_ctx(mname, &mname, true);
Cyrill Gorcunovc56d9ad2010-02-11 15:12:19 +03003986 head = ctx ? (SMacro *)hash_findix(&ctx->localmac, mname) : NULL;
3987 } else
3988 head = NULL;
H. Peter Anvin072771e2008-05-22 13:17:51 -07003989
H. Peter Anvine2c80182005-01-15 22:15:51 +00003990 /*
3991 * We've hit an identifier. As in is_mmacro below, we first
3992 * check whether the identifier is a single-line macro at
3993 * all, then think about checking for parameters if
3994 * necessary.
3995 */
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04003996 list_for_each(m, head)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003997 if (!mstrcmp(m->name, mname, m->casesense))
3998 break;
3999 if (m) {
4000 mstart = tline;
4001 params = NULL;
4002 paramsize = NULL;
4003 if (m->nparam == 0) {
4004 /*
4005 * Simple case: the macro is parameterless. Discard the
4006 * one token that the macro call took, and push the
4007 * expansion back on the to-do stack.
4008 */
4009 if (!m->expansion) {
4010 if (!strcmp("__FILE__", m->name)) {
4011 int32_t num = 0;
4012 char *file = NULL;
4013 src_get(&num, &file);
4014 tline->text = nasm_quote(file, strlen(file));
4015 tline->type = TOK_STRING;
4016 nasm_free(file);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004017 continue;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004018 }
4019 if (!strcmp("__LINE__", m->name)) {
4020 nasm_free(tline->text);
4021 make_tok_num(tline, src_get_linnum());
4022 continue;
4023 }
4024 if (!strcmp("__BITS__", m->name)) {
4025 nasm_free(tline->text);
4026 make_tok_num(tline, globalbits);
4027 continue;
4028 }
4029 tline = delete_Token(tline);
4030 continue;
4031 }
4032 } else {
4033 /*
4034 * Complicated case: at least one macro with this name
H. Peter Anvine2c80182005-01-15 22:15:51 +00004035 * exists and takes parameters. We must find the
4036 * parameters in the call, count them, find the SMacro
4037 * that corresponds to that form of the macro call, and
4038 * substitute for the parameters when we expand. What a
4039 * pain.
4040 */
4041 /*tline = tline->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004042 skip_white_(tline); */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004043 do {
4044 t = tline->next;
4045 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004046 t->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004047 t->text = NULL;
4048 t = tline->next = delete_Token(t);
4049 }
4050 tline = t;
4051 } while (tok_type_(tline, TOK_WHITESPACE));
4052 if (!tok_is_(tline, "(")) {
4053 /*
4054 * This macro wasn't called with parameters: ignore
4055 * the call. (Behaviour borrowed from gnu cpp.)
4056 */
4057 tline = mstart;
4058 m = NULL;
4059 } else {
4060 int paren = 0;
4061 int white = 0;
4062 brackets = 0;
4063 nparam = 0;
4064 sparam = PARAM_DELTA;
4065 params = nasm_malloc(sparam * sizeof(Token *));
4066 params[0] = tline->next;
4067 paramsize = nasm_malloc(sparam * sizeof(int));
4068 paramsize[0] = 0;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004069 while (true) { /* parameter loop */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004070 /*
4071 * For some unusual expansions
4072 * which concatenates function call
4073 */
4074 t = tline->next;
4075 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004076 t->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004077 t->text = NULL;
4078 t = tline->next = delete_Token(t);
4079 }
4080 tline = t;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00004081
H. Peter Anvine2c80182005-01-15 22:15:51 +00004082 if (!tline) {
4083 error(ERR_NONFATAL,
4084 "macro call expects terminating `)'");
4085 break;
4086 }
4087 if (tline->type == TOK_WHITESPACE
4088 && brackets <= 0) {
4089 if (paramsize[nparam])
4090 white++;
4091 else
4092 params[nparam] = tline->next;
4093 continue; /* parameter loop */
4094 }
4095 if (tline->type == TOK_OTHER
4096 && tline->text[1] == 0) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004097 char ch = tline->text[0];
H. Peter Anvine2c80182005-01-15 22:15:51 +00004098 if (ch == ',' && !paren && brackets <= 0) {
4099 if (++nparam >= sparam) {
4100 sparam += PARAM_DELTA;
4101 params = nasm_realloc(params,
Cyrill Gorcunoved4a8052010-04-09 15:40:35 +04004102 sparam * sizeof(Token *));
4103 paramsize = nasm_realloc(paramsize,
4104 sparam * sizeof(int));
H. Peter Anvine2c80182005-01-15 22:15:51 +00004105 }
4106 params[nparam] = tline->next;
4107 paramsize[nparam] = 0;
4108 white = 0;
4109 continue; /* parameter loop */
4110 }
4111 if (ch == '{' &&
4112 (brackets > 0 || (brackets == 0 &&
4113 !paramsize[nparam])))
4114 {
4115 if (!(brackets++)) {
4116 params[nparam] = tline->next;
4117 continue; /* parameter loop */
4118 }
4119 }
4120 if (ch == '}' && brackets > 0)
4121 if (--brackets == 0) {
4122 brackets = -1;
4123 continue; /* parameter loop */
4124 }
4125 if (ch == '(' && !brackets)
4126 paren++;
4127 if (ch == ')' && brackets <= 0)
4128 if (--paren < 0)
4129 break;
4130 }
4131 if (brackets < 0) {
4132 brackets = 0;
4133 error(ERR_NONFATAL, "braces do not "
4134 "enclose all of macro parameter");
4135 }
4136 paramsize[nparam] += white + 1;
4137 white = 0;
4138 } /* parameter loop */
4139 nparam++;
4140 while (m && (m->nparam != nparam ||
4141 mstrcmp(m->name, mname,
4142 m->casesense)))
4143 m = m->next;
4144 if (!m)
H. Peter Anvin917a3492008-09-24 09:14:49 -07004145 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00004146 "macro `%s' exists, "
4147 "but not taking %d parameters",
4148 mstart->text, nparam);
4149 }
4150 }
4151 if (m && m->in_progress)
4152 m = NULL;
4153 if (!m) { /* in progess or didn't find '(' or wrong nparam */
H. Peter Anvin70653092007-10-19 14:42:29 -07004154 /*
H. Peter Anvine2c80182005-01-15 22:15:51 +00004155 * Design question: should we handle !tline, which
4156 * indicates missing ')' here, or expand those
4157 * macros anyway, which requires the (t) test a few
H. Peter Anvin70653092007-10-19 14:42:29 -07004158 * lines down?
H. Peter Anvine2c80182005-01-15 22:15:51 +00004159 */
4160 nasm_free(params);
4161 nasm_free(paramsize);
4162 tline = mstart;
4163 } else {
4164 /*
4165 * Expand the macro: we are placed on the last token of the
4166 * call, so that we can easily split the call from the
4167 * following tokens. We also start by pushing an SMAC_END
4168 * token for the cycle removal.
4169 */
4170 t = tline;
4171 if (t) {
4172 tline = t->next;
4173 t->next = NULL;
4174 }
4175 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004176 tt->a.mac = m;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004177 m->in_progress = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004178 tline = tt;
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04004179 list_for_each(t, m->expansion) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004180 if (t->type >= TOK_SMAC_PARAM) {
4181 Token *pcopy = tline, **ptail = &pcopy;
4182 Token *ttt, *pt;
4183 int i;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004184
H. Peter Anvine2c80182005-01-15 22:15:51 +00004185 ttt = params[t->type - TOK_SMAC_PARAM];
Cyrill Gorcunoved4a8052010-04-09 15:40:35 +04004186 i = paramsize[t->type - TOK_SMAC_PARAM];
4187 while (--i >= 0) {
4188 pt = *ptail = new_Token(tline, ttt->type,
4189 ttt->text, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004190 ptail = &pt->next;
4191 ttt = ttt->next;
4192 }
4193 tline = pcopy;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004194 } else if (t->type == TOK_PREPROC_Q) {
4195 tt = new_Token(tline, TOK_ID, mname, 0);
4196 tline = tt;
4197 } else if (t->type == TOK_PREPROC_QQ) {
4198 tt = new_Token(tline, TOK_ID, m->name, 0);
4199 tline = tt;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004200 } else {
4201 tt = new_Token(tline, t->type, t->text, 0);
4202 tline = tt;
4203 }
4204 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004205
H. Peter Anvine2c80182005-01-15 22:15:51 +00004206 /*
4207 * Having done that, get rid of the macro call, and clean
4208 * up the parameters.
4209 */
4210 nasm_free(params);
4211 nasm_free(paramsize);
4212 free_tlist(mstart);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004213 expanded = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004214 continue; /* main token loop */
4215 }
4216 }
4217 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004218
H. Peter Anvine2c80182005-01-15 22:15:51 +00004219 if (tline->type == TOK_SMAC_END) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004220 tline->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004221 tline = delete_Token(tline);
4222 } else {
4223 t = *tail = tline;
4224 tline = tline->next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004225 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004226 t->next = NULL;
4227 tail = &t->next;
4228 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004229 }
4230
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004231 /*
4232 * Now scan the entire line and look for successive TOK_IDs that resulted
Keith Kaniosb7a89542007-04-12 02:40:54 +00004233 * after expansion (they can't be produced by tokenize()). The successive
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004234 * TOK_IDs should be concatenated.
4235 * Also we look for %+ tokens and concatenate the tokens before and after
4236 * them (without white spaces in between).
4237 */
H. Peter Anvin8287daf2009-07-07 16:00:58 -07004238 if (expanded && paste_tokens(&thead, true)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004239 /*
4240 * If we concatenated something, *and* we had previously expanded
4241 * an actual macro, scan the lines again for macros...
4242 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004243 tline = thead;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004244 expanded = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004245 goto again;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004246 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004247
Cyrill Gorcunovbd38c8f2009-11-21 11:11:23 +03004248err:
H. Peter Anvine2c80182005-01-15 22:15:51 +00004249 if (org_tline) {
4250 if (thead) {
4251 *org_tline = *thead;
4252 /* since we just gave text to org_line, don't free it */
4253 thead->text = NULL;
4254 delete_Token(thead);
4255 } else {
4256 /* the expression expanded to empty line;
4257 we can't return NULL for some reasons
4258 we just set the line to a single WHITESPACE token. */
4259 memset(org_tline, 0, sizeof(*org_tline));
4260 org_tline->text = NULL;
4261 org_tline->type = TOK_WHITESPACE;
4262 }
4263 thead = org_tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004264 }
4265
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004266 return thead;
4267}
4268
4269/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004270 * Similar to expand_smacro but used exclusively with macro identifiers
4271 * right before they are fetched in. The reason is that there can be
4272 * identifiers consisting of several subparts. We consider that if there
4273 * are more than one element forming the name, user wants a expansion,
4274 * otherwise it will be left as-is. Example:
4275 *
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004276 * %define %$abc cde
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004277 *
4278 * the identifier %$abc will be left as-is so that the handler for %define
4279 * will suck it and define the corresponding value. Other case:
4280 *
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004281 * %define _%$abc cde
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004282 *
4283 * In this case user wants name to be expanded *before* %define starts
4284 * working, so we'll expand %$abc into something (if it has a value;
4285 * otherwise it will be left as-is) then concatenate all successive
4286 * PP_IDs into one.
4287 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004288static Token *expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004289{
4290 Token *cur, *oldnext = NULL;
4291
H. Peter Anvin734b1882002-04-30 21:01:08 +00004292 if (!tline || !tline->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004293 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004294
4295 cur = tline;
4296 while (cur->next &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00004297 (cur->next->type == TOK_ID ||
4298 cur->next->type == TOK_PREPROC_ID
4299 || cur->next->type == TOK_NUMBER))
4300 cur = cur->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004301
4302 /* If identifier consists of just one token, don't expand */
4303 if (cur == tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004304 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004305
H. Peter Anvine2c80182005-01-15 22:15:51 +00004306 if (cur) {
4307 oldnext = cur->next; /* Detach the tail past identifier */
4308 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004309 }
4310
H. Peter Anvin734b1882002-04-30 21:01:08 +00004311 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004312
H. Peter Anvine2c80182005-01-15 22:15:51 +00004313 if (cur) {
4314 /* expand_smacro possibly changhed tline; re-scan for EOL */
4315 cur = tline;
4316 while (cur && cur->next)
4317 cur = cur->next;
4318 if (cur)
4319 cur->next = oldnext;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004320 }
4321
4322 return tline;
4323}
4324
4325/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004326 * Determine whether the given line constitutes a multi-line macro
4327 * call, and return the MMacro structure called if so. Doesn't have
4328 * to check for an initial label - that's taken care of in
4329 * expand_mmacro - but must check numbers of parameters. Guaranteed
4330 * to be called with tline->type == TOK_ID, so the putative macro
4331 * name is easy to find.
4332 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004333static MMacro *is_mmacro(Token * tline, Token *** params_array)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004334{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004335 MMacro *head, *m;
4336 Token **params;
4337 int nparam;
4338
H. Peter Anvin166c2472008-05-28 12:28:58 -07004339 head = (MMacro *) hash_findix(&mmacros, tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004340
4341 /*
4342 * Efficiency: first we see if any macro exists with the given
4343 * name. If not, we can return NULL immediately. _Then_ we
4344 * count the parameters, and then we look further along the
4345 * list if necessary to find the proper MMacro.
4346 */
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04004347 list_for_each(m, head)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004348 if (!mstrcmp(m->name, tline->text, m->casesense))
4349 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004350 if (!m)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004351 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004352
4353 /*
4354 * OK, we have a potential macro. Count and demarcate the
4355 * parameters.
4356 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00004357 count_mmac_params(tline->next, &nparam, &params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004358
4359 /*
4360 * So we know how many parameters we've got. Find the MMacro
4361 * structure that handles this number.
4362 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004363 while (m) {
4364 if (m->nparam_min <= nparam
4365 && (m->plus || nparam <= m->nparam_max)) {
4366 /*
4367 * This one is right. Just check if cycle removal
4368 * prohibits us using it before we actually celebrate...
4369 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004370 if (m->in_progress > m->max_depth) {
4371 if (m->max_depth > 0) {
4372 error(ERR_WARNING,
4373 "reached maximum recursion depth of %i",
4374 m->max_depth);
4375 }
4376 nasm_free(params);
4377 return NULL;
4378 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004379 /*
4380 * It's right, and we can use it. Add its default
4381 * parameters to the end of our list if necessary.
4382 */
4383 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
4384 params =
4385 nasm_realloc(params,
4386 ((m->nparam_min + m->ndefs +
4387 1) * sizeof(*params)));
4388 while (nparam < m->nparam_min + m->ndefs) {
4389 params[nparam] = m->defaults[nparam - m->nparam_min];
4390 nparam++;
4391 }
4392 }
4393 /*
4394 * If we've gone over the maximum parameter count (and
4395 * we're in Plus mode), ignore parameters beyond
4396 * nparam_max.
4397 */
4398 if (m->plus && nparam > m->nparam_max)
4399 nparam = m->nparam_max;
4400 /*
4401 * Then terminate the parameter list, and leave.
4402 */
4403 if (!params) { /* need this special case */
4404 params = nasm_malloc(sizeof(*params));
4405 nparam = 0;
4406 }
4407 params[nparam] = NULL;
4408 *params_array = params;
4409 return m;
4410 }
4411 /*
4412 * This one wasn't right: look for the next one with the
4413 * same name.
4414 */
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04004415 list_for_each(m, m->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004416 if (!mstrcmp(m->name, tline->text, m->casesense))
4417 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004418 }
4419
4420 /*
4421 * After all that, we didn't find one with the right number of
4422 * parameters. Issue a warning, and fail to expand the macro.
4423 */
H. Peter Anvin917a3492008-09-24 09:14:49 -07004424 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00004425 "macro `%s' exists, but not taking %d parameters",
4426 tline->text, nparam);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004427 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004428 return NULL;
4429}
4430
Keith Kanios891775e2009-07-11 06:08:54 -05004431
4432/*
4433 * Save MMacro invocation specific fields in
4434 * preparation for a recursive macro expansion
4435 */
4436static void push_mmacro(MMacro *m)
4437{
4438 MMacroInvocation *i;
4439
H. Peter Anvin89cee572009-07-15 09:16:54 -04004440 i = nasm_malloc(sizeof(MMacroInvocation));
4441 i->prev = m->prev;
4442 i->params = m->params;
4443 i->iline = m->iline;
4444 i->nparam = m->nparam;
4445 i->rotate = m->rotate;
4446 i->paramlen = m->paramlen;
4447 i->unique = m->unique;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004448 i->condcnt = m->condcnt;
H. Peter Anvin89cee572009-07-15 09:16:54 -04004449 m->prev = i;
Keith Kanios891775e2009-07-11 06:08:54 -05004450}
4451
4452
4453/*
4454 * Restore MMacro invocation specific fields that were
4455 * saved during a previous recursive macro expansion
4456 */
4457static void pop_mmacro(MMacro *m)
4458{
4459 MMacroInvocation *i;
4460
H. Peter Anvin89cee572009-07-15 09:16:54 -04004461 if (m->prev) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004462 i = m->prev;
4463 m->prev = i->prev;
4464 m->params = i->params;
4465 m->iline = i->iline;
4466 m->nparam = i->nparam;
4467 m->rotate = i->rotate;
4468 m->paramlen = i->paramlen;
4469 m->unique = i->unique;
4470 m->condcnt = i->condcnt;
4471 nasm_free(i);
H. Peter Anvin89cee572009-07-15 09:16:54 -04004472 }
Keith Kanios891775e2009-07-11 06:08:54 -05004473}
4474
4475
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004476/*
4477 * Expand the multi-line macro call made by the given line, if
4478 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvineba20a72002-04-30 20:53:55 +00004479 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004480 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004481static int expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004482{
4483 Token *startline = tline;
4484 Token *label = NULL;
4485 int dont_prepend = 0;
H. Peter Anvince2233b2008-05-25 21:57:00 -07004486 Token **params, *t, *mtok, *tt;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004487 MMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004488 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004489 int i, nparam, *paramlen;
H. Peter Anvinc751e862008-06-09 10:18:45 -07004490 const char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004491
4492 t = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004493 skip_white_(t);
H. Peter Anvince2233b2008-05-25 21:57:00 -07004494 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00004495 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004496 return 0;
H. Peter Anvince2233b2008-05-25 21:57:00 -07004497 mtok = t;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004498 m = is_mmacro(t, &params);
H. Peter Anvinc751e862008-06-09 10:18:45 -07004499 if (m) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004500 mname = t->text;
H. Peter Anvinc751e862008-06-09 10:18:45 -07004501 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004502 Token *last;
4503 /*
4504 * We have an id which isn't a macro call. We'll assume
4505 * it might be a label; we'll also check to see if a
4506 * colon follows it. Then, if there's another id after
4507 * that lot, we'll check it again for macro-hood.
4508 */
4509 label = last = t;
4510 t = t->next;
4511 if (tok_type_(t, TOK_WHITESPACE))
4512 last = t, t = t->next;
4513 if (tok_is_(t, ":")) {
4514 dont_prepend = 1;
4515 last = t, t = t->next;
4516 if (tok_type_(t, TOK_WHITESPACE))
4517 last = t, t = t->next;
4518 }
H. Peter Anvin89cee572009-07-15 09:16:54 -04004519 if (!tok_type_(t, TOK_ID) || !(m = is_mmacro(t, &params)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004520 return 0;
4521 last->next = NULL;
Keith Kanios891775e2009-07-11 06:08:54 -05004522 mname = t->text;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004523 tline = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004524 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004525
4526 /*
4527 * Fix up the parameters: this involves stripping leading and
4528 * trailing whitespace, then stripping braces if they are
4529 * present.
4530 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004531 for (nparam = 0; params[nparam]; nparam++) ;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004532 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004533
H. Peter Anvine2c80182005-01-15 22:15:51 +00004534 for (i = 0; params[i]; i++) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004535 int brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004536 int comma = (!m->plus || i < nparam - 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004537
H. Peter Anvine2c80182005-01-15 22:15:51 +00004538 t = params[i];
4539 skip_white_(t);
4540 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004541 t = t->next, brace = true, comma = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004542 params[i] = t;
4543 paramlen[i] = 0;
4544 while (t) {
4545 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
4546 break; /* ... because we have hit a comma */
4547 if (comma && t->type == TOK_WHITESPACE
4548 && tok_is_(t->next, ","))
4549 break; /* ... or a space then a comma */
4550 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
4551 break; /* ... or a brace */
4552 t = t->next;
4553 paramlen[i]++;
4554 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004555 }
4556
4557 /*
4558 * OK, we have a MMacro structure together with a set of
4559 * parameters. We must now go through the expansion and push
H. Peter Anvin76690a12002-04-30 20:52:49 +00004560 * copies of each Line on to istk->expansion. Substitution of
4561 * parameter tokens and macro-local tokens doesn't get done
4562 * until the single-line macro substitution process; this is
4563 * because delaying them allows us to change the semantics
4564 * later through %rotate.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004565 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00004566 * First, push an end marker on to istk->expansion, mark this
4567 * macro as in progress, and set up its invocation-specific
4568 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004569 */
4570 ll = nasm_malloc(sizeof(Line));
4571 ll->next = istk->expansion;
4572 ll->finishes = m;
4573 ll->first = NULL;
4574 istk->expansion = ll;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004575
H. Peter Anvin89cee572009-07-15 09:16:54 -04004576 /*
4577 * Save the previous MMacro expansion in the case of
4578 * macro recursion
4579 */
4580 if (m->max_depth && m->in_progress)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004581 push_mmacro(m);
H. Peter Anvin76690a12002-04-30 20:52:49 +00004582
Keith Kanios891775e2009-07-11 06:08:54 -05004583 m->in_progress ++;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004584 m->params = params;
4585 m->iline = tline;
4586 m->nparam = nparam;
4587 m->rotate = 0;
4588 m->paramlen = paramlen;
4589 m->unique = unique++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004590 m->lineno = 0;
Keith Kanios3c0d91f2009-10-25 13:28:03 -05004591 m->condcnt = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004592
4593 m->next_active = istk->mstk;
4594 istk->mstk = m;
4595
Cyrill Gorcunov367d59e2010-04-09 15:43:03 +04004596 list_for_each(l, m->expansion) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004597 Token **tail;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004598
H. Peter Anvine2c80182005-01-15 22:15:51 +00004599 ll = nasm_malloc(sizeof(Line));
4600 ll->finishes = NULL;
4601 ll->next = istk->expansion;
4602 istk->expansion = ll;
4603 tail = &ll->first;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004604
Cyrill Gorcunov367d59e2010-04-09 15:43:03 +04004605 list_for_each(t, l->first) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004606 Token *x = t;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004607 switch (t->type) {
4608 case TOK_PREPROC_Q:
4609 tt = *tail = new_Token(NULL, TOK_ID, mname, 0);
4610 break;
4611 case TOK_PREPROC_QQ:
4612 tt = *tail = new_Token(NULL, TOK_ID, m->name, 0);
4613 break;
4614 case TOK_PREPROC_ID:
4615 if (t->text[1] == '0' && t->text[2] == '0') {
4616 dont_prepend = -1;
4617 x = label;
4618 if (!x)
4619 continue;
4620 }
4621 /* fall through */
4622 default:
4623 tt = *tail = new_Token(NULL, x->type, x->text, 0);
4624 break;
4625 }
4626 tail = &tt->next;
4627 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004628 *tail = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004629 }
4630
4631 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00004632 * If we had a label, push it on as the first line of
4633 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004634 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004635 if (label) {
4636 if (dont_prepend < 0)
4637 free_tlist(startline);
4638 else {
4639 ll = nasm_malloc(sizeof(Line));
4640 ll->finishes = NULL;
4641 ll->next = istk->expansion;
4642 istk->expansion = ll;
4643 ll->first = startline;
4644 if (!dont_prepend) {
4645 while (label->next)
4646 label = label->next;
4647 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
4648 }
4649 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004650 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004651
H. Peter Anvin734b1882002-04-30 21:01:08 +00004652 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004653
H. Peter Anvineba20a72002-04-30 20:53:55 +00004654 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004655}
4656
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004657/* The function that actually does the error reporting */
4658static void verror(int severity, const char *fmt, va_list arg)
4659{
4660 char buff[1024];
4661
4662 vsnprintf(buff, sizeof(buff), fmt, arg);
4663
4664 if (istk && istk->mstk && istk->mstk->name)
H. Peter Anvindbb640b2009-07-18 18:57:16 -07004665 nasm_error(severity, "(%s:%d) %s", istk->mstk->name,
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004666 istk->mstk->lineno, buff);
4667 else
H. Peter Anvindbb640b2009-07-18 18:57:16 -07004668 nasm_error(severity, "%s", buff);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004669}
4670
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004671/*
4672 * Since preprocessor always operate only on the line that didn't
H. Peter Anvin917a3492008-09-24 09:14:49 -07004673 * arrived yet, we should always use ERR_OFFBY1.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004674 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004675static void error(int severity, const char *fmt, ...)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004676{
4677 va_list arg;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004678
4679 /* If we're in a dead branch of IF or something like it, ignore the error */
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00004680 if (istk && istk->conds && !emitting(istk->conds->state))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004681 return;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004682
H. Peter Anvin734b1882002-04-30 21:01:08 +00004683 va_start(arg, fmt);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004684 verror(severity, fmt, arg);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004685 va_end(arg);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004686}
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004687
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004688/*
4689 * Because %else etc are evaluated in the state context
4690 * of the previous branch, errors might get lost with error():
4691 * %if 0 ... %else trailing garbage ... %endif
4692 * So %else etc should report errors with this function.
4693 */
4694static void error_precond(int severity, const char *fmt, ...)
4695{
4696 va_list arg;
4697
4698 /* Only ignore the error if it's really in a dead branch */
4699 if (istk && istk->conds && istk->conds->state == COND_NEVER)
4700 return;
4701
4702 va_start(arg, fmt);
4703 verror(severity, fmt, arg);
4704 va_end(arg);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004705}
4706
H. Peter Anvin734b1882002-04-30 21:01:08 +00004707static void
H. Peter Anvindbb640b2009-07-18 18:57:16 -07004708pp_reset(char *file, int apass, ListGen * listgen, StrList **deplist)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004709{
H. Peter Anvin7383b402008-09-24 10:20:40 -07004710 Token *t;
4711
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004712 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004713 istk = nasm_malloc(sizeof(Include));
4714 istk->next = NULL;
4715 istk->conds = NULL;
4716 istk->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004717 istk->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004718 istk->fp = fopen(file, "r");
H. Peter Anvineba20a72002-04-30 20:53:55 +00004719 istk->fname = NULL;
4720 src_set_fname(nasm_strdup(file));
4721 src_set_linnum(0);
4722 istk->lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004723 if (!istk->fp)
H. Peter Anvin917a3492008-09-24 09:14:49 -07004724 error(ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'",
H. Peter Anvine2c80182005-01-15 22:15:51 +00004725 file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004726 defining = NULL;
Charles Crayned4200be2008-07-12 16:42:33 -07004727 nested_mac_count = 0;
4728 nested_rep_count = 0;
H. Peter Anvin97a23472007-09-16 17:57:25 -07004729 init_macros();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004730 unique = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004731 if (tasm_compatible_mode) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07004732 stdmacpos = nasm_stdmac;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004733 } else {
H. Peter Anvina4835d42008-05-20 14:21:29 -07004734 stdmacpos = nasm_stdmac_after_tasm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004735 }
H. Peter Anvind2456592008-06-19 15:04:18 -07004736 any_extrastdmac = extrastdmac && *extrastdmac;
4737 do_predef = true;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004738 list = listgen;
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004739
4740 /*
4741 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4742 * The caller, however, will also pass in 3 for preprocess-only so
4743 * we can set __PASS__ accordingly.
4744 */
4745 pass = apass > 2 ? 2 : apass;
4746
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07004747 dephead = deptail = deplist;
4748 if (deplist) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004749 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
4750 sl->next = NULL;
4751 strcpy(sl->str, file);
4752 *deptail = sl;
4753 deptail = &sl->next;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07004754 }
H. Peter Anvin7383b402008-09-24 10:20:40 -07004755
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004756 /*
4757 * Define the __PASS__ macro. This is defined here unlike
4758 * all the other builtins, because it is special -- it varies between
4759 * passes.
4760 */
H. Peter Anvin7383b402008-09-24 10:20:40 -07004761 t = nasm_malloc(sizeof(*t));
4762 t->next = NULL;
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004763 make_tok_num(t, apass);
H. Peter Anvin7383b402008-09-24 10:20:40 -07004764 t->a.mac = NULL;
4765 define_smacro(NULL, "__PASS__", true, 0, t);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004766}
4767
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004768static char *pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004769{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004770 char *line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004771 Token *tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004772
H. Peter Anvine2c80182005-01-15 22:15:51 +00004773 while (1) {
4774 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00004775 * Fetch a tokenized line, either from the macro-expansion
H. Peter Anvine2c80182005-01-15 22:15:51 +00004776 * buffer or from the input file.
4777 */
4778 tline = NULL;
4779 while (istk->expansion && istk->expansion->finishes) {
4780 Line *l = istk->expansion;
4781 if (!l->finishes->name && l->finishes->in_progress > 1) {
4782 Line *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004783
H. Peter Anvine2c80182005-01-15 22:15:51 +00004784 /*
4785 * This is a macro-end marker for a macro with no
4786 * name, which means it's not really a macro at all
4787 * but a %rep block, and the `in_progress' field is
4788 * more than 1, meaning that we still need to
4789 * repeat. (1 means the natural last repetition; 0
4790 * means termination by %exitrep.) We have
4791 * therefore expanded up to the %endrep, and must
4792 * push the whole block on to the expansion buffer
4793 * again. We don't bother to remove the macro-end
4794 * marker: we'd only have to generate another one
4795 * if we did.
4796 */
4797 l->finishes->in_progress--;
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04004798 list_for_each(l, l->finishes->expansion) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004799 Token *t, *tt, **tail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004800
H. Peter Anvine2c80182005-01-15 22:15:51 +00004801 ll = nasm_malloc(sizeof(Line));
4802 ll->next = istk->expansion;
4803 ll->finishes = NULL;
4804 ll->first = NULL;
4805 tail = &ll->first;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004806
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04004807 list_for_each(t, l->first) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004808 if (t->text || t->type == TOK_WHITESPACE) {
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04004809 tt = *tail = new_Token(NULL, t->type, t->text, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004810 tail = &tt->next;
4811 }
4812 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004813
H. Peter Anvine2c80182005-01-15 22:15:51 +00004814 istk->expansion = ll;
4815 }
4816 } else {
4817 /*
4818 * Check whether a `%rep' was started and not ended
4819 * within this macro expansion. This can happen and
4820 * should be detected. It's a fatal error because
4821 * I'm too confused to work out how to recover
4822 * sensibly from it.
4823 */
4824 if (defining) {
4825 if (defining->name)
4826 error(ERR_PANIC,
4827 "defining with name in expansion");
4828 else if (istk->mstk->name)
4829 error(ERR_FATAL,
4830 "`%%rep' without `%%endrep' within"
4831 " expansion of macro `%s'",
4832 istk->mstk->name);
4833 }
H. Peter Anvin87bc6192002-04-30 20:53:16 +00004834
H. Peter Anvine2c80182005-01-15 22:15:51 +00004835 /*
4836 * FIXME: investigate the relationship at this point between
4837 * istk->mstk and l->finishes
4838 */
4839 {
4840 MMacro *m = istk->mstk;
4841 istk->mstk = m->next_active;
4842 if (m->name) {
4843 /*
4844 * This was a real macro call, not a %rep, and
4845 * therefore the parameter information needs to
4846 * be freed.
4847 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004848 if (m->prev) {
4849 pop_mmacro(m);
4850 l->finishes->in_progress --;
4851 } else {
Keith Kanios891775e2009-07-11 06:08:54 -05004852 nasm_free(m->params);
4853 free_tlist(m->iline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004854 nasm_free(m->paramlen);
4855 l->finishes->in_progress = 0;
4856 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004857 } else
4858 free_mmacro(m);
4859 }
4860 istk->expansion = l->next;
4861 nasm_free(l);
4862 list->downlevel(LIST_MACRO);
4863 }
4864 }
4865 while (1) { /* until we get a line we can use */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004866
H. Peter Anvine2c80182005-01-15 22:15:51 +00004867 if (istk->expansion) { /* from a macro expansion */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004868 char *p;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004869 Line *l = istk->expansion;
4870 if (istk->mstk)
4871 istk->mstk->lineno++;
4872 tline = l->first;
4873 istk->expansion = l->next;
4874 nasm_free(l);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004875 p = detoken(tline, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004876 list->line(LIST_MACRO, p);
4877 nasm_free(p);
4878 break;
4879 }
4880 line = read_line();
4881 if (line) { /* from the current input file */
4882 line = prepreproc(line);
Keith Kaniosb7a89542007-04-12 02:40:54 +00004883 tline = tokenize(line);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004884 nasm_free(line);
4885 break;
4886 }
4887 /*
4888 * The current file has ended; work down the istk
4889 */
4890 {
4891 Include *i = istk;
4892 fclose(i->fp);
4893 if (i->conds)
4894 error(ERR_FATAL,
4895 "expected `%%endif' before end of file");
4896 /* only set line and file name if there's a next node */
4897 if (i->next) {
4898 src_set_linnum(i->lineno);
4899 nasm_free(src_set_fname(i->fname));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004900 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004901 istk = i->next;
4902 list->downlevel(LIST_INCLUDE);
4903 nasm_free(i);
4904 if (!istk)
4905 return NULL;
Victor van den Elzen4c9d6222008-10-01 13:08:50 +02004906 if (istk->expansion && istk->expansion->finishes)
4907 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004908 }
4909 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004910
H. Peter Anvine2c80182005-01-15 22:15:51 +00004911 /*
4912 * We must expand MMacro parameters and MMacro-local labels
4913 * _before_ we plunge into directive processing, to cope
4914 * with things like `%define something %1' such as STRUC
4915 * uses. Unless we're _defining_ a MMacro, in which case
4916 * those tokens should be left alone to go into the
4917 * definition; and unless we're in a non-emitting
4918 * condition, in which case we don't want to meddle with
4919 * anything.
4920 */
Charles Crayned4200be2008-07-12 16:42:33 -07004921 if (!defining && !(istk->conds && !emitting(istk->conds->state))
H. Peter Anvin992fe752008-10-19 15:45:05 -07004922 && !(istk->mstk && !istk->mstk->in_progress)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004923 tline = expand_mmac_params(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004924 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004925
H. Peter Anvine2c80182005-01-15 22:15:51 +00004926 /*
4927 * Check the line to see if it's a preprocessor directive.
4928 */
4929 if (do_directive(tline) == DIRECTIVE_FOUND) {
4930 continue;
4931 } else if (defining) {
4932 /*
4933 * We're defining a multi-line macro. We emit nothing
4934 * at all, and just
Keith Kaniosb7a89542007-04-12 02:40:54 +00004935 * shove the tokenized line on to the macro definition.
H. Peter Anvine2c80182005-01-15 22:15:51 +00004936 */
4937 Line *l = nasm_malloc(sizeof(Line));
4938 l->next = defining->expansion;
4939 l->first = tline;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004940 l->finishes = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004941 defining->expansion = l;
4942 continue;
4943 } else if (istk->conds && !emitting(istk->conds->state)) {
4944 /*
4945 * We're in a non-emitting branch of a condition block.
4946 * Emit nothing at all, not even a blank line: when we
4947 * emerge from the condition we'll give a line-number
4948 * directive so we keep our place correctly.
4949 */
4950 free_tlist(tline);
4951 continue;
4952 } else if (istk->mstk && !istk->mstk->in_progress) {
4953 /*
4954 * We're in a %rep block which has been terminated, so
4955 * we're walking through to the %endrep without
4956 * emitting anything. Emit nothing at all, not even a
4957 * blank line: when we emerge from the %rep block we'll
4958 * give a line-number directive so we keep our place
4959 * correctly.
4960 */
4961 free_tlist(tline);
4962 continue;
4963 } else {
4964 tline = expand_smacro(tline);
4965 if (!expand_mmacro(tline)) {
4966 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00004967 * De-tokenize the line again, and emit it.
H. Peter Anvine2c80182005-01-15 22:15:51 +00004968 */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004969 line = detoken(tline, true);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004970 free_tlist(tline);
4971 break;
4972 } else {
4973 continue; /* expand_mmacro calls free_tlist */
4974 }
4975 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004976 }
4977
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004978 return line;
4979}
4980
H. Peter Anvine2c80182005-01-15 22:15:51 +00004981static void pp_cleanup(int pass)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004982{
H. Peter Anvine2c80182005-01-15 22:15:51 +00004983 if (defining) {
H. Peter Anvin89cee572009-07-15 09:16:54 -04004984 if (defining->name) {
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02004985 error(ERR_NONFATAL,
4986 "end of file while still defining macro `%s'",
4987 defining->name);
4988 } else {
4989 error(ERR_NONFATAL, "end of file while still in %%rep");
4990 }
4991
H. Peter Anvine2c80182005-01-15 22:15:51 +00004992 free_mmacro(defining);
Cyrill Gorcunova327c652010-02-14 17:19:38 +03004993 defining = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004994 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004995 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004996 ctx_pop();
H. Peter Anvin97a23472007-09-16 17:57:25 -07004997 free_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00004998 while (istk) {
4999 Include *i = istk;
5000 istk = istk->next;
5001 fclose(i->fp);
5002 nasm_free(i->fname);
5003 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005004 }
5005 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005006 ctx_pop();
H. Peter Anvin86877b22008-06-20 15:55:45 -07005007 nasm_free(src_set_fname(NULL));
H. Peter Anvine2c80182005-01-15 22:15:51 +00005008 if (pass == 0) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03005009 IncPath *i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005010 free_llist(predef);
5011 delete_Blocks();
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03005012 while ((i = ipath)) {
5013 ipath = i->next;
5014 if (i->path)
5015 nasm_free(i->path);
5016 nasm_free(i);
5017 }
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07005018 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005019}
5020
Keith Kaniosa6dfa782007-04-13 16:47:53 +00005021void pp_include_path(char *path)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005022{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005023 IncPath *i;
H. Peter Anvin37a321f2007-09-24 13:41:58 -07005024
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005025 i = nasm_malloc(sizeof(IncPath));
H. Peter Anvin37a321f2007-09-24 13:41:58 -07005026 i->path = path ? nasm_strdup(path) : NULL;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00005027 i->next = NULL;
5028
H. Peter Anvin89cee572009-07-15 09:16:54 -04005029 if (ipath) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00005030 IncPath *j = ipath;
H. Peter Anvin89cee572009-07-15 09:16:54 -04005031 while (j->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005032 j = j->next;
5033 j->next = i;
5034 } else {
5035 ipath = i;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00005036 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005037}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00005038
Keith Kaniosa6dfa782007-04-13 16:47:53 +00005039void pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005040{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005041 Token *inc, *space, *name;
5042 Line *l;
5043
H. Peter Anvin734b1882002-04-30 21:01:08 +00005044 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
5045 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
5046 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005047
5048 l = nasm_malloc(sizeof(Line));
5049 l->next = predef;
5050 l->first = inc;
H. Peter Anvin538002d2008-06-28 18:30:27 -07005051 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005052 predef = l;
5053}
5054
Keith Kaniosa6dfa782007-04-13 16:47:53 +00005055void pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005056{
5057 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005058 Line *l;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00005059 char *equals;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005060
5061 equals = strchr(definition, '=');
H. Peter Anvin734b1882002-04-30 21:01:08 +00005062 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
5063 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005064 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005065 *equals = ' ';
Keith Kaniosb7a89542007-04-12 02:40:54 +00005066 space->next = tokenize(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005067 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005068 *equals = '=';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005069
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005070 l = nasm_malloc(sizeof(Line));
5071 l->next = predef;
5072 l->first = def;
H. Peter Anvin538002d2008-06-28 18:30:27 -07005073 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005074 predef = l;
5075}
5076
Keith Kaniosa6dfa782007-04-13 16:47:53 +00005077void pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00005078{
5079 Token *def, *space;
5080 Line *l;
5081
H. Peter Anvin734b1882002-04-30 21:01:08 +00005082 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
5083 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Keith Kaniosb7a89542007-04-12 02:40:54 +00005084 space->next = tokenize(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00005085
5086 l = nasm_malloc(sizeof(Line));
5087 l->next = predef;
5088 l->first = def;
H. Peter Anvin538002d2008-06-28 18:30:27 -07005089 l->finishes = NULL;
H. Peter Anvin620515a2002-04-30 20:57:38 +00005090 predef = l;
5091}
5092
Keith Kaniosb7a89542007-04-12 02:40:54 +00005093/*
5094 * Added by Keith Kanios:
5095 *
5096 * This function is used to assist with "runtime" preprocessor
5097 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
5098 *
5099 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
5100 * PASS A VALID STRING TO THIS FUNCTION!!!!!
5101 */
5102
Keith Kaniosa6dfa782007-04-13 16:47:53 +00005103void pp_runtime(char *definition)
Keith Kaniosb7a89542007-04-12 02:40:54 +00005104{
5105 Token *def;
H. Peter Anvin70653092007-10-19 14:42:29 -07005106
Keith Kaniosb7a89542007-04-12 02:40:54 +00005107 def = tokenize(definition);
H. Peter Anvin89cee572009-07-15 09:16:54 -04005108 if (do_directive(def) == NO_DIRECTIVE_FOUND)
Keith Kaniosb7a89542007-04-12 02:40:54 +00005109 free_tlist(def);
H. Peter Anvin70653092007-10-19 14:42:29 -07005110
Keith Kaniosb7a89542007-04-12 02:40:54 +00005111}
5112
H. Peter Anvina70547f2008-07-19 21:44:26 -07005113void pp_extra_stdmac(macros_t *macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005114{
H. Peter Anvin76690a12002-04-30 20:52:49 +00005115 extrastdmac = macros;
5116}
5117
Keith Kaniosa5fc6462007-10-13 07:09:22 -07005118static void make_tok_num(Token * tok, int64_t val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005119{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00005120 char numbuf[20];
Keith Kaniosa5fc6462007-10-13 07:09:22 -07005121 snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
H. Peter Anvineba20a72002-04-30 20:53:55 +00005122 tok->text = nasm_strdup(numbuf);
5123 tok->type = TOK_NUMBER;
5124}
5125
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005126Preproc nasmpp = {
5127 pp_reset,
5128 pp_getline,
5129 pp_cleanup
5130};