blob: 6af2ac64a90de7cadf83eb779e82a4b50127c166 [file] [log] [blame]
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07001/* ----------------------------------------------------------------------- *
2 *
3 * Copyright 1996-2009 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
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.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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;
H. Peter Anvin89cee572009-07-15 09:16:54 -0400135 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;
139 bool plus; /* is the last parameter greedy? */
140 bool nolist; /* is this macro listing-inhibited? */
Keith Kanios891775e2009-07-11 06:08:54 -0500141 int64_t in_progress; /* is this macro currently being expanded? */
H. Peter Anvin89cee572009-07-15 09:16:54 -0400142 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 */
Keith Kanios3c0d91f2009-10-25 13:28:03 -0500156 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,
H. Peter Anvind784a082009-04-20 14:01:18 -0700209 TOK_PASTE, /* %+ */
H. Peter Anvin9bb46df2009-04-07 21:59:24 -0700210 TOK_INDIRECT, /* %[...] */
H. Peter Anvin5b76fa22008-05-26 11:14:38 -0700211 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 {
219 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;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000264 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
321#define DIRECTIVE_FOUND 1
322
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
H. Peter Anvine2c80182005-01-15 22:15:51 +0000386static 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
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700389static 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,
452 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,
459 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 */
465#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
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000470/* Handle TASM specific directives, which do not contain a % in
471 * front of them. We do it here because I could not find any other
472 * place to do it for the moment, and it is a hack (ideally it would
473 * be nice to be able to use the NASM pre-processor to do it).
474 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000475static char *check_tasm_directive(char *line)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000476{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000477 int32_t i, j, k, m, len;
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400478 char *p, *q, *oldline, oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000479
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400480 p = nasm_skip_spaces(line);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000481
482 /* Binary search for the directive name */
483 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +0000484 j = elements(tasm_directives);
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400485 q = nasm_skip_word(p);
486 len = q - p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000487 if (len) {
488 oldchar = p[len];
489 p[len] = 0;
490 while (j - i > 1) {
491 k = (j + i) / 2;
492 m = nasm_stricmp(p, tasm_directives[k]);
493 if (m == 0) {
494 /* We have found a directive, so jam a % in front of it
495 * so that NASM will then recognise it as one if it's own.
496 */
497 p[len] = oldchar;
498 len = strlen(p);
499 oldline = line;
500 line = nasm_malloc(len + 2);
501 line[0] = '%';
502 if (k == TM_IFDIFI) {
H. Peter Anvin18f48792009-06-27 15:56:27 -0700503 /*
504 * NASM does not recognise IFDIFI, so we convert
505 * it to %if 0. This is not used in NASM
506 * compatible code, but does need to parse for the
507 * TASM macro package.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000508 */
H. Peter Anvin18f48792009-06-27 15:56:27 -0700509 strcpy(line + 1, "if 0");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000510 } else {
511 memcpy(line + 1, p, len + 1);
512 }
513 nasm_free(oldline);
514 return line;
515 } else if (m < 0) {
516 j = k;
517 } else
518 i = k;
519 }
520 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000521 }
522 return line;
523}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000524
H. Peter Anvin76690a12002-04-30 20:52:49 +0000525/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000526 * The pre-preprocessing stage... This function translates line
527 * number indications as they emerge from GNU cpp (`# lineno "file"
528 * flags') into NASM preprocessor line number indications (`%line
529 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000530 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000531static char *prepreproc(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000532{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000533 int lineno, fnlen;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000534 char *fname, *oldline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000535
H. Peter Anvine2c80182005-01-15 22:15:51 +0000536 if (line[0] == '#' && line[1] == ' ') {
537 oldline = line;
538 fname = oldline + 2;
539 lineno = atoi(fname);
540 fname += strspn(fname, "0123456789 ");
541 if (*fname == '"')
542 fname++;
543 fnlen = strcspn(fname, "\"");
544 line = nasm_malloc(20 + fnlen);
545 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
546 nasm_free(oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000547 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000548 if (tasm_compatible_mode)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000549 return check_tasm_directive(line);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000550 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000551}
552
553/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000554 * Free a linked list of tokens.
555 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000556static void free_tlist(Token * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000557{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000558 while (list) {
559 list = delete_Token(list);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000560 }
561}
562
563/*
564 * Free a linked list of lines.
565 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000566static void free_llist(Line * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000567{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000568 Line *l;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000569 while (list) {
570 l = list;
571 list = list->next;
572 free_tlist(l->first);
573 nasm_free(l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000574 }
575}
576
577/*
H. Peter Anvineba20a72002-04-30 20:53:55 +0000578 * Free an MMacro
579 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000580static void free_mmacro(MMacro * m)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000581{
H. Peter Anvin734b1882002-04-30 21:01:08 +0000582 nasm_free(m->name);
583 free_tlist(m->dlist);
584 nasm_free(m->defaults);
585 free_llist(m->expansion);
586 nasm_free(m);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000587}
588
589/*
H. Peter Anvin97a23472007-09-16 17:57:25 -0700590 * Free all currently defined macros, and free the hash tables
591 */
H. Peter Anvin072771e2008-05-22 13:17:51 -0700592static void free_smacro_table(struct hash_table *smt)
H. Peter Anvin97a23472007-09-16 17:57:25 -0700593{
H. Peter Anvin97a23472007-09-16 17:57:25 -0700594 SMacro *s;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700595 const char *key;
596 struct hash_tbl_node *it = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -0700597
H. Peter Anvin072771e2008-05-22 13:17:51 -0700598 while ((s = hash_iterate(smt, &it, &key)) != NULL) {
H. Peter Anvin97a23472007-09-16 17:57:25 -0700599 nasm_free((void *)key);
600 while (s) {
601 SMacro *ns = s->next;
602 nasm_free(s->name);
603 free_tlist(s->expansion);
604 nasm_free(s);
605 s = ns;
606 }
607 }
H. Peter Anvin072771e2008-05-22 13:17:51 -0700608 hash_free(smt);
609}
610
611static void free_mmacro_table(struct hash_table *mmt)
612{
613 MMacro *m;
614 const char *key;
615 struct hash_tbl_node *it = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -0700616
617 it = NULL;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700618 while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
H. Peter Anvin97a23472007-09-16 17:57:25 -0700619 nasm_free((void *)key);
620 while (m) {
621 MMacro *nm = m->next;
622 free_mmacro(m);
623 m = nm;
624 }
625 }
H. Peter Anvin072771e2008-05-22 13:17:51 -0700626 hash_free(mmt);
627}
628
629static void free_macros(void)
630{
H. Peter Anvin166c2472008-05-28 12:28:58 -0700631 free_smacro_table(&smacros);
632 free_mmacro_table(&mmacros);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700633}
634
635/*
636 * Initialize the hash tables
637 */
638static void init_macros(void)
639{
H. Peter Anvin166c2472008-05-28 12:28:58 -0700640 hash_init(&smacros, HASH_LARGE);
641 hash_init(&mmacros, HASH_LARGE);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700642}
643
644/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000645 * Pop the context stack.
646 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000647static void ctx_pop(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000648{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000649 Context *c = cstk;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000650
651 cstk = cstk->next;
H. Peter Anvin166c2472008-05-28 12:28:58 -0700652 free_smacro_table(&c->localmac);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000653 nasm_free(c->name);
654 nasm_free(c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000655}
656
H. Peter Anvin072771e2008-05-22 13:17:51 -0700657/*
658 * Search for a key in the hash index; adding it if necessary
659 * (in which case we initialize the data pointer to NULL.)
660 */
661static void **
662hash_findi_add(struct hash_table *hash, const char *str)
663{
664 struct hash_insert hi;
665 void **r;
666 char *strx;
667
668 r = hash_findi(hash, str, &hi);
669 if (r)
670 return r;
671
672 strx = nasm_strdup(str); /* Use a more efficient allocator here? */
673 return hash_add(&hi, strx, NULL);
674}
675
676/*
677 * Like hash_findi, but returns the data element rather than a pointer
678 * to it. Used only when not adding a new element, hence no third
679 * argument.
680 */
681static void *
682hash_findix(struct hash_table *hash, const char *str)
683{
684 void **p;
685
686 p = hash_findi(hash, str, NULL);
687 return p ? *p : NULL;
688}
689
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000690#define BUF_DELTA 512
691/*
692 * Read a line from the top file in istk, handling multiple CR/LFs
693 * at the end of the line read, and handling spurious ^Zs. Will
694 * return lines from the standard macro set if this has not already
695 * been done.
696 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000697static char *read_line(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000698{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000699 char *buffer, *p, *q;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000700 int bufsize, continued_count;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000701
H. Peter Anvine2c80182005-01-15 22:15:51 +0000702 if (stdmacpos) {
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700703 unsigned char c;
H. Peter Anvin7e50d232008-06-25 14:54:14 -0700704 const unsigned char *p = stdmacpos;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700705 char *ret, *q;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700706 size_t len = 0;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700707 while ((c = *p++)) {
708 if (c >= 0x80)
709 len += pp_directives_len[c-0x80]+1;
710 else
711 len++;
712 }
713 ret = nasm_malloc(len+1);
H. Peter Anvincda81632008-06-21 15:15:40 -0700714 q = ret;
715 while ((c = *stdmacpos++)) {
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700716 if (c >= 0x80) {
717 memcpy(q, pp_directives[c-0x80], pp_directives_len[c-0x80]);
718 q += pp_directives_len[c-0x80];
719 *q++ = ' ';
720 } else {
721 *q++ = c;
722 }
723 }
H. Peter Anvincda81632008-06-21 15:15:40 -0700724 stdmacpos = p;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700725 *q = '\0';
726
H. Peter Anvind2456592008-06-19 15:04:18 -0700727 if (!*stdmacpos) {
728 /* This was the last of the standard macro chain... */
729 stdmacpos = NULL;
730 if (any_extrastdmac) {
731 stdmacpos = extrastdmac;
732 any_extrastdmac = false;
733 } else if (do_predef) {
734 Line *pd, *l;
735 Token *head, **tail, *t;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000736
H. Peter Anvind2456592008-06-19 15:04:18 -0700737 /*
738 * Nasty hack: here we push the contents of
739 * `predef' on to the top-level expansion stack,
740 * since this is the most convenient way to
741 * implement the pre-include and pre-define
742 * features.
743 */
744 for (pd = predef; pd; pd = pd->next) {
745 head = NULL;
746 tail = &head;
747 for (t = pd->first; t; t = t->next) {
748 *tail = new_Token(NULL, t->type, t->text, 0);
749 tail = &(*tail)->next;
750 }
751 l = nasm_malloc(sizeof(Line));
752 l->next = istk->expansion;
753 l->first = head;
H. Peter Anvin538002d2008-06-28 18:30:27 -0700754 l->finishes = NULL;
H. Peter Anvind2456592008-06-19 15:04:18 -0700755 istk->expansion = l;
756 }
757 do_predef = false;
758 }
759 }
760 return ret;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000761 }
762
763 bufsize = BUF_DELTA;
764 buffer = nasm_malloc(BUF_DELTA);
765 p = buffer;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000766 continued_count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000767 while (1) {
768 q = fgets(p, bufsize - (p - buffer), istk->fp);
769 if (!q)
770 break;
771 p += strlen(p);
772 if (p > buffer && p[-1] == '\n') {
773 /* Convert backslash-CRLF line continuation sequences into
774 nothing at all (for DOS and Windows) */
775 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
776 p -= 3;
777 *p = 0;
778 continued_count++;
779 }
780 /* Also convert backslash-LF line continuation sequences into
781 nothing at all (for Unix) */
782 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
783 p -= 2;
784 *p = 0;
785 continued_count++;
786 } else {
787 break;
788 }
789 }
790 if (p - buffer > bufsize - 10) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000791 int32_t offset = p - buffer;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000792 bufsize += BUF_DELTA;
793 buffer = nasm_realloc(buffer, bufsize);
794 p = buffer + offset; /* prevent stale-pointer problems */
795 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000796 }
797
H. Peter Anvine2c80182005-01-15 22:15:51 +0000798 if (!q && p == buffer) {
799 nasm_free(buffer);
800 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000801 }
802
H. Peter Anvine2c80182005-01-15 22:15:51 +0000803 src_set_linnum(src_get_linnum() + istk->lineinc +
804 (continued_count * istk->lineinc));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000805
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000806 /*
807 * Play safe: remove CRs as well as LFs, if any of either are
808 * present at the end of the line.
809 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000810 while (--p >= buffer && (*p == '\n' || *p == '\r'))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000811 *p = '\0';
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000812
813 /*
814 * Handle spurious ^Z, which may be inserted into source files
815 * by some file transfer utilities.
816 */
817 buffer[strcspn(buffer, "\032")] = '\0';
818
H. Peter Anvin734b1882002-04-30 21:01:08 +0000819 list->line(LIST_READ, buffer);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000820
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000821 return buffer;
822}
823
824/*
Keith Kaniosb7a89542007-04-12 02:40:54 +0000825 * Tokenize a line of text. This is a very simple process since we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000826 * don't need to parse the value out of e.g. numeric tokens: we
827 * simply split one string into many.
828 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000829static Token *tokenize(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000830{
H. Peter Anvinca544db2008-10-19 19:30:11 -0700831 char c, *p = line;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000832 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000833 Token *list = NULL;
834 Token *t, **tail = &list;
835
H. Peter Anvine2c80182005-01-15 22:15:51 +0000836 while (*line) {
837 p = line;
838 if (*p == '%') {
839 p++;
H. Peter Anvind784a082009-04-20 14:01:18 -0700840 if (*p == '+' && !nasm_isdigit(p[1])) {
841 p++;
842 type = TOK_PASTE;
843 } else if (nasm_isdigit(*p) ||
844 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000845 do {
846 p++;
847 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700848 while (nasm_isdigit(*p));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000849 type = TOK_PREPROC_ID;
850 } else if (*p == '{') {
851 p++;
852 while (*p && *p != '}') {
853 p[-1] = *p;
854 p++;
855 }
856 p[-1] = '\0';
857 if (*p)
858 p++;
859 type = TOK_PREPROC_ID;
H. Peter Anvin992fe752008-10-19 15:45:05 -0700860 } else if (*p == '[') {
861 int lvl = 1;
862 line += 2; /* Skip the leading %[ */
863 p++;
H. Peter Anvinec033012008-10-19 22:12:06 -0700864 while (lvl && (c = *p++)) {
H. Peter Anvinca544db2008-10-19 19:30:11 -0700865 switch (c) {
866 case ']':
867 lvl--;
868 break;
869 case '%':
H. Peter Anvinca544db2008-10-19 19:30:11 -0700870 if (*p == '[')
871 lvl++;
872 break;
873 case '\'':
874 case '\"':
875 case '`':
H. Peter Anvinec033012008-10-19 22:12:06 -0700876 p = nasm_skip_string(p)+1;
H. Peter Anvinca544db2008-10-19 19:30:11 -0700877 break;
878 default:
879 break;
H. Peter Anvin992fe752008-10-19 15:45:05 -0700880 }
H. Peter Anvin992fe752008-10-19 15:45:05 -0700881 }
H. Peter Anvinec033012008-10-19 22:12:06 -0700882 p--;
H. Peter Anvin992fe752008-10-19 15:45:05 -0700883 if (*p)
884 *p++ = '\0';
H. Peter Anvine1265812008-10-19 22:14:30 -0700885 if (lvl)
886 error(ERR_NONFATAL, "unterminated %[ construct");
H. Peter Anvin992fe752008-10-19 15:45:05 -0700887 type = TOK_INDIRECT;
H. Peter Anvin6c81f0a2008-05-25 21:46:17 -0700888 } else if (*p == '?') {
889 type = TOK_PREPROC_Q; /* %? */
890 p++;
891 if (*p == '?') {
892 type = TOK_PREPROC_QQ; /* %?? */
893 p++;
894 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000895 } else if (isidchar(*p) ||
896 ((*p == '!' || *p == '%' || *p == '$') &&
897 isidchar(p[1]))) {
898 do {
899 p++;
900 }
901 while (isidchar(*p));
902 type = TOK_PREPROC_ID;
903 } else {
904 type = TOK_OTHER;
905 if (*p == '%')
906 p++;
907 }
908 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
909 type = TOK_ID;
910 p++;
911 while (*p && isidchar(*p))
912 p++;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700913 } else if (*p == '\'' || *p == '"' || *p == '`') {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000914 /*
915 * A string token.
916 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000917 type = TOK_STRING;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700918 p = nasm_skip_string(p);
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000919
H. Peter Anvine2c80182005-01-15 22:15:51 +0000920 if (*p) {
921 p++;
922 } else {
H. Peter Anvin917a3492008-09-24 09:14:49 -0700923 error(ERR_WARNING|ERR_PASS1, "unterminated string");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000924 /* Handling unterminated strings by UNV */
925 /* type = -1; */
926 }
Victor van den Elzenfb5f2512009-04-17 16:17:59 +0200927 } else if (p[0] == '$' && p[1] == '$') {
H. Peter Anvin8e1f8112009-04-17 14:20:44 -0700928 type = TOK_OTHER; /* TOKEN_BASE */
Victor van den Elzenfb5f2512009-04-17 16:17:59 +0200929 p += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000930 } else if (isnumstart(*p)) {
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700931 bool is_hex = false;
932 bool is_float = false;
933 bool has_e = false;
934 char c, *r;
935
H. Peter Anvine2c80182005-01-15 22:15:51 +0000936 /*
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700937 * A numeric token.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000938 */
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700939
940 if (*p == '$') {
941 p++;
942 is_hex = true;
943 }
944
945 for (;;) {
946 c = *p++;
947
948 if (!is_hex && (c == 'e' || c == 'E')) {
949 has_e = true;
950 if (*p == '+' || *p == '-') {
951 /* e can only be followed by +/- if it is either a
952 prefixed hex number or a floating-point number */
953 p++;
954 is_float = true;
955 }
956 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
957 is_hex = true;
958 } else if (c == 'P' || c == 'p') {
959 is_float = true;
960 if (*p == '+' || *p == '-')
961 p++;
962 } else if (isnumchar(c) || c == '_')
963 ; /* just advance */
964 else if (c == '.') {
965 /* we need to deal with consequences of the legacy
966 parser, like "1.nolist" being two tokens
967 (TOK_NUMBER, TOK_ID) here; at least give it
968 a shot for now. In the future, we probably need
969 a flex-based scanner with proper pattern matching
970 to do it as well as it can be done. Nothing in
971 the world is going to help the person who wants
972 0x123.p16 interpreted as two tokens, though. */
973 r = p;
974 while (*r == '_')
975 r++;
976
H. Peter Anvinf221b9e2008-06-21 11:03:51 -0700977 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700978 (!is_hex && (*r == 'e' || *r == 'E')) ||
979 (*r == 'p' || *r == 'P')) {
980 p = r;
981 is_float = true;
982 } else
983 break; /* Terminate the token */
984 } else
985 break;
986 }
987 p--; /* Point to first character beyond number */
988
H. Peter Anvin8e1f8112009-04-17 14:20:44 -0700989 if (p == line+1 && *line == '$') {
990 type = TOK_OTHER; /* TOKEN_HERE */
991 } else {
992 if (has_e && !is_hex) {
993 /* 1e13 is floating-point, but 1e13h is not */
994 is_float = true;
995 }
H. Peter Anvind784a082009-04-20 14:01:18 -0700996
H. Peter Anvin8e1f8112009-04-17 14:20:44 -0700997 type = is_float ? TOK_FLOAT : TOK_NUMBER;
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700998 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700999 } else if (nasm_isspace(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001000 type = TOK_WHITESPACE;
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +04001001 p = nasm_skip_spaces(p);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001002 /*
1003 * Whitespace just before end-of-line is discarded by
1004 * pretending it's a comment; whitespace just before a
1005 * comment gets lumped into the comment.
1006 */
1007 if (!*p || *p == ';') {
1008 type = TOK_COMMENT;
1009 while (*p)
1010 p++;
1011 }
1012 } else if (*p == ';') {
1013 type = TOK_COMMENT;
1014 while (*p)
1015 p++;
1016 } else {
1017 /*
1018 * Anything else is an operator of some kind. We check
1019 * for all the double-character operators (>>, <<, //,
1020 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001021 * else is a single-character operator.
H. Peter Anvine2c80182005-01-15 22:15:51 +00001022 */
1023 type = TOK_OTHER;
1024 if ((p[0] == '>' && p[1] == '>') ||
1025 (p[0] == '<' && p[1] == '<') ||
1026 (p[0] == '/' && p[1] == '/') ||
1027 (p[0] == '<' && p[1] == '=') ||
1028 (p[0] == '>' && p[1] == '=') ||
1029 (p[0] == '=' && p[1] == '=') ||
1030 (p[0] == '!' && p[1] == '=') ||
1031 (p[0] == '<' && p[1] == '>') ||
1032 (p[0] == '&' && p[1] == '&') ||
1033 (p[0] == '|' && p[1] == '|') ||
1034 (p[0] == '^' && p[1] == '^')) {
1035 p++;
1036 }
1037 p++;
1038 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001039
H. Peter Anvine2c80182005-01-15 22:15:51 +00001040 /* Handling unterminated string by UNV */
1041 /*if (type == -1)
H. Peter Anvin89cee572009-07-15 09:16:54 -04001042 {
1043 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1044 t->text[p-line] = *line;
1045 tail = &t->next;
1046 }
1047 else */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001048 if (type != TOK_COMMENT) {
1049 *tail = t = new_Token(NULL, type, line, p - line);
1050 tail = &t->next;
1051 }
1052 line = p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001053 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001054 return list;
1055}
1056
H. Peter Anvince616072002-04-30 21:02:23 +00001057/*
1058 * this function allocates a new managed block of memory and
H. Peter Anvin70653092007-10-19 14:42:29 -07001059 * returns a pointer to the block. The managed blocks are
H. Peter Anvince616072002-04-30 21:02:23 +00001060 * deleted only all at once by the delete_Blocks function.
1061 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001062static void *new_Block(size_t size)
H. Peter Anvince616072002-04-30 21:02:23 +00001063{
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001064 Blocks *b = &blocks;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001065
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001066 /* first, get to the end of the linked list */
1067 while (b->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001068 b = b->next;
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001069 /* now allocate the requested chunk */
1070 b->chunk = nasm_malloc(size);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001071
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001072 /* now allocate a new block for the next request */
1073 b->next = nasm_malloc(sizeof(Blocks));
1074 /* and initialize the contents of the new block */
1075 b->next->next = NULL;
1076 b->next->chunk = NULL;
1077 return b->chunk;
H. Peter Anvince616072002-04-30 21:02:23 +00001078}
1079
1080/*
1081 * this function deletes all managed blocks of memory
1082 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001083static void delete_Blocks(void)
H. Peter Anvince616072002-04-30 21:02:23 +00001084{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001085 Blocks *a, *b = &blocks;
H. Peter Anvince616072002-04-30 21:02:23 +00001086
H. Peter Anvin70653092007-10-19 14:42:29 -07001087 /*
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001088 * keep in mind that the first block, pointed to by blocks
H. Peter Anvin70653092007-10-19 14:42:29 -07001089 * is a static and not dynamically allocated, so we don't
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001090 * free it.
1091 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001092 while (b) {
1093 if (b->chunk)
1094 nasm_free(b->chunk);
1095 a = b;
1096 b = b->next;
1097 if (a != &blocks)
1098 nasm_free(a);
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001099 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001100}
H. Peter Anvin734b1882002-04-30 21:01:08 +00001101
1102/*
H. Peter Anvin70653092007-10-19 14:42:29 -07001103 * this function creates a new Token and passes a pointer to it
H. Peter Anvin734b1882002-04-30 21:01:08 +00001104 * back to the caller. It sets the type and text elements, and
H. Peter Anvinf26e0972008-07-01 21:26:27 -07001105 * also the a.mac and next elements to NULL.
H. Peter Anvin734b1882002-04-30 21:01:08 +00001106 */
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001107static Token *new_Token(Token * next, enum pp_token_type type,
H. Peter Anvinc751e862008-06-09 10:18:45 -07001108 const char *text, int txtlen)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001109{
1110 Token *t;
1111 int i;
1112
H. Peter Anvin89cee572009-07-15 09:16:54 -04001113 if (!freeTokens) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001114 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
1115 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
1116 freeTokens[i].next = &freeTokens[i + 1];
1117 freeTokens[i].next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001118 }
1119 t = freeTokens;
1120 freeTokens = t->next;
1121 t->next = next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07001122 t->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001123 t->type = type;
H. Peter Anvin89cee572009-07-15 09:16:54 -04001124 if (type == TOK_WHITESPACE || !text) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001125 t->text = NULL;
1126 } else {
1127 if (txtlen == 0)
1128 txtlen = strlen(text);
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001129 t->text = nasm_malloc(txtlen+1);
1130 memcpy(t->text, text, txtlen);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001131 t->text[txtlen] = '\0';
H. Peter Anvin734b1882002-04-30 21:01:08 +00001132 }
1133 return t;
1134}
1135
H. Peter Anvine2c80182005-01-15 22:15:51 +00001136static Token *delete_Token(Token * t)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001137{
1138 Token *next = t->next;
1139 nasm_free(t->text);
H. Peter Anvin788e6c12002-04-30 21:02:01 +00001140 t->next = freeTokens;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001141 freeTokens = t;
1142 return next;
1143}
1144
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001145/*
1146 * Convert a line of tokens back into text.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001147 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1148 * will be transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001149 */
H. Peter Anvin9e200162008-06-04 17:23:14 -07001150static char *detoken(Token * tlist, bool expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001151{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001152 Token *t;
1153 int len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001154 char *line, *p;
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001155 const char *q;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001156
1157 len = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001158 for (t = tlist; t; t = t->next) {
1159 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001160 char *p = getenv(t->text + 2);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001161 nasm_free(t->text);
1162 if (p)
1163 t->text = nasm_strdup(p);
1164 else
1165 t->text = NULL;
1166 }
1167 /* Expand local macros here and not during preprocessing */
1168 if (expand_locals &&
1169 t->type == TOK_PREPROC_ID && t->text &&
1170 t->text[0] == '%' && t->text[1] == '$') {
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001171 const char *q;
1172 char *p;
1173 Context *ctx = get_ctx(t->text, &q, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001174 if (ctx) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001175 char buffer[40];
Keith Kanios93f2e9a2007-04-14 00:10:59 +00001176 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001177 p = nasm_strcat(buffer, q);
1178 nasm_free(t->text);
1179 t->text = p;
1180 }
1181 }
1182 if (t->type == TOK_WHITESPACE) {
1183 len++;
1184 } else if (t->text) {
1185 len += strlen(t->text);
1186 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001187 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001188 p = line = nasm_malloc(len + 1);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001189 for (t = tlist; t; t = t->next) {
1190 if (t->type == TOK_WHITESPACE) {
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001191 *p++ = ' ';
H. Peter Anvine2c80182005-01-15 22:15:51 +00001192 } else if (t->text) {
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001193 q = t->text;
1194 while (*q)
1195 *p++ = *q++;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001196 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001197 }
1198 *p = '\0';
1199 return line;
1200}
1201
1202/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001203 * A scanner, suitable for use by the expression evaluator, which
1204 * operates on a line of Tokens. Expects a pointer to a pointer to
1205 * the first token in the line to be passed in as its private_data
1206 * field.
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001207 *
1208 * FIX: This really needs to be unified with stdscan.
H. Peter Anvin76690a12002-04-30 20:52:49 +00001209 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001210static int ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001211{
H. Peter Anvin76690a12002-04-30 20:52:49 +00001212 Token **tlineptr = private_data;
1213 Token *tline;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001214 char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001215
H. Peter Anvine2c80182005-01-15 22:15:51 +00001216 do {
1217 tline = *tlineptr;
1218 *tlineptr = tline ? tline->next : NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001219 }
1220 while (tline && (tline->type == TOK_WHITESPACE ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001221 tline->type == TOK_COMMENT));
H. Peter Anvin76690a12002-04-30 20:52:49 +00001222
1223 if (!tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001224 return tokval->t_type = TOKEN_EOS;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001225
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001226 tokval->t_charptr = tline->text;
1227
H. Peter Anvin76690a12002-04-30 20:52:49 +00001228 if (tline->text[0] == '$' && !tline->text[1])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001229 return tokval->t_type = TOKEN_HERE;
H. Peter Anvin7cf897e2002-05-30 21:30:33 +00001230 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001231 return tokval->t_type = TOKEN_BASE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001232
H. Peter Anvine2c80182005-01-15 22:15:51 +00001233 if (tline->type == TOK_ID) {
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001234 p = tokval->t_charptr = tline->text;
1235 if (p[0] == '$') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001236 tokval->t_charptr++;
1237 return tokval->t_type = TOKEN_ID;
1238 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001239
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001240 for (r = p, s = ourcopy; *r; r++) {
Philipp Thomas76ec8e72008-05-21 08:53:21 -07001241 if (r >= p+MAX_KEYWORD)
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001242 return tokval->t_type = TOKEN_ID; /* Not a keyword */
H. Peter Anvinac8f8fc2008-06-11 15:49:41 -07001243 *s++ = nasm_tolower(*r);
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001244 }
1245 *s = '\0';
1246 /* right, so we have an identifier sitting in temp storage. now,
1247 * is it actually a register or instruction name, or what? */
1248 return nasm_token_hash(ourcopy, tokval);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001249 }
1250
H. Peter Anvine2c80182005-01-15 22:15:51 +00001251 if (tline->type == TOK_NUMBER) {
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001252 bool rn_error;
1253 tokval->t_integer = readnum(tline->text, &rn_error);
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001254 tokval->t_charptr = tline->text;
H. Peter Anvin11627042008-06-09 20:45:19 -07001255 if (rn_error)
1256 return tokval->t_type = TOKEN_ERRNUM;
1257 else
1258 return tokval->t_type = TOKEN_NUM;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001259 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001260
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001261 if (tline->type == TOK_FLOAT) {
1262 return tokval->t_type = TOKEN_FLOAT;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001263 }
1264
H. Peter Anvine2c80182005-01-15 22:15:51 +00001265 if (tline->type == TOK_STRING) {
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07001266 char bq, *ep;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001267
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07001268 bq = tline->text[0];
H. Peter Anvin11627042008-06-09 20:45:19 -07001269 tokval->t_charptr = tline->text;
1270 tokval->t_inttwo = nasm_unquote(tline->text, &ep);
H. Peter Anvind2456592008-06-19 15:04:18 -07001271
H. Peter Anvin11627042008-06-09 20:45:19 -07001272 if (ep[0] != bq || ep[1] != '\0')
1273 return tokval->t_type = TOKEN_ERRSTR;
1274 else
1275 return tokval->t_type = TOKEN_STR;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001276 }
1277
H. Peter Anvine2c80182005-01-15 22:15:51 +00001278 if (tline->type == TOK_OTHER) {
1279 if (!strcmp(tline->text, "<<"))
1280 return tokval->t_type = TOKEN_SHL;
1281 if (!strcmp(tline->text, ">>"))
1282 return tokval->t_type = TOKEN_SHR;
1283 if (!strcmp(tline->text, "//"))
1284 return tokval->t_type = TOKEN_SDIV;
1285 if (!strcmp(tline->text, "%%"))
1286 return tokval->t_type = TOKEN_SMOD;
1287 if (!strcmp(tline->text, "=="))
1288 return tokval->t_type = TOKEN_EQ;
1289 if (!strcmp(tline->text, "<>"))
1290 return tokval->t_type = TOKEN_NE;
1291 if (!strcmp(tline->text, "!="))
1292 return tokval->t_type = TOKEN_NE;
1293 if (!strcmp(tline->text, "<="))
1294 return tokval->t_type = TOKEN_LE;
1295 if (!strcmp(tline->text, ">="))
1296 return tokval->t_type = TOKEN_GE;
1297 if (!strcmp(tline->text, "&&"))
1298 return tokval->t_type = TOKEN_DBL_AND;
1299 if (!strcmp(tline->text, "^^"))
1300 return tokval->t_type = TOKEN_DBL_XOR;
1301 if (!strcmp(tline->text, "||"))
1302 return tokval->t_type = TOKEN_DBL_OR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001303 }
1304
1305 /*
1306 * We have no other options: just return the first character of
1307 * the token text.
1308 */
1309 return tokval->t_type = tline->text[0];
1310}
1311
1312/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001313 * Compare a string to the name of an existing macro; this is a
1314 * simple wrapper which calls either strcmp or nasm_stricmp
1315 * depending on the value of the `casesense' parameter.
1316 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001317static int mstrcmp(const char *p, const char *q, bool casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001318{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001319 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001320}
1321
1322/*
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001323 * Compare a string to the name of an existing macro; this is a
1324 * simple wrapper which calls either strcmp or nasm_stricmp
1325 * depending on the value of the `casesense' parameter.
1326 */
1327static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
1328{
1329 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
1330}
1331
1332/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001333 * Return the Context structure associated with a %$ token. Return
1334 * NULL, having _already_ reported an error condition, if the
1335 * context stack isn't deep enough for the supplied number of $
1336 * signs.
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001337 * If all_contexts == true, contexts that enclose current are
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001338 * also scanned for such smacro, until it is found; if not -
1339 * only the context that directly results from the number of $'s
1340 * in variable's name.
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001341 *
1342 * If "namep" is non-NULL, set it to the pointer to the macro name
1343 * tail, i.e. the part beyond %$...
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001344 */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001345static Context *get_ctx(const char *name, const char **namep,
1346 bool all_contexts)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001347{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001348 Context *ctx;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001349 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001350 int i;
1351
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001352 if (namep)
1353 *namep = name;
1354
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001355 if (!name || name[0] != '%' || name[1] != '$')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001356 return NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001357
H. Peter Anvine2c80182005-01-15 22:15:51 +00001358 if (!cstk) {
1359 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1360 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001361 }
1362
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001363 name += 2;
1364 ctx = cstk;
1365 i = 0;
1366 while (ctx && *name == '$') {
1367 name++;
1368 i++;
1369 ctx = ctx->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001370 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001371 if (!ctx) {
1372 error(ERR_NONFATAL, "`%s': context stack is only"
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001373 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001374 return NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001375 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001376
1377 if (namep)
1378 *namep = name;
1379
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001380 if (!all_contexts)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001381 return ctx;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001382
H. Peter Anvine2c80182005-01-15 22:15:51 +00001383 do {
1384 /* Search for this smacro in found context */
H. Peter Anvin166c2472008-05-28 12:28:58 -07001385 m = hash_findix(&ctx->localmac, name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001386 while (m) {
1387 if (!mstrcmp(m->name, name, m->casesense))
1388 return ctx;
1389 m = m->next;
1390 }
1391 ctx = ctx->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001392 }
1393 while (ctx);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001394 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001395}
1396
1397/*
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001398 * Check to see if a file is already in a string list
1399 */
1400static bool in_list(const StrList *list, const char *str)
1401{
1402 while (list) {
1403 if (!strcmp(list->str, str))
1404 return true;
1405 list = list->next;
1406 }
1407 return false;
1408}
1409
1410/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001411 * Open an include file. This routine must always return a valid
1412 * file pointer if it returns - it's responsible for throwing an
1413 * ERR_FATAL and bombing out completely if not. It should also try
1414 * the include path one by one until it finds the file or reaches
1415 * the end of the path.
1416 */
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07001417static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
H. Peter Anvin418ca702008-05-30 10:42:30 -07001418 bool missing_ok)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001419{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001420 FILE *fp;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001421 char *prefix = "";
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001422 IncPath *ip = ipath;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001423 int len = strlen(file);
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001424 size_t prefix_len = 0;
1425 StrList *sl;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001426
H. Peter Anvine2c80182005-01-15 22:15:51 +00001427 while (1) {
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001428 sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
1429 memcpy(sl->str, prefix, prefix_len);
1430 memcpy(sl->str+prefix_len, file, len+1);
1431 fp = fopen(sl->str, "r");
H. Peter Anvin418ca702008-05-30 10:42:30 -07001432 if (fp && dhead && !in_list(*dhead, sl->str)) {
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001433 sl->next = NULL;
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07001434 **dtail = sl;
1435 *dtail = &sl->next;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001436 } else {
1437 nasm_free(sl);
1438 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001439 if (fp)
1440 return fp;
H. Peter Anvin418ca702008-05-30 10:42:30 -07001441 if (!ip) {
1442 if (!missing_ok)
1443 break;
1444 prefix = NULL;
1445 } else {
1446 prefix = ip->path;
1447 ip = ip->next;
1448 }
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001449 if (prefix) {
1450 prefix_len = strlen(prefix);
1451 } else {
1452 /* -MG given and file not found */
H. Peter Anvin418ca702008-05-30 10:42:30 -07001453 if (dhead && !in_list(*dhead, file)) {
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001454 sl = nasm_malloc(len+1+sizeof sl->next);
1455 sl->next = NULL;
1456 strcpy(sl->str, file);
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07001457 **dtail = sl;
1458 *dtail = &sl->next;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001459 }
H. Peter Anvin37a321f2007-09-24 13:41:58 -07001460 return NULL;
1461 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001462 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001463
H. Peter Anvin734b1882002-04-30 21:01:08 +00001464 error(ERR_FATAL, "unable to open include file `%s'", file);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001465 return NULL; /* never reached - placate compilers */
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001466}
1467
1468/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001469 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001470 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001471 * return true if _any_ single-line macro of that name is defined.
1472 * Otherwise, will return true if a single-line macro with either
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001473 * `nparam' or no parameters is defined.
1474 *
1475 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001476 * defined, or nparam is -1, the address of the definition structure
1477 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001478 * is NULL, no action will be taken regarding its contents, and no
1479 * error will occur.
1480 *
1481 * Note that this is also called with nparam zero to resolve
1482 * `ifdef'.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001483 *
1484 * If you already know which context macro belongs to, you can pass
1485 * the context pointer as first parameter; if you won't but name begins
1486 * with %$ the context will be automatically computed. If all_contexts
1487 * is true, macro will be searched in outer contexts as well.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001488 */
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001489static bool
H. Peter Anvinb2a5fda2008-06-19 21:42:42 -07001490smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001491 bool nocase)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001492{
H. Peter Anvin166c2472008-05-28 12:28:58 -07001493 struct hash_table *smtbl;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001494 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001495
H. Peter Anvin97a23472007-09-16 17:57:25 -07001496 if (ctx) {
H. Peter Anvin166c2472008-05-28 12:28:58 -07001497 smtbl = &ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001498 } else if (name[0] == '%' && name[1] == '$') {
1499 if (cstk)
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001500 ctx = get_ctx(name, &name, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001501 if (!ctx)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001502 return false; /* got to return _something_ */
H. Peter Anvin166c2472008-05-28 12:28:58 -07001503 smtbl = &ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001504 } else {
H. Peter Anvin166c2472008-05-28 12:28:58 -07001505 smtbl = &smacros;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001506 }
H. Peter Anvin166c2472008-05-28 12:28:58 -07001507 m = (SMacro *) hash_findix(smtbl, name);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001508
H. Peter Anvine2c80182005-01-15 22:15:51 +00001509 while (m) {
1510 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
Charles Crayne192d5b52007-10-18 19:02:42 -07001511 (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001512 if (defn) {
Charles Crayne192d5b52007-10-18 19:02:42 -07001513 if (nparam == (int) m->nparam || nparam == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001514 *defn = m;
1515 else
1516 *defn = NULL;
1517 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001518 return true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001519 }
1520 m = m->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001521 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001522
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001523 return false;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001524}
1525
1526/*
1527 * Count and mark off the parameters in a multi-line macro call.
1528 * This is called both from within the multi-line macro expansion
1529 * code, and also to mark off the default parameters when provided
1530 * in a %macro definition line.
1531 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001532static void count_mmac_params(Token * t, int *nparam, Token *** params)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001533{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001534 int paramsize, brace;
1535
1536 *nparam = paramsize = 0;
1537 *params = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001538 while (t) {
H. Peter Anvin91fb6f12008-09-01 10:56:33 -07001539 /* +1: we need space for the final NULL */
1540 if (*nparam+1 >= paramsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001541 paramsize += PARAM_DELTA;
1542 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1543 }
1544 skip_white_(t);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001545 brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001546 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001547 brace = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001548 (*params)[(*nparam)++] = t;
1549 while (tok_isnt_(t, brace ? "}" : ","))
1550 t = t->next;
1551 if (t) { /* got a comma/brace */
1552 t = t->next;
1553 if (brace) {
1554 /*
1555 * Now we've found the closing brace, look further
1556 * for the comma.
1557 */
1558 skip_white_(t);
1559 if (tok_isnt_(t, ",")) {
1560 error(ERR_NONFATAL,
1561 "braces do not enclose all of macro parameter");
1562 while (tok_isnt_(t, ","))
1563 t = t->next;
1564 }
1565 if (t)
1566 t = t->next; /* eat the comma */
1567 }
1568 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001569 }
1570}
1571
1572/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001573 * Determine whether one of the various `if' conditions is true or
1574 * not.
1575 *
1576 * We must free the tline we get passed.
1577 */
H. Peter Anvin70055962007-10-11 00:05:31 -07001578static bool if_condition(Token * tline, enum preproc_token ct)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001579{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001580 enum pp_conditional i = PP_COND(ct);
H. Peter Anvin70055962007-10-11 00:05:31 -07001581 bool j;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001582 Token *t, *tt, **tptr, *origline;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001583 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001584 expr *evalresult;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001585 enum pp_token_type needtype;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001586
1587 origline = tline;
1588
H. Peter Anvine2c80182005-01-15 22:15:51 +00001589 switch (i) {
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001590 case PPC_IFCTX:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001591 j = false; /* have we matched yet? */
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001592 while (true) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001593 skip_white_(tline);
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001594 if (!tline)
1595 break;
1596 if (tline->type != TOK_ID) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001597 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001598 "`%s' expects context identifiers", pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001599 free_tlist(origline);
1600 return -1;
1601 }
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001602 if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001603 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001604 tline = tline->next;
1605 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001606 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001607
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001608 case PPC_IFDEF:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001609 j = false; /* have we matched yet? */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001610 while (tline) {
1611 skip_white_(tline);
1612 if (!tline || (tline->type != TOK_ID &&
1613 (tline->type != TOK_PREPROC_ID ||
1614 tline->text[1] != '$'))) {
1615 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001616 "`%s' expects macro identifiers", pp_directives[ct]);
1617 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001618 }
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001619 if (smacro_defined(NULL, tline->text, 0, NULL, true))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001620 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001621 tline = tline->next;
1622 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001623 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001624
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001625 case PPC_IFIDN:
1626 case PPC_IFIDNI:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001627 tline = expand_smacro(tline);
1628 t = tt = tline;
1629 while (tok_isnt_(tt, ","))
1630 tt = tt->next;
1631 if (!tt) {
1632 error(ERR_NONFATAL,
1633 "`%s' expects two comma-separated arguments",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001634 pp_directives[ct]);
1635 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001636 }
1637 tt = tt->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001638 j = true; /* assume equality unless proved not */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001639 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1640 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1641 error(ERR_NONFATAL, "`%s': more than one comma on line",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001642 pp_directives[ct]);
1643 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001644 }
1645 if (t->type == TOK_WHITESPACE) {
1646 t = t->next;
1647 continue;
1648 }
1649 if (tt->type == TOK_WHITESPACE) {
1650 tt = tt->next;
1651 continue;
1652 }
1653 if (tt->type != t->type) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001654 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001655 break;
1656 }
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001657 /* When comparing strings, need to unquote them first */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001658 if (t->type == TOK_STRING) {
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07001659 size_t l1 = nasm_unquote(t->text, NULL);
1660 size_t l2 = nasm_unquote(tt->text, NULL);
H. Peter Anvind2456592008-06-19 15:04:18 -07001661
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001662 if (l1 != l2) {
1663 j = false;
1664 break;
1665 }
1666 if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
1667 j = false;
1668 break;
1669 }
1670 } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001671 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001672 break;
1673 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001674
H. Peter Anvine2c80182005-01-15 22:15:51 +00001675 t = t->next;
1676 tt = tt->next;
1677 }
1678 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001679 j = false; /* trailing gunk on one end or other */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001680 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001681
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001682 case PPC_IFMACRO:
H. Peter Anvin89cee572009-07-15 09:16:54 -04001683 {
1684 bool found = false;
1685 MMacro searching, *mmac;
H. Peter Anvin65747262002-05-07 00:10:05 +00001686
H. Peter Anvin89cee572009-07-15 09:16:54 -04001687 skip_white_(tline);
1688 tline = expand_id(tline);
1689 if (!tok_type_(tline, TOK_ID)) {
1690 error(ERR_NONFATAL,
1691 "`%s' expects a macro name", pp_directives[ct]);
1692 goto fail;
1693 }
1694 searching.name = nasm_strdup(tline->text);
1695 searching.casesense = true;
1696 searching.plus = false;
1697 searching.nolist = false;
1698 searching.in_progress = 0;
1699 searching.max_depth = 0;
1700 searching.rep_nest = NULL;
1701 searching.nparam_min = 0;
1702 searching.nparam_max = INT_MAX;
1703 tline = expand_smacro(tline->next);
1704 skip_white_(tline);
1705 if (!tline) {
1706 } else if (!tok_type_(tline, TOK_NUMBER)) {
1707 error(ERR_NONFATAL,
1708 "`%s' expects a parameter count or nothing",
1709 pp_directives[ct]);
1710 } else {
1711 searching.nparam_min = searching.nparam_max =
1712 readnum(tline->text, &j);
1713 if (j)
1714 error(ERR_NONFATAL,
1715 "unable to parse parameter count `%s'",
1716 tline->text);
1717 }
1718 if (tline && tok_is_(tline->next, "-")) {
1719 tline = tline->next->next;
1720 if (tok_is_(tline, "*"))
1721 searching.nparam_max = INT_MAX;
1722 else if (!tok_type_(tline, TOK_NUMBER))
1723 error(ERR_NONFATAL,
1724 "`%s' expects a parameter count after `-'",
1725 pp_directives[ct]);
1726 else {
1727 searching.nparam_max = readnum(tline->text, &j);
1728 if (j)
1729 error(ERR_NONFATAL,
1730 "unable to parse parameter count `%s'",
1731 tline->text);
1732 if (searching.nparam_min > searching.nparam_max)
1733 error(ERR_NONFATAL,
1734 "minimum parameter count exceeds maximum");
H. Peter Anvin97a23472007-09-16 17:57:25 -07001735 }
H. Peter Anvin89cee572009-07-15 09:16:54 -04001736 }
1737 if (tline && tok_is_(tline->next, "+")) {
1738 tline = tline->next;
1739 searching.plus = true;
1740 }
1741 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
1742 while (mmac) {
1743 if (!strcmp(mmac->name, searching.name) &&
1744 (mmac->nparam_min <= searching.nparam_max
1745 || searching.plus)
1746 && (searching.nparam_min <= mmac->nparam_max
1747 || mmac->plus)) {
1748 found = true;
1749 break;
1750 }
1751 mmac = mmac->next;
1752 }
1753 if (tline && tline->next)
1754 error(ERR_WARNING|ERR_PASS1,
1755 "trailing garbage after %%ifmacro ignored");
1756 nasm_free(searching.name);
1757 j = found;
1758 break;
1759 }
H. Peter Anvin65747262002-05-07 00:10:05 +00001760
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001761 case PPC_IFID:
1762 needtype = TOK_ID;
1763 goto iftype;
1764 case PPC_IFNUM:
1765 needtype = TOK_NUMBER;
1766 goto iftype;
1767 case PPC_IFSTR:
1768 needtype = TOK_STRING;
1769 goto iftype;
1770
1771 iftype:
H. Peter Anvin134b9462008-02-16 17:01:40 -08001772 t = tline = expand_smacro(tline);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001773
H. Peter Anvin927c92b2008-02-16 13:44:52 -08001774 while (tok_type_(t, TOK_WHITESPACE) ||
1775 (needtype == TOK_NUMBER &&
1776 tok_type_(t, TOK_OTHER) &&
1777 (t->text[0] == '-' || t->text[0] == '+') &&
1778 !t->text[1]))
1779 t = t->next;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001780
H. Peter Anvincbf768d2008-02-16 16:41:25 -08001781 j = tok_type_(t, needtype);
1782 break;
1783
1784 case PPC_IFTOKEN:
1785 t = tline = expand_smacro(tline);
1786 while (tok_type_(t, TOK_WHITESPACE))
1787 t = t->next;
1788
1789 j = false;
1790 if (t) {
1791 t = t->next; /* Skip the actual token */
1792 while (tok_type_(t, TOK_WHITESPACE))
1793 t = t->next;
1794 j = !t; /* Should be nothing left */
1795 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001796 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001797
H. Peter Anvin134b9462008-02-16 17:01:40 -08001798 case PPC_IFEMPTY:
1799 t = tline = expand_smacro(tline);
1800 while (tok_type_(t, TOK_WHITESPACE))
1801 t = t->next;
1802
1803 j = !t; /* Should be empty */
1804 break;
1805
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001806 case PPC_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001807 t = tline = expand_smacro(tline);
1808 tptr = &t;
1809 tokval.t_type = TOKEN_INVALID;
1810 evalresult = evaluate(ppscan, tptr, &tokval,
1811 NULL, pass | CRITICAL, error, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001812 if (!evalresult)
1813 return -1;
1814 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07001815 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001816 "trailing garbage after expression ignored");
1817 if (!is_simple(evalresult)) {
1818 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001819 "non-constant value given to `%s'", pp_directives[ct]);
1820 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001821 }
Chuck Crayne60ae75d2007-05-02 01:59:16 +00001822 j = reloc_value(evalresult) != 0;
H. Peter Anvin90e6e812008-07-16 14:38:24 -07001823 break;
H. Peter Anvin95e28822007-09-12 04:20:08 +00001824
H. Peter Anvine2c80182005-01-15 22:15:51 +00001825 default:
1826 error(ERR_FATAL,
1827 "preprocessor directive `%s' not yet implemented",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001828 pp_directives[ct]);
1829 goto fail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001830 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001831
1832 free_tlist(origline);
1833 return j ^ PP_NEGATIVE(ct);
H. Peter Anvin70653092007-10-19 14:42:29 -07001834
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001835fail:
1836 free_tlist(origline);
1837 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001838}
1839
1840/*
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001841 * Common code for defining an smacro
1842 */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001843static bool define_smacro(Context *ctx, const char *mname, bool casesense,
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001844 int nparam, Token *expansion)
1845{
1846 SMacro *smac, **smhead;
H. Peter Anvin166c2472008-05-28 12:28:58 -07001847 struct hash_table *smtbl;
H. Peter Anvin70653092007-10-19 14:42:29 -07001848
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001849 if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
1850 if (!smac) {
H. Peter Anvin917a3492008-09-24 09:14:49 -07001851 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001852 "single-line macro `%s' defined both with and"
1853 " without parameters", mname);
1854
1855 /* Some instances of the old code considered this a failure,
1856 some others didn't. What is the right thing to do here? */
1857 free_tlist(expansion);
1858 return false; /* Failure */
1859 } else {
1860 /*
1861 * We're redefining, so we have to take over an
1862 * existing SMacro structure. This means freeing
1863 * what was already in it.
1864 */
1865 nasm_free(smac->name);
1866 free_tlist(smac->expansion);
1867 }
1868 } else {
H. Peter Anvin166c2472008-05-28 12:28:58 -07001869 smtbl = ctx ? &ctx->localmac : &smacros;
1870 smhead = (SMacro **) hash_findi_add(smtbl, mname);
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001871 smac = nasm_malloc(sizeof(SMacro));
1872 smac->next = *smhead;
1873 *smhead = smac;
1874 }
1875 smac->name = nasm_strdup(mname);
1876 smac->casesense = casesense;
1877 smac->nparam = nparam;
1878 smac->expansion = expansion;
1879 smac->in_progress = false;
1880 return true; /* Success */
1881}
1882
1883/*
1884 * Undefine an smacro
1885 */
1886static void undef_smacro(Context *ctx, const char *mname)
1887{
1888 SMacro **smhead, *s, **sp;
H. Peter Anvin166c2472008-05-28 12:28:58 -07001889 struct hash_table *smtbl;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001890
H. Peter Anvin166c2472008-05-28 12:28:58 -07001891 smtbl = ctx ? &ctx->localmac : &smacros;
1892 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
H. Peter Anvin70653092007-10-19 14:42:29 -07001893
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001894 if (smhead) {
1895 /*
1896 * We now have a macro name... go hunt for it.
1897 */
1898 sp = smhead;
1899 while ((s = *sp) != NULL) {
1900 if (!mstrcmp(s->name, mname, s->casesense)) {
1901 *sp = s->next;
1902 nasm_free(s->name);
1903 free_tlist(s->expansion);
1904 nasm_free(s);
1905 } else {
1906 sp = &s->next;
1907 }
1908 }
1909 }
1910}
1911
H. Peter Anvin8781cb02007-11-08 20:01:11 -08001912/*
H. Peter Anvina26433d2008-07-16 14:40:01 -07001913 * Parse a mmacro specification.
1914 */
1915static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
1916{
1917 bool err;
1918
1919 tline = tline->next;
1920 skip_white_(tline);
1921 tline = expand_id(tline);
1922 if (!tok_type_(tline, TOK_ID)) {
1923 error(ERR_NONFATAL, "`%s' expects a macro name", directive);
1924 return false;
1925 }
Victor van den Elzenb916ede2008-07-23 15:14:22 +02001926
H. Peter Anvin89cee572009-07-15 09:16:54 -04001927 def->prev = NULL;
H. Peter Anvina26433d2008-07-16 14:40:01 -07001928 def->name = nasm_strdup(tline->text);
1929 def->plus = false;
1930 def->nolist = false;
1931 def->in_progress = 0;
1932 def->rep_nest = NULL;
Victor van den Elzenb916ede2008-07-23 15:14:22 +02001933 def->nparam_min = 0;
1934 def->nparam_max = 0;
1935
H. Peter Anvina26433d2008-07-16 14:40:01 -07001936 tline = expand_smacro(tline->next);
1937 skip_white_(tline);
1938 if (!tok_type_(tline, TOK_NUMBER)) {
1939 error(ERR_NONFATAL, "`%s' expects a parameter count", directive);
H. Peter Anvina26433d2008-07-16 14:40:01 -07001940 } else {
1941 def->nparam_min = def->nparam_max =
1942 readnum(tline->text, &err);
1943 if (err)
1944 error(ERR_NONFATAL,
1945 "unable to parse parameter count `%s'", tline->text);
1946 }
1947 if (tline && tok_is_(tline->next, "-")) {
1948 tline = tline->next->next;
1949 if (tok_is_(tline, "*")) {
1950 def->nparam_max = INT_MAX;
1951 } else if (!tok_type_(tline, TOK_NUMBER)) {
1952 error(ERR_NONFATAL,
1953 "`%s' expects a parameter count after `-'", directive);
1954 } else {
1955 def->nparam_max = readnum(tline->text, &err);
1956 if (err) {
1957 error(ERR_NONFATAL, "unable to parse parameter count `%s'",
1958 tline->text);
1959 }
1960 if (def->nparam_min > def->nparam_max) {
1961 error(ERR_NONFATAL, "minimum parameter count exceeds maximum");
1962 }
1963 }
1964 }
1965 if (tline && tok_is_(tline->next, "+")) {
1966 tline = tline->next;
1967 def->plus = true;
1968 }
1969 if (tline && tok_type_(tline->next, TOK_ID) &&
1970 !nasm_stricmp(tline->next->text, ".nolist")) {
1971 tline = tline->next;
1972 def->nolist = true;
1973 }
Keith Kanios891775e2009-07-11 06:08:54 -05001974
H. Peter Anvina26433d2008-07-16 14:40:01 -07001975 /*
1976 * Handle default parameters.
1977 */
1978 if (tline && tline->next) {
1979 def->dlist = tline->next;
1980 tline->next = NULL;
1981 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
1982 } else {
1983 def->dlist = NULL;
1984 def->defaults = NULL;
1985 }
1986 def->expansion = NULL;
1987
H. Peter Anvin89cee572009-07-15 09:16:54 -04001988 if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
1989 !def->plus)
1990 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MDP,
1991 "too many default macro parameters");
Victor van den Elzenb916ede2008-07-23 15:14:22 +02001992
H. Peter Anvina26433d2008-07-16 14:40:01 -07001993 return true;
1994}
1995
1996
1997/*
H. Peter Anvin8781cb02007-11-08 20:01:11 -08001998 * Decode a size directive
1999 */
2000static int parse_size(const char *str) {
2001 static const char *size_names[] =
H. Peter Anvindfb91802008-05-20 11:43:53 -07002002 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002003 static const int sizes[] =
H. Peter Anvindfb91802008-05-20 11:43:53 -07002004 { 0, 1, 4, 16, 8, 10, 2, 32 };
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002005
2006 return sizes[bsii(str, size_names, elements(size_names))+1];
2007}
2008
H. Peter Anvinf9c9a672009-07-14 15:14:05 -04002009/*
2010 * nasm_unquote with error if the string contains NUL characters.
2011 * If the string contains NUL characters, issue an error and return
2012 * the C len, i.e. truncate at the NUL.
2013 */
2014static size_t nasm_unquote_cstr(char *qstr, enum preproc_token directive)
2015{
2016 size_t len = nasm_unquote(qstr, NULL);
2017 size_t clen = strlen(qstr);
2018
2019 if (len != clen)
H. Peter Anvincd0943e2009-07-14 15:17:11 -04002020 error(ERR_NONFATAL, "NUL character in `%s' directive",
2021 pp_directives[directive]);
H. Peter Anvinf9c9a672009-07-14 15:14:05 -04002022
2023 return clen;
2024}
2025
Ed Beroset3ab3f412002-06-11 03:31:49 +00002026/**
2027 * find and process preprocessor directive in passed line
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002028 * Find out if a line contains a preprocessor directive, and deal
2029 * with it if so.
H. Peter Anvin70653092007-10-19 14:42:29 -07002030 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00002031 * If a directive _is_ found, it is the responsibility of this routine
2032 * (and not the caller) to free_tlist() the line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002033 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00002034 * @param tline a pointer to the current tokeninzed line linked list
2035 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
H. Peter Anvin70653092007-10-19 14:42:29 -07002036 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002037 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002038static int do_directive(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002039{
H. Peter Anvin4169a472007-09-12 01:29:43 +00002040 enum preproc_token i;
2041 int j;
H. Peter Anvin70055962007-10-11 00:05:31 -07002042 bool err;
2043 int nparam;
2044 bool nolist;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002045 bool casesense;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -07002046 int k, m;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002047 int offset;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002048 char *p, *pp;
2049 const char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002050 Include *inc;
2051 Context *ctx;
2052 Cond *cond;
H. Peter Anvin97a23472007-09-16 17:57:25 -07002053 MMacro *mmac, **mmhead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002054 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
2055 Line *l;
2056 struct tokenval tokval;
2057 expr *evalresult;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002058 MMacro *tmp_defining; /* Used when manipulating rep_nest */
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002059 int64_t count;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07002060 size_t len;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002061 int severity;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002062
2063 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002064
H. Peter Anvineba20a72002-04-30 20:53:55 +00002065 skip_white_(tline);
H. Peter Anvinf2936d72008-06-04 15:11:23 -07002066 if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00002067 (tline->text[1] == '%' || tline->text[1] == '$'
2068 || tline->text[1] == '!'))
2069 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002070
H. Peter Anvin4169a472007-09-12 01:29:43 +00002071 i = pp_token_hash(tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002072
2073 /*
2074 * If we're in a non-emitting branch of a condition construct,
H. Peter Anvin76690a12002-04-30 20:52:49 +00002075 * or walking to the end of an already terminated %rep block,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002076 * we should ignore all directives except for condition
2077 * directives.
2078 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00002079 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00002080 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
2081 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002082 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002083
2084 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002085 * If we're defining a macro or reading a %rep block, we should
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02002086 * ignore all directives except for %macro/%imacro (which nest),
2087 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2088 * If we're in a %rep block, another %rep nests, so should be let through.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002089 */
2090 if (defining && i != PP_MACRO && i != PP_IMACRO &&
H. Peter Anvindb8f96e2009-07-15 09:07:29 -04002091 i != PP_RMACRO && i != PP_IRMACRO &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00002092 i != PP_ENDMACRO && i != PP_ENDM &&
2093 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
2094 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002095 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002096
Charles Crayned4200be2008-07-12 16:42:33 -07002097 if (defining) {
Keith Kanios852f1ee2009-07-12 00:19:55 -05002098 if (i == PP_MACRO || i == PP_IMACRO ||
H. Peter Anvindb8f96e2009-07-15 09:07:29 -04002099 i == PP_RMACRO || i == PP_IRMACRO) {
Charles Crayned4200be2008-07-12 16:42:33 -07002100 nested_mac_count++;
2101 return NO_DIRECTIVE_FOUND;
2102 } else if (nested_mac_count > 0) {
2103 if (i == PP_ENDMACRO) {
2104 nested_mac_count--;
2105 return NO_DIRECTIVE_FOUND;
2106 }
2107 }
2108 if (!defining->name) {
2109 if (i == PP_REP) {
2110 nested_rep_count++;
2111 return NO_DIRECTIVE_FOUND;
2112 } else if (nested_rep_count > 0) {
2113 if (i == PP_ENDREP) {
2114 nested_rep_count--;
2115 return NO_DIRECTIVE_FOUND;
2116 }
2117 }
2118 }
2119 }
2120
H. Peter Anvin4169a472007-09-12 01:29:43 +00002121 switch (i) {
2122 case PP_INVALID:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002123 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2124 tline->text);
2125 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002126
H. Peter Anvine2c80182005-01-15 22:15:51 +00002127 case PP_STACKSIZE:
2128 /* Directive to tell NASM what the default stack size is. The
2129 * default is for a 16-bit stack, and this can be overriden with
2130 * %stacksize large.
2131 * the following form:
2132 *
2133 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2134 */
2135 tline = tline->next;
2136 if (tline && tline->type == TOK_WHITESPACE)
2137 tline = tline->next;
2138 if (!tline || tline->type != TOK_ID) {
2139 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
2140 free_tlist(origline);
2141 return DIRECTIVE_FOUND;
2142 }
2143 if (nasm_stricmp(tline->text, "flat") == 0) {
2144 /* All subsequent ARG directives are for a 32-bit stack */
2145 StackSize = 4;
2146 StackPointer = "ebp";
2147 ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002148 LocalOffset = 0;
Charles Crayne7eaf9192007-11-08 22:11:14 -08002149 } else if (nasm_stricmp(tline->text, "flat64") == 0) {
2150 /* All subsequent ARG directives are for a 64-bit stack */
2151 StackSize = 8;
2152 StackPointer = "rbp";
2153 ArgOffset = 8;
2154 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002155 } else if (nasm_stricmp(tline->text, "large") == 0) {
2156 /* All subsequent ARG directives are for a 16-bit stack,
2157 * far function call.
2158 */
2159 StackSize = 2;
2160 StackPointer = "bp";
2161 ArgOffset = 4;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002162 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002163 } else if (nasm_stricmp(tline->text, "small") == 0) {
2164 /* All subsequent ARG directives are for a 16-bit stack,
2165 * far function call. We don't support near functions.
2166 */
2167 StackSize = 2;
2168 StackPointer = "bp";
2169 ArgOffset = 6;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002170 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002171 } else {
2172 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
2173 free_tlist(origline);
2174 return DIRECTIVE_FOUND;
2175 }
2176 free_tlist(origline);
2177 return DIRECTIVE_FOUND;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002178
H. Peter Anvine2c80182005-01-15 22:15:51 +00002179 case PP_ARG:
2180 /* TASM like ARG directive to define arguments to functions, in
2181 * the following form:
2182 *
2183 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2184 */
2185 offset = ArgOffset;
2186 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002187 char *arg, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00002188 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002189
H. Peter Anvine2c80182005-01-15 22:15:51 +00002190 /* Find the argument name */
2191 tline = tline->next;
2192 if (tline && tline->type == TOK_WHITESPACE)
2193 tline = tline->next;
2194 if (!tline || tline->type != TOK_ID) {
2195 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
2196 free_tlist(origline);
2197 return DIRECTIVE_FOUND;
2198 }
2199 arg = tline->text;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002200
H. Peter Anvine2c80182005-01-15 22:15:51 +00002201 /* Find the argument size type */
2202 tline = tline->next;
2203 if (!tline || tline->type != TOK_OTHER
2204 || tline->text[0] != ':') {
2205 error(ERR_NONFATAL,
2206 "Syntax error processing `%%arg' directive");
2207 free_tlist(origline);
2208 return DIRECTIVE_FOUND;
2209 }
2210 tline = tline->next;
2211 if (!tline || tline->type != TOK_ID) {
2212 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
2213 free_tlist(origline);
2214 return DIRECTIVE_FOUND;
2215 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002216
H. Peter Anvine2c80182005-01-15 22:15:51 +00002217 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002218 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002219 tt = expand_smacro(tt);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002220 size = parse_size(tt->text);
2221 if (!size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002222 error(ERR_NONFATAL,
2223 "Invalid size type for `%%arg' missing directive");
2224 free_tlist(tt);
2225 free_tlist(origline);
2226 return DIRECTIVE_FOUND;
2227 }
2228 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002229
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002230 /* Round up to even stack slots */
2231 size = (size+StackSize-1) & ~(StackSize-1);
2232
H. Peter Anvine2c80182005-01-15 22:15:51 +00002233 /* Now define the macro for the argument */
2234 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
2235 arg, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002236 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00002237 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002238
H. Peter Anvine2c80182005-01-15 22:15:51 +00002239 /* Move to the next argument in the list */
2240 tline = tline->next;
2241 if (tline && tline->type == TOK_WHITESPACE)
2242 tline = tline->next;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002243 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2244 ArgOffset = offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002245 free_tlist(origline);
2246 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002247
H. Peter Anvine2c80182005-01-15 22:15:51 +00002248 case PP_LOCAL:
2249 /* TASM like LOCAL directive to define local variables for a
2250 * function, in the following form:
2251 *
2252 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2253 *
2254 * The '= LocalSize' at the end is ignored by NASM, but is
2255 * required by TASM to define the local parameter size (and used
2256 * by the TASM macro package).
2257 */
2258 offset = LocalOffset;
2259 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002260 char *local, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00002261 int size = StackSize;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002262
H. Peter Anvine2c80182005-01-15 22:15:51 +00002263 /* Find the argument name */
2264 tline = tline->next;
2265 if (tline && tline->type == TOK_WHITESPACE)
2266 tline = tline->next;
2267 if (!tline || tline->type != TOK_ID) {
2268 error(ERR_NONFATAL,
2269 "`%%local' missing argument parameter");
2270 free_tlist(origline);
2271 return DIRECTIVE_FOUND;
2272 }
2273 local = tline->text;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002274
H. Peter Anvine2c80182005-01-15 22:15:51 +00002275 /* Find the argument size type */
2276 tline = tline->next;
2277 if (!tline || tline->type != TOK_OTHER
2278 || tline->text[0] != ':') {
2279 error(ERR_NONFATAL,
2280 "Syntax error processing `%%local' directive");
2281 free_tlist(origline);
2282 return DIRECTIVE_FOUND;
2283 }
2284 tline = tline->next;
2285 if (!tline || tline->type != TOK_ID) {
2286 error(ERR_NONFATAL,
2287 "`%%local' missing size type parameter");
2288 free_tlist(origline);
2289 return DIRECTIVE_FOUND;
2290 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002291
H. Peter Anvine2c80182005-01-15 22:15:51 +00002292 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002293 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002294 tt = expand_smacro(tt);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002295 size = parse_size(tt->text);
2296 if (!size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002297 error(ERR_NONFATAL,
2298 "Invalid size type for `%%local' missing directive");
2299 free_tlist(tt);
2300 free_tlist(origline);
2301 return DIRECTIVE_FOUND;
2302 }
2303 free_tlist(tt);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002304
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002305 /* Round up to even stack slots */
2306 size = (size+StackSize-1) & ~(StackSize-1);
2307
2308 offset += size; /* Negative offset, increment before */
2309
2310 /* Now define the macro for the argument */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002311 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
2312 local, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002313 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002314
H. Peter Anvine2c80182005-01-15 22:15:51 +00002315 /* Now define the assign to setup the enter_c macro correctly */
2316 snprintf(directive, sizeof(directive),
2317 "%%assign %%$localsize %%$localsize+%d", size);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002318 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002319
H. Peter Anvine2c80182005-01-15 22:15:51 +00002320 /* Move to the next argument in the list */
2321 tline = tline->next;
2322 if (tline && tline->type == TOK_WHITESPACE)
2323 tline = tline->next;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002324 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2325 LocalOffset = offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002326 free_tlist(origline);
2327 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002328
H. Peter Anvine2c80182005-01-15 22:15:51 +00002329 case PP_CLEAR:
2330 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002331 error(ERR_WARNING|ERR_PASS1,
2332 "trailing garbage after `%%clear' ignored");
H. Peter Anvin97a23472007-09-16 17:57:25 -07002333 free_macros();
2334 init_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00002335 free_tlist(origline);
2336 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002337
H. Peter Anvin418ca702008-05-30 10:42:30 -07002338 case PP_DEPEND:
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002339 t = tline->next = expand_smacro(tline->next);
2340 skip_white_(t);
2341 if (!t || (t->type != TOK_STRING &&
H. Peter Anvin89cee572009-07-15 09:16:54 -04002342 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin418ca702008-05-30 10:42:30 -07002343 error(ERR_NONFATAL, "`%%depend' expects a file name");
2344 free_tlist(origline);
2345 return DIRECTIVE_FOUND; /* but we did _something_ */
2346 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002347 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002348 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin418ca702008-05-30 10:42:30 -07002349 "trailing garbage after `%%depend' ignored");
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002350 p = t->text;
2351 if (t->type != TOK_INTERNAL_STRING)
H. Peter Anvinf9c9a672009-07-14 15:14:05 -04002352 nasm_unquote_cstr(p, i);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002353 if (dephead && !in_list(*dephead, p)) {
2354 StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next);
2355 sl->next = NULL;
2356 strcpy(sl->str, p);
2357 *deptail = sl;
2358 deptail = &sl->next;
2359 }
2360 free_tlist(origline);
2361 return DIRECTIVE_FOUND;
2362
2363 case PP_INCLUDE:
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002364 t = tline->next = expand_smacro(tline->next);
2365 skip_white_(t);
H. Peter Anvind2456592008-06-19 15:04:18 -07002366
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002367 if (!t || (t->type != TOK_STRING &&
H. Peter Anvin89cee572009-07-15 09:16:54 -04002368 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002369 error(ERR_NONFATAL, "`%%include' expects a file name");
2370 free_tlist(origline);
2371 return DIRECTIVE_FOUND; /* but we did _something_ */
2372 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002373 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002374 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002375 "trailing garbage after `%%include' ignored");
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002376 p = t->text;
2377 if (t->type != TOK_INTERNAL_STRING)
H. Peter Anvinf9c9a672009-07-14 15:14:05 -04002378 nasm_unquote_cstr(p, i);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002379 inc = nasm_malloc(sizeof(Include));
2380 inc->next = istk;
2381 inc->conds = NULL;
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07002382 inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002383 if (!inc->fp) {
H. Peter Anvin37a321f2007-09-24 13:41:58 -07002384 /* -MG given but file not found */
2385 nasm_free(inc);
2386 } else {
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002387 inc->fname = src_set_fname(nasm_strdup(p));
H. Peter Anvin37a321f2007-09-24 13:41:58 -07002388 inc->lineno = src_set_linnum(0);
2389 inc->lineinc = 1;
2390 inc->expansion = NULL;
2391 inc->mstk = NULL;
2392 istk = inc;
2393 list->uplevel(LIST_INCLUDE);
2394 }
2395 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002396 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002397
H. Peter Anvind2456592008-06-19 15:04:18 -07002398 case PP_USE:
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002399 {
H. Peter Anvina70547f2008-07-19 21:44:26 -07002400 static macros_t *use_pkg;
H. Peter Anvinb2a5fda2008-06-19 21:42:42 -07002401 const char *pkg_macro;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002402
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002403 tline = tline->next;
2404 skip_white_(tline);
2405 tline = expand_id(tline);
H. Peter Anvind2456592008-06-19 15:04:18 -07002406
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002407 if (!tline || (tline->type != TOK_STRING &&
2408 tline->type != TOK_INTERNAL_STRING &&
2409 tline->type != TOK_ID)) {
H. Peter Anvin926fc402008-06-19 16:26:12 -07002410 error(ERR_NONFATAL, "`%%use' expects a package name");
H. Peter Anvind2456592008-06-19 15:04:18 -07002411 free_tlist(origline);
2412 return DIRECTIVE_FOUND; /* but we did _something_ */
2413 }
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002414 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002415 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvind2456592008-06-19 15:04:18 -07002416 "trailing garbage after `%%use' ignored");
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002417 if (tline->type == TOK_STRING)
H. Peter Anvinf9c9a672009-07-14 15:14:05 -04002418 nasm_unquote_cstr(tline->text, i);
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002419 use_pkg = nasm_stdmac_find_package(tline->text);
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002420 if (!use_pkg)
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002421 error(ERR_NONFATAL, "unknown `%%use' package: %s", tline->text);
H. Peter Anvinb2a5fda2008-06-19 21:42:42 -07002422 /* The first string will be <%define>__USE_*__ */
H. Peter Anvin7e50d232008-06-25 14:54:14 -07002423 pkg_macro = (char *)use_pkg + 1;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002424 if (!smacro_defined(NULL, pkg_macro, 0, NULL, true)) {
2425 /* Not already included, go ahead and include it */
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002426 stdmacpos = use_pkg;
2427 }
H. Peter Anvind2456592008-06-19 15:04:18 -07002428 free_tlist(origline);
2429 return DIRECTIVE_FOUND;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002430 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002431 case PP_PUSH:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002432 case PP_REPL:
H. Peter Anvin42b56392008-10-24 16:24:21 -07002433 case PP_POP:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002434 tline = tline->next;
2435 skip_white_(tline);
2436 tline = expand_id(tline);
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002437 if (tline) {
2438 if (!tok_type_(tline, TOK_ID)) {
H. Peter Anvin42b56392008-10-24 16:24:21 -07002439 error(ERR_NONFATAL, "`%s' expects a context identifier",
2440 pp_directives[i]);
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002441 free_tlist(origline);
2442 return DIRECTIVE_FOUND; /* but we did _something_ */
2443 }
2444 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002445 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin42b56392008-10-24 16:24:21 -07002446 "trailing garbage after `%s' ignored",
2447 pp_directives[i]);
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002448 p = nasm_strdup(tline->text);
2449 } else {
H. Peter Anvin42b56392008-10-24 16:24:21 -07002450 p = NULL; /* Anonymous */
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002451 }
H. Peter Anvin42b56392008-10-24 16:24:21 -07002452
2453 if (i == PP_PUSH) {
2454 ctx = nasm_malloc(sizeof(Context));
2455 ctx->next = cstk;
2456 hash_init(&ctx->localmac, HASH_SMALL);
2457 ctx->name = p;
2458 ctx->number = unique++;
2459 cstk = ctx;
2460 } else {
2461 /* %pop or %repl */
2462 if (!cstk) {
2463 error(ERR_NONFATAL, "`%s': context stack is empty",
2464 pp_directives[i]);
2465 } else if (i == PP_POP) {
2466 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
2467 error(ERR_NONFATAL, "`%%pop' in wrong context: %s, "
2468 "expected %s",
2469 cstk->name ? cstk->name : "anonymous", p);
2470 else
2471 ctx_pop();
2472 } else {
2473 /* i == PP_REPL */
2474 nasm_free(cstk->name);
2475 cstk->name = p;
2476 p = NULL;
2477 }
2478 nasm_free(p);
2479 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002480 free_tlist(origline);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002481 return DIRECTIVE_FOUND;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002482 case PP_FATAL:
H. Peter Anvin931cab62009-07-07 16:06:21 -07002483 severity = ERR_FATAL;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002484 goto issue_error;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002485 case PP_ERROR:
H. Peter Anvin931cab62009-07-07 16:06:21 -07002486 severity = ERR_NONFATAL;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002487 goto issue_error;
H. Peter Anvin7df04172008-06-10 18:27:38 -07002488 case PP_WARNING:
H. Peter Anvin931cab62009-07-07 16:06:21 -07002489 severity = ERR_WARNING|ERR_WARN_USER;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002490 goto issue_error;
2491
2492 issue_error:
H. Peter Anvin7df04172008-06-10 18:27:38 -07002493 {
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002494 /* Only error out if this is the final pass */
2495 if (pass != 2 && i != PP_FATAL)
2496 return DIRECTIVE_FOUND;
H. Peter Anvin89cee572009-07-15 09:16:54 -04002497
2498 tline->next = expand_smacro(tline->next);
2499 tline = tline->next;
2500 skip_white_(tline);
H. Peter Anvin7df04172008-06-10 18:27:38 -07002501 t = tline ? tline->next : NULL;
2502 skip_white_(t);
H. Peter Anvin89cee572009-07-15 09:16:54 -04002503 if (tok_type_(tline, TOK_STRING) && !t) {
H. Peter Anvin7df04172008-06-10 18:27:38 -07002504 /* The line contains only a quoted string */
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07002505 p = tline->text;
H. Peter Anvinf9c9a672009-07-14 15:14:05 -04002506 nasm_unquote(p, NULL); /* Ignore NUL character truncation */
H. Peter Anvin931cab62009-07-07 16:06:21 -07002507 error(severity, "%s", p);
H. Peter Anvin7df04172008-06-10 18:27:38 -07002508 } else {
2509 /* Not a quoted string, or more than a quoted string */
H. Peter Anvin89cee572009-07-15 09:16:54 -04002510 p = detoken(tline, false);
H. Peter Anvin931cab62009-07-07 16:06:21 -07002511 error(severity, "%s", p);
H. Peter Anvin7df04172008-06-10 18:27:38 -07002512 nasm_free(p);
H. Peter Anvind2456592008-06-19 15:04:18 -07002513 }
H. Peter Anvin89cee572009-07-15 09:16:54 -04002514 free_tlist(origline);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002515 return DIRECTIVE_FOUND;
H. Peter Anvin7df04172008-06-10 18:27:38 -07002516 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002517
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002518 CASE_PP_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002519 if (istk->conds && !emitting(istk->conds->state))
2520 j = COND_NEVER;
2521 else {
2522 j = if_condition(tline->next, i);
2523 tline->next = NULL; /* it got freed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002524 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2525 }
2526 cond = nasm_malloc(sizeof(Cond));
2527 cond->next = istk->conds;
2528 cond->state = j;
2529 istk->conds = cond;
Keith Kanios3c0d91f2009-10-25 13:28:03 -05002530 if(istk->mstk)
2531 istk->mstk->condcnt ++;
H. Peter Anvin7061ad72007-11-26 22:02:21 -08002532 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002533 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002534
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002535 CASE_PP_ELIF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002536 if (!istk->conds)
H. Peter Anvin4169a472007-09-12 01:29:43 +00002537 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002538 switch(istk->conds->state) {
H. Peter Anvin89cee572009-07-15 09:16:54 -04002539 case COND_IF_TRUE:
2540 istk->conds->state = COND_DONE;
2541 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002542
H. Peter Anvin89cee572009-07-15 09:16:54 -04002543 case COND_DONE:
2544 case COND_NEVER:
2545 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002546
H. Peter Anvin89cee572009-07-15 09:16:54 -04002547 case COND_ELSE_TRUE:
2548 case COND_ELSE_FALSE:
2549 error_precond(ERR_WARNING|ERR_PASS1,
2550 "`%%elif' after `%%else' ignored");
2551 istk->conds->state = COND_NEVER;
2552 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002553
H. Peter Anvin89cee572009-07-15 09:16:54 -04002554 case COND_IF_FALSE:
2555 /*
2556 * IMPORTANT: In the case of %if, we will already have
2557 * called expand_mmac_params(); however, if we're
2558 * processing an %elif we must have been in a
2559 * non-emitting mode, which would have inhibited
2560 * the normal invocation of expand_mmac_params().
2561 * Therefore, we have to do it explicitly here.
2562 */
2563 j = if_condition(expand_mmac_params(tline->next), i);
2564 tline->next = NULL; /* it got freed */
2565 istk->conds->state =
2566 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2567 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002568 }
H. Peter Anvin7061ad72007-11-26 22:02:21 -08002569 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002570 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002571
H. Peter Anvine2c80182005-01-15 22:15:51 +00002572 case PP_ELSE:
2573 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002574 error_precond(ERR_WARNING|ERR_PASS1,
2575 "trailing garbage after `%%else' ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00002576 if (!istk->conds)
2577 error(ERR_FATAL, "`%%else': no matching `%%if'");
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002578 switch(istk->conds->state) {
H. Peter Anvin89cee572009-07-15 09:16:54 -04002579 case COND_IF_TRUE:
2580 case COND_DONE:
2581 istk->conds->state = COND_ELSE_FALSE;
2582 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002583
H. Peter Anvin89cee572009-07-15 09:16:54 -04002584 case COND_NEVER:
2585 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002586
H. Peter Anvin89cee572009-07-15 09:16:54 -04002587 case COND_IF_FALSE:
2588 istk->conds->state = COND_ELSE_TRUE;
2589 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002590
H. Peter Anvin89cee572009-07-15 09:16:54 -04002591 case COND_ELSE_TRUE:
2592 case COND_ELSE_FALSE:
2593 error_precond(ERR_WARNING|ERR_PASS1,
2594 "`%%else' after `%%else' ignored.");
2595 istk->conds->state = COND_NEVER;
2596 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002597 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002598 free_tlist(origline);
2599 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002600
H. Peter Anvine2c80182005-01-15 22:15:51 +00002601 case PP_ENDIF:
2602 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002603 error_precond(ERR_WARNING|ERR_PASS1,
2604 "trailing garbage after `%%endif' ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00002605 if (!istk->conds)
2606 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2607 cond = istk->conds;
2608 istk->conds = cond->next;
2609 nasm_free(cond);
Keith Kanios3c0d91f2009-10-25 13:28:03 -05002610 if(istk->mstk)
2611 istk->mstk->condcnt --;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002612 free_tlist(origline);
2613 return DIRECTIVE_FOUND;
Keith Kanios0af5ee22009-07-11 14:26:34 -05002614
H. Peter Anvindb8f96e2009-07-15 09:07:29 -04002615 case PP_RMACRO:
2616 case PP_IRMACRO:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002617 case PP_MACRO:
2618 case PP_IMACRO:
H. Peter Anvina26433d2008-07-16 14:40:01 -07002619 if (defining) {
H. Peter Anvindb8f96e2009-07-15 09:07:29 -04002620 error(ERR_FATAL, "`%s': already defining a macro",
2621 pp_directives[i]);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002622 return DIRECTIVE_FOUND;
2623 }
H. Peter Anvindb8f96e2009-07-15 09:07:29 -04002624 defining = nasm_malloc(sizeof(MMacro));
2625 defining->max_depth =
2626 (i == PP_RMACRO) || (i == PP_IRMACRO) ? DEADMAN_LIMIT : 0;
2627 defining->casesense = (i == PP_MACRO) || (i == PP_RMACRO);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002628 if (!parse_mmacro_spec(tline, defining, pp_directives[i])) {
2629 nasm_free(defining);
2630 defining = NULL;
2631 return DIRECTIVE_FOUND;
2632 }
2633
H. Peter Anvin166c2472008-05-28 12:28:58 -07002634 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002635 while (mmac) {
2636 if (!strcmp(mmac->name, defining->name) &&
2637 (mmac->nparam_min <= defining->nparam_max
2638 || defining->plus)
2639 && (defining->nparam_min <= mmac->nparam_max
2640 || mmac->plus)) {
H. Peter Anvin917a3492008-09-24 09:14:49 -07002641 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002642 "redefining multi-line macro `%s'", defining->name);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002643 return DIRECTIVE_FOUND;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002644 }
2645 mmac = mmac->next;
2646 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002647 free_tlist(origline);
2648 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002649
H. Peter Anvine2c80182005-01-15 22:15:51 +00002650 case PP_ENDM:
2651 case PP_ENDMACRO:
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02002652 if (! (defining && defining->name)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002653 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2654 return DIRECTIVE_FOUND;
2655 }
Keith Kanios852f1ee2009-07-12 00:19:55 -05002656 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002657 defining->next = *mmhead;
Keith Kanios852f1ee2009-07-12 00:19:55 -05002658 *mmhead = defining;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002659 defining = NULL;
2660 free_tlist(origline);
2661 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002662
H. Peter Anvin89cee572009-07-15 09:16:54 -04002663 case PP_EXITMACRO:
Keith Kanios852f1ee2009-07-12 00:19:55 -05002664 /*
2665 * We must search along istk->expansion until we hit a
Keith Kanios3c0d91f2009-10-25 13:28:03 -05002666 * macro-end marker for a macro with a name. Then we
2667 * bypass all lines between exitmacro and endmacro.
Keith Kanios852f1ee2009-07-12 00:19:55 -05002668 */
H. Peter Anvin89cee572009-07-15 09:16:54 -04002669 for (l = istk->expansion; l; l = l->next)
Keith Kanios852f1ee2009-07-12 00:19:55 -05002670 if (l->finishes && l->finishes->name)
2671 break;
2672
2673 if (l) {
Keith Kanios3c0d91f2009-10-25 13:28:03 -05002674 /*
2675 * Remove all conditional entries relative to this
2676 * macro invocation. (safe to do in this context)
2677 */
2678 for ( ; l->finishes->condcnt > 0; l->finishes->condcnt --) {
2679 cond = istk->conds;
2680 istk->conds = cond->next;
2681 nasm_free(cond);
2682 }
2683 istk->expansion = l;
Keith Kanios852f1ee2009-07-12 00:19:55 -05002684 } else {
2685 error(ERR_NONFATAL, "`%%exitmacro' not within `%%macro' block");
H. Peter Anvin89cee572009-07-15 09:16:54 -04002686 }
Keith Kanios852f1ee2009-07-12 00:19:55 -05002687 free_tlist(origline);
2688 return DIRECTIVE_FOUND;
2689
H. Peter Anvina26433d2008-07-16 14:40:01 -07002690 case PP_UNMACRO:
2691 case PP_UNIMACRO:
2692 {
2693 MMacro **mmac_p;
2694 MMacro spec;
2695
2696 spec.casesense = (i == PP_UNMACRO);
2697 if (!parse_mmacro_spec(tline, &spec, pp_directives[i])) {
2698 return DIRECTIVE_FOUND;
2699 }
2700 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
2701 while (mmac_p && *mmac_p) {
2702 mmac = *mmac_p;
2703 if (mmac->casesense == spec.casesense &&
2704 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
2705 mmac->nparam_min == spec.nparam_min &&
2706 mmac->nparam_max == spec.nparam_max &&
2707 mmac->plus == spec.plus) {
2708 *mmac_p = mmac->next;
2709 free_mmacro(mmac);
2710 } else {
2711 mmac_p = &mmac->next;
2712 }
2713 }
2714 free_tlist(origline);
2715 free_tlist(spec.dlist);
2716 return DIRECTIVE_FOUND;
2717 }
2718
H. Peter Anvine2c80182005-01-15 22:15:51 +00002719 case PP_ROTATE:
2720 if (tline->next && tline->next->type == TOK_WHITESPACE)
2721 tline = tline->next;
H. Peter Anvin89cee572009-07-15 09:16:54 -04002722 if (!tline->next) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002723 free_tlist(origline);
2724 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2725 return DIRECTIVE_FOUND;
2726 }
2727 t = expand_smacro(tline->next);
2728 tline->next = NULL;
2729 free_tlist(origline);
2730 tline = t;
2731 tptr = &t;
2732 tokval.t_type = TOKEN_INVALID;
2733 evalresult =
2734 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2735 free_tlist(tline);
2736 if (!evalresult)
2737 return DIRECTIVE_FOUND;
2738 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002739 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002740 "trailing garbage after expression ignored");
2741 if (!is_simple(evalresult)) {
2742 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2743 return DIRECTIVE_FOUND;
2744 }
2745 mmac = istk->mstk;
2746 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2747 mmac = mmac->next_active;
2748 if (!mmac) {
2749 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2750 } else if (mmac->nparam == 0) {
2751 error(ERR_NONFATAL,
2752 "`%%rotate' invoked within macro without parameters");
2753 } else {
H. Peter Anvin25a99342007-09-22 17:45:45 -07002754 int rotate = mmac->rotate + reloc_value(evalresult);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002755
H. Peter Anvin25a99342007-09-22 17:45:45 -07002756 rotate %= (int)mmac->nparam;
2757 if (rotate < 0)
2758 rotate += mmac->nparam;
H. Peter Anvin70653092007-10-19 14:42:29 -07002759
H. Peter Anvin25a99342007-09-22 17:45:45 -07002760 mmac->rotate = rotate;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002761 }
2762 return DIRECTIVE_FOUND;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002763
H. Peter Anvine2c80182005-01-15 22:15:51 +00002764 case PP_REP:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002765 nolist = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002766 do {
2767 tline = tline->next;
2768 } while (tok_type_(tline, TOK_WHITESPACE));
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002769
H. Peter Anvine2c80182005-01-15 22:15:51 +00002770 if (tok_type_(tline, TOK_ID) &&
2771 nasm_stricmp(tline->text, ".nolist") == 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002772 nolist = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002773 do {
2774 tline = tline->next;
2775 } while (tok_type_(tline, TOK_WHITESPACE));
2776 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002777
H. Peter Anvine2c80182005-01-15 22:15:51 +00002778 if (tline) {
2779 t = expand_smacro(tline);
2780 tptr = &t;
2781 tokval.t_type = TOKEN_INVALID;
2782 evalresult =
2783 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2784 if (!evalresult) {
2785 free_tlist(origline);
2786 return DIRECTIVE_FOUND;
2787 }
2788 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002789 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002790 "trailing garbage after expression ignored");
2791 if (!is_simple(evalresult)) {
2792 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2793 return DIRECTIVE_FOUND;
2794 }
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002795 count = reloc_value(evalresult) + 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002796 } else {
2797 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002798 count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002799 }
2800 free_tlist(origline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002801
H. Peter Anvine2c80182005-01-15 22:15:51 +00002802 tmp_defining = defining;
2803 defining = nasm_malloc(sizeof(MMacro));
H. Peter Anvin89cee572009-07-15 09:16:54 -04002804 defining->prev = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002805 defining->name = NULL; /* flags this macro as a %rep block */
H. Peter Anvin70055962007-10-11 00:05:31 -07002806 defining->casesense = false;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002807 defining->plus = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002808 defining->nolist = nolist;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002809 defining->in_progress = count;
H. Peter Anvin89cee572009-07-15 09:16:54 -04002810 defining->max_depth = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002811 defining->nparam_min = defining->nparam_max = 0;
2812 defining->defaults = NULL;
2813 defining->dlist = NULL;
2814 defining->expansion = NULL;
2815 defining->next_active = istk->mstk;
2816 defining->rep_nest = tmp_defining;
2817 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002818
H. Peter Anvine2c80182005-01-15 22:15:51 +00002819 case PP_ENDREP:
2820 if (!defining || defining->name) {
2821 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2822 return DIRECTIVE_FOUND;
2823 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002824
H. Peter Anvine2c80182005-01-15 22:15:51 +00002825 /*
2826 * Now we have a "macro" defined - although it has no name
2827 * and we won't be entering it in the hash tables - we must
2828 * push a macro-end marker for it on to istk->expansion.
2829 * After that, it will take care of propagating itself (a
2830 * macro-end marker line for a macro which is really a %rep
2831 * block will cause the macro to be re-expanded, complete
2832 * with another macro-end marker to ensure the process
2833 * continues) until the whole expansion is forcibly removed
2834 * from istk->expansion by a %exitrep.
2835 */
2836 l = nasm_malloc(sizeof(Line));
2837 l->next = istk->expansion;
2838 l->finishes = defining;
2839 l->first = NULL;
2840 istk->expansion = l;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002841
H. Peter Anvine2c80182005-01-15 22:15:51 +00002842 istk->mstk = defining;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002843
H. Peter Anvine2c80182005-01-15 22:15:51 +00002844 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2845 tmp_defining = defining;
2846 defining = defining->rep_nest;
2847 free_tlist(origline);
2848 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002849
H. Peter Anvine2c80182005-01-15 22:15:51 +00002850 case PP_EXITREP:
2851 /*
2852 * We must search along istk->expansion until we hit a
2853 * macro-end marker for a macro with no name. Then we set
2854 * its `in_progress' flag to 0.
2855 */
2856 for (l = istk->expansion; l; l = l->next)
2857 if (l->finishes && !l->finishes->name)
H. Peter Anvinca348b62008-07-23 10:49:26 -04002858 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002859
H. Peter Anvine2c80182005-01-15 22:15:51 +00002860 if (l)
Charles Crayned4200be2008-07-12 16:42:33 -07002861 l->finishes->in_progress = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002862 else
2863 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2864 free_tlist(origline);
2865 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002866
H. Peter Anvine2c80182005-01-15 22:15:51 +00002867 case PP_XDEFINE:
2868 case PP_IXDEFINE:
2869 case PP_DEFINE:
2870 case PP_IDEFINE:
H. Peter Anvin95e7f952007-10-11 13:38:38 -07002871 casesense = (i == PP_DEFINE || i == PP_XDEFINE);
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002872
H. Peter Anvine2c80182005-01-15 22:15:51 +00002873 tline = tline->next;
2874 skip_white_(tline);
2875 tline = expand_id(tline);
2876 if (!tline || (tline->type != TOK_ID &&
2877 (tline->type != TOK_PREPROC_ID ||
2878 tline->text[1] != '$'))) {
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002879 error(ERR_NONFATAL, "`%s' expects a macro identifier",
2880 pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002881 free_tlist(origline);
2882 return DIRECTIVE_FOUND;
2883 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002884
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002885 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002886 last = tline;
2887 param_start = tline = tline->next;
2888 nparam = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002889
H. Peter Anvine2c80182005-01-15 22:15:51 +00002890 /* Expand the macro definition now for %xdefine and %ixdefine */
2891 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2892 tline = expand_smacro(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002893
H. Peter Anvine2c80182005-01-15 22:15:51 +00002894 if (tok_is_(tline, "(")) {
2895 /*
2896 * This macro has parameters.
2897 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002898
H. Peter Anvine2c80182005-01-15 22:15:51 +00002899 tline = tline->next;
2900 while (1) {
2901 skip_white_(tline);
2902 if (!tline) {
2903 error(ERR_NONFATAL, "parameter identifier expected");
2904 free_tlist(origline);
2905 return DIRECTIVE_FOUND;
2906 }
2907 if (tline->type != TOK_ID) {
2908 error(ERR_NONFATAL,
2909 "`%s': parameter identifier expected",
2910 tline->text);
2911 free_tlist(origline);
2912 return DIRECTIVE_FOUND;
2913 }
2914 tline->type = TOK_SMAC_PARAM + nparam++;
2915 tline = tline->next;
2916 skip_white_(tline);
2917 if (tok_is_(tline, ",")) {
2918 tline = tline->next;
H. Peter Anvinca348b62008-07-23 10:49:26 -04002919 } else {
2920 if (!tok_is_(tline, ")")) {
2921 error(ERR_NONFATAL,
2922 "`)' expected to terminate macro template");
2923 free_tlist(origline);
2924 return DIRECTIVE_FOUND;
2925 }
2926 break;
2927 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002928 }
2929 last = tline;
2930 tline = tline->next;
2931 }
2932 if (tok_type_(tline, TOK_WHITESPACE))
2933 last = tline, tline = tline->next;
2934 macro_start = NULL;
2935 last->next = NULL;
2936 t = tline;
2937 while (t) {
2938 if (t->type == TOK_ID) {
2939 for (tt = param_start; tt; tt = tt->next)
2940 if (tt->type >= TOK_SMAC_PARAM &&
2941 !strcmp(tt->text, t->text))
2942 t->type = tt->type;
2943 }
2944 tt = t->next;
2945 t->next = macro_start;
2946 macro_start = t;
2947 t = tt;
2948 }
2949 /*
2950 * Good. We now have a macro name, a parameter count, and a
2951 * token list (in reverse order) for an expansion. We ought
2952 * to be OK just to create an SMacro, store it, and let
2953 * free_tlist have the rest of the line (which we have
2954 * carefully re-terminated after chopping off the expansion
2955 * from the end).
2956 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002957 define_smacro(ctx, mname, casesense, nparam, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002958 free_tlist(origline);
2959 return DIRECTIVE_FOUND;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002960
H. Peter Anvine2c80182005-01-15 22:15:51 +00002961 case PP_UNDEF:
2962 tline = tline->next;
2963 skip_white_(tline);
2964 tline = expand_id(tline);
2965 if (!tline || (tline->type != TOK_ID &&
2966 (tline->type != TOK_PREPROC_ID ||
2967 tline->text[1] != '$'))) {
2968 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2969 free_tlist(origline);
2970 return DIRECTIVE_FOUND;
2971 }
2972 if (tline->next) {
H. Peter Anvin917a3492008-09-24 09:14:49 -07002973 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002974 "trailing garbage after macro name ignored");
2975 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002976
H. Peter Anvine2c80182005-01-15 22:15:51 +00002977 /* Find the context that symbol belongs to */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002978 ctx = get_ctx(tline->text, &mname, false);
2979 undef_smacro(ctx, mname);
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002980 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002981 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002982
H. Peter Anvin9e200162008-06-04 17:23:14 -07002983 case PP_DEFSTR:
2984 case PP_IDEFSTR:
2985 casesense = (i == PP_DEFSTR);
2986
2987 tline = tline->next;
2988 skip_white_(tline);
2989 tline = expand_id(tline);
2990 if (!tline || (tline->type != TOK_ID &&
2991 (tline->type != TOK_PREPROC_ID ||
2992 tline->text[1] != '$'))) {
2993 error(ERR_NONFATAL, "`%s' expects a macro identifier",
2994 pp_directives[i]);
2995 free_tlist(origline);
2996 return DIRECTIVE_FOUND;
2997 }
2998
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002999 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvin9e200162008-06-04 17:23:14 -07003000 last = tline;
3001 tline = expand_smacro(tline->next);
3002 last->next = NULL;
3003
3004 while (tok_type_(tline, TOK_WHITESPACE))
3005 tline = delete_Token(tline);
3006
3007 p = detoken(tline, false);
3008 macro_start = nasm_malloc(sizeof(*macro_start));
3009 macro_start->next = NULL;
3010 macro_start->text = nasm_quote(p, strlen(p));
3011 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003012 macro_start->a.mac = NULL;
H. Peter Anvin9e200162008-06-04 17:23:14 -07003013 nasm_free(p);
3014
3015 /*
3016 * We now have a macro name, an implicit parameter count of
3017 * zero, and a string token to use as an expansion. Create
3018 * and store an SMacro.
3019 */
3020 define_smacro(ctx, mname, casesense, 0, macro_start);
3021 free_tlist(origline);
3022 return DIRECTIVE_FOUND;
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003023
H. Peter Anvin2f55bda2009-07-14 15:04:04 -04003024 case PP_DEFTOK:
3025 case PP_IDEFTOK:
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003026 casesense = (i == PP_DEFTOK);
H. Peter Anvin89cee572009-07-15 09:16:54 -04003027
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003028 tline = tline->next;
3029 skip_white_(tline);
3030 tline = expand_id(tline);
3031 if (!tline || (tline->type != TOK_ID &&
3032 (tline->type != TOK_PREPROC_ID ||
3033 tline->text[1] != '$'))) {
3034 error(ERR_NONFATAL,
3035 "`%s' expects a macro identifier as first parameter",
H. Peter Anvin89cee572009-07-15 09:16:54 -04003036 pp_directives[i]);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003037 free_tlist(origline);
3038 return DIRECTIVE_FOUND;
3039 }
3040 ctx = get_ctx(tline->text, &mname, false);
3041 last = tline;
3042 tline = expand_smacro(tline->next);
3043 last->next = NULL;
3044
3045 t = tline;
3046 while (tok_type_(t, TOK_WHITESPACE))
3047 t = t->next;
3048 /* t should now point to the string */
3049 if (t->type != TOK_STRING) {
3050 error(ERR_NONFATAL,
3051 "`%s` requires string as second parameter",
H. Peter Anvin89cee572009-07-15 09:16:54 -04003052 pp_directives[i]);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003053 free_tlist(tline);
3054 free_tlist(origline);
3055 return DIRECTIVE_FOUND;
3056 }
3057
H. Peter Anvinf9c9a672009-07-14 15:14:05 -04003058 nasm_unquote_cstr(t->text, i);
H. Peter Anvin2f55bda2009-07-14 15:04:04 -04003059 macro_start = tokenize(t->text);
H. Peter Anvin89cee572009-07-15 09:16:54 -04003060
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003061 /*
3062 * We now have a macro name, an implicit parameter count of
3063 * zero, and a numeric token to use as an expansion. Create
3064 * and store an SMacro.
3065 */
3066 define_smacro(ctx, mname, casesense, 0, macro_start);
3067 free_tlist(tline);
3068 free_tlist(origline);
3069 return DIRECTIVE_FOUND;
H. Peter Anvin9e200162008-06-04 17:23:14 -07003070
H. Peter Anvin418ca702008-05-30 10:42:30 -07003071 case PP_PATHSEARCH:
3072 {
3073 FILE *fp;
3074 StrList *xsl = NULL;
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07003075 StrList **xst = &xsl;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003076
3077 casesense = true;
3078
3079 tline = tline->next;
3080 skip_white_(tline);
3081 tline = expand_id(tline);
3082 if (!tline || (tline->type != TOK_ID &&
3083 (tline->type != TOK_PREPROC_ID ||
3084 tline->text[1] != '$'))) {
3085 error(ERR_NONFATAL,
3086 "`%%pathsearch' expects a macro identifier as first parameter");
3087 free_tlist(origline);
3088 return DIRECTIVE_FOUND;
3089 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003090 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003091 last = tline;
3092 tline = expand_smacro(tline->next);
3093 last->next = NULL;
3094
3095 t = tline;
3096 while (tok_type_(t, TOK_WHITESPACE))
3097 t = t->next;
3098
3099 if (!t || (t->type != TOK_STRING &&
3100 t->type != TOK_INTERNAL_STRING)) {
3101 error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
3102 free_tlist(tline);
3103 free_tlist(origline);
3104 return DIRECTIVE_FOUND; /* but we did _something_ */
3105 }
3106 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07003107 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin418ca702008-05-30 10:42:30 -07003108 "trailing garbage after `%%pathsearch' ignored");
H. Peter Anvin427cc912008-06-01 21:43:03 -07003109 p = t->text;
3110 if (t->type != TOK_INTERNAL_STRING)
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003111 nasm_unquote(p, NULL);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003112
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07003113 fp = inc_fopen(p, &xsl, &xst, true);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003114 if (fp) {
3115 p = xsl->str;
3116 fclose(fp); /* Don't actually care about the file */
3117 }
3118 macro_start = nasm_malloc(sizeof(*macro_start));
3119 macro_start->next = NULL;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003120 macro_start->text = nasm_quote(p, strlen(p));
H. Peter Anvin418ca702008-05-30 10:42:30 -07003121 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003122 macro_start->a.mac = NULL;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003123 if (xsl)
3124 nasm_free(xsl);
3125
3126 /*
3127 * We now have a macro name, an implicit parameter count of
3128 * zero, and a string token to use as an expansion. Create
3129 * and store an SMacro.
3130 */
3131 define_smacro(ctx, mname, casesense, 0, macro_start);
3132 free_tlist(tline);
3133 free_tlist(origline);
3134 return DIRECTIVE_FOUND;
3135 }
3136
H. Peter Anvine2c80182005-01-15 22:15:51 +00003137 case PP_STRLEN:
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003138 casesense = true;
H. Peter Anvin70653092007-10-19 14:42:29 -07003139
H. Peter Anvine2c80182005-01-15 22:15:51 +00003140 tline = tline->next;
3141 skip_white_(tline);
3142 tline = expand_id(tline);
3143 if (!tline || (tline->type != TOK_ID &&
3144 (tline->type != TOK_PREPROC_ID ||
3145 tline->text[1] != '$'))) {
3146 error(ERR_NONFATAL,
3147 "`%%strlen' expects a macro identifier as first parameter");
3148 free_tlist(origline);
3149 return DIRECTIVE_FOUND;
3150 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003151 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003152 last = tline;
3153 tline = expand_smacro(tline->next);
3154 last->next = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003155
H. Peter Anvine2c80182005-01-15 22:15:51 +00003156 t = tline;
3157 while (tok_type_(t, TOK_WHITESPACE))
3158 t = t->next;
3159 /* t should now point to the string */
3160 if (t->type != TOK_STRING) {
3161 error(ERR_NONFATAL,
3162 "`%%strlen` requires string as second parameter");
3163 free_tlist(tline);
3164 free_tlist(origline);
3165 return DIRECTIVE_FOUND;
3166 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003167
H. Peter Anvine2c80182005-01-15 22:15:51 +00003168 macro_start = nasm_malloc(sizeof(*macro_start));
3169 macro_start->next = NULL;
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003170 make_tok_num(macro_start, nasm_unquote(t->text, NULL));
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003171 macro_start->a.mac = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003172
H. Peter Anvine2c80182005-01-15 22:15:51 +00003173 /*
3174 * We now have a macro name, an implicit parameter count of
3175 * zero, and a numeric token to use as an expansion. Create
3176 * and store an SMacro.
3177 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003178 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003179 free_tlist(tline);
3180 free_tlist(origline);
3181 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003182
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003183 case PP_STRCAT:
3184 casesense = true;
3185
3186 tline = tline->next;
3187 skip_white_(tline);
3188 tline = expand_id(tline);
3189 if (!tline || (tline->type != TOK_ID &&
3190 (tline->type != TOK_PREPROC_ID ||
3191 tline->text[1] != '$'))) {
3192 error(ERR_NONFATAL,
3193 "`%%strcat' expects a macro identifier as first parameter");
3194 free_tlist(origline);
3195 return DIRECTIVE_FOUND;
3196 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003197 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003198 last = tline;
3199 tline = expand_smacro(tline->next);
3200 last->next = NULL;
3201
3202 len = 0;
3203 for (t = tline; t; t = t->next) {
3204 switch (t->type) {
3205 case TOK_WHITESPACE:
3206 break;
3207 case TOK_STRING:
3208 len += t->a.len = nasm_unquote(t->text, NULL);
3209 break;
H. Peter Anvinaccf4332008-07-01 21:42:08 -07003210 case TOK_OTHER:
3211 if (!strcmp(t->text, ",")) /* permit comma separators */
3212 break;
3213 /* else fall through */
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003214 default:
3215 error(ERR_NONFATAL,
3216 "non-string passed to `%%strcat' (%d)", t->type);
3217 free_tlist(tline);
3218 free_tlist(origline);
3219 return DIRECTIVE_FOUND;
3220 }
3221 }
3222
3223 p = pp = nasm_malloc(len);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003224 for (t = tline; t; t = t->next) {
3225 if (t->type == TOK_STRING) {
3226 memcpy(p, t->text, t->a.len);
3227 p += t->a.len;
3228 }
3229 }
3230
3231 /*
3232 * We now have a macro name, an implicit parameter count of
3233 * zero, and a numeric token to use as an expansion. Create
3234 * and store an SMacro.
3235 */
3236 macro_start = new_Token(NULL, TOK_STRING, NULL, 0);
3237 macro_start->text = nasm_quote(pp, len);
3238 nasm_free(pp);
3239 define_smacro(ctx, mname, casesense, 0, macro_start);
3240 free_tlist(tline);
3241 free_tlist(origline);
3242 return DIRECTIVE_FOUND;
3243
H. Peter Anvine2c80182005-01-15 22:15:51 +00003244 case PP_SUBSTR:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003245 {
3246 int64_t a1, a2;
3247 size_t len;
H. Peter Anvind2456592008-06-19 15:04:18 -07003248
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003249 casesense = true;
3250
H. Peter Anvine2c80182005-01-15 22:15:51 +00003251 tline = tline->next;
3252 skip_white_(tline);
3253 tline = expand_id(tline);
3254 if (!tline || (tline->type != TOK_ID &&
3255 (tline->type != TOK_PREPROC_ID ||
3256 tline->text[1] != '$'))) {
3257 error(ERR_NONFATAL,
3258 "`%%substr' expects a macro identifier as first parameter");
3259 free_tlist(origline);
3260 return DIRECTIVE_FOUND;
3261 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003262 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003263 last = tline;
3264 tline = expand_smacro(tline->next);
3265 last->next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003266
H. Peter Anvine2c80182005-01-15 22:15:51 +00003267 t = tline->next;
3268 while (tok_type_(t, TOK_WHITESPACE))
3269 t = t->next;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003270
H. Peter Anvine2c80182005-01-15 22:15:51 +00003271 /* t should now point to the string */
3272 if (t->type != TOK_STRING) {
3273 error(ERR_NONFATAL,
3274 "`%%substr` requires string as second parameter");
3275 free_tlist(tline);
3276 free_tlist(origline);
3277 return DIRECTIVE_FOUND;
3278 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003279
H. Peter Anvine2c80182005-01-15 22:15:51 +00003280 tt = t->next;
3281 tptr = &tt;
3282 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003283 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3284 pass, error, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003285 if (!evalresult) {
3286 free_tlist(tline);
3287 free_tlist(origline);
3288 return DIRECTIVE_FOUND;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003289 } else if (!is_simple(evalresult)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003290 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3291 free_tlist(tline);
3292 free_tlist(origline);
3293 return DIRECTIVE_FOUND;
3294 }
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003295 a1 = evalresult->value-1;
3296
3297 while (tok_type_(tt, TOK_WHITESPACE))
3298 tt = tt->next;
3299 if (!tt) {
3300 a2 = 1; /* Backwards compatibility: one character */
3301 } else {
3302 tokval.t_type = TOKEN_INVALID;
3303 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3304 pass, error, NULL);
3305 if (!evalresult) {
3306 free_tlist(tline);
3307 free_tlist(origline);
3308 return DIRECTIVE_FOUND;
3309 } else if (!is_simple(evalresult)) {
3310 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3311 free_tlist(tline);
3312 free_tlist(origline);
3313 return DIRECTIVE_FOUND;
3314 }
3315 a2 = evalresult->value;
3316 }
3317
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003318 len = nasm_unquote(t->text, NULL);
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003319 if (a2 < 0)
3320 a2 = a2+1+len-a1;
3321 if (a1+a2 > (int64_t)len)
3322 a2 = len-a1;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003323
H. Peter Anvine2c80182005-01-15 22:15:51 +00003324 macro_start = nasm_malloc(sizeof(*macro_start));
3325 macro_start->next = NULL;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003326 macro_start->text = nasm_quote((a1 < 0) ? "" : t->text+a1, a2);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003327 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003328 macro_start->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003329
H. Peter Anvine2c80182005-01-15 22:15:51 +00003330 /*
3331 * We now have a macro name, an implicit parameter count of
3332 * zero, and a numeric token to use as an expansion. Create
3333 * and store an SMacro.
3334 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003335 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003336 free_tlist(tline);
3337 free_tlist(origline);
3338 return DIRECTIVE_FOUND;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003339 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003340
H. Peter Anvine2c80182005-01-15 22:15:51 +00003341 case PP_ASSIGN:
3342 case PP_IASSIGN:
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003343 casesense = (i == PP_ASSIGN);
3344
H. Peter Anvine2c80182005-01-15 22:15:51 +00003345 tline = tline->next;
3346 skip_white_(tline);
3347 tline = expand_id(tline);
3348 if (!tline || (tline->type != TOK_ID &&
3349 (tline->type != TOK_PREPROC_ID ||
3350 tline->text[1] != '$'))) {
3351 error(ERR_NONFATAL,
3352 "`%%%sassign' expects a macro identifier",
3353 (i == PP_IASSIGN ? "i" : ""));
3354 free_tlist(origline);
3355 return DIRECTIVE_FOUND;
3356 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003357 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003358 last = tline;
3359 tline = expand_smacro(tline->next);
3360 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003361
H. Peter Anvine2c80182005-01-15 22:15:51 +00003362 t = tline;
3363 tptr = &t;
3364 tokval.t_type = TOKEN_INVALID;
3365 evalresult =
3366 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3367 free_tlist(tline);
3368 if (!evalresult) {
3369 free_tlist(origline);
3370 return DIRECTIVE_FOUND;
3371 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003372
H. Peter Anvine2c80182005-01-15 22:15:51 +00003373 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07003374 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003375 "trailing garbage after expression ignored");
H. Peter Anvin734b1882002-04-30 21:01:08 +00003376
H. Peter Anvine2c80182005-01-15 22:15:51 +00003377 if (!is_simple(evalresult)) {
3378 error(ERR_NONFATAL,
3379 "non-constant value given to `%%%sassign'",
3380 (i == PP_IASSIGN ? "i" : ""));
3381 free_tlist(origline);
3382 return DIRECTIVE_FOUND;
3383 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003384
H. Peter Anvine2c80182005-01-15 22:15:51 +00003385 macro_start = nasm_malloc(sizeof(*macro_start));
3386 macro_start->next = NULL;
3387 make_tok_num(macro_start, reloc_value(evalresult));
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003388 macro_start->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003389
H. Peter Anvine2c80182005-01-15 22:15:51 +00003390 /*
3391 * We now have a macro name, an implicit parameter count of
3392 * zero, and a numeric token to use as an expansion. Create
3393 * and store an SMacro.
3394 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003395 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003396 free_tlist(origline);
3397 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003398
H. Peter Anvine2c80182005-01-15 22:15:51 +00003399 case PP_LINE:
3400 /*
3401 * Syntax is `%line nnn[+mmm] [filename]'
3402 */
3403 tline = tline->next;
3404 skip_white_(tline);
3405 if (!tok_type_(tline, TOK_NUMBER)) {
3406 error(ERR_NONFATAL, "`%%line' expects line number");
3407 free_tlist(origline);
3408 return DIRECTIVE_FOUND;
3409 }
H. Peter Anvin70055962007-10-11 00:05:31 -07003410 k = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003411 m = 1;
3412 tline = tline->next;
3413 if (tok_is_(tline, "+")) {
3414 tline = tline->next;
3415 if (!tok_type_(tline, TOK_NUMBER)) {
3416 error(ERR_NONFATAL, "`%%line' expects line increment");
3417 free_tlist(origline);
3418 return DIRECTIVE_FOUND;
3419 }
H. Peter Anvin70055962007-10-11 00:05:31 -07003420 m = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003421 tline = tline->next;
3422 }
3423 skip_white_(tline);
3424 src_set_linnum(k);
3425 istk->lineinc = m;
3426 if (tline) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003427 nasm_free(src_set_fname(detoken(tline, false)));
H. Peter Anvine2c80182005-01-15 22:15:51 +00003428 }
3429 free_tlist(origline);
3430 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003431
H. Peter Anvine2c80182005-01-15 22:15:51 +00003432 default:
3433 error(ERR_FATAL,
3434 "preprocessor directive `%s' not yet implemented",
H. Peter Anvin4169a472007-09-12 01:29:43 +00003435 pp_directives[i]);
H. Peter Anvina26433d2008-07-16 14:40:01 -07003436 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003437 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003438}
3439
3440/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00003441 * Ensure that a macro parameter contains a condition code and
3442 * nothing else. Return the condition code index if so, or -1
3443 * otherwise.
3444 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003445static int find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003446{
H. Peter Anvin76690a12002-04-30 20:52:49 +00003447 Token *tt;
3448 int i, j, k, m;
3449
H. Peter Anvin25a99342007-09-22 17:45:45 -07003450 if (!t)
H. Peter Anvin89cee572009-07-15 09:16:54 -04003451 return -1; /* Probably a %+ without a space */
H. Peter Anvin25a99342007-09-22 17:45:45 -07003452
H. Peter Anvineba20a72002-04-30 20:53:55 +00003453 skip_white_(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003454 if (t->type != TOK_ID)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003455 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003456 tt = t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003457 skip_white_(tt);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003458 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003459 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003460
3461 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +00003462 j = elements(conditions);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003463 while (j - i > 1) {
3464 k = (j + i) / 2;
3465 m = nasm_stricmp(t->text, conditions[k]);
3466 if (m == 0) {
3467 i = k;
3468 j = -2;
3469 break;
3470 } else if (m < 0) {
3471 j = k;
3472 } else
3473 i = k;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003474 }
3475 if (j != -2)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003476 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003477 return i;
3478}
3479
H. Peter Anvind784a082009-04-20 14:01:18 -07003480static bool paste_tokens(Token **head, bool handle_paste_tokens)
3481{
3482 Token **tail, *t, *tt;
3483 Token **paste_head;
3484 bool did_paste = false;
3485 char *tmp;
3486
3487 /* Now handle token pasting... */
3488 paste_head = NULL;
3489 tail = head;
3490 while ((t = *tail) && (tt = t->next)) {
3491 switch (t->type) {
3492 case TOK_WHITESPACE:
3493 if (tt->type == TOK_WHITESPACE) {
3494 /* Zap adjacent whitespace tokens */
3495 t->next = delete_Token(tt);
3496 } else {
3497 /* Do not advance paste_head here */
3498 tail = &t->next;
3499 }
3500 break;
3501 case TOK_ID:
3502 case TOK_PREPROC_ID:
3503 case TOK_NUMBER:
3504 case TOK_FLOAT:
3505 {
3506 size_t len = 0;
3507 char *tmp, *p;
3508
3509 while (tt && (tt->type == TOK_ID || tt->type == TOK_PREPROC_ID ||
3510 tt->type == TOK_NUMBER || tt->type == TOK_FLOAT ||
3511 tt->type == TOK_OTHER)) {
3512 len += strlen(tt->text);
3513 tt = tt->next;
3514 }
3515
3516 /* Now tt points to the first token after the potential
3517 paste area... */
3518 if (tt != t->next) {
3519 /* We have at least two tokens... */
3520 len += strlen(t->text);
3521 p = tmp = nasm_malloc(len+1);
3522
3523 while (t != tt) {
3524 strcpy(p, t->text);
3525 p = strchr(p, '\0');
3526 t = delete_Token(t);
3527 }
3528
3529 t = *tail = tokenize(tmp);
3530 nasm_free(tmp);
3531
3532 while (t->next) {
3533 tail = &t->next;
3534 t = t->next;
3535 }
3536 t->next = tt; /* Attach the remaining token chain */
3537
3538 did_paste = true;
3539 }
3540 paste_head = tail;
3541 tail = &t->next;
3542 break;
3543 }
3544 case TOK_PASTE: /* %+ */
3545 if (handle_paste_tokens) {
3546 /* Zap %+ and whitespace tokens to the right */
3547 while (t && (t->type == TOK_WHITESPACE ||
3548 t->type == TOK_PASTE))
3549 t = *tail = delete_Token(t);
3550 if (!paste_head || !t)
3551 break; /* Nothing to paste with */
3552 tail = paste_head;
3553 t = *tail;
3554 tt = t->next;
3555 while (tok_type_(tt, TOK_WHITESPACE))
3556 tt = t->next = delete_Token(tt);
3557
3558 if (tt) {
3559 tmp = nasm_strcat(t->text, tt->text);
3560 delete_Token(t);
3561 tt = delete_Token(tt);
3562 t = *tail = tokenize(tmp);
3563 nasm_free(tmp);
3564 while (t->next) {
3565 tail = &t->next;
3566 t = t->next;
3567 }
3568 t->next = tt; /* Attach the remaining token chain */
3569 did_paste = true;
3570 }
3571 paste_head = tail;
3572 tail = &t->next;
3573 break;
3574 }
3575 /* else fall through */
3576 default:
3577 tail = paste_head = &t->next;
3578 break;
3579 }
3580 }
3581 return did_paste;
3582}
H. Peter Anvin76690a12002-04-30 20:52:49 +00003583/*
3584 * Expand MMacro-local things: parameter references (%0, %n, %+n,
H. Peter Anvin67c63722008-10-26 23:49:00 -07003585 * %-n) and MMacro-local identifiers (%%foo) as well as
3586 * macro indirection (%[...]).
H. Peter Anvin76690a12002-04-30 20:52:49 +00003587 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003588static Token *expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003589{
H. Peter Anvin734b1882002-04-30 21:01:08 +00003590 Token *t, *tt, **tail, *thead;
H. Peter Anvin6125b622009-04-08 14:02:25 -07003591 bool changed = false;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003592
3593 tail = &thead;
3594 thead = NULL;
3595
H. Peter Anvine2c80182005-01-15 22:15:51 +00003596 while (tline) {
3597 if (tline->type == TOK_PREPROC_ID &&
3598 (((tline->text[1] == '+' || tline->text[1] == '-')
3599 && tline->text[2]) || tline->text[1] == '%'
3600 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003601 char *text = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003602 int type = 0, cc; /* type = 0 to placate optimisers */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003603 char tmpbuf[30];
H. Peter Anvin25a99342007-09-22 17:45:45 -07003604 unsigned int n;
3605 int i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003606 MMacro *mac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003607
H. Peter Anvine2c80182005-01-15 22:15:51 +00003608 t = tline;
3609 tline = tline->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003610
H. Peter Anvine2c80182005-01-15 22:15:51 +00003611 mac = istk->mstk;
3612 while (mac && !mac->name) /* avoid mistaking %reps for macros */
3613 mac = mac->next_active;
3614 if (!mac)
3615 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
3616 else
3617 switch (t->text[1]) {
3618 /*
3619 * We have to make a substitution of one of the
3620 * forms %1, %-1, %+1, %%foo, %0.
3621 */
3622 case '0':
3623 type = TOK_NUMBER;
3624 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
3625 text = nasm_strdup(tmpbuf);
3626 break;
3627 case '%':
3628 type = TOK_ID;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07003629 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
H. Peter Anvine2c80182005-01-15 22:15:51 +00003630 mac->unique);
3631 text = nasm_strcat(tmpbuf, t->text + 2);
3632 break;
3633 case '-':
3634 n = atoi(t->text + 2) - 1;
3635 if (n >= mac->nparam)
3636 tt = NULL;
3637 else {
3638 if (mac->nparam > 1)
3639 n = (n + mac->rotate) % mac->nparam;
3640 tt = mac->params[n];
3641 }
3642 cc = find_cc(tt);
3643 if (cc == -1) {
3644 error(ERR_NONFATAL,
3645 "macro parameter %d is not a condition code",
3646 n + 1);
3647 text = NULL;
3648 } else {
3649 type = TOK_ID;
3650 if (inverse_ccs[cc] == -1) {
3651 error(ERR_NONFATAL,
3652 "condition code `%s' is not invertible",
3653 conditions[cc]);
3654 text = NULL;
3655 } else
H. Peter Anvin67c63722008-10-26 23:49:00 -07003656 text = nasm_strdup(conditions[inverse_ccs[cc]]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003657 }
3658 break;
3659 case '+':
3660 n = atoi(t->text + 2) - 1;
3661 if (n >= mac->nparam)
3662 tt = NULL;
3663 else {
3664 if (mac->nparam > 1)
3665 n = (n + mac->rotate) % mac->nparam;
3666 tt = mac->params[n];
3667 }
3668 cc = find_cc(tt);
3669 if (cc == -1) {
3670 error(ERR_NONFATAL,
3671 "macro parameter %d is not a condition code",
3672 n + 1);
3673 text = NULL;
3674 } else {
3675 type = TOK_ID;
3676 text = nasm_strdup(conditions[cc]);
3677 }
3678 break;
3679 default:
3680 n = atoi(t->text + 1) - 1;
3681 if (n >= mac->nparam)
3682 tt = NULL;
3683 else {
3684 if (mac->nparam > 1)
3685 n = (n + mac->rotate) % mac->nparam;
3686 tt = mac->params[n];
3687 }
3688 if (tt) {
3689 for (i = 0; i < mac->paramlen[n]; i++) {
3690 *tail = new_Token(NULL, tt->type, tt->text, 0);
3691 tail = &(*tail)->next;
3692 tt = tt->next;
3693 }
3694 }
3695 text = NULL; /* we've done it here */
3696 break;
3697 }
3698 if (!text) {
3699 delete_Token(t);
3700 } else {
3701 *tail = t;
3702 tail = &t->next;
3703 t->type = type;
3704 nasm_free(t->text);
3705 t->text = text;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003706 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003707 }
H. Peter Anvin6125b622009-04-08 14:02:25 -07003708 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003709 continue;
H. Peter Anvin67c63722008-10-26 23:49:00 -07003710 } else if (tline->type == TOK_INDIRECT) {
3711 t = tline;
3712 tline = tline->next;
3713 tt = tokenize(t->text);
3714 tt = expand_mmac_params(tt);
3715 tt = expand_smacro(tt);
3716 *tail = tt;
3717 while (tt) {
3718 tt->a.mac = NULL; /* Necessary? */
3719 tail = &tt->next;
3720 tt = tt->next;
3721 }
3722 delete_Token(t);
H. Peter Anvin6125b622009-04-08 14:02:25 -07003723 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003724 } else {
3725 t = *tail = tline;
3726 tline = tline->next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003727 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003728 tail = &t->next;
3729 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003730 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00003731 *tail = NULL;
H. Peter Anvin67c63722008-10-26 23:49:00 -07003732
H. Peter Anvind784a082009-04-20 14:01:18 -07003733 if (changed)
H. Peter Anvinfc30f8c2009-07-06 18:48:23 -07003734 paste_tokens(&thead, false);
H. Peter Anvin6125b622009-04-08 14:02:25 -07003735
H. Peter Anvin76690a12002-04-30 20:52:49 +00003736 return thead;
3737}
3738
3739/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003740 * Expand all single-line macro calls made in the given line.
3741 * Return the expanded version of the line. The original is deemed
3742 * to be destroyed in the process. (In reality we'll just move
3743 * Tokens from input to output a lot of the time, rather than
3744 * actually bothering to destroy and replicate.)
3745 */
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003746
H. Peter Anvine2c80182005-01-15 22:15:51 +00003747static Token *expand_smacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003748{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003749 Token *t, *tt, *mstart, **tail, *thead;
H. Peter Anvin166c2472008-05-28 12:28:58 -07003750 struct hash_table *smtbl;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003751 SMacro *head = NULL, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003752 Token **params;
3753 int *paramsize;
H. Peter Anvin25a99342007-09-22 17:45:45 -07003754 unsigned int nparam, sparam;
H. Peter Anvind784a082009-04-20 14:01:18 -07003755 int brackets;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003756 Token *org_tline = tline;
3757 Context *ctx;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003758 const char *mname;
H. Peter Anvin2a15e692007-11-19 13:14:59 -08003759 int deadman = DEADMAN_LIMIT;
H. Peter Anvin8287daf2009-07-07 16:00:58 -07003760 bool expanded;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003761
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003762 /*
3763 * Trick: we should avoid changing the start token pointer since it can
3764 * be contained in "next" field of other token. Because of this
3765 * we allocate a copy of first token and work with it; at the end of
3766 * routine we copy it back
3767 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003768 if (org_tline) {
3769 tline =
3770 new_Token(org_tline->next, org_tline->type, org_tline->text,
3771 0);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003772 tline->a.mac = org_tline->a.mac;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003773 nasm_free(org_tline->text);
3774 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003775 }
3776
H. Peter Anvin8287daf2009-07-07 16:00:58 -07003777 expanded = true; /* Always expand %+ at least once */
3778
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003779again:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003780 tail = &thead;
3781 thead = NULL;
3782
H. Peter Anvine2c80182005-01-15 22:15:51 +00003783 while (tline) { /* main token loop */
H. Peter Anvin2a15e692007-11-19 13:14:59 -08003784 if (!--deadman) {
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003785 error(ERR_NONFATAL, "interminable macro recursion");
3786 break;
3787 }
3788
H. Peter Anvine2c80182005-01-15 22:15:51 +00003789 if ((mname = tline->text)) {
3790 /* if this token is a local macro, look in local context */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003791 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
3792 ctx = get_ctx(mname, &mname, true);
3793 else
3794 ctx = NULL;
3795 smtbl = ctx ? &ctx->localmac : &smacros;
H. Peter Anvin166c2472008-05-28 12:28:58 -07003796 head = (SMacro *) hash_findix(smtbl, mname);
H. Peter Anvin072771e2008-05-22 13:17:51 -07003797
H. Peter Anvine2c80182005-01-15 22:15:51 +00003798 /*
3799 * We've hit an identifier. As in is_mmacro below, we first
3800 * check whether the identifier is a single-line macro at
3801 * all, then think about checking for parameters if
3802 * necessary.
3803 */
H. Peter Anvin97a23472007-09-16 17:57:25 -07003804 for (m = head; m; m = m->next)
3805 if (!mstrcmp(m->name, mname, m->casesense))
3806 break;
3807 if (m) {
3808 mstart = tline;
3809 params = NULL;
3810 paramsize = NULL;
3811 if (m->nparam == 0) {
3812 /*
3813 * Simple case: the macro is parameterless. Discard the
3814 * one token that the macro call took, and push the
3815 * expansion back on the to-do stack.
3816 */
3817 if (!m->expansion) {
3818 if (!strcmp("__FILE__", m->name)) {
3819 int32_t num = 0;
H. Peter Anvin932de6c2008-07-31 18:46:11 -07003820 char *file = NULL;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003821 src_get(&num, &file);
3822 tline->text = nasm_quote(file, strlen(file));
H. Peter Anvin97a23472007-09-16 17:57:25 -07003823 tline->type = TOK_STRING;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003824 nasm_free(file);
H. Peter Anvin97a23472007-09-16 17:57:25 -07003825 continue;
3826 }
3827 if (!strcmp("__LINE__", m->name)) {
3828 nasm_free(tline->text);
3829 make_tok_num(tline, src_get_linnum());
3830 continue;
3831 }
3832 if (!strcmp("__BITS__", m->name)) {
3833 nasm_free(tline->text);
3834 make_tok_num(tline, globalbits);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003835 continue;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003836 }
3837 tline = delete_Token(tline);
3838 continue;
3839 }
3840 } else {
3841 /*
3842 * Complicated case: at least one macro with this name
H. Peter Anvine2c80182005-01-15 22:15:51 +00003843 * exists and takes parameters. We must find the
3844 * parameters in the call, count them, find the SMacro
3845 * that corresponds to that form of the macro call, and
3846 * substitute for the parameters when we expand. What a
3847 * pain.
3848 */
3849 /*tline = tline->next;
H. Peter Anvin89cee572009-07-15 09:16:54 -04003850 skip_white_(tline); */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003851 do {
3852 t = tline->next;
3853 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003854 t->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003855 t->text = NULL;
3856 t = tline->next = delete_Token(t);
3857 }
3858 tline = t;
3859 } while (tok_type_(tline, TOK_WHITESPACE));
3860 if (!tok_is_(tline, "(")) {
3861 /*
3862 * This macro wasn't called with parameters: ignore
3863 * the call. (Behaviour borrowed from gnu cpp.)
3864 */
3865 tline = mstart;
3866 m = NULL;
3867 } else {
3868 int paren = 0;
3869 int white = 0;
3870 brackets = 0;
3871 nparam = 0;
3872 sparam = PARAM_DELTA;
3873 params = nasm_malloc(sparam * sizeof(Token *));
3874 params[0] = tline->next;
3875 paramsize = nasm_malloc(sparam * sizeof(int));
3876 paramsize[0] = 0;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003877 while (true) { /* parameter loop */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003878 /*
3879 * For some unusual expansions
3880 * which concatenates function call
3881 */
3882 t = tline->next;
3883 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003884 t->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003885 t->text = NULL;
3886 t = tline->next = delete_Token(t);
3887 }
3888 tline = t;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003889
H. Peter Anvine2c80182005-01-15 22:15:51 +00003890 if (!tline) {
3891 error(ERR_NONFATAL,
3892 "macro call expects terminating `)'");
3893 break;
3894 }
3895 if (tline->type == TOK_WHITESPACE
3896 && brackets <= 0) {
3897 if (paramsize[nparam])
3898 white++;
3899 else
3900 params[nparam] = tline->next;
3901 continue; /* parameter loop */
3902 }
3903 if (tline->type == TOK_OTHER
3904 && tline->text[1] == 0) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003905 char ch = tline->text[0];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003906 if (ch == ',' && !paren && brackets <= 0) {
3907 if (++nparam >= sparam) {
3908 sparam += PARAM_DELTA;
3909 params = nasm_realloc(params,
3910 sparam *
3911 sizeof(Token
3912 *));
3913 paramsize =
3914 nasm_realloc(paramsize,
3915 sparam *
3916 sizeof(int));
3917 }
3918 params[nparam] = tline->next;
3919 paramsize[nparam] = 0;
3920 white = 0;
3921 continue; /* parameter loop */
3922 }
3923 if (ch == '{' &&
3924 (brackets > 0 || (brackets == 0 &&
3925 !paramsize[nparam])))
3926 {
3927 if (!(brackets++)) {
3928 params[nparam] = tline->next;
3929 continue; /* parameter loop */
3930 }
3931 }
3932 if (ch == '}' && brackets > 0)
3933 if (--brackets == 0) {
3934 brackets = -1;
3935 continue; /* parameter loop */
3936 }
3937 if (ch == '(' && !brackets)
3938 paren++;
3939 if (ch == ')' && brackets <= 0)
3940 if (--paren < 0)
3941 break;
3942 }
3943 if (brackets < 0) {
3944 brackets = 0;
3945 error(ERR_NONFATAL, "braces do not "
3946 "enclose all of macro parameter");
3947 }
3948 paramsize[nparam] += white + 1;
3949 white = 0;
3950 } /* parameter loop */
3951 nparam++;
3952 while (m && (m->nparam != nparam ||
3953 mstrcmp(m->name, mname,
3954 m->casesense)))
3955 m = m->next;
3956 if (!m)
H. Peter Anvin917a3492008-09-24 09:14:49 -07003957 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003958 "macro `%s' exists, "
3959 "but not taking %d parameters",
3960 mstart->text, nparam);
3961 }
3962 }
3963 if (m && m->in_progress)
3964 m = NULL;
3965 if (!m) { /* in progess or didn't find '(' or wrong nparam */
H. Peter Anvin70653092007-10-19 14:42:29 -07003966 /*
H. Peter Anvine2c80182005-01-15 22:15:51 +00003967 * Design question: should we handle !tline, which
3968 * indicates missing ')' here, or expand those
3969 * macros anyway, which requires the (t) test a few
H. Peter Anvin70653092007-10-19 14:42:29 -07003970 * lines down?
H. Peter Anvine2c80182005-01-15 22:15:51 +00003971 */
3972 nasm_free(params);
3973 nasm_free(paramsize);
3974 tline = mstart;
3975 } else {
3976 /*
3977 * Expand the macro: we are placed on the last token of the
3978 * call, so that we can easily split the call from the
3979 * following tokens. We also start by pushing an SMAC_END
3980 * token for the cycle removal.
3981 */
3982 t = tline;
3983 if (t) {
3984 tline = t->next;
3985 t->next = NULL;
3986 }
3987 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003988 tt->a.mac = m;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003989 m->in_progress = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003990 tline = tt;
3991 for (t = m->expansion; t; t = t->next) {
3992 if (t->type >= TOK_SMAC_PARAM) {
3993 Token *pcopy = tline, **ptail = &pcopy;
3994 Token *ttt, *pt;
3995 int i;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003996
H. Peter Anvine2c80182005-01-15 22:15:51 +00003997 ttt = params[t->type - TOK_SMAC_PARAM];
3998 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3999 --i >= 0;) {
4000 pt = *ptail =
4001 new_Token(tline, ttt->type, ttt->text,
4002 0);
4003 ptail = &pt->next;
4004 ttt = ttt->next;
4005 }
4006 tline = pcopy;
H. Peter Anvin6c81f0a2008-05-25 21:46:17 -07004007 } else if (t->type == TOK_PREPROC_Q) {
4008 tt = new_Token(tline, TOK_ID, mname, 0);
4009 tline = tt;
4010 } else if (t->type == TOK_PREPROC_QQ) {
4011 tt = new_Token(tline, TOK_ID, m->name, 0);
4012 tline = tt;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004013 } else {
4014 tt = new_Token(tline, t->type, t->text, 0);
4015 tline = tt;
4016 }
4017 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004018
H. Peter Anvine2c80182005-01-15 22:15:51 +00004019 /*
4020 * Having done that, get rid of the macro call, and clean
4021 * up the parameters.
4022 */
4023 nasm_free(params);
4024 nasm_free(paramsize);
4025 free_tlist(mstart);
H. Peter Anvind784a082009-04-20 14:01:18 -07004026 expanded = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004027 continue; /* main token loop */
4028 }
4029 }
4030 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004031
H. Peter Anvine2c80182005-01-15 22:15:51 +00004032 if (tline->type == TOK_SMAC_END) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004033 tline->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004034 tline = delete_Token(tline);
4035 } else {
4036 t = *tail = tline;
4037 tline = tline->next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004038 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004039 t->next = NULL;
4040 tail = &t->next;
4041 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004042 }
4043
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004044 /*
4045 * Now scan the entire line and look for successive TOK_IDs that resulted
Keith Kaniosb7a89542007-04-12 02:40:54 +00004046 * after expansion (they can't be produced by tokenize()). The successive
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004047 * TOK_IDs should be concatenated.
4048 * Also we look for %+ tokens and concatenate the tokens before and after
4049 * them (without white spaces in between).
4050 */
H. Peter Anvin8287daf2009-07-07 16:00:58 -07004051 if (expanded && paste_tokens(&thead, true)) {
H. Peter Anvinfc30f8c2009-07-06 18:48:23 -07004052 /*
4053 * If we concatenated something, *and* we had previously expanded
4054 * an actual macro, scan the lines again for macros...
4055 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004056 tline = thead;
H. Peter Anvin8287daf2009-07-07 16:00:58 -07004057 expanded = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004058 goto again;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004059 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004060
H. Peter Anvine2c80182005-01-15 22:15:51 +00004061 if (org_tline) {
4062 if (thead) {
4063 *org_tline = *thead;
4064 /* since we just gave text to org_line, don't free it */
4065 thead->text = NULL;
4066 delete_Token(thead);
4067 } else {
4068 /* the expression expanded to empty line;
4069 we can't return NULL for some reasons
4070 we just set the line to a single WHITESPACE token. */
4071 memset(org_tline, 0, sizeof(*org_tline));
4072 org_tline->text = NULL;
4073 org_tline->type = TOK_WHITESPACE;
4074 }
4075 thead = org_tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004076 }
4077
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004078 return thead;
4079}
4080
4081/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004082 * Similar to expand_smacro but used exclusively with macro identifiers
4083 * right before they are fetched in. The reason is that there can be
4084 * identifiers consisting of several subparts. We consider that if there
4085 * are more than one element forming the name, user wants a expansion,
4086 * otherwise it will be left as-is. Example:
4087 *
4088 * %define %$abc cde
4089 *
4090 * the identifier %$abc will be left as-is so that the handler for %define
4091 * will suck it and define the corresponding value. Other case:
4092 *
4093 * %define _%$abc cde
4094 *
4095 * In this case user wants name to be expanded *before* %define starts
4096 * working, so we'll expand %$abc into something (if it has a value;
4097 * otherwise it will be left as-is) then concatenate all successive
4098 * PP_IDs into one.
4099 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004100static Token *expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004101{
4102 Token *cur, *oldnext = NULL;
4103
H. Peter Anvin734b1882002-04-30 21:01:08 +00004104 if (!tline || !tline->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004105 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004106
4107 cur = tline;
4108 while (cur->next &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00004109 (cur->next->type == TOK_ID ||
4110 cur->next->type == TOK_PREPROC_ID
4111 || cur->next->type == TOK_NUMBER))
4112 cur = cur->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004113
4114 /* If identifier consists of just one token, don't expand */
4115 if (cur == tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004116 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004117
H. Peter Anvine2c80182005-01-15 22:15:51 +00004118 if (cur) {
4119 oldnext = cur->next; /* Detach the tail past identifier */
4120 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004121 }
4122
H. Peter Anvin734b1882002-04-30 21:01:08 +00004123 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004124
H. Peter Anvine2c80182005-01-15 22:15:51 +00004125 if (cur) {
4126 /* expand_smacro possibly changhed tline; re-scan for EOL */
4127 cur = tline;
4128 while (cur && cur->next)
4129 cur = cur->next;
4130 if (cur)
4131 cur->next = oldnext;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004132 }
4133
4134 return tline;
4135}
4136
4137/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004138 * Determine whether the given line constitutes a multi-line macro
4139 * call, and return the MMacro structure called if so. Doesn't have
4140 * to check for an initial label - that's taken care of in
4141 * expand_mmacro - but must check numbers of parameters. Guaranteed
4142 * to be called with tline->type == TOK_ID, so the putative macro
4143 * name is easy to find.
4144 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004145static MMacro *is_mmacro(Token * tline, Token *** params_array)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004146{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004147 MMacro *head, *m;
4148 Token **params;
4149 int nparam;
4150
H. Peter Anvin166c2472008-05-28 12:28:58 -07004151 head = (MMacro *) hash_findix(&mmacros, tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004152
4153 /*
4154 * Efficiency: first we see if any macro exists with the given
4155 * name. If not, we can return NULL immediately. _Then_ we
4156 * count the parameters, and then we look further along the
4157 * list if necessary to find the proper MMacro.
4158 */
4159 for (m = head; m; m = m->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004160 if (!mstrcmp(m->name, tline->text, m->casesense))
4161 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004162 if (!m)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004163 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004164
4165 /*
4166 * OK, we have a potential macro. Count and demarcate the
4167 * parameters.
4168 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00004169 count_mmac_params(tline->next, &nparam, &params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004170
4171 /*
4172 * So we know how many parameters we've got. Find the MMacro
4173 * structure that handles this number.
4174 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004175 while (m) {
4176 if (m->nparam_min <= nparam
4177 && (m->plus || nparam <= m->nparam_max)) {
4178 /*
4179 * This one is right. Just check if cycle removal
4180 * prohibits us using it before we actually celebrate...
4181 */
H. Peter Anvin89cee572009-07-15 09:16:54 -04004182 if (m->in_progress > m->max_depth) {
4183 if (m->max_depth > 0) {
4184 error(ERR_WARNING,
4185 "reached maximum recursion depth of %i",
4186 m->max_depth);
4187 }
4188 nasm_free(params);
4189 return NULL;
4190 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004191 /*
4192 * It's right, and we can use it. Add its default
4193 * parameters to the end of our list if necessary.
4194 */
4195 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
4196 params =
4197 nasm_realloc(params,
4198 ((m->nparam_min + m->ndefs +
4199 1) * sizeof(*params)));
4200 while (nparam < m->nparam_min + m->ndefs) {
4201 params[nparam] = m->defaults[nparam - m->nparam_min];
4202 nparam++;
4203 }
4204 }
4205 /*
4206 * If we've gone over the maximum parameter count (and
4207 * we're in Plus mode), ignore parameters beyond
4208 * nparam_max.
4209 */
4210 if (m->plus && nparam > m->nparam_max)
4211 nparam = m->nparam_max;
4212 /*
4213 * Then terminate the parameter list, and leave.
4214 */
4215 if (!params) { /* need this special case */
4216 params = nasm_malloc(sizeof(*params));
4217 nparam = 0;
4218 }
4219 params[nparam] = NULL;
4220 *params_array = params;
4221 return m;
4222 }
4223 /*
4224 * This one wasn't right: look for the next one with the
4225 * same name.
4226 */
4227 for (m = m->next; m; m = m->next)
4228 if (!mstrcmp(m->name, tline->text, m->casesense))
4229 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004230 }
4231
4232 /*
4233 * After all that, we didn't find one with the right number of
4234 * parameters. Issue a warning, and fail to expand the macro.
4235 */
H. Peter Anvin917a3492008-09-24 09:14:49 -07004236 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00004237 "macro `%s' exists, but not taking %d parameters",
4238 tline->text, nparam);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004239 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004240 return NULL;
4241}
4242
Keith Kanios891775e2009-07-11 06:08:54 -05004243
4244/*
4245 * Save MMacro invocation specific fields in
4246 * preparation for a recursive macro expansion
4247 */
4248static void push_mmacro(MMacro *m)
4249{
4250 MMacroInvocation *i;
4251
H. Peter Anvin89cee572009-07-15 09:16:54 -04004252 i = nasm_malloc(sizeof(MMacroInvocation));
4253 i->prev = m->prev;
4254 i->params = m->params;
4255 i->iline = m->iline;
4256 i->nparam = m->nparam;
4257 i->rotate = m->rotate;
4258 i->paramlen = m->paramlen;
4259 i->unique = m->unique;
Keith Kanios3c0d91f2009-10-25 13:28:03 -05004260 i->condcnt = m->condcnt;
H. Peter Anvin89cee572009-07-15 09:16:54 -04004261 m->prev = i;
Keith Kanios891775e2009-07-11 06:08:54 -05004262}
4263
4264
4265/*
4266 * Restore MMacro invocation specific fields that were
4267 * saved during a previous recursive macro expansion
4268 */
4269static void pop_mmacro(MMacro *m)
4270{
4271 MMacroInvocation *i;
4272
H. Peter Anvin89cee572009-07-15 09:16:54 -04004273 if (m->prev) {
4274 i = m->prev;
4275 m->prev = i->prev;
4276 m->params = i->params;
4277 m->iline = i->iline;
4278 m->nparam = i->nparam;
4279 m->rotate = i->rotate;
4280 m->paramlen = i->paramlen;
4281 m->unique = i->unique;
Keith Kanios3c0d91f2009-10-25 13:28:03 -05004282 m->condcnt = i->condcnt;
H. Peter Anvin89cee572009-07-15 09:16:54 -04004283 nasm_free(i);
4284 }
Keith Kanios891775e2009-07-11 06:08:54 -05004285}
4286
4287
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004288/*
4289 * Expand the multi-line macro call made by the given line, if
4290 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvineba20a72002-04-30 20:53:55 +00004291 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004292 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004293static int expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004294{
4295 Token *startline = tline;
4296 Token *label = NULL;
4297 int dont_prepend = 0;
H. Peter Anvince2233b2008-05-25 21:57:00 -07004298 Token **params, *t, *mtok, *tt;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004299 MMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004300 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004301 int i, nparam, *paramlen;
H. Peter Anvinc751e862008-06-09 10:18:45 -07004302 const char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004303
4304 t = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004305 skip_white_(t);
H. Peter Anvince2233b2008-05-25 21:57:00 -07004306 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00004307 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004308 return 0;
H. Peter Anvince2233b2008-05-25 21:57:00 -07004309 mtok = t;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004310 m = is_mmacro(t, &params);
H. Peter Anvinc751e862008-06-09 10:18:45 -07004311 if (m) {
4312 mname = t->text;
4313 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004314 Token *last;
4315 /*
4316 * We have an id which isn't a macro call. We'll assume
4317 * it might be a label; we'll also check to see if a
4318 * colon follows it. Then, if there's another id after
4319 * that lot, we'll check it again for macro-hood.
4320 */
4321 label = last = t;
4322 t = t->next;
4323 if (tok_type_(t, TOK_WHITESPACE))
4324 last = t, t = t->next;
4325 if (tok_is_(t, ":")) {
4326 dont_prepend = 1;
4327 last = t, t = t->next;
4328 if (tok_type_(t, TOK_WHITESPACE))
4329 last = t, t = t->next;
4330 }
H. Peter Anvin89cee572009-07-15 09:16:54 -04004331 if (!tok_type_(t, TOK_ID) || !(m = is_mmacro(t, &params)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004332 return 0;
4333 last->next = NULL;
Keith Kanios891775e2009-07-11 06:08:54 -05004334 mname = t->text;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004335 tline = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004336 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004337
4338 /*
4339 * Fix up the parameters: this involves stripping leading and
4340 * trailing whitespace, then stripping braces if they are
4341 * present.
4342 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004343 for (nparam = 0; params[nparam]; nparam++) ;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004344 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004345
H. Peter Anvine2c80182005-01-15 22:15:51 +00004346 for (i = 0; params[i]; i++) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004347 int brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004348 int comma = (!m->plus || i < nparam - 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004349
H. Peter Anvine2c80182005-01-15 22:15:51 +00004350 t = params[i];
4351 skip_white_(t);
4352 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004353 t = t->next, brace = true, comma = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004354 params[i] = t;
4355 paramlen[i] = 0;
4356 while (t) {
4357 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
4358 break; /* ... because we have hit a comma */
4359 if (comma && t->type == TOK_WHITESPACE
4360 && tok_is_(t->next, ","))
4361 break; /* ... or a space then a comma */
4362 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
4363 break; /* ... or a brace */
4364 t = t->next;
4365 paramlen[i]++;
4366 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004367 }
4368
4369 /*
4370 * OK, we have a MMacro structure together with a set of
4371 * parameters. We must now go through the expansion and push
H. Peter Anvin76690a12002-04-30 20:52:49 +00004372 * copies of each Line on to istk->expansion. Substitution of
4373 * parameter tokens and macro-local tokens doesn't get done
4374 * until the single-line macro substitution process; this is
4375 * because delaying them allows us to change the semantics
4376 * later through %rotate.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004377 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00004378 * First, push an end marker on to istk->expansion, mark this
4379 * macro as in progress, and set up its invocation-specific
4380 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004381 */
4382 ll = nasm_malloc(sizeof(Line));
4383 ll->next = istk->expansion;
4384 ll->finishes = m;
4385 ll->first = NULL;
4386 istk->expansion = ll;
Keith Kanios891775e2009-07-11 06:08:54 -05004387
H. Peter Anvin89cee572009-07-15 09:16:54 -04004388 /*
4389 * Save the previous MMacro expansion in the case of
4390 * macro recursion
4391 */
4392 if (m->max_depth && m->in_progress)
4393 push_mmacro(m);
H. Peter Anvin76690a12002-04-30 20:52:49 +00004394
Keith Kanios891775e2009-07-11 06:08:54 -05004395 m->in_progress ++;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004396 m->params = params;
4397 m->iline = tline;
4398 m->nparam = nparam;
4399 m->rotate = 0;
4400 m->paramlen = paramlen;
4401 m->unique = unique++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004402 m->lineno = 0;
Keith Kanios3c0d91f2009-10-25 13:28:03 -05004403 m->condcnt = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004404
4405 m->next_active = istk->mstk;
4406 istk->mstk = m;
4407
H. Peter Anvine2c80182005-01-15 22:15:51 +00004408 for (l = m->expansion; l; l = l->next) {
4409 Token **tail;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004410
H. Peter Anvine2c80182005-01-15 22:15:51 +00004411 ll = nasm_malloc(sizeof(Line));
4412 ll->finishes = NULL;
4413 ll->next = istk->expansion;
4414 istk->expansion = ll;
4415 tail = &ll->first;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004416
H. Peter Anvine2c80182005-01-15 22:15:51 +00004417 for (t = l->first; t; t = t->next) {
4418 Token *x = t;
H. Peter Anvince2233b2008-05-25 21:57:00 -07004419 switch (t->type) {
4420 case TOK_PREPROC_Q:
H. Peter Anvinc751e862008-06-09 10:18:45 -07004421 tt = *tail = new_Token(NULL, TOK_ID, mname, 0);
H. Peter Anvince2233b2008-05-25 21:57:00 -07004422 break;
4423 case TOK_PREPROC_QQ:
4424 tt = *tail = new_Token(NULL, TOK_ID, m->name, 0);
4425 break;
4426 case TOK_PREPROC_ID:
4427 if (t->text[1] == '0' && t->text[2] == '0') {
4428 dont_prepend = -1;
4429 x = label;
4430 if (!x)
4431 continue;
4432 }
4433 /* fall through */
4434 default:
4435 tt = *tail = new_Token(NULL, x->type, x->text, 0);
4436 break;
H. Peter Anvin166c2472008-05-28 12:28:58 -07004437 }
H. Peter Anvince2233b2008-05-25 21:57:00 -07004438 tail = &tt->next;
4439 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004440 *tail = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004441 }
4442
4443 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00004444 * If we had a label, push it on as the first line of
4445 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004446 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004447 if (label) {
4448 if (dont_prepend < 0)
4449 free_tlist(startline);
4450 else {
4451 ll = nasm_malloc(sizeof(Line));
4452 ll->finishes = NULL;
4453 ll->next = istk->expansion;
4454 istk->expansion = ll;
4455 ll->first = startline;
4456 if (!dont_prepend) {
4457 while (label->next)
4458 label = label->next;
4459 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
4460 }
4461 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004462 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004463
H. Peter Anvin734b1882002-04-30 21:01:08 +00004464 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004465
H. Peter Anvineba20a72002-04-30 20:53:55 +00004466 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004467}
4468
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004469/* The function that actually does the error reporting */
4470static void verror(int severity, const char *fmt, va_list arg)
4471{
4472 char buff[1024];
4473
4474 vsnprintf(buff, sizeof(buff), fmt, arg);
4475
4476 if (istk && istk->mstk && istk->mstk->name)
H. Peter Anvindbb640b2009-07-18 18:57:16 -07004477 nasm_error(severity, "(%s:%d) %s", istk->mstk->name,
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004478 istk->mstk->lineno, buff);
4479 else
H. Peter Anvindbb640b2009-07-18 18:57:16 -07004480 nasm_error(severity, "%s", buff);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004481}
4482
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004483/*
4484 * Since preprocessor always operate only on the line that didn't
H. Peter Anvin917a3492008-09-24 09:14:49 -07004485 * arrived yet, we should always use ERR_OFFBY1.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004486 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004487static void error(int severity, const char *fmt, ...)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004488{
4489 va_list arg;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004490
4491 /* If we're in a dead branch of IF or something like it, ignore the error */
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00004492 if (istk && istk->conds && !emitting(istk->conds->state))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004493 return;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004494
H. Peter Anvin734b1882002-04-30 21:01:08 +00004495 va_start(arg, fmt);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004496 verror(severity, fmt, arg);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004497 va_end(arg);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004498}
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004499
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004500/*
4501 * Because %else etc are evaluated in the state context
4502 * of the previous branch, errors might get lost with error():
4503 * %if 0 ... %else trailing garbage ... %endif
4504 * So %else etc should report errors with this function.
4505 */
4506static void error_precond(int severity, const char *fmt, ...)
4507{
4508 va_list arg;
4509
4510 /* Only ignore the error if it's really in a dead branch */
4511 if (istk && istk->conds && istk->conds->state == COND_NEVER)
4512 return;
4513
4514 va_start(arg, fmt);
4515 verror(severity, fmt, arg);
4516 va_end(arg);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004517}
4518
H. Peter Anvin734b1882002-04-30 21:01:08 +00004519static void
H. Peter Anvindbb640b2009-07-18 18:57:16 -07004520pp_reset(char *file, int apass, ListGen * listgen, StrList **deplist)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004521{
H. Peter Anvin7383b402008-09-24 10:20:40 -07004522 Token *t;
4523
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004524 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004525 istk = nasm_malloc(sizeof(Include));
4526 istk->next = NULL;
4527 istk->conds = NULL;
4528 istk->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004529 istk->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004530 istk->fp = fopen(file, "r");
H. Peter Anvineba20a72002-04-30 20:53:55 +00004531 istk->fname = NULL;
4532 src_set_fname(nasm_strdup(file));
4533 src_set_linnum(0);
4534 istk->lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004535 if (!istk->fp)
H. Peter Anvin917a3492008-09-24 09:14:49 -07004536 error(ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'",
H. Peter Anvine2c80182005-01-15 22:15:51 +00004537 file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004538 defining = NULL;
Charles Crayned4200be2008-07-12 16:42:33 -07004539 nested_mac_count = 0;
4540 nested_rep_count = 0;
H. Peter Anvin97a23472007-09-16 17:57:25 -07004541 init_macros();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004542 unique = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004543 if (tasm_compatible_mode) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07004544 stdmacpos = nasm_stdmac;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004545 } else {
H. Peter Anvina4835d42008-05-20 14:21:29 -07004546 stdmacpos = nasm_stdmac_after_tasm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004547 }
H. Peter Anvind2456592008-06-19 15:04:18 -07004548 any_extrastdmac = extrastdmac && *extrastdmac;
4549 do_predef = true;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004550 list = listgen;
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004551
4552 /*
4553 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4554 * The caller, however, will also pass in 3 for preprocess-only so
4555 * we can set __PASS__ accordingly.
4556 */
4557 pass = apass > 2 ? 2 : apass;
4558
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07004559 dephead = deptail = deplist;
4560 if (deplist) {
4561 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
4562 sl->next = NULL;
4563 strcpy(sl->str, file);
4564 *deptail = sl;
4565 deptail = &sl->next;
4566 }
H. Peter Anvin7383b402008-09-24 10:20:40 -07004567
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004568 /*
4569 * Define the __PASS__ macro. This is defined here unlike
4570 * all the other builtins, because it is special -- it varies between
4571 * passes.
4572 */
H. Peter Anvin7383b402008-09-24 10:20:40 -07004573 t = nasm_malloc(sizeof(*t));
4574 t->next = NULL;
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004575 make_tok_num(t, apass);
H. Peter Anvin7383b402008-09-24 10:20:40 -07004576 t->a.mac = NULL;
4577 define_smacro(NULL, "__PASS__", true, 0, t);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004578}
4579
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004580static char *pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004581{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004582 char *line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004583 Token *tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004584
H. Peter Anvine2c80182005-01-15 22:15:51 +00004585 while (1) {
4586 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00004587 * Fetch a tokenized line, either from the macro-expansion
H. Peter Anvine2c80182005-01-15 22:15:51 +00004588 * buffer or from the input file.
4589 */
4590 tline = NULL;
4591 while (istk->expansion && istk->expansion->finishes) {
4592 Line *l = istk->expansion;
4593 if (!l->finishes->name && l->finishes->in_progress > 1) {
4594 Line *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004595
H. Peter Anvine2c80182005-01-15 22:15:51 +00004596 /*
4597 * This is a macro-end marker for a macro with no
4598 * name, which means it's not really a macro at all
4599 * but a %rep block, and the `in_progress' field is
4600 * more than 1, meaning that we still need to
4601 * repeat. (1 means the natural last repetition; 0
4602 * means termination by %exitrep.) We have
4603 * therefore expanded up to the %endrep, and must
4604 * push the whole block on to the expansion buffer
4605 * again. We don't bother to remove the macro-end
4606 * marker: we'd only have to generate another one
4607 * if we did.
4608 */
4609 l->finishes->in_progress--;
4610 for (l = l->finishes->expansion; l; l = l->next) {
4611 Token *t, *tt, **tail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004612
H. Peter Anvine2c80182005-01-15 22:15:51 +00004613 ll = nasm_malloc(sizeof(Line));
4614 ll->next = istk->expansion;
4615 ll->finishes = NULL;
4616 ll->first = NULL;
4617 tail = &ll->first;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004618
H. Peter Anvine2c80182005-01-15 22:15:51 +00004619 for (t = l->first; t; t = t->next) {
4620 if (t->text || t->type == TOK_WHITESPACE) {
4621 tt = *tail =
4622 new_Token(NULL, t->type, t->text, 0);
4623 tail = &tt->next;
4624 }
4625 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004626
H. Peter Anvine2c80182005-01-15 22:15:51 +00004627 istk->expansion = ll;
4628 }
4629 } else {
4630 /*
4631 * Check whether a `%rep' was started and not ended
4632 * within this macro expansion. This can happen and
4633 * should be detected. It's a fatal error because
4634 * I'm too confused to work out how to recover
4635 * sensibly from it.
4636 */
4637 if (defining) {
4638 if (defining->name)
4639 error(ERR_PANIC,
4640 "defining with name in expansion");
4641 else if (istk->mstk->name)
4642 error(ERR_FATAL,
4643 "`%%rep' without `%%endrep' within"
4644 " expansion of macro `%s'",
4645 istk->mstk->name);
4646 }
H. Peter Anvin87bc6192002-04-30 20:53:16 +00004647
H. Peter Anvine2c80182005-01-15 22:15:51 +00004648 /*
4649 * FIXME: investigate the relationship at this point between
4650 * istk->mstk and l->finishes
4651 */
4652 {
4653 MMacro *m = istk->mstk;
4654 istk->mstk = m->next_active;
4655 if (m->name) {
4656 /*
4657 * This was a real macro call, not a %rep, and
4658 * therefore the parameter information needs to
4659 * be freed.
4660 */
H. Peter Anvin89cee572009-07-15 09:16:54 -04004661 if (m->prev) {
4662 pop_mmacro(m);
4663 l->finishes->in_progress --;
4664 } else {
Keith Kanios891775e2009-07-11 06:08:54 -05004665 nasm_free(m->params);
4666 free_tlist(m->iline);
H. Peter Anvin89cee572009-07-15 09:16:54 -04004667 nasm_free(m->paramlen);
4668 l->finishes->in_progress = 0;
4669 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004670 } else
4671 free_mmacro(m);
4672 }
4673 istk->expansion = l->next;
4674 nasm_free(l);
4675 list->downlevel(LIST_MACRO);
4676 }
4677 }
4678 while (1) { /* until we get a line we can use */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004679
H. Peter Anvine2c80182005-01-15 22:15:51 +00004680 if (istk->expansion) { /* from a macro expansion */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004681 char *p;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004682 Line *l = istk->expansion;
4683 if (istk->mstk)
4684 istk->mstk->lineno++;
4685 tline = l->first;
4686 istk->expansion = l->next;
4687 nasm_free(l);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004688 p = detoken(tline, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004689 list->line(LIST_MACRO, p);
4690 nasm_free(p);
4691 break;
4692 }
4693 line = read_line();
4694 if (line) { /* from the current input file */
4695 line = prepreproc(line);
Keith Kaniosb7a89542007-04-12 02:40:54 +00004696 tline = tokenize(line);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004697 nasm_free(line);
4698 break;
4699 }
4700 /*
4701 * The current file has ended; work down the istk
4702 */
4703 {
4704 Include *i = istk;
4705 fclose(i->fp);
4706 if (i->conds)
4707 error(ERR_FATAL,
4708 "expected `%%endif' before end of file");
4709 /* only set line and file name if there's a next node */
4710 if (i->next) {
4711 src_set_linnum(i->lineno);
4712 nasm_free(src_set_fname(i->fname));
H. Peter Anvin86877b22008-06-20 15:55:45 -07004713 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004714 istk = i->next;
4715 list->downlevel(LIST_INCLUDE);
4716 nasm_free(i);
4717 if (!istk)
4718 return NULL;
Victor van den Elzen4c9d6222008-10-01 13:08:50 +02004719 if (istk->expansion && istk->expansion->finishes)
4720 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004721 }
4722 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004723
H. Peter Anvine2c80182005-01-15 22:15:51 +00004724 /*
4725 * We must expand MMacro parameters and MMacro-local labels
4726 * _before_ we plunge into directive processing, to cope
4727 * with things like `%define something %1' such as STRUC
4728 * uses. Unless we're _defining_ a MMacro, in which case
4729 * those tokens should be left alone to go into the
4730 * definition; and unless we're in a non-emitting
4731 * condition, in which case we don't want to meddle with
4732 * anything.
4733 */
Charles Crayned4200be2008-07-12 16:42:33 -07004734 if (!defining && !(istk->conds && !emitting(istk->conds->state))
H. Peter Anvin992fe752008-10-19 15:45:05 -07004735 && !(istk->mstk && !istk->mstk->in_progress)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004736 tline = expand_mmac_params(tline);
H. Peter Anvin992fe752008-10-19 15:45:05 -07004737 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004738
H. Peter Anvine2c80182005-01-15 22:15:51 +00004739 /*
4740 * Check the line to see if it's a preprocessor directive.
4741 */
4742 if (do_directive(tline) == DIRECTIVE_FOUND) {
4743 continue;
4744 } else if (defining) {
4745 /*
4746 * We're defining a multi-line macro. We emit nothing
4747 * at all, and just
Keith Kaniosb7a89542007-04-12 02:40:54 +00004748 * shove the tokenized line on to the macro definition.
H. Peter Anvine2c80182005-01-15 22:15:51 +00004749 */
4750 Line *l = nasm_malloc(sizeof(Line));
4751 l->next = defining->expansion;
4752 l->first = tline;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004753 l->finishes = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004754 defining->expansion = l;
4755 continue;
4756 } else if (istk->conds && !emitting(istk->conds->state)) {
4757 /*
4758 * We're in a non-emitting branch of a condition block.
4759 * Emit nothing at all, not even a blank line: when we
4760 * emerge from the condition we'll give a line-number
4761 * directive so we keep our place correctly.
4762 */
4763 free_tlist(tline);
4764 continue;
4765 } else if (istk->mstk && !istk->mstk->in_progress) {
4766 /*
4767 * We're in a %rep block which has been terminated, so
4768 * we're walking through to the %endrep without
4769 * emitting anything. Emit nothing at all, not even a
4770 * blank line: when we emerge from the %rep block we'll
4771 * give a line-number directive so we keep our place
4772 * correctly.
4773 */
4774 free_tlist(tline);
4775 continue;
4776 } else {
4777 tline = expand_smacro(tline);
4778 if (!expand_mmacro(tline)) {
4779 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00004780 * De-tokenize the line again, and emit it.
H. Peter Anvine2c80182005-01-15 22:15:51 +00004781 */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004782 line = detoken(tline, true);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004783 free_tlist(tline);
4784 break;
4785 } else {
4786 continue; /* expand_mmacro calls free_tlist */
4787 }
4788 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004789 }
4790
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004791 return line;
4792}
4793
H. Peter Anvine2c80182005-01-15 22:15:51 +00004794static void pp_cleanup(int pass)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004795{
H. Peter Anvine2c80182005-01-15 22:15:51 +00004796 if (defining) {
H. Peter Anvin89cee572009-07-15 09:16:54 -04004797 if (defining->name) {
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02004798 error(ERR_NONFATAL,
4799 "end of file while still defining macro `%s'",
4800 defining->name);
4801 } else {
4802 error(ERR_NONFATAL, "end of file while still in %%rep");
4803 }
4804
H. Peter Anvine2c80182005-01-15 22:15:51 +00004805 free_mmacro(defining);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004806 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004807 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004808 ctx_pop();
H. Peter Anvin97a23472007-09-16 17:57:25 -07004809 free_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00004810 while (istk) {
4811 Include *i = istk;
4812 istk = istk->next;
4813 fclose(i->fp);
4814 nasm_free(i->fname);
4815 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004816 }
4817 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004818 ctx_pop();
H. Peter Anvin86877b22008-06-20 15:55:45 -07004819 nasm_free(src_set_fname(NULL));
H. Peter Anvine2c80182005-01-15 22:15:51 +00004820 if (pass == 0) {
H. Peter Anvin86877b22008-06-20 15:55:45 -07004821 IncPath *i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004822 free_llist(predef);
4823 delete_Blocks();
H. Peter Anvin86877b22008-06-20 15:55:45 -07004824 while ((i = ipath)) {
4825 ipath = i->next;
4826 if (i->path)
4827 nasm_free(i->path);
4828 nasm_free(i);
4829 }
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07004830 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004831}
4832
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004833void pp_include_path(char *path)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004834{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004835 IncPath *i;
H. Peter Anvin37a321f2007-09-24 13:41:58 -07004836
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004837 i = nasm_malloc(sizeof(IncPath));
H. Peter Anvin37a321f2007-09-24 13:41:58 -07004838 i->path = path ? nasm_strdup(path) : NULL;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004839 i->next = NULL;
4840
H. Peter Anvin89cee572009-07-15 09:16:54 -04004841 if (ipath) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004842 IncPath *j = ipath;
H. Peter Anvin89cee572009-07-15 09:16:54 -04004843 while (j->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004844 j = j->next;
4845 j->next = i;
4846 } else {
4847 ipath = i;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004848 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004849}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004850
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004851void pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004852{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004853 Token *inc, *space, *name;
4854 Line *l;
4855
H. Peter Anvin734b1882002-04-30 21:01:08 +00004856 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
4857 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
4858 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004859
4860 l = nasm_malloc(sizeof(Line));
4861 l->next = predef;
4862 l->first = inc;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004863 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004864 predef = l;
4865}
4866
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004867void pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004868{
4869 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004870 Line *l;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004871 char *equals;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004872
4873 equals = strchr(definition, '=');
H. Peter Anvin734b1882002-04-30 21:01:08 +00004874 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4875 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004876 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004877 *equals = ' ';
Keith Kaniosb7a89542007-04-12 02:40:54 +00004878 space->next = tokenize(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004879 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004880 *equals = '=';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004881
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004882 l = nasm_malloc(sizeof(Line));
4883 l->next = predef;
4884 l->first = def;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004885 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004886 predef = l;
4887}
4888
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004889void pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00004890{
4891 Token *def, *space;
4892 Line *l;
4893
H. Peter Anvin734b1882002-04-30 21:01:08 +00004894 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4895 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Keith Kaniosb7a89542007-04-12 02:40:54 +00004896 space->next = tokenize(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00004897
4898 l = nasm_malloc(sizeof(Line));
4899 l->next = predef;
4900 l->first = def;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004901 l->finishes = NULL;
H. Peter Anvin620515a2002-04-30 20:57:38 +00004902 predef = l;
4903}
4904
Keith Kaniosb7a89542007-04-12 02:40:54 +00004905/*
4906 * Added by Keith Kanios:
4907 *
4908 * This function is used to assist with "runtime" preprocessor
4909 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4910 *
4911 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4912 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4913 */
4914
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004915void pp_runtime(char *definition)
Keith Kaniosb7a89542007-04-12 02:40:54 +00004916{
4917 Token *def;
H. Peter Anvin70653092007-10-19 14:42:29 -07004918
Keith Kaniosb7a89542007-04-12 02:40:54 +00004919 def = tokenize(definition);
H. Peter Anvin89cee572009-07-15 09:16:54 -04004920 if (do_directive(def) == NO_DIRECTIVE_FOUND)
Keith Kaniosb7a89542007-04-12 02:40:54 +00004921 free_tlist(def);
H. Peter Anvin70653092007-10-19 14:42:29 -07004922
Keith Kaniosb7a89542007-04-12 02:40:54 +00004923}
4924
H. Peter Anvina70547f2008-07-19 21:44:26 -07004925void pp_extra_stdmac(macros_t *macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004926{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004927 extrastdmac = macros;
4928}
4929
Keith Kaniosa5fc6462007-10-13 07:09:22 -07004930static void make_tok_num(Token * tok, int64_t val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004931{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004932 char numbuf[20];
Keith Kaniosa5fc6462007-10-13 07:09:22 -07004933 snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004934 tok->text = nasm_strdup(numbuf);
4935 tok->type = TOK_NUMBER;
4936}
4937
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004938Preproc nasmpp = {
4939 pp_reset,
4940 pp_getline,
4941 pp_cleanup
4942};