blob: dab0b2af293fc37509922f56e848736322511332 [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 */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000156};
157
Keith Kanios891775e2009-07-11 06:08:54 -0500158
159/* Store the definition of a multi-line macro, as defined in a
160 * previous recursive macro expansion.
161 */
162struct MMacroInvocation {
H. Peter Anvin89cee572009-07-15 09:16:54 -0400163 MMacroInvocation *prev; /* previous invocation */
164 Token **params; /* actual parameters */
165 Token *iline; /* invocation line */
Keith Kanios891775e2009-07-11 06:08:54 -0500166 unsigned int nparam, rotate;
167 int *paramlen;
168 uint64_t unique;
169};
170
171
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000172/*
173 * The context stack is composed of a linked list of these.
174 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000175struct Context {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000176 Context *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000177 char *name;
H. Peter Anvin166c2472008-05-28 12:28:58 -0700178 struct hash_table localmac;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000179 uint32_t number;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000180};
181
182/*
183 * This is the internal form which we break input lines up into.
184 * Typically stored in linked lists.
185 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000186 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
187 * necessarily used as-is, but is intended to denote the number of
188 * the substituted parameter. So in the definition
189 *
190 * %define a(x,y) ( (x) & ~(y) )
H. Peter Anvin70653092007-10-19 14:42:29 -0700191 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000192 * the token representing `x' will have its type changed to
193 * TOK_SMAC_PARAM, but the one representing `y' will be
194 * TOK_SMAC_PARAM+1.
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000195 *
196 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
197 * which doesn't need quotes around it. Used in the pre-include
198 * mechanism as an alternative to trying to find a sensible type of
199 * quote to use on the filename we were passed.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000200 */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000201enum pp_token_type {
202 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID,
203 TOK_PREPROC_ID, TOK_STRING,
H. Peter Anvin6c81f0a2008-05-25 21:46:17 -0700204 TOK_NUMBER, TOK_FLOAT, TOK_SMAC_END, TOK_OTHER,
205 TOK_INTERNAL_STRING,
206 TOK_PREPROC_Q, TOK_PREPROC_QQ,
H. Peter Anvind784a082009-04-20 14:01:18 -0700207 TOK_PASTE, /* %+ */
H. Peter Anvin9bb46df2009-04-07 21:59:24 -0700208 TOK_INDIRECT, /* %[...] */
H. Peter Anvin5b76fa22008-05-26 11:14:38 -0700209 TOK_SMAC_PARAM, /* MUST BE LAST IN THE LIST!!! */
210 TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000211};
212
H. Peter Anvine2c80182005-01-15 22:15:51 +0000213struct Token {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000214 Token *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000215 char *text;
H. Peter Anvinf26e0972008-07-01 21:26:27 -0700216 union {
217 SMacro *mac; /* associated macro for TOK_SMAC_END */
218 size_t len; /* scratch length field */
219 } a; /* Auxiliary data */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000220 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000221};
222
223/*
224 * Multi-line macro definitions are stored as a linked list of
225 * these, which is essentially a container to allow several linked
226 * lists of Tokens.
H. Peter Anvin70653092007-10-19 14:42:29 -0700227 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000228 * Note that in this module, linked lists are treated as stacks
229 * wherever possible. For this reason, Lines are _pushed_ on to the
230 * `expansion' field in MMacro structures, so that the linked list,
231 * if walked, would give the macro lines in reverse order; this
232 * means that we can walk the list when expanding a macro, and thus
233 * push the lines on to the `expansion' field in _istk_ in reverse
234 * order (so that when popped back off they are in the right
235 * order). It may seem cockeyed, and it relies on my design having
236 * an even number of steps in, but it works...
237 *
238 * Some of these structures, rather than being actual lines, are
239 * markers delimiting the end of the expansion of a given macro.
H. Peter Anvin76690a12002-04-30 20:52:49 +0000240 * This is for use in the cycle-tracking and %rep-handling code.
241 * Such structures have `finishes' non-NULL, and `first' NULL. All
242 * others have `finishes' NULL, but `first' may still be NULL if
243 * the line is blank.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000244 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000245struct Line {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000246 Line *next;
247 MMacro *finishes;
248 Token *first;
249};
250
251/*
252 * To handle an arbitrary level of file inclusion, we maintain a
253 * stack (ie linked list) of these things.
254 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000255struct Include {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000256 Include *next;
257 FILE *fp;
258 Cond *conds;
259 Line *expansion;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000260 char *fname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000261 int lineno, lineinc;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000262 MMacro *mstk; /* stack of active macros/reps */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000263};
264
265/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000266 * Include search path. This is simply a list of strings which get
267 * prepended, in turn, to the name of an include file, in an
268 * attempt to find the file if it's not in the current directory.
269 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000270struct IncPath {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000271 IncPath *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000272 char *path;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000273};
274
275/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000276 * Conditional assembly: we maintain a separate stack of these for
277 * each level of file inclusion. (The only reason we keep the
278 * stacks separate is to ensure that a stray `%endif' in a file
279 * included from within the true branch of a `%if' won't terminate
280 * it and cause confusion: instead, rightly, it'll cause an error.)
281 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000282struct Cond {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000283 Cond *next;
284 int state;
285};
H. Peter Anvine2c80182005-01-15 22:15:51 +0000286enum {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000287 /*
288 * These states are for use just after %if or %elif: IF_TRUE
289 * means the condition has evaluated to truth so we are
290 * currently emitting, whereas IF_FALSE means we are not
291 * currently emitting but will start doing so if a %else comes
292 * up. In these states, all directives are admissible: %elif,
293 * %else and %endif. (And of course %if.)
294 */
295 COND_IF_TRUE, COND_IF_FALSE,
296 /*
297 * These states come up after a %else: ELSE_TRUE means we're
298 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
299 * any %elif or %else will cause an error.
300 */
301 COND_ELSE_TRUE, COND_ELSE_FALSE,
302 /*
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200303 * These states mean that we're not emitting now, and also that
304 * nothing until %endif will be emitted at all. COND_DONE is
305 * used when we've had our moment of emission
306 * and have now started seeing %elifs. COND_NEVER is used when
307 * the condition construct in question is contained within a
308 * non-emitting branch of a larger condition construct,
309 * or if there is an error.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000310 */
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200311 COND_DONE, COND_NEVER
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000312};
313#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
314
H. Peter Anvin70653092007-10-19 14:42:29 -0700315/*
Ed Beroset3ab3f412002-06-11 03:31:49 +0000316 * These defines are used as the possible return values for do_directive
317 */
318#define NO_DIRECTIVE_FOUND 0
319#define DIRECTIVE_FOUND 1
320
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000321/*
Keith Kanios852f1ee2009-07-12 00:19:55 -0500322 * This define sets the upper limit for smacro and recursive mmacro
323 * expansions
324 */
325#define DEADMAN_LIMIT (1 << 20)
326
327/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000328 * Condition codes. Note that we use c_ prefix not C_ because C_ is
329 * used in nasm.h for the "real" condition codes. At _this_ level,
330 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
331 * ones, so we need a different enum...
332 */
H. Peter Anvin476d2862007-10-02 22:04:15 -0700333static const char * const conditions[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000334 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
335 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
H. Peter Anvince9be342007-09-12 00:22:29 +0000336 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000337};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700338enum pp_conds {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000339 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
340 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 -0700341 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
342 c_none = -1
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000343};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700344static const enum pp_conds inverse_ccs[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000345 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
346 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 +0000347 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000348};
349
H. Peter Anvin76690a12002-04-30 20:52:49 +0000350/*
351 * Directive names.
352 */
H. Peter Anvin65747262002-05-07 00:10:05 +0000353/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
H. Peter Anvin9bf0aa72007-09-12 02:12:07 +0000354static int is_condition(enum preproc_token arg)
H. Peter Anvin65747262002-05-07 00:10:05 +0000355{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000356 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
H. Peter Anvin65747262002-05-07 00:10:05 +0000357}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000358
359/* For TASM compatibility we need to be able to recognise TASM compatible
360 * conditional compilation directives. Using the NASM pre-processor does
361 * not work, so we look for them specifically from the following list and
362 * then jam in the equivalent NASM directive into the input stream.
363 */
364
H. Peter Anvine2c80182005-01-15 22:15:51 +0000365enum {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000366 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
367 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
368};
369
H. Peter Anvin476d2862007-10-02 22:04:15 -0700370static const char * const tasm_directives[] = {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000371 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
372 "ifndef", "include", "local"
373};
374
375static int StackSize = 4;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000376static char *StackPointer = "ebp";
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000377static int ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -0800378static int LocalOffset = 0;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000379
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000380static Context *cstk;
381static Include *istk;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000382static IncPath *ipath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000383
H. Peter Anvine2c80182005-01-15 22:15:51 +0000384static int pass; /* HACK: pass 0 = generate dependencies only */
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700385static StrList **dephead, **deptail; /* Dependency list */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000386
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700387static uint64_t unique; /* unique identifier numbers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000388
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000389static Line *predef = NULL;
H. Peter Anvind2456592008-06-19 15:04:18 -0700390static bool do_predef;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000391
392static ListGen *list;
393
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000394/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000395 * The current set of multi-line macros we have defined.
396 */
H. Peter Anvin166c2472008-05-28 12:28:58 -0700397static struct hash_table mmacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000398
399/*
400 * The current set of single-line macros we have defined.
401 */
H. Peter Anvin166c2472008-05-28 12:28:58 -0700402static struct hash_table smacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000403
404/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000405 * The multi-line macro we are currently defining, or the %rep
406 * block we are currently reading, if any.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000407 */
408static MMacro *defining;
409
Charles Crayned4200be2008-07-12 16:42:33 -0700410static uint64_t nested_mac_count;
411static uint64_t nested_rep_count;
412
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000413/*
414 * The number of macro parameters to allocate space for at a time.
415 */
416#define PARAM_DELTA 16
417
418/*
H. Peter Anvina4835d42008-05-20 14:21:29 -0700419 * The standard macro set: defined in macros.c in the array nasm_stdmac.
420 * This gives our position in the macro set, when we're processing it.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000421 */
H. Peter Anvina70547f2008-07-19 21:44:26 -0700422static macros_t *stdmacpos;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000423
424/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000425 * The extra standard macros that come from the object format, if
426 * any.
427 */
H. Peter Anvina70547f2008-07-19 21:44:26 -0700428static macros_t *extrastdmac = NULL;
H. Peter Anvincfb71762008-06-20 15:20:16 -0700429static bool any_extrastdmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000430
431/*
H. Peter Anvin734b1882002-04-30 21:01:08 +0000432 * Tokens are allocated in blocks to improve speed
433 */
434#define TOKEN_BLOCKSIZE 4096
435static Token *freeTokens = NULL;
H. Peter Anvince616072002-04-30 21:02:23 +0000436struct Blocks {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000437 Blocks *next;
438 void *chunk;
H. Peter Anvince616072002-04-30 21:02:23 +0000439};
440
441static Blocks blocks = { NULL, NULL };
H. Peter Anvin734b1882002-04-30 21:01:08 +0000442
443/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000444 * Forward declarations.
445 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000446static Token *expand_mmac_params(Token * tline);
447static Token *expand_smacro(Token * tline);
448static Token *expand_id(Token * tline);
H. Peter Anvinf8ad5322009-02-21 17:55:08 -0800449static Context *get_ctx(const char *name, const char **namep,
450 bool all_contexts);
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700451static void make_tok_num(Token * tok, int64_t val);
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000452static void error(int severity, const char *fmt, ...);
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200453static void error_precond(int severity, const char *fmt, ...);
H. Peter Anvince616072002-04-30 21:02:23 +0000454static void *new_Block(size_t size);
455static void delete_Blocks(void);
H. Peter Anvinc751e862008-06-09 10:18:45 -0700456static Token *new_Token(Token * next, enum pp_token_type type,
457 const char *text, int txtlen);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000458static Token *delete_Token(Token * t);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000459
460/*
461 * Macros for safe checking of token pointers, avoid *(NULL)
462 */
463#define tok_type_(x,t) ((x) && (x)->type == (t))
464#define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
465#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
466#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
H. Peter Anvin76690a12002-04-30 20:52:49 +0000467
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000468/* Handle TASM specific directives, which do not contain a % in
469 * front of them. We do it here because I could not find any other
470 * place to do it for the moment, and it is a hack (ideally it would
471 * be nice to be able to use the NASM pre-processor to do it).
472 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000473static char *check_tasm_directive(char *line)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000474{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000475 int32_t i, j, k, m, len;
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400476 char *p, *q, *oldline, oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000477
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400478 p = nasm_skip_spaces(line);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000479
480 /* Binary search for the directive name */
481 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +0000482 j = elements(tasm_directives);
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400483 q = nasm_skip_word(p);
484 len = q - p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000485 if (len) {
486 oldchar = p[len];
487 p[len] = 0;
488 while (j - i > 1) {
489 k = (j + i) / 2;
490 m = nasm_stricmp(p, tasm_directives[k]);
491 if (m == 0) {
492 /* We have found a directive, so jam a % in front of it
493 * so that NASM will then recognise it as one if it's own.
494 */
495 p[len] = oldchar;
496 len = strlen(p);
497 oldline = line;
498 line = nasm_malloc(len + 2);
499 line[0] = '%';
500 if (k == TM_IFDIFI) {
H. Peter Anvin18f48792009-06-27 15:56:27 -0700501 /*
502 * NASM does not recognise IFDIFI, so we convert
503 * it to %if 0. This is not used in NASM
504 * compatible code, but does need to parse for the
505 * TASM macro package.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000506 */
H. Peter Anvin18f48792009-06-27 15:56:27 -0700507 strcpy(line + 1, "if 0");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000508 } else {
509 memcpy(line + 1, p, len + 1);
510 }
511 nasm_free(oldline);
512 return line;
513 } else if (m < 0) {
514 j = k;
515 } else
516 i = k;
517 }
518 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000519 }
520 return line;
521}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000522
H. Peter Anvin76690a12002-04-30 20:52:49 +0000523/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000524 * The pre-preprocessing stage... This function translates line
525 * number indications as they emerge from GNU cpp (`# lineno "file"
526 * flags') into NASM preprocessor line number indications (`%line
527 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000528 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000529static char *prepreproc(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000530{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000531 int lineno, fnlen;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000532 char *fname, *oldline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000533
H. Peter Anvine2c80182005-01-15 22:15:51 +0000534 if (line[0] == '#' && line[1] == ' ') {
535 oldline = line;
536 fname = oldline + 2;
537 lineno = atoi(fname);
538 fname += strspn(fname, "0123456789 ");
539 if (*fname == '"')
540 fname++;
541 fnlen = strcspn(fname, "\"");
542 line = nasm_malloc(20 + fnlen);
543 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
544 nasm_free(oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000545 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000546 if (tasm_compatible_mode)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000547 return check_tasm_directive(line);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000548 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000549}
550
551/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000552 * Free a linked list of tokens.
553 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000554static void free_tlist(Token * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000555{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000556 while (list) {
557 list = delete_Token(list);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000558 }
559}
560
561/*
562 * Free a linked list of lines.
563 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000564static void free_llist(Line * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000565{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000566 Line *l;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000567 while (list) {
568 l = list;
569 list = list->next;
570 free_tlist(l->first);
571 nasm_free(l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000572 }
573}
574
575/*
H. Peter Anvineba20a72002-04-30 20:53:55 +0000576 * Free an MMacro
577 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000578static void free_mmacro(MMacro * m)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000579{
H. Peter Anvin734b1882002-04-30 21:01:08 +0000580 nasm_free(m->name);
581 free_tlist(m->dlist);
582 nasm_free(m->defaults);
583 free_llist(m->expansion);
584 nasm_free(m);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000585}
586
587/*
H. Peter Anvin97a23472007-09-16 17:57:25 -0700588 * Free all currently defined macros, and free the hash tables
589 */
H. Peter Anvin072771e2008-05-22 13:17:51 -0700590static void free_smacro_table(struct hash_table *smt)
H. Peter Anvin97a23472007-09-16 17:57:25 -0700591{
H. Peter Anvin97a23472007-09-16 17:57:25 -0700592 SMacro *s;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700593 const char *key;
594 struct hash_tbl_node *it = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -0700595
H. Peter Anvin072771e2008-05-22 13:17:51 -0700596 while ((s = hash_iterate(smt, &it, &key)) != NULL) {
H. Peter Anvin97a23472007-09-16 17:57:25 -0700597 nasm_free((void *)key);
598 while (s) {
599 SMacro *ns = s->next;
600 nasm_free(s->name);
601 free_tlist(s->expansion);
602 nasm_free(s);
603 s = ns;
604 }
605 }
H. Peter Anvin072771e2008-05-22 13:17:51 -0700606 hash_free(smt);
607}
608
609static void free_mmacro_table(struct hash_table *mmt)
610{
611 MMacro *m;
612 const char *key;
613 struct hash_tbl_node *it = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -0700614
615 it = NULL;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700616 while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
H. Peter Anvin97a23472007-09-16 17:57:25 -0700617 nasm_free((void *)key);
618 while (m) {
619 MMacro *nm = m->next;
620 free_mmacro(m);
621 m = nm;
622 }
623 }
H. Peter Anvin072771e2008-05-22 13:17:51 -0700624 hash_free(mmt);
625}
626
627static void free_macros(void)
628{
H. Peter Anvin166c2472008-05-28 12:28:58 -0700629 free_smacro_table(&smacros);
630 free_mmacro_table(&mmacros);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700631}
632
633/*
634 * Initialize the hash tables
635 */
636static void init_macros(void)
637{
H. Peter Anvin166c2472008-05-28 12:28:58 -0700638 hash_init(&smacros, HASH_LARGE);
639 hash_init(&mmacros, HASH_LARGE);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700640}
641
642/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000643 * Pop the context stack.
644 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000645static void ctx_pop(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000646{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000647 Context *c = cstk;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000648
649 cstk = cstk->next;
H. Peter Anvin166c2472008-05-28 12:28:58 -0700650 free_smacro_table(&c->localmac);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000651 nasm_free(c->name);
652 nasm_free(c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000653}
654
H. Peter Anvin072771e2008-05-22 13:17:51 -0700655/*
656 * Search for a key in the hash index; adding it if necessary
657 * (in which case we initialize the data pointer to NULL.)
658 */
659static void **
660hash_findi_add(struct hash_table *hash, const char *str)
661{
662 struct hash_insert hi;
663 void **r;
664 char *strx;
665
666 r = hash_findi(hash, str, &hi);
667 if (r)
668 return r;
669
670 strx = nasm_strdup(str); /* Use a more efficient allocator here? */
671 return hash_add(&hi, strx, NULL);
672}
673
674/*
675 * Like hash_findi, but returns the data element rather than a pointer
676 * to it. Used only when not adding a new element, hence no third
677 * argument.
678 */
679static void *
680hash_findix(struct hash_table *hash, const char *str)
681{
682 void **p;
683
684 p = hash_findi(hash, str, NULL);
685 return p ? *p : NULL;
686}
687
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000688#define BUF_DELTA 512
689/*
690 * Read a line from the top file in istk, handling multiple CR/LFs
691 * at the end of the line read, and handling spurious ^Zs. Will
692 * return lines from the standard macro set if this has not already
693 * been done.
694 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000695static char *read_line(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000696{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000697 char *buffer, *p, *q;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000698 int bufsize, continued_count;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000699
H. Peter Anvine2c80182005-01-15 22:15:51 +0000700 if (stdmacpos) {
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700701 unsigned char c;
H. Peter Anvin7e50d232008-06-25 14:54:14 -0700702 const unsigned char *p = stdmacpos;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700703 char *ret, *q;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700704 size_t len = 0;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700705 while ((c = *p++)) {
706 if (c >= 0x80)
707 len += pp_directives_len[c-0x80]+1;
708 else
709 len++;
710 }
711 ret = nasm_malloc(len+1);
H. Peter Anvincda81632008-06-21 15:15:40 -0700712 q = ret;
713 while ((c = *stdmacpos++)) {
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700714 if (c >= 0x80) {
715 memcpy(q, pp_directives[c-0x80], pp_directives_len[c-0x80]);
716 q += pp_directives_len[c-0x80];
717 *q++ = ' ';
718 } else {
719 *q++ = c;
720 }
721 }
H. Peter Anvincda81632008-06-21 15:15:40 -0700722 stdmacpos = p;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700723 *q = '\0';
724
H. Peter Anvind2456592008-06-19 15:04:18 -0700725 if (!*stdmacpos) {
726 /* This was the last of the standard macro chain... */
727 stdmacpos = NULL;
728 if (any_extrastdmac) {
729 stdmacpos = extrastdmac;
730 any_extrastdmac = false;
731 } else if (do_predef) {
732 Line *pd, *l;
733 Token *head, **tail, *t;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000734
H. Peter Anvind2456592008-06-19 15:04:18 -0700735 /*
736 * Nasty hack: here we push the contents of
737 * `predef' on to the top-level expansion stack,
738 * since this is the most convenient way to
739 * implement the pre-include and pre-define
740 * features.
741 */
742 for (pd = predef; pd; pd = pd->next) {
743 head = NULL;
744 tail = &head;
745 for (t = pd->first; t; t = t->next) {
746 *tail = new_Token(NULL, t->type, t->text, 0);
747 tail = &(*tail)->next;
748 }
749 l = nasm_malloc(sizeof(Line));
750 l->next = istk->expansion;
751 l->first = head;
H. Peter Anvin538002d2008-06-28 18:30:27 -0700752 l->finishes = NULL;
H. Peter Anvind2456592008-06-19 15:04:18 -0700753 istk->expansion = l;
754 }
755 do_predef = false;
756 }
757 }
758 return ret;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000759 }
760
761 bufsize = BUF_DELTA;
762 buffer = nasm_malloc(BUF_DELTA);
763 p = buffer;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000764 continued_count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000765 while (1) {
766 q = fgets(p, bufsize - (p - buffer), istk->fp);
767 if (!q)
768 break;
769 p += strlen(p);
770 if (p > buffer && p[-1] == '\n') {
771 /* Convert backslash-CRLF line continuation sequences into
772 nothing at all (for DOS and Windows) */
773 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
774 p -= 3;
775 *p = 0;
776 continued_count++;
777 }
778 /* Also convert backslash-LF line continuation sequences into
779 nothing at all (for Unix) */
780 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
781 p -= 2;
782 *p = 0;
783 continued_count++;
784 } else {
785 break;
786 }
787 }
788 if (p - buffer > bufsize - 10) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000789 int32_t offset = p - buffer;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000790 bufsize += BUF_DELTA;
791 buffer = nasm_realloc(buffer, bufsize);
792 p = buffer + offset; /* prevent stale-pointer problems */
793 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000794 }
795
H. Peter Anvine2c80182005-01-15 22:15:51 +0000796 if (!q && p == buffer) {
797 nasm_free(buffer);
798 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000799 }
800
H. Peter Anvine2c80182005-01-15 22:15:51 +0000801 src_set_linnum(src_get_linnum() + istk->lineinc +
802 (continued_count * istk->lineinc));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000803
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000804 /*
805 * Play safe: remove CRs as well as LFs, if any of either are
806 * present at the end of the line.
807 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000808 while (--p >= buffer && (*p == '\n' || *p == '\r'))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000809 *p = '\0';
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000810
811 /*
812 * Handle spurious ^Z, which may be inserted into source files
813 * by some file transfer utilities.
814 */
815 buffer[strcspn(buffer, "\032")] = '\0';
816
H. Peter Anvin734b1882002-04-30 21:01:08 +0000817 list->line(LIST_READ, buffer);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000818
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000819 return buffer;
820}
821
822/*
Keith Kaniosb7a89542007-04-12 02:40:54 +0000823 * Tokenize a line of text. This is a very simple process since we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000824 * don't need to parse the value out of e.g. numeric tokens: we
825 * simply split one string into many.
826 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000827static Token *tokenize(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000828{
H. Peter Anvinca544db2008-10-19 19:30:11 -0700829 char c, *p = line;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000830 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000831 Token *list = NULL;
832 Token *t, **tail = &list;
833
H. Peter Anvine2c80182005-01-15 22:15:51 +0000834 while (*line) {
835 p = line;
836 if (*p == '%') {
837 p++;
H. Peter Anvind784a082009-04-20 14:01:18 -0700838 if (*p == '+' && !nasm_isdigit(p[1])) {
839 p++;
840 type = TOK_PASTE;
841 } else if (nasm_isdigit(*p) ||
842 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000843 do {
844 p++;
845 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700846 while (nasm_isdigit(*p));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000847 type = TOK_PREPROC_ID;
848 } else if (*p == '{') {
849 p++;
850 while (*p && *p != '}') {
851 p[-1] = *p;
852 p++;
853 }
854 p[-1] = '\0';
855 if (*p)
856 p++;
857 type = TOK_PREPROC_ID;
H. Peter Anvin992fe752008-10-19 15:45:05 -0700858 } else if (*p == '[') {
859 int lvl = 1;
860 line += 2; /* Skip the leading %[ */
861 p++;
H. Peter Anvinec033012008-10-19 22:12:06 -0700862 while (lvl && (c = *p++)) {
H. Peter Anvinca544db2008-10-19 19:30:11 -0700863 switch (c) {
864 case ']':
865 lvl--;
866 break;
867 case '%':
H. Peter Anvinca544db2008-10-19 19:30:11 -0700868 if (*p == '[')
869 lvl++;
870 break;
871 case '\'':
872 case '\"':
873 case '`':
H. Peter Anvinec033012008-10-19 22:12:06 -0700874 p = nasm_skip_string(p)+1;
H. Peter Anvinca544db2008-10-19 19:30:11 -0700875 break;
876 default:
877 break;
H. Peter Anvin992fe752008-10-19 15:45:05 -0700878 }
H. Peter Anvin992fe752008-10-19 15:45:05 -0700879 }
H. Peter Anvinec033012008-10-19 22:12:06 -0700880 p--;
H. Peter Anvin992fe752008-10-19 15:45:05 -0700881 if (*p)
882 *p++ = '\0';
H. Peter Anvine1265812008-10-19 22:14:30 -0700883 if (lvl)
884 error(ERR_NONFATAL, "unterminated %[ construct");
H. Peter Anvin992fe752008-10-19 15:45:05 -0700885 type = TOK_INDIRECT;
H. Peter Anvin6c81f0a2008-05-25 21:46:17 -0700886 } else if (*p == '?') {
887 type = TOK_PREPROC_Q; /* %? */
888 p++;
889 if (*p == '?') {
890 type = TOK_PREPROC_QQ; /* %?? */
891 p++;
892 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000893 } else if (isidchar(*p) ||
894 ((*p == '!' || *p == '%' || *p == '$') &&
895 isidchar(p[1]))) {
896 do {
897 p++;
898 }
899 while (isidchar(*p));
900 type = TOK_PREPROC_ID;
901 } else {
902 type = TOK_OTHER;
903 if (*p == '%')
904 p++;
905 }
906 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
907 type = TOK_ID;
908 p++;
909 while (*p && isidchar(*p))
910 p++;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700911 } else if (*p == '\'' || *p == '"' || *p == '`') {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000912 /*
913 * A string token.
914 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000915 type = TOK_STRING;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700916 p = nasm_skip_string(p);
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000917
H. Peter Anvine2c80182005-01-15 22:15:51 +0000918 if (*p) {
919 p++;
920 } else {
H. Peter Anvin917a3492008-09-24 09:14:49 -0700921 error(ERR_WARNING|ERR_PASS1, "unterminated string");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000922 /* Handling unterminated strings by UNV */
923 /* type = -1; */
924 }
Victor van den Elzenfb5f2512009-04-17 16:17:59 +0200925 } else if (p[0] == '$' && p[1] == '$') {
H. Peter Anvin8e1f8112009-04-17 14:20:44 -0700926 type = TOK_OTHER; /* TOKEN_BASE */
Victor van den Elzenfb5f2512009-04-17 16:17:59 +0200927 p += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000928 } else if (isnumstart(*p)) {
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700929 bool is_hex = false;
930 bool is_float = false;
931 bool has_e = false;
932 char c, *r;
933
H. Peter Anvine2c80182005-01-15 22:15:51 +0000934 /*
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700935 * A numeric token.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000936 */
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700937
938 if (*p == '$') {
939 p++;
940 is_hex = true;
941 }
942
943 for (;;) {
944 c = *p++;
945
946 if (!is_hex && (c == 'e' || c == 'E')) {
947 has_e = true;
948 if (*p == '+' || *p == '-') {
949 /* e can only be followed by +/- if it is either a
950 prefixed hex number or a floating-point number */
951 p++;
952 is_float = true;
953 }
954 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
955 is_hex = true;
956 } else if (c == 'P' || c == 'p') {
957 is_float = true;
958 if (*p == '+' || *p == '-')
959 p++;
960 } else if (isnumchar(c) || c == '_')
961 ; /* just advance */
962 else if (c == '.') {
963 /* we need to deal with consequences of the legacy
964 parser, like "1.nolist" being two tokens
965 (TOK_NUMBER, TOK_ID) here; at least give it
966 a shot for now. In the future, we probably need
967 a flex-based scanner with proper pattern matching
968 to do it as well as it can be done. Nothing in
969 the world is going to help the person who wants
970 0x123.p16 interpreted as two tokens, though. */
971 r = p;
972 while (*r == '_')
973 r++;
974
H. Peter Anvinf221b9e2008-06-21 11:03:51 -0700975 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700976 (!is_hex && (*r == 'e' || *r == 'E')) ||
977 (*r == 'p' || *r == 'P')) {
978 p = r;
979 is_float = true;
980 } else
981 break; /* Terminate the token */
982 } else
983 break;
984 }
985 p--; /* Point to first character beyond number */
986
H. Peter Anvin8e1f8112009-04-17 14:20:44 -0700987 if (p == line+1 && *line == '$') {
988 type = TOK_OTHER; /* TOKEN_HERE */
989 } else {
990 if (has_e && !is_hex) {
991 /* 1e13 is floating-point, but 1e13h is not */
992 is_float = true;
993 }
H. Peter Anvind784a082009-04-20 14:01:18 -0700994
H. Peter Anvin8e1f8112009-04-17 14:20:44 -0700995 type = is_float ? TOK_FLOAT : TOK_NUMBER;
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700996 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700997 } else if (nasm_isspace(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000998 type = TOK_WHITESPACE;
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400999 p = nasm_skip_spaces(p);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001000 /*
1001 * Whitespace just before end-of-line is discarded by
1002 * pretending it's a comment; whitespace just before a
1003 * comment gets lumped into the comment.
1004 */
1005 if (!*p || *p == ';') {
1006 type = TOK_COMMENT;
1007 while (*p)
1008 p++;
1009 }
1010 } else if (*p == ';') {
1011 type = TOK_COMMENT;
1012 while (*p)
1013 p++;
1014 } else {
1015 /*
1016 * Anything else is an operator of some kind. We check
1017 * for all the double-character operators (>>, <<, //,
1018 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001019 * else is a single-character operator.
H. Peter Anvine2c80182005-01-15 22:15:51 +00001020 */
1021 type = TOK_OTHER;
1022 if ((p[0] == '>' && p[1] == '>') ||
1023 (p[0] == '<' && p[1] == '<') ||
1024 (p[0] == '/' && p[1] == '/') ||
1025 (p[0] == '<' && p[1] == '=') ||
1026 (p[0] == '>' && p[1] == '=') ||
1027 (p[0] == '=' && p[1] == '=') ||
1028 (p[0] == '!' && p[1] == '=') ||
1029 (p[0] == '<' && p[1] == '>') ||
1030 (p[0] == '&' && p[1] == '&') ||
1031 (p[0] == '|' && p[1] == '|') ||
1032 (p[0] == '^' && p[1] == '^')) {
1033 p++;
1034 }
1035 p++;
1036 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001037
H. Peter Anvine2c80182005-01-15 22:15:51 +00001038 /* Handling unterminated string by UNV */
1039 /*if (type == -1)
H. Peter Anvin89cee572009-07-15 09:16:54 -04001040 {
1041 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1042 t->text[p-line] = *line;
1043 tail = &t->next;
1044 }
1045 else */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001046 if (type != TOK_COMMENT) {
1047 *tail = t = new_Token(NULL, type, line, p - line);
1048 tail = &t->next;
1049 }
1050 line = p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001051 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001052 return list;
1053}
1054
H. Peter Anvince616072002-04-30 21:02:23 +00001055/*
1056 * this function allocates a new managed block of memory and
H. Peter Anvin70653092007-10-19 14:42:29 -07001057 * returns a pointer to the block. The managed blocks are
H. Peter Anvince616072002-04-30 21:02:23 +00001058 * deleted only all at once by the delete_Blocks function.
1059 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001060static void *new_Block(size_t size)
H. Peter Anvince616072002-04-30 21:02:23 +00001061{
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001062 Blocks *b = &blocks;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001063
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001064 /* first, get to the end of the linked list */
1065 while (b->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001066 b = b->next;
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001067 /* now allocate the requested chunk */
1068 b->chunk = nasm_malloc(size);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001069
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001070 /* now allocate a new block for the next request */
1071 b->next = nasm_malloc(sizeof(Blocks));
1072 /* and initialize the contents of the new block */
1073 b->next->next = NULL;
1074 b->next->chunk = NULL;
1075 return b->chunk;
H. Peter Anvince616072002-04-30 21:02:23 +00001076}
1077
1078/*
1079 * this function deletes all managed blocks of memory
1080 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001081static void delete_Blocks(void)
H. Peter Anvince616072002-04-30 21:02:23 +00001082{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001083 Blocks *a, *b = &blocks;
H. Peter Anvince616072002-04-30 21:02:23 +00001084
H. Peter Anvin70653092007-10-19 14:42:29 -07001085 /*
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001086 * keep in mind that the first block, pointed to by blocks
H. Peter Anvin70653092007-10-19 14:42:29 -07001087 * is a static and not dynamically allocated, so we don't
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001088 * free it.
1089 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001090 while (b) {
1091 if (b->chunk)
1092 nasm_free(b->chunk);
1093 a = b;
1094 b = b->next;
1095 if (a != &blocks)
1096 nasm_free(a);
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001097 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001098}
H. Peter Anvin734b1882002-04-30 21:01:08 +00001099
1100/*
H. Peter Anvin70653092007-10-19 14:42:29 -07001101 * this function creates a new Token and passes a pointer to it
H. Peter Anvin734b1882002-04-30 21:01:08 +00001102 * back to the caller. It sets the type and text elements, and
H. Peter Anvinf26e0972008-07-01 21:26:27 -07001103 * also the a.mac and next elements to NULL.
H. Peter Anvin734b1882002-04-30 21:01:08 +00001104 */
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001105static Token *new_Token(Token * next, enum pp_token_type type,
H. Peter Anvinc751e862008-06-09 10:18:45 -07001106 const char *text, int txtlen)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001107{
1108 Token *t;
1109 int i;
1110
H. Peter Anvin89cee572009-07-15 09:16:54 -04001111 if (!freeTokens) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001112 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
1113 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
1114 freeTokens[i].next = &freeTokens[i + 1];
1115 freeTokens[i].next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001116 }
1117 t = freeTokens;
1118 freeTokens = t->next;
1119 t->next = next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07001120 t->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001121 t->type = type;
H. Peter Anvin89cee572009-07-15 09:16:54 -04001122 if (type == TOK_WHITESPACE || !text) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001123 t->text = NULL;
1124 } else {
1125 if (txtlen == 0)
1126 txtlen = strlen(text);
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001127 t->text = nasm_malloc(txtlen+1);
1128 memcpy(t->text, text, txtlen);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001129 t->text[txtlen] = '\0';
H. Peter Anvin734b1882002-04-30 21:01:08 +00001130 }
1131 return t;
1132}
1133
H. Peter Anvine2c80182005-01-15 22:15:51 +00001134static Token *delete_Token(Token * t)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001135{
1136 Token *next = t->next;
1137 nasm_free(t->text);
H. Peter Anvin788e6c12002-04-30 21:02:01 +00001138 t->next = freeTokens;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001139 freeTokens = t;
1140 return next;
1141}
1142
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001143/*
1144 * Convert a line of tokens back into text.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001145 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1146 * will be transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001147 */
H. Peter Anvin9e200162008-06-04 17:23:14 -07001148static char *detoken(Token * tlist, bool expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001149{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001150 Token *t;
1151 int len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001152 char *line, *p;
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001153 const char *q;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001154
1155 len = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001156 for (t = tlist; t; t = t->next) {
1157 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001158 char *p = getenv(t->text + 2);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001159 nasm_free(t->text);
1160 if (p)
1161 t->text = nasm_strdup(p);
1162 else
1163 t->text = NULL;
1164 }
1165 /* Expand local macros here and not during preprocessing */
1166 if (expand_locals &&
1167 t->type == TOK_PREPROC_ID && t->text &&
1168 t->text[0] == '%' && t->text[1] == '$') {
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001169 const char *q;
1170 char *p;
1171 Context *ctx = get_ctx(t->text, &q, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001172 if (ctx) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001173 char buffer[40];
Keith Kanios93f2e9a2007-04-14 00:10:59 +00001174 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001175 p = nasm_strcat(buffer, q);
1176 nasm_free(t->text);
1177 t->text = p;
1178 }
1179 }
1180 if (t->type == TOK_WHITESPACE) {
1181 len++;
1182 } else if (t->text) {
1183 len += strlen(t->text);
1184 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001185 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001186 p = line = nasm_malloc(len + 1);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001187 for (t = tlist; t; t = t->next) {
1188 if (t->type == TOK_WHITESPACE) {
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001189 *p++ = ' ';
H. Peter Anvine2c80182005-01-15 22:15:51 +00001190 } else if (t->text) {
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001191 q = t->text;
1192 while (*q)
1193 *p++ = *q++;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001194 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001195 }
1196 *p = '\0';
1197 return line;
1198}
1199
1200/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001201 * A scanner, suitable for use by the expression evaluator, which
1202 * operates on a line of Tokens. Expects a pointer to a pointer to
1203 * the first token in the line to be passed in as its private_data
1204 * field.
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001205 *
1206 * FIX: This really needs to be unified with stdscan.
H. Peter Anvin76690a12002-04-30 20:52:49 +00001207 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001208static int ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001209{
H. Peter Anvin76690a12002-04-30 20:52:49 +00001210 Token **tlineptr = private_data;
1211 Token *tline;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001212 char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001213
H. Peter Anvine2c80182005-01-15 22:15:51 +00001214 do {
1215 tline = *tlineptr;
1216 *tlineptr = tline ? tline->next : NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001217 }
1218 while (tline && (tline->type == TOK_WHITESPACE ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001219 tline->type == TOK_COMMENT));
H. Peter Anvin76690a12002-04-30 20:52:49 +00001220
1221 if (!tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001222 return tokval->t_type = TOKEN_EOS;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001223
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001224 tokval->t_charptr = tline->text;
1225
H. Peter Anvin76690a12002-04-30 20:52:49 +00001226 if (tline->text[0] == '$' && !tline->text[1])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001227 return tokval->t_type = TOKEN_HERE;
H. Peter Anvin7cf897e2002-05-30 21:30:33 +00001228 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001229 return tokval->t_type = TOKEN_BASE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001230
H. Peter Anvine2c80182005-01-15 22:15:51 +00001231 if (tline->type == TOK_ID) {
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001232 p = tokval->t_charptr = tline->text;
1233 if (p[0] == '$') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001234 tokval->t_charptr++;
1235 return tokval->t_type = TOKEN_ID;
1236 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001237
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001238 for (r = p, s = ourcopy; *r; r++) {
Philipp Thomas76ec8e72008-05-21 08:53:21 -07001239 if (r >= p+MAX_KEYWORD)
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001240 return tokval->t_type = TOKEN_ID; /* Not a keyword */
H. Peter Anvinac8f8fc2008-06-11 15:49:41 -07001241 *s++ = nasm_tolower(*r);
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001242 }
1243 *s = '\0';
1244 /* right, so we have an identifier sitting in temp storage. now,
1245 * is it actually a register or instruction name, or what? */
1246 return nasm_token_hash(ourcopy, tokval);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001247 }
1248
H. Peter Anvine2c80182005-01-15 22:15:51 +00001249 if (tline->type == TOK_NUMBER) {
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001250 bool rn_error;
1251 tokval->t_integer = readnum(tline->text, &rn_error);
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001252 tokval->t_charptr = tline->text;
H. Peter Anvin11627042008-06-09 20:45:19 -07001253 if (rn_error)
1254 return tokval->t_type = TOKEN_ERRNUM;
1255 else
1256 return tokval->t_type = TOKEN_NUM;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001257 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001258
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001259 if (tline->type == TOK_FLOAT) {
1260 return tokval->t_type = TOKEN_FLOAT;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001261 }
1262
H. Peter Anvine2c80182005-01-15 22:15:51 +00001263 if (tline->type == TOK_STRING) {
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07001264 char bq, *ep;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001265
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07001266 bq = tline->text[0];
H. Peter Anvin11627042008-06-09 20:45:19 -07001267 tokval->t_charptr = tline->text;
1268 tokval->t_inttwo = nasm_unquote(tline->text, &ep);
H. Peter Anvind2456592008-06-19 15:04:18 -07001269
H. Peter Anvin11627042008-06-09 20:45:19 -07001270 if (ep[0] != bq || ep[1] != '\0')
1271 return tokval->t_type = TOKEN_ERRSTR;
1272 else
1273 return tokval->t_type = TOKEN_STR;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001274 }
1275
H. Peter Anvine2c80182005-01-15 22:15:51 +00001276 if (tline->type == TOK_OTHER) {
1277 if (!strcmp(tline->text, "<<"))
1278 return tokval->t_type = TOKEN_SHL;
1279 if (!strcmp(tline->text, ">>"))
1280 return tokval->t_type = TOKEN_SHR;
1281 if (!strcmp(tline->text, "//"))
1282 return tokval->t_type = TOKEN_SDIV;
1283 if (!strcmp(tline->text, "%%"))
1284 return tokval->t_type = TOKEN_SMOD;
1285 if (!strcmp(tline->text, "=="))
1286 return tokval->t_type = TOKEN_EQ;
1287 if (!strcmp(tline->text, "<>"))
1288 return tokval->t_type = TOKEN_NE;
1289 if (!strcmp(tline->text, "!="))
1290 return tokval->t_type = TOKEN_NE;
1291 if (!strcmp(tline->text, "<="))
1292 return tokval->t_type = TOKEN_LE;
1293 if (!strcmp(tline->text, ">="))
1294 return tokval->t_type = TOKEN_GE;
1295 if (!strcmp(tline->text, "&&"))
1296 return tokval->t_type = TOKEN_DBL_AND;
1297 if (!strcmp(tline->text, "^^"))
1298 return tokval->t_type = TOKEN_DBL_XOR;
1299 if (!strcmp(tline->text, "||"))
1300 return tokval->t_type = TOKEN_DBL_OR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001301 }
1302
1303 /*
1304 * We have no other options: just return the first character of
1305 * the token text.
1306 */
1307 return tokval->t_type = tline->text[0];
1308}
1309
1310/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001311 * Compare a string to the name of an existing macro; this is a
1312 * simple wrapper which calls either strcmp or nasm_stricmp
1313 * depending on the value of the `casesense' parameter.
1314 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001315static int mstrcmp(const char *p, const char *q, bool casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001316{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001317 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001318}
1319
1320/*
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001321 * Compare a string to the name of an existing macro; this is a
1322 * simple wrapper which calls either strcmp or nasm_stricmp
1323 * depending on the value of the `casesense' parameter.
1324 */
1325static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
1326{
1327 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
1328}
1329
1330/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001331 * Return the Context structure associated with a %$ token. Return
1332 * NULL, having _already_ reported an error condition, if the
1333 * context stack isn't deep enough for the supplied number of $
1334 * signs.
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001335 * If all_contexts == true, contexts that enclose current are
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001336 * also scanned for such smacro, until it is found; if not -
1337 * only the context that directly results from the number of $'s
1338 * in variable's name.
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001339 *
1340 * If "namep" is non-NULL, set it to the pointer to the macro name
1341 * tail, i.e. the part beyond %$...
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001342 */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001343static Context *get_ctx(const char *name, const char **namep,
1344 bool all_contexts)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001345{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001346 Context *ctx;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001347 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001348 int i;
1349
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001350 if (namep)
1351 *namep = name;
1352
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001353 if (!name || name[0] != '%' || name[1] != '$')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001354 return NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001355
H. Peter Anvine2c80182005-01-15 22:15:51 +00001356 if (!cstk) {
1357 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1358 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001359 }
1360
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001361 name += 2;
1362 ctx = cstk;
1363 i = 0;
1364 while (ctx && *name == '$') {
1365 name++;
1366 i++;
1367 ctx = ctx->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001368 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001369 if (!ctx) {
1370 error(ERR_NONFATAL, "`%s': context stack is only"
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001371 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001372 return NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001373 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001374
1375 if (namep)
1376 *namep = name;
1377
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001378 if (!all_contexts)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001379 return ctx;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001380
H. Peter Anvine2c80182005-01-15 22:15:51 +00001381 do {
1382 /* Search for this smacro in found context */
H. Peter Anvin166c2472008-05-28 12:28:58 -07001383 m = hash_findix(&ctx->localmac, name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001384 while (m) {
1385 if (!mstrcmp(m->name, name, m->casesense))
1386 return ctx;
1387 m = m->next;
1388 }
1389 ctx = ctx->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001390 }
1391 while (ctx);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001392 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001393}
1394
1395/*
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001396 * Check to see if a file is already in a string list
1397 */
1398static bool in_list(const StrList *list, const char *str)
1399{
1400 while (list) {
1401 if (!strcmp(list->str, str))
1402 return true;
1403 list = list->next;
1404 }
1405 return false;
1406}
1407
1408/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001409 * Open an include file. This routine must always return a valid
1410 * file pointer if it returns - it's responsible for throwing an
1411 * ERR_FATAL and bombing out completely if not. It should also try
1412 * the include path one by one until it finds the file or reaches
1413 * the end of the path.
1414 */
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07001415static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
H. Peter Anvin418ca702008-05-30 10:42:30 -07001416 bool missing_ok)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001417{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001418 FILE *fp;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001419 char *prefix = "";
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001420 IncPath *ip = ipath;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001421 int len = strlen(file);
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001422 size_t prefix_len = 0;
1423 StrList *sl;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001424
H. Peter Anvine2c80182005-01-15 22:15:51 +00001425 while (1) {
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001426 sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
1427 memcpy(sl->str, prefix, prefix_len);
1428 memcpy(sl->str+prefix_len, file, len+1);
1429 fp = fopen(sl->str, "r");
H. Peter Anvin418ca702008-05-30 10:42:30 -07001430 if (fp && dhead && !in_list(*dhead, sl->str)) {
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001431 sl->next = NULL;
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07001432 **dtail = sl;
1433 *dtail = &sl->next;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001434 } else {
1435 nasm_free(sl);
1436 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001437 if (fp)
1438 return fp;
H. Peter Anvin418ca702008-05-30 10:42:30 -07001439 if (!ip) {
1440 if (!missing_ok)
1441 break;
1442 prefix = NULL;
1443 } else {
1444 prefix = ip->path;
1445 ip = ip->next;
1446 }
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001447 if (prefix) {
1448 prefix_len = strlen(prefix);
1449 } else {
1450 /* -MG given and file not found */
H. Peter Anvin418ca702008-05-30 10:42:30 -07001451 if (dhead && !in_list(*dhead, file)) {
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001452 sl = nasm_malloc(len+1+sizeof sl->next);
1453 sl->next = NULL;
1454 strcpy(sl->str, file);
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07001455 **dtail = sl;
1456 *dtail = &sl->next;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001457 }
H. Peter Anvin37a321f2007-09-24 13:41:58 -07001458 return NULL;
1459 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001460 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001461
H. Peter Anvin734b1882002-04-30 21:01:08 +00001462 error(ERR_FATAL, "unable to open include file `%s'", file);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001463 return NULL; /* never reached - placate compilers */
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001464}
1465
1466/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001467 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001468 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001469 * return true if _any_ single-line macro of that name is defined.
1470 * Otherwise, will return true if a single-line macro with either
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001471 * `nparam' or no parameters is defined.
1472 *
1473 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001474 * defined, or nparam is -1, the address of the definition structure
1475 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001476 * is NULL, no action will be taken regarding its contents, and no
1477 * error will occur.
1478 *
1479 * Note that this is also called with nparam zero to resolve
1480 * `ifdef'.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001481 *
1482 * If you already know which context macro belongs to, you can pass
1483 * the context pointer as first parameter; if you won't but name begins
1484 * with %$ the context will be automatically computed. If all_contexts
1485 * is true, macro will be searched in outer contexts as well.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001486 */
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001487static bool
H. Peter Anvinb2a5fda2008-06-19 21:42:42 -07001488smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001489 bool nocase)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001490{
H. Peter Anvin166c2472008-05-28 12:28:58 -07001491 struct hash_table *smtbl;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001492 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001493
H. Peter Anvin97a23472007-09-16 17:57:25 -07001494 if (ctx) {
H. Peter Anvin166c2472008-05-28 12:28:58 -07001495 smtbl = &ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001496 } else if (name[0] == '%' && name[1] == '$') {
1497 if (cstk)
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001498 ctx = get_ctx(name, &name, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001499 if (!ctx)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001500 return false; /* got to return _something_ */
H. Peter Anvin166c2472008-05-28 12:28:58 -07001501 smtbl = &ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001502 } else {
H. Peter Anvin166c2472008-05-28 12:28:58 -07001503 smtbl = &smacros;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001504 }
H. Peter Anvin166c2472008-05-28 12:28:58 -07001505 m = (SMacro *) hash_findix(smtbl, name);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001506
H. Peter Anvine2c80182005-01-15 22:15:51 +00001507 while (m) {
1508 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
Charles Crayne192d5b52007-10-18 19:02:42 -07001509 (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001510 if (defn) {
Charles Crayne192d5b52007-10-18 19:02:42 -07001511 if (nparam == (int) m->nparam || nparam == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001512 *defn = m;
1513 else
1514 *defn = NULL;
1515 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001516 return true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001517 }
1518 m = m->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001519 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001520
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001521 return false;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001522}
1523
1524/*
1525 * Count and mark off the parameters in a multi-line macro call.
1526 * This is called both from within the multi-line macro expansion
1527 * code, and also to mark off the default parameters when provided
1528 * in a %macro definition line.
1529 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001530static void count_mmac_params(Token * t, int *nparam, Token *** params)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001531{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001532 int paramsize, brace;
1533
1534 *nparam = paramsize = 0;
1535 *params = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001536 while (t) {
H. Peter Anvin91fb6f12008-09-01 10:56:33 -07001537 /* +1: we need space for the final NULL */
1538 if (*nparam+1 >= paramsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001539 paramsize += PARAM_DELTA;
1540 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1541 }
1542 skip_white_(t);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001543 brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001544 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001545 brace = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001546 (*params)[(*nparam)++] = t;
1547 while (tok_isnt_(t, brace ? "}" : ","))
1548 t = t->next;
1549 if (t) { /* got a comma/brace */
1550 t = t->next;
1551 if (brace) {
1552 /*
1553 * Now we've found the closing brace, look further
1554 * for the comma.
1555 */
1556 skip_white_(t);
1557 if (tok_isnt_(t, ",")) {
1558 error(ERR_NONFATAL,
1559 "braces do not enclose all of macro parameter");
1560 while (tok_isnt_(t, ","))
1561 t = t->next;
1562 }
1563 if (t)
1564 t = t->next; /* eat the comma */
1565 }
1566 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001567 }
1568}
1569
1570/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001571 * Determine whether one of the various `if' conditions is true or
1572 * not.
1573 *
1574 * We must free the tline we get passed.
1575 */
H. Peter Anvin70055962007-10-11 00:05:31 -07001576static bool if_condition(Token * tline, enum preproc_token ct)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001577{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001578 enum pp_conditional i = PP_COND(ct);
H. Peter Anvin70055962007-10-11 00:05:31 -07001579 bool j;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001580 Token *t, *tt, **tptr, *origline;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001581 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001582 expr *evalresult;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001583 enum pp_token_type needtype;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001584
1585 origline = tline;
1586
H. Peter Anvine2c80182005-01-15 22:15:51 +00001587 switch (i) {
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001588 case PPC_IFCTX:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001589 j = false; /* have we matched yet? */
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001590 while (true) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001591 skip_white_(tline);
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001592 if (!tline)
1593 break;
1594 if (tline->type != TOK_ID) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001595 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001596 "`%s' expects context identifiers", pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001597 free_tlist(origline);
1598 return -1;
1599 }
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001600 if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001601 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001602 tline = tline->next;
1603 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001604 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001605
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001606 case PPC_IFDEF:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001607 j = false; /* have we matched yet? */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001608 while (tline) {
1609 skip_white_(tline);
1610 if (!tline || (tline->type != TOK_ID &&
1611 (tline->type != TOK_PREPROC_ID ||
1612 tline->text[1] != '$'))) {
1613 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001614 "`%s' expects macro identifiers", pp_directives[ct]);
1615 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001616 }
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001617 if (smacro_defined(NULL, tline->text, 0, NULL, true))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001618 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001619 tline = tline->next;
1620 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001621 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001622
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001623 case PPC_IFIDN:
1624 case PPC_IFIDNI:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001625 tline = expand_smacro(tline);
1626 t = tt = tline;
1627 while (tok_isnt_(tt, ","))
1628 tt = tt->next;
1629 if (!tt) {
1630 error(ERR_NONFATAL,
1631 "`%s' expects two comma-separated arguments",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001632 pp_directives[ct]);
1633 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001634 }
1635 tt = tt->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001636 j = true; /* assume equality unless proved not */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001637 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1638 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1639 error(ERR_NONFATAL, "`%s': more than one comma on line",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001640 pp_directives[ct]);
1641 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001642 }
1643 if (t->type == TOK_WHITESPACE) {
1644 t = t->next;
1645 continue;
1646 }
1647 if (tt->type == TOK_WHITESPACE) {
1648 tt = tt->next;
1649 continue;
1650 }
1651 if (tt->type != t->type) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001652 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001653 break;
1654 }
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001655 /* When comparing strings, need to unquote them first */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001656 if (t->type == TOK_STRING) {
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07001657 size_t l1 = nasm_unquote(t->text, NULL);
1658 size_t l2 = nasm_unquote(tt->text, NULL);
H. Peter Anvind2456592008-06-19 15:04:18 -07001659
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001660 if (l1 != l2) {
1661 j = false;
1662 break;
1663 }
1664 if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
1665 j = false;
1666 break;
1667 }
1668 } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001669 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001670 break;
1671 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001672
H. Peter Anvine2c80182005-01-15 22:15:51 +00001673 t = t->next;
1674 tt = tt->next;
1675 }
1676 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001677 j = false; /* trailing gunk on one end or other */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001678 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001679
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001680 case PPC_IFMACRO:
H. Peter Anvin89cee572009-07-15 09:16:54 -04001681 {
1682 bool found = false;
1683 MMacro searching, *mmac;
H. Peter Anvin65747262002-05-07 00:10:05 +00001684
H. Peter Anvin89cee572009-07-15 09:16:54 -04001685 skip_white_(tline);
1686 tline = expand_id(tline);
1687 if (!tok_type_(tline, TOK_ID)) {
1688 error(ERR_NONFATAL,
1689 "`%s' expects a macro name", pp_directives[ct]);
1690 goto fail;
1691 }
1692 searching.name = nasm_strdup(tline->text);
1693 searching.casesense = true;
1694 searching.plus = false;
1695 searching.nolist = false;
1696 searching.in_progress = 0;
1697 searching.max_depth = 0;
1698 searching.rep_nest = NULL;
1699 searching.nparam_min = 0;
1700 searching.nparam_max = INT_MAX;
1701 tline = expand_smacro(tline->next);
1702 skip_white_(tline);
1703 if (!tline) {
1704 } else if (!tok_type_(tline, TOK_NUMBER)) {
1705 error(ERR_NONFATAL,
1706 "`%s' expects a parameter count or nothing",
1707 pp_directives[ct]);
1708 } else {
1709 searching.nparam_min = searching.nparam_max =
1710 readnum(tline->text, &j);
1711 if (j)
1712 error(ERR_NONFATAL,
1713 "unable to parse parameter count `%s'",
1714 tline->text);
1715 }
1716 if (tline && tok_is_(tline->next, "-")) {
1717 tline = tline->next->next;
1718 if (tok_is_(tline, "*"))
1719 searching.nparam_max = INT_MAX;
1720 else if (!tok_type_(tline, TOK_NUMBER))
1721 error(ERR_NONFATAL,
1722 "`%s' expects a parameter count after `-'",
1723 pp_directives[ct]);
1724 else {
1725 searching.nparam_max = readnum(tline->text, &j);
1726 if (j)
1727 error(ERR_NONFATAL,
1728 "unable to parse parameter count `%s'",
1729 tline->text);
1730 if (searching.nparam_min > searching.nparam_max)
1731 error(ERR_NONFATAL,
1732 "minimum parameter count exceeds maximum");
H. Peter Anvin97a23472007-09-16 17:57:25 -07001733 }
H. Peter Anvin89cee572009-07-15 09:16:54 -04001734 }
1735 if (tline && tok_is_(tline->next, "+")) {
1736 tline = tline->next;
1737 searching.plus = true;
1738 }
1739 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
1740 while (mmac) {
1741 if (!strcmp(mmac->name, searching.name) &&
1742 (mmac->nparam_min <= searching.nparam_max
1743 || searching.plus)
1744 && (searching.nparam_min <= mmac->nparam_max
1745 || mmac->plus)) {
1746 found = true;
1747 break;
1748 }
1749 mmac = mmac->next;
1750 }
1751 if (tline && tline->next)
1752 error(ERR_WARNING|ERR_PASS1,
1753 "trailing garbage after %%ifmacro ignored");
1754 nasm_free(searching.name);
1755 j = found;
1756 break;
1757 }
H. Peter Anvin65747262002-05-07 00:10:05 +00001758
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001759 case PPC_IFID:
1760 needtype = TOK_ID;
1761 goto iftype;
1762 case PPC_IFNUM:
1763 needtype = TOK_NUMBER;
1764 goto iftype;
1765 case PPC_IFSTR:
1766 needtype = TOK_STRING;
1767 goto iftype;
1768
1769 iftype:
H. Peter Anvin134b9462008-02-16 17:01:40 -08001770 t = tline = expand_smacro(tline);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001771
H. Peter Anvin927c92b2008-02-16 13:44:52 -08001772 while (tok_type_(t, TOK_WHITESPACE) ||
1773 (needtype == TOK_NUMBER &&
1774 tok_type_(t, TOK_OTHER) &&
1775 (t->text[0] == '-' || t->text[0] == '+') &&
1776 !t->text[1]))
1777 t = t->next;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001778
H. Peter Anvincbf768d2008-02-16 16:41:25 -08001779 j = tok_type_(t, needtype);
1780 break;
1781
1782 case PPC_IFTOKEN:
1783 t = tline = expand_smacro(tline);
1784 while (tok_type_(t, TOK_WHITESPACE))
1785 t = t->next;
1786
1787 j = false;
1788 if (t) {
1789 t = t->next; /* Skip the actual token */
1790 while (tok_type_(t, TOK_WHITESPACE))
1791 t = t->next;
1792 j = !t; /* Should be nothing left */
1793 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001794 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001795
H. Peter Anvin134b9462008-02-16 17:01:40 -08001796 case PPC_IFEMPTY:
1797 t = tline = expand_smacro(tline);
1798 while (tok_type_(t, TOK_WHITESPACE))
1799 t = t->next;
1800
1801 j = !t; /* Should be empty */
1802 break;
1803
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001804 case PPC_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001805 t = tline = expand_smacro(tline);
1806 tptr = &t;
1807 tokval.t_type = TOKEN_INVALID;
1808 evalresult = evaluate(ppscan, tptr, &tokval,
1809 NULL, pass | CRITICAL, error, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001810 if (!evalresult)
1811 return -1;
1812 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07001813 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001814 "trailing garbage after expression ignored");
1815 if (!is_simple(evalresult)) {
1816 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001817 "non-constant value given to `%s'", pp_directives[ct]);
1818 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001819 }
Chuck Crayne60ae75d2007-05-02 01:59:16 +00001820 j = reloc_value(evalresult) != 0;
H. Peter Anvin90e6e812008-07-16 14:38:24 -07001821 break;
H. Peter Anvin95e28822007-09-12 04:20:08 +00001822
H. Peter Anvine2c80182005-01-15 22:15:51 +00001823 default:
1824 error(ERR_FATAL,
1825 "preprocessor directive `%s' not yet implemented",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001826 pp_directives[ct]);
1827 goto fail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001828 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001829
1830 free_tlist(origline);
1831 return j ^ PP_NEGATIVE(ct);
H. Peter Anvin70653092007-10-19 14:42:29 -07001832
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001833fail:
1834 free_tlist(origline);
1835 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001836}
1837
1838/*
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001839 * Common code for defining an smacro
1840 */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001841static bool define_smacro(Context *ctx, const char *mname, bool casesense,
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001842 int nparam, Token *expansion)
1843{
1844 SMacro *smac, **smhead;
H. Peter Anvin166c2472008-05-28 12:28:58 -07001845 struct hash_table *smtbl;
H. Peter Anvin70653092007-10-19 14:42:29 -07001846
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001847 if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
1848 if (!smac) {
H. Peter Anvin917a3492008-09-24 09:14:49 -07001849 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001850 "single-line macro `%s' defined both with and"
1851 " without parameters", mname);
1852
1853 /* Some instances of the old code considered this a failure,
1854 some others didn't. What is the right thing to do here? */
1855 free_tlist(expansion);
1856 return false; /* Failure */
1857 } else {
1858 /*
1859 * We're redefining, so we have to take over an
1860 * existing SMacro structure. This means freeing
1861 * what was already in it.
1862 */
1863 nasm_free(smac->name);
1864 free_tlist(smac->expansion);
1865 }
1866 } else {
H. Peter Anvin166c2472008-05-28 12:28:58 -07001867 smtbl = ctx ? &ctx->localmac : &smacros;
1868 smhead = (SMacro **) hash_findi_add(smtbl, mname);
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001869 smac = nasm_malloc(sizeof(SMacro));
1870 smac->next = *smhead;
1871 *smhead = smac;
1872 }
1873 smac->name = nasm_strdup(mname);
1874 smac->casesense = casesense;
1875 smac->nparam = nparam;
1876 smac->expansion = expansion;
1877 smac->in_progress = false;
1878 return true; /* Success */
1879}
1880
1881/*
1882 * Undefine an smacro
1883 */
1884static void undef_smacro(Context *ctx, const char *mname)
1885{
1886 SMacro **smhead, *s, **sp;
H. Peter Anvin166c2472008-05-28 12:28:58 -07001887 struct hash_table *smtbl;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001888
H. Peter Anvin166c2472008-05-28 12:28:58 -07001889 smtbl = ctx ? &ctx->localmac : &smacros;
1890 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
H. Peter Anvin70653092007-10-19 14:42:29 -07001891
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001892 if (smhead) {
1893 /*
1894 * We now have a macro name... go hunt for it.
1895 */
1896 sp = smhead;
1897 while ((s = *sp) != NULL) {
1898 if (!mstrcmp(s->name, mname, s->casesense)) {
1899 *sp = s->next;
1900 nasm_free(s->name);
1901 free_tlist(s->expansion);
1902 nasm_free(s);
1903 } else {
1904 sp = &s->next;
1905 }
1906 }
1907 }
1908}
1909
H. Peter Anvin8781cb02007-11-08 20:01:11 -08001910/*
H. Peter Anvina26433d2008-07-16 14:40:01 -07001911 * Parse a mmacro specification.
1912 */
1913static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
1914{
1915 bool err;
1916
1917 tline = tline->next;
1918 skip_white_(tline);
1919 tline = expand_id(tline);
1920 if (!tok_type_(tline, TOK_ID)) {
1921 error(ERR_NONFATAL, "`%s' expects a macro name", directive);
1922 return false;
1923 }
Victor van den Elzenb916ede2008-07-23 15:14:22 +02001924
H. Peter Anvin89cee572009-07-15 09:16:54 -04001925 def->prev = NULL;
H. Peter Anvina26433d2008-07-16 14:40:01 -07001926 def->name = nasm_strdup(tline->text);
1927 def->plus = false;
1928 def->nolist = false;
1929 def->in_progress = 0;
1930 def->rep_nest = NULL;
Victor van den Elzenb916ede2008-07-23 15:14:22 +02001931 def->nparam_min = 0;
1932 def->nparam_max = 0;
1933
H. Peter Anvina26433d2008-07-16 14:40:01 -07001934 tline = expand_smacro(tline->next);
1935 skip_white_(tline);
1936 if (!tok_type_(tline, TOK_NUMBER)) {
1937 error(ERR_NONFATAL, "`%s' expects a parameter count", directive);
H. Peter Anvina26433d2008-07-16 14:40:01 -07001938 } else {
1939 def->nparam_min = def->nparam_max =
1940 readnum(tline->text, &err);
1941 if (err)
1942 error(ERR_NONFATAL,
1943 "unable to parse parameter count `%s'", tline->text);
1944 }
1945 if (tline && tok_is_(tline->next, "-")) {
1946 tline = tline->next->next;
1947 if (tok_is_(tline, "*")) {
1948 def->nparam_max = INT_MAX;
1949 } else if (!tok_type_(tline, TOK_NUMBER)) {
1950 error(ERR_NONFATAL,
1951 "`%s' expects a parameter count after `-'", directive);
1952 } else {
1953 def->nparam_max = readnum(tline->text, &err);
1954 if (err) {
1955 error(ERR_NONFATAL, "unable to parse parameter count `%s'",
1956 tline->text);
1957 }
1958 if (def->nparam_min > def->nparam_max) {
1959 error(ERR_NONFATAL, "minimum parameter count exceeds maximum");
1960 }
1961 }
1962 }
1963 if (tline && tok_is_(tline->next, "+")) {
1964 tline = tline->next;
1965 def->plus = true;
1966 }
1967 if (tline && tok_type_(tline->next, TOK_ID) &&
1968 !nasm_stricmp(tline->next->text, ".nolist")) {
1969 tline = tline->next;
1970 def->nolist = true;
1971 }
Keith Kanios891775e2009-07-11 06:08:54 -05001972
H. Peter Anvina26433d2008-07-16 14:40:01 -07001973 /*
1974 * Handle default parameters.
1975 */
1976 if (tline && tline->next) {
1977 def->dlist = tline->next;
1978 tline->next = NULL;
1979 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
1980 } else {
1981 def->dlist = NULL;
1982 def->defaults = NULL;
1983 }
1984 def->expansion = NULL;
1985
H. Peter Anvin89cee572009-07-15 09:16:54 -04001986 if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
1987 !def->plus)
1988 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MDP,
1989 "too many default macro parameters");
Victor van den Elzenb916ede2008-07-23 15:14:22 +02001990
H. Peter Anvina26433d2008-07-16 14:40:01 -07001991 return true;
1992}
1993
1994
1995/*
H. Peter Anvin8781cb02007-11-08 20:01:11 -08001996 * Decode a size directive
1997 */
1998static int parse_size(const char *str) {
1999 static const char *size_names[] =
H. Peter Anvindfb91802008-05-20 11:43:53 -07002000 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002001 static const int sizes[] =
H. Peter Anvindfb91802008-05-20 11:43:53 -07002002 { 0, 1, 4, 16, 8, 10, 2, 32 };
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002003
2004 return sizes[bsii(str, size_names, elements(size_names))+1];
2005}
2006
H. Peter Anvinf9c9a672009-07-14 15:14:05 -04002007/*
2008 * nasm_unquote with error if the string contains NUL characters.
2009 * If the string contains NUL characters, issue an error and return
2010 * the C len, i.e. truncate at the NUL.
2011 */
2012static size_t nasm_unquote_cstr(char *qstr, enum preproc_token directive)
2013{
2014 size_t len = nasm_unquote(qstr, NULL);
2015 size_t clen = strlen(qstr);
2016
2017 if (len != clen)
H. Peter Anvincd0943e2009-07-14 15:17:11 -04002018 error(ERR_NONFATAL, "NUL character in `%s' directive",
2019 pp_directives[directive]);
H. Peter Anvinf9c9a672009-07-14 15:14:05 -04002020
2021 return clen;
2022}
2023
Ed Beroset3ab3f412002-06-11 03:31:49 +00002024/**
2025 * find and process preprocessor directive in passed line
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002026 * Find out if a line contains a preprocessor directive, and deal
2027 * with it if so.
H. Peter Anvin70653092007-10-19 14:42:29 -07002028 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00002029 * If a directive _is_ found, it is the responsibility of this routine
2030 * (and not the caller) to free_tlist() the line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002031 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00002032 * @param tline a pointer to the current tokeninzed line linked list
2033 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
H. Peter Anvin70653092007-10-19 14:42:29 -07002034 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002035 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002036static int do_directive(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002037{
H. Peter Anvin4169a472007-09-12 01:29:43 +00002038 enum preproc_token i;
2039 int j;
H. Peter Anvin70055962007-10-11 00:05:31 -07002040 bool err;
2041 int nparam;
2042 bool nolist;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002043 bool casesense;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -07002044 int k, m;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002045 int offset;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002046 char *p, *pp;
2047 const char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002048 Include *inc;
2049 Context *ctx;
2050 Cond *cond;
H. Peter Anvin97a23472007-09-16 17:57:25 -07002051 MMacro *mmac, **mmhead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002052 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
2053 Line *l;
2054 struct tokenval tokval;
2055 expr *evalresult;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002056 MMacro *tmp_defining; /* Used when manipulating rep_nest */
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002057 int64_t count;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07002058 size_t len;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002059 int severity;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002060
2061 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002062
H. Peter Anvineba20a72002-04-30 20:53:55 +00002063 skip_white_(tline);
H. Peter Anvinf2936d72008-06-04 15:11:23 -07002064 if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00002065 (tline->text[1] == '%' || tline->text[1] == '$'
2066 || tline->text[1] == '!'))
2067 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002068
H. Peter Anvin4169a472007-09-12 01:29:43 +00002069 i = pp_token_hash(tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002070
2071 /*
2072 * If we're in a non-emitting branch of a condition construct,
H. Peter Anvin76690a12002-04-30 20:52:49 +00002073 * or walking to the end of an already terminated %rep block,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002074 * we should ignore all directives except for condition
2075 * directives.
2076 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00002077 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00002078 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
2079 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002080 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002081
2082 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002083 * If we're defining a macro or reading a %rep block, we should
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02002084 * ignore all directives except for %macro/%imacro (which nest),
2085 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2086 * If we're in a %rep block, another %rep nests, so should be let through.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002087 */
2088 if (defining && i != PP_MACRO && i != PP_IMACRO &&
H. Peter Anvindb8f96e2009-07-15 09:07:29 -04002089 i != PP_RMACRO && i != PP_IRMACRO &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00002090 i != PP_ENDMACRO && i != PP_ENDM &&
2091 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
2092 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002093 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002094
Charles Crayned4200be2008-07-12 16:42:33 -07002095 if (defining) {
Keith Kanios852f1ee2009-07-12 00:19:55 -05002096 if (i == PP_MACRO || i == PP_IMACRO ||
H. Peter Anvindb8f96e2009-07-15 09:07:29 -04002097 i == PP_RMACRO || i == PP_IRMACRO) {
Charles Crayned4200be2008-07-12 16:42:33 -07002098 nested_mac_count++;
2099 return NO_DIRECTIVE_FOUND;
2100 } else if (nested_mac_count > 0) {
2101 if (i == PP_ENDMACRO) {
2102 nested_mac_count--;
2103 return NO_DIRECTIVE_FOUND;
2104 }
2105 }
2106 if (!defining->name) {
2107 if (i == PP_REP) {
2108 nested_rep_count++;
2109 return NO_DIRECTIVE_FOUND;
2110 } else if (nested_rep_count > 0) {
2111 if (i == PP_ENDREP) {
2112 nested_rep_count--;
2113 return NO_DIRECTIVE_FOUND;
2114 }
2115 }
2116 }
2117 }
2118
H. Peter Anvin4169a472007-09-12 01:29:43 +00002119 switch (i) {
2120 case PP_INVALID:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002121 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2122 tline->text);
2123 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002124
H. Peter Anvine2c80182005-01-15 22:15:51 +00002125 case PP_STACKSIZE:
2126 /* Directive to tell NASM what the default stack size is. The
2127 * default is for a 16-bit stack, and this can be overriden with
2128 * %stacksize large.
2129 * the following form:
2130 *
2131 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2132 */
2133 tline = tline->next;
2134 if (tline && tline->type == TOK_WHITESPACE)
2135 tline = tline->next;
2136 if (!tline || tline->type != TOK_ID) {
2137 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
2138 free_tlist(origline);
2139 return DIRECTIVE_FOUND;
2140 }
2141 if (nasm_stricmp(tline->text, "flat") == 0) {
2142 /* All subsequent ARG directives are for a 32-bit stack */
2143 StackSize = 4;
2144 StackPointer = "ebp";
2145 ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002146 LocalOffset = 0;
Charles Crayne7eaf9192007-11-08 22:11:14 -08002147 } else if (nasm_stricmp(tline->text, "flat64") == 0) {
2148 /* All subsequent ARG directives are for a 64-bit stack */
2149 StackSize = 8;
2150 StackPointer = "rbp";
2151 ArgOffset = 8;
2152 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002153 } else if (nasm_stricmp(tline->text, "large") == 0) {
2154 /* All subsequent ARG directives are for a 16-bit stack,
2155 * far function call.
2156 */
2157 StackSize = 2;
2158 StackPointer = "bp";
2159 ArgOffset = 4;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002160 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002161 } else if (nasm_stricmp(tline->text, "small") == 0) {
2162 /* All subsequent ARG directives are for a 16-bit stack,
2163 * far function call. We don't support near functions.
2164 */
2165 StackSize = 2;
2166 StackPointer = "bp";
2167 ArgOffset = 6;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002168 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002169 } else {
2170 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
2171 free_tlist(origline);
2172 return DIRECTIVE_FOUND;
2173 }
2174 free_tlist(origline);
2175 return DIRECTIVE_FOUND;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002176
H. Peter Anvine2c80182005-01-15 22:15:51 +00002177 case PP_ARG:
2178 /* TASM like ARG directive to define arguments to functions, in
2179 * the following form:
2180 *
2181 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2182 */
2183 offset = ArgOffset;
2184 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002185 char *arg, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00002186 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002187
H. Peter Anvine2c80182005-01-15 22:15:51 +00002188 /* Find the argument name */
2189 tline = tline->next;
2190 if (tline && tline->type == TOK_WHITESPACE)
2191 tline = tline->next;
2192 if (!tline || tline->type != TOK_ID) {
2193 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
2194 free_tlist(origline);
2195 return DIRECTIVE_FOUND;
2196 }
2197 arg = tline->text;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002198
H. Peter Anvine2c80182005-01-15 22:15:51 +00002199 /* Find the argument size type */
2200 tline = tline->next;
2201 if (!tline || tline->type != TOK_OTHER
2202 || tline->text[0] != ':') {
2203 error(ERR_NONFATAL,
2204 "Syntax error processing `%%arg' directive");
2205 free_tlist(origline);
2206 return DIRECTIVE_FOUND;
2207 }
2208 tline = tline->next;
2209 if (!tline || tline->type != TOK_ID) {
2210 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
2211 free_tlist(origline);
2212 return DIRECTIVE_FOUND;
2213 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002214
H. Peter Anvine2c80182005-01-15 22:15:51 +00002215 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002216 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002217 tt = expand_smacro(tt);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002218 size = parse_size(tt->text);
2219 if (!size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002220 error(ERR_NONFATAL,
2221 "Invalid size type for `%%arg' missing directive");
2222 free_tlist(tt);
2223 free_tlist(origline);
2224 return DIRECTIVE_FOUND;
2225 }
2226 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002227
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002228 /* Round up to even stack slots */
2229 size = (size+StackSize-1) & ~(StackSize-1);
2230
H. Peter Anvine2c80182005-01-15 22:15:51 +00002231 /* Now define the macro for the argument */
2232 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
2233 arg, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002234 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00002235 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002236
H. Peter Anvine2c80182005-01-15 22:15:51 +00002237 /* Move to the next argument in the list */
2238 tline = tline->next;
2239 if (tline && tline->type == TOK_WHITESPACE)
2240 tline = tline->next;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002241 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2242 ArgOffset = offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002243 free_tlist(origline);
2244 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002245
H. Peter Anvine2c80182005-01-15 22:15:51 +00002246 case PP_LOCAL:
2247 /* TASM like LOCAL directive to define local variables for a
2248 * function, in the following form:
2249 *
2250 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2251 *
2252 * The '= LocalSize' at the end is ignored by NASM, but is
2253 * required by TASM to define the local parameter size (and used
2254 * by the TASM macro package).
2255 */
2256 offset = LocalOffset;
2257 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002258 char *local, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00002259 int size = StackSize;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002260
H. Peter Anvine2c80182005-01-15 22:15:51 +00002261 /* Find the argument name */
2262 tline = tline->next;
2263 if (tline && tline->type == TOK_WHITESPACE)
2264 tline = tline->next;
2265 if (!tline || tline->type != TOK_ID) {
2266 error(ERR_NONFATAL,
2267 "`%%local' missing argument parameter");
2268 free_tlist(origline);
2269 return DIRECTIVE_FOUND;
2270 }
2271 local = tline->text;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002272
H. Peter Anvine2c80182005-01-15 22:15:51 +00002273 /* Find the argument size type */
2274 tline = tline->next;
2275 if (!tline || tline->type != TOK_OTHER
2276 || tline->text[0] != ':') {
2277 error(ERR_NONFATAL,
2278 "Syntax error processing `%%local' directive");
2279 free_tlist(origline);
2280 return DIRECTIVE_FOUND;
2281 }
2282 tline = tline->next;
2283 if (!tline || tline->type != TOK_ID) {
2284 error(ERR_NONFATAL,
2285 "`%%local' missing size type parameter");
2286 free_tlist(origline);
2287 return DIRECTIVE_FOUND;
2288 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002289
H. Peter Anvine2c80182005-01-15 22:15:51 +00002290 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002291 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002292 tt = expand_smacro(tt);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002293 size = parse_size(tt->text);
2294 if (!size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002295 error(ERR_NONFATAL,
2296 "Invalid size type for `%%local' missing directive");
2297 free_tlist(tt);
2298 free_tlist(origline);
2299 return DIRECTIVE_FOUND;
2300 }
2301 free_tlist(tt);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002302
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002303 /* Round up to even stack slots */
2304 size = (size+StackSize-1) & ~(StackSize-1);
2305
2306 offset += size; /* Negative offset, increment before */
2307
2308 /* Now define the macro for the argument */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002309 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
2310 local, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002311 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002312
H. Peter Anvine2c80182005-01-15 22:15:51 +00002313 /* Now define the assign to setup the enter_c macro correctly */
2314 snprintf(directive, sizeof(directive),
2315 "%%assign %%$localsize %%$localsize+%d", size);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002316 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002317
H. Peter Anvine2c80182005-01-15 22:15:51 +00002318 /* Move to the next argument in the list */
2319 tline = tline->next;
2320 if (tline && tline->type == TOK_WHITESPACE)
2321 tline = tline->next;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002322 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2323 LocalOffset = offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002324 free_tlist(origline);
2325 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002326
H. Peter Anvine2c80182005-01-15 22:15:51 +00002327 case PP_CLEAR:
2328 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002329 error(ERR_WARNING|ERR_PASS1,
2330 "trailing garbage after `%%clear' ignored");
H. Peter Anvin97a23472007-09-16 17:57:25 -07002331 free_macros();
2332 init_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00002333 free_tlist(origline);
2334 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002335
H. Peter Anvin418ca702008-05-30 10:42:30 -07002336 case PP_DEPEND:
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002337 t = tline->next = expand_smacro(tline->next);
2338 skip_white_(t);
2339 if (!t || (t->type != TOK_STRING &&
H. Peter Anvin89cee572009-07-15 09:16:54 -04002340 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin418ca702008-05-30 10:42:30 -07002341 error(ERR_NONFATAL, "`%%depend' expects a file name");
2342 free_tlist(origline);
2343 return DIRECTIVE_FOUND; /* but we did _something_ */
2344 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002345 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002346 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin418ca702008-05-30 10:42:30 -07002347 "trailing garbage after `%%depend' ignored");
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002348 p = t->text;
2349 if (t->type != TOK_INTERNAL_STRING)
H. Peter Anvinf9c9a672009-07-14 15:14:05 -04002350 nasm_unquote_cstr(p, i);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002351 if (dephead && !in_list(*dephead, p)) {
2352 StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next);
2353 sl->next = NULL;
2354 strcpy(sl->str, p);
2355 *deptail = sl;
2356 deptail = &sl->next;
2357 }
2358 free_tlist(origline);
2359 return DIRECTIVE_FOUND;
2360
2361 case PP_INCLUDE:
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002362 t = tline->next = expand_smacro(tline->next);
2363 skip_white_(t);
H. Peter Anvind2456592008-06-19 15:04:18 -07002364
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002365 if (!t || (t->type != TOK_STRING &&
H. Peter Anvin89cee572009-07-15 09:16:54 -04002366 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002367 error(ERR_NONFATAL, "`%%include' expects a file name");
2368 free_tlist(origline);
2369 return DIRECTIVE_FOUND; /* but we did _something_ */
2370 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002371 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002372 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002373 "trailing garbage after `%%include' ignored");
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002374 p = t->text;
2375 if (t->type != TOK_INTERNAL_STRING)
H. Peter Anvinf9c9a672009-07-14 15:14:05 -04002376 nasm_unquote_cstr(p, i);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002377 inc = nasm_malloc(sizeof(Include));
2378 inc->next = istk;
2379 inc->conds = NULL;
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07002380 inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002381 if (!inc->fp) {
H. Peter Anvin37a321f2007-09-24 13:41:58 -07002382 /* -MG given but file not found */
2383 nasm_free(inc);
2384 } else {
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002385 inc->fname = src_set_fname(nasm_strdup(p));
H. Peter Anvin37a321f2007-09-24 13:41:58 -07002386 inc->lineno = src_set_linnum(0);
2387 inc->lineinc = 1;
2388 inc->expansion = NULL;
2389 inc->mstk = NULL;
2390 istk = inc;
2391 list->uplevel(LIST_INCLUDE);
2392 }
2393 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002394 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002395
H. Peter Anvind2456592008-06-19 15:04:18 -07002396 case PP_USE:
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002397 {
H. Peter Anvina70547f2008-07-19 21:44:26 -07002398 static macros_t *use_pkg;
H. Peter Anvinb2a5fda2008-06-19 21:42:42 -07002399 const char *pkg_macro;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002400
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002401 tline = tline->next;
2402 skip_white_(tline);
2403 tline = expand_id(tline);
H. Peter Anvind2456592008-06-19 15:04:18 -07002404
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002405 if (!tline || (tline->type != TOK_STRING &&
2406 tline->type != TOK_INTERNAL_STRING &&
2407 tline->type != TOK_ID)) {
H. Peter Anvin926fc402008-06-19 16:26:12 -07002408 error(ERR_NONFATAL, "`%%use' expects a package name");
H. Peter Anvind2456592008-06-19 15:04:18 -07002409 free_tlist(origline);
2410 return DIRECTIVE_FOUND; /* but we did _something_ */
2411 }
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002412 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002413 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvind2456592008-06-19 15:04:18 -07002414 "trailing garbage after `%%use' ignored");
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002415 if (tline->type == TOK_STRING)
H. Peter Anvinf9c9a672009-07-14 15:14:05 -04002416 nasm_unquote_cstr(tline->text, i);
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002417 use_pkg = nasm_stdmac_find_package(tline->text);
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002418 if (!use_pkg)
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002419 error(ERR_NONFATAL, "unknown `%%use' package: %s", tline->text);
H. Peter Anvinb2a5fda2008-06-19 21:42:42 -07002420 /* The first string will be <%define>__USE_*__ */
H. Peter Anvin7e50d232008-06-25 14:54:14 -07002421 pkg_macro = (char *)use_pkg + 1;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002422 if (!smacro_defined(NULL, pkg_macro, 0, NULL, true)) {
2423 /* Not already included, go ahead and include it */
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002424 stdmacpos = use_pkg;
2425 }
H. Peter Anvind2456592008-06-19 15:04:18 -07002426 free_tlist(origline);
2427 return DIRECTIVE_FOUND;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002428 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002429 case PP_PUSH:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002430 case PP_REPL:
H. Peter Anvin42b56392008-10-24 16:24:21 -07002431 case PP_POP:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002432 tline = tline->next;
2433 skip_white_(tline);
2434 tline = expand_id(tline);
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002435 if (tline) {
2436 if (!tok_type_(tline, TOK_ID)) {
H. Peter Anvin42b56392008-10-24 16:24:21 -07002437 error(ERR_NONFATAL, "`%s' expects a context identifier",
2438 pp_directives[i]);
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002439 free_tlist(origline);
2440 return DIRECTIVE_FOUND; /* but we did _something_ */
2441 }
2442 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002443 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin42b56392008-10-24 16:24:21 -07002444 "trailing garbage after `%s' ignored",
2445 pp_directives[i]);
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002446 p = nasm_strdup(tline->text);
2447 } else {
H. Peter Anvin42b56392008-10-24 16:24:21 -07002448 p = NULL; /* Anonymous */
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002449 }
H. Peter Anvin42b56392008-10-24 16:24:21 -07002450
2451 if (i == PP_PUSH) {
2452 ctx = nasm_malloc(sizeof(Context));
2453 ctx->next = cstk;
2454 hash_init(&ctx->localmac, HASH_SMALL);
2455 ctx->name = p;
2456 ctx->number = unique++;
2457 cstk = ctx;
2458 } else {
2459 /* %pop or %repl */
2460 if (!cstk) {
2461 error(ERR_NONFATAL, "`%s': context stack is empty",
2462 pp_directives[i]);
2463 } else if (i == PP_POP) {
2464 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
2465 error(ERR_NONFATAL, "`%%pop' in wrong context: %s, "
2466 "expected %s",
2467 cstk->name ? cstk->name : "anonymous", p);
2468 else
2469 ctx_pop();
2470 } else {
2471 /* i == PP_REPL */
2472 nasm_free(cstk->name);
2473 cstk->name = p;
2474 p = NULL;
2475 }
2476 nasm_free(p);
2477 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002478 free_tlist(origline);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002479 return DIRECTIVE_FOUND;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002480 case PP_FATAL:
H. Peter Anvin931cab62009-07-07 16:06:21 -07002481 severity = ERR_FATAL;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002482 goto issue_error;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002483 case PP_ERROR:
H. Peter Anvin931cab62009-07-07 16:06:21 -07002484 severity = ERR_NONFATAL;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002485 goto issue_error;
H. Peter Anvin7df04172008-06-10 18:27:38 -07002486 case PP_WARNING:
H. Peter Anvin931cab62009-07-07 16:06:21 -07002487 severity = ERR_WARNING|ERR_WARN_USER;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002488 goto issue_error;
2489
2490 issue_error:
H. Peter Anvin7df04172008-06-10 18:27:38 -07002491 {
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002492 /* Only error out if this is the final pass */
2493 if (pass != 2 && i != PP_FATAL)
2494 return DIRECTIVE_FOUND;
H. Peter Anvin89cee572009-07-15 09:16:54 -04002495
2496 tline->next = expand_smacro(tline->next);
2497 tline = tline->next;
2498 skip_white_(tline);
H. Peter Anvin7df04172008-06-10 18:27:38 -07002499 t = tline ? tline->next : NULL;
2500 skip_white_(t);
H. Peter Anvin89cee572009-07-15 09:16:54 -04002501 if (tok_type_(tline, TOK_STRING) && !t) {
H. Peter Anvin7df04172008-06-10 18:27:38 -07002502 /* The line contains only a quoted string */
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07002503 p = tline->text;
H. Peter Anvinf9c9a672009-07-14 15:14:05 -04002504 nasm_unquote(p, NULL); /* Ignore NUL character truncation */
H. Peter Anvin931cab62009-07-07 16:06:21 -07002505 error(severity, "%s", p);
H. Peter Anvin7df04172008-06-10 18:27:38 -07002506 } else {
2507 /* Not a quoted string, or more than a quoted string */
H. Peter Anvin89cee572009-07-15 09:16:54 -04002508 p = detoken(tline, false);
H. Peter Anvin931cab62009-07-07 16:06:21 -07002509 error(severity, "%s", p);
H. Peter Anvin7df04172008-06-10 18:27:38 -07002510 nasm_free(p);
H. Peter Anvind2456592008-06-19 15:04:18 -07002511 }
H. Peter Anvin89cee572009-07-15 09:16:54 -04002512 free_tlist(origline);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002513 return DIRECTIVE_FOUND;
H. Peter Anvin7df04172008-06-10 18:27:38 -07002514 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002515
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002516 CASE_PP_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002517 if (istk->conds && !emitting(istk->conds->state))
2518 j = COND_NEVER;
2519 else {
2520 j = if_condition(tline->next, i);
2521 tline->next = NULL; /* it got freed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002522 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2523 }
2524 cond = nasm_malloc(sizeof(Cond));
2525 cond->next = istk->conds;
2526 cond->state = j;
2527 istk->conds = cond;
H. Peter Anvin7061ad72007-11-26 22:02:21 -08002528 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002529 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002530
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002531 CASE_PP_ELIF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002532 if (!istk->conds)
H. Peter Anvin4169a472007-09-12 01:29:43 +00002533 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002534 switch(istk->conds->state) {
H. Peter Anvin89cee572009-07-15 09:16:54 -04002535 case COND_IF_TRUE:
2536 istk->conds->state = COND_DONE;
2537 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002538
H. Peter Anvin89cee572009-07-15 09:16:54 -04002539 case COND_DONE:
2540 case COND_NEVER:
2541 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002542
H. Peter Anvin89cee572009-07-15 09:16:54 -04002543 case COND_ELSE_TRUE:
2544 case COND_ELSE_FALSE:
2545 error_precond(ERR_WARNING|ERR_PASS1,
2546 "`%%elif' after `%%else' ignored");
2547 istk->conds->state = COND_NEVER;
2548 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002549
H. Peter Anvin89cee572009-07-15 09:16:54 -04002550 case COND_IF_FALSE:
2551 /*
2552 * IMPORTANT: In the case of %if, we will already have
2553 * called expand_mmac_params(); however, if we're
2554 * processing an %elif we must have been in a
2555 * non-emitting mode, which would have inhibited
2556 * the normal invocation of expand_mmac_params().
2557 * Therefore, we have to do it explicitly here.
2558 */
2559 j = if_condition(expand_mmac_params(tline->next), i);
2560 tline->next = NULL; /* it got freed */
2561 istk->conds->state =
2562 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2563 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002564 }
H. Peter Anvin7061ad72007-11-26 22:02:21 -08002565 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002566 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002567
H. Peter Anvine2c80182005-01-15 22:15:51 +00002568 case PP_ELSE:
2569 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002570 error_precond(ERR_WARNING|ERR_PASS1,
2571 "trailing garbage after `%%else' ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00002572 if (!istk->conds)
2573 error(ERR_FATAL, "`%%else': no matching `%%if'");
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002574 switch(istk->conds->state) {
H. Peter Anvin89cee572009-07-15 09:16:54 -04002575 case COND_IF_TRUE:
2576 case COND_DONE:
2577 istk->conds->state = COND_ELSE_FALSE;
2578 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002579
H. Peter Anvin89cee572009-07-15 09:16:54 -04002580 case COND_NEVER:
2581 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002582
H. Peter Anvin89cee572009-07-15 09:16:54 -04002583 case COND_IF_FALSE:
2584 istk->conds->state = COND_ELSE_TRUE;
2585 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002586
H. Peter Anvin89cee572009-07-15 09:16:54 -04002587 case COND_ELSE_TRUE:
2588 case COND_ELSE_FALSE:
2589 error_precond(ERR_WARNING|ERR_PASS1,
2590 "`%%else' after `%%else' ignored.");
2591 istk->conds->state = COND_NEVER;
2592 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002593 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002594 free_tlist(origline);
2595 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002596
H. Peter Anvine2c80182005-01-15 22:15:51 +00002597 case PP_ENDIF:
2598 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002599 error_precond(ERR_WARNING|ERR_PASS1,
2600 "trailing garbage after `%%endif' ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00002601 if (!istk->conds)
2602 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2603 cond = istk->conds;
2604 istk->conds = cond->next;
2605 nasm_free(cond);
2606 free_tlist(origline);
2607 return DIRECTIVE_FOUND;
Keith Kanios0af5ee22009-07-11 14:26:34 -05002608
H. Peter Anvindb8f96e2009-07-15 09:07:29 -04002609 case PP_RMACRO:
2610 case PP_IRMACRO:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002611 case PP_MACRO:
2612 case PP_IMACRO:
H. Peter Anvina26433d2008-07-16 14:40:01 -07002613 if (defining) {
H. Peter Anvindb8f96e2009-07-15 09:07:29 -04002614 error(ERR_FATAL, "`%s': already defining a macro",
2615 pp_directives[i]);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002616 return DIRECTIVE_FOUND;
2617 }
H. Peter Anvindb8f96e2009-07-15 09:07:29 -04002618 defining = nasm_malloc(sizeof(MMacro));
2619 defining->max_depth =
2620 (i == PP_RMACRO) || (i == PP_IRMACRO) ? DEADMAN_LIMIT : 0;
2621 defining->casesense = (i == PP_MACRO) || (i == PP_RMACRO);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002622 if (!parse_mmacro_spec(tline, defining, pp_directives[i])) {
2623 nasm_free(defining);
2624 defining = NULL;
2625 return DIRECTIVE_FOUND;
2626 }
2627
H. Peter Anvin166c2472008-05-28 12:28:58 -07002628 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002629 while (mmac) {
2630 if (!strcmp(mmac->name, defining->name) &&
2631 (mmac->nparam_min <= defining->nparam_max
2632 || defining->plus)
2633 && (defining->nparam_min <= mmac->nparam_max
2634 || mmac->plus)) {
H. Peter Anvin917a3492008-09-24 09:14:49 -07002635 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002636 "redefining multi-line macro `%s'", defining->name);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002637 return DIRECTIVE_FOUND;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002638 }
2639 mmac = mmac->next;
2640 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002641 free_tlist(origline);
2642 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002643
H. Peter Anvine2c80182005-01-15 22:15:51 +00002644 case PP_ENDM:
2645 case PP_ENDMACRO:
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02002646 if (! (defining && defining->name)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002647 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2648 return DIRECTIVE_FOUND;
2649 }
Keith Kanios852f1ee2009-07-12 00:19:55 -05002650 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002651 defining->next = *mmhead;
Keith Kanios852f1ee2009-07-12 00:19:55 -05002652 *mmhead = defining;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002653 defining = NULL;
2654 free_tlist(origline);
2655 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002656
H. Peter Anvin89cee572009-07-15 09:16:54 -04002657 case PP_EXITMACRO:
Keith Kanios852f1ee2009-07-12 00:19:55 -05002658 /*
2659 * We must search along istk->expansion until we hit a
2660 * macro-end marker for a macro with a name. Then we set
2661 * its `in_progress' flag to 0.
2662 */
H. Peter Anvin89cee572009-07-15 09:16:54 -04002663 for (l = istk->expansion; l; l = l->next)
Keith Kanios852f1ee2009-07-12 00:19:55 -05002664 if (l->finishes && l->finishes->name)
2665 break;
2666
2667 if (l) {
H. Peter Anvin89cee572009-07-15 09:16:54 -04002668 l->finishes->in_progress = 0;
Keith Kanios852f1ee2009-07-12 00:19:55 -05002669 } else {
2670 error(ERR_NONFATAL, "`%%exitmacro' not within `%%macro' block");
H. Peter Anvin89cee572009-07-15 09:16:54 -04002671 }
Keith Kanios852f1ee2009-07-12 00:19:55 -05002672 free_tlist(origline);
2673 return DIRECTIVE_FOUND;
2674
H. Peter Anvina26433d2008-07-16 14:40:01 -07002675 case PP_UNMACRO:
2676 case PP_UNIMACRO:
2677 {
2678 MMacro **mmac_p;
2679 MMacro spec;
2680
2681 spec.casesense = (i == PP_UNMACRO);
2682 if (!parse_mmacro_spec(tline, &spec, pp_directives[i])) {
2683 return DIRECTIVE_FOUND;
2684 }
2685 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
2686 while (mmac_p && *mmac_p) {
2687 mmac = *mmac_p;
2688 if (mmac->casesense == spec.casesense &&
2689 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
2690 mmac->nparam_min == spec.nparam_min &&
2691 mmac->nparam_max == spec.nparam_max &&
2692 mmac->plus == spec.plus) {
2693 *mmac_p = mmac->next;
2694 free_mmacro(mmac);
2695 } else {
2696 mmac_p = &mmac->next;
2697 }
2698 }
2699 free_tlist(origline);
2700 free_tlist(spec.dlist);
2701 return DIRECTIVE_FOUND;
2702 }
2703
H. Peter Anvine2c80182005-01-15 22:15:51 +00002704 case PP_ROTATE:
2705 if (tline->next && tline->next->type == TOK_WHITESPACE)
2706 tline = tline->next;
H. Peter Anvin89cee572009-07-15 09:16:54 -04002707 if (!tline->next) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002708 free_tlist(origline);
2709 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2710 return DIRECTIVE_FOUND;
2711 }
2712 t = expand_smacro(tline->next);
2713 tline->next = NULL;
2714 free_tlist(origline);
2715 tline = t;
2716 tptr = &t;
2717 tokval.t_type = TOKEN_INVALID;
2718 evalresult =
2719 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2720 free_tlist(tline);
2721 if (!evalresult)
2722 return DIRECTIVE_FOUND;
2723 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002724 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002725 "trailing garbage after expression ignored");
2726 if (!is_simple(evalresult)) {
2727 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2728 return DIRECTIVE_FOUND;
2729 }
2730 mmac = istk->mstk;
2731 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2732 mmac = mmac->next_active;
2733 if (!mmac) {
2734 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2735 } else if (mmac->nparam == 0) {
2736 error(ERR_NONFATAL,
2737 "`%%rotate' invoked within macro without parameters");
2738 } else {
H. Peter Anvin25a99342007-09-22 17:45:45 -07002739 int rotate = mmac->rotate + reloc_value(evalresult);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002740
H. Peter Anvin25a99342007-09-22 17:45:45 -07002741 rotate %= (int)mmac->nparam;
2742 if (rotate < 0)
2743 rotate += mmac->nparam;
H. Peter Anvin70653092007-10-19 14:42:29 -07002744
H. Peter Anvin25a99342007-09-22 17:45:45 -07002745 mmac->rotate = rotate;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002746 }
2747 return DIRECTIVE_FOUND;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002748
H. Peter Anvine2c80182005-01-15 22:15:51 +00002749 case PP_REP:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002750 nolist = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002751 do {
2752 tline = tline->next;
2753 } while (tok_type_(tline, TOK_WHITESPACE));
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002754
H. Peter Anvine2c80182005-01-15 22:15:51 +00002755 if (tok_type_(tline, TOK_ID) &&
2756 nasm_stricmp(tline->text, ".nolist") == 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002757 nolist = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002758 do {
2759 tline = tline->next;
2760 } while (tok_type_(tline, TOK_WHITESPACE));
2761 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002762
H. Peter Anvine2c80182005-01-15 22:15:51 +00002763 if (tline) {
2764 t = expand_smacro(tline);
2765 tptr = &t;
2766 tokval.t_type = TOKEN_INVALID;
2767 evalresult =
2768 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2769 if (!evalresult) {
2770 free_tlist(origline);
2771 return DIRECTIVE_FOUND;
2772 }
2773 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002774 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002775 "trailing garbage after expression ignored");
2776 if (!is_simple(evalresult)) {
2777 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2778 return DIRECTIVE_FOUND;
2779 }
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002780 count = reloc_value(evalresult) + 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002781 } else {
2782 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002783 count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002784 }
2785 free_tlist(origline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002786
H. Peter Anvine2c80182005-01-15 22:15:51 +00002787 tmp_defining = defining;
2788 defining = nasm_malloc(sizeof(MMacro));
H. Peter Anvin89cee572009-07-15 09:16:54 -04002789 defining->prev = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002790 defining->name = NULL; /* flags this macro as a %rep block */
H. Peter Anvin70055962007-10-11 00:05:31 -07002791 defining->casesense = false;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002792 defining->plus = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002793 defining->nolist = nolist;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002794 defining->in_progress = count;
H. Peter Anvin89cee572009-07-15 09:16:54 -04002795 defining->max_depth = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002796 defining->nparam_min = defining->nparam_max = 0;
2797 defining->defaults = NULL;
2798 defining->dlist = NULL;
2799 defining->expansion = NULL;
2800 defining->next_active = istk->mstk;
2801 defining->rep_nest = tmp_defining;
2802 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002803
H. Peter Anvine2c80182005-01-15 22:15:51 +00002804 case PP_ENDREP:
2805 if (!defining || defining->name) {
2806 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2807 return DIRECTIVE_FOUND;
2808 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002809
H. Peter Anvine2c80182005-01-15 22:15:51 +00002810 /*
2811 * Now we have a "macro" defined - although it has no name
2812 * and we won't be entering it in the hash tables - we must
2813 * push a macro-end marker for it on to istk->expansion.
2814 * After that, it will take care of propagating itself (a
2815 * macro-end marker line for a macro which is really a %rep
2816 * block will cause the macro to be re-expanded, complete
2817 * with another macro-end marker to ensure the process
2818 * continues) until the whole expansion is forcibly removed
2819 * from istk->expansion by a %exitrep.
2820 */
2821 l = nasm_malloc(sizeof(Line));
2822 l->next = istk->expansion;
2823 l->finishes = defining;
2824 l->first = NULL;
2825 istk->expansion = l;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002826
H. Peter Anvine2c80182005-01-15 22:15:51 +00002827 istk->mstk = defining;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002828
H. Peter Anvine2c80182005-01-15 22:15:51 +00002829 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2830 tmp_defining = defining;
2831 defining = defining->rep_nest;
2832 free_tlist(origline);
2833 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002834
H. Peter Anvine2c80182005-01-15 22:15:51 +00002835 case PP_EXITREP:
2836 /*
2837 * We must search along istk->expansion until we hit a
2838 * macro-end marker for a macro with no name. Then we set
2839 * its `in_progress' flag to 0.
2840 */
2841 for (l = istk->expansion; l; l = l->next)
2842 if (l->finishes && !l->finishes->name)
H. Peter Anvinca348b62008-07-23 10:49:26 -04002843 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002844
H. Peter Anvine2c80182005-01-15 22:15:51 +00002845 if (l)
Charles Crayned4200be2008-07-12 16:42:33 -07002846 l->finishes->in_progress = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002847 else
2848 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2849 free_tlist(origline);
2850 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002851
H. Peter Anvine2c80182005-01-15 22:15:51 +00002852 case PP_XDEFINE:
2853 case PP_IXDEFINE:
2854 case PP_DEFINE:
2855 case PP_IDEFINE:
H. Peter Anvin95e7f952007-10-11 13:38:38 -07002856 casesense = (i == PP_DEFINE || i == PP_XDEFINE);
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002857
H. Peter Anvine2c80182005-01-15 22:15:51 +00002858 tline = tline->next;
2859 skip_white_(tline);
2860 tline = expand_id(tline);
2861 if (!tline || (tline->type != TOK_ID &&
2862 (tline->type != TOK_PREPROC_ID ||
2863 tline->text[1] != '$'))) {
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002864 error(ERR_NONFATAL, "`%s' expects a macro identifier",
2865 pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002866 free_tlist(origline);
2867 return DIRECTIVE_FOUND;
2868 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002869
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002870 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002871 last = tline;
2872 param_start = tline = tline->next;
2873 nparam = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002874
H. Peter Anvine2c80182005-01-15 22:15:51 +00002875 /* Expand the macro definition now for %xdefine and %ixdefine */
2876 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2877 tline = expand_smacro(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002878
H. Peter Anvine2c80182005-01-15 22:15:51 +00002879 if (tok_is_(tline, "(")) {
2880 /*
2881 * This macro has parameters.
2882 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002883
H. Peter Anvine2c80182005-01-15 22:15:51 +00002884 tline = tline->next;
2885 while (1) {
2886 skip_white_(tline);
2887 if (!tline) {
2888 error(ERR_NONFATAL, "parameter identifier expected");
2889 free_tlist(origline);
2890 return DIRECTIVE_FOUND;
2891 }
2892 if (tline->type != TOK_ID) {
2893 error(ERR_NONFATAL,
2894 "`%s': parameter identifier expected",
2895 tline->text);
2896 free_tlist(origline);
2897 return DIRECTIVE_FOUND;
2898 }
2899 tline->type = TOK_SMAC_PARAM + nparam++;
2900 tline = tline->next;
2901 skip_white_(tline);
2902 if (tok_is_(tline, ",")) {
2903 tline = tline->next;
H. Peter Anvinca348b62008-07-23 10:49:26 -04002904 } else {
2905 if (!tok_is_(tline, ")")) {
2906 error(ERR_NONFATAL,
2907 "`)' expected to terminate macro template");
2908 free_tlist(origline);
2909 return DIRECTIVE_FOUND;
2910 }
2911 break;
2912 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002913 }
2914 last = tline;
2915 tline = tline->next;
2916 }
2917 if (tok_type_(tline, TOK_WHITESPACE))
2918 last = tline, tline = tline->next;
2919 macro_start = NULL;
2920 last->next = NULL;
2921 t = tline;
2922 while (t) {
2923 if (t->type == TOK_ID) {
2924 for (tt = param_start; tt; tt = tt->next)
2925 if (tt->type >= TOK_SMAC_PARAM &&
2926 !strcmp(tt->text, t->text))
2927 t->type = tt->type;
2928 }
2929 tt = t->next;
2930 t->next = macro_start;
2931 macro_start = t;
2932 t = tt;
2933 }
2934 /*
2935 * Good. We now have a macro name, a parameter count, and a
2936 * token list (in reverse order) for an expansion. We ought
2937 * to be OK just to create an SMacro, store it, and let
2938 * free_tlist have the rest of the line (which we have
2939 * carefully re-terminated after chopping off the expansion
2940 * from the end).
2941 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002942 define_smacro(ctx, mname, casesense, nparam, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002943 free_tlist(origline);
2944 return DIRECTIVE_FOUND;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002945
H. Peter Anvine2c80182005-01-15 22:15:51 +00002946 case PP_UNDEF:
2947 tline = tline->next;
2948 skip_white_(tline);
2949 tline = expand_id(tline);
2950 if (!tline || (tline->type != TOK_ID &&
2951 (tline->type != TOK_PREPROC_ID ||
2952 tline->text[1] != '$'))) {
2953 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2954 free_tlist(origline);
2955 return DIRECTIVE_FOUND;
2956 }
2957 if (tline->next) {
H. Peter Anvin917a3492008-09-24 09:14:49 -07002958 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002959 "trailing garbage after macro name ignored");
2960 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002961
H. Peter Anvine2c80182005-01-15 22:15:51 +00002962 /* Find the context that symbol belongs to */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002963 ctx = get_ctx(tline->text, &mname, false);
2964 undef_smacro(ctx, mname);
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002965 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002966 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002967
H. Peter Anvin9e200162008-06-04 17:23:14 -07002968 case PP_DEFSTR:
2969 case PP_IDEFSTR:
2970 casesense = (i == PP_DEFSTR);
2971
2972 tline = tline->next;
2973 skip_white_(tline);
2974 tline = expand_id(tline);
2975 if (!tline || (tline->type != TOK_ID &&
2976 (tline->type != TOK_PREPROC_ID ||
2977 tline->text[1] != '$'))) {
2978 error(ERR_NONFATAL, "`%s' expects a macro identifier",
2979 pp_directives[i]);
2980 free_tlist(origline);
2981 return DIRECTIVE_FOUND;
2982 }
2983
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002984 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvin9e200162008-06-04 17:23:14 -07002985 last = tline;
2986 tline = expand_smacro(tline->next);
2987 last->next = NULL;
2988
2989 while (tok_type_(tline, TOK_WHITESPACE))
2990 tline = delete_Token(tline);
2991
2992 p = detoken(tline, false);
2993 macro_start = nasm_malloc(sizeof(*macro_start));
2994 macro_start->next = NULL;
2995 macro_start->text = nasm_quote(p, strlen(p));
2996 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07002997 macro_start->a.mac = NULL;
H. Peter Anvin9e200162008-06-04 17:23:14 -07002998 nasm_free(p);
2999
3000 /*
3001 * We now have a macro name, an implicit parameter count of
3002 * zero, and a string token to use as an expansion. Create
3003 * and store an SMacro.
3004 */
3005 define_smacro(ctx, mname, casesense, 0, macro_start);
3006 free_tlist(origline);
3007 return DIRECTIVE_FOUND;
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003008
H. Peter Anvin2f55bda2009-07-14 15:04:04 -04003009 case PP_DEFTOK:
3010 case PP_IDEFTOK:
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003011 casesense = (i == PP_DEFTOK);
H. Peter Anvin89cee572009-07-15 09:16:54 -04003012
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003013 tline = tline->next;
3014 skip_white_(tline);
3015 tline = expand_id(tline);
3016 if (!tline || (tline->type != TOK_ID &&
3017 (tline->type != TOK_PREPROC_ID ||
3018 tline->text[1] != '$'))) {
3019 error(ERR_NONFATAL,
3020 "`%s' expects a macro identifier as first parameter",
H. Peter Anvin89cee572009-07-15 09:16:54 -04003021 pp_directives[i]);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003022 free_tlist(origline);
3023 return DIRECTIVE_FOUND;
3024 }
3025 ctx = get_ctx(tline->text, &mname, false);
3026 last = tline;
3027 tline = expand_smacro(tline->next);
3028 last->next = NULL;
3029
3030 t = tline;
3031 while (tok_type_(t, TOK_WHITESPACE))
3032 t = t->next;
3033 /* t should now point to the string */
3034 if (t->type != TOK_STRING) {
3035 error(ERR_NONFATAL,
3036 "`%s` requires string as second parameter",
H. Peter Anvin89cee572009-07-15 09:16:54 -04003037 pp_directives[i]);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003038 free_tlist(tline);
3039 free_tlist(origline);
3040 return DIRECTIVE_FOUND;
3041 }
3042
H. Peter Anvinf9c9a672009-07-14 15:14:05 -04003043 nasm_unquote_cstr(t->text, i);
H. Peter Anvin2f55bda2009-07-14 15:04:04 -04003044 macro_start = tokenize(t->text);
H. Peter Anvin89cee572009-07-15 09:16:54 -04003045
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003046 /*
3047 * We now have a macro name, an implicit parameter count of
3048 * zero, and a numeric token to use as an expansion. Create
3049 * and store an SMacro.
3050 */
3051 define_smacro(ctx, mname, casesense, 0, macro_start);
3052 free_tlist(tline);
3053 free_tlist(origline);
3054 return DIRECTIVE_FOUND;
H. Peter Anvin9e200162008-06-04 17:23:14 -07003055
H. Peter Anvin418ca702008-05-30 10:42:30 -07003056 case PP_PATHSEARCH:
3057 {
3058 FILE *fp;
3059 StrList *xsl = NULL;
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07003060 StrList **xst = &xsl;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003061
3062 casesense = true;
3063
3064 tline = tline->next;
3065 skip_white_(tline);
3066 tline = expand_id(tline);
3067 if (!tline || (tline->type != TOK_ID &&
3068 (tline->type != TOK_PREPROC_ID ||
3069 tline->text[1] != '$'))) {
3070 error(ERR_NONFATAL,
3071 "`%%pathsearch' expects a macro identifier as first parameter");
3072 free_tlist(origline);
3073 return DIRECTIVE_FOUND;
3074 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003075 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003076 last = tline;
3077 tline = expand_smacro(tline->next);
3078 last->next = NULL;
3079
3080 t = tline;
3081 while (tok_type_(t, TOK_WHITESPACE))
3082 t = t->next;
3083
3084 if (!t || (t->type != TOK_STRING &&
3085 t->type != TOK_INTERNAL_STRING)) {
3086 error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
3087 free_tlist(tline);
3088 free_tlist(origline);
3089 return DIRECTIVE_FOUND; /* but we did _something_ */
3090 }
3091 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07003092 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin418ca702008-05-30 10:42:30 -07003093 "trailing garbage after `%%pathsearch' ignored");
H. Peter Anvin427cc912008-06-01 21:43:03 -07003094 p = t->text;
3095 if (t->type != TOK_INTERNAL_STRING)
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003096 nasm_unquote(p, NULL);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003097
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07003098 fp = inc_fopen(p, &xsl, &xst, true);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003099 if (fp) {
3100 p = xsl->str;
3101 fclose(fp); /* Don't actually care about the file */
3102 }
3103 macro_start = nasm_malloc(sizeof(*macro_start));
3104 macro_start->next = NULL;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003105 macro_start->text = nasm_quote(p, strlen(p));
H. Peter Anvin418ca702008-05-30 10:42:30 -07003106 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003107 macro_start->a.mac = NULL;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003108 if (xsl)
3109 nasm_free(xsl);
3110
3111 /*
3112 * We now have a macro name, an implicit parameter count of
3113 * zero, and a string token to use as an expansion. Create
3114 * and store an SMacro.
3115 */
3116 define_smacro(ctx, mname, casesense, 0, macro_start);
3117 free_tlist(tline);
3118 free_tlist(origline);
3119 return DIRECTIVE_FOUND;
3120 }
3121
H. Peter Anvine2c80182005-01-15 22:15:51 +00003122 case PP_STRLEN:
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003123 casesense = true;
H. Peter Anvin70653092007-10-19 14:42:29 -07003124
H. Peter Anvine2c80182005-01-15 22:15:51 +00003125 tline = tline->next;
3126 skip_white_(tline);
3127 tline = expand_id(tline);
3128 if (!tline || (tline->type != TOK_ID &&
3129 (tline->type != TOK_PREPROC_ID ||
3130 tline->text[1] != '$'))) {
3131 error(ERR_NONFATAL,
3132 "`%%strlen' expects a macro identifier as first parameter");
3133 free_tlist(origline);
3134 return DIRECTIVE_FOUND;
3135 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003136 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003137 last = tline;
3138 tline = expand_smacro(tline->next);
3139 last->next = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003140
H. Peter Anvine2c80182005-01-15 22:15:51 +00003141 t = tline;
3142 while (tok_type_(t, TOK_WHITESPACE))
3143 t = t->next;
3144 /* t should now point to the string */
3145 if (t->type != TOK_STRING) {
3146 error(ERR_NONFATAL,
3147 "`%%strlen` requires string as second parameter");
3148 free_tlist(tline);
3149 free_tlist(origline);
3150 return DIRECTIVE_FOUND;
3151 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003152
H. Peter Anvine2c80182005-01-15 22:15:51 +00003153 macro_start = nasm_malloc(sizeof(*macro_start));
3154 macro_start->next = NULL;
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003155 make_tok_num(macro_start, nasm_unquote(t->text, NULL));
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003156 macro_start->a.mac = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003157
H. Peter Anvine2c80182005-01-15 22:15:51 +00003158 /*
3159 * We now have a macro name, an implicit parameter count of
3160 * zero, and a numeric token to use as an expansion. Create
3161 * and store an SMacro.
3162 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003163 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003164 free_tlist(tline);
3165 free_tlist(origline);
3166 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003167
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003168 case PP_STRCAT:
3169 casesense = true;
3170
3171 tline = tline->next;
3172 skip_white_(tline);
3173 tline = expand_id(tline);
3174 if (!tline || (tline->type != TOK_ID &&
3175 (tline->type != TOK_PREPROC_ID ||
3176 tline->text[1] != '$'))) {
3177 error(ERR_NONFATAL,
3178 "`%%strcat' expects a macro identifier as first parameter");
3179 free_tlist(origline);
3180 return DIRECTIVE_FOUND;
3181 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003182 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003183 last = tline;
3184 tline = expand_smacro(tline->next);
3185 last->next = NULL;
3186
3187 len = 0;
3188 for (t = tline; t; t = t->next) {
3189 switch (t->type) {
3190 case TOK_WHITESPACE:
3191 break;
3192 case TOK_STRING:
3193 len += t->a.len = nasm_unquote(t->text, NULL);
3194 break;
H. Peter Anvinaccf4332008-07-01 21:42:08 -07003195 case TOK_OTHER:
3196 if (!strcmp(t->text, ",")) /* permit comma separators */
3197 break;
3198 /* else fall through */
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003199 default:
3200 error(ERR_NONFATAL,
3201 "non-string passed to `%%strcat' (%d)", t->type);
3202 free_tlist(tline);
3203 free_tlist(origline);
3204 return DIRECTIVE_FOUND;
3205 }
3206 }
3207
3208 p = pp = nasm_malloc(len);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003209 for (t = tline; t; t = t->next) {
3210 if (t->type == TOK_STRING) {
3211 memcpy(p, t->text, t->a.len);
3212 p += t->a.len;
3213 }
3214 }
3215
3216 /*
3217 * We now have a macro name, an implicit parameter count of
3218 * zero, and a numeric token to use as an expansion. Create
3219 * and store an SMacro.
3220 */
3221 macro_start = new_Token(NULL, TOK_STRING, NULL, 0);
3222 macro_start->text = nasm_quote(pp, len);
3223 nasm_free(pp);
3224 define_smacro(ctx, mname, casesense, 0, macro_start);
3225 free_tlist(tline);
3226 free_tlist(origline);
3227 return DIRECTIVE_FOUND;
3228
H. Peter Anvine2c80182005-01-15 22:15:51 +00003229 case PP_SUBSTR:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003230 {
3231 int64_t a1, a2;
3232 size_t len;
H. Peter Anvind2456592008-06-19 15:04:18 -07003233
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003234 casesense = true;
3235
H. Peter Anvine2c80182005-01-15 22:15:51 +00003236 tline = tline->next;
3237 skip_white_(tline);
3238 tline = expand_id(tline);
3239 if (!tline || (tline->type != TOK_ID &&
3240 (tline->type != TOK_PREPROC_ID ||
3241 tline->text[1] != '$'))) {
3242 error(ERR_NONFATAL,
3243 "`%%substr' expects a macro identifier as first parameter");
3244 free_tlist(origline);
3245 return DIRECTIVE_FOUND;
3246 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003247 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003248 last = tline;
3249 tline = expand_smacro(tline->next);
3250 last->next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003251
H. Peter Anvine2c80182005-01-15 22:15:51 +00003252 t = tline->next;
3253 while (tok_type_(t, TOK_WHITESPACE))
3254 t = t->next;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003255
H. Peter Anvine2c80182005-01-15 22:15:51 +00003256 /* t should now point to the string */
3257 if (t->type != TOK_STRING) {
3258 error(ERR_NONFATAL,
3259 "`%%substr` requires string as second parameter");
3260 free_tlist(tline);
3261 free_tlist(origline);
3262 return DIRECTIVE_FOUND;
3263 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003264
H. Peter Anvine2c80182005-01-15 22:15:51 +00003265 tt = t->next;
3266 tptr = &tt;
3267 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003268 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3269 pass, error, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003270 if (!evalresult) {
3271 free_tlist(tline);
3272 free_tlist(origline);
3273 return DIRECTIVE_FOUND;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003274 } else if (!is_simple(evalresult)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003275 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3276 free_tlist(tline);
3277 free_tlist(origline);
3278 return DIRECTIVE_FOUND;
3279 }
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003280 a1 = evalresult->value-1;
3281
3282 while (tok_type_(tt, TOK_WHITESPACE))
3283 tt = tt->next;
3284 if (!tt) {
3285 a2 = 1; /* Backwards compatibility: one character */
3286 } else {
3287 tokval.t_type = TOKEN_INVALID;
3288 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3289 pass, error, NULL);
3290 if (!evalresult) {
3291 free_tlist(tline);
3292 free_tlist(origline);
3293 return DIRECTIVE_FOUND;
3294 } else if (!is_simple(evalresult)) {
3295 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3296 free_tlist(tline);
3297 free_tlist(origline);
3298 return DIRECTIVE_FOUND;
3299 }
3300 a2 = evalresult->value;
3301 }
3302
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003303 len = nasm_unquote(t->text, NULL);
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003304 if (a2 < 0)
3305 a2 = a2+1+len-a1;
3306 if (a1+a2 > (int64_t)len)
3307 a2 = len-a1;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003308
H. Peter Anvine2c80182005-01-15 22:15:51 +00003309 macro_start = nasm_malloc(sizeof(*macro_start));
3310 macro_start->next = NULL;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003311 macro_start->text = nasm_quote((a1 < 0) ? "" : t->text+a1, a2);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003312 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003313 macro_start->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003314
H. Peter Anvine2c80182005-01-15 22:15:51 +00003315 /*
3316 * We now have a macro name, an implicit parameter count of
3317 * zero, and a numeric token to use as an expansion. Create
3318 * and store an SMacro.
3319 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003320 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003321 free_tlist(tline);
3322 free_tlist(origline);
3323 return DIRECTIVE_FOUND;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003324 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003325
H. Peter Anvine2c80182005-01-15 22:15:51 +00003326 case PP_ASSIGN:
3327 case PP_IASSIGN:
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003328 casesense = (i == PP_ASSIGN);
3329
H. Peter Anvine2c80182005-01-15 22:15:51 +00003330 tline = tline->next;
3331 skip_white_(tline);
3332 tline = expand_id(tline);
3333 if (!tline || (tline->type != TOK_ID &&
3334 (tline->type != TOK_PREPROC_ID ||
3335 tline->text[1] != '$'))) {
3336 error(ERR_NONFATAL,
3337 "`%%%sassign' expects a macro identifier",
3338 (i == PP_IASSIGN ? "i" : ""));
3339 free_tlist(origline);
3340 return DIRECTIVE_FOUND;
3341 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003342 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003343 last = tline;
3344 tline = expand_smacro(tline->next);
3345 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003346
H. Peter Anvine2c80182005-01-15 22:15:51 +00003347 t = tline;
3348 tptr = &t;
3349 tokval.t_type = TOKEN_INVALID;
3350 evalresult =
3351 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3352 free_tlist(tline);
3353 if (!evalresult) {
3354 free_tlist(origline);
3355 return DIRECTIVE_FOUND;
3356 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003357
H. Peter Anvine2c80182005-01-15 22:15:51 +00003358 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07003359 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003360 "trailing garbage after expression ignored");
H. Peter Anvin734b1882002-04-30 21:01:08 +00003361
H. Peter Anvine2c80182005-01-15 22:15:51 +00003362 if (!is_simple(evalresult)) {
3363 error(ERR_NONFATAL,
3364 "non-constant value given to `%%%sassign'",
3365 (i == PP_IASSIGN ? "i" : ""));
3366 free_tlist(origline);
3367 return DIRECTIVE_FOUND;
3368 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003369
H. Peter Anvine2c80182005-01-15 22:15:51 +00003370 macro_start = nasm_malloc(sizeof(*macro_start));
3371 macro_start->next = NULL;
3372 make_tok_num(macro_start, reloc_value(evalresult));
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003373 macro_start->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003374
H. Peter Anvine2c80182005-01-15 22:15:51 +00003375 /*
3376 * We now have a macro name, an implicit parameter count of
3377 * zero, and a numeric token to use as an expansion. Create
3378 * and store an SMacro.
3379 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003380 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003381 free_tlist(origline);
3382 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003383
H. Peter Anvine2c80182005-01-15 22:15:51 +00003384 case PP_LINE:
3385 /*
3386 * Syntax is `%line nnn[+mmm] [filename]'
3387 */
3388 tline = tline->next;
3389 skip_white_(tline);
3390 if (!tok_type_(tline, TOK_NUMBER)) {
3391 error(ERR_NONFATAL, "`%%line' expects line number");
3392 free_tlist(origline);
3393 return DIRECTIVE_FOUND;
3394 }
H. Peter Anvin70055962007-10-11 00:05:31 -07003395 k = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003396 m = 1;
3397 tline = tline->next;
3398 if (tok_is_(tline, "+")) {
3399 tline = tline->next;
3400 if (!tok_type_(tline, TOK_NUMBER)) {
3401 error(ERR_NONFATAL, "`%%line' expects line increment");
3402 free_tlist(origline);
3403 return DIRECTIVE_FOUND;
3404 }
H. Peter Anvin70055962007-10-11 00:05:31 -07003405 m = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003406 tline = tline->next;
3407 }
3408 skip_white_(tline);
3409 src_set_linnum(k);
3410 istk->lineinc = m;
3411 if (tline) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003412 nasm_free(src_set_fname(detoken(tline, false)));
H. Peter Anvine2c80182005-01-15 22:15:51 +00003413 }
3414 free_tlist(origline);
3415 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003416
H. Peter Anvine2c80182005-01-15 22:15:51 +00003417 default:
3418 error(ERR_FATAL,
3419 "preprocessor directive `%s' not yet implemented",
H. Peter Anvin4169a472007-09-12 01:29:43 +00003420 pp_directives[i]);
H. Peter Anvina26433d2008-07-16 14:40:01 -07003421 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003422 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003423}
3424
3425/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00003426 * Ensure that a macro parameter contains a condition code and
3427 * nothing else. Return the condition code index if so, or -1
3428 * otherwise.
3429 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003430static int find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003431{
H. Peter Anvin76690a12002-04-30 20:52:49 +00003432 Token *tt;
3433 int i, j, k, m;
3434
H. Peter Anvin25a99342007-09-22 17:45:45 -07003435 if (!t)
H. Peter Anvin89cee572009-07-15 09:16:54 -04003436 return -1; /* Probably a %+ without a space */
H. Peter Anvin25a99342007-09-22 17:45:45 -07003437
H. Peter Anvineba20a72002-04-30 20:53:55 +00003438 skip_white_(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003439 if (t->type != TOK_ID)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003440 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003441 tt = t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003442 skip_white_(tt);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003443 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003444 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003445
3446 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +00003447 j = elements(conditions);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003448 while (j - i > 1) {
3449 k = (j + i) / 2;
3450 m = nasm_stricmp(t->text, conditions[k]);
3451 if (m == 0) {
3452 i = k;
3453 j = -2;
3454 break;
3455 } else if (m < 0) {
3456 j = k;
3457 } else
3458 i = k;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003459 }
3460 if (j != -2)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003461 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003462 return i;
3463}
3464
H. Peter Anvind784a082009-04-20 14:01:18 -07003465static bool paste_tokens(Token **head, bool handle_paste_tokens)
3466{
3467 Token **tail, *t, *tt;
3468 Token **paste_head;
3469 bool did_paste = false;
3470 char *tmp;
3471
3472 /* Now handle token pasting... */
3473 paste_head = NULL;
3474 tail = head;
3475 while ((t = *tail) && (tt = t->next)) {
3476 switch (t->type) {
3477 case TOK_WHITESPACE:
3478 if (tt->type == TOK_WHITESPACE) {
3479 /* Zap adjacent whitespace tokens */
3480 t->next = delete_Token(tt);
3481 } else {
3482 /* Do not advance paste_head here */
3483 tail = &t->next;
3484 }
3485 break;
3486 case TOK_ID:
3487 case TOK_PREPROC_ID:
3488 case TOK_NUMBER:
3489 case TOK_FLOAT:
3490 {
3491 size_t len = 0;
3492 char *tmp, *p;
3493
3494 while (tt && (tt->type == TOK_ID || tt->type == TOK_PREPROC_ID ||
3495 tt->type == TOK_NUMBER || tt->type == TOK_FLOAT ||
3496 tt->type == TOK_OTHER)) {
3497 len += strlen(tt->text);
3498 tt = tt->next;
3499 }
3500
3501 /* Now tt points to the first token after the potential
3502 paste area... */
3503 if (tt != t->next) {
3504 /* We have at least two tokens... */
3505 len += strlen(t->text);
3506 p = tmp = nasm_malloc(len+1);
3507
3508 while (t != tt) {
3509 strcpy(p, t->text);
3510 p = strchr(p, '\0');
3511 t = delete_Token(t);
3512 }
3513
3514 t = *tail = tokenize(tmp);
3515 nasm_free(tmp);
3516
3517 while (t->next) {
3518 tail = &t->next;
3519 t = t->next;
3520 }
3521 t->next = tt; /* Attach the remaining token chain */
3522
3523 did_paste = true;
3524 }
3525 paste_head = tail;
3526 tail = &t->next;
3527 break;
3528 }
3529 case TOK_PASTE: /* %+ */
3530 if (handle_paste_tokens) {
3531 /* Zap %+ and whitespace tokens to the right */
3532 while (t && (t->type == TOK_WHITESPACE ||
3533 t->type == TOK_PASTE))
3534 t = *tail = delete_Token(t);
3535 if (!paste_head || !t)
3536 break; /* Nothing to paste with */
3537 tail = paste_head;
3538 t = *tail;
3539 tt = t->next;
3540 while (tok_type_(tt, TOK_WHITESPACE))
3541 tt = t->next = delete_Token(tt);
3542
3543 if (tt) {
3544 tmp = nasm_strcat(t->text, tt->text);
3545 delete_Token(t);
3546 tt = delete_Token(tt);
3547 t = *tail = tokenize(tmp);
3548 nasm_free(tmp);
3549 while (t->next) {
3550 tail = &t->next;
3551 t = t->next;
3552 }
3553 t->next = tt; /* Attach the remaining token chain */
3554 did_paste = true;
3555 }
3556 paste_head = tail;
3557 tail = &t->next;
3558 break;
3559 }
3560 /* else fall through */
3561 default:
3562 tail = paste_head = &t->next;
3563 break;
3564 }
3565 }
3566 return did_paste;
3567}
H. Peter Anvin76690a12002-04-30 20:52:49 +00003568/*
3569 * Expand MMacro-local things: parameter references (%0, %n, %+n,
H. Peter Anvin67c63722008-10-26 23:49:00 -07003570 * %-n) and MMacro-local identifiers (%%foo) as well as
3571 * macro indirection (%[...]).
H. Peter Anvin76690a12002-04-30 20:52:49 +00003572 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003573static Token *expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003574{
H. Peter Anvin734b1882002-04-30 21:01:08 +00003575 Token *t, *tt, **tail, *thead;
H. Peter Anvin6125b622009-04-08 14:02:25 -07003576 bool changed = false;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003577
3578 tail = &thead;
3579 thead = NULL;
3580
H. Peter Anvine2c80182005-01-15 22:15:51 +00003581 while (tline) {
3582 if (tline->type == TOK_PREPROC_ID &&
3583 (((tline->text[1] == '+' || tline->text[1] == '-')
3584 && tline->text[2]) || tline->text[1] == '%'
3585 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003586 char *text = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003587 int type = 0, cc; /* type = 0 to placate optimisers */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003588 char tmpbuf[30];
H. Peter Anvin25a99342007-09-22 17:45:45 -07003589 unsigned int n;
3590 int i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003591 MMacro *mac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003592
H. Peter Anvine2c80182005-01-15 22:15:51 +00003593 t = tline;
3594 tline = tline->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003595
H. Peter Anvine2c80182005-01-15 22:15:51 +00003596 mac = istk->mstk;
3597 while (mac && !mac->name) /* avoid mistaking %reps for macros */
3598 mac = mac->next_active;
3599 if (!mac)
3600 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
3601 else
3602 switch (t->text[1]) {
3603 /*
3604 * We have to make a substitution of one of the
3605 * forms %1, %-1, %+1, %%foo, %0.
3606 */
3607 case '0':
3608 type = TOK_NUMBER;
3609 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
3610 text = nasm_strdup(tmpbuf);
3611 break;
3612 case '%':
3613 type = TOK_ID;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07003614 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
H. Peter Anvine2c80182005-01-15 22:15:51 +00003615 mac->unique);
3616 text = nasm_strcat(tmpbuf, t->text + 2);
3617 break;
3618 case '-':
3619 n = atoi(t->text + 2) - 1;
3620 if (n >= mac->nparam)
3621 tt = NULL;
3622 else {
3623 if (mac->nparam > 1)
3624 n = (n + mac->rotate) % mac->nparam;
3625 tt = mac->params[n];
3626 }
3627 cc = find_cc(tt);
3628 if (cc == -1) {
3629 error(ERR_NONFATAL,
3630 "macro parameter %d is not a condition code",
3631 n + 1);
3632 text = NULL;
3633 } else {
3634 type = TOK_ID;
3635 if (inverse_ccs[cc] == -1) {
3636 error(ERR_NONFATAL,
3637 "condition code `%s' is not invertible",
3638 conditions[cc]);
3639 text = NULL;
3640 } else
H. Peter Anvin67c63722008-10-26 23:49:00 -07003641 text = nasm_strdup(conditions[inverse_ccs[cc]]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003642 }
3643 break;
3644 case '+':
3645 n = atoi(t->text + 2) - 1;
3646 if (n >= mac->nparam)
3647 tt = NULL;
3648 else {
3649 if (mac->nparam > 1)
3650 n = (n + mac->rotate) % mac->nparam;
3651 tt = mac->params[n];
3652 }
3653 cc = find_cc(tt);
3654 if (cc == -1) {
3655 error(ERR_NONFATAL,
3656 "macro parameter %d is not a condition code",
3657 n + 1);
3658 text = NULL;
3659 } else {
3660 type = TOK_ID;
3661 text = nasm_strdup(conditions[cc]);
3662 }
3663 break;
3664 default:
3665 n = atoi(t->text + 1) - 1;
3666 if (n >= mac->nparam)
3667 tt = NULL;
3668 else {
3669 if (mac->nparam > 1)
3670 n = (n + mac->rotate) % mac->nparam;
3671 tt = mac->params[n];
3672 }
3673 if (tt) {
3674 for (i = 0; i < mac->paramlen[n]; i++) {
3675 *tail = new_Token(NULL, tt->type, tt->text, 0);
3676 tail = &(*tail)->next;
3677 tt = tt->next;
3678 }
3679 }
3680 text = NULL; /* we've done it here */
3681 break;
3682 }
3683 if (!text) {
3684 delete_Token(t);
3685 } else {
3686 *tail = t;
3687 tail = &t->next;
3688 t->type = type;
3689 nasm_free(t->text);
3690 t->text = text;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003691 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003692 }
H. Peter Anvin6125b622009-04-08 14:02:25 -07003693 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003694 continue;
H. Peter Anvin67c63722008-10-26 23:49:00 -07003695 } else if (tline->type == TOK_INDIRECT) {
3696 t = tline;
3697 tline = tline->next;
3698 tt = tokenize(t->text);
3699 tt = expand_mmac_params(tt);
3700 tt = expand_smacro(tt);
3701 *tail = tt;
3702 while (tt) {
3703 tt->a.mac = NULL; /* Necessary? */
3704 tail = &tt->next;
3705 tt = tt->next;
3706 }
3707 delete_Token(t);
H. Peter Anvin6125b622009-04-08 14:02:25 -07003708 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003709 } else {
3710 t = *tail = tline;
3711 tline = tline->next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003712 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003713 tail = &t->next;
3714 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003715 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00003716 *tail = NULL;
H. Peter Anvin67c63722008-10-26 23:49:00 -07003717
H. Peter Anvind784a082009-04-20 14:01:18 -07003718 if (changed)
H. Peter Anvinfc30f8c2009-07-06 18:48:23 -07003719 paste_tokens(&thead, false);
H. Peter Anvin6125b622009-04-08 14:02:25 -07003720
H. Peter Anvin76690a12002-04-30 20:52:49 +00003721 return thead;
3722}
3723
3724/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003725 * Expand all single-line macro calls made in the given line.
3726 * Return the expanded version of the line. The original is deemed
3727 * to be destroyed in the process. (In reality we'll just move
3728 * Tokens from input to output a lot of the time, rather than
3729 * actually bothering to destroy and replicate.)
3730 */
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003731
H. Peter Anvine2c80182005-01-15 22:15:51 +00003732static Token *expand_smacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003733{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003734 Token *t, *tt, *mstart, **tail, *thead;
H. Peter Anvin166c2472008-05-28 12:28:58 -07003735 struct hash_table *smtbl;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003736 SMacro *head = NULL, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003737 Token **params;
3738 int *paramsize;
H. Peter Anvin25a99342007-09-22 17:45:45 -07003739 unsigned int nparam, sparam;
H. Peter Anvind784a082009-04-20 14:01:18 -07003740 int brackets;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003741 Token *org_tline = tline;
3742 Context *ctx;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003743 const char *mname;
H. Peter Anvin2a15e692007-11-19 13:14:59 -08003744 int deadman = DEADMAN_LIMIT;
H. Peter Anvin8287daf2009-07-07 16:00:58 -07003745 bool expanded;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003746
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003747 /*
3748 * Trick: we should avoid changing the start token pointer since it can
3749 * be contained in "next" field of other token. Because of this
3750 * we allocate a copy of first token and work with it; at the end of
3751 * routine we copy it back
3752 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003753 if (org_tline) {
3754 tline =
3755 new_Token(org_tline->next, org_tline->type, org_tline->text,
3756 0);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003757 tline->a.mac = org_tline->a.mac;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003758 nasm_free(org_tline->text);
3759 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003760 }
3761
H. Peter Anvin8287daf2009-07-07 16:00:58 -07003762 expanded = true; /* Always expand %+ at least once */
3763
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003764again:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003765 tail = &thead;
3766 thead = NULL;
3767
H. Peter Anvine2c80182005-01-15 22:15:51 +00003768 while (tline) { /* main token loop */
H. Peter Anvin2a15e692007-11-19 13:14:59 -08003769 if (!--deadman) {
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003770 error(ERR_NONFATAL, "interminable macro recursion");
3771 break;
3772 }
3773
H. Peter Anvine2c80182005-01-15 22:15:51 +00003774 if ((mname = tline->text)) {
3775 /* if this token is a local macro, look in local context */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003776 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
3777 ctx = get_ctx(mname, &mname, true);
3778 else
3779 ctx = NULL;
3780 smtbl = ctx ? &ctx->localmac : &smacros;
H. Peter Anvin166c2472008-05-28 12:28:58 -07003781 head = (SMacro *) hash_findix(smtbl, mname);
H. Peter Anvin072771e2008-05-22 13:17:51 -07003782
H. Peter Anvine2c80182005-01-15 22:15:51 +00003783 /*
3784 * We've hit an identifier. As in is_mmacro below, we first
3785 * check whether the identifier is a single-line macro at
3786 * all, then think about checking for parameters if
3787 * necessary.
3788 */
H. Peter Anvin97a23472007-09-16 17:57:25 -07003789 for (m = head; m; m = m->next)
3790 if (!mstrcmp(m->name, mname, m->casesense))
3791 break;
3792 if (m) {
3793 mstart = tline;
3794 params = NULL;
3795 paramsize = NULL;
3796 if (m->nparam == 0) {
3797 /*
3798 * Simple case: the macro is parameterless. Discard the
3799 * one token that the macro call took, and push the
3800 * expansion back on the to-do stack.
3801 */
3802 if (!m->expansion) {
3803 if (!strcmp("__FILE__", m->name)) {
3804 int32_t num = 0;
H. Peter Anvin932de6c2008-07-31 18:46:11 -07003805 char *file = NULL;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003806 src_get(&num, &file);
3807 tline->text = nasm_quote(file, strlen(file));
H. Peter Anvin97a23472007-09-16 17:57:25 -07003808 tline->type = TOK_STRING;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003809 nasm_free(file);
H. Peter Anvin97a23472007-09-16 17:57:25 -07003810 continue;
3811 }
3812 if (!strcmp("__LINE__", m->name)) {
3813 nasm_free(tline->text);
3814 make_tok_num(tline, src_get_linnum());
3815 continue;
3816 }
3817 if (!strcmp("__BITS__", m->name)) {
3818 nasm_free(tline->text);
3819 make_tok_num(tline, globalbits);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003820 continue;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003821 }
3822 tline = delete_Token(tline);
3823 continue;
3824 }
3825 } else {
3826 /*
3827 * Complicated case: at least one macro with this name
H. Peter Anvine2c80182005-01-15 22:15:51 +00003828 * exists and takes parameters. We must find the
3829 * parameters in the call, count them, find the SMacro
3830 * that corresponds to that form of the macro call, and
3831 * substitute for the parameters when we expand. What a
3832 * pain.
3833 */
3834 /*tline = tline->next;
H. Peter Anvin89cee572009-07-15 09:16:54 -04003835 skip_white_(tline); */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003836 do {
3837 t = tline->next;
3838 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003839 t->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003840 t->text = NULL;
3841 t = tline->next = delete_Token(t);
3842 }
3843 tline = t;
3844 } while (tok_type_(tline, TOK_WHITESPACE));
3845 if (!tok_is_(tline, "(")) {
3846 /*
3847 * This macro wasn't called with parameters: ignore
3848 * the call. (Behaviour borrowed from gnu cpp.)
3849 */
3850 tline = mstart;
3851 m = NULL;
3852 } else {
3853 int paren = 0;
3854 int white = 0;
3855 brackets = 0;
3856 nparam = 0;
3857 sparam = PARAM_DELTA;
3858 params = nasm_malloc(sparam * sizeof(Token *));
3859 params[0] = tline->next;
3860 paramsize = nasm_malloc(sparam * sizeof(int));
3861 paramsize[0] = 0;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003862 while (true) { /* parameter loop */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003863 /*
3864 * For some unusual expansions
3865 * which concatenates function call
3866 */
3867 t = tline->next;
3868 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003869 t->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003870 t->text = NULL;
3871 t = tline->next = delete_Token(t);
3872 }
3873 tline = t;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003874
H. Peter Anvine2c80182005-01-15 22:15:51 +00003875 if (!tline) {
3876 error(ERR_NONFATAL,
3877 "macro call expects terminating `)'");
3878 break;
3879 }
3880 if (tline->type == TOK_WHITESPACE
3881 && brackets <= 0) {
3882 if (paramsize[nparam])
3883 white++;
3884 else
3885 params[nparam] = tline->next;
3886 continue; /* parameter loop */
3887 }
3888 if (tline->type == TOK_OTHER
3889 && tline->text[1] == 0) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003890 char ch = tline->text[0];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003891 if (ch == ',' && !paren && brackets <= 0) {
3892 if (++nparam >= sparam) {
3893 sparam += PARAM_DELTA;
3894 params = nasm_realloc(params,
3895 sparam *
3896 sizeof(Token
3897 *));
3898 paramsize =
3899 nasm_realloc(paramsize,
3900 sparam *
3901 sizeof(int));
3902 }
3903 params[nparam] = tline->next;
3904 paramsize[nparam] = 0;
3905 white = 0;
3906 continue; /* parameter loop */
3907 }
3908 if (ch == '{' &&
3909 (brackets > 0 || (brackets == 0 &&
3910 !paramsize[nparam])))
3911 {
3912 if (!(brackets++)) {
3913 params[nparam] = tline->next;
3914 continue; /* parameter loop */
3915 }
3916 }
3917 if (ch == '}' && brackets > 0)
3918 if (--brackets == 0) {
3919 brackets = -1;
3920 continue; /* parameter loop */
3921 }
3922 if (ch == '(' && !brackets)
3923 paren++;
3924 if (ch == ')' && brackets <= 0)
3925 if (--paren < 0)
3926 break;
3927 }
3928 if (brackets < 0) {
3929 brackets = 0;
3930 error(ERR_NONFATAL, "braces do not "
3931 "enclose all of macro parameter");
3932 }
3933 paramsize[nparam] += white + 1;
3934 white = 0;
3935 } /* parameter loop */
3936 nparam++;
3937 while (m && (m->nparam != nparam ||
3938 mstrcmp(m->name, mname,
3939 m->casesense)))
3940 m = m->next;
3941 if (!m)
H. Peter Anvin917a3492008-09-24 09:14:49 -07003942 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003943 "macro `%s' exists, "
3944 "but not taking %d parameters",
3945 mstart->text, nparam);
3946 }
3947 }
3948 if (m && m->in_progress)
3949 m = NULL;
3950 if (!m) { /* in progess or didn't find '(' or wrong nparam */
H. Peter Anvin70653092007-10-19 14:42:29 -07003951 /*
H. Peter Anvine2c80182005-01-15 22:15:51 +00003952 * Design question: should we handle !tline, which
3953 * indicates missing ')' here, or expand those
3954 * macros anyway, which requires the (t) test a few
H. Peter Anvin70653092007-10-19 14:42:29 -07003955 * lines down?
H. Peter Anvine2c80182005-01-15 22:15:51 +00003956 */
3957 nasm_free(params);
3958 nasm_free(paramsize);
3959 tline = mstart;
3960 } else {
3961 /*
3962 * Expand the macro: we are placed on the last token of the
3963 * call, so that we can easily split the call from the
3964 * following tokens. We also start by pushing an SMAC_END
3965 * token for the cycle removal.
3966 */
3967 t = tline;
3968 if (t) {
3969 tline = t->next;
3970 t->next = NULL;
3971 }
3972 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003973 tt->a.mac = m;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003974 m->in_progress = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003975 tline = tt;
3976 for (t = m->expansion; t; t = t->next) {
3977 if (t->type >= TOK_SMAC_PARAM) {
3978 Token *pcopy = tline, **ptail = &pcopy;
3979 Token *ttt, *pt;
3980 int i;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003981
H. Peter Anvine2c80182005-01-15 22:15:51 +00003982 ttt = params[t->type - TOK_SMAC_PARAM];
3983 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3984 --i >= 0;) {
3985 pt = *ptail =
3986 new_Token(tline, ttt->type, ttt->text,
3987 0);
3988 ptail = &pt->next;
3989 ttt = ttt->next;
3990 }
3991 tline = pcopy;
H. Peter Anvin6c81f0a2008-05-25 21:46:17 -07003992 } else if (t->type == TOK_PREPROC_Q) {
3993 tt = new_Token(tline, TOK_ID, mname, 0);
3994 tline = tt;
3995 } else if (t->type == TOK_PREPROC_QQ) {
3996 tt = new_Token(tline, TOK_ID, m->name, 0);
3997 tline = tt;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003998 } else {
3999 tt = new_Token(tline, t->type, t->text, 0);
4000 tline = tt;
4001 }
4002 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004003
H. Peter Anvine2c80182005-01-15 22:15:51 +00004004 /*
4005 * Having done that, get rid of the macro call, and clean
4006 * up the parameters.
4007 */
4008 nasm_free(params);
4009 nasm_free(paramsize);
4010 free_tlist(mstart);
H. Peter Anvind784a082009-04-20 14:01:18 -07004011 expanded = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004012 continue; /* main token loop */
4013 }
4014 }
4015 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004016
H. Peter Anvine2c80182005-01-15 22:15:51 +00004017 if (tline->type == TOK_SMAC_END) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004018 tline->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004019 tline = delete_Token(tline);
4020 } else {
4021 t = *tail = tline;
4022 tline = tline->next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004023 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004024 t->next = NULL;
4025 tail = &t->next;
4026 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004027 }
4028
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004029 /*
4030 * Now scan the entire line and look for successive TOK_IDs that resulted
Keith Kaniosb7a89542007-04-12 02:40:54 +00004031 * after expansion (they can't be produced by tokenize()). The successive
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004032 * TOK_IDs should be concatenated.
4033 * Also we look for %+ tokens and concatenate the tokens before and after
4034 * them (without white spaces in between).
4035 */
H. Peter Anvin8287daf2009-07-07 16:00:58 -07004036 if (expanded && paste_tokens(&thead, true)) {
H. Peter Anvinfc30f8c2009-07-06 18:48:23 -07004037 /*
4038 * If we concatenated something, *and* we had previously expanded
4039 * an actual macro, scan the lines again for macros...
4040 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004041 tline = thead;
H. Peter Anvin8287daf2009-07-07 16:00:58 -07004042 expanded = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004043 goto again;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004044 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004045
H. Peter Anvine2c80182005-01-15 22:15:51 +00004046 if (org_tline) {
4047 if (thead) {
4048 *org_tline = *thead;
4049 /* since we just gave text to org_line, don't free it */
4050 thead->text = NULL;
4051 delete_Token(thead);
4052 } else {
4053 /* the expression expanded to empty line;
4054 we can't return NULL for some reasons
4055 we just set the line to a single WHITESPACE token. */
4056 memset(org_tline, 0, sizeof(*org_tline));
4057 org_tline->text = NULL;
4058 org_tline->type = TOK_WHITESPACE;
4059 }
4060 thead = org_tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004061 }
4062
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004063 return thead;
4064}
4065
4066/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004067 * Similar to expand_smacro but used exclusively with macro identifiers
4068 * right before they are fetched in. The reason is that there can be
4069 * identifiers consisting of several subparts. We consider that if there
4070 * are more than one element forming the name, user wants a expansion,
4071 * otherwise it will be left as-is. Example:
4072 *
4073 * %define %$abc cde
4074 *
4075 * the identifier %$abc will be left as-is so that the handler for %define
4076 * will suck it and define the corresponding value. Other case:
4077 *
4078 * %define _%$abc cde
4079 *
4080 * In this case user wants name to be expanded *before* %define starts
4081 * working, so we'll expand %$abc into something (if it has a value;
4082 * otherwise it will be left as-is) then concatenate all successive
4083 * PP_IDs into one.
4084 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004085static Token *expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004086{
4087 Token *cur, *oldnext = NULL;
4088
H. Peter Anvin734b1882002-04-30 21:01:08 +00004089 if (!tline || !tline->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004090 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004091
4092 cur = tline;
4093 while (cur->next &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00004094 (cur->next->type == TOK_ID ||
4095 cur->next->type == TOK_PREPROC_ID
4096 || cur->next->type == TOK_NUMBER))
4097 cur = cur->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004098
4099 /* If identifier consists of just one token, don't expand */
4100 if (cur == tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004101 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004102
H. Peter Anvine2c80182005-01-15 22:15:51 +00004103 if (cur) {
4104 oldnext = cur->next; /* Detach the tail past identifier */
4105 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004106 }
4107
H. Peter Anvin734b1882002-04-30 21:01:08 +00004108 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004109
H. Peter Anvine2c80182005-01-15 22:15:51 +00004110 if (cur) {
4111 /* expand_smacro possibly changhed tline; re-scan for EOL */
4112 cur = tline;
4113 while (cur && cur->next)
4114 cur = cur->next;
4115 if (cur)
4116 cur->next = oldnext;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004117 }
4118
4119 return tline;
4120}
4121
4122/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004123 * Determine whether the given line constitutes a multi-line macro
4124 * call, and return the MMacro structure called if so. Doesn't have
4125 * to check for an initial label - that's taken care of in
4126 * expand_mmacro - but must check numbers of parameters. Guaranteed
4127 * to be called with tline->type == TOK_ID, so the putative macro
4128 * name is easy to find.
4129 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004130static MMacro *is_mmacro(Token * tline, Token *** params_array)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004131{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004132 MMacro *head, *m;
4133 Token **params;
4134 int nparam;
4135
H. Peter Anvin166c2472008-05-28 12:28:58 -07004136 head = (MMacro *) hash_findix(&mmacros, tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004137
4138 /*
4139 * Efficiency: first we see if any macro exists with the given
4140 * name. If not, we can return NULL immediately. _Then_ we
4141 * count the parameters, and then we look further along the
4142 * list if necessary to find the proper MMacro.
4143 */
4144 for (m = head; m; m = m->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004145 if (!mstrcmp(m->name, tline->text, m->casesense))
4146 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004147 if (!m)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004148 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004149
4150 /*
4151 * OK, we have a potential macro. Count and demarcate the
4152 * parameters.
4153 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00004154 count_mmac_params(tline->next, &nparam, &params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004155
4156 /*
4157 * So we know how many parameters we've got. Find the MMacro
4158 * structure that handles this number.
4159 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004160 while (m) {
4161 if (m->nparam_min <= nparam
4162 && (m->plus || nparam <= m->nparam_max)) {
4163 /*
4164 * This one is right. Just check if cycle removal
4165 * prohibits us using it before we actually celebrate...
4166 */
H. Peter Anvin89cee572009-07-15 09:16:54 -04004167 if (m->in_progress > m->max_depth) {
4168 if (m->max_depth > 0) {
4169 error(ERR_WARNING,
4170 "reached maximum recursion depth of %i",
4171 m->max_depth);
4172 }
4173 nasm_free(params);
4174 return NULL;
4175 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004176 /*
4177 * It's right, and we can use it. Add its default
4178 * parameters to the end of our list if necessary.
4179 */
4180 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
4181 params =
4182 nasm_realloc(params,
4183 ((m->nparam_min + m->ndefs +
4184 1) * sizeof(*params)));
4185 while (nparam < m->nparam_min + m->ndefs) {
4186 params[nparam] = m->defaults[nparam - m->nparam_min];
4187 nparam++;
4188 }
4189 }
4190 /*
4191 * If we've gone over the maximum parameter count (and
4192 * we're in Plus mode), ignore parameters beyond
4193 * nparam_max.
4194 */
4195 if (m->plus && nparam > m->nparam_max)
4196 nparam = m->nparam_max;
4197 /*
4198 * Then terminate the parameter list, and leave.
4199 */
4200 if (!params) { /* need this special case */
4201 params = nasm_malloc(sizeof(*params));
4202 nparam = 0;
4203 }
4204 params[nparam] = NULL;
4205 *params_array = params;
4206 return m;
4207 }
4208 /*
4209 * This one wasn't right: look for the next one with the
4210 * same name.
4211 */
4212 for (m = m->next; m; m = m->next)
4213 if (!mstrcmp(m->name, tline->text, m->casesense))
4214 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004215 }
4216
4217 /*
4218 * After all that, we didn't find one with the right number of
4219 * parameters. Issue a warning, and fail to expand the macro.
4220 */
H. Peter Anvin917a3492008-09-24 09:14:49 -07004221 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00004222 "macro `%s' exists, but not taking %d parameters",
4223 tline->text, nparam);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004224 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004225 return NULL;
4226}
4227
Keith Kanios891775e2009-07-11 06:08:54 -05004228
4229/*
4230 * Save MMacro invocation specific fields in
4231 * preparation for a recursive macro expansion
4232 */
4233static void push_mmacro(MMacro *m)
4234{
4235 MMacroInvocation *i;
4236
H. Peter Anvin89cee572009-07-15 09:16:54 -04004237 i = nasm_malloc(sizeof(MMacroInvocation));
4238 i->prev = m->prev;
4239 i->params = m->params;
4240 i->iline = m->iline;
4241 i->nparam = m->nparam;
4242 i->rotate = m->rotate;
4243 i->paramlen = m->paramlen;
4244 i->unique = m->unique;
4245 m->prev = i;
Keith Kanios891775e2009-07-11 06:08:54 -05004246}
4247
4248
4249/*
4250 * Restore MMacro invocation specific fields that were
4251 * saved during a previous recursive macro expansion
4252 */
4253static void pop_mmacro(MMacro *m)
4254{
4255 MMacroInvocation *i;
4256
H. Peter Anvin89cee572009-07-15 09:16:54 -04004257 if (m->prev) {
4258 i = m->prev;
4259 m->prev = i->prev;
4260 m->params = i->params;
4261 m->iline = i->iline;
4262 m->nparam = i->nparam;
4263 m->rotate = i->rotate;
4264 m->paramlen = i->paramlen;
4265 m->unique = i->unique;
4266 nasm_free(i);
4267 }
Keith Kanios891775e2009-07-11 06:08:54 -05004268}
4269
4270
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004271/*
4272 * Expand the multi-line macro call made by the given line, if
4273 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvineba20a72002-04-30 20:53:55 +00004274 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004275 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004276static int expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004277{
4278 Token *startline = tline;
4279 Token *label = NULL;
4280 int dont_prepend = 0;
H. Peter Anvince2233b2008-05-25 21:57:00 -07004281 Token **params, *t, *mtok, *tt;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004282 MMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004283 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004284 int i, nparam, *paramlen;
H. Peter Anvinc751e862008-06-09 10:18:45 -07004285 const char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004286
4287 t = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004288 skip_white_(t);
H. Peter Anvince2233b2008-05-25 21:57:00 -07004289 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00004290 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004291 return 0;
H. Peter Anvince2233b2008-05-25 21:57:00 -07004292 mtok = t;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004293 m = is_mmacro(t, &params);
H. Peter Anvinc751e862008-06-09 10:18:45 -07004294 if (m) {
4295 mname = t->text;
4296 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004297 Token *last;
4298 /*
4299 * We have an id which isn't a macro call. We'll assume
4300 * it might be a label; we'll also check to see if a
4301 * colon follows it. Then, if there's another id after
4302 * that lot, we'll check it again for macro-hood.
4303 */
4304 label = last = t;
4305 t = t->next;
4306 if (tok_type_(t, TOK_WHITESPACE))
4307 last = t, t = t->next;
4308 if (tok_is_(t, ":")) {
4309 dont_prepend = 1;
4310 last = t, t = t->next;
4311 if (tok_type_(t, TOK_WHITESPACE))
4312 last = t, t = t->next;
4313 }
H. Peter Anvin89cee572009-07-15 09:16:54 -04004314 if (!tok_type_(t, TOK_ID) || !(m = is_mmacro(t, &params)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004315 return 0;
4316 last->next = NULL;
Keith Kanios891775e2009-07-11 06:08:54 -05004317 mname = t->text;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004318 tline = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004319 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004320
4321 /*
4322 * Fix up the parameters: this involves stripping leading and
4323 * trailing whitespace, then stripping braces if they are
4324 * present.
4325 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004326 for (nparam = 0; params[nparam]; nparam++) ;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004327 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004328
H. Peter Anvine2c80182005-01-15 22:15:51 +00004329 for (i = 0; params[i]; i++) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004330 int brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004331 int comma = (!m->plus || i < nparam - 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004332
H. Peter Anvine2c80182005-01-15 22:15:51 +00004333 t = params[i];
4334 skip_white_(t);
4335 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004336 t = t->next, brace = true, comma = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004337 params[i] = t;
4338 paramlen[i] = 0;
4339 while (t) {
4340 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
4341 break; /* ... because we have hit a comma */
4342 if (comma && t->type == TOK_WHITESPACE
4343 && tok_is_(t->next, ","))
4344 break; /* ... or a space then a comma */
4345 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
4346 break; /* ... or a brace */
4347 t = t->next;
4348 paramlen[i]++;
4349 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004350 }
4351
4352 /*
4353 * OK, we have a MMacro structure together with a set of
4354 * parameters. We must now go through the expansion and push
H. Peter Anvin76690a12002-04-30 20:52:49 +00004355 * copies of each Line on to istk->expansion. Substitution of
4356 * parameter tokens and macro-local tokens doesn't get done
4357 * until the single-line macro substitution process; this is
4358 * because delaying them allows us to change the semantics
4359 * later through %rotate.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004360 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00004361 * First, push an end marker on to istk->expansion, mark this
4362 * macro as in progress, and set up its invocation-specific
4363 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004364 */
4365 ll = nasm_malloc(sizeof(Line));
4366 ll->next = istk->expansion;
4367 ll->finishes = m;
4368 ll->first = NULL;
4369 istk->expansion = ll;
Keith Kanios891775e2009-07-11 06:08:54 -05004370
H. Peter Anvin89cee572009-07-15 09:16:54 -04004371 /*
4372 * Save the previous MMacro expansion in the case of
4373 * macro recursion
4374 */
4375 if (m->max_depth && m->in_progress)
4376 push_mmacro(m);
H. Peter Anvin76690a12002-04-30 20:52:49 +00004377
Keith Kanios891775e2009-07-11 06:08:54 -05004378 m->in_progress ++;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004379 m->params = params;
4380 m->iline = tline;
4381 m->nparam = nparam;
4382 m->rotate = 0;
4383 m->paramlen = paramlen;
4384 m->unique = unique++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004385 m->lineno = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004386
4387 m->next_active = istk->mstk;
4388 istk->mstk = m;
4389
H. Peter Anvine2c80182005-01-15 22:15:51 +00004390 for (l = m->expansion; l; l = l->next) {
4391 Token **tail;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004392
H. Peter Anvine2c80182005-01-15 22:15:51 +00004393 ll = nasm_malloc(sizeof(Line));
4394 ll->finishes = NULL;
4395 ll->next = istk->expansion;
4396 istk->expansion = ll;
4397 tail = &ll->first;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004398
H. Peter Anvine2c80182005-01-15 22:15:51 +00004399 for (t = l->first; t; t = t->next) {
4400 Token *x = t;
H. Peter Anvince2233b2008-05-25 21:57:00 -07004401 switch (t->type) {
4402 case TOK_PREPROC_Q:
H. Peter Anvinc751e862008-06-09 10:18:45 -07004403 tt = *tail = new_Token(NULL, TOK_ID, mname, 0);
H. Peter Anvince2233b2008-05-25 21:57:00 -07004404 break;
4405 case TOK_PREPROC_QQ:
4406 tt = *tail = new_Token(NULL, TOK_ID, m->name, 0);
4407 break;
4408 case TOK_PREPROC_ID:
4409 if (t->text[1] == '0' && t->text[2] == '0') {
4410 dont_prepend = -1;
4411 x = label;
4412 if (!x)
4413 continue;
4414 }
4415 /* fall through */
4416 default:
4417 tt = *tail = new_Token(NULL, x->type, x->text, 0);
4418 break;
H. Peter Anvin166c2472008-05-28 12:28:58 -07004419 }
H. Peter Anvince2233b2008-05-25 21:57:00 -07004420 tail = &tt->next;
4421 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004422 *tail = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004423 }
4424
4425 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00004426 * If we had a label, push it on as the first line of
4427 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004428 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004429 if (label) {
4430 if (dont_prepend < 0)
4431 free_tlist(startline);
4432 else {
4433 ll = nasm_malloc(sizeof(Line));
4434 ll->finishes = NULL;
4435 ll->next = istk->expansion;
4436 istk->expansion = ll;
4437 ll->first = startline;
4438 if (!dont_prepend) {
4439 while (label->next)
4440 label = label->next;
4441 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
4442 }
4443 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004444 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004445
H. Peter Anvin734b1882002-04-30 21:01:08 +00004446 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004447
H. Peter Anvineba20a72002-04-30 20:53:55 +00004448 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004449}
4450
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004451/* The function that actually does the error reporting */
4452static void verror(int severity, const char *fmt, va_list arg)
4453{
4454 char buff[1024];
4455
4456 vsnprintf(buff, sizeof(buff), fmt, arg);
4457
4458 if (istk && istk->mstk && istk->mstk->name)
H. Peter Anvindbb640b2009-07-18 18:57:16 -07004459 nasm_error(severity, "(%s:%d) %s", istk->mstk->name,
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004460 istk->mstk->lineno, buff);
4461 else
H. Peter Anvindbb640b2009-07-18 18:57:16 -07004462 nasm_error(severity, "%s", buff);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004463}
4464
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004465/*
4466 * Since preprocessor always operate only on the line that didn't
H. Peter Anvin917a3492008-09-24 09:14:49 -07004467 * arrived yet, we should always use ERR_OFFBY1.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004468 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004469static void error(int severity, const char *fmt, ...)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004470{
4471 va_list arg;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004472
4473 /* If we're in a dead branch of IF or something like it, ignore the error */
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00004474 if (istk && istk->conds && !emitting(istk->conds->state))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004475 return;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004476
H. Peter Anvin734b1882002-04-30 21:01:08 +00004477 va_start(arg, fmt);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004478 verror(severity, fmt, arg);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004479 va_end(arg);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004480}
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004481
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004482/*
4483 * Because %else etc are evaluated in the state context
4484 * of the previous branch, errors might get lost with error():
4485 * %if 0 ... %else trailing garbage ... %endif
4486 * So %else etc should report errors with this function.
4487 */
4488static void error_precond(int severity, const char *fmt, ...)
4489{
4490 va_list arg;
4491
4492 /* Only ignore the error if it's really in a dead branch */
4493 if (istk && istk->conds && istk->conds->state == COND_NEVER)
4494 return;
4495
4496 va_start(arg, fmt);
4497 verror(severity, fmt, arg);
4498 va_end(arg);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004499}
4500
H. Peter Anvin734b1882002-04-30 21:01:08 +00004501static void
H. Peter Anvindbb640b2009-07-18 18:57:16 -07004502pp_reset(char *file, int apass, ListGen * listgen, StrList **deplist)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004503{
H. Peter Anvin7383b402008-09-24 10:20:40 -07004504 Token *t;
4505
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004506 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004507 istk = nasm_malloc(sizeof(Include));
4508 istk->next = NULL;
4509 istk->conds = NULL;
4510 istk->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004511 istk->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004512 istk->fp = fopen(file, "r");
H. Peter Anvineba20a72002-04-30 20:53:55 +00004513 istk->fname = NULL;
4514 src_set_fname(nasm_strdup(file));
4515 src_set_linnum(0);
4516 istk->lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004517 if (!istk->fp)
H. Peter Anvin917a3492008-09-24 09:14:49 -07004518 error(ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'",
H. Peter Anvine2c80182005-01-15 22:15:51 +00004519 file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004520 defining = NULL;
Charles Crayned4200be2008-07-12 16:42:33 -07004521 nested_mac_count = 0;
4522 nested_rep_count = 0;
H. Peter Anvin97a23472007-09-16 17:57:25 -07004523 init_macros();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004524 unique = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004525 if (tasm_compatible_mode) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07004526 stdmacpos = nasm_stdmac;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004527 } else {
H. Peter Anvina4835d42008-05-20 14:21:29 -07004528 stdmacpos = nasm_stdmac_after_tasm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004529 }
H. Peter Anvind2456592008-06-19 15:04:18 -07004530 any_extrastdmac = extrastdmac && *extrastdmac;
4531 do_predef = true;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004532 list = listgen;
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004533
4534 /*
4535 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4536 * The caller, however, will also pass in 3 for preprocess-only so
4537 * we can set __PASS__ accordingly.
4538 */
4539 pass = apass > 2 ? 2 : apass;
4540
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07004541 dephead = deptail = deplist;
4542 if (deplist) {
4543 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
4544 sl->next = NULL;
4545 strcpy(sl->str, file);
4546 *deptail = sl;
4547 deptail = &sl->next;
4548 }
H. Peter Anvin7383b402008-09-24 10:20:40 -07004549
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004550 /*
4551 * Define the __PASS__ macro. This is defined here unlike
4552 * all the other builtins, because it is special -- it varies between
4553 * passes.
4554 */
H. Peter Anvin7383b402008-09-24 10:20:40 -07004555 t = nasm_malloc(sizeof(*t));
4556 t->next = NULL;
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004557 make_tok_num(t, apass);
H. Peter Anvin7383b402008-09-24 10:20:40 -07004558 t->a.mac = NULL;
4559 define_smacro(NULL, "__PASS__", true, 0, t);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004560}
4561
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004562static char *pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004563{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004564 char *line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004565 Token *tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004566
H. Peter Anvine2c80182005-01-15 22:15:51 +00004567 while (1) {
4568 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00004569 * Fetch a tokenized line, either from the macro-expansion
H. Peter Anvine2c80182005-01-15 22:15:51 +00004570 * buffer or from the input file.
4571 */
4572 tline = NULL;
4573 while (istk->expansion && istk->expansion->finishes) {
4574 Line *l = istk->expansion;
4575 if (!l->finishes->name && l->finishes->in_progress > 1) {
4576 Line *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004577
H. Peter Anvine2c80182005-01-15 22:15:51 +00004578 /*
4579 * This is a macro-end marker for a macro with no
4580 * name, which means it's not really a macro at all
4581 * but a %rep block, and the `in_progress' field is
4582 * more than 1, meaning that we still need to
4583 * repeat. (1 means the natural last repetition; 0
4584 * means termination by %exitrep.) We have
4585 * therefore expanded up to the %endrep, and must
4586 * push the whole block on to the expansion buffer
4587 * again. We don't bother to remove the macro-end
4588 * marker: we'd only have to generate another one
4589 * if we did.
4590 */
4591 l->finishes->in_progress--;
4592 for (l = l->finishes->expansion; l; l = l->next) {
4593 Token *t, *tt, **tail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004594
H. Peter Anvine2c80182005-01-15 22:15:51 +00004595 ll = nasm_malloc(sizeof(Line));
4596 ll->next = istk->expansion;
4597 ll->finishes = NULL;
4598 ll->first = NULL;
4599 tail = &ll->first;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004600
H. Peter Anvine2c80182005-01-15 22:15:51 +00004601 for (t = l->first; t; t = t->next) {
4602 if (t->text || t->type == TOK_WHITESPACE) {
4603 tt = *tail =
4604 new_Token(NULL, t->type, t->text, 0);
4605 tail = &tt->next;
4606 }
4607 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004608
H. Peter Anvine2c80182005-01-15 22:15:51 +00004609 istk->expansion = ll;
4610 }
4611 } else {
4612 /*
4613 * Check whether a `%rep' was started and not ended
4614 * within this macro expansion. This can happen and
4615 * should be detected. It's a fatal error because
4616 * I'm too confused to work out how to recover
4617 * sensibly from it.
4618 */
4619 if (defining) {
4620 if (defining->name)
4621 error(ERR_PANIC,
4622 "defining with name in expansion");
4623 else if (istk->mstk->name)
4624 error(ERR_FATAL,
4625 "`%%rep' without `%%endrep' within"
4626 " expansion of macro `%s'",
4627 istk->mstk->name);
4628 }
H. Peter Anvin87bc6192002-04-30 20:53:16 +00004629
H. Peter Anvine2c80182005-01-15 22:15:51 +00004630 /*
4631 * FIXME: investigate the relationship at this point between
4632 * istk->mstk and l->finishes
4633 */
4634 {
4635 MMacro *m = istk->mstk;
4636 istk->mstk = m->next_active;
4637 if (m->name) {
4638 /*
4639 * This was a real macro call, not a %rep, and
4640 * therefore the parameter information needs to
4641 * be freed.
4642 */
H. Peter Anvin89cee572009-07-15 09:16:54 -04004643 if (m->prev) {
4644 pop_mmacro(m);
4645 l->finishes->in_progress --;
4646 } else {
Keith Kanios891775e2009-07-11 06:08:54 -05004647 nasm_free(m->params);
4648 free_tlist(m->iline);
H. Peter Anvin89cee572009-07-15 09:16:54 -04004649 nasm_free(m->paramlen);
4650 l->finishes->in_progress = 0;
4651 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004652 } else
4653 free_mmacro(m);
4654 }
4655 istk->expansion = l->next;
4656 nasm_free(l);
4657 list->downlevel(LIST_MACRO);
4658 }
4659 }
4660 while (1) { /* until we get a line we can use */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004661
H. Peter Anvine2c80182005-01-15 22:15:51 +00004662 if (istk->expansion) { /* from a macro expansion */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004663 char *p;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004664 Line *l = istk->expansion;
4665 if (istk->mstk)
4666 istk->mstk->lineno++;
4667 tline = l->first;
4668 istk->expansion = l->next;
4669 nasm_free(l);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004670 p = detoken(tline, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004671 list->line(LIST_MACRO, p);
4672 nasm_free(p);
4673 break;
4674 }
4675 line = read_line();
4676 if (line) { /* from the current input file */
4677 line = prepreproc(line);
Keith Kaniosb7a89542007-04-12 02:40:54 +00004678 tline = tokenize(line);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004679 nasm_free(line);
4680 break;
4681 }
4682 /*
4683 * The current file has ended; work down the istk
4684 */
4685 {
4686 Include *i = istk;
4687 fclose(i->fp);
4688 if (i->conds)
4689 error(ERR_FATAL,
4690 "expected `%%endif' before end of file");
4691 /* only set line and file name if there's a next node */
4692 if (i->next) {
4693 src_set_linnum(i->lineno);
4694 nasm_free(src_set_fname(i->fname));
H. Peter Anvin86877b22008-06-20 15:55:45 -07004695 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004696 istk = i->next;
4697 list->downlevel(LIST_INCLUDE);
4698 nasm_free(i);
4699 if (!istk)
4700 return NULL;
Victor van den Elzen4c9d6222008-10-01 13:08:50 +02004701 if (istk->expansion && istk->expansion->finishes)
4702 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004703 }
4704 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004705
H. Peter Anvine2c80182005-01-15 22:15:51 +00004706 /*
4707 * We must expand MMacro parameters and MMacro-local labels
4708 * _before_ we plunge into directive processing, to cope
4709 * with things like `%define something %1' such as STRUC
4710 * uses. Unless we're _defining_ a MMacro, in which case
4711 * those tokens should be left alone to go into the
4712 * definition; and unless we're in a non-emitting
4713 * condition, in which case we don't want to meddle with
4714 * anything.
4715 */
Charles Crayned4200be2008-07-12 16:42:33 -07004716 if (!defining && !(istk->conds && !emitting(istk->conds->state))
H. Peter Anvin992fe752008-10-19 15:45:05 -07004717 && !(istk->mstk && !istk->mstk->in_progress)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004718 tline = expand_mmac_params(tline);
H. Peter Anvin992fe752008-10-19 15:45:05 -07004719 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004720
H. Peter Anvine2c80182005-01-15 22:15:51 +00004721 /*
4722 * Check the line to see if it's a preprocessor directive.
4723 */
4724 if (do_directive(tline) == DIRECTIVE_FOUND) {
4725 continue;
4726 } else if (defining) {
4727 /*
4728 * We're defining a multi-line macro. We emit nothing
4729 * at all, and just
Keith Kaniosb7a89542007-04-12 02:40:54 +00004730 * shove the tokenized line on to the macro definition.
H. Peter Anvine2c80182005-01-15 22:15:51 +00004731 */
4732 Line *l = nasm_malloc(sizeof(Line));
4733 l->next = defining->expansion;
4734 l->first = tline;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004735 l->finishes = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004736 defining->expansion = l;
4737 continue;
4738 } else if (istk->conds && !emitting(istk->conds->state)) {
4739 /*
4740 * We're in a non-emitting branch of a condition block.
4741 * Emit nothing at all, not even a blank line: when we
4742 * emerge from the condition we'll give a line-number
4743 * directive so we keep our place correctly.
4744 */
4745 free_tlist(tline);
4746 continue;
4747 } else if (istk->mstk && !istk->mstk->in_progress) {
4748 /*
4749 * We're in a %rep block which has been terminated, so
4750 * we're walking through to the %endrep without
4751 * emitting anything. Emit nothing at all, not even a
4752 * blank line: when we emerge from the %rep block we'll
4753 * give a line-number directive so we keep our place
4754 * correctly.
4755 */
4756 free_tlist(tline);
4757 continue;
4758 } else {
4759 tline = expand_smacro(tline);
4760 if (!expand_mmacro(tline)) {
4761 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00004762 * De-tokenize the line again, and emit it.
H. Peter Anvine2c80182005-01-15 22:15:51 +00004763 */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004764 line = detoken(tline, true);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004765 free_tlist(tline);
4766 break;
4767 } else {
4768 continue; /* expand_mmacro calls free_tlist */
4769 }
4770 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004771 }
4772
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004773 return line;
4774}
4775
H. Peter Anvine2c80182005-01-15 22:15:51 +00004776static void pp_cleanup(int pass)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004777{
H. Peter Anvine2c80182005-01-15 22:15:51 +00004778 if (defining) {
H. Peter Anvin89cee572009-07-15 09:16:54 -04004779 if (defining->name) {
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02004780 error(ERR_NONFATAL,
4781 "end of file while still defining macro `%s'",
4782 defining->name);
4783 } else {
4784 error(ERR_NONFATAL, "end of file while still in %%rep");
4785 }
4786
H. Peter Anvine2c80182005-01-15 22:15:51 +00004787 free_mmacro(defining);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004788 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004789 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004790 ctx_pop();
H. Peter Anvin97a23472007-09-16 17:57:25 -07004791 free_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00004792 while (istk) {
4793 Include *i = istk;
4794 istk = istk->next;
4795 fclose(i->fp);
4796 nasm_free(i->fname);
4797 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004798 }
4799 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004800 ctx_pop();
H. Peter Anvin86877b22008-06-20 15:55:45 -07004801 nasm_free(src_set_fname(NULL));
H. Peter Anvine2c80182005-01-15 22:15:51 +00004802 if (pass == 0) {
H. Peter Anvin86877b22008-06-20 15:55:45 -07004803 IncPath *i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004804 free_llist(predef);
4805 delete_Blocks();
H. Peter Anvin86877b22008-06-20 15:55:45 -07004806 while ((i = ipath)) {
4807 ipath = i->next;
4808 if (i->path)
4809 nasm_free(i->path);
4810 nasm_free(i);
4811 }
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07004812 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004813}
4814
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004815void pp_include_path(char *path)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004816{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004817 IncPath *i;
H. Peter Anvin37a321f2007-09-24 13:41:58 -07004818
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004819 i = nasm_malloc(sizeof(IncPath));
H. Peter Anvin37a321f2007-09-24 13:41:58 -07004820 i->path = path ? nasm_strdup(path) : NULL;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004821 i->next = NULL;
4822
H. Peter Anvin89cee572009-07-15 09:16:54 -04004823 if (ipath) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004824 IncPath *j = ipath;
H. Peter Anvin89cee572009-07-15 09:16:54 -04004825 while (j->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004826 j = j->next;
4827 j->next = i;
4828 } else {
4829 ipath = i;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004830 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004831}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004832
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004833void pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004834{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004835 Token *inc, *space, *name;
4836 Line *l;
4837
H. Peter Anvin734b1882002-04-30 21:01:08 +00004838 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
4839 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
4840 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004841
4842 l = nasm_malloc(sizeof(Line));
4843 l->next = predef;
4844 l->first = inc;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004845 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004846 predef = l;
4847}
4848
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004849void pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004850{
4851 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004852 Line *l;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004853 char *equals;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004854
4855 equals = strchr(definition, '=');
H. Peter Anvin734b1882002-04-30 21:01:08 +00004856 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4857 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004858 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004859 *equals = ' ';
Keith Kaniosb7a89542007-04-12 02:40:54 +00004860 space->next = tokenize(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004861 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004862 *equals = '=';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004863
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004864 l = nasm_malloc(sizeof(Line));
4865 l->next = predef;
4866 l->first = def;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004867 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004868 predef = l;
4869}
4870
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004871void pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00004872{
4873 Token *def, *space;
4874 Line *l;
4875
H. Peter Anvin734b1882002-04-30 21:01:08 +00004876 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4877 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Keith Kaniosb7a89542007-04-12 02:40:54 +00004878 space->next = tokenize(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00004879
4880 l = nasm_malloc(sizeof(Line));
4881 l->next = predef;
4882 l->first = def;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004883 l->finishes = NULL;
H. Peter Anvin620515a2002-04-30 20:57:38 +00004884 predef = l;
4885}
4886
Keith Kaniosb7a89542007-04-12 02:40:54 +00004887/*
4888 * Added by Keith Kanios:
4889 *
4890 * This function is used to assist with "runtime" preprocessor
4891 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4892 *
4893 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4894 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4895 */
4896
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004897void pp_runtime(char *definition)
Keith Kaniosb7a89542007-04-12 02:40:54 +00004898{
4899 Token *def;
H. Peter Anvin70653092007-10-19 14:42:29 -07004900
Keith Kaniosb7a89542007-04-12 02:40:54 +00004901 def = tokenize(definition);
H. Peter Anvin89cee572009-07-15 09:16:54 -04004902 if (do_directive(def) == NO_DIRECTIVE_FOUND)
Keith Kaniosb7a89542007-04-12 02:40:54 +00004903 free_tlist(def);
H. Peter Anvin70653092007-10-19 14:42:29 -07004904
Keith Kaniosb7a89542007-04-12 02:40:54 +00004905}
4906
H. Peter Anvina70547f2008-07-19 21:44:26 -07004907void pp_extra_stdmac(macros_t *macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004908{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004909 extrastdmac = macros;
4910}
4911
Keith Kaniosa5fc6462007-10-13 07:09:22 -07004912static void make_tok_num(Token * tok, int64_t val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004913{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004914 char numbuf[20];
Keith Kaniosa5fc6462007-10-13 07:09:22 -07004915 snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004916 tok->text = nasm_strdup(numbuf);
4917 tok->type = TOK_NUMBER;
4918}
4919
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004920Preproc nasmpp = {
4921 pp_reset,
4922 pp_getline,
4923 pp_cleanup
4924};