blob: ab24953a2bd04d2392a4ef533ead8a84ebb4a34f [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"
80#include "tokens.h"
H. Peter Anvina4835d42008-05-20 14:21:29 -070081#include "tables.h"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000082
83typedef struct SMacro SMacro;
84typedef struct MMacro MMacro;
85typedef struct Context Context;
86typedef struct Token Token;
H. Peter Anvince616072002-04-30 21:02:23 +000087typedef struct Blocks Blocks;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000088typedef struct Line Line;
89typedef struct Include Include;
90typedef struct Cond Cond;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000091typedef struct IncPath IncPath;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000092
93/*
H. Peter Anvin97a23472007-09-16 17:57:25 -070094 * Note on the storage of both SMacro and MMacros: the hash table
95 * indexes them case-insensitively, and we then have to go through a
96 * linked list of potential case aliases (and, for MMacros, parameter
97 * ranges); this is to preserve the matching semantics of the earlier
98 * code. If the number of case aliases for a specific macro is a
99 * performance issue, you may want to reconsider your coding style.
100 */
101
102/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000103 * Store the definition of a single-line macro.
104 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000105struct SMacro {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000106 SMacro *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000107 char *name;
H. Peter Anvin70055962007-10-11 00:05:31 -0700108 bool casesense;
H. Peter Anvin16ed4382007-10-11 10:06:19 -0700109 bool in_progress;
H. Peter Anvin70055962007-10-11 00:05:31 -0700110 unsigned int nparam;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000111 Token *expansion;
112};
113
114/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000115 * Store the definition of a multi-line macro. This is also used to
116 * store the interiors of `%rep...%endrep' blocks, which are
117 * effectively self-re-invoking multi-line macros which simply
118 * don't have a name or bother to appear in the hash tables. %rep
119 * blocks are signified by having a NULL `name' field.
120 *
121 * In a MMacro describing a `%rep' block, the `in_progress' field
122 * isn't merely boolean, but gives the number of repeats left to
123 * run.
124 *
125 * The `next' field is used for storing MMacros in hash tables; the
126 * `next_active' field is for stacking them on istk entries.
127 *
128 * When a MMacro is being expanded, `params', `iline', `nparam',
129 * `paramlen', `rotate' and `unique' are local to the invocation.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000130 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000131struct MMacro {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000132 MMacro *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000133 char *name;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -0700134 int nparam_min, nparam_max;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700135 bool casesense;
136 bool plus; /* is the last parameter greedy? */
137 bool nolist; /* is this macro listing-inhibited? */
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700138 int64_t in_progress;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000139 Token *dlist; /* All defaults as one list */
140 Token **defaults; /* Parameter default pointers */
141 int ndefs; /* number of default parameters */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000142 Line *expansion;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000143
144 MMacro *next_active;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000145 MMacro *rep_nest; /* used for nesting %rep */
146 Token **params; /* actual parameters */
147 Token *iline; /* invocation line */
H. Peter Anvin25a99342007-09-22 17:45:45 -0700148 unsigned int nparam, rotate;
149 int *paramlen;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700150 uint64_t unique;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000151 int lineno; /* Current line number on expansion */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000152};
153
154/*
155 * The context stack is composed of a linked list of these.
156 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000157struct Context {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000158 Context *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000159 char *name;
H. Peter Anvin166c2472008-05-28 12:28:58 -0700160 struct hash_table localmac;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000161 uint32_t number;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000162};
163
164/*
165 * This is the internal form which we break input lines up into.
166 * Typically stored in linked lists.
167 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000168 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
169 * necessarily used as-is, but is intended to denote the number of
170 * the substituted parameter. So in the definition
171 *
172 * %define a(x,y) ( (x) & ~(y) )
H. Peter Anvin70653092007-10-19 14:42:29 -0700173 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000174 * the token representing `x' will have its type changed to
175 * TOK_SMAC_PARAM, but the one representing `y' will be
176 * TOK_SMAC_PARAM+1.
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000177 *
178 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
179 * which doesn't need quotes around it. Used in the pre-include
180 * mechanism as an alternative to trying to find a sensible type of
181 * quote to use on the filename we were passed.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000182 */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000183enum pp_token_type {
184 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID,
185 TOK_PREPROC_ID, TOK_STRING,
H. Peter Anvin6c81f0a2008-05-25 21:46:17 -0700186 TOK_NUMBER, TOK_FLOAT, TOK_SMAC_END, TOK_OTHER,
187 TOK_INTERNAL_STRING,
188 TOK_PREPROC_Q, TOK_PREPROC_QQ,
H. Peter Anvind784a082009-04-20 14:01:18 -0700189 TOK_PASTE, /* %+ */
H. Peter Anvin9bb46df2009-04-07 21:59:24 -0700190 TOK_INDIRECT, /* %[...] */
H. Peter Anvin5b76fa22008-05-26 11:14:38 -0700191 TOK_SMAC_PARAM, /* MUST BE LAST IN THE LIST!!! */
192 TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000193};
194
H. Peter Anvine2c80182005-01-15 22:15:51 +0000195struct Token {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000196 Token *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000197 char *text;
H. Peter Anvinf26e0972008-07-01 21:26:27 -0700198 union {
199 SMacro *mac; /* associated macro for TOK_SMAC_END */
200 size_t len; /* scratch length field */
201 } a; /* Auxiliary data */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000202 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000203};
204
205/*
206 * Multi-line macro definitions are stored as a linked list of
207 * these, which is essentially a container to allow several linked
208 * lists of Tokens.
H. Peter Anvin70653092007-10-19 14:42:29 -0700209 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000210 * Note that in this module, linked lists are treated as stacks
211 * wherever possible. For this reason, Lines are _pushed_ on to the
212 * `expansion' field in MMacro structures, so that the linked list,
213 * if walked, would give the macro lines in reverse order; this
214 * means that we can walk the list when expanding a macro, and thus
215 * push the lines on to the `expansion' field in _istk_ in reverse
216 * order (so that when popped back off they are in the right
217 * order). It may seem cockeyed, and it relies on my design having
218 * an even number of steps in, but it works...
219 *
220 * Some of these structures, rather than being actual lines, are
221 * markers delimiting the end of the expansion of a given macro.
H. Peter Anvin76690a12002-04-30 20:52:49 +0000222 * This is for use in the cycle-tracking and %rep-handling code.
223 * Such structures have `finishes' non-NULL, and `first' NULL. All
224 * others have `finishes' NULL, but `first' may still be NULL if
225 * the line is blank.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000226 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000227struct Line {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000228 Line *next;
229 MMacro *finishes;
230 Token *first;
231};
232
233/*
234 * To handle an arbitrary level of file inclusion, we maintain a
235 * stack (ie linked list) of these things.
236 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000237struct Include {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000238 Include *next;
239 FILE *fp;
240 Cond *conds;
241 Line *expansion;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000242 char *fname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000243 int lineno, lineinc;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000244 MMacro *mstk; /* stack of active macros/reps */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000245};
246
247/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000248 * Include search path. This is simply a list of strings which get
249 * prepended, in turn, to the name of an include file, in an
250 * attempt to find the file if it's not in the current directory.
251 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000252struct IncPath {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000253 IncPath *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000254 char *path;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000255};
256
257/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000258 * Conditional assembly: we maintain a separate stack of these for
259 * each level of file inclusion. (The only reason we keep the
260 * stacks separate is to ensure that a stray `%endif' in a file
261 * included from within the true branch of a `%if' won't terminate
262 * it and cause confusion: instead, rightly, it'll cause an error.)
263 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000264struct Cond {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000265 Cond *next;
266 int state;
267};
H. Peter Anvine2c80182005-01-15 22:15:51 +0000268enum {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000269 /*
270 * These states are for use just after %if or %elif: IF_TRUE
271 * means the condition has evaluated to truth so we are
272 * currently emitting, whereas IF_FALSE means we are not
273 * currently emitting but will start doing so if a %else comes
274 * up. In these states, all directives are admissible: %elif,
275 * %else and %endif. (And of course %if.)
276 */
277 COND_IF_TRUE, COND_IF_FALSE,
278 /*
279 * These states come up after a %else: ELSE_TRUE means we're
280 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
281 * any %elif or %else will cause an error.
282 */
283 COND_ELSE_TRUE, COND_ELSE_FALSE,
284 /*
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200285 * These states mean that we're not emitting now, and also that
286 * nothing until %endif will be emitted at all. COND_DONE is
287 * used when we've had our moment of emission
288 * and have now started seeing %elifs. COND_NEVER is used when
289 * the condition construct in question is contained within a
290 * non-emitting branch of a larger condition construct,
291 * or if there is an error.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000292 */
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200293 COND_DONE, COND_NEVER
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000294};
295#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
296
H. Peter Anvin70653092007-10-19 14:42:29 -0700297/*
Ed Beroset3ab3f412002-06-11 03:31:49 +0000298 * These defines are used as the possible return values for do_directive
299 */
300#define NO_DIRECTIVE_FOUND 0
301#define DIRECTIVE_FOUND 1
302
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000303/*
304 * Condition codes. Note that we use c_ prefix not C_ because C_ is
305 * used in nasm.h for the "real" condition codes. At _this_ level,
306 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
307 * ones, so we need a different enum...
308 */
H. Peter Anvin476d2862007-10-02 22:04:15 -0700309static const char * const conditions[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000310 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
311 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
H. Peter Anvince9be342007-09-12 00:22:29 +0000312 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000313};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700314enum pp_conds {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000315 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
316 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 -0700317 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
318 c_none = -1
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000319};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700320static const enum pp_conds inverse_ccs[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000321 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
322 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 +0000323 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000324};
325
H. Peter Anvin76690a12002-04-30 20:52:49 +0000326/*
327 * Directive names.
328 */
H. Peter Anvin65747262002-05-07 00:10:05 +0000329/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
H. Peter Anvin9bf0aa72007-09-12 02:12:07 +0000330static int is_condition(enum preproc_token arg)
H. Peter Anvin65747262002-05-07 00:10:05 +0000331{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000332 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
H. Peter Anvin65747262002-05-07 00:10:05 +0000333}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000334
335/* For TASM compatibility we need to be able to recognise TASM compatible
336 * conditional compilation directives. Using the NASM pre-processor does
337 * not work, so we look for them specifically from the following list and
338 * then jam in the equivalent NASM directive into the input stream.
339 */
340
H. Peter Anvine2c80182005-01-15 22:15:51 +0000341enum {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000342 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
343 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
344};
345
H. Peter Anvin476d2862007-10-02 22:04:15 -0700346static const char * const tasm_directives[] = {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000347 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
348 "ifndef", "include", "local"
349};
350
351static int StackSize = 4;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000352static char *StackPointer = "ebp";
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000353static int ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -0800354static int LocalOffset = 0;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000355
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000356static Context *cstk;
357static Include *istk;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000358static IncPath *ipath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000359
H. Peter Anvine2c80182005-01-15 22:15:51 +0000360static efunc _error; /* Pointer to client-provided error reporting function */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000361static evalfunc evaluate;
362
H. Peter Anvine2c80182005-01-15 22:15:51 +0000363static int pass; /* HACK: pass 0 = generate dependencies only */
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700364static StrList **dephead, **deptail; /* Dependency list */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000365
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700366static uint64_t unique; /* unique identifier numbers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000367
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000368static Line *predef = NULL;
H. Peter Anvind2456592008-06-19 15:04:18 -0700369static bool do_predef;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000370
371static ListGen *list;
372
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000373/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000374 * The current set of multi-line macros we have defined.
375 */
H. Peter Anvin166c2472008-05-28 12:28:58 -0700376static struct hash_table mmacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000377
378/*
379 * The current set of single-line macros we have defined.
380 */
H. Peter Anvin166c2472008-05-28 12:28:58 -0700381static struct hash_table smacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000382
383/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000384 * The multi-line macro we are currently defining, or the %rep
385 * block we are currently reading, if any.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000386 */
387static MMacro *defining;
388
Charles Crayned4200be2008-07-12 16:42:33 -0700389static uint64_t nested_mac_count;
390static uint64_t nested_rep_count;
391
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000392/*
393 * The number of macro parameters to allocate space for at a time.
394 */
395#define PARAM_DELTA 16
396
397/*
H. Peter Anvina4835d42008-05-20 14:21:29 -0700398 * The standard macro set: defined in macros.c in the array nasm_stdmac.
399 * This gives our position in the macro set, when we're processing it.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000400 */
H. Peter Anvina70547f2008-07-19 21:44:26 -0700401static macros_t *stdmacpos;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000402
403/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000404 * The extra standard macros that come from the object format, if
405 * any.
406 */
H. Peter Anvina70547f2008-07-19 21:44:26 -0700407static macros_t *extrastdmac = NULL;
H. Peter Anvincfb71762008-06-20 15:20:16 -0700408static bool any_extrastdmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000409
410/*
H. Peter Anvin734b1882002-04-30 21:01:08 +0000411 * Tokens are allocated in blocks to improve speed
412 */
413#define TOKEN_BLOCKSIZE 4096
414static Token *freeTokens = NULL;
H. Peter Anvince616072002-04-30 21:02:23 +0000415struct Blocks {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000416 Blocks *next;
417 void *chunk;
H. Peter Anvince616072002-04-30 21:02:23 +0000418};
419
420static Blocks blocks = { NULL, NULL };
H. Peter Anvin734b1882002-04-30 21:01:08 +0000421
422/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000423 * Forward declarations.
424 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000425static Token *expand_mmac_params(Token * tline);
426static Token *expand_smacro(Token * tline);
427static Token *expand_id(Token * tline);
H. Peter Anvinf8ad5322009-02-21 17:55:08 -0800428static Context *get_ctx(const char *name, const char **namep,
429 bool all_contexts);
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700430static void make_tok_num(Token * tok, int64_t val);
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000431static void error(int severity, const char *fmt, ...);
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200432static void error_precond(int severity, const char *fmt, ...);
H. Peter Anvince616072002-04-30 21:02:23 +0000433static void *new_Block(size_t size);
434static void delete_Blocks(void);
H. Peter Anvinc751e862008-06-09 10:18:45 -0700435static Token *new_Token(Token * next, enum pp_token_type type,
436 const char *text, int txtlen);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000437static Token *delete_Token(Token * t);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000438
439/*
440 * Macros for safe checking of token pointers, avoid *(NULL)
441 */
442#define tok_type_(x,t) ((x) && (x)->type == (t))
443#define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
444#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
445#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
H. Peter Anvin76690a12002-04-30 20:52:49 +0000446
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000447/* Handle TASM specific directives, which do not contain a % in
448 * front of them. We do it here because I could not find any other
449 * place to do it for the moment, and it is a hack (ideally it would
450 * be nice to be able to use the NASM pre-processor to do it).
451 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000452static char *check_tasm_directive(char *line)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000453{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000454 int32_t i, j, k, m, len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000455 char *p = line, *oldline, oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000456
457 /* Skip whitespace */
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700458 while (nasm_isspace(*p) && *p != 0)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000459 p++;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000460
461 /* Binary search for the directive name */
462 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +0000463 j = elements(tasm_directives);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000464 len = 0;
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700465 while (!nasm_isspace(p[len]) && p[len] != 0)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000466 len++;
467 if (len) {
468 oldchar = p[len];
469 p[len] = 0;
470 while (j - i > 1) {
471 k = (j + i) / 2;
472 m = nasm_stricmp(p, tasm_directives[k]);
473 if (m == 0) {
474 /* We have found a directive, so jam a % in front of it
475 * so that NASM will then recognise it as one if it's own.
476 */
477 p[len] = oldchar;
478 len = strlen(p);
479 oldline = line;
480 line = nasm_malloc(len + 2);
481 line[0] = '%';
482 if (k == TM_IFDIFI) {
H. Peter Anvin18f48792009-06-27 15:56:27 -0700483 /*
484 * NASM does not recognise IFDIFI, so we convert
485 * it to %if 0. This is not used in NASM
486 * compatible code, but does need to parse for the
487 * TASM macro package.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000488 */
H. Peter Anvin18f48792009-06-27 15:56:27 -0700489 strcpy(line + 1, "if 0");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000490 } else {
491 memcpy(line + 1, p, len + 1);
492 }
493 nasm_free(oldline);
494 return line;
495 } else if (m < 0) {
496 j = k;
497 } else
498 i = k;
499 }
500 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000501 }
502 return line;
503}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000504
H. Peter Anvin76690a12002-04-30 20:52:49 +0000505/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000506 * The pre-preprocessing stage... This function translates line
507 * number indications as they emerge from GNU cpp (`# lineno "file"
508 * flags') into NASM preprocessor line number indications (`%line
509 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000510 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000511static char *prepreproc(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000512{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000513 int lineno, fnlen;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000514 char *fname, *oldline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000515
H. Peter Anvine2c80182005-01-15 22:15:51 +0000516 if (line[0] == '#' && line[1] == ' ') {
517 oldline = line;
518 fname = oldline + 2;
519 lineno = atoi(fname);
520 fname += strspn(fname, "0123456789 ");
521 if (*fname == '"')
522 fname++;
523 fnlen = strcspn(fname, "\"");
524 line = nasm_malloc(20 + fnlen);
525 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
526 nasm_free(oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000527 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000528 if (tasm_compatible_mode)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000529 return check_tasm_directive(line);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000530 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000531}
532
533/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000534 * Free a linked list of tokens.
535 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000536static void free_tlist(Token * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000537{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000538 while (list) {
539 list = delete_Token(list);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000540 }
541}
542
543/*
544 * Free a linked list of lines.
545 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000546static void free_llist(Line * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000547{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000548 Line *l;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000549 while (list) {
550 l = list;
551 list = list->next;
552 free_tlist(l->first);
553 nasm_free(l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000554 }
555}
556
557/*
H. Peter Anvineba20a72002-04-30 20:53:55 +0000558 * Free an MMacro
559 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000560static void free_mmacro(MMacro * m)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000561{
H. Peter Anvin734b1882002-04-30 21:01:08 +0000562 nasm_free(m->name);
563 free_tlist(m->dlist);
564 nasm_free(m->defaults);
565 free_llist(m->expansion);
566 nasm_free(m);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000567}
568
569/*
H. Peter Anvin97a23472007-09-16 17:57:25 -0700570 * Free all currently defined macros, and free the hash tables
571 */
H. Peter Anvin072771e2008-05-22 13:17:51 -0700572static void free_smacro_table(struct hash_table *smt)
H. Peter Anvin97a23472007-09-16 17:57:25 -0700573{
H. Peter Anvin97a23472007-09-16 17:57:25 -0700574 SMacro *s;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700575 const char *key;
576 struct hash_tbl_node *it = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -0700577
H. Peter Anvin072771e2008-05-22 13:17:51 -0700578 while ((s = hash_iterate(smt, &it, &key)) != NULL) {
H. Peter Anvin97a23472007-09-16 17:57:25 -0700579 nasm_free((void *)key);
580 while (s) {
581 SMacro *ns = s->next;
582 nasm_free(s->name);
583 free_tlist(s->expansion);
584 nasm_free(s);
585 s = ns;
586 }
587 }
H. Peter Anvin072771e2008-05-22 13:17:51 -0700588 hash_free(smt);
589}
590
591static void free_mmacro_table(struct hash_table *mmt)
592{
593 MMacro *m;
594 const char *key;
595 struct hash_tbl_node *it = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -0700596
597 it = NULL;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700598 while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
H. Peter Anvin97a23472007-09-16 17:57:25 -0700599 nasm_free((void *)key);
600 while (m) {
601 MMacro *nm = m->next;
602 free_mmacro(m);
603 m = nm;
604 }
605 }
H. Peter Anvin072771e2008-05-22 13:17:51 -0700606 hash_free(mmt);
607}
608
609static void free_macros(void)
610{
H. Peter Anvin166c2472008-05-28 12:28:58 -0700611 free_smacro_table(&smacros);
612 free_mmacro_table(&mmacros);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700613}
614
615/*
616 * Initialize the hash tables
617 */
618static void init_macros(void)
619{
H. Peter Anvin166c2472008-05-28 12:28:58 -0700620 hash_init(&smacros, HASH_LARGE);
621 hash_init(&mmacros, HASH_LARGE);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700622}
623
624/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000625 * Pop the context stack.
626 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000627static void ctx_pop(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000628{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000629 Context *c = cstk;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000630
631 cstk = cstk->next;
H. Peter Anvin166c2472008-05-28 12:28:58 -0700632 free_smacro_table(&c->localmac);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000633 nasm_free(c->name);
634 nasm_free(c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000635}
636
H. Peter Anvin072771e2008-05-22 13:17:51 -0700637/*
638 * Search for a key in the hash index; adding it if necessary
639 * (in which case we initialize the data pointer to NULL.)
640 */
641static void **
642hash_findi_add(struct hash_table *hash, const char *str)
643{
644 struct hash_insert hi;
645 void **r;
646 char *strx;
647
648 r = hash_findi(hash, str, &hi);
649 if (r)
650 return r;
651
652 strx = nasm_strdup(str); /* Use a more efficient allocator here? */
653 return hash_add(&hi, strx, NULL);
654}
655
656/*
657 * Like hash_findi, but returns the data element rather than a pointer
658 * to it. Used only when not adding a new element, hence no third
659 * argument.
660 */
661static void *
662hash_findix(struct hash_table *hash, const char *str)
663{
664 void **p;
665
666 p = hash_findi(hash, str, NULL);
667 return p ? *p : NULL;
668}
669
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000670#define BUF_DELTA 512
671/*
672 * Read a line from the top file in istk, handling multiple CR/LFs
673 * at the end of the line read, and handling spurious ^Zs. Will
674 * return lines from the standard macro set if this has not already
675 * been done.
676 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000677static char *read_line(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000678{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000679 char *buffer, *p, *q;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000680 int bufsize, continued_count;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000681
H. Peter Anvine2c80182005-01-15 22:15:51 +0000682 if (stdmacpos) {
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700683 unsigned char c;
H. Peter Anvin7e50d232008-06-25 14:54:14 -0700684 const unsigned char *p = stdmacpos;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700685 char *ret, *q;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700686 size_t len = 0;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700687 while ((c = *p++)) {
688 if (c >= 0x80)
689 len += pp_directives_len[c-0x80]+1;
690 else
691 len++;
692 }
693 ret = nasm_malloc(len+1);
H. Peter Anvincda81632008-06-21 15:15:40 -0700694 q = ret;
695 while ((c = *stdmacpos++)) {
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700696 if (c >= 0x80) {
697 memcpy(q, pp_directives[c-0x80], pp_directives_len[c-0x80]);
698 q += pp_directives_len[c-0x80];
699 *q++ = ' ';
700 } else {
701 *q++ = c;
702 }
703 }
H. Peter Anvincda81632008-06-21 15:15:40 -0700704 stdmacpos = p;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700705 *q = '\0';
706
H. Peter Anvind2456592008-06-19 15:04:18 -0700707 if (!*stdmacpos) {
708 /* This was the last of the standard macro chain... */
709 stdmacpos = NULL;
710 if (any_extrastdmac) {
711 stdmacpos = extrastdmac;
712 any_extrastdmac = false;
713 } else if (do_predef) {
714 Line *pd, *l;
715 Token *head, **tail, *t;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000716
H. Peter Anvind2456592008-06-19 15:04:18 -0700717 /*
718 * Nasty hack: here we push the contents of
719 * `predef' on to the top-level expansion stack,
720 * since this is the most convenient way to
721 * implement the pre-include and pre-define
722 * features.
723 */
724 for (pd = predef; pd; pd = pd->next) {
725 head = NULL;
726 tail = &head;
727 for (t = pd->first; t; t = t->next) {
728 *tail = new_Token(NULL, t->type, t->text, 0);
729 tail = &(*tail)->next;
730 }
731 l = nasm_malloc(sizeof(Line));
732 l->next = istk->expansion;
733 l->first = head;
H. Peter Anvin538002d2008-06-28 18:30:27 -0700734 l->finishes = NULL;
H. Peter Anvind2456592008-06-19 15:04:18 -0700735 istk->expansion = l;
736 }
737 do_predef = false;
738 }
739 }
740 return ret;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000741 }
742
743 bufsize = BUF_DELTA;
744 buffer = nasm_malloc(BUF_DELTA);
745 p = buffer;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000746 continued_count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000747 while (1) {
748 q = fgets(p, bufsize - (p - buffer), istk->fp);
749 if (!q)
750 break;
751 p += strlen(p);
752 if (p > buffer && p[-1] == '\n') {
753 /* Convert backslash-CRLF line continuation sequences into
754 nothing at all (for DOS and Windows) */
755 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
756 p -= 3;
757 *p = 0;
758 continued_count++;
759 }
760 /* Also convert backslash-LF line continuation sequences into
761 nothing at all (for Unix) */
762 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
763 p -= 2;
764 *p = 0;
765 continued_count++;
766 } else {
767 break;
768 }
769 }
770 if (p - buffer > bufsize - 10) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000771 int32_t offset = p - buffer;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000772 bufsize += BUF_DELTA;
773 buffer = nasm_realloc(buffer, bufsize);
774 p = buffer + offset; /* prevent stale-pointer problems */
775 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000776 }
777
H. Peter Anvine2c80182005-01-15 22:15:51 +0000778 if (!q && p == buffer) {
779 nasm_free(buffer);
780 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000781 }
782
H. Peter Anvine2c80182005-01-15 22:15:51 +0000783 src_set_linnum(src_get_linnum() + istk->lineinc +
784 (continued_count * istk->lineinc));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000785
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000786 /*
787 * Play safe: remove CRs as well as LFs, if any of either are
788 * present at the end of the line.
789 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000790 while (--p >= buffer && (*p == '\n' || *p == '\r'))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000791 *p = '\0';
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000792
793 /*
794 * Handle spurious ^Z, which may be inserted into source files
795 * by some file transfer utilities.
796 */
797 buffer[strcspn(buffer, "\032")] = '\0';
798
H. Peter Anvin734b1882002-04-30 21:01:08 +0000799 list->line(LIST_READ, buffer);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000800
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000801 return buffer;
802}
803
804/*
Keith Kaniosb7a89542007-04-12 02:40:54 +0000805 * Tokenize a line of text. This is a very simple process since we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000806 * don't need to parse the value out of e.g. numeric tokens: we
807 * simply split one string into many.
808 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000809static Token *tokenize(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000810{
H. Peter Anvinca544db2008-10-19 19:30:11 -0700811 char c, *p = line;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000812 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000813 Token *list = NULL;
814 Token *t, **tail = &list;
815
H. Peter Anvine2c80182005-01-15 22:15:51 +0000816 while (*line) {
817 p = line;
818 if (*p == '%') {
819 p++;
H. Peter Anvind784a082009-04-20 14:01:18 -0700820 if (*p == '+' && !nasm_isdigit(p[1])) {
821 p++;
822 type = TOK_PASTE;
823 } else if (nasm_isdigit(*p) ||
824 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000825 do {
826 p++;
827 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700828 while (nasm_isdigit(*p));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000829 type = TOK_PREPROC_ID;
830 } else if (*p == '{') {
831 p++;
832 while (*p && *p != '}') {
833 p[-1] = *p;
834 p++;
835 }
836 p[-1] = '\0';
837 if (*p)
838 p++;
839 type = TOK_PREPROC_ID;
H. Peter Anvin992fe752008-10-19 15:45:05 -0700840 } else if (*p == '[') {
841 int lvl = 1;
842 line += 2; /* Skip the leading %[ */
843 p++;
H. Peter Anvinec033012008-10-19 22:12:06 -0700844 while (lvl && (c = *p++)) {
H. Peter Anvinca544db2008-10-19 19:30:11 -0700845 switch (c) {
846 case ']':
847 lvl--;
848 break;
849 case '%':
H. Peter Anvinca544db2008-10-19 19:30:11 -0700850 if (*p == '[')
851 lvl++;
852 break;
853 case '\'':
854 case '\"':
855 case '`':
H. Peter Anvinec033012008-10-19 22:12:06 -0700856 p = nasm_skip_string(p)+1;
H. Peter Anvinca544db2008-10-19 19:30:11 -0700857 break;
858 default:
859 break;
H. Peter Anvin992fe752008-10-19 15:45:05 -0700860 }
H. Peter Anvin992fe752008-10-19 15:45:05 -0700861 }
H. Peter Anvinec033012008-10-19 22:12:06 -0700862 p--;
H. Peter Anvin992fe752008-10-19 15:45:05 -0700863 if (*p)
864 *p++ = '\0';
H. Peter Anvine1265812008-10-19 22:14:30 -0700865 if (lvl)
866 error(ERR_NONFATAL, "unterminated %[ construct");
H. Peter Anvin992fe752008-10-19 15:45:05 -0700867 type = TOK_INDIRECT;
H. Peter Anvin6c81f0a2008-05-25 21:46:17 -0700868 } else if (*p == '?') {
869 type = TOK_PREPROC_Q; /* %? */
870 p++;
871 if (*p == '?') {
872 type = TOK_PREPROC_QQ; /* %?? */
873 p++;
874 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000875 } else if (isidchar(*p) ||
876 ((*p == '!' || *p == '%' || *p == '$') &&
877 isidchar(p[1]))) {
878 do {
879 p++;
880 }
881 while (isidchar(*p));
882 type = TOK_PREPROC_ID;
883 } else {
884 type = TOK_OTHER;
885 if (*p == '%')
886 p++;
887 }
888 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
889 type = TOK_ID;
890 p++;
891 while (*p && isidchar(*p))
892 p++;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700893 } else if (*p == '\'' || *p == '"' || *p == '`') {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000894 /*
895 * A string token.
896 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000897 type = TOK_STRING;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700898 p = nasm_skip_string(p);
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000899
H. Peter Anvine2c80182005-01-15 22:15:51 +0000900 if (*p) {
901 p++;
902 } else {
H. Peter Anvin917a3492008-09-24 09:14:49 -0700903 error(ERR_WARNING|ERR_PASS1, "unterminated string");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000904 /* Handling unterminated strings by UNV */
905 /* type = -1; */
906 }
Victor van den Elzenfb5f2512009-04-17 16:17:59 +0200907 } else if (p[0] == '$' && p[1] == '$') {
H. Peter Anvin8e1f8112009-04-17 14:20:44 -0700908 type = TOK_OTHER; /* TOKEN_BASE */
Victor van den Elzenfb5f2512009-04-17 16:17:59 +0200909 p += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000910 } else if (isnumstart(*p)) {
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700911 bool is_hex = false;
912 bool is_float = false;
913 bool has_e = false;
914 char c, *r;
915
H. Peter Anvine2c80182005-01-15 22:15:51 +0000916 /*
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700917 * A numeric token.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000918 */
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700919
920 if (*p == '$') {
921 p++;
922 is_hex = true;
923 }
924
925 for (;;) {
926 c = *p++;
927
928 if (!is_hex && (c == 'e' || c == 'E')) {
929 has_e = true;
930 if (*p == '+' || *p == '-') {
931 /* e can only be followed by +/- if it is either a
932 prefixed hex number or a floating-point number */
933 p++;
934 is_float = true;
935 }
936 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
937 is_hex = true;
938 } else if (c == 'P' || c == 'p') {
939 is_float = true;
940 if (*p == '+' || *p == '-')
941 p++;
942 } else if (isnumchar(c) || c == '_')
943 ; /* just advance */
944 else if (c == '.') {
945 /* we need to deal with consequences of the legacy
946 parser, like "1.nolist" being two tokens
947 (TOK_NUMBER, TOK_ID) here; at least give it
948 a shot for now. In the future, we probably need
949 a flex-based scanner with proper pattern matching
950 to do it as well as it can be done. Nothing in
951 the world is going to help the person who wants
952 0x123.p16 interpreted as two tokens, though. */
953 r = p;
954 while (*r == '_')
955 r++;
956
H. Peter Anvinf221b9e2008-06-21 11:03:51 -0700957 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700958 (!is_hex && (*r == 'e' || *r == 'E')) ||
959 (*r == 'p' || *r == 'P')) {
960 p = r;
961 is_float = true;
962 } else
963 break; /* Terminate the token */
964 } else
965 break;
966 }
967 p--; /* Point to first character beyond number */
968
H. Peter Anvin8e1f8112009-04-17 14:20:44 -0700969 if (p == line+1 && *line == '$') {
970 type = TOK_OTHER; /* TOKEN_HERE */
971 } else {
972 if (has_e && !is_hex) {
973 /* 1e13 is floating-point, but 1e13h is not */
974 is_float = true;
975 }
H. Peter Anvind784a082009-04-20 14:01:18 -0700976
H. Peter Anvin8e1f8112009-04-17 14:20:44 -0700977 type = is_float ? TOK_FLOAT : TOK_NUMBER;
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700978 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700979 } else if (nasm_isspace(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000980 type = TOK_WHITESPACE;
981 p++;
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700982 while (*p && nasm_isspace(*p))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000983 p++;
984 /*
985 * Whitespace just before end-of-line is discarded by
986 * pretending it's a comment; whitespace just before a
987 * comment gets lumped into the comment.
988 */
989 if (!*p || *p == ';') {
990 type = TOK_COMMENT;
991 while (*p)
992 p++;
993 }
994 } else if (*p == ';') {
995 type = TOK_COMMENT;
996 while (*p)
997 p++;
998 } else {
999 /*
1000 * Anything else is an operator of some kind. We check
1001 * for all the double-character operators (>>, <<, //,
1002 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001003 * else is a single-character operator.
H. Peter Anvine2c80182005-01-15 22:15:51 +00001004 */
1005 type = TOK_OTHER;
1006 if ((p[0] == '>' && p[1] == '>') ||
1007 (p[0] == '<' && p[1] == '<') ||
1008 (p[0] == '/' && p[1] == '/') ||
1009 (p[0] == '<' && p[1] == '=') ||
1010 (p[0] == '>' && p[1] == '=') ||
1011 (p[0] == '=' && p[1] == '=') ||
1012 (p[0] == '!' && p[1] == '=') ||
1013 (p[0] == '<' && p[1] == '>') ||
1014 (p[0] == '&' && p[1] == '&') ||
1015 (p[0] == '|' && p[1] == '|') ||
1016 (p[0] == '^' && p[1] == '^')) {
1017 p++;
1018 }
1019 p++;
1020 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001021
H. Peter Anvine2c80182005-01-15 22:15:51 +00001022 /* Handling unterminated string by UNV */
1023 /*if (type == -1)
1024 {
1025 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1026 t->text[p-line] = *line;
1027 tail = &t->next;
1028 }
1029 else */
1030 if (type != TOK_COMMENT) {
1031 *tail = t = new_Token(NULL, type, line, p - line);
1032 tail = &t->next;
1033 }
1034 line = p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001035 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001036 return list;
1037}
1038
H. Peter Anvince616072002-04-30 21:02:23 +00001039/*
1040 * this function allocates a new managed block of memory and
H. Peter Anvin70653092007-10-19 14:42:29 -07001041 * returns a pointer to the block. The managed blocks are
H. Peter Anvince616072002-04-30 21:02:23 +00001042 * deleted only all at once by the delete_Blocks function.
1043 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001044static void *new_Block(size_t size)
H. Peter Anvince616072002-04-30 21:02:23 +00001045{
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001046 Blocks *b = &blocks;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001047
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001048 /* first, get to the end of the linked list */
1049 while (b->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001050 b = b->next;
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001051 /* now allocate the requested chunk */
1052 b->chunk = nasm_malloc(size);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001053
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001054 /* now allocate a new block for the next request */
1055 b->next = nasm_malloc(sizeof(Blocks));
1056 /* and initialize the contents of the new block */
1057 b->next->next = NULL;
1058 b->next->chunk = NULL;
1059 return b->chunk;
H. Peter Anvince616072002-04-30 21:02:23 +00001060}
1061
1062/*
1063 * this function deletes all managed blocks of memory
1064 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001065static void delete_Blocks(void)
H. Peter Anvince616072002-04-30 21:02:23 +00001066{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001067 Blocks *a, *b = &blocks;
H. Peter Anvince616072002-04-30 21:02:23 +00001068
H. Peter Anvin70653092007-10-19 14:42:29 -07001069 /*
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001070 * keep in mind that the first block, pointed to by blocks
H. Peter Anvin70653092007-10-19 14:42:29 -07001071 * is a static and not dynamically allocated, so we don't
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001072 * free it.
1073 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001074 while (b) {
1075 if (b->chunk)
1076 nasm_free(b->chunk);
1077 a = b;
1078 b = b->next;
1079 if (a != &blocks)
1080 nasm_free(a);
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001081 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001082}
H. Peter Anvin734b1882002-04-30 21:01:08 +00001083
1084/*
H. Peter Anvin70653092007-10-19 14:42:29 -07001085 * this function creates a new Token and passes a pointer to it
H. Peter Anvin734b1882002-04-30 21:01:08 +00001086 * back to the caller. It sets the type and text elements, and
H. Peter Anvinf26e0972008-07-01 21:26:27 -07001087 * also the a.mac and next elements to NULL.
H. Peter Anvin734b1882002-04-30 21:01:08 +00001088 */
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001089static Token *new_Token(Token * next, enum pp_token_type type,
H. Peter Anvinc751e862008-06-09 10:18:45 -07001090 const char *text, int txtlen)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001091{
1092 Token *t;
1093 int i;
1094
H. Peter Anvine2c80182005-01-15 22:15:51 +00001095 if (freeTokens == NULL) {
1096 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
1097 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
1098 freeTokens[i].next = &freeTokens[i + 1];
1099 freeTokens[i].next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001100 }
1101 t = freeTokens;
1102 freeTokens = t->next;
1103 t->next = next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07001104 t->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001105 t->type = type;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001106 if (type == TOK_WHITESPACE || text == NULL) {
1107 t->text = NULL;
1108 } else {
1109 if (txtlen == 0)
1110 txtlen = strlen(text);
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001111 t->text = nasm_malloc(txtlen+1);
1112 memcpy(t->text, text, txtlen);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001113 t->text[txtlen] = '\0';
H. Peter Anvin734b1882002-04-30 21:01:08 +00001114 }
1115 return t;
1116}
1117
H. Peter Anvine2c80182005-01-15 22:15:51 +00001118static Token *delete_Token(Token * t)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001119{
1120 Token *next = t->next;
1121 nasm_free(t->text);
H. Peter Anvin788e6c12002-04-30 21:02:01 +00001122 t->next = freeTokens;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001123 freeTokens = t;
1124 return next;
1125}
1126
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001127/*
1128 * Convert a line of tokens back into text.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001129 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1130 * will be transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001131 */
H. Peter Anvin9e200162008-06-04 17:23:14 -07001132static char *detoken(Token * tlist, bool expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001133{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001134 Token *t;
1135 int len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001136 char *line, *p;
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001137 const char *q;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001138
1139 len = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001140 for (t = tlist; t; t = t->next) {
1141 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001142 char *p = getenv(t->text + 2);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001143 nasm_free(t->text);
1144 if (p)
1145 t->text = nasm_strdup(p);
1146 else
1147 t->text = NULL;
1148 }
1149 /* Expand local macros here and not during preprocessing */
1150 if (expand_locals &&
1151 t->type == TOK_PREPROC_ID && t->text &&
1152 t->text[0] == '%' && t->text[1] == '$') {
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001153 const char *q;
1154 char *p;
1155 Context *ctx = get_ctx(t->text, &q, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001156 if (ctx) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001157 char buffer[40];
Keith Kanios93f2e9a2007-04-14 00:10:59 +00001158 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001159 p = nasm_strcat(buffer, q);
1160 nasm_free(t->text);
1161 t->text = p;
1162 }
1163 }
1164 if (t->type == TOK_WHITESPACE) {
1165 len++;
1166 } else if (t->text) {
1167 len += strlen(t->text);
1168 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001169 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001170 p = line = nasm_malloc(len + 1);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001171 for (t = tlist; t; t = t->next) {
1172 if (t->type == TOK_WHITESPACE) {
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001173 *p++ = ' ';
H. Peter Anvine2c80182005-01-15 22:15:51 +00001174 } else if (t->text) {
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001175 q = t->text;
1176 while (*q)
1177 *p++ = *q++;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001178 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001179 }
1180 *p = '\0';
1181 return line;
1182}
1183
1184/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001185 * A scanner, suitable for use by the expression evaluator, which
1186 * operates on a line of Tokens. Expects a pointer to a pointer to
1187 * the first token in the line to be passed in as its private_data
1188 * field.
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001189 *
1190 * FIX: This really needs to be unified with stdscan.
H. Peter Anvin76690a12002-04-30 20:52:49 +00001191 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001192static int ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001193{
H. Peter Anvin76690a12002-04-30 20:52:49 +00001194 Token **tlineptr = private_data;
1195 Token *tline;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001196 char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001197
H. Peter Anvine2c80182005-01-15 22:15:51 +00001198 do {
1199 tline = *tlineptr;
1200 *tlineptr = tline ? tline->next : NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001201 }
1202 while (tline && (tline->type == TOK_WHITESPACE ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001203 tline->type == TOK_COMMENT));
H. Peter Anvin76690a12002-04-30 20:52:49 +00001204
1205 if (!tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001206 return tokval->t_type = TOKEN_EOS;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001207
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001208 tokval->t_charptr = tline->text;
1209
H. Peter Anvin76690a12002-04-30 20:52:49 +00001210 if (tline->text[0] == '$' && !tline->text[1])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001211 return tokval->t_type = TOKEN_HERE;
H. Peter Anvin7cf897e2002-05-30 21:30:33 +00001212 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001213 return tokval->t_type = TOKEN_BASE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001214
H. Peter Anvine2c80182005-01-15 22:15:51 +00001215 if (tline->type == TOK_ID) {
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001216 p = tokval->t_charptr = tline->text;
1217 if (p[0] == '$') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001218 tokval->t_charptr++;
1219 return tokval->t_type = TOKEN_ID;
1220 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001221
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001222 for (r = p, s = ourcopy; *r; r++) {
Philipp Thomas76ec8e72008-05-21 08:53:21 -07001223 if (r >= p+MAX_KEYWORD)
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001224 return tokval->t_type = TOKEN_ID; /* Not a keyword */
H. Peter Anvinac8f8fc2008-06-11 15:49:41 -07001225 *s++ = nasm_tolower(*r);
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001226 }
1227 *s = '\0';
1228 /* right, so we have an identifier sitting in temp storage. now,
1229 * is it actually a register or instruction name, or what? */
1230 return nasm_token_hash(ourcopy, tokval);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001231 }
1232
H. Peter Anvine2c80182005-01-15 22:15:51 +00001233 if (tline->type == TOK_NUMBER) {
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001234 bool rn_error;
1235 tokval->t_integer = readnum(tline->text, &rn_error);
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001236 tokval->t_charptr = tline->text;
H. Peter Anvin11627042008-06-09 20:45:19 -07001237 if (rn_error)
1238 return tokval->t_type = TOKEN_ERRNUM;
1239 else
1240 return tokval->t_type = TOKEN_NUM;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001241 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001242
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001243 if (tline->type == TOK_FLOAT) {
1244 return tokval->t_type = TOKEN_FLOAT;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001245 }
1246
H. Peter Anvine2c80182005-01-15 22:15:51 +00001247 if (tline->type == TOK_STRING) {
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07001248 char bq, *ep;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001249
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07001250 bq = tline->text[0];
H. Peter Anvin11627042008-06-09 20:45:19 -07001251 tokval->t_charptr = tline->text;
1252 tokval->t_inttwo = nasm_unquote(tline->text, &ep);
H. Peter Anvind2456592008-06-19 15:04:18 -07001253
H. Peter Anvin11627042008-06-09 20:45:19 -07001254 if (ep[0] != bq || ep[1] != '\0')
1255 return tokval->t_type = TOKEN_ERRSTR;
1256 else
1257 return tokval->t_type = TOKEN_STR;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001258 }
1259
H. Peter Anvine2c80182005-01-15 22:15:51 +00001260 if (tline->type == TOK_OTHER) {
1261 if (!strcmp(tline->text, "<<"))
1262 return tokval->t_type = TOKEN_SHL;
1263 if (!strcmp(tline->text, ">>"))
1264 return tokval->t_type = TOKEN_SHR;
1265 if (!strcmp(tline->text, "//"))
1266 return tokval->t_type = TOKEN_SDIV;
1267 if (!strcmp(tline->text, "%%"))
1268 return tokval->t_type = TOKEN_SMOD;
1269 if (!strcmp(tline->text, "=="))
1270 return tokval->t_type = TOKEN_EQ;
1271 if (!strcmp(tline->text, "<>"))
1272 return tokval->t_type = TOKEN_NE;
1273 if (!strcmp(tline->text, "!="))
1274 return tokval->t_type = TOKEN_NE;
1275 if (!strcmp(tline->text, "<="))
1276 return tokval->t_type = TOKEN_LE;
1277 if (!strcmp(tline->text, ">="))
1278 return tokval->t_type = TOKEN_GE;
1279 if (!strcmp(tline->text, "&&"))
1280 return tokval->t_type = TOKEN_DBL_AND;
1281 if (!strcmp(tline->text, "^^"))
1282 return tokval->t_type = TOKEN_DBL_XOR;
1283 if (!strcmp(tline->text, "||"))
1284 return tokval->t_type = TOKEN_DBL_OR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001285 }
1286
1287 /*
1288 * We have no other options: just return the first character of
1289 * the token text.
1290 */
1291 return tokval->t_type = tline->text[0];
1292}
1293
1294/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001295 * Compare a string to the name of an existing macro; this is a
1296 * simple wrapper which calls either strcmp or nasm_stricmp
1297 * depending on the value of the `casesense' parameter.
1298 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001299static int mstrcmp(const char *p, const char *q, bool casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001300{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001301 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001302}
1303
1304/*
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001305 * Compare a string to the name of an existing macro; this is a
1306 * simple wrapper which calls either strcmp or nasm_stricmp
1307 * depending on the value of the `casesense' parameter.
1308 */
1309static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
1310{
1311 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
1312}
1313
1314/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001315 * Return the Context structure associated with a %$ token. Return
1316 * NULL, having _already_ reported an error condition, if the
1317 * context stack isn't deep enough for the supplied number of $
1318 * signs.
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001319 * If all_contexts == true, contexts that enclose current are
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001320 * also scanned for such smacro, until it is found; if not -
1321 * only the context that directly results from the number of $'s
1322 * in variable's name.
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001323 *
1324 * If "namep" is non-NULL, set it to the pointer to the macro name
1325 * tail, i.e. the part beyond %$...
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001326 */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001327static Context *get_ctx(const char *name, const char **namep,
1328 bool all_contexts)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001329{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001330 Context *ctx;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001331 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001332 int i;
1333
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001334 if (namep)
1335 *namep = name;
1336
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001337 if (!name || name[0] != '%' || name[1] != '$')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001338 return NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001339
H. Peter Anvine2c80182005-01-15 22:15:51 +00001340 if (!cstk) {
1341 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1342 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001343 }
1344
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001345 name += 2;
1346 ctx = cstk;
1347 i = 0;
1348 while (ctx && *name == '$') {
1349 name++;
1350 i++;
1351 ctx = ctx->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001352 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001353 if (!ctx) {
1354 error(ERR_NONFATAL, "`%s': context stack is only"
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001355 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001356 return NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001357 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001358
1359 if (namep)
1360 *namep = name;
1361
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001362 if (!all_contexts)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001363 return ctx;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001364
H. Peter Anvine2c80182005-01-15 22:15:51 +00001365 do {
1366 /* Search for this smacro in found context */
H. Peter Anvin166c2472008-05-28 12:28:58 -07001367 m = hash_findix(&ctx->localmac, name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001368 while (m) {
1369 if (!mstrcmp(m->name, name, m->casesense))
1370 return ctx;
1371 m = m->next;
1372 }
1373 ctx = ctx->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001374 }
1375 while (ctx);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001376 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001377}
1378
1379/*
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001380 * Check to see if a file is already in a string list
1381 */
1382static bool in_list(const StrList *list, const char *str)
1383{
1384 while (list) {
1385 if (!strcmp(list->str, str))
1386 return true;
1387 list = list->next;
1388 }
1389 return false;
1390}
1391
1392/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001393 * Open an include file. This routine must always return a valid
1394 * file pointer if it returns - it's responsible for throwing an
1395 * ERR_FATAL and bombing out completely if not. It should also try
1396 * the include path one by one until it finds the file or reaches
1397 * the end of the path.
1398 */
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07001399static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
H. Peter Anvin418ca702008-05-30 10:42:30 -07001400 bool missing_ok)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001401{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001402 FILE *fp;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001403 char *prefix = "";
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001404 IncPath *ip = ipath;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001405 int len = strlen(file);
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001406 size_t prefix_len = 0;
1407 StrList *sl;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001408
H. Peter Anvine2c80182005-01-15 22:15:51 +00001409 while (1) {
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001410 sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
1411 memcpy(sl->str, prefix, prefix_len);
1412 memcpy(sl->str+prefix_len, file, len+1);
1413 fp = fopen(sl->str, "r");
H. Peter Anvin418ca702008-05-30 10:42:30 -07001414 if (fp && dhead && !in_list(*dhead, sl->str)) {
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001415 sl->next = NULL;
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07001416 **dtail = sl;
1417 *dtail = &sl->next;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001418 } else {
1419 nasm_free(sl);
1420 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001421 if (fp)
1422 return fp;
H. Peter Anvin418ca702008-05-30 10:42:30 -07001423 if (!ip) {
1424 if (!missing_ok)
1425 break;
1426 prefix = NULL;
1427 } else {
1428 prefix = ip->path;
1429 ip = ip->next;
1430 }
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001431 if (prefix) {
1432 prefix_len = strlen(prefix);
1433 } else {
1434 /* -MG given and file not found */
H. Peter Anvin418ca702008-05-30 10:42:30 -07001435 if (dhead && !in_list(*dhead, file)) {
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001436 sl = nasm_malloc(len+1+sizeof sl->next);
1437 sl->next = NULL;
1438 strcpy(sl->str, file);
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07001439 **dtail = sl;
1440 *dtail = &sl->next;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001441 }
H. Peter Anvin37a321f2007-09-24 13:41:58 -07001442 return NULL;
1443 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001444 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001445
H. Peter Anvin734b1882002-04-30 21:01:08 +00001446 error(ERR_FATAL, "unable to open include file `%s'", file);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001447 return NULL; /* never reached - placate compilers */
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001448}
1449
1450/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001451 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001452 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001453 * return true if _any_ single-line macro of that name is defined.
1454 * Otherwise, will return true if a single-line macro with either
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001455 * `nparam' or no parameters is defined.
1456 *
1457 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001458 * defined, or nparam is -1, the address of the definition structure
1459 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001460 * is NULL, no action will be taken regarding its contents, and no
1461 * error will occur.
1462 *
1463 * Note that this is also called with nparam zero to resolve
1464 * `ifdef'.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001465 *
1466 * If you already know which context macro belongs to, you can pass
1467 * the context pointer as first parameter; if you won't but name begins
1468 * with %$ the context will be automatically computed. If all_contexts
1469 * is true, macro will be searched in outer contexts as well.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001470 */
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001471static bool
H. Peter Anvinb2a5fda2008-06-19 21:42:42 -07001472smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001473 bool nocase)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001474{
H. Peter Anvin166c2472008-05-28 12:28:58 -07001475 struct hash_table *smtbl;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001476 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001477
H. Peter Anvin97a23472007-09-16 17:57:25 -07001478 if (ctx) {
H. Peter Anvin166c2472008-05-28 12:28:58 -07001479 smtbl = &ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001480 } else if (name[0] == '%' && name[1] == '$') {
1481 if (cstk)
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001482 ctx = get_ctx(name, &name, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001483 if (!ctx)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001484 return false; /* got to return _something_ */
H. Peter Anvin166c2472008-05-28 12:28:58 -07001485 smtbl = &ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001486 } else {
H. Peter Anvin166c2472008-05-28 12:28:58 -07001487 smtbl = &smacros;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001488 }
H. Peter Anvin166c2472008-05-28 12:28:58 -07001489 m = (SMacro *) hash_findix(smtbl, name);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001490
H. Peter Anvine2c80182005-01-15 22:15:51 +00001491 while (m) {
1492 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
Charles Crayne192d5b52007-10-18 19:02:42 -07001493 (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001494 if (defn) {
Charles Crayne192d5b52007-10-18 19:02:42 -07001495 if (nparam == (int) m->nparam || nparam == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001496 *defn = m;
1497 else
1498 *defn = NULL;
1499 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001500 return true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001501 }
1502 m = m->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001503 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001504
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001505 return false;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001506}
1507
1508/*
1509 * Count and mark off the parameters in a multi-line macro call.
1510 * This is called both from within the multi-line macro expansion
1511 * code, and also to mark off the default parameters when provided
1512 * in a %macro definition line.
1513 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001514static void count_mmac_params(Token * t, int *nparam, Token *** params)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001515{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001516 int paramsize, brace;
1517
1518 *nparam = paramsize = 0;
1519 *params = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001520 while (t) {
H. Peter Anvin91fb6f12008-09-01 10:56:33 -07001521 /* +1: we need space for the final NULL */
1522 if (*nparam+1 >= paramsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001523 paramsize += PARAM_DELTA;
1524 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1525 }
1526 skip_white_(t);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001527 brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001528 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001529 brace = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001530 (*params)[(*nparam)++] = t;
1531 while (tok_isnt_(t, brace ? "}" : ","))
1532 t = t->next;
1533 if (t) { /* got a comma/brace */
1534 t = t->next;
1535 if (brace) {
1536 /*
1537 * Now we've found the closing brace, look further
1538 * for the comma.
1539 */
1540 skip_white_(t);
1541 if (tok_isnt_(t, ",")) {
1542 error(ERR_NONFATAL,
1543 "braces do not enclose all of macro parameter");
1544 while (tok_isnt_(t, ","))
1545 t = t->next;
1546 }
1547 if (t)
1548 t = t->next; /* eat the comma */
1549 }
1550 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001551 }
1552}
1553
1554/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001555 * Determine whether one of the various `if' conditions is true or
1556 * not.
1557 *
1558 * We must free the tline we get passed.
1559 */
H. Peter Anvin70055962007-10-11 00:05:31 -07001560static bool if_condition(Token * tline, enum preproc_token ct)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001561{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001562 enum pp_conditional i = PP_COND(ct);
H. Peter Anvin70055962007-10-11 00:05:31 -07001563 bool j;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001564 Token *t, *tt, **tptr, *origline;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001565 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001566 expr *evalresult;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001567 enum pp_token_type needtype;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001568
1569 origline = tline;
1570
H. Peter Anvine2c80182005-01-15 22:15:51 +00001571 switch (i) {
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001572 case PPC_IFCTX:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001573 j = false; /* have we matched yet? */
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001574 while (true) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001575 skip_white_(tline);
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001576 if (!tline)
1577 break;
1578 if (tline->type != TOK_ID) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001579 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001580 "`%s' expects context identifiers", pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001581 free_tlist(origline);
1582 return -1;
1583 }
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001584 if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001585 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001586 tline = tline->next;
1587 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001588 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001589
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001590 case PPC_IFDEF:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001591 j = false; /* have we matched yet? */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001592 while (tline) {
1593 skip_white_(tline);
1594 if (!tline || (tline->type != TOK_ID &&
1595 (tline->type != TOK_PREPROC_ID ||
1596 tline->text[1] != '$'))) {
1597 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001598 "`%s' expects macro identifiers", pp_directives[ct]);
1599 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001600 }
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001601 if (smacro_defined(NULL, tline->text, 0, NULL, true))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001602 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001603 tline = tline->next;
1604 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001605 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001606
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001607 case PPC_IFIDN:
1608 case PPC_IFIDNI:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001609 tline = expand_smacro(tline);
1610 t = tt = tline;
1611 while (tok_isnt_(tt, ","))
1612 tt = tt->next;
1613 if (!tt) {
1614 error(ERR_NONFATAL,
1615 "`%s' expects two comma-separated arguments",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001616 pp_directives[ct]);
1617 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001618 }
1619 tt = tt->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001620 j = true; /* assume equality unless proved not */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001621 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1622 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1623 error(ERR_NONFATAL, "`%s': more than one comma on line",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001624 pp_directives[ct]);
1625 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001626 }
1627 if (t->type == TOK_WHITESPACE) {
1628 t = t->next;
1629 continue;
1630 }
1631 if (tt->type == TOK_WHITESPACE) {
1632 tt = tt->next;
1633 continue;
1634 }
1635 if (tt->type != t->type) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001636 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001637 break;
1638 }
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001639 /* When comparing strings, need to unquote them first */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001640 if (t->type == TOK_STRING) {
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07001641 size_t l1 = nasm_unquote(t->text, NULL);
1642 size_t l2 = nasm_unquote(tt->text, NULL);
H. Peter Anvind2456592008-06-19 15:04:18 -07001643
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001644 if (l1 != l2) {
1645 j = false;
1646 break;
1647 }
1648 if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
1649 j = false;
1650 break;
1651 }
1652 } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001653 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001654 break;
1655 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001656
H. Peter Anvine2c80182005-01-15 22:15:51 +00001657 t = t->next;
1658 tt = tt->next;
1659 }
1660 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001661 j = false; /* trailing gunk on one end or other */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001662 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001663
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001664 case PPC_IFMACRO:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001665 {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001666 bool found = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001667 MMacro searching, *mmac;
H. Peter Anvin65747262002-05-07 00:10:05 +00001668
H. Peter Anvine2c80182005-01-15 22:15:51 +00001669 skip_white_(tline);
1670 tline = expand_id(tline);
1671 if (!tok_type_(tline, TOK_ID)) {
1672 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001673 "`%s' expects a macro name", pp_directives[ct]);
1674 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001675 }
1676 searching.name = nasm_strdup(tline->text);
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001677 searching.casesense = true;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001678 searching.plus = false;
1679 searching.nolist = false;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07001680 searching.in_progress = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001681 searching.rep_nest = NULL;
1682 searching.nparam_min = 0;
1683 searching.nparam_max = INT_MAX;
1684 tline = expand_smacro(tline->next);
1685 skip_white_(tline);
1686 if (!tline) {
1687 } else if (!tok_type_(tline, TOK_NUMBER)) {
1688 error(ERR_NONFATAL,
1689 "`%s' expects a parameter count or nothing",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001690 pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001691 } else {
1692 searching.nparam_min = searching.nparam_max =
1693 readnum(tline->text, &j);
1694 if (j)
1695 error(ERR_NONFATAL,
1696 "unable to parse parameter count `%s'",
1697 tline->text);
1698 }
1699 if (tline && tok_is_(tline->next, "-")) {
1700 tline = tline->next->next;
1701 if (tok_is_(tline, "*"))
1702 searching.nparam_max = INT_MAX;
1703 else if (!tok_type_(tline, TOK_NUMBER))
1704 error(ERR_NONFATAL,
1705 "`%s' expects a parameter count after `-'",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001706 pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001707 else {
1708 searching.nparam_max = readnum(tline->text, &j);
1709 if (j)
1710 error(ERR_NONFATAL,
1711 "unable to parse parameter count `%s'",
1712 tline->text);
1713 if (searching.nparam_min > searching.nparam_max)
1714 error(ERR_NONFATAL,
1715 "minimum parameter count exceeds maximum");
1716 }
1717 }
1718 if (tline && tok_is_(tline->next, "+")) {
1719 tline = tline->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001720 searching.plus = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001721 }
H. Peter Anvin166c2472008-05-28 12:28:58 -07001722 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
H. Peter Anvin97a23472007-09-16 17:57:25 -07001723 while (mmac) {
1724 if (!strcmp(mmac->name, searching.name) &&
1725 (mmac->nparam_min <= searching.nparam_max
1726 || searching.plus)
1727 && (searching.nparam_min <= mmac->nparam_max
1728 || mmac->plus)) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001729 found = true;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001730 break;
1731 }
1732 mmac = mmac->next;
1733 }
Victor van den Elzenb916ede2008-07-23 15:14:22 +02001734 if(tline && tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07001735 error(ERR_WARNING|ERR_PASS1,
1736 "trailing garbage after %%ifmacro ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001737 nasm_free(searching.name);
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001738 j = found;
1739 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001740 }
H. Peter Anvin65747262002-05-07 00:10:05 +00001741
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001742 case PPC_IFID:
1743 needtype = TOK_ID;
1744 goto iftype;
1745 case PPC_IFNUM:
1746 needtype = TOK_NUMBER;
1747 goto iftype;
1748 case PPC_IFSTR:
1749 needtype = TOK_STRING;
1750 goto iftype;
1751
1752 iftype:
H. Peter Anvin134b9462008-02-16 17:01:40 -08001753 t = tline = expand_smacro(tline);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001754
H. Peter Anvin927c92b2008-02-16 13:44:52 -08001755 while (tok_type_(t, TOK_WHITESPACE) ||
1756 (needtype == TOK_NUMBER &&
1757 tok_type_(t, TOK_OTHER) &&
1758 (t->text[0] == '-' || t->text[0] == '+') &&
1759 !t->text[1]))
1760 t = t->next;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001761
H. Peter Anvincbf768d2008-02-16 16:41:25 -08001762 j = tok_type_(t, needtype);
1763 break;
1764
1765 case PPC_IFTOKEN:
1766 t = tline = expand_smacro(tline);
1767 while (tok_type_(t, TOK_WHITESPACE))
1768 t = t->next;
1769
1770 j = false;
1771 if (t) {
1772 t = t->next; /* Skip the actual token */
1773 while (tok_type_(t, TOK_WHITESPACE))
1774 t = t->next;
1775 j = !t; /* Should be nothing left */
1776 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001777 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001778
H. Peter Anvin134b9462008-02-16 17:01:40 -08001779 case PPC_IFEMPTY:
1780 t = tline = expand_smacro(tline);
1781 while (tok_type_(t, TOK_WHITESPACE))
1782 t = t->next;
1783
1784 j = !t; /* Should be empty */
1785 break;
1786
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001787 case PPC_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001788 t = tline = expand_smacro(tline);
1789 tptr = &t;
1790 tokval.t_type = TOKEN_INVALID;
1791 evalresult = evaluate(ppscan, tptr, &tokval,
1792 NULL, pass | CRITICAL, error, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001793 if (!evalresult)
1794 return -1;
1795 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07001796 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001797 "trailing garbage after expression ignored");
1798 if (!is_simple(evalresult)) {
1799 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001800 "non-constant value given to `%s'", pp_directives[ct]);
1801 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001802 }
Chuck Crayne60ae75d2007-05-02 01:59:16 +00001803 j = reloc_value(evalresult) != 0;
H. Peter Anvin90e6e812008-07-16 14:38:24 -07001804 break;
H. Peter Anvin95e28822007-09-12 04:20:08 +00001805
H. Peter Anvine2c80182005-01-15 22:15:51 +00001806 default:
1807 error(ERR_FATAL,
1808 "preprocessor directive `%s' not yet implemented",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001809 pp_directives[ct]);
1810 goto fail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001811 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001812
1813 free_tlist(origline);
1814 return j ^ PP_NEGATIVE(ct);
H. Peter Anvin70653092007-10-19 14:42:29 -07001815
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001816fail:
1817 free_tlist(origline);
1818 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001819}
1820
1821/*
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001822 * Common code for defining an smacro
1823 */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001824static bool define_smacro(Context *ctx, const char *mname, bool casesense,
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001825 int nparam, Token *expansion)
1826{
1827 SMacro *smac, **smhead;
H. Peter Anvin166c2472008-05-28 12:28:58 -07001828 struct hash_table *smtbl;
H. Peter Anvin70653092007-10-19 14:42:29 -07001829
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001830 if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
1831 if (!smac) {
H. Peter Anvin917a3492008-09-24 09:14:49 -07001832 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001833 "single-line macro `%s' defined both with and"
1834 " without parameters", mname);
1835
1836 /* Some instances of the old code considered this a failure,
1837 some others didn't. What is the right thing to do here? */
1838 free_tlist(expansion);
1839 return false; /* Failure */
1840 } else {
1841 /*
1842 * We're redefining, so we have to take over an
1843 * existing SMacro structure. This means freeing
1844 * what was already in it.
1845 */
1846 nasm_free(smac->name);
1847 free_tlist(smac->expansion);
1848 }
1849 } else {
H. Peter Anvin166c2472008-05-28 12:28:58 -07001850 smtbl = ctx ? &ctx->localmac : &smacros;
1851 smhead = (SMacro **) hash_findi_add(smtbl, mname);
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001852 smac = nasm_malloc(sizeof(SMacro));
1853 smac->next = *smhead;
1854 *smhead = smac;
1855 }
1856 smac->name = nasm_strdup(mname);
1857 smac->casesense = casesense;
1858 smac->nparam = nparam;
1859 smac->expansion = expansion;
1860 smac->in_progress = false;
1861 return true; /* Success */
1862}
1863
1864/*
1865 * Undefine an smacro
1866 */
1867static void undef_smacro(Context *ctx, const char *mname)
1868{
1869 SMacro **smhead, *s, **sp;
H. Peter Anvin166c2472008-05-28 12:28:58 -07001870 struct hash_table *smtbl;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001871
H. Peter Anvin166c2472008-05-28 12:28:58 -07001872 smtbl = ctx ? &ctx->localmac : &smacros;
1873 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
H. Peter Anvin70653092007-10-19 14:42:29 -07001874
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001875 if (smhead) {
1876 /*
1877 * We now have a macro name... go hunt for it.
1878 */
1879 sp = smhead;
1880 while ((s = *sp) != NULL) {
1881 if (!mstrcmp(s->name, mname, s->casesense)) {
1882 *sp = s->next;
1883 nasm_free(s->name);
1884 free_tlist(s->expansion);
1885 nasm_free(s);
1886 } else {
1887 sp = &s->next;
1888 }
1889 }
1890 }
1891}
1892
H. Peter Anvin8781cb02007-11-08 20:01:11 -08001893/*
H. Peter Anvina26433d2008-07-16 14:40:01 -07001894 * Parse a mmacro specification.
1895 */
1896static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
1897{
1898 bool err;
1899
1900 tline = tline->next;
1901 skip_white_(tline);
1902 tline = expand_id(tline);
1903 if (!tok_type_(tline, TOK_ID)) {
1904 error(ERR_NONFATAL, "`%s' expects a macro name", directive);
1905 return false;
1906 }
Victor van den Elzenb916ede2008-07-23 15:14:22 +02001907
H. Peter Anvina26433d2008-07-16 14:40:01 -07001908 def->name = nasm_strdup(tline->text);
1909 def->plus = false;
1910 def->nolist = false;
1911 def->in_progress = 0;
1912 def->rep_nest = NULL;
Victor van den Elzenb916ede2008-07-23 15:14:22 +02001913 def->nparam_min = 0;
1914 def->nparam_max = 0;
1915
H. Peter Anvina26433d2008-07-16 14:40:01 -07001916 tline = expand_smacro(tline->next);
1917 skip_white_(tline);
1918 if (!tok_type_(tline, TOK_NUMBER)) {
1919 error(ERR_NONFATAL, "`%s' expects a parameter count", directive);
H. Peter Anvina26433d2008-07-16 14:40:01 -07001920 } else {
1921 def->nparam_min = def->nparam_max =
1922 readnum(tline->text, &err);
1923 if (err)
1924 error(ERR_NONFATAL,
1925 "unable to parse parameter count `%s'", tline->text);
1926 }
1927 if (tline && tok_is_(tline->next, "-")) {
1928 tline = tline->next->next;
1929 if (tok_is_(tline, "*")) {
1930 def->nparam_max = INT_MAX;
1931 } else if (!tok_type_(tline, TOK_NUMBER)) {
1932 error(ERR_NONFATAL,
1933 "`%s' expects a parameter count after `-'", directive);
1934 } else {
1935 def->nparam_max = readnum(tline->text, &err);
1936 if (err) {
1937 error(ERR_NONFATAL, "unable to parse parameter count `%s'",
1938 tline->text);
1939 }
1940 if (def->nparam_min > def->nparam_max) {
1941 error(ERR_NONFATAL, "minimum parameter count exceeds maximum");
1942 }
1943 }
1944 }
1945 if (tline && tok_is_(tline->next, "+")) {
1946 tline = tline->next;
1947 def->plus = true;
1948 }
1949 if (tline && tok_type_(tline->next, TOK_ID) &&
1950 !nasm_stricmp(tline->next->text, ".nolist")) {
1951 tline = tline->next;
1952 def->nolist = true;
1953 }
1954
1955 /*
1956 * Handle default parameters.
1957 */
1958 if (tline && tline->next) {
1959 def->dlist = tline->next;
1960 tline->next = NULL;
1961 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
1962 } else {
1963 def->dlist = NULL;
1964 def->defaults = NULL;
1965 }
1966 def->expansion = NULL;
1967
Victor van den Elzen22343c22008-08-06 14:47:54 +02001968 if(def->defaults &&
1969 def->ndefs > def->nparam_max - def->nparam_min &&
1970 !def->plus)
H. Peter Anvin917a3492008-09-24 09:14:49 -07001971 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MDP,
1972 "too many default macro parameters");
Victor van den Elzenb916ede2008-07-23 15:14:22 +02001973
H. Peter Anvina26433d2008-07-16 14:40:01 -07001974 return true;
1975}
1976
1977
1978/*
H. Peter Anvin8781cb02007-11-08 20:01:11 -08001979 * Decode a size directive
1980 */
1981static int parse_size(const char *str) {
1982 static const char *size_names[] =
H. Peter Anvindfb91802008-05-20 11:43:53 -07001983 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
H. Peter Anvin8781cb02007-11-08 20:01:11 -08001984 static const int sizes[] =
H. Peter Anvindfb91802008-05-20 11:43:53 -07001985 { 0, 1, 4, 16, 8, 10, 2, 32 };
H. Peter Anvin8781cb02007-11-08 20:01:11 -08001986
1987 return sizes[bsii(str, size_names, elements(size_names))+1];
1988}
1989
Ed Beroset3ab3f412002-06-11 03:31:49 +00001990/**
1991 * find and process preprocessor directive in passed line
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001992 * Find out if a line contains a preprocessor directive, and deal
1993 * with it if so.
H. Peter Anvin70653092007-10-19 14:42:29 -07001994 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00001995 * If a directive _is_ found, it is the responsibility of this routine
1996 * (and not the caller) to free_tlist() the line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001997 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00001998 * @param tline a pointer to the current tokeninzed line linked list
1999 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
H. Peter Anvin70653092007-10-19 14:42:29 -07002000 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002001 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002002static int do_directive(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002003{
H. Peter Anvin4169a472007-09-12 01:29:43 +00002004 enum preproc_token i;
2005 int j;
H. Peter Anvin70055962007-10-11 00:05:31 -07002006 bool err;
2007 int nparam;
2008 bool nolist;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002009 bool casesense;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -07002010 int k, m;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002011 int offset;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002012 char *p, *pp;
2013 const char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002014 Include *inc;
2015 Context *ctx;
2016 Cond *cond;
H. Peter Anvin97a23472007-09-16 17:57:25 -07002017 MMacro *mmac, **mmhead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002018 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
2019 Line *l;
2020 struct tokenval tokval;
2021 expr *evalresult;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002022 MMacro *tmp_defining; /* Used when manipulating rep_nest */
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002023 int64_t count;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07002024 size_t len;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002025 int severity;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002026
2027 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002028
H. Peter Anvineba20a72002-04-30 20:53:55 +00002029 skip_white_(tline);
H. Peter Anvinf2936d72008-06-04 15:11:23 -07002030 if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00002031 (tline->text[1] == '%' || tline->text[1] == '$'
2032 || tline->text[1] == '!'))
2033 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002034
H. Peter Anvin4169a472007-09-12 01:29:43 +00002035 i = pp_token_hash(tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002036
2037 /*
2038 * If we're in a non-emitting branch of a condition construct,
H. Peter Anvin76690a12002-04-30 20:52:49 +00002039 * or walking to the end of an already terminated %rep block,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002040 * we should ignore all directives except for condition
2041 * directives.
2042 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00002043 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00002044 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
2045 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002046 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002047
2048 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002049 * If we're defining a macro or reading a %rep block, we should
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02002050 * ignore all directives except for %macro/%imacro (which nest),
2051 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2052 * If we're in a %rep block, another %rep nests, so should be let through.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002053 */
2054 if (defining && i != PP_MACRO && i != PP_IMACRO &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00002055 i != PP_ENDMACRO && i != PP_ENDM &&
2056 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
2057 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002058 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002059
Charles Crayned4200be2008-07-12 16:42:33 -07002060 if (defining) {
2061 if (i == PP_MACRO || i == PP_IMACRO) {
2062 nested_mac_count++;
2063 return NO_DIRECTIVE_FOUND;
2064 } else if (nested_mac_count > 0) {
2065 if (i == PP_ENDMACRO) {
2066 nested_mac_count--;
2067 return NO_DIRECTIVE_FOUND;
2068 }
2069 }
2070 if (!defining->name) {
2071 if (i == PP_REP) {
2072 nested_rep_count++;
2073 return NO_DIRECTIVE_FOUND;
2074 } else if (nested_rep_count > 0) {
2075 if (i == PP_ENDREP) {
2076 nested_rep_count--;
2077 return NO_DIRECTIVE_FOUND;
2078 }
2079 }
2080 }
2081 }
2082
H. Peter Anvin4169a472007-09-12 01:29:43 +00002083 switch (i) {
2084 case PP_INVALID:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002085 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2086 tline->text);
2087 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002088
H. Peter Anvine2c80182005-01-15 22:15:51 +00002089 case PP_STACKSIZE:
2090 /* Directive to tell NASM what the default stack size is. The
2091 * default is for a 16-bit stack, and this can be overriden with
2092 * %stacksize large.
2093 * the following form:
2094 *
2095 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2096 */
2097 tline = tline->next;
2098 if (tline && tline->type == TOK_WHITESPACE)
2099 tline = tline->next;
2100 if (!tline || tline->type != TOK_ID) {
2101 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
2102 free_tlist(origline);
2103 return DIRECTIVE_FOUND;
2104 }
2105 if (nasm_stricmp(tline->text, "flat") == 0) {
2106 /* All subsequent ARG directives are for a 32-bit stack */
2107 StackSize = 4;
2108 StackPointer = "ebp";
2109 ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002110 LocalOffset = 0;
Charles Crayne7eaf9192007-11-08 22:11:14 -08002111 } else if (nasm_stricmp(tline->text, "flat64") == 0) {
2112 /* All subsequent ARG directives are for a 64-bit stack */
2113 StackSize = 8;
2114 StackPointer = "rbp";
2115 ArgOffset = 8;
2116 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002117 } else if (nasm_stricmp(tline->text, "large") == 0) {
2118 /* All subsequent ARG directives are for a 16-bit stack,
2119 * far function call.
2120 */
2121 StackSize = 2;
2122 StackPointer = "bp";
2123 ArgOffset = 4;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002124 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002125 } else if (nasm_stricmp(tline->text, "small") == 0) {
2126 /* All subsequent ARG directives are for a 16-bit stack,
2127 * far function call. We don't support near functions.
2128 */
2129 StackSize = 2;
2130 StackPointer = "bp";
2131 ArgOffset = 6;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002132 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002133 } else {
2134 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
2135 free_tlist(origline);
2136 return DIRECTIVE_FOUND;
2137 }
2138 free_tlist(origline);
2139 return DIRECTIVE_FOUND;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002140
H. Peter Anvine2c80182005-01-15 22:15:51 +00002141 case PP_ARG:
2142 /* TASM like ARG directive to define arguments to functions, in
2143 * the following form:
2144 *
2145 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2146 */
2147 offset = ArgOffset;
2148 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002149 char *arg, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00002150 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002151
H. Peter Anvine2c80182005-01-15 22:15:51 +00002152 /* Find the argument name */
2153 tline = tline->next;
2154 if (tline && tline->type == TOK_WHITESPACE)
2155 tline = tline->next;
2156 if (!tline || tline->type != TOK_ID) {
2157 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
2158 free_tlist(origline);
2159 return DIRECTIVE_FOUND;
2160 }
2161 arg = tline->text;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002162
H. Peter Anvine2c80182005-01-15 22:15:51 +00002163 /* Find the argument size type */
2164 tline = tline->next;
2165 if (!tline || tline->type != TOK_OTHER
2166 || tline->text[0] != ':') {
2167 error(ERR_NONFATAL,
2168 "Syntax error processing `%%arg' directive");
2169 free_tlist(origline);
2170 return DIRECTIVE_FOUND;
2171 }
2172 tline = tline->next;
2173 if (!tline || tline->type != TOK_ID) {
2174 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
2175 free_tlist(origline);
2176 return DIRECTIVE_FOUND;
2177 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002178
H. Peter Anvine2c80182005-01-15 22:15:51 +00002179 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002180 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002181 tt = expand_smacro(tt);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002182 size = parse_size(tt->text);
2183 if (!size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002184 error(ERR_NONFATAL,
2185 "Invalid size type for `%%arg' missing directive");
2186 free_tlist(tt);
2187 free_tlist(origline);
2188 return DIRECTIVE_FOUND;
2189 }
2190 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002191
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002192 /* Round up to even stack slots */
2193 size = (size+StackSize-1) & ~(StackSize-1);
2194
H. Peter Anvine2c80182005-01-15 22:15:51 +00002195 /* Now define the macro for the argument */
2196 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
2197 arg, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002198 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00002199 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002200
H. Peter Anvine2c80182005-01-15 22:15:51 +00002201 /* Move to the next argument in the list */
2202 tline = tline->next;
2203 if (tline && tline->type == TOK_WHITESPACE)
2204 tline = tline->next;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002205 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2206 ArgOffset = offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002207 free_tlist(origline);
2208 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002209
H. Peter Anvine2c80182005-01-15 22:15:51 +00002210 case PP_LOCAL:
2211 /* TASM like LOCAL directive to define local variables for a
2212 * function, in the following form:
2213 *
2214 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2215 *
2216 * The '= LocalSize' at the end is ignored by NASM, but is
2217 * required by TASM to define the local parameter size (and used
2218 * by the TASM macro package).
2219 */
2220 offset = LocalOffset;
2221 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002222 char *local, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00002223 int size = StackSize;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002224
H. Peter Anvine2c80182005-01-15 22:15:51 +00002225 /* Find the argument name */
2226 tline = tline->next;
2227 if (tline && tline->type == TOK_WHITESPACE)
2228 tline = tline->next;
2229 if (!tline || tline->type != TOK_ID) {
2230 error(ERR_NONFATAL,
2231 "`%%local' missing argument parameter");
2232 free_tlist(origline);
2233 return DIRECTIVE_FOUND;
2234 }
2235 local = tline->text;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002236
H. Peter Anvine2c80182005-01-15 22:15:51 +00002237 /* Find the argument size type */
2238 tline = tline->next;
2239 if (!tline || tline->type != TOK_OTHER
2240 || tline->text[0] != ':') {
2241 error(ERR_NONFATAL,
2242 "Syntax error processing `%%local' directive");
2243 free_tlist(origline);
2244 return DIRECTIVE_FOUND;
2245 }
2246 tline = tline->next;
2247 if (!tline || tline->type != TOK_ID) {
2248 error(ERR_NONFATAL,
2249 "`%%local' missing size type parameter");
2250 free_tlist(origline);
2251 return DIRECTIVE_FOUND;
2252 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002253
H. Peter Anvine2c80182005-01-15 22:15:51 +00002254 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002255 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002256 tt = expand_smacro(tt);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002257 size = parse_size(tt->text);
2258 if (!size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002259 error(ERR_NONFATAL,
2260 "Invalid size type for `%%local' missing directive");
2261 free_tlist(tt);
2262 free_tlist(origline);
2263 return DIRECTIVE_FOUND;
2264 }
2265 free_tlist(tt);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002266
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002267 /* Round up to even stack slots */
2268 size = (size+StackSize-1) & ~(StackSize-1);
2269
2270 offset += size; /* Negative offset, increment before */
2271
2272 /* Now define the macro for the argument */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002273 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
2274 local, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002275 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002276
H. Peter Anvine2c80182005-01-15 22:15:51 +00002277 /* Now define the assign to setup the enter_c macro correctly */
2278 snprintf(directive, sizeof(directive),
2279 "%%assign %%$localsize %%$localsize+%d", size);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002280 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002281
H. Peter Anvine2c80182005-01-15 22:15:51 +00002282 /* Move to the next argument in the list */
2283 tline = tline->next;
2284 if (tline && tline->type == TOK_WHITESPACE)
2285 tline = tline->next;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002286 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2287 LocalOffset = offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002288 free_tlist(origline);
2289 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002290
H. Peter Anvine2c80182005-01-15 22:15:51 +00002291 case PP_CLEAR:
2292 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002293 error(ERR_WARNING|ERR_PASS1,
2294 "trailing garbage after `%%clear' ignored");
H. Peter Anvin97a23472007-09-16 17:57:25 -07002295 free_macros();
2296 init_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00002297 free_tlist(origline);
2298 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002299
H. Peter Anvin418ca702008-05-30 10:42:30 -07002300 case PP_DEPEND:
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002301 t = tline->next = expand_smacro(tline->next);
2302 skip_white_(t);
2303 if (!t || (t->type != TOK_STRING &&
2304 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin418ca702008-05-30 10:42:30 -07002305 error(ERR_NONFATAL, "`%%depend' expects a file name");
2306 free_tlist(origline);
2307 return DIRECTIVE_FOUND; /* but we did _something_ */
2308 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002309 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002310 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin418ca702008-05-30 10:42:30 -07002311 "trailing garbage after `%%depend' ignored");
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002312 p = t->text;
2313 if (t->type != TOK_INTERNAL_STRING)
2314 nasm_unquote(p, NULL);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002315 if (dephead && !in_list(*dephead, p)) {
2316 StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next);
2317 sl->next = NULL;
2318 strcpy(sl->str, p);
2319 *deptail = sl;
2320 deptail = &sl->next;
2321 }
2322 free_tlist(origline);
2323 return DIRECTIVE_FOUND;
2324
2325 case PP_INCLUDE:
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002326 t = tline->next = expand_smacro(tline->next);
2327 skip_white_(t);
H. Peter Anvind2456592008-06-19 15:04:18 -07002328
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002329 if (!t || (t->type != TOK_STRING &&
2330 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002331 error(ERR_NONFATAL, "`%%include' expects a file name");
2332 free_tlist(origline);
2333 return DIRECTIVE_FOUND; /* but we did _something_ */
2334 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002335 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002336 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002337 "trailing garbage after `%%include' ignored");
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002338 p = t->text;
2339 if (t->type != TOK_INTERNAL_STRING)
2340 nasm_unquote(p, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002341 inc = nasm_malloc(sizeof(Include));
2342 inc->next = istk;
2343 inc->conds = NULL;
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07002344 inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002345 if (!inc->fp) {
H. Peter Anvin37a321f2007-09-24 13:41:58 -07002346 /* -MG given but file not found */
2347 nasm_free(inc);
2348 } else {
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002349 inc->fname = src_set_fname(nasm_strdup(p));
H. Peter Anvin37a321f2007-09-24 13:41:58 -07002350 inc->lineno = src_set_linnum(0);
2351 inc->lineinc = 1;
2352 inc->expansion = NULL;
2353 inc->mstk = NULL;
2354 istk = inc;
2355 list->uplevel(LIST_INCLUDE);
2356 }
2357 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002358 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002359
H. Peter Anvind2456592008-06-19 15:04:18 -07002360 case PP_USE:
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002361 {
H. Peter Anvina70547f2008-07-19 21:44:26 -07002362 static macros_t *use_pkg;
H. Peter Anvinb2a5fda2008-06-19 21:42:42 -07002363 const char *pkg_macro;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002364
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002365 tline = tline->next;
2366 skip_white_(tline);
2367 tline = expand_id(tline);
H. Peter Anvind2456592008-06-19 15:04:18 -07002368
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002369 if (!tline || (tline->type != TOK_STRING &&
2370 tline->type != TOK_INTERNAL_STRING &&
2371 tline->type != TOK_ID)) {
H. Peter Anvin926fc402008-06-19 16:26:12 -07002372 error(ERR_NONFATAL, "`%%use' expects a package name");
H. Peter Anvind2456592008-06-19 15:04:18 -07002373 free_tlist(origline);
2374 return DIRECTIVE_FOUND; /* but we did _something_ */
2375 }
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002376 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002377 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvind2456592008-06-19 15:04:18 -07002378 "trailing garbage after `%%use' ignored");
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002379 if (tline->type == TOK_STRING)
2380 nasm_unquote(tline->text, NULL);
2381 use_pkg = nasm_stdmac_find_package(tline->text);
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002382 if (!use_pkg)
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002383 error(ERR_NONFATAL, "unknown `%%use' package: %s", tline->text);
H. Peter Anvinb2a5fda2008-06-19 21:42:42 -07002384 /* The first string will be <%define>__USE_*__ */
H. Peter Anvin7e50d232008-06-25 14:54:14 -07002385 pkg_macro = (char *)use_pkg + 1;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002386 if (!smacro_defined(NULL, pkg_macro, 0, NULL, true)) {
2387 /* Not already included, go ahead and include it */
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002388 stdmacpos = use_pkg;
2389 }
H. Peter Anvind2456592008-06-19 15:04:18 -07002390 free_tlist(origline);
2391 return DIRECTIVE_FOUND;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002392 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002393 case PP_PUSH:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002394 case PP_REPL:
H. Peter Anvin42b56392008-10-24 16:24:21 -07002395 case PP_POP:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002396 tline = tline->next;
2397 skip_white_(tline);
2398 tline = expand_id(tline);
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002399 if (tline) {
2400 if (!tok_type_(tline, TOK_ID)) {
H. Peter Anvin42b56392008-10-24 16:24:21 -07002401 error(ERR_NONFATAL, "`%s' expects a context identifier",
2402 pp_directives[i]);
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002403 free_tlist(origline);
2404 return DIRECTIVE_FOUND; /* but we did _something_ */
2405 }
2406 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002407 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin42b56392008-10-24 16:24:21 -07002408 "trailing garbage after `%s' ignored",
2409 pp_directives[i]);
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002410 p = nasm_strdup(tline->text);
2411 } else {
H. Peter Anvin42b56392008-10-24 16:24:21 -07002412 p = NULL; /* Anonymous */
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002413 }
H. Peter Anvin42b56392008-10-24 16:24:21 -07002414
2415 if (i == PP_PUSH) {
2416 ctx = nasm_malloc(sizeof(Context));
2417 ctx->next = cstk;
2418 hash_init(&ctx->localmac, HASH_SMALL);
2419 ctx->name = p;
2420 ctx->number = unique++;
2421 cstk = ctx;
2422 } else {
2423 /* %pop or %repl */
2424 if (!cstk) {
2425 error(ERR_NONFATAL, "`%s': context stack is empty",
2426 pp_directives[i]);
2427 } else if (i == PP_POP) {
2428 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
2429 error(ERR_NONFATAL, "`%%pop' in wrong context: %s, "
2430 "expected %s",
2431 cstk->name ? cstk->name : "anonymous", p);
2432 else
2433 ctx_pop();
2434 } else {
2435 /* i == PP_REPL */
2436 nasm_free(cstk->name);
2437 cstk->name = p;
2438 p = NULL;
2439 }
2440 nasm_free(p);
2441 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002442 free_tlist(origline);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002443 return DIRECTIVE_FOUND;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002444 case PP_FATAL:
2445 severity = ERR_FATAL|ERR_NO_SEVERITY;
2446 goto issue_error;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002447 case PP_ERROR:
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002448 severity = ERR_NONFATAL|ERR_NO_SEVERITY;
2449 goto issue_error;
H. Peter Anvin7df04172008-06-10 18:27:38 -07002450 case PP_WARNING:
H. Peter Anvin2f160432008-09-30 16:39:17 -07002451 severity = ERR_WARNING|ERR_NO_SEVERITY|ERR_WARN_USER;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002452 goto issue_error;
2453
2454 issue_error:
H. Peter Anvin7df04172008-06-10 18:27:38 -07002455 {
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002456 /* Only error out if this is the final pass */
2457 if (pass != 2 && i != PP_FATAL)
2458 return DIRECTIVE_FOUND;
H. Peter Anvin7df04172008-06-10 18:27:38 -07002459
H. Peter Anvine2c80182005-01-15 22:15:51 +00002460 tline->next = expand_smacro(tline->next);
2461 tline = tline->next;
2462 skip_white_(tline);
H. Peter Anvin7df04172008-06-10 18:27:38 -07002463 t = tline ? tline->next : NULL;
2464 skip_white_(t);
2465 if (tok_type_(tline, TOK_STRING) && !t) {
2466 /* The line contains only a quoted string */
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07002467 p = tline->text;
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002468 nasm_unquote(p, NULL);
H. Peter Anvin7df04172008-06-10 18:27:38 -07002469 error(severity, "%s: %s", pp_directives[i], p);
2470 } else {
2471 /* Not a quoted string, or more than a quoted string */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002472 p = detoken(tline, false);
H. Peter Anvin7df04172008-06-10 18:27:38 -07002473 error(severity, "%s: %s", pp_directives[i], p);
2474 nasm_free(p);
H. Peter Anvind2456592008-06-19 15:04:18 -07002475 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002476 free_tlist(origline);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002477 return DIRECTIVE_FOUND;
H. Peter Anvin7df04172008-06-10 18:27:38 -07002478 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002479
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002480 CASE_PP_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002481 if (istk->conds && !emitting(istk->conds->state))
2482 j = COND_NEVER;
2483 else {
2484 j = if_condition(tline->next, i);
2485 tline->next = NULL; /* it got freed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002486 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2487 }
2488 cond = nasm_malloc(sizeof(Cond));
2489 cond->next = istk->conds;
2490 cond->state = j;
2491 istk->conds = cond;
H. Peter Anvin7061ad72007-11-26 22:02:21 -08002492 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002493 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002494
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002495 CASE_PP_ELIF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002496 if (!istk->conds)
H. Peter Anvin4169a472007-09-12 01:29:43 +00002497 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002498 switch(istk->conds->state) {
2499 case COND_IF_TRUE:
2500 istk->conds->state = COND_DONE;
2501 break;
2502
2503 case COND_DONE:
2504 case COND_NEVER:
2505 break;
2506
2507 case COND_ELSE_TRUE:
2508 case COND_ELSE_FALSE:
H. Peter Anvin917a3492008-09-24 09:14:49 -07002509 error_precond(ERR_WARNING|ERR_PASS1,
2510 "`%%elif' after `%%else' ignored");
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002511 istk->conds->state = COND_NEVER;
2512 break;
2513
2514 case COND_IF_FALSE:
2515 /*
2516 * IMPORTANT: In the case of %if, we will already have
2517 * called expand_mmac_params(); however, if we're
2518 * processing an %elif we must have been in a
2519 * non-emitting mode, which would have inhibited
H. Peter Anvin67c63722008-10-26 23:49:00 -07002520 * the normal invocation of expand_mmac_params().
2521 * Therefore, we have to do it explicitly here.
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002522 */
H. Peter Anvin67c63722008-10-26 23:49:00 -07002523 j = if_condition(expand_mmac_params(tline->next), i);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002524 tline->next = NULL; /* it got freed */
2525 istk->conds->state =
2526 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2527 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002528 }
H. Peter Anvin7061ad72007-11-26 22:02:21 -08002529 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002530 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002531
H. Peter Anvine2c80182005-01-15 22:15:51 +00002532 case PP_ELSE:
2533 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002534 error_precond(ERR_WARNING|ERR_PASS1,
2535 "trailing garbage after `%%else' ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00002536 if (!istk->conds)
2537 error(ERR_FATAL, "`%%else': no matching `%%if'");
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002538 switch(istk->conds->state) {
2539 case COND_IF_TRUE:
2540 case COND_DONE:
2541 istk->conds->state = COND_ELSE_FALSE;
2542 break;
2543
2544 case COND_NEVER:
2545 break;
2546
2547 case COND_IF_FALSE:
2548 istk->conds->state = COND_ELSE_TRUE;
2549 break;
2550
2551 case COND_ELSE_TRUE:
2552 case COND_ELSE_FALSE:
H. Peter Anvin917a3492008-09-24 09:14:49 -07002553 error_precond(ERR_WARNING|ERR_PASS1,
2554 "`%%else' after `%%else' ignored.");
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002555 istk->conds->state = COND_NEVER;
2556 break;
2557 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002558 free_tlist(origline);
2559 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002560
H. Peter Anvine2c80182005-01-15 22:15:51 +00002561 case PP_ENDIF:
2562 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002563 error_precond(ERR_WARNING|ERR_PASS1,
2564 "trailing garbage after `%%endif' ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00002565 if (!istk->conds)
2566 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2567 cond = istk->conds;
2568 istk->conds = cond->next;
2569 nasm_free(cond);
2570 free_tlist(origline);
2571 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002572
H. Peter Anvine2c80182005-01-15 22:15:51 +00002573 case PP_MACRO:
2574 case PP_IMACRO:
H. Peter Anvina26433d2008-07-16 14:40:01 -07002575 if (defining) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002576 error(ERR_FATAL,
2577 "`%%%smacro': already defining a macro",
2578 (i == PP_IMACRO ? "i" : ""));
H. Peter Anvina26433d2008-07-16 14:40:01 -07002579 return DIRECTIVE_FOUND;
2580 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002581 defining = nasm_malloc(sizeof(MMacro));
H. Peter Anvina26433d2008-07-16 14:40:01 -07002582 defining->casesense = (i == PP_MACRO);
2583 if (!parse_mmacro_spec(tline, defining, pp_directives[i])) {
2584 nasm_free(defining);
2585 defining = NULL;
2586 return DIRECTIVE_FOUND;
2587 }
2588
H. Peter Anvin166c2472008-05-28 12:28:58 -07002589 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002590 while (mmac) {
2591 if (!strcmp(mmac->name, defining->name) &&
2592 (mmac->nparam_min <= defining->nparam_max
2593 || defining->plus)
2594 && (defining->nparam_min <= mmac->nparam_max
2595 || mmac->plus)) {
H. Peter Anvin917a3492008-09-24 09:14:49 -07002596 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002597 "redefining multi-line macro `%s'", defining->name);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002598 return DIRECTIVE_FOUND;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002599 }
2600 mmac = mmac->next;
2601 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002602 free_tlist(origline);
2603 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002604
H. Peter Anvine2c80182005-01-15 22:15:51 +00002605 case PP_ENDM:
2606 case PP_ENDMACRO:
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02002607 if (! (defining && defining->name)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002608 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2609 return DIRECTIVE_FOUND;
2610 }
H. Peter Anvin166c2472008-05-28 12:28:58 -07002611 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002612 defining->next = *mmhead;
2613 *mmhead = defining;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002614 defining = NULL;
2615 free_tlist(origline);
2616 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002617
H. Peter Anvina26433d2008-07-16 14:40:01 -07002618 case PP_UNMACRO:
2619 case PP_UNIMACRO:
2620 {
2621 MMacro **mmac_p;
2622 MMacro spec;
2623
2624 spec.casesense = (i == PP_UNMACRO);
2625 if (!parse_mmacro_spec(tline, &spec, pp_directives[i])) {
2626 return DIRECTIVE_FOUND;
2627 }
2628 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
2629 while (mmac_p && *mmac_p) {
2630 mmac = *mmac_p;
2631 if (mmac->casesense == spec.casesense &&
2632 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
2633 mmac->nparam_min == spec.nparam_min &&
2634 mmac->nparam_max == spec.nparam_max &&
2635 mmac->plus == spec.plus) {
2636 *mmac_p = mmac->next;
2637 free_mmacro(mmac);
2638 } else {
2639 mmac_p = &mmac->next;
2640 }
2641 }
2642 free_tlist(origline);
2643 free_tlist(spec.dlist);
2644 return DIRECTIVE_FOUND;
2645 }
2646
H. Peter Anvine2c80182005-01-15 22:15:51 +00002647 case PP_ROTATE:
2648 if (tline->next && tline->next->type == TOK_WHITESPACE)
2649 tline = tline->next;
2650 if (tline->next == NULL) {
2651 free_tlist(origline);
2652 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2653 return DIRECTIVE_FOUND;
2654 }
2655 t = expand_smacro(tline->next);
2656 tline->next = NULL;
2657 free_tlist(origline);
2658 tline = t;
2659 tptr = &t;
2660 tokval.t_type = TOKEN_INVALID;
2661 evalresult =
2662 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2663 free_tlist(tline);
2664 if (!evalresult)
2665 return DIRECTIVE_FOUND;
2666 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002667 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002668 "trailing garbage after expression ignored");
2669 if (!is_simple(evalresult)) {
2670 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2671 return DIRECTIVE_FOUND;
2672 }
2673 mmac = istk->mstk;
2674 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2675 mmac = mmac->next_active;
2676 if (!mmac) {
2677 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2678 } else if (mmac->nparam == 0) {
2679 error(ERR_NONFATAL,
2680 "`%%rotate' invoked within macro without parameters");
2681 } else {
H. Peter Anvin25a99342007-09-22 17:45:45 -07002682 int rotate = mmac->rotate + reloc_value(evalresult);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002683
H. Peter Anvin25a99342007-09-22 17:45:45 -07002684 rotate %= (int)mmac->nparam;
2685 if (rotate < 0)
2686 rotate += mmac->nparam;
H. Peter Anvin70653092007-10-19 14:42:29 -07002687
H. Peter Anvin25a99342007-09-22 17:45:45 -07002688 mmac->rotate = rotate;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002689 }
2690 return DIRECTIVE_FOUND;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002691
H. Peter Anvine2c80182005-01-15 22:15:51 +00002692 case PP_REP:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002693 nolist = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002694 do {
2695 tline = tline->next;
2696 } while (tok_type_(tline, TOK_WHITESPACE));
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002697
H. Peter Anvine2c80182005-01-15 22:15:51 +00002698 if (tok_type_(tline, TOK_ID) &&
2699 nasm_stricmp(tline->text, ".nolist") == 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002700 nolist = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002701 do {
2702 tline = tline->next;
2703 } while (tok_type_(tline, TOK_WHITESPACE));
2704 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002705
H. Peter Anvine2c80182005-01-15 22:15:51 +00002706 if (tline) {
2707 t = expand_smacro(tline);
2708 tptr = &t;
2709 tokval.t_type = TOKEN_INVALID;
2710 evalresult =
2711 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2712 if (!evalresult) {
2713 free_tlist(origline);
2714 return DIRECTIVE_FOUND;
2715 }
2716 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002717 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002718 "trailing garbage after expression ignored");
2719 if (!is_simple(evalresult)) {
2720 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2721 return DIRECTIVE_FOUND;
2722 }
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002723 count = reloc_value(evalresult) + 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002724 } else {
2725 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002726 count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002727 }
2728 free_tlist(origline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002729
H. Peter Anvine2c80182005-01-15 22:15:51 +00002730 tmp_defining = defining;
2731 defining = nasm_malloc(sizeof(MMacro));
2732 defining->name = NULL; /* flags this macro as a %rep block */
H. Peter Anvin70055962007-10-11 00:05:31 -07002733 defining->casesense = false;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002734 defining->plus = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002735 defining->nolist = nolist;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002736 defining->in_progress = count;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002737 defining->nparam_min = defining->nparam_max = 0;
2738 defining->defaults = NULL;
2739 defining->dlist = NULL;
2740 defining->expansion = NULL;
2741 defining->next_active = istk->mstk;
2742 defining->rep_nest = tmp_defining;
2743 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002744
H. Peter Anvine2c80182005-01-15 22:15:51 +00002745 case PP_ENDREP:
2746 if (!defining || defining->name) {
2747 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2748 return DIRECTIVE_FOUND;
2749 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002750
H. Peter Anvine2c80182005-01-15 22:15:51 +00002751 /*
2752 * Now we have a "macro" defined - although it has no name
2753 * and we won't be entering it in the hash tables - we must
2754 * push a macro-end marker for it on to istk->expansion.
2755 * After that, it will take care of propagating itself (a
2756 * macro-end marker line for a macro which is really a %rep
2757 * block will cause the macro to be re-expanded, complete
2758 * with another macro-end marker to ensure the process
2759 * continues) until the whole expansion is forcibly removed
2760 * from istk->expansion by a %exitrep.
2761 */
2762 l = nasm_malloc(sizeof(Line));
2763 l->next = istk->expansion;
2764 l->finishes = defining;
2765 l->first = NULL;
2766 istk->expansion = l;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002767
H. Peter Anvine2c80182005-01-15 22:15:51 +00002768 istk->mstk = defining;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002769
H. Peter Anvine2c80182005-01-15 22:15:51 +00002770 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2771 tmp_defining = defining;
2772 defining = defining->rep_nest;
2773 free_tlist(origline);
2774 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002775
H. Peter Anvine2c80182005-01-15 22:15:51 +00002776 case PP_EXITREP:
2777 /*
2778 * We must search along istk->expansion until we hit a
2779 * macro-end marker for a macro with no name. Then we set
2780 * its `in_progress' flag to 0.
2781 */
2782 for (l = istk->expansion; l; l = l->next)
2783 if (l->finishes && !l->finishes->name)
H. Peter Anvinca348b62008-07-23 10:49:26 -04002784 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002785
H. Peter Anvine2c80182005-01-15 22:15:51 +00002786 if (l)
Charles Crayned4200be2008-07-12 16:42:33 -07002787 l->finishes->in_progress = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002788 else
2789 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2790 free_tlist(origline);
2791 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002792
H. Peter Anvine2c80182005-01-15 22:15:51 +00002793 case PP_XDEFINE:
2794 case PP_IXDEFINE:
2795 case PP_DEFINE:
2796 case PP_IDEFINE:
H. Peter Anvin95e7f952007-10-11 13:38:38 -07002797 casesense = (i == PP_DEFINE || i == PP_XDEFINE);
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002798
H. Peter Anvine2c80182005-01-15 22:15:51 +00002799 tline = tline->next;
2800 skip_white_(tline);
2801 tline = expand_id(tline);
2802 if (!tline || (tline->type != TOK_ID &&
2803 (tline->type != TOK_PREPROC_ID ||
2804 tline->text[1] != '$'))) {
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002805 error(ERR_NONFATAL, "`%s' expects a macro identifier",
2806 pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002807 free_tlist(origline);
2808 return DIRECTIVE_FOUND;
2809 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002810
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002811 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002812 last = tline;
2813 param_start = tline = tline->next;
2814 nparam = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002815
H. Peter Anvine2c80182005-01-15 22:15:51 +00002816 /* Expand the macro definition now for %xdefine and %ixdefine */
2817 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2818 tline = expand_smacro(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002819
H. Peter Anvine2c80182005-01-15 22:15:51 +00002820 if (tok_is_(tline, "(")) {
2821 /*
2822 * This macro has parameters.
2823 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002824
H. Peter Anvine2c80182005-01-15 22:15:51 +00002825 tline = tline->next;
2826 while (1) {
2827 skip_white_(tline);
2828 if (!tline) {
2829 error(ERR_NONFATAL, "parameter identifier expected");
2830 free_tlist(origline);
2831 return DIRECTIVE_FOUND;
2832 }
2833 if (tline->type != TOK_ID) {
2834 error(ERR_NONFATAL,
2835 "`%s': parameter identifier expected",
2836 tline->text);
2837 free_tlist(origline);
2838 return DIRECTIVE_FOUND;
2839 }
2840 tline->type = TOK_SMAC_PARAM + nparam++;
2841 tline = tline->next;
2842 skip_white_(tline);
2843 if (tok_is_(tline, ",")) {
2844 tline = tline->next;
H. Peter Anvinca348b62008-07-23 10:49:26 -04002845 } else {
2846 if (!tok_is_(tline, ")")) {
2847 error(ERR_NONFATAL,
2848 "`)' expected to terminate macro template");
2849 free_tlist(origline);
2850 return DIRECTIVE_FOUND;
2851 }
2852 break;
2853 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002854 }
2855 last = tline;
2856 tline = tline->next;
2857 }
2858 if (tok_type_(tline, TOK_WHITESPACE))
2859 last = tline, tline = tline->next;
2860 macro_start = NULL;
2861 last->next = NULL;
2862 t = tline;
2863 while (t) {
2864 if (t->type == TOK_ID) {
2865 for (tt = param_start; tt; tt = tt->next)
2866 if (tt->type >= TOK_SMAC_PARAM &&
2867 !strcmp(tt->text, t->text))
2868 t->type = tt->type;
2869 }
2870 tt = t->next;
2871 t->next = macro_start;
2872 macro_start = t;
2873 t = tt;
2874 }
2875 /*
2876 * Good. We now have a macro name, a parameter count, and a
2877 * token list (in reverse order) for an expansion. We ought
2878 * to be OK just to create an SMacro, store it, and let
2879 * free_tlist have the rest of the line (which we have
2880 * carefully re-terminated after chopping off the expansion
2881 * from the end).
2882 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002883 define_smacro(ctx, mname, casesense, nparam, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002884 free_tlist(origline);
2885 return DIRECTIVE_FOUND;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002886
H. Peter Anvine2c80182005-01-15 22:15:51 +00002887 case PP_UNDEF:
2888 tline = tline->next;
2889 skip_white_(tline);
2890 tline = expand_id(tline);
2891 if (!tline || (tline->type != TOK_ID &&
2892 (tline->type != TOK_PREPROC_ID ||
2893 tline->text[1] != '$'))) {
2894 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2895 free_tlist(origline);
2896 return DIRECTIVE_FOUND;
2897 }
2898 if (tline->next) {
H. Peter Anvin917a3492008-09-24 09:14:49 -07002899 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002900 "trailing garbage after macro name ignored");
2901 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002902
H. Peter Anvine2c80182005-01-15 22:15:51 +00002903 /* Find the context that symbol belongs to */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002904 ctx = get_ctx(tline->text, &mname, false);
2905 undef_smacro(ctx, mname);
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002906 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002907 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002908
H. Peter Anvin9e200162008-06-04 17:23:14 -07002909 case PP_DEFSTR:
2910 case PP_IDEFSTR:
2911 casesense = (i == PP_DEFSTR);
2912
2913 tline = tline->next;
2914 skip_white_(tline);
2915 tline = expand_id(tline);
2916 if (!tline || (tline->type != TOK_ID &&
2917 (tline->type != TOK_PREPROC_ID ||
2918 tline->text[1] != '$'))) {
2919 error(ERR_NONFATAL, "`%s' expects a macro identifier",
2920 pp_directives[i]);
2921 free_tlist(origline);
2922 return DIRECTIVE_FOUND;
2923 }
2924
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002925 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvin9e200162008-06-04 17:23:14 -07002926 last = tline;
2927 tline = expand_smacro(tline->next);
2928 last->next = NULL;
2929
2930 while (tok_type_(tline, TOK_WHITESPACE))
2931 tline = delete_Token(tline);
2932
2933 p = detoken(tline, false);
2934 macro_start = nasm_malloc(sizeof(*macro_start));
2935 macro_start->next = NULL;
2936 macro_start->text = nasm_quote(p, strlen(p));
2937 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07002938 macro_start->a.mac = NULL;
H. Peter Anvin9e200162008-06-04 17:23:14 -07002939 nasm_free(p);
2940
2941 /*
2942 * We now have a macro name, an implicit parameter count of
2943 * zero, and a string token to use as an expansion. Create
2944 * and store an SMacro.
2945 */
2946 define_smacro(ctx, mname, casesense, 0, macro_start);
2947 free_tlist(origline);
2948 return DIRECTIVE_FOUND;
2949
H. Peter Anvin418ca702008-05-30 10:42:30 -07002950 case PP_PATHSEARCH:
2951 {
2952 FILE *fp;
2953 StrList *xsl = NULL;
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07002954 StrList **xst = &xsl;
H. Peter Anvin418ca702008-05-30 10:42:30 -07002955
2956 casesense = true;
2957
2958 tline = tline->next;
2959 skip_white_(tline);
2960 tline = expand_id(tline);
2961 if (!tline || (tline->type != TOK_ID &&
2962 (tline->type != TOK_PREPROC_ID ||
2963 tline->text[1] != '$'))) {
2964 error(ERR_NONFATAL,
2965 "`%%pathsearch' expects a macro identifier as first parameter");
2966 free_tlist(origline);
2967 return DIRECTIVE_FOUND;
2968 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002969 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002970 last = tline;
2971 tline = expand_smacro(tline->next);
2972 last->next = NULL;
2973
2974 t = tline;
2975 while (tok_type_(t, TOK_WHITESPACE))
2976 t = t->next;
2977
2978 if (!t || (t->type != TOK_STRING &&
2979 t->type != TOK_INTERNAL_STRING)) {
2980 error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
2981 free_tlist(tline);
2982 free_tlist(origline);
2983 return DIRECTIVE_FOUND; /* but we did _something_ */
2984 }
2985 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002986 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin418ca702008-05-30 10:42:30 -07002987 "trailing garbage after `%%pathsearch' ignored");
H. Peter Anvin427cc912008-06-01 21:43:03 -07002988 p = t->text;
2989 if (t->type != TOK_INTERNAL_STRING)
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002990 nasm_unquote(p, NULL);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002991
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07002992 fp = inc_fopen(p, &xsl, &xst, true);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002993 if (fp) {
2994 p = xsl->str;
2995 fclose(fp); /* Don't actually care about the file */
2996 }
2997 macro_start = nasm_malloc(sizeof(*macro_start));
2998 macro_start->next = NULL;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07002999 macro_start->text = nasm_quote(p, strlen(p));
H. Peter Anvin418ca702008-05-30 10:42:30 -07003000 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003001 macro_start->a.mac = NULL;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003002 if (xsl)
3003 nasm_free(xsl);
3004
3005 /*
3006 * We now have a macro name, an implicit parameter count of
3007 * zero, and a string token to use as an expansion. Create
3008 * and store an SMacro.
3009 */
3010 define_smacro(ctx, mname, casesense, 0, macro_start);
3011 free_tlist(tline);
3012 free_tlist(origline);
3013 return DIRECTIVE_FOUND;
3014 }
3015
H. Peter Anvine2c80182005-01-15 22:15:51 +00003016 case PP_STRLEN:
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003017 casesense = true;
H. Peter Anvin70653092007-10-19 14:42:29 -07003018
H. Peter Anvine2c80182005-01-15 22:15:51 +00003019 tline = tline->next;
3020 skip_white_(tline);
3021 tline = expand_id(tline);
3022 if (!tline || (tline->type != TOK_ID &&
3023 (tline->type != TOK_PREPROC_ID ||
3024 tline->text[1] != '$'))) {
3025 error(ERR_NONFATAL,
3026 "`%%strlen' expects a macro identifier as first parameter");
3027 free_tlist(origline);
3028 return DIRECTIVE_FOUND;
3029 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003030 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003031 last = tline;
3032 tline = expand_smacro(tline->next);
3033 last->next = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003034
H. Peter Anvine2c80182005-01-15 22:15:51 +00003035 t = tline;
3036 while (tok_type_(t, TOK_WHITESPACE))
3037 t = t->next;
3038 /* t should now point to the string */
3039 if (t->type != TOK_STRING) {
3040 error(ERR_NONFATAL,
3041 "`%%strlen` requires string as second parameter");
3042 free_tlist(tline);
3043 free_tlist(origline);
3044 return DIRECTIVE_FOUND;
3045 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003046
H. Peter Anvine2c80182005-01-15 22:15:51 +00003047 macro_start = nasm_malloc(sizeof(*macro_start));
3048 macro_start->next = NULL;
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003049 make_tok_num(macro_start, nasm_unquote(t->text, NULL));
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003050 macro_start->a.mac = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003051
H. Peter Anvine2c80182005-01-15 22:15:51 +00003052 /*
3053 * We now have a macro name, an implicit parameter count of
3054 * zero, and a numeric token to use as an expansion. Create
3055 * and store an SMacro.
3056 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003057 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003058 free_tlist(tline);
3059 free_tlist(origline);
3060 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003061
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003062 case PP_STRCAT:
3063 casesense = true;
3064
3065 tline = tline->next;
3066 skip_white_(tline);
3067 tline = expand_id(tline);
3068 if (!tline || (tline->type != TOK_ID &&
3069 (tline->type != TOK_PREPROC_ID ||
3070 tline->text[1] != '$'))) {
3071 error(ERR_NONFATAL,
3072 "`%%strcat' expects a macro identifier as first parameter");
3073 free_tlist(origline);
3074 return DIRECTIVE_FOUND;
3075 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003076 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003077 last = tline;
3078 tline = expand_smacro(tline->next);
3079 last->next = NULL;
3080
3081 len = 0;
3082 for (t = tline; t; t = t->next) {
3083 switch (t->type) {
3084 case TOK_WHITESPACE:
3085 break;
3086 case TOK_STRING:
3087 len += t->a.len = nasm_unquote(t->text, NULL);
3088 break;
H. Peter Anvinaccf4332008-07-01 21:42:08 -07003089 case TOK_OTHER:
3090 if (!strcmp(t->text, ",")) /* permit comma separators */
3091 break;
3092 /* else fall through */
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003093 default:
3094 error(ERR_NONFATAL,
3095 "non-string passed to `%%strcat' (%d)", t->type);
3096 free_tlist(tline);
3097 free_tlist(origline);
3098 return DIRECTIVE_FOUND;
3099 }
3100 }
3101
3102 p = pp = nasm_malloc(len);
3103 t = tline;
3104 for (t = tline; t; t = t->next) {
3105 if (t->type == TOK_STRING) {
3106 memcpy(p, t->text, t->a.len);
3107 p += t->a.len;
3108 }
3109 }
3110
3111 /*
3112 * We now have a macro name, an implicit parameter count of
3113 * zero, and a numeric token to use as an expansion. Create
3114 * and store an SMacro.
3115 */
3116 macro_start = new_Token(NULL, TOK_STRING, NULL, 0);
3117 macro_start->text = nasm_quote(pp, len);
3118 nasm_free(pp);
3119 define_smacro(ctx, mname, casesense, 0, macro_start);
3120 free_tlist(tline);
3121 free_tlist(origline);
3122 return DIRECTIVE_FOUND;
3123
H. Peter Anvine2c80182005-01-15 22:15:51 +00003124 case PP_SUBSTR:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003125 {
3126 int64_t a1, a2;
3127 size_t len;
H. Peter Anvind2456592008-06-19 15:04:18 -07003128
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003129 casesense = true;
3130
H. Peter Anvine2c80182005-01-15 22:15:51 +00003131 tline = tline->next;
3132 skip_white_(tline);
3133 tline = expand_id(tline);
3134 if (!tline || (tline->type != TOK_ID &&
3135 (tline->type != TOK_PREPROC_ID ||
3136 tline->text[1] != '$'))) {
3137 error(ERR_NONFATAL,
3138 "`%%substr' expects a macro identifier as first parameter");
3139 free_tlist(origline);
3140 return DIRECTIVE_FOUND;
3141 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003142 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003143 last = tline;
3144 tline = expand_smacro(tline->next);
3145 last->next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003146
H. Peter Anvine2c80182005-01-15 22:15:51 +00003147 t = tline->next;
3148 while (tok_type_(t, TOK_WHITESPACE))
3149 t = t->next;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003150
H. Peter Anvine2c80182005-01-15 22:15:51 +00003151 /* t should now point to the string */
3152 if (t->type != TOK_STRING) {
3153 error(ERR_NONFATAL,
3154 "`%%substr` requires string as second parameter");
3155 free_tlist(tline);
3156 free_tlist(origline);
3157 return DIRECTIVE_FOUND;
3158 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003159
H. Peter Anvine2c80182005-01-15 22:15:51 +00003160 tt = t->next;
3161 tptr = &tt;
3162 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003163 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3164 pass, error, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003165 if (!evalresult) {
3166 free_tlist(tline);
3167 free_tlist(origline);
3168 return DIRECTIVE_FOUND;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003169 } else if (!is_simple(evalresult)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003170 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3171 free_tlist(tline);
3172 free_tlist(origline);
3173 return DIRECTIVE_FOUND;
3174 }
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003175 a1 = evalresult->value-1;
3176
3177 while (tok_type_(tt, TOK_WHITESPACE))
3178 tt = tt->next;
3179 if (!tt) {
3180 a2 = 1; /* Backwards compatibility: one character */
3181 } else {
3182 tokval.t_type = TOKEN_INVALID;
3183 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3184 pass, error, NULL);
3185 if (!evalresult) {
3186 free_tlist(tline);
3187 free_tlist(origline);
3188 return DIRECTIVE_FOUND;
3189 } else if (!is_simple(evalresult)) {
3190 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3191 free_tlist(tline);
3192 free_tlist(origline);
3193 return DIRECTIVE_FOUND;
3194 }
3195 a2 = evalresult->value;
3196 }
3197
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003198 len = nasm_unquote(t->text, NULL);
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003199 if (a2 < 0)
3200 a2 = a2+1+len-a1;
3201 if (a1+a2 > (int64_t)len)
3202 a2 = len-a1;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003203
H. Peter Anvine2c80182005-01-15 22:15:51 +00003204 macro_start = nasm_malloc(sizeof(*macro_start));
3205 macro_start->next = NULL;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003206 macro_start->text = nasm_quote((a1 < 0) ? "" : t->text+a1, a2);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003207 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003208 macro_start->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003209
H. Peter Anvine2c80182005-01-15 22:15:51 +00003210 /*
3211 * We now have a macro name, an implicit parameter count of
3212 * zero, and a numeric token to use as an expansion. Create
3213 * and store an SMacro.
3214 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003215 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003216 free_tlist(tline);
3217 free_tlist(origline);
3218 return DIRECTIVE_FOUND;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003219 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003220
H. Peter Anvine2c80182005-01-15 22:15:51 +00003221 case PP_ASSIGN:
3222 case PP_IASSIGN:
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003223 casesense = (i == PP_ASSIGN);
3224
H. Peter Anvine2c80182005-01-15 22:15:51 +00003225 tline = tline->next;
3226 skip_white_(tline);
3227 tline = expand_id(tline);
3228 if (!tline || (tline->type != TOK_ID &&
3229 (tline->type != TOK_PREPROC_ID ||
3230 tline->text[1] != '$'))) {
3231 error(ERR_NONFATAL,
3232 "`%%%sassign' expects a macro identifier",
3233 (i == PP_IASSIGN ? "i" : ""));
3234 free_tlist(origline);
3235 return DIRECTIVE_FOUND;
3236 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003237 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003238 last = tline;
3239 tline = expand_smacro(tline->next);
3240 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003241
H. Peter Anvine2c80182005-01-15 22:15:51 +00003242 t = tline;
3243 tptr = &t;
3244 tokval.t_type = TOKEN_INVALID;
3245 evalresult =
3246 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3247 free_tlist(tline);
3248 if (!evalresult) {
3249 free_tlist(origline);
3250 return DIRECTIVE_FOUND;
3251 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003252
H. Peter Anvine2c80182005-01-15 22:15:51 +00003253 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07003254 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003255 "trailing garbage after expression ignored");
H. Peter Anvin734b1882002-04-30 21:01:08 +00003256
H. Peter Anvine2c80182005-01-15 22:15:51 +00003257 if (!is_simple(evalresult)) {
3258 error(ERR_NONFATAL,
3259 "non-constant value given to `%%%sassign'",
3260 (i == PP_IASSIGN ? "i" : ""));
3261 free_tlist(origline);
3262 return DIRECTIVE_FOUND;
3263 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003264
H. Peter Anvine2c80182005-01-15 22:15:51 +00003265 macro_start = nasm_malloc(sizeof(*macro_start));
3266 macro_start->next = NULL;
3267 make_tok_num(macro_start, reloc_value(evalresult));
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003268 macro_start->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003269
H. Peter Anvine2c80182005-01-15 22:15:51 +00003270 /*
3271 * We now have a macro name, an implicit parameter count of
3272 * zero, and a numeric token to use as an expansion. Create
3273 * and store an SMacro.
3274 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003275 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003276 free_tlist(origline);
3277 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003278
H. Peter Anvine2c80182005-01-15 22:15:51 +00003279 case PP_LINE:
3280 /*
3281 * Syntax is `%line nnn[+mmm] [filename]'
3282 */
3283 tline = tline->next;
3284 skip_white_(tline);
3285 if (!tok_type_(tline, TOK_NUMBER)) {
3286 error(ERR_NONFATAL, "`%%line' expects line number");
3287 free_tlist(origline);
3288 return DIRECTIVE_FOUND;
3289 }
H. Peter Anvin70055962007-10-11 00:05:31 -07003290 k = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003291 m = 1;
3292 tline = tline->next;
3293 if (tok_is_(tline, "+")) {
3294 tline = tline->next;
3295 if (!tok_type_(tline, TOK_NUMBER)) {
3296 error(ERR_NONFATAL, "`%%line' expects line increment");
3297 free_tlist(origline);
3298 return DIRECTIVE_FOUND;
3299 }
H. Peter Anvin70055962007-10-11 00:05:31 -07003300 m = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003301 tline = tline->next;
3302 }
3303 skip_white_(tline);
3304 src_set_linnum(k);
3305 istk->lineinc = m;
3306 if (tline) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003307 nasm_free(src_set_fname(detoken(tline, false)));
H. Peter Anvine2c80182005-01-15 22:15:51 +00003308 }
3309 free_tlist(origline);
3310 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003311
H. Peter Anvine2c80182005-01-15 22:15:51 +00003312 default:
3313 error(ERR_FATAL,
3314 "preprocessor directive `%s' not yet implemented",
H. Peter Anvin4169a472007-09-12 01:29:43 +00003315 pp_directives[i]);
H. Peter Anvina26433d2008-07-16 14:40:01 -07003316 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003317 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003318}
3319
3320/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00003321 * Ensure that a macro parameter contains a condition code and
3322 * nothing else. Return the condition code index if so, or -1
3323 * otherwise.
3324 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003325static int find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003326{
H. Peter Anvin76690a12002-04-30 20:52:49 +00003327 Token *tt;
3328 int i, j, k, m;
3329
H. Peter Anvin25a99342007-09-22 17:45:45 -07003330 if (!t)
3331 return -1; /* Probably a %+ without a space */
3332
H. Peter Anvineba20a72002-04-30 20:53:55 +00003333 skip_white_(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003334 if (t->type != TOK_ID)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003335 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003336 tt = t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003337 skip_white_(tt);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003338 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003339 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003340
3341 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +00003342 j = elements(conditions);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003343 while (j - i > 1) {
3344 k = (j + i) / 2;
3345 m = nasm_stricmp(t->text, conditions[k]);
3346 if (m == 0) {
3347 i = k;
3348 j = -2;
3349 break;
3350 } else if (m < 0) {
3351 j = k;
3352 } else
3353 i = k;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003354 }
3355 if (j != -2)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003356 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003357 return i;
3358}
3359
H. Peter Anvind784a082009-04-20 14:01:18 -07003360static bool paste_tokens(Token **head, bool handle_paste_tokens)
3361{
3362 Token **tail, *t, *tt;
3363 Token **paste_head;
3364 bool did_paste = false;
3365 char *tmp;
3366
3367 /* Now handle token pasting... */
3368 paste_head = NULL;
3369 tail = head;
3370 while ((t = *tail) && (tt = t->next)) {
3371 switch (t->type) {
3372 case TOK_WHITESPACE:
3373 if (tt->type == TOK_WHITESPACE) {
3374 /* Zap adjacent whitespace tokens */
3375 t->next = delete_Token(tt);
3376 } else {
3377 /* Do not advance paste_head here */
3378 tail = &t->next;
3379 }
3380 break;
3381 case TOK_ID:
3382 case TOK_PREPROC_ID:
3383 case TOK_NUMBER:
3384 case TOK_FLOAT:
3385 {
3386 size_t len = 0;
3387 char *tmp, *p;
3388
3389 while (tt && (tt->type == TOK_ID || tt->type == TOK_PREPROC_ID ||
3390 tt->type == TOK_NUMBER || tt->type == TOK_FLOAT ||
3391 tt->type == TOK_OTHER)) {
3392 len += strlen(tt->text);
3393 tt = tt->next;
3394 }
3395
3396 /* Now tt points to the first token after the potential
3397 paste area... */
3398 if (tt != t->next) {
3399 /* We have at least two tokens... */
3400 len += strlen(t->text);
3401 p = tmp = nasm_malloc(len+1);
3402
3403 while (t != tt) {
3404 strcpy(p, t->text);
3405 p = strchr(p, '\0');
3406 t = delete_Token(t);
3407 }
3408
3409 t = *tail = tokenize(tmp);
3410 nasm_free(tmp);
3411
3412 while (t->next) {
3413 tail = &t->next;
3414 t = t->next;
3415 }
3416 t->next = tt; /* Attach the remaining token chain */
3417
3418 did_paste = true;
3419 }
3420 paste_head = tail;
3421 tail = &t->next;
3422 break;
3423 }
3424 case TOK_PASTE: /* %+ */
3425 if (handle_paste_tokens) {
3426 /* Zap %+ and whitespace tokens to the right */
3427 while (t && (t->type == TOK_WHITESPACE ||
3428 t->type == TOK_PASTE))
3429 t = *tail = delete_Token(t);
3430 if (!paste_head || !t)
3431 break; /* Nothing to paste with */
3432 tail = paste_head;
3433 t = *tail;
3434 tt = t->next;
3435 while (tok_type_(tt, TOK_WHITESPACE))
3436 tt = t->next = delete_Token(tt);
3437
3438 if (tt) {
3439 tmp = nasm_strcat(t->text, tt->text);
3440 delete_Token(t);
3441 tt = delete_Token(tt);
3442 t = *tail = tokenize(tmp);
3443 nasm_free(tmp);
3444 while (t->next) {
3445 tail = &t->next;
3446 t = t->next;
3447 }
3448 t->next = tt; /* Attach the remaining token chain */
3449 did_paste = true;
3450 }
3451 paste_head = tail;
3452 tail = &t->next;
3453 break;
3454 }
3455 /* else fall through */
3456 default:
3457 tail = paste_head = &t->next;
3458 break;
3459 }
3460 }
3461 return did_paste;
3462}
H. Peter Anvin76690a12002-04-30 20:52:49 +00003463/*
3464 * Expand MMacro-local things: parameter references (%0, %n, %+n,
H. Peter Anvin67c63722008-10-26 23:49:00 -07003465 * %-n) and MMacro-local identifiers (%%foo) as well as
3466 * macro indirection (%[...]).
H. Peter Anvin76690a12002-04-30 20:52:49 +00003467 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003468static Token *expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003469{
H. Peter Anvin734b1882002-04-30 21:01:08 +00003470 Token *t, *tt, **tail, *thead;
H. Peter Anvin6125b622009-04-08 14:02:25 -07003471 bool changed = false;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003472
3473 tail = &thead;
3474 thead = NULL;
3475
H. Peter Anvine2c80182005-01-15 22:15:51 +00003476 while (tline) {
3477 if (tline->type == TOK_PREPROC_ID &&
3478 (((tline->text[1] == '+' || tline->text[1] == '-')
3479 && tline->text[2]) || tline->text[1] == '%'
3480 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003481 char *text = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003482 int type = 0, cc; /* type = 0 to placate optimisers */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003483 char tmpbuf[30];
H. Peter Anvin25a99342007-09-22 17:45:45 -07003484 unsigned int n;
3485 int i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003486 MMacro *mac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003487
H. Peter Anvine2c80182005-01-15 22:15:51 +00003488 t = tline;
3489 tline = tline->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003490
H. Peter Anvine2c80182005-01-15 22:15:51 +00003491 mac = istk->mstk;
3492 while (mac && !mac->name) /* avoid mistaking %reps for macros */
3493 mac = mac->next_active;
3494 if (!mac)
3495 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
3496 else
3497 switch (t->text[1]) {
3498 /*
3499 * We have to make a substitution of one of the
3500 * forms %1, %-1, %+1, %%foo, %0.
3501 */
3502 case '0':
3503 type = TOK_NUMBER;
3504 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
3505 text = nasm_strdup(tmpbuf);
3506 break;
3507 case '%':
3508 type = TOK_ID;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07003509 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
H. Peter Anvine2c80182005-01-15 22:15:51 +00003510 mac->unique);
3511 text = nasm_strcat(tmpbuf, t->text + 2);
3512 break;
3513 case '-':
3514 n = atoi(t->text + 2) - 1;
3515 if (n >= mac->nparam)
3516 tt = NULL;
3517 else {
3518 if (mac->nparam > 1)
3519 n = (n + mac->rotate) % mac->nparam;
3520 tt = mac->params[n];
3521 }
3522 cc = find_cc(tt);
3523 if (cc == -1) {
3524 error(ERR_NONFATAL,
3525 "macro parameter %d is not a condition code",
3526 n + 1);
3527 text = NULL;
3528 } else {
3529 type = TOK_ID;
3530 if (inverse_ccs[cc] == -1) {
3531 error(ERR_NONFATAL,
3532 "condition code `%s' is not invertible",
3533 conditions[cc]);
3534 text = NULL;
3535 } else
H. Peter Anvin67c63722008-10-26 23:49:00 -07003536 text = nasm_strdup(conditions[inverse_ccs[cc]]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003537 }
3538 break;
3539 case '+':
3540 n = atoi(t->text + 2) - 1;
3541 if (n >= mac->nparam)
3542 tt = NULL;
3543 else {
3544 if (mac->nparam > 1)
3545 n = (n + mac->rotate) % mac->nparam;
3546 tt = mac->params[n];
3547 }
3548 cc = find_cc(tt);
3549 if (cc == -1) {
3550 error(ERR_NONFATAL,
3551 "macro parameter %d is not a condition code",
3552 n + 1);
3553 text = NULL;
3554 } else {
3555 type = TOK_ID;
3556 text = nasm_strdup(conditions[cc]);
3557 }
3558 break;
3559 default:
3560 n = atoi(t->text + 1) - 1;
3561 if (n >= mac->nparam)
3562 tt = NULL;
3563 else {
3564 if (mac->nparam > 1)
3565 n = (n + mac->rotate) % mac->nparam;
3566 tt = mac->params[n];
3567 }
3568 if (tt) {
3569 for (i = 0; i < mac->paramlen[n]; i++) {
3570 *tail = new_Token(NULL, tt->type, tt->text, 0);
3571 tail = &(*tail)->next;
3572 tt = tt->next;
3573 }
3574 }
3575 text = NULL; /* we've done it here */
3576 break;
3577 }
3578 if (!text) {
3579 delete_Token(t);
3580 } else {
3581 *tail = t;
3582 tail = &t->next;
3583 t->type = type;
3584 nasm_free(t->text);
3585 t->text = text;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003586 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003587 }
H. Peter Anvin6125b622009-04-08 14:02:25 -07003588 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003589 continue;
H. Peter Anvin67c63722008-10-26 23:49:00 -07003590 } else if (tline->type == TOK_INDIRECT) {
3591 t = tline;
3592 tline = tline->next;
3593 tt = tokenize(t->text);
3594 tt = expand_mmac_params(tt);
3595 tt = expand_smacro(tt);
3596 *tail = tt;
3597 while (tt) {
3598 tt->a.mac = NULL; /* Necessary? */
3599 tail = &tt->next;
3600 tt = tt->next;
3601 }
3602 delete_Token(t);
H. Peter Anvin6125b622009-04-08 14:02:25 -07003603 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003604 } else {
3605 t = *tail = tline;
3606 tline = tline->next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003607 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003608 tail = &t->next;
3609 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003610 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00003611 *tail = NULL;
H. Peter Anvin67c63722008-10-26 23:49:00 -07003612
H. Peter Anvind784a082009-04-20 14:01:18 -07003613 if (changed)
H. Peter Anvinfc30f8c2009-07-06 18:48:23 -07003614 paste_tokens(&thead, false);
H. Peter Anvin6125b622009-04-08 14:02:25 -07003615
H. Peter Anvin76690a12002-04-30 20:52:49 +00003616 return thead;
3617}
3618
3619/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003620 * Expand all single-line macro calls made in the given line.
3621 * Return the expanded version of the line. The original is deemed
3622 * to be destroyed in the process. (In reality we'll just move
3623 * Tokens from input to output a lot of the time, rather than
3624 * actually bothering to destroy and replicate.)
3625 */
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003626#define DEADMAN_LIMIT (1 << 20)
3627
H. Peter Anvine2c80182005-01-15 22:15:51 +00003628static Token *expand_smacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003629{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003630 Token *t, *tt, *mstart, **tail, *thead;
H. Peter Anvin166c2472008-05-28 12:28:58 -07003631 struct hash_table *smtbl;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003632 SMacro *head = NULL, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003633 Token **params;
3634 int *paramsize;
H. Peter Anvin25a99342007-09-22 17:45:45 -07003635 unsigned int nparam, sparam;
H. Peter Anvind784a082009-04-20 14:01:18 -07003636 int brackets;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003637 Token *org_tline = tline;
3638 Context *ctx;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003639 const char *mname;
H. Peter Anvin2a15e692007-11-19 13:14:59 -08003640 int deadman = DEADMAN_LIMIT;
H. Peter Anvin8287daf2009-07-07 16:00:58 -07003641 bool expanded;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003642
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003643 /*
3644 * Trick: we should avoid changing the start token pointer since it can
3645 * be contained in "next" field of other token. Because of this
3646 * we allocate a copy of first token and work with it; at the end of
3647 * routine we copy it back
3648 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003649 if (org_tline) {
3650 tline =
3651 new_Token(org_tline->next, org_tline->type, org_tline->text,
3652 0);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003653 tline->a.mac = org_tline->a.mac;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003654 nasm_free(org_tline->text);
3655 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003656 }
3657
H. Peter Anvin8287daf2009-07-07 16:00:58 -07003658 expanded = true; /* Always expand %+ at least once */
3659
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003660again:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003661 tail = &thead;
3662 thead = NULL;
3663
H. Peter Anvine2c80182005-01-15 22:15:51 +00003664 while (tline) { /* main token loop */
H. Peter Anvin2a15e692007-11-19 13:14:59 -08003665 if (!--deadman) {
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003666 error(ERR_NONFATAL, "interminable macro recursion");
3667 break;
3668 }
3669
H. Peter Anvine2c80182005-01-15 22:15:51 +00003670 if ((mname = tline->text)) {
3671 /* if this token is a local macro, look in local context */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003672 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
3673 ctx = get_ctx(mname, &mname, true);
3674 else
3675 ctx = NULL;
3676 smtbl = ctx ? &ctx->localmac : &smacros;
H. Peter Anvin166c2472008-05-28 12:28:58 -07003677 head = (SMacro *) hash_findix(smtbl, mname);
H. Peter Anvin072771e2008-05-22 13:17:51 -07003678
H. Peter Anvine2c80182005-01-15 22:15:51 +00003679 /*
3680 * We've hit an identifier. As in is_mmacro below, we first
3681 * check whether the identifier is a single-line macro at
3682 * all, then think about checking for parameters if
3683 * necessary.
3684 */
H. Peter Anvin97a23472007-09-16 17:57:25 -07003685 for (m = head; m; m = m->next)
3686 if (!mstrcmp(m->name, mname, m->casesense))
3687 break;
3688 if (m) {
3689 mstart = tline;
3690 params = NULL;
3691 paramsize = NULL;
3692 if (m->nparam == 0) {
3693 /*
3694 * Simple case: the macro is parameterless. Discard the
3695 * one token that the macro call took, and push the
3696 * expansion back on the to-do stack.
3697 */
3698 if (!m->expansion) {
3699 if (!strcmp("__FILE__", m->name)) {
3700 int32_t num = 0;
H. Peter Anvin932de6c2008-07-31 18:46:11 -07003701 char *file = NULL;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003702 src_get(&num, &file);
3703 tline->text = nasm_quote(file, strlen(file));
H. Peter Anvin97a23472007-09-16 17:57:25 -07003704 tline->type = TOK_STRING;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003705 nasm_free(file);
H. Peter Anvin97a23472007-09-16 17:57:25 -07003706 continue;
3707 }
3708 if (!strcmp("__LINE__", m->name)) {
3709 nasm_free(tline->text);
3710 make_tok_num(tline, src_get_linnum());
3711 continue;
3712 }
3713 if (!strcmp("__BITS__", m->name)) {
3714 nasm_free(tline->text);
3715 make_tok_num(tline, globalbits);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003716 continue;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003717 }
3718 tline = delete_Token(tline);
3719 continue;
3720 }
3721 } else {
3722 /*
3723 * Complicated case: at least one macro with this name
H. Peter Anvine2c80182005-01-15 22:15:51 +00003724 * exists and takes parameters. We must find the
3725 * parameters in the call, count them, find the SMacro
3726 * that corresponds to that form of the macro call, and
3727 * substitute for the parameters when we expand. What a
3728 * pain.
3729 */
3730 /*tline = tline->next;
3731 skip_white_(tline); */
3732 do {
3733 t = tline->next;
3734 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003735 t->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003736 t->text = NULL;
3737 t = tline->next = delete_Token(t);
3738 }
3739 tline = t;
3740 } while (tok_type_(tline, TOK_WHITESPACE));
3741 if (!tok_is_(tline, "(")) {
3742 /*
3743 * This macro wasn't called with parameters: ignore
3744 * the call. (Behaviour borrowed from gnu cpp.)
3745 */
3746 tline = mstart;
3747 m = NULL;
3748 } else {
3749 int paren = 0;
3750 int white = 0;
3751 brackets = 0;
3752 nparam = 0;
3753 sparam = PARAM_DELTA;
3754 params = nasm_malloc(sparam * sizeof(Token *));
3755 params[0] = tline->next;
3756 paramsize = nasm_malloc(sparam * sizeof(int));
3757 paramsize[0] = 0;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003758 while (true) { /* parameter loop */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003759 /*
3760 * For some unusual expansions
3761 * which concatenates function call
3762 */
3763 t = tline->next;
3764 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003765 t->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003766 t->text = NULL;
3767 t = tline->next = delete_Token(t);
3768 }
3769 tline = t;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003770
H. Peter Anvine2c80182005-01-15 22:15:51 +00003771 if (!tline) {
3772 error(ERR_NONFATAL,
3773 "macro call expects terminating `)'");
3774 break;
3775 }
3776 if (tline->type == TOK_WHITESPACE
3777 && brackets <= 0) {
3778 if (paramsize[nparam])
3779 white++;
3780 else
3781 params[nparam] = tline->next;
3782 continue; /* parameter loop */
3783 }
3784 if (tline->type == TOK_OTHER
3785 && tline->text[1] == 0) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003786 char ch = tline->text[0];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003787 if (ch == ',' && !paren && brackets <= 0) {
3788 if (++nparam >= sparam) {
3789 sparam += PARAM_DELTA;
3790 params = nasm_realloc(params,
3791 sparam *
3792 sizeof(Token
3793 *));
3794 paramsize =
3795 nasm_realloc(paramsize,
3796 sparam *
3797 sizeof(int));
3798 }
3799 params[nparam] = tline->next;
3800 paramsize[nparam] = 0;
3801 white = 0;
3802 continue; /* parameter loop */
3803 }
3804 if (ch == '{' &&
3805 (brackets > 0 || (brackets == 0 &&
3806 !paramsize[nparam])))
3807 {
3808 if (!(brackets++)) {
3809 params[nparam] = tline->next;
3810 continue; /* parameter loop */
3811 }
3812 }
3813 if (ch == '}' && brackets > 0)
3814 if (--brackets == 0) {
3815 brackets = -1;
3816 continue; /* parameter loop */
3817 }
3818 if (ch == '(' && !brackets)
3819 paren++;
3820 if (ch == ')' && brackets <= 0)
3821 if (--paren < 0)
3822 break;
3823 }
3824 if (brackets < 0) {
3825 brackets = 0;
3826 error(ERR_NONFATAL, "braces do not "
3827 "enclose all of macro parameter");
3828 }
3829 paramsize[nparam] += white + 1;
3830 white = 0;
3831 } /* parameter loop */
3832 nparam++;
3833 while (m && (m->nparam != nparam ||
3834 mstrcmp(m->name, mname,
3835 m->casesense)))
3836 m = m->next;
3837 if (!m)
H. Peter Anvin917a3492008-09-24 09:14:49 -07003838 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003839 "macro `%s' exists, "
3840 "but not taking %d parameters",
3841 mstart->text, nparam);
3842 }
3843 }
3844 if (m && m->in_progress)
3845 m = NULL;
3846 if (!m) { /* in progess or didn't find '(' or wrong nparam */
H. Peter Anvin70653092007-10-19 14:42:29 -07003847 /*
H. Peter Anvine2c80182005-01-15 22:15:51 +00003848 * Design question: should we handle !tline, which
3849 * indicates missing ')' here, or expand those
3850 * macros anyway, which requires the (t) test a few
H. Peter Anvin70653092007-10-19 14:42:29 -07003851 * lines down?
H. Peter Anvine2c80182005-01-15 22:15:51 +00003852 */
3853 nasm_free(params);
3854 nasm_free(paramsize);
3855 tline = mstart;
3856 } else {
3857 /*
3858 * Expand the macro: we are placed on the last token of the
3859 * call, so that we can easily split the call from the
3860 * following tokens. We also start by pushing an SMAC_END
3861 * token for the cycle removal.
3862 */
3863 t = tline;
3864 if (t) {
3865 tline = t->next;
3866 t->next = NULL;
3867 }
3868 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003869 tt->a.mac = m;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003870 m->in_progress = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003871 tline = tt;
3872 for (t = m->expansion; t; t = t->next) {
3873 if (t->type >= TOK_SMAC_PARAM) {
3874 Token *pcopy = tline, **ptail = &pcopy;
3875 Token *ttt, *pt;
3876 int i;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003877
H. Peter Anvine2c80182005-01-15 22:15:51 +00003878 ttt = params[t->type - TOK_SMAC_PARAM];
3879 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3880 --i >= 0;) {
3881 pt = *ptail =
3882 new_Token(tline, ttt->type, ttt->text,
3883 0);
3884 ptail = &pt->next;
3885 ttt = ttt->next;
3886 }
3887 tline = pcopy;
H. Peter Anvin6c81f0a2008-05-25 21:46:17 -07003888 } else if (t->type == TOK_PREPROC_Q) {
3889 tt = new_Token(tline, TOK_ID, mname, 0);
3890 tline = tt;
3891 } else if (t->type == TOK_PREPROC_QQ) {
3892 tt = new_Token(tline, TOK_ID, m->name, 0);
3893 tline = tt;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003894 } else {
3895 tt = new_Token(tline, t->type, t->text, 0);
3896 tline = tt;
3897 }
3898 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003899
H. Peter Anvine2c80182005-01-15 22:15:51 +00003900 /*
3901 * Having done that, get rid of the macro call, and clean
3902 * up the parameters.
3903 */
3904 nasm_free(params);
3905 nasm_free(paramsize);
3906 free_tlist(mstart);
H. Peter Anvind784a082009-04-20 14:01:18 -07003907 expanded = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003908 continue; /* main token loop */
3909 }
3910 }
3911 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003912
H. Peter Anvine2c80182005-01-15 22:15:51 +00003913 if (tline->type == TOK_SMAC_END) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003914 tline->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003915 tline = delete_Token(tline);
3916 } else {
3917 t = *tail = tline;
3918 tline = tline->next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003919 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003920 t->next = NULL;
3921 tail = &t->next;
3922 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003923 }
3924
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003925 /*
3926 * Now scan the entire line and look for successive TOK_IDs that resulted
Keith Kaniosb7a89542007-04-12 02:40:54 +00003927 * after expansion (they can't be produced by tokenize()). The successive
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003928 * TOK_IDs should be concatenated.
3929 * Also we look for %+ tokens and concatenate the tokens before and after
3930 * them (without white spaces in between).
3931 */
H. Peter Anvin8287daf2009-07-07 16:00:58 -07003932 if (expanded && paste_tokens(&thead, true)) {
H. Peter Anvinfc30f8c2009-07-06 18:48:23 -07003933 /*
3934 * If we concatenated something, *and* we had previously expanded
3935 * an actual macro, scan the lines again for macros...
3936 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003937 tline = thead;
H. Peter Anvin8287daf2009-07-07 16:00:58 -07003938 expanded = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003939 goto again;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003940 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003941
H. Peter Anvine2c80182005-01-15 22:15:51 +00003942 if (org_tline) {
3943 if (thead) {
3944 *org_tline = *thead;
3945 /* since we just gave text to org_line, don't free it */
3946 thead->text = NULL;
3947 delete_Token(thead);
3948 } else {
3949 /* the expression expanded to empty line;
3950 we can't return NULL for some reasons
3951 we just set the line to a single WHITESPACE token. */
3952 memset(org_tline, 0, sizeof(*org_tline));
3953 org_tline->text = NULL;
3954 org_tline->type = TOK_WHITESPACE;
3955 }
3956 thead = org_tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003957 }
3958
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003959 return thead;
3960}
3961
3962/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003963 * Similar to expand_smacro but used exclusively with macro identifiers
3964 * right before they are fetched in. The reason is that there can be
3965 * identifiers consisting of several subparts. We consider that if there
3966 * are more than one element forming the name, user wants a expansion,
3967 * otherwise it will be left as-is. Example:
3968 *
3969 * %define %$abc cde
3970 *
3971 * the identifier %$abc will be left as-is so that the handler for %define
3972 * will suck it and define the corresponding value. Other case:
3973 *
3974 * %define _%$abc cde
3975 *
3976 * In this case user wants name to be expanded *before* %define starts
3977 * working, so we'll expand %$abc into something (if it has a value;
3978 * otherwise it will be left as-is) then concatenate all successive
3979 * PP_IDs into one.
3980 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003981static Token *expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003982{
3983 Token *cur, *oldnext = NULL;
3984
H. Peter Anvin734b1882002-04-30 21:01:08 +00003985 if (!tline || !tline->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003986 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003987
3988 cur = tline;
3989 while (cur->next &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00003990 (cur->next->type == TOK_ID ||
3991 cur->next->type == TOK_PREPROC_ID
3992 || cur->next->type == TOK_NUMBER))
3993 cur = cur->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003994
3995 /* If identifier consists of just one token, don't expand */
3996 if (cur == tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003997 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003998
H. Peter Anvine2c80182005-01-15 22:15:51 +00003999 if (cur) {
4000 oldnext = cur->next; /* Detach the tail past identifier */
4001 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004002 }
4003
H. Peter Anvin734b1882002-04-30 21:01:08 +00004004 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004005
H. Peter Anvine2c80182005-01-15 22:15:51 +00004006 if (cur) {
4007 /* expand_smacro possibly changhed tline; re-scan for EOL */
4008 cur = tline;
4009 while (cur && cur->next)
4010 cur = cur->next;
4011 if (cur)
4012 cur->next = oldnext;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004013 }
4014
4015 return tline;
4016}
4017
4018/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004019 * Determine whether the given line constitutes a multi-line macro
4020 * call, and return the MMacro structure called if so. Doesn't have
4021 * to check for an initial label - that's taken care of in
4022 * expand_mmacro - but must check numbers of parameters. Guaranteed
4023 * to be called with tline->type == TOK_ID, so the putative macro
4024 * name is easy to find.
4025 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004026static MMacro *is_mmacro(Token * tline, Token *** params_array)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004027{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004028 MMacro *head, *m;
4029 Token **params;
4030 int nparam;
4031
H. Peter Anvin166c2472008-05-28 12:28:58 -07004032 head = (MMacro *) hash_findix(&mmacros, tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004033
4034 /*
4035 * Efficiency: first we see if any macro exists with the given
4036 * name. If not, we can return NULL immediately. _Then_ we
4037 * count the parameters, and then we look further along the
4038 * list if necessary to find the proper MMacro.
4039 */
4040 for (m = head; m; m = m->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004041 if (!mstrcmp(m->name, tline->text, m->casesense))
4042 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004043 if (!m)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004044 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004045
4046 /*
4047 * OK, we have a potential macro. Count and demarcate the
4048 * parameters.
4049 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00004050 count_mmac_params(tline->next, &nparam, &params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004051
4052 /*
4053 * So we know how many parameters we've got. Find the MMacro
4054 * structure that handles this number.
4055 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004056 while (m) {
4057 if (m->nparam_min <= nparam
4058 && (m->plus || nparam <= m->nparam_max)) {
4059 /*
4060 * This one is right. Just check if cycle removal
4061 * prohibits us using it before we actually celebrate...
4062 */
4063 if (m->in_progress) {
H. Peter Anvineba20a72002-04-30 20:53:55 +00004064#if 0
H. Peter Anvine2c80182005-01-15 22:15:51 +00004065 error(ERR_NONFATAL,
4066 "self-reference in multi-line macro `%s'", m->name);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004067#endif
H. Peter Anvine2c80182005-01-15 22:15:51 +00004068 nasm_free(params);
4069 return NULL;
4070 }
4071 /*
4072 * It's right, and we can use it. Add its default
4073 * parameters to the end of our list if necessary.
4074 */
4075 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
4076 params =
4077 nasm_realloc(params,
4078 ((m->nparam_min + m->ndefs +
4079 1) * sizeof(*params)));
4080 while (nparam < m->nparam_min + m->ndefs) {
4081 params[nparam] = m->defaults[nparam - m->nparam_min];
4082 nparam++;
4083 }
4084 }
4085 /*
4086 * If we've gone over the maximum parameter count (and
4087 * we're in Plus mode), ignore parameters beyond
4088 * nparam_max.
4089 */
4090 if (m->plus && nparam > m->nparam_max)
4091 nparam = m->nparam_max;
4092 /*
4093 * Then terminate the parameter list, and leave.
4094 */
4095 if (!params) { /* need this special case */
4096 params = nasm_malloc(sizeof(*params));
4097 nparam = 0;
4098 }
4099 params[nparam] = NULL;
4100 *params_array = params;
4101 return m;
4102 }
4103 /*
4104 * This one wasn't right: look for the next one with the
4105 * same name.
4106 */
4107 for (m = m->next; m; m = m->next)
4108 if (!mstrcmp(m->name, tline->text, m->casesense))
4109 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004110 }
4111
4112 /*
4113 * After all that, we didn't find one with the right number of
4114 * parameters. Issue a warning, and fail to expand the macro.
4115 */
H. Peter Anvin917a3492008-09-24 09:14:49 -07004116 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00004117 "macro `%s' exists, but not taking %d parameters",
4118 tline->text, nparam);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004119 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004120 return NULL;
4121}
4122
4123/*
4124 * Expand the multi-line macro call made by the given line, if
4125 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvineba20a72002-04-30 20:53:55 +00004126 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004127 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004128static int expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004129{
4130 Token *startline = tline;
4131 Token *label = NULL;
4132 int dont_prepend = 0;
H. Peter Anvince2233b2008-05-25 21:57:00 -07004133 Token **params, *t, *mtok, *tt;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004134 MMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004135 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004136 int i, nparam, *paramlen;
H. Peter Anvinc751e862008-06-09 10:18:45 -07004137 const char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004138
4139 t = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004140 skip_white_(t);
H. Peter Anvince2233b2008-05-25 21:57:00 -07004141 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00004142 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004143 return 0;
H. Peter Anvince2233b2008-05-25 21:57:00 -07004144 mtok = t;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004145 m = is_mmacro(t, &params);
H. Peter Anvinc751e862008-06-09 10:18:45 -07004146 if (m) {
4147 mname = t->text;
4148 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004149 Token *last;
4150 /*
4151 * We have an id which isn't a macro call. We'll assume
4152 * it might be a label; we'll also check to see if a
4153 * colon follows it. Then, if there's another id after
4154 * that lot, we'll check it again for macro-hood.
4155 */
4156 label = last = t;
4157 t = t->next;
4158 if (tok_type_(t, TOK_WHITESPACE))
4159 last = t, t = t->next;
4160 if (tok_is_(t, ":")) {
4161 dont_prepend = 1;
4162 last = t, t = t->next;
4163 if (tok_type_(t, TOK_WHITESPACE))
4164 last = t, t = t->next;
4165 }
4166 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
4167 return 0;
4168 last->next = NULL;
H. Peter Anvinc751e862008-06-09 10:18:45 -07004169 mname = t->text;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004170 tline = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004171 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004172
4173 /*
4174 * Fix up the parameters: this involves stripping leading and
4175 * trailing whitespace, then stripping braces if they are
4176 * present.
4177 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004178 for (nparam = 0; params[nparam]; nparam++) ;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004179 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004180
H. Peter Anvine2c80182005-01-15 22:15:51 +00004181 for (i = 0; params[i]; i++) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004182 int brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004183 int comma = (!m->plus || i < nparam - 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004184
H. Peter Anvine2c80182005-01-15 22:15:51 +00004185 t = params[i];
4186 skip_white_(t);
4187 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004188 t = t->next, brace = true, comma = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004189 params[i] = t;
4190 paramlen[i] = 0;
4191 while (t) {
4192 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
4193 break; /* ... because we have hit a comma */
4194 if (comma && t->type == TOK_WHITESPACE
4195 && tok_is_(t->next, ","))
4196 break; /* ... or a space then a comma */
4197 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
4198 break; /* ... or a brace */
4199 t = t->next;
4200 paramlen[i]++;
4201 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004202 }
4203
4204 /*
4205 * OK, we have a MMacro structure together with a set of
4206 * parameters. We must now go through the expansion and push
H. Peter Anvin76690a12002-04-30 20:52:49 +00004207 * copies of each Line on to istk->expansion. Substitution of
4208 * parameter tokens and macro-local tokens doesn't get done
4209 * until the single-line macro substitution process; this is
4210 * because delaying them allows us to change the semantics
4211 * later through %rotate.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004212 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00004213 * First, push an end marker on to istk->expansion, mark this
4214 * macro as in progress, and set up its invocation-specific
4215 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004216 */
4217 ll = nasm_malloc(sizeof(Line));
4218 ll->next = istk->expansion;
4219 ll->finishes = m;
4220 ll->first = NULL;
4221 istk->expansion = ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004222
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004223 m->in_progress = true;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004224 m->params = params;
4225 m->iline = tline;
4226 m->nparam = nparam;
4227 m->rotate = 0;
4228 m->paramlen = paramlen;
4229 m->unique = unique++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004230 m->lineno = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004231
4232 m->next_active = istk->mstk;
4233 istk->mstk = m;
4234
H. Peter Anvine2c80182005-01-15 22:15:51 +00004235 for (l = m->expansion; l; l = l->next) {
4236 Token **tail;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004237
H. Peter Anvine2c80182005-01-15 22:15:51 +00004238 ll = nasm_malloc(sizeof(Line));
4239 ll->finishes = NULL;
4240 ll->next = istk->expansion;
4241 istk->expansion = ll;
4242 tail = &ll->first;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004243
H. Peter Anvine2c80182005-01-15 22:15:51 +00004244 for (t = l->first; t; t = t->next) {
4245 Token *x = t;
H. Peter Anvince2233b2008-05-25 21:57:00 -07004246 switch (t->type) {
4247 case TOK_PREPROC_Q:
H. Peter Anvinc751e862008-06-09 10:18:45 -07004248 tt = *tail = new_Token(NULL, TOK_ID, mname, 0);
H. Peter Anvince2233b2008-05-25 21:57:00 -07004249 break;
4250 case TOK_PREPROC_QQ:
4251 tt = *tail = new_Token(NULL, TOK_ID, m->name, 0);
4252 break;
4253 case TOK_PREPROC_ID:
4254 if (t->text[1] == '0' && t->text[2] == '0') {
4255 dont_prepend = -1;
4256 x = label;
4257 if (!x)
4258 continue;
4259 }
4260 /* fall through */
4261 default:
4262 tt = *tail = new_Token(NULL, x->type, x->text, 0);
4263 break;
H. Peter Anvin166c2472008-05-28 12:28:58 -07004264 }
H. Peter Anvince2233b2008-05-25 21:57:00 -07004265 tail = &tt->next;
4266 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004267 *tail = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004268 }
4269
4270 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00004271 * If we had a label, push it on as the first line of
4272 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004273 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004274 if (label) {
4275 if (dont_prepend < 0)
4276 free_tlist(startline);
4277 else {
4278 ll = nasm_malloc(sizeof(Line));
4279 ll->finishes = NULL;
4280 ll->next = istk->expansion;
4281 istk->expansion = ll;
4282 ll->first = startline;
4283 if (!dont_prepend) {
4284 while (label->next)
4285 label = label->next;
4286 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
4287 }
4288 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004289 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004290
H. Peter Anvin734b1882002-04-30 21:01:08 +00004291 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004292
H. Peter Anvineba20a72002-04-30 20:53:55 +00004293 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004294}
4295
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004296/* The function that actually does the error reporting */
4297static void verror(int severity, const char *fmt, va_list arg)
4298{
4299 char buff[1024];
4300
4301 vsnprintf(buff, sizeof(buff), fmt, arg);
4302
4303 if (istk && istk->mstk && istk->mstk->name)
H. Peter Anvin917a3492008-09-24 09:14:49 -07004304 _error(severity, "(%s:%d) %s", istk->mstk->name,
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004305 istk->mstk->lineno, buff);
4306 else
H. Peter Anvin917a3492008-09-24 09:14:49 -07004307 _error(severity, "%s", buff);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004308}
4309
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004310/*
4311 * Since preprocessor always operate only on the line that didn't
H. Peter Anvin917a3492008-09-24 09:14:49 -07004312 * arrived yet, we should always use ERR_OFFBY1.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004313 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004314static void error(int severity, const char *fmt, ...)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004315{
4316 va_list arg;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004317
4318 /* If we're in a dead branch of IF or something like it, ignore the error */
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00004319 if (istk && istk->conds && !emitting(istk->conds->state))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004320 return;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004321
H. Peter Anvin734b1882002-04-30 21:01:08 +00004322 va_start(arg, fmt);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004323 verror(severity, fmt, arg);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004324 va_end(arg);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004325}
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004326
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004327/*
4328 * Because %else etc are evaluated in the state context
4329 * of the previous branch, errors might get lost with error():
4330 * %if 0 ... %else trailing garbage ... %endif
4331 * So %else etc should report errors with this function.
4332 */
4333static void error_precond(int severity, const char *fmt, ...)
4334{
4335 va_list arg;
4336
4337 /* Only ignore the error if it's really in a dead branch */
4338 if (istk && istk->conds && istk->conds->state == COND_NEVER)
4339 return;
4340
4341 va_start(arg, fmt);
4342 verror(severity, fmt, arg);
4343 va_end(arg);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004344}
4345
H. Peter Anvin734b1882002-04-30 21:01:08 +00004346static void
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004347pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07004348 ListGen * listgen, StrList **deplist)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004349{
H. Peter Anvin7383b402008-09-24 10:20:40 -07004350 Token *t;
4351
H. Peter Anvin99941bf2002-05-14 17:44:03 +00004352 _error = errfunc;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004353 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004354 istk = nasm_malloc(sizeof(Include));
4355 istk->next = NULL;
4356 istk->conds = NULL;
4357 istk->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004358 istk->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004359 istk->fp = fopen(file, "r");
H. Peter Anvineba20a72002-04-30 20:53:55 +00004360 istk->fname = NULL;
4361 src_set_fname(nasm_strdup(file));
4362 src_set_linnum(0);
4363 istk->lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004364 if (!istk->fp)
H. Peter Anvin917a3492008-09-24 09:14:49 -07004365 error(ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'",
H. Peter Anvine2c80182005-01-15 22:15:51 +00004366 file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004367 defining = NULL;
Charles Crayned4200be2008-07-12 16:42:33 -07004368 nested_mac_count = 0;
4369 nested_rep_count = 0;
H. Peter Anvin97a23472007-09-16 17:57:25 -07004370 init_macros();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004371 unique = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004372 if (tasm_compatible_mode) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07004373 stdmacpos = nasm_stdmac;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004374 } else {
H. Peter Anvina4835d42008-05-20 14:21:29 -07004375 stdmacpos = nasm_stdmac_after_tasm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004376 }
H. Peter Anvind2456592008-06-19 15:04:18 -07004377 any_extrastdmac = extrastdmac && *extrastdmac;
4378 do_predef = true;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004379 list = listgen;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004380 evaluate = eval;
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004381
4382 /*
4383 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4384 * The caller, however, will also pass in 3 for preprocess-only so
4385 * we can set __PASS__ accordingly.
4386 */
4387 pass = apass > 2 ? 2 : apass;
4388
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07004389 dephead = deptail = deplist;
4390 if (deplist) {
4391 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
4392 sl->next = NULL;
4393 strcpy(sl->str, file);
4394 *deptail = sl;
4395 deptail = &sl->next;
4396 }
H. Peter Anvin7383b402008-09-24 10:20:40 -07004397
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004398 /*
4399 * Define the __PASS__ macro. This is defined here unlike
4400 * all the other builtins, because it is special -- it varies between
4401 * passes.
4402 */
H. Peter Anvin7383b402008-09-24 10:20:40 -07004403 t = nasm_malloc(sizeof(*t));
4404 t->next = NULL;
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004405 make_tok_num(t, apass);
H. Peter Anvin7383b402008-09-24 10:20:40 -07004406 t->a.mac = NULL;
4407 define_smacro(NULL, "__PASS__", true, 0, t);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004408}
4409
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004410static char *pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004411{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004412 char *line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004413 Token *tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004414
H. Peter Anvine2c80182005-01-15 22:15:51 +00004415 while (1) {
4416 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00004417 * Fetch a tokenized line, either from the macro-expansion
H. Peter Anvine2c80182005-01-15 22:15:51 +00004418 * buffer or from the input file.
4419 */
4420 tline = NULL;
4421 while (istk->expansion && istk->expansion->finishes) {
4422 Line *l = istk->expansion;
4423 if (!l->finishes->name && l->finishes->in_progress > 1) {
4424 Line *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004425
H. Peter Anvine2c80182005-01-15 22:15:51 +00004426 /*
4427 * This is a macro-end marker for a macro with no
4428 * name, which means it's not really a macro at all
4429 * but a %rep block, and the `in_progress' field is
4430 * more than 1, meaning that we still need to
4431 * repeat. (1 means the natural last repetition; 0
4432 * means termination by %exitrep.) We have
4433 * therefore expanded up to the %endrep, and must
4434 * push the whole block on to the expansion buffer
4435 * again. We don't bother to remove the macro-end
4436 * marker: we'd only have to generate another one
4437 * if we did.
4438 */
4439 l->finishes->in_progress--;
4440 for (l = l->finishes->expansion; l; l = l->next) {
4441 Token *t, *tt, **tail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004442
H. Peter Anvine2c80182005-01-15 22:15:51 +00004443 ll = nasm_malloc(sizeof(Line));
4444 ll->next = istk->expansion;
4445 ll->finishes = NULL;
4446 ll->first = NULL;
4447 tail = &ll->first;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004448
H. Peter Anvine2c80182005-01-15 22:15:51 +00004449 for (t = l->first; t; t = t->next) {
4450 if (t->text || t->type == TOK_WHITESPACE) {
4451 tt = *tail =
4452 new_Token(NULL, t->type, t->text, 0);
4453 tail = &tt->next;
4454 }
4455 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004456
H. Peter Anvine2c80182005-01-15 22:15:51 +00004457 istk->expansion = ll;
4458 }
4459 } else {
4460 /*
4461 * Check whether a `%rep' was started and not ended
4462 * within this macro expansion. This can happen and
4463 * should be detected. It's a fatal error because
4464 * I'm too confused to work out how to recover
4465 * sensibly from it.
4466 */
4467 if (defining) {
4468 if (defining->name)
4469 error(ERR_PANIC,
4470 "defining with name in expansion");
4471 else if (istk->mstk->name)
4472 error(ERR_FATAL,
4473 "`%%rep' without `%%endrep' within"
4474 " expansion of macro `%s'",
4475 istk->mstk->name);
4476 }
H. Peter Anvin87bc6192002-04-30 20:53:16 +00004477
H. Peter Anvine2c80182005-01-15 22:15:51 +00004478 /*
4479 * FIXME: investigate the relationship at this point between
4480 * istk->mstk and l->finishes
4481 */
4482 {
4483 MMacro *m = istk->mstk;
4484 istk->mstk = m->next_active;
4485 if (m->name) {
4486 /*
4487 * This was a real macro call, not a %rep, and
4488 * therefore the parameter information needs to
4489 * be freed.
4490 */
4491 nasm_free(m->params);
4492 free_tlist(m->iline);
4493 nasm_free(m->paramlen);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004494 l->finishes->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004495 } else
4496 free_mmacro(m);
4497 }
4498 istk->expansion = l->next;
4499 nasm_free(l);
4500 list->downlevel(LIST_MACRO);
4501 }
4502 }
4503 while (1) { /* until we get a line we can use */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004504
H. Peter Anvine2c80182005-01-15 22:15:51 +00004505 if (istk->expansion) { /* from a macro expansion */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004506 char *p;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004507 Line *l = istk->expansion;
4508 if (istk->mstk)
4509 istk->mstk->lineno++;
4510 tline = l->first;
4511 istk->expansion = l->next;
4512 nasm_free(l);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004513 p = detoken(tline, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004514 list->line(LIST_MACRO, p);
4515 nasm_free(p);
4516 break;
4517 }
4518 line = read_line();
4519 if (line) { /* from the current input file */
4520 line = prepreproc(line);
Keith Kaniosb7a89542007-04-12 02:40:54 +00004521 tline = tokenize(line);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004522 nasm_free(line);
4523 break;
4524 }
4525 /*
4526 * The current file has ended; work down the istk
4527 */
4528 {
4529 Include *i = istk;
4530 fclose(i->fp);
4531 if (i->conds)
4532 error(ERR_FATAL,
4533 "expected `%%endif' before end of file");
4534 /* only set line and file name if there's a next node */
4535 if (i->next) {
4536 src_set_linnum(i->lineno);
4537 nasm_free(src_set_fname(i->fname));
H. Peter Anvin86877b22008-06-20 15:55:45 -07004538 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004539 istk = i->next;
4540 list->downlevel(LIST_INCLUDE);
4541 nasm_free(i);
4542 if (!istk)
4543 return NULL;
Victor van den Elzen4c9d6222008-10-01 13:08:50 +02004544 if (istk->expansion && istk->expansion->finishes)
4545 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004546 }
4547 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004548
H. Peter Anvine2c80182005-01-15 22:15:51 +00004549 /*
4550 * We must expand MMacro parameters and MMacro-local labels
4551 * _before_ we plunge into directive processing, to cope
4552 * with things like `%define something %1' such as STRUC
4553 * uses. Unless we're _defining_ a MMacro, in which case
4554 * those tokens should be left alone to go into the
4555 * definition; and unless we're in a non-emitting
4556 * condition, in which case we don't want to meddle with
4557 * anything.
4558 */
Charles Crayned4200be2008-07-12 16:42:33 -07004559 if (!defining && !(istk->conds && !emitting(istk->conds->state))
H. Peter Anvin992fe752008-10-19 15:45:05 -07004560 && !(istk->mstk && !istk->mstk->in_progress)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004561 tline = expand_mmac_params(tline);
H. Peter Anvin992fe752008-10-19 15:45:05 -07004562 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004563
H. Peter Anvine2c80182005-01-15 22:15:51 +00004564 /*
4565 * Check the line to see if it's a preprocessor directive.
4566 */
4567 if (do_directive(tline) == DIRECTIVE_FOUND) {
4568 continue;
4569 } else if (defining) {
4570 /*
4571 * We're defining a multi-line macro. We emit nothing
4572 * at all, and just
Keith Kaniosb7a89542007-04-12 02:40:54 +00004573 * shove the tokenized line on to the macro definition.
H. Peter Anvine2c80182005-01-15 22:15:51 +00004574 */
4575 Line *l = nasm_malloc(sizeof(Line));
4576 l->next = defining->expansion;
4577 l->first = tline;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004578 l->finishes = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004579 defining->expansion = l;
4580 continue;
4581 } else if (istk->conds && !emitting(istk->conds->state)) {
4582 /*
4583 * We're in a non-emitting branch of a condition block.
4584 * Emit nothing at all, not even a blank line: when we
4585 * emerge from the condition we'll give a line-number
4586 * directive so we keep our place correctly.
4587 */
4588 free_tlist(tline);
4589 continue;
4590 } else if (istk->mstk && !istk->mstk->in_progress) {
4591 /*
4592 * We're in a %rep block which has been terminated, so
4593 * we're walking through to the %endrep without
4594 * emitting anything. Emit nothing at all, not even a
4595 * blank line: when we emerge from the %rep block we'll
4596 * give a line-number directive so we keep our place
4597 * correctly.
4598 */
4599 free_tlist(tline);
4600 continue;
4601 } else {
4602 tline = expand_smacro(tline);
4603 if (!expand_mmacro(tline)) {
4604 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00004605 * De-tokenize the line again, and emit it.
H. Peter Anvine2c80182005-01-15 22:15:51 +00004606 */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004607 line = detoken(tline, true);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004608 free_tlist(tline);
4609 break;
4610 } else {
4611 continue; /* expand_mmacro calls free_tlist */
4612 }
4613 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004614 }
4615
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004616 return line;
4617}
4618
H. Peter Anvine2c80182005-01-15 22:15:51 +00004619static void pp_cleanup(int pass)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004620{
H. Peter Anvine2c80182005-01-15 22:15:51 +00004621 if (defining) {
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02004622 if(defining->name) {
4623 error(ERR_NONFATAL,
4624 "end of file while still defining macro `%s'",
4625 defining->name);
4626 } else {
4627 error(ERR_NONFATAL, "end of file while still in %%rep");
4628 }
4629
H. Peter Anvine2c80182005-01-15 22:15:51 +00004630 free_mmacro(defining);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004631 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004632 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004633 ctx_pop();
H. Peter Anvin97a23472007-09-16 17:57:25 -07004634 free_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00004635 while (istk) {
4636 Include *i = istk;
4637 istk = istk->next;
4638 fclose(i->fp);
4639 nasm_free(i->fname);
4640 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004641 }
4642 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004643 ctx_pop();
H. Peter Anvin86877b22008-06-20 15:55:45 -07004644 nasm_free(src_set_fname(NULL));
H. Peter Anvine2c80182005-01-15 22:15:51 +00004645 if (pass == 0) {
H. Peter Anvin86877b22008-06-20 15:55:45 -07004646 IncPath *i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004647 free_llist(predef);
4648 delete_Blocks();
H. Peter Anvin86877b22008-06-20 15:55:45 -07004649 while ((i = ipath)) {
4650 ipath = i->next;
4651 if (i->path)
4652 nasm_free(i->path);
4653 nasm_free(i);
4654 }
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07004655 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004656}
4657
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004658void pp_include_path(char *path)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004659{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004660 IncPath *i;
H. Peter Anvin37a321f2007-09-24 13:41:58 -07004661
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004662 i = nasm_malloc(sizeof(IncPath));
H. Peter Anvin37a321f2007-09-24 13:41:58 -07004663 i->path = path ? nasm_strdup(path) : NULL;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004664 i->next = NULL;
4665
H. Peter Anvine2c80182005-01-15 22:15:51 +00004666 if (ipath != NULL) {
4667 IncPath *j = ipath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004668 while (j->next != NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004669 j = j->next;
4670 j->next = i;
4671 } else {
4672 ipath = i;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004673 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004674}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004675
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004676void pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004677{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004678 Token *inc, *space, *name;
4679 Line *l;
4680
H. Peter Anvin734b1882002-04-30 21:01:08 +00004681 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
4682 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
4683 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004684
4685 l = nasm_malloc(sizeof(Line));
4686 l->next = predef;
4687 l->first = inc;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004688 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004689 predef = l;
4690}
4691
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004692void pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004693{
4694 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004695 Line *l;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004696 char *equals;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004697
4698 equals = strchr(definition, '=');
H. Peter Anvin734b1882002-04-30 21:01:08 +00004699 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4700 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004701 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004702 *equals = ' ';
Keith Kaniosb7a89542007-04-12 02:40:54 +00004703 space->next = tokenize(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004704 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004705 *equals = '=';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004706
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004707 l = nasm_malloc(sizeof(Line));
4708 l->next = predef;
4709 l->first = def;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004710 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004711 predef = l;
4712}
4713
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004714void pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00004715{
4716 Token *def, *space;
4717 Line *l;
4718
H. Peter Anvin734b1882002-04-30 21:01:08 +00004719 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4720 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Keith Kaniosb7a89542007-04-12 02:40:54 +00004721 space->next = tokenize(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00004722
4723 l = nasm_malloc(sizeof(Line));
4724 l->next = predef;
4725 l->first = def;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004726 l->finishes = NULL;
H. Peter Anvin620515a2002-04-30 20:57:38 +00004727 predef = l;
4728}
4729
Keith Kaniosb7a89542007-04-12 02:40:54 +00004730/*
4731 * Added by Keith Kanios:
4732 *
4733 * This function is used to assist with "runtime" preprocessor
4734 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4735 *
4736 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4737 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4738 */
4739
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004740void pp_runtime(char *definition)
Keith Kaniosb7a89542007-04-12 02:40:54 +00004741{
4742 Token *def;
H. Peter Anvin70653092007-10-19 14:42:29 -07004743
Keith Kaniosb7a89542007-04-12 02:40:54 +00004744 def = tokenize(definition);
4745 if(do_directive(def) == NO_DIRECTIVE_FOUND)
4746 free_tlist(def);
H. Peter Anvin70653092007-10-19 14:42:29 -07004747
Keith Kaniosb7a89542007-04-12 02:40:54 +00004748}
4749
H. Peter Anvina70547f2008-07-19 21:44:26 -07004750void pp_extra_stdmac(macros_t *macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004751{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004752 extrastdmac = macros;
4753}
4754
Keith Kaniosa5fc6462007-10-13 07:09:22 -07004755static void make_tok_num(Token * tok, int64_t val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004756{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004757 char numbuf[20];
Keith Kaniosa5fc6462007-10-13 07:09:22 -07004758 snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004759 tok->text = nasm_strdup(numbuf);
4760 tok->type = TOK_NUMBER;
4761}
4762
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004763Preproc nasmpp = {
4764 pp_reset,
4765 pp_getline,
4766 pp_cleanup
4767};