blob: 69c870870b78aadb9ad40491bac79e5ea2298591 [file] [log] [blame]
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07001/* ----------------------------------------------------------------------- *
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002 *
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07003 * Copyright 1996-2020 The NASM Authors - All Rights Reserved
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07004 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07007 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000010 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -070011 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
Cyrill Gorcunovaccda192010-02-16 10:27:56 +030017 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -070018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * ----------------------------------------------------------------------- */
33
34/*
35 * preproc.c macro preprocessor for the Netwide Assembler
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000036 */
37
H. Peter Anvin4836e332002-04-30 20:56:43 +000038/* Typical flow of text through preproc
39 *
Keith Kaniosb7a89542007-04-12 02:40:54 +000040 * pp_getline gets tokenized lines, either
H. Peter Anvin4836e332002-04-30 20:56:43 +000041 *
42 * from a macro expansion
43 *
44 * or
45 * {
46 * read_line gets raw text from stdmacpos, or predef, or current input file
Keith Kaniosb7a89542007-04-12 02:40:54 +000047 * tokenize converts to tokens
H. Peter Anvin4836e332002-04-30 20:56:43 +000048 * }
49 *
50 * expand_mmac_params is used to expand %1 etc., unless a macro is being
51 * defined or a false conditional is being processed
52 * (%0, %1, %+1, %-1, %%foo
53 *
54 * do_directive checks for directives
55 *
56 * expand_smacro is used to expand single line macros
57 *
58 * expand_mmacro is used to expand multi-line macros
59 *
60 * detoken is used to convert the line back to text
61 */
H. Peter Anvineba20a72002-04-30 20:53:55 +000062
H. Peter Anvinfe501952007-10-02 21:53:51 -070063#include "compiler.h"
64
H. Peter Anvinc2f3f262018-12-27 12:37:25 -080065#include "nctype.h"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000066
67#include "nasm.h"
68#include "nasmlib.h"
H. Peter Anvinb20bc732017-03-07 19:23:03 -080069#include "error.h"
H. Peter Anvin4169a472007-09-12 01:29:43 +000070#include "preproc.h"
H. Peter Anvin97a23472007-09-16 17:57:25 -070071#include "hashtbl.h"
H. Peter Anvin8cad14b2008-06-01 17:23:51 -070072#include "quote.h"
H. Peter Anvinc2df2822007-10-24 15:29:28 -070073#include "stdscan.h"
H. Peter Anvindbb640b2009-07-18 18:57:16 -070074#include "eval.h"
H. Peter Anvinc2df2822007-10-24 15:29:28 -070075#include "tokens.h"
H. Peter Anvina4835d42008-05-20 14:21:29 -070076#include "tables.h"
H. Peter Anvin8ac25aa2016-02-18 01:16:18 -080077#include "listing.h"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000078
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -070079/*
80 * Preprocessor execution options that can be controlled by %pragma or
81 * other directives. This structure is initialized to zero on each
82 * pass; this *must* reflect the default initial state.
83 */
84static struct pp_opts {
85 bool noaliases;
86 bool sane_empty_expansion;
87} ppopt;
88
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000089typedef struct SMacro SMacro;
H. Peter Anvin36206cd2012-03-03 16:14:51 -080090typedef struct MMacro MMacro;
91typedef struct MMacroInvocation MMacroInvocation;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000092typedef struct Context Context;
93typedef struct Token Token;
94typedef struct Line Line;
95typedef struct Include Include;
H. Peter Anvin36206cd2012-03-03 16:14:51 -080096typedef struct Cond Cond;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000097
98/*
H. Peter Anvin8571f062019-09-23 16:40:03 -070099 * This is the internal form which we break input lines up into.
100 * Typically stored in linked lists.
101 *
102 * Note that `type' serves a double meaning: TOK_SMAC_START_PARAMS is
103 * not necessarily used as-is, but is also used to encode the number
104 * and expansion type of substituted parameter. So in the definition
105 *
106 * %define a(x,=y) ( (x) & ~(y) )
107 *
108 * the token representing `x' will have its type changed to
109 * tok_smac_param(0) but the one representing `y' will be
110 * tok_smac_param(1); see the accessor functions below.
111 *
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700112 * TOK_INTERNAL_STRING is a string which has been unquoted, but should
113 * be treated as if it was a quoted string. The code is free to change
114 * one into the other at will. TOK_NAKED_STRING is a text token which
115 * should be treated as a string, but which MUST NOT be turned into a
116 * quoted string. TOK_INTERNAL_STRINGs can contain any character,
117 * including NUL, but TOK_NAKED_STRING must be a valid C string.
H. Peter Anvin8571f062019-09-23 16:40:03 -0700118 */
119enum pp_token_type {
120 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT,
121 TOK_CORRUPT, /* Token text modified in an unsafe manner, now bogus */
122 TOK_BLOCK, /* Storage block pointer, not a real token */
123 TOK_ID,
124 TOK_PREPROC_ID, TOK_MMACRO_PARAM, TOK_LOCAL_SYMBOL,
125 TOK_LOCAL_MACRO, TOK_ENVIRON, TOK_STRING,
126 TOK_NUMBER, TOK_FLOAT, TOK_OTHER,
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700127 TOK_INTERNAL_STRING, TOK_NAKED_STRING,
H. Peter Anvin8571f062019-09-23 16:40:03 -0700128 TOK_PREPROC_Q, TOK_PREPROC_QQ,
129 TOK_PASTE, /* %+ */
130 TOK_COND_COMMA, /* %, */
131 TOK_INDIRECT, /* %[...] */
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700132 TOK_XDEF_PARAM, /* Used during %xdefine processing */
H. Peter Anvin8571f062019-09-23 16:40:03 -0700133 TOK_SMAC_START_PARAMS, /* MUST BE LAST IN THE LIST!!! */
134 TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
135};
136
137static inline enum pp_token_type tok_smac_param(int param)
138{
139 return TOK_SMAC_START_PARAMS + param;
140}
141static int smac_nparam(enum pp_token_type toktype)
142{
143 return toktype - TOK_SMAC_START_PARAMS;
144}
145static bool is_smac_param(enum pp_token_type toktype)
146{
147 return toktype >= TOK_SMAC_START_PARAMS;
148}
149
150#define PP_CONCAT_MASK(x) (1U << (x))
151
152struct tokseq_match {
153 int mask_head;
154 int mask_tail;
155};
156
157/*
158 * This is tuned so struct Token should be 64 bytes on 64-bit
159 * systems and 32 bytes on 32-bit systems. It enables them
160 * to be nicely cache aligned, and the text to still be kept
161 * inline for nearly all tokens.
162 *
163 * We prohibit tokens of length > MAX_TEXT even though
164 * length here is an unsigned int; this avoids problems
165 * if the length is passed through an interface with type "int",
166 * and is absurdly large anyway.
167 *
168 * For the text mode, in pointer mode the pointer is stored at the end
169 * of the union and the pad field is cleared. This allows short tokens
170 * to be unconditionally tested for by only looking at the first text
171 * bytes and not examining the type or len fields.
172 */
173#define INLINE_TEXT (7*sizeof(char *)-sizeof(enum pp_token_type)-sizeof(unsigned int)-1)
174#define MAX_TEXT (INT_MAX-2)
175
176struct Token {
177 Token *next;
178 enum pp_token_type type;
179 unsigned int len;
180 union {
181 char a[INLINE_TEXT+1];
182 struct {
183 char pad[INLINE_TEXT+1 - sizeof(char *)];
184 char *ptr;
185 } p;
186 } text;
187};
188
189/*
H. Peter Anvin97a23472007-09-16 17:57:25 -0700190 * Note on the storage of both SMacro and MMacros: the hash table
191 * indexes them case-insensitively, and we then have to go through a
192 * linked list of potential case aliases (and, for MMacros, parameter
193 * ranges); this is to preserve the matching semantics of the earlier
194 * code. If the number of case aliases for a specific macro is a
195 * performance issue, you may want to reconsider your coding style.
196 */
197
198/*
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -0700199 * Function call tp obtain the expansion of an smacro
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -0700200 */
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -0700201typedef Token *(*ExpandSMacro)(const SMacro *s, Token **params, int nparams);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -0700202
203/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000204 * Store the definition of a single-line macro.
205 */
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -0700206enum sparmflags {
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -0700207 SPARM_PLAIN = 0,
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -0700208 SPARM_EVAL = 1, /* Evaluate as a numeric expression (=) */
209 SPARM_STR = 2, /* Convert to quoted string ($) */
210 SPARM_NOSTRIP = 4, /* Don't strip braces (!) */
211 SPARM_GREEDY = 8 /* Greedy final parameter (+) */
212};
213
214struct smac_param {
H. Peter Anvin8571f062019-09-23 16:40:03 -0700215 Token name;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -0700216 enum sparmflags flags;
217};
218
H. Peter Anvine2c80182005-01-15 22:15:51 +0000219struct SMacro {
H. Peter Anvin8b262472019-02-26 14:00:54 -0800220 SMacro *next; /* MUST BE FIRST - see free_smacro() */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800221 char *name;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -0700222 Token *expansion;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -0700223 ExpandSMacro expand;
224 intorptr expandpvt;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -0700225 struct smac_param *params;
226 int nparam;
227 bool greedy;
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800228 bool casesense;
229 bool in_progress;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -0700230 bool alias; /* This is an alias macro */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000231};
232
233/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800234 * Store the definition of a multi-line macro. This is also used to
235 * store the interiors of `%rep...%endrep' blocks, which are
236 * effectively self-re-invoking multi-line macros which simply
237 * don't have a name or bother to appear in the hash tables. %rep
238 * blocks are signified by having a NULL `name' field.
239 *
240 * In a MMacro describing a `%rep' block, the `in_progress' field
241 * isn't merely boolean, but gives the number of repeats left to
242 * run.
243 *
244 * The `next' field is used for storing MMacros in hash tables; the
245 * `next_active' field is for stacking them on istk entries.
246 *
247 * When a MMacro is being expanded, `params', `iline', `nparam',
248 * `paramlen', `rotate' and `unique' are local to the invocation.
249 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700250
251/*
252 * Expansion stack. Note that .mmac can point back to the macro itself,
253 * whereas .mstk cannot.
254 */
255struct mstk {
256 MMacro *mstk; /* Any expansion, real macro or not */
257 MMacro *mmac; /* Highest level actual mmacro */
258};
259
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800260struct MMacro {
261 MMacro *next;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700262#if 0
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800263 MMacroInvocation *prev; /* previous invocation */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700264#endif
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800265 char *name;
266 int nparam_min, nparam_max;
267 bool casesense;
268 bool plus; /* is the last parameter greedy? */
269 bool nolist; /* is this macro listing-inhibited? */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700270 bool capture_label; /* macro definition has %00; capture label */
271 int32_t in_progress; /* is this macro currently being expanded? */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800272 int32_t max_depth; /* maximum number of recursive expansions allowed */
273 Token *dlist; /* All defaults as one list */
274 Token **defaults; /* Parameter default pointers */
275 int ndefs; /* number of default parameters */
276 Line *expansion;
277
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700278 struct mstk mstk; /* Macro expansion stack */
279 struct mstk dstk; /* Macro definitions stack */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800280 Token **params; /* actual parameters */
281 Token *iline; /* invocation line */
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700282 struct src_location where; /* location of definition */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800283 unsigned int nparam, rotate;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700284 char *iname; /* name invoked as */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800285 int *paramlen;
286 uint64_t unique;
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800287 uint64_t condcnt; /* number of if blocks... */
288};
289
290
291/* Store the definition of a multi-line macro, as defined in a
292 * previous recursive macro expansion.
293 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700294#if 0
295
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800296struct MMacroInvocation {
297 MMacroInvocation *prev; /* previous invocation */
298 Token **params; /* actual parameters */
299 Token *iline; /* invocation line */
300 unsigned int nparam, rotate;
301 int *paramlen;
302 uint64_t unique;
303 uint64_t condcnt;
304};
305
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700306#endif
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800307
308/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000309 * The context stack is composed of a linked list of these.
310 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000311struct Context {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800312 Context *next;
H. Peter Anvin8571f062019-09-23 16:40:03 -0700313 const char *name;
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800314 struct hash_table localmac;
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -0700315 uint64_t number;
316 unsigned int depth;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000317};
318
H. Peter Anvin8571f062019-09-23 16:40:03 -0700319
320static inline const char *tok_text(const struct Token *t)
321{
322 return (t->len <= INLINE_TEXT) ? t->text.a : t->text.p.ptr;
323}
324
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000325/*
H. Peter Anvin8571f062019-09-23 16:40:03 -0700326 * Returns a mutable pointer to the text buffer. The text can be changed,
327 * but the length MUST NOT CHANGE, in either direction; nor is it permitted
328 * to pad with null characters to create an artificially shorter string.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000329 */
H. Peter Anvin8571f062019-09-23 16:40:03 -0700330static inline char *tok_text_buf(struct Token *t)
H. Peter Anvin8b262472019-02-26 14:00:54 -0800331{
H. Peter Anvin8571f062019-09-23 16:40:03 -0700332 return (t->len <= INLINE_TEXT) ? t->text.a : t->text.p.ptr;
H. Peter Anvin8b262472019-02-26 14:00:54 -0800333}
334
H. Peter Anvin8571f062019-09-23 16:40:03 -0700335static inline unsigned int tok_check_len(size_t len)
336{
337 if (unlikely(len > MAX_TEXT))
338 nasm_fatal("impossibly large token");
Cyrill Gorcunov8dcbbd72010-09-25 02:33:20 +0400339
H. Peter Anvin8571f062019-09-23 16:40:03 -0700340 return len;
341}
Cyrill Gorcunov575d4282010-10-06 00:25:55 +0400342
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700343static inline bool tok_text_match(const struct Token *a, const struct Token *b)
344{
345 return a->len == b->len && !memcmp(tok_text(a), tok_text(b), a->len);
346}
347
348static inline bool tok_match(const struct Token *a, const struct Token *b)
349{
350 return a->type == b->type && tok_text_match(a, b);
351}
352
H. Peter Anvin8571f062019-09-23 16:40:03 -0700353/* strlen() variant useful for set_text() and its variants */
354static size_t tok_strlen(const char *str)
355{
356 return strnlen(str, MAX_TEXT+1);
357}
358
359/*
360 * Set the text field to a copy of the given string; the length if
361 * not given should be obtained with tok_strlen().
362 */
363static Token *set_text(struct Token *t, const char *text, size_t len)
364{
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700365 char *textp;
366
H. Peter Anvin8571f062019-09-23 16:40:03 -0700367 if (t->len > INLINE_TEXT)
368 nasm_free(t->text.p.ptr);
369
H. Peter Anvin (Intel)00335e42020-06-14 19:49:19 -0700370 nasm_zero(t->text);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700371
H. Peter Anvin (Intel)00335e42020-06-14 19:49:19 -0700372 t->len = len = tok_check_len(len);
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700373 textp = (len > INLINE_TEXT)
374 ? (t->text.p.ptr = nasm_malloc(len+1)) : t->text.a;
375 memcpy(textp, text, len);
376 textp[len] = '\0';
H. Peter Anvin8571f062019-09-23 16:40:03 -0700377 return t;
378}
379
380/*
381 * Set the text field to the existing pre-allocated string, either
382 * taking over or freeing the allocation in the process.
383 */
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700384static Token *set_text_free(struct Token *t, char *text, unsigned int len)
H. Peter Anvin8571f062019-09-23 16:40:03 -0700385{
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700386 char *textp;
387
H. Peter Anvin8571f062019-09-23 16:40:03 -0700388 if (t->len > INLINE_TEXT)
389 nasm_free(t->text.p.ptr);
390
H. Peter Anvin (Intel)00335e42020-06-14 19:49:19 -0700391 nasm_zero(t->text);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700392
H. Peter Anvin (Intel)00335e42020-06-14 19:49:19 -0700393 t->len = len = tok_check_len(len);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700394 if (len > INLINE_TEXT) {
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700395 textp = t->text.p.ptr = text;
H. Peter Anvin8571f062019-09-23 16:40:03 -0700396 } else {
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700397 textp = memcpy(t->text.a, text, len);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700398 nasm_free(text);
399 }
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700400 textp[len] = '\0';
H. Peter Anvin8571f062019-09-23 16:40:03 -0700401
402 return t;
403}
404
405/*
406 * Allocate a new buffer containing a copy of the text field
407 * of the token.
408 */
409static char *dup_text(const struct Token *t)
410{
411 size_t size = t->len + 1;
412 char *p = nasm_malloc(size);
413
414 return memcpy(p, tok_text(t), size);
415}
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000416
417/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800418 * Multi-line macro definitions are stored as a linked list of
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000419 * these, which is essentially a container to allow several linked
420 * lists of Tokens.
H. Peter Anvin70653092007-10-19 14:42:29 -0700421 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000422 * Note that in this module, linked lists are treated as stacks
423 * wherever possible. For this reason, Lines are _pushed_ on to the
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800424 * `expansion' field in MMacro structures, so that the linked list,
425 * if walked, would give the macro lines in reverse order; this
426 * means that we can walk the list when expanding a macro, and thus
427 * push the lines on to the `expansion' field in _istk_ in reverse
428 * order (so that when popped back off they are in the right
429 * order). It may seem cockeyed, and it relies on my design having
430 * an even number of steps in, but it works...
431 *
432 * Some of these structures, rather than being actual lines, are
433 * markers delimiting the end of the expansion of a given macro.
434 * This is for use in the cycle-tracking and %rep-handling code.
435 * Such structures have `finishes' non-NULL, and `first' NULL. All
436 * others have `finishes' NULL, but `first' may still be NULL if
437 * the line is blank.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000438 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000439struct Line {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800440 Line *next;
441 MMacro *finishes;
442 Token *first;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700443 struct src_location where; /* Where defined */
Keith Kaniosb307a4f2010-11-06 17:41:51 -0500444};
445
446/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000447 * To handle an arbitrary level of file inclusion, we maintain a
448 * stack (ie linked list) of these things.
449 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000450struct Include {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800451 Include *next;
452 FILE *fp;
453 Cond *conds;
454 Line *expansion;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700455 struct mstk mstk;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700456 struct src_location where; /* Filename and current line number */
457 int32_t lineinc; /* Increment given by %line */
H. Peter Anvin6686de22019-08-10 05:33:14 -0700458 bool nolist;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000459};
460
461/*
H. Peter Anvin169ac7c2016-09-25 17:08:05 -0700462 * File real name hash, so we don't have to re-search the include
463 * path for every pass (and potentially more than that if a file
464 * is used more than once.)
465 */
466struct hash_table FileHash;
467
468/*
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -0700469 * Counters to trap on insane macro recursion or processing.
470 * Note: for smacros these count *down*, for mmacros they count *up*.
471 */
472struct deadman {
473 int64_t total; /* Total number of macros/tokens */
474 int64_t levels; /* Descent depth across all macros */
475 bool triggered; /* Already triggered, no need for error msg */
476};
477
478static struct deadman smacro_deadman, mmacro_deadman;
479
480/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000481 * Conditional assembly: we maintain a separate stack of these for
482 * each level of file inclusion. (The only reason we keep the
483 * stacks separate is to ensure that a stray `%endif' in a file
484 * included from within the true branch of a `%if' won't terminate
485 * it and cause confusion: instead, rightly, it'll cause an error.)
486 */
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -0700487enum cond_state {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000488 /*
489 * These states are for use just after %if or %elif: IF_TRUE
490 * means the condition has evaluated to truth so we are
491 * currently emitting, whereas IF_FALSE means we are not
492 * currently emitting but will start doing so if a %else comes
493 * up. In these states, all directives are admissible: %elif,
494 * %else and %endif. (And of course %if.)
495 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800496 COND_IF_TRUE, COND_IF_FALSE,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000497 /*
498 * These states come up after a %else: ELSE_TRUE means we're
499 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
500 * any %elif or %else will cause an error.
501 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800502 COND_ELSE_TRUE, COND_ELSE_FALSE,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000503 /*
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200504 * These states mean that we're not emitting now, and also that
505 * nothing until %endif will be emitted at all. COND_DONE is
506 * used when we've had our moment of emission
507 * and have now started seeing %elifs. COND_NEVER is used when
508 * the condition construct in question is contained within a
509 * non-emitting branch of a larger condition construct,
510 * or if there is an error.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000511 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800512 COND_DONE, COND_NEVER
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000513};
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -0700514struct Cond {
515 Cond *next;
516 enum cond_state state;
517};
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800518#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000519
H. Peter Anvin70653092007-10-19 14:42:29 -0700520/*
Ed Beroset3ab3f412002-06-11 03:31:49 +0000521 * These defines are used as the possible return values for do_directive
522 */
523#define NO_DIRECTIVE_FOUND 0
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300524#define DIRECTIVE_FOUND 1
Ed Beroset3ab3f412002-06-11 03:31:49 +0000525
Keith Kanios852f1ee2009-07-12 00:19:55 -0500526/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000527 * Condition codes. Note that we use c_ prefix not C_ because C_ is
528 * used in nasm.h for the "real" condition codes. At _this_ level,
529 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
530 * ones, so we need a different enum...
531 */
H. Peter Anvin476d2862007-10-02 22:04:15 -0700532static const char * const conditions[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000533 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
534 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
H. Peter Anvince9be342007-09-12 00:22:29 +0000535 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000536};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700537enum pp_conds {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000538 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
539 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 -0700540 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
541 c_none = -1
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000542};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700543static const enum pp_conds inverse_ccs[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000544 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
545 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 +0000546 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000547};
548
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800549/*
550 * Directive names.
551 */
552/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
553static int is_condition(enum preproc_token arg)
554{
555 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
556}
557
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000558/* For TASM compatibility we need to be able to recognise TASM compatible
559 * conditional compilation directives. Using the NASM pre-processor does
560 * not work, so we look for them specifically from the following list and
561 * then jam in the equivalent NASM directive into the input stream.
562 */
563
H. Peter Anvine2c80182005-01-15 22:15:51 +0000564enum {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000565 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
566 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
567};
568
H. Peter Anvin476d2862007-10-02 22:04:15 -0700569static const char * const tasm_directives[] = {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000570 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
571 "ifndef", "include", "local"
572};
573
574static int StackSize = 4;
H. Peter Anvin6c8b2be2016-05-24 23:46:50 -0700575static const char *StackPointer = "ebp";
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000576static int ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -0800577static int LocalOffset = 0;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000578
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000579static Context *cstk;
580static Include *istk;
Cyrill Gorcunov8c0666b2018-11-24 14:33:48 +0300581static const struct strlist *ipath_list;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000582
Cyrill Gorcunovb7bb5ac2018-11-11 21:33:52 +0300583static struct strlist *deplist;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000584
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300585static uint64_t unique; /* unique identifier numbers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000586
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800587static Line *predef = NULL;
H. Peter Anvind2456592008-06-19 15:04:18 -0700588static bool do_predef;
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800589static enum preproc_mode pp_mode;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000590
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000591/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800592 * The current set of multi-line macros we have defined.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000593 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800594static struct hash_table mmacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000595
596/*
597 * The current set of single-line macros we have defined.
598 */
H. Peter Anvin166c2472008-05-28 12:28:58 -0700599static struct hash_table smacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000600
601/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800602 * The multi-line macro we are currently defining, or the %rep
603 * block we are currently reading, if any.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000604 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800605static MMacro *defining;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000606
Charles Crayned4200be2008-07-12 16:42:33 -0700607static uint64_t nested_mac_count;
608static uint64_t nested_rep_count;
609
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000610/*
611 * The number of macro parameters to allocate space for at a time.
612 */
613#define PARAM_DELTA 16
614
615/*
H. Peter Anvinf7606612016-07-13 14:23:48 -0700616 * The standard macro set: defined in macros.c in a set of arrays.
617 * This gives our position in any macro set, while we are processing it.
618 * The stdmacset is an array of such macro sets.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000619 */
H. Peter Anvina70547f2008-07-19 21:44:26 -0700620static macros_t *stdmacpos;
H. Peter Anvinf7606612016-07-13 14:23:48 -0700621static macros_t **stdmacnext;
622static macros_t *stdmacros[8];
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +0300623static macros_t *extrastdmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000624
625/*
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -0700626 * Map of which %use packages have been loaded
627 */
628static bool *use_loaded;
629
630/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000631 * Forward declarations.
632 */
H. Peter Anvinf7606612016-07-13 14:23:48 -0700633static void pp_add_stdmac(macros_t *macros);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000634static Token *expand_mmac_params(Token * tline);
635static Token *expand_smacro(Token * tline);
636static Token *expand_id(Token * tline);
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +0400637static Context *get_ctx(const char *name, const char **namep);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700638static Token *make_tok_num(Token *next, int64_t val);
639static Token *make_tok_qstr(Token *next, const char *str);
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -0700640static Token *make_tok_qstr_len(Token *next, const char *str, size_t len);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700641static Token *make_tok_char(Token *next, char op);
H. Peter Anvinc751e862008-06-09 10:18:45 -0700642static Token *new_Token(Token * next, enum pp_token_type type,
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -0700643 const char *text, size_t txtlen);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700644static Token *new_Token_free(Token * next, enum pp_token_type type,
645 char *text, size_t txtlen);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -0700646static Token *dup_Token(Token *next, const Token *src);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -0700647static Token *new_White(Token *next);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700648static Token *delete_Token(Token *t);
649static Token *steal_Token(Token *dst, Token *src);
H. Peter Anvindd88aa92019-09-12 19:39:48 -0700650static const struct use_package *
H. Peter Anvin8571f062019-09-23 16:40:03 -0700651get_use_pkg(Token *t, const char *dname, const char **name);
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -0700652static void mark_smac_params(Token *tline, const SMacro *tmpl,
653 enum pp_token_type type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000654
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -0700655/* Safe test for token type, false on x == NULL */
656static inline bool tok_type(const Token *x, enum pp_token_type t)
657{
658 return x && x->type == t;
659}
660
661/* Whitespace token? */
662static inline bool tok_white(const Token *x)
663{
664 return tok_type(x, TOK_WHITESPACE);
665}
666
667/* Skip past any whitespace */
668static inline Token *skip_white(Token *x)
669{
670 while (tok_white(x))
671 x = x->next;
672
673 return x;
674}
675
676/* Delete any whitespace */
677static Token *zap_white(Token *x)
678{
679 while (tok_white(x))
680 x = delete_Token(x);
681
682 return x;
683}
684
H. Peter Anvin8571f062019-09-23 16:40:03 -0700685/*
686 * Single special character tests. The use of & rather than && is intentional; it
687 * tells the compiler that it is safe to access text.a[1] unconditionally; hopefully
688 * a smart compiler should turn it into a 16-bit memory reference.
689 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -0700690static inline bool tok_is(const Token *x, char c)
691{
H. Peter Anvin8571f062019-09-23 16:40:03 -0700692 return x && ((x->text.a[0] == c) & !x->text.a[1]);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -0700693}
694
695/* True if any other kind of token that "c", but not NULL */
696static inline bool tok_isnt(const Token *x, char c)
697{
H. Peter Anvin8571f062019-09-23 16:40:03 -0700698 return x && !((x->text.a[0] == c) & !x->text.a[1]);
699}
700
701/*
702 * Unquote a token if it is a string, and set its type to
703 * TOK_INTERNAL_STRING.
704 */
705static const char *unquote_token(Token *t)
706{
707 if (t->type != TOK_STRING)
708 return tok_text(t);
709
710 t->type = TOK_INTERNAL_STRING;
711
712 if (t->len > INLINE_TEXT) {
713 char *p = t->text.p.ptr;
714
715 t->len = nasm_unquote(p, NULL);
716
717 if (t->len <= INLINE_TEXT) {
718 nasm_zero(t->text.a);
719 memcpy(t->text.a, p, t->len);
720 nasm_free(p);
721 return t->text.a;
722 } else {
723 return p;
724 }
725 } else {
726 t->len = nasm_unquote(t->text.a, NULL);
727 return t->text.a;
728 }
729}
730
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700731/*
732 * Same as unquote_token(), but error out if the resulting string
733 * contains unacceptable control characters.
734 */
H. Peter Anvin8571f062019-09-23 16:40:03 -0700735static const char *unquote_token_cstr(Token *t)
736{
737 if (t->type != TOK_STRING)
738 return tok_text(t);
739
740 t->type = TOK_INTERNAL_STRING;
741
742 if (t->len > INLINE_TEXT) {
743 char *p = t->text.p.ptr;
744
745 t->len = nasm_unquote_cstr(p, NULL);
746
747 if (t->len <= INLINE_TEXT) {
748 nasm_zero(t->text.a);
749 memcpy(t->text.a, p, t->len);
750 nasm_free(p);
751 return t->text.a;
752 } else {
753 return p;
754 }
755 } else {
756 t->len = nasm_unquote_cstr(t->text.a, NULL);
757 return t->text.a;
758 }
759}
760
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700761/*
762 * Convert a TOK_INTERNAL_STRING token to a quoted
763 * TOK_STRING tokens.
764 */
765static Token *quote_any_token(Token *t);
766static inline Token *quote_token(Token *t)
767{
768 if (likely(!tok_is(t, TOK_INTERNAL_STRING)))
769 return t;
770
771 return quote_any_token(t);
772}
773
774/*
775 * Convert *any* kind of token to a quoted
776 * TOK_STRING token.
777 */
778static Token *quote_any_token(Token *t)
H. Peter Anvin8571f062019-09-23 16:40:03 -0700779{
780 size_t len;
781 char *p;
782
783 p = nasm_quote(tok_text(t), &len);
784 t->type = TOK_STRING;
785 return set_text_free(t, p, len);
786}
787
Cyrill Gorcunov194ba892011-06-30 01:16:35 +0400788/*
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700789 * In-place reverse a list of tokens.
790 */
791static Token *reverse_tokens(Token *t)
792{
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800793 Token *prev = NULL;
794 Token *next;
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700795
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800796 while (t) {
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +0400797 next = t->next;
798 t->next = prev;
799 prev = t;
800 t = next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800801 }
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700802
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800803 return prev;
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700804}
805
806/*
H. Peter Anvin8571f062019-09-23 16:40:03 -0700807 * getenv() variant operating on an input token
808 */
809static const char *pp_getenv(const Token *t, bool warn)
810{
811 const char *txt = tok_text(t);
812 const char *v;
813 char *buf = NULL;
814 bool is_string = false;
815
816 if (!t)
817 return NULL;
818
819 switch (t->type) {
820 case TOK_ENVIRON:
821 txt += 2; /* Skip leading %! */
822 is_string = nasm_isquote(*txt);
823 break;
824
825 case TOK_STRING:
826 is_string = true;
827 break;
828
829 case TOK_INTERNAL_STRING:
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700830 case TOK_NAKED_STRING:
H. Peter Anvin8571f062019-09-23 16:40:03 -0700831 case TOK_ID:
832 is_string = false;
833 break;
834
835 default:
836 return NULL;
837 }
838
839 if (is_string) {
840 buf = nasm_strdup(txt);
841 nasm_unquote_cstr(buf, NULL);
842 txt = buf;
843 }
844
845 v = getenv(txt);
846 if (warn && !v) {
847 /*!
848 *!environment [on] nonexistent environment variable
849 *! warns if a nonexistent environment variable
850 *! is accessed using the \c{%!} preprocessor
851 *! construct (see \k{getenv}.) Such environment
852 *! variables are treated as empty (with this
853 *! warning issued) starting in NASM 2.15;
854 *! earlier versions of NASM would treat this as
855 *! an error.
856 */
857 nasm_warn(WARN_ENVIRONMENT, "nonexistent environment variable `%s'", txt);
858 v = "";
859 }
860
861 if (buf)
862 nasm_free(buf);
863
864 return v;
865}
866
867/*
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300868 * Handle TASM specific directives, which do not contain a % in
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000869 * front of them. We do it here because I could not find any other
870 * place to do it for the moment, and it is a hack (ideally it would
871 * be nice to be able to use the NASM pre-processor to do it).
872 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000873static char *check_tasm_directive(char *line)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000874{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000875 int32_t i, j, k, m, len;
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400876 char *p, *q, *oldline, oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000877
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400878 p = nasm_skip_spaces(line);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000879
880 /* Binary search for the directive name */
881 i = -1;
Cyrill Gorcunova7319242010-06-03 22:04:36 +0400882 j = ARRAY_SIZE(tasm_directives);
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400883 q = nasm_skip_word(p);
884 len = q - p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000885 if (len) {
886 oldchar = p[len];
887 p[len] = 0;
888 while (j - i > 1) {
889 k = (j + i) / 2;
890 m = nasm_stricmp(p, tasm_directives[k]);
891 if (m == 0) {
892 /* We have found a directive, so jam a % in front of it
893 * so that NASM will then recognise it as one if it's own.
894 */
895 p[len] = oldchar;
896 len = strlen(p);
897 oldline = line;
898 line = nasm_malloc(len + 2);
899 line[0] = '%';
900 if (k == TM_IFDIFI) {
H. Peter Anvin18f48792009-06-27 15:56:27 -0700901 /*
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300902 * NASM does not recognise IFDIFI, so we convert
903 * it to %if 0. This is not used in NASM
904 * compatible code, but does need to parse for the
905 * TASM macro package.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000906 */
H. Peter Anvin18f48792009-06-27 15:56:27 -0700907 strcpy(line + 1, "if 0");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000908 } else {
909 memcpy(line + 1, p, len + 1);
910 }
911 nasm_free(oldline);
912 return line;
913 } else if (m < 0) {
914 j = k;
915 } else
916 i = k;
917 }
918 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000919 }
920 return line;
921}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000922
H. Peter Anvin76690a12002-04-30 20:52:49 +0000923/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000924 * The pre-preprocessing stage... This function translates line
925 * number indications as they emerge from GNU cpp (`# lineno "file"
926 * flags') into NASM preprocessor line number indications (`%line
927 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000928 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000929static char *prepreproc(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000930{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000931 int lineno, fnlen;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000932 char *fname, *oldline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000933
H. Peter Anvine2c80182005-01-15 22:15:51 +0000934 if (line[0] == '#' && line[1] == ' ') {
935 oldline = line;
936 fname = oldline + 2;
937 lineno = atoi(fname);
938 fname += strspn(fname, "0123456789 ");
939 if (*fname == '"')
940 fname++;
941 fnlen = strcspn(fname, "\"");
942 line = nasm_malloc(20 + fnlen);
943 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
944 nasm_free(oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000945 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000946 if (tasm_compatible_mode)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000947 return check_tasm_directive(line);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000948 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000949}
950
951/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000952 * Free a linked list of tokens.
953 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000954static void free_tlist(Token * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000955{
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400956 while (list)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000957 list = delete_Token(list);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000958}
959
960/*
961 * Free a linked list of lines.
962 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000963static void free_llist(Line * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000964{
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400965 Line *l, *tmp;
966 list_for_each_safe(l, tmp, list) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000967 free_tlist(l->first);
968 nasm_free(l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000969 }
970}
971
972/*
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -0700973 * Free an array of linked lists of tokens
974 */
975static void free_tlist_array(Token **array, size_t nlists)
976{
977 Token **listp = array;
978
979 while (nlists--)
980 free_tlist(*listp++);
981
982 nasm_free(array);
983}
984
985/*
986 * Duplicate a linked list of tokens.
987 */
988static Token *dup_tlist(const Token *list, Token ***tailp)
989{
990 Token *newlist = NULL;
991 Token **tailpp = &newlist;
992 const Token *t;
993
994 list_for_each(t, list) {
995 Token *nt;
996 *tailpp = nt = dup_Token(NULL, t);
997 tailpp = &nt->next;
998 }
999
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001000 if (tailp) {
1001 **tailp = newlist;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07001002 *tailp = tailpp;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001003 }
1004
1005 return newlist;
1006}
1007
1008/*
1009 * Duplicate a linked list of tokens with a maximum count
1010 */
1011static Token *dup_tlistn(const Token *list, size_t cnt, Token ***tailp)
1012{
1013 Token *newlist = NULL;
1014 Token **tailpp = &newlist;
1015 const Token *t;
1016
1017 list_for_each(t, list) {
1018 Token *nt;
1019 if (!cnt--)
1020 break;
1021 *tailpp = nt = dup_Token(NULL, t);
1022 tailpp = &nt->next;
1023 }
1024
1025 if (tailp) {
1026 **tailp = newlist;
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07001027 if (newlist)
1028 *tailp = tailpp;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001029 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07001030
1031 return newlist;
1032}
1033
1034/*
1035 * Duplicate a linked list of tokens in reverse order
1036 */
1037static Token *dup_tlist_reverse(const Token *list, Token *tail)
1038{
1039 const Token *t;
1040
1041 list_for_each(t, list)
1042 tail = dup_Token(tail, t);
1043
1044 return tail;
1045}
1046
1047/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001048 * Free an MMacro
H. Peter Anvineba20a72002-04-30 20:53:55 +00001049 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001050static void free_mmacro(MMacro * m)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001051{
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001052 nasm_free(m->name);
1053 free_tlist(m->dlist);
1054 nasm_free(m->defaults);
1055 free_llist(m->expansion);
1056 nasm_free(m);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001057}
1058
1059/*
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001060 * Clear or free an SMacro
H. Peter Anvin8b262472019-02-26 14:00:54 -08001061 */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001062static void free_smacro_members(SMacro *s)
H. Peter Anvin8b262472019-02-26 14:00:54 -08001063{
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07001064 if (s->params) {
1065 int i;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001066 for (i = 0; i < s->nparam; i++) {
1067 if (s->params[i].name.len > INLINE_TEXT)
1068 nasm_free(s->params[i].name.text.p.ptr);
1069 }
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07001070 nasm_free(s->params);
1071 }
H. Peter Anvin8b262472019-02-26 14:00:54 -08001072 nasm_free(s->name);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001073 free_tlist(s->expansion);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001074}
1075
1076static void clear_smacro(SMacro *s)
1077{
1078 free_smacro_members(s);
1079 /* Wipe everything except the next pointer */
1080 memset(&s->next + 1, 0, sizeof *s - sizeof s->next);
1081}
1082
1083/*
1084 * Free an SMacro
1085 */
1086static void free_smacro(SMacro *s)
1087{
1088 free_smacro_members(s);
1089 nasm_free(s);
H. Peter Anvin8b262472019-02-26 14:00:54 -08001090}
1091
1092/*
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001093 * Free all currently defined macros, and free the hash tables if empty
H. Peter Anvin97a23472007-09-16 17:57:25 -07001094 */
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001095enum clear_what {
1096 CLEAR_NONE = 0,
1097 CLEAR_DEFINE = 1, /* Clear smacros */
1098 CLEAR_DEFALIAS = 2, /* Clear smacro aliases */
1099 CLEAR_ALLDEFINE = CLEAR_DEFINE|CLEAR_DEFALIAS,
1100 CLEAR_MMACRO = 4,
1101 CLEAR_ALL = CLEAR_ALLDEFINE|CLEAR_MMACRO
1102};
1103
1104static void clear_smacro_table(struct hash_table *smt, enum clear_what what)
H. Peter Anvin97a23472007-09-16 17:57:25 -07001105{
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001106 struct hash_iterator it;
1107 const struct hash_node *np;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001108 bool empty = true;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001109
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001110 /*
1111 * Walk the hash table and clear out anything we don't want
1112 */
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001113 hash_for_each(smt, it, np) {
1114 SMacro *tmp;
1115 SMacro *s = np->data;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001116 SMacro **head = (SMacro **)&np->data;
1117
1118 list_for_each_safe(s, tmp, s) {
1119 if (what & ((enum clear_what)s->alias + 1)) {
1120 *head = s->next;
1121 free_smacro(s);
1122 } else {
1123 empty = false;
1124 }
1125 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07001126 }
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001127
1128 /*
1129 * Free the hash table and keys if and only if it is now empty.
1130 * Note: we cannot free keys even for an empty list above, as that
1131 * mucks up the hash algorithm.
1132 */
1133 if (empty)
1134 hash_free_all(smt, true);
1135}
1136
1137static void free_smacro_table(struct hash_table *smt)
1138{
1139 clear_smacro_table(smt, CLEAR_ALLDEFINE);
H. Peter Anvin072771e2008-05-22 13:17:51 -07001140}
1141
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001142static void free_mmacro_table(struct hash_table *mmt)
H. Peter Anvin072771e2008-05-22 13:17:51 -07001143{
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001144 struct hash_iterator it;
1145 const struct hash_node *np;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001146
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001147 hash_for_each(mmt, it, np) {
1148 MMacro *tmp;
1149 MMacro *m = np->data;
1150 nasm_free((void *)np->key);
1151 list_for_each_safe(m, tmp, m)
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001152 free_mmacro(m);
H. Peter Anvin97a23472007-09-16 17:57:25 -07001153 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001154 hash_free(mmt);
H. Peter Anvin072771e2008-05-22 13:17:51 -07001155}
1156
1157static void free_macros(void)
1158{
H. Peter Anvin166c2472008-05-28 12:28:58 -07001159 free_smacro_table(&smacros);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001160 free_mmacro_table(&mmacros);
H. Peter Anvin97a23472007-09-16 17:57:25 -07001161}
1162
1163/*
1164 * Initialize the hash tables
1165 */
1166static void init_macros(void)
1167{
H. Peter Anvin97a23472007-09-16 17:57:25 -07001168}
1169
1170/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001171 * Pop the context stack.
1172 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001173static void ctx_pop(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001174{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001175 Context *c = cstk;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001176
1177 cstk = cstk->next;
H. Peter Anvin166c2472008-05-28 12:28:58 -07001178 free_smacro_table(&c->localmac);
H. Peter Anvin8571f062019-09-23 16:40:03 -07001179 nasm_free((char *)c->name);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001180 nasm_free(c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001181}
1182
H. Peter Anvin072771e2008-05-22 13:17:51 -07001183/*
1184 * Search for a key in the hash index; adding it if necessary
1185 * (in which case we initialize the data pointer to NULL.)
1186 */
1187static void **
1188hash_findi_add(struct hash_table *hash, const char *str)
1189{
1190 struct hash_insert hi;
1191 void **r;
1192 char *strx;
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001193 size_t l = strlen(str) + 1;
H. Peter Anvin072771e2008-05-22 13:17:51 -07001194
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001195 r = hash_findib(hash, str, l, &hi);
H. Peter Anvin072771e2008-05-22 13:17:51 -07001196 if (r)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001197 return r;
H. Peter Anvin072771e2008-05-22 13:17:51 -07001198
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001199 strx = nasm_malloc(l); /* Use a more efficient allocator here? */
1200 memcpy(strx, str, l);
H. Peter Anvin072771e2008-05-22 13:17:51 -07001201 return hash_add(&hi, strx, NULL);
1202}
1203
1204/*
1205 * Like hash_findi, but returns the data element rather than a pointer
1206 * to it. Used only when not adding a new element, hence no third
1207 * argument.
1208 */
1209static void *
1210hash_findix(struct hash_table *hash, const char *str)
1211{
1212 void **p;
1213
1214 p = hash_findi(hash, str, NULL);
1215 return p ? *p : NULL;
1216}
1217
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001218/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001219 * read line from standart macros set,
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001220 * if there no more left -- return NULL
1221 */
1222static char *line_from_stdmac(void)
1223{
1224 unsigned char c;
1225 const unsigned char *p = stdmacpos;
1226 char *line, *q;
1227 size_t len = 0;
1228
1229 if (!stdmacpos)
1230 return NULL;
1231
H. Peter Anvin (Intel)6d5c77c2019-08-15 02:29:40 -07001232 /*
1233 * 32-126 is ASCII, 127 is end of line, 128-31 are directives
1234 * (allowed to wrap around) corresponding to PP_* tokens 0-159.
1235 */
1236 while ((c = *p++) != 127) {
1237 uint8_t ndir = c - 128;
1238 if (ndir < 256-96)
1239 len += pp_directives_len[ndir] + 1;
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001240 else
1241 len++;
1242 }
1243
1244 line = nasm_malloc(len + 1);
1245 q = line;
H. Peter Anvin (Intel)6d5c77c2019-08-15 02:29:40 -07001246
1247 while ((c = *stdmacpos++) != 127) {
1248 uint8_t ndir = c - 128;
1249 if (ndir < 256-96) {
1250 memcpy(q, pp_directives[ndir], pp_directives_len[ndir]);
1251 q += pp_directives_len[ndir];
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001252 *q++ = ' ';
1253 } else {
1254 *q++ = c;
1255 }
1256 }
1257 stdmacpos = p;
1258 *q = '\0';
1259
H. Peter Anvin (Intel)6d5c77c2019-08-15 02:29:40 -07001260 if (*stdmacpos == 127) {
H. Peter Anvinf7606612016-07-13 14:23:48 -07001261 /* This was the last of this particular macro set */
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001262 stdmacpos = NULL;
H. Peter Anvinf7606612016-07-13 14:23:48 -07001263 if (*stdmacnext) {
1264 stdmacpos = *stdmacnext++;
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001265 } else if (do_predef) {
1266 Line *pd, *l;
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001267
1268 /*
1269 * Nasty hack: here we push the contents of
1270 * `predef' on to the top-level expansion stack,
1271 * since this is the most convenient way to
1272 * implement the pre-include and pre-define
1273 * features.
1274 */
1275 list_for_each(pd, predef) {
H. Peter Anvin6686de22019-08-10 05:33:14 -07001276 nasm_new(l);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001277 l->next = istk->expansion;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07001278 l->first = dup_tlist(pd->first, NULL);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001279 l->finishes = NULL;
1280
1281 istk->expansion = l;
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001282 }
1283 do_predef = false;
1284 }
1285 }
1286
1287 return line;
1288}
1289
H. Peter Anvin6686de22019-08-10 05:33:14 -07001290/*
1291 * Read a line from a file. Return NULL on end of file.
1292 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001293static char *line_from_file(FILE *f)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001294{
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001295 int c;
1296 unsigned int size, next;
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001297 const unsigned int delta = 512;
1298 const unsigned int pad = 8;
1299 unsigned int nr_cont = 0;
1300 bool cont = false;
1301 char *buffer, *p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001302
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001303 size = delta;
1304 p = buffer = nasm_malloc(size);
1305
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001306 do {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001307 c = fgetc(f);
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001308
1309 switch (c) {
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001310 case EOF:
1311 if (p == buffer) {
1312 nasm_free(buffer);
1313 return NULL;
1314 }
1315 c = 0;
1316 break;
1317
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001318 case '\r':
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001319 next = fgetc(f);
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001320 if (next != '\n')
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001321 ungetc(next, f);
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001322 if (cont) {
1323 cont = false;
1324 continue;
1325 }
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001326 c = 0;
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001327 break;
1328
1329 case '\n':
1330 if (cont) {
1331 cont = false;
1332 continue;
1333 }
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001334 c = 0;
1335 break;
1336
1337 case 032: /* ^Z = legacy MS-DOS end of file mark */
1338 c = 0;
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001339 break;
1340
1341 case '\\':
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001342 next = fgetc(f);
1343 ungetc(next, f);
Cyrill Gorcunov490f85e2012-12-27 20:02:17 +04001344 if (next == '\r' || next == '\n') {
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001345 cont = true;
1346 nr_cont++;
1347 continue;
1348 }
1349 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001350 }
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001351
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001352 if (p >= (buffer + size - pad)) {
1353 buffer = nasm_realloc(buffer, size + delta);
1354 p = buffer + size - pad;
1355 size += delta;
1356 }
1357
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001358 *p++ = c;
1359 } while (c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001360
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07001361 istk->where.lineno += (nr_cont + 1) * istk->lineinc;
1362 src_set_linnum(istk->where.lineno);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001363
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001364 return buffer;
1365}
1366
1367/*
H. Peter Anvin6686de22019-08-10 05:33:14 -07001368 * Common read routine regardless of source
1369 */
1370static char *read_line(void)
1371{
1372 char *line;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001373 FILE *f = istk->fp;
H. Peter Anvin6686de22019-08-10 05:33:14 -07001374
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001375 if (f)
1376 line = line_from_file(f);
H. Peter Anvin6686de22019-08-10 05:33:14 -07001377 else
1378 line = line_from_stdmac();
1379
1380 if (!line)
1381 return NULL;
1382
1383 if (!istk->nolist)
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07001384 lfmt->line(LIST_READ, istk->where.lineno, line);
H. Peter Anvin6686de22019-08-10 05:33:14 -07001385
1386 return line;
1387}
1388
1389/*
Keith Kaniosb7a89542007-04-12 02:40:54 +00001390 * Tokenize a line of text. This is a very simple process since we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001391 * don't need to parse the value out of e.g. numeric tokens: we
1392 * simply split one string into many.
1393 */
H. Peter Anvin8571f062019-09-23 16:40:03 -07001394static Token *tokenize(const char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001395{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001396 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001397 Token *list = NULL;
1398 Token *t, **tail = &list;
1399
H. Peter Anvine2c80182005-01-15 22:15:51 +00001400 while (*line) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001401 const char *p = line;
1402 const char *ep = NULL; /* End of token, for trimming the end */
1403 size_t toklen;
1404 char firstchar = *p; /* Can be used to override the first char */
H. Peter Anvin (Intel)98031bf2019-08-09 16:11:28 -07001405
H. Peter Anvine2c80182005-01-15 22:15:51 +00001406 if (*p == '%') {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001407 /*
1408 * Preprocessor construct; find the end of the token.
1409 * Classification is handled later, because %{...} can be
1410 * used to create any preprocessor token.
1411 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001412 p++;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001413 if (*p == '+' && !nasm_isdigit(p[1])) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001414 /* Paste token */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001415 p++;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001416 } else if (nasm_isdigit(*p) ||
1417 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001418 do {
1419 p++;
1420 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001421 while (nasm_isdigit(*p));
H. Peter Anvin8571f062019-09-23 16:40:03 -07001422 } else if (*p == '{' || *p == '[') {
1423 /* %{...} or %[...] */
1424 char firstchar = *p;
1425 char endchar = *p + 2; /* } or ] */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001426 int lvl = 1;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001427 line += (*p++ == '{'); /* Skip { but not [ (yet) */
1428 while (lvl) {
1429 if (*p == firstchar) {
1430 lvl++;
1431 } else if (*p == endchar) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001432 lvl--;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001433 } else if (nasm_isquote(*p)) {
1434 p = nasm_skip_string(p);
1435 }
1436
1437 /*
1438 * *p can have been advanced to a null character by
1439 * nasm_skip_string()
1440 */
1441 if (!*p) {
1442 nasm_warn(WARN_OTHER, "unterminated %%%c construct",
1443 firstchar);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001444 break;
1445 }
H. Peter Anvin (Intel)98031bf2019-08-09 16:11:28 -07001446 p++;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001447 }
1448 ep = lvl ? p : p-1; /* Terminal character not part of token */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001449 } else if (*p == '?') {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001450 /* %? or %?? */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001451 p++;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001452 if (*p == '?')
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001453 p++;
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001454 } else if (*p == '!') {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001455 /* Environment variable reference */
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001456 p++;
H. Peter Anvin13506202018-11-28 14:55:58 -08001457 if (nasm_isidchar(*p)) {
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001458 do {
1459 p++;
1460 }
H. Peter Anvin13506202018-11-28 14:55:58 -08001461 while (nasm_isidchar(*p));
H. Peter Anvin53e2e4c2018-11-28 15:01:40 -08001462 } else if (nasm_isquote(*p)) {
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001463 p = nasm_skip_string(p);
1464 if (*p)
1465 p++;
1466 else
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03001467 nasm_nonfatalf(ERR_PASS1, "unterminated %%! string");
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001468 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001469 /* %! without anything else... */
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001470 }
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07001471 } else if (*p == ',') {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001472 /* Conditional comma */
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07001473 p++;
H. Peter Anvin13506202018-11-28 14:55:58 -08001474 } else if (nasm_isidchar(*p) ||
H. Peter Anvin8571f062019-09-23 16:40:03 -07001475 ((*p == '%' || *p == '$') && nasm_isidchar(p[1]))) {
1476 /* Identifier or some sort */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001477 do {
1478 p++;
1479 }
H. Peter Anvin13506202018-11-28 14:55:58 -08001480 while (nasm_isidchar(*p));
H. Peter Anvin8571f062019-09-23 16:40:03 -07001481 } else if (*p == '%') {
1482 /* %% operator */
1483 p++;
1484 }
1485
1486 if (!ep)
1487 ep = p;
1488 toklen = ep - line;
1489
1490 /* Classify here, to handle %{...} correctly */
1491 if (toklen < 2) {
1492 type = TOK_OTHER; /* % operator */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001493 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001494 char c0 = line[1];
1495
1496 switch (c0) {
1497 case '+':
1498 type = (toklen == 2) ? TOK_PASTE : TOK_MMACRO_PARAM;
1499 break;
1500
1501 case '-':
1502 type = TOK_MMACRO_PARAM;
1503 break;
1504
1505 case '?':
1506 if (toklen == 2)
1507 type = TOK_PREPROC_Q;
1508 else if (toklen == 3 && line[2] == '?')
1509 type = TOK_PREPROC_QQ;
1510 else
1511 type = TOK_PREPROC_ID;
1512 break;
1513
1514 case '!':
1515 type = (toklen == 2) ? TOK_OTHER : TOK_ENVIRON;
1516 break;
1517
1518 case '%':
1519 type = (toklen == 2) ? TOK_OTHER : TOK_LOCAL_SYMBOL;
1520 break;
1521
1522 case '$':
1523 type = (toklen == 2) ? TOK_OTHER : TOK_LOCAL_MACRO;
1524 break;
1525
1526 case '[':
1527 line += 2; /* Skip %[ */
1528 firstchar = *line; /* Don't clobber */
1529 toklen -= 2;
1530 type = TOK_INDIRECT;
1531 break;
1532
1533 case ',':
1534 type = (toklen == 2) ? TOK_COND_COMMA : TOK_PREPROC_ID;
1535 break;
1536
1537 case '\'':
1538 case '\"':
1539 case '`':
1540 /* %{'string'} */
1541 type = TOK_PREPROC_ID;
1542 break;
1543
1544 case ':':
1545 type = TOK_MMACRO_PARAM; /* %{:..} */
1546 break;
1547
1548 default:
1549 if (nasm_isdigit(c0))
1550 type = TOK_MMACRO_PARAM;
1551 else if (nasm_isidchar(c0) || toklen > 2)
1552 type = TOK_PREPROC_ID;
1553 else
1554 type = TOK_OTHER;
1555 break;
1556 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001557 }
H. Peter Anvin13506202018-11-28 14:55:58 -08001558 } else if (nasm_isidstart(*p) || (*p == '$' && nasm_isidstart(p[1]))) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001559 /*
1560 * An identifier. This includes the ? operator, which is
1561 * treated as a keyword, not as a special character
1562 * operator
1563 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001564 type = TOK_ID;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001565 while (nasm_isidchar(*++p))
1566 ;
1567 } else if (nasm_isquote(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001568 /*
1569 * A string token.
1570 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001571 type = TOK_STRING;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001572 p = nasm_skip_string(p);
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001573
H. Peter Anvine2c80182005-01-15 22:15:51 +00001574 if (*p) {
1575 p++;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001576 } else {
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08001577 nasm_warn(WARN_OTHER, "unterminated string");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001578 /* Handling unterminated strings by UNV */
1579 /* type = -1; */
1580 }
Victor van den Elzenfb5f2512009-04-17 16:17:59 +02001581 } else if (p[0] == '$' && p[1] == '$') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001582 type = TOK_OTHER; /* TOKEN_BASE */
Victor van den Elzenfb5f2512009-04-17 16:17:59 +02001583 p += 2;
H. Peter Anvin13506202018-11-28 14:55:58 -08001584 } else if (nasm_isnumstart(*p)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001585 bool is_hex = false;
1586 bool is_float = false;
1587 bool has_e = false;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001588 char c;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001589
H. Peter Anvine2c80182005-01-15 22:15:51 +00001590 /*
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001591 * A numeric token.
H. Peter Anvine2c80182005-01-15 22:15:51 +00001592 */
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001593
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001594 if (*p == '$') {
1595 p++;
1596 is_hex = true;
1597 }
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001598
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001599 for (;;) {
1600 c = *p++;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001601
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001602 if (!is_hex && (c == 'e' || c == 'E')) {
1603 has_e = true;
1604 if (*p == '+' || *p == '-') {
1605 /*
1606 * e can only be followed by +/- if it is either a
1607 * prefixed hex number or a floating-point number
1608 */
1609 p++;
1610 is_float = true;
1611 }
1612 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
1613 is_hex = true;
1614 } else if (c == 'P' || c == 'p') {
1615 is_float = true;
1616 if (*p == '+' || *p == '-')
1617 p++;
H. Peter Anvin13506202018-11-28 14:55:58 -08001618 } else if (nasm_isnumchar(c))
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001619 ; /* just advance */
1620 else if (c == '.') {
1621 /*
1622 * we need to deal with consequences of the legacy
1623 * parser, like "1.nolist" being two tokens
1624 * (TOK_NUMBER, TOK_ID) here; at least give it
1625 * a shot for now. In the future, we probably need
1626 * a flex-based scanner with proper pattern matching
1627 * to do it as well as it can be done. Nothing in
1628 * the world is going to help the person who wants
1629 * 0x123.p16 interpreted as two tokens, though.
1630 */
H. Peter Anvin8571f062019-09-23 16:40:03 -07001631 const char *r = p;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001632 while (*r == '_')
1633 r++;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001634
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001635 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
1636 (!is_hex && (*r == 'e' || *r == 'E')) ||
1637 (*r == 'p' || *r == 'P')) {
1638 p = r;
1639 is_float = true;
1640 } else
1641 break; /* Terminate the token */
1642 } else
1643 break;
1644 }
1645 p--; /* Point to first character beyond number */
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001646
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001647 if (p == line+1 && *line == '$') {
1648 type = TOK_OTHER; /* TOKEN_HERE */
1649 } else {
1650 if (has_e && !is_hex) {
1651 /* 1e13 is floating-point, but 1e13h is not */
1652 is_float = true;
1653 }
H. Peter Anvind784a082009-04-20 14:01:18 -07001654
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001655 type = is_float ? TOK_FLOAT : TOK_NUMBER;
1656 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001657 } else if (nasm_isspace(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001658 type = TOK_WHITESPACE;
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +04001659 p = nasm_skip_spaces(p);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001660 /*
1661 * Whitespace just before end-of-line is discarded by
1662 * pretending it's a comment; whitespace just before a
1663 * comment gets lumped into the comment.
1664 */
1665 if (!*p || *p == ';') {
1666 type = TOK_COMMENT;
1667 while (*p)
1668 p++;
1669 }
1670 } else if (*p == ';') {
1671 type = TOK_COMMENT;
1672 while (*p)
1673 p++;
1674 } else {
1675 /*
1676 * Anything else is an operator of some kind. We check
1677 * for all the double-character operators (>>, <<, //,
H. Peter Anvin8571f062019-09-23 16:40:03 -07001678 * %%, <=, >=, ==, !=, <>, &&, ||, ^^) and the triple-
1679 * character operators (<<<, >>>, <=>) but anything
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001680 * else is a single-character operator.
H. Peter Anvine2c80182005-01-15 22:15:51 +00001681 */
1682 type = TOK_OTHER;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001683 switch (*p++) {
1684 case '>':
1685 if (*p == '>') {
1686 p++;
1687 if (*p == '>')
1688 p++;
H. Peter Anvind03a6c82019-10-07 21:29:05 -07001689 } else if (*p == '=') {
1690 p++;
1691 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07001692 break;
1693
1694 case '<':
1695 if (*p == '<') {
1696 p++;
1697 if (*p == '<')
1698 p++;
1699 } else if (*p == '=') {
1700 p++;
1701 if (*p == '>')
1702 p++;
1703 } else if (*p == '>') {
1704 p++;
1705 }
1706 break;
1707
1708 case '!':
1709 if (*p == '=')
1710 p++;
1711 break;
1712
1713 case '/':
1714 case '=':
1715 case '&':
1716 case '|':
1717 case '^':
1718 /* These operators can be doubled but nothing else */
1719 if (*p == p[-1])
1720 p++;
1721 break;
1722
1723 default:
1724 break;
1725 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001726 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001727
H. Peter Anvin8571f062019-09-23 16:40:03 -07001728 if (type == TOK_WHITESPACE) {
1729 *tail = t = new_White(NULL);
1730 tail = &t->next;
1731 } else if (type != TOK_COMMENT) {
H. Peter Anvin (Intel)98031bf2019-08-09 16:11:28 -07001732 if (!ep)
1733 ep = p;
1734 *tail = t = new_Token(NULL, type, line, ep - line);
H. Peter Anvin8571f062019-09-23 16:40:03 -07001735 *tok_text_buf(t) = firstchar; /* E.g. %{foo} -> {foo -> %foo */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001736 tail = &t->next;
1737 }
1738 line = p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001739 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001740 return list;
1741}
1742
H. Peter Anvin8571f062019-09-23 16:40:03 -07001743/*
1744 * Tokens are allocated in blocks to improve speed. Set the blocksize
1745 * to 0 to use regular nasm_malloc(); this is useful for debugging.
1746 *
1747 * alloc_Token() returns a zero-initialized token structure.
1748 */
1749#define TOKEN_BLOCKSIZE 4096
1750
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001751#if TOKEN_BLOCKSIZE
H. Peter Anvin8571f062019-09-23 16:40:03 -07001752
1753static Token *freeTokens = NULL;
1754static Token *tokenblocks = NULL;
1755
1756static Token *alloc_Token(void)
H. Peter Anvince616072002-04-30 21:02:23 +00001757{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001758 Token *t = freeTokens;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001759
H. Peter Anvin8571f062019-09-23 16:40:03 -07001760 if (unlikely(!t)) {
1761 Token *block;
1762 size_t i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001763
H. Peter Anvin8571f062019-09-23 16:40:03 -07001764 nasm_newn(block, TOKEN_BLOCKSIZE);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001765
H. Peter Anvin8571f062019-09-23 16:40:03 -07001766 /*
1767 * The first entry in each array are a linked list of
1768 * block allocations and is not used for data.
1769 */
1770 block[0].next = tokenblocks;
1771 block[0].type = TOK_BLOCK;
1772 tokenblocks = block;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001773
H. Peter Anvin8571f062019-09-23 16:40:03 -07001774 /*
1775 * Add the rest to the free list
1776 */
1777 for (i = 2; i < TOKEN_BLOCKSIZE - 1; i++)
1778 block[i].next = &block[i+1];
1779
1780 freeTokens = &block[2];
1781
1782 /*
1783 * Return the topmost usable token
1784 */
1785 return &block[1];
1786 }
1787
1788 freeTokens = t->next;
1789 t->next = NULL;
1790 return t;
H. Peter Anvince616072002-04-30 21:02:23 +00001791}
1792
H. Peter Anvin8571f062019-09-23 16:40:03 -07001793static Token *delete_Token(Token *t)
1794{
1795 Token *next = t->next;
1796
1797 nasm_zero(*t);
1798 t->next = freeTokens;
1799 freeTokens = t;
1800
1801 return next;
1802}
1803
H. Peter Anvine2c80182005-01-15 22:15:51 +00001804static void delete_Blocks(void)
H. Peter Anvince616072002-04-30 21:02:23 +00001805{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001806 Token *block, *blocktmp;
H. Peter Anvince616072002-04-30 21:02:23 +00001807
H. Peter Anvin8571f062019-09-23 16:40:03 -07001808 list_for_each_safe(block, blocktmp, tokenblocks)
1809 nasm_free(block);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001810
H. Peter Anvin8571f062019-09-23 16:40:03 -07001811 freeTokens = tokenblocks = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001812}
H. Peter Anvin734b1882002-04-30 21:01:08 +00001813
H. Peter Anvin8571f062019-09-23 16:40:03 -07001814#else
1815
1816static inline Token *alloc_Token(void)
1817{
1818 Token *t;
1819 nasm_new(*t);
1820 return t;
1821}
1822
1823static Token *delete_Token(Token *t)
1824{
1825 Token *next = t->next;
1826 nasm_free(t);
1827 return next;
1828}
1829
1830static inline void delete_Blocks(void)
1831{
1832 /* Nothing to do */
1833}
1834
1835#endif
1836
H. Peter Anvin734b1882002-04-30 21:01:08 +00001837/*
H. Peter Anvin70653092007-10-19 14:42:29 -07001838 * this function creates a new Token and passes a pointer to it
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001839 * back to the caller. It sets the type, text, and next pointer elements.
H. Peter Anvin734b1882002-04-30 21:01:08 +00001840 */
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001841static Token *new_Token(Token * next, enum pp_token_type type,
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001842 const char *text, size_t txtlen)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001843{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001844 Token *t = alloc_Token();
1845 char *textp;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001846
H. Peter Anvin734b1882002-04-30 21:01:08 +00001847 t->next = next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001848 t->type = type;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001849 if (type == TOK_WHITESPACE) {
1850 t->len = 1;
1851 t->text.a[0] = ' ';
H. Peter Anvine2c80182005-01-15 22:15:51 +00001852 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001853 if (text && text[0] && !txtlen)
1854 txtlen = tok_strlen(text);
1855
1856 t->len = tok_check_len(txtlen);
1857
1858 if (text) {
1859 textp = (txtlen > INLINE_TEXT)
1860 ? (t->text.p.ptr = nasm_malloc(txtlen+1)) : t->text.a;
1861 memcpy(textp, text, txtlen);
1862 textp[txtlen] = '\0'; /* In case we needed malloc() */
1863 } else {
1864 /*
1865 * Allocate a buffer but do not fill it. The caller
1866 * can fill in text, but must not change the length.
1867 * The filled in text must be exactly txtlen once
1868 * the buffer is filled and before the token is added
1869 * to any line lists.
1870 */
1871 if (txtlen > INLINE_TEXT)
1872 t->text.p.ptr = nasm_zalloc(txtlen+1);
1873 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001874 }
1875 return t;
1876}
1877
H. Peter Anvin8571f062019-09-23 16:40:03 -07001878/*
1879 * Same as new_Token(), but text belongs to the new token and is
1880 * either taken over or freed. This function MUST be called
1881 * with valid txt and txtlen, unlike new_Token().
1882 */
1883static Token *new_Token_free(Token * next, enum pp_token_type type,
1884 char *text, size_t txtlen)
1885{
1886 Token *t = alloc_Token();
1887
1888 t->next = next;
1889 t->type = type;
1890 t->len = tok_check_len(txtlen);
1891
1892 if (txtlen <= INLINE_TEXT) {
1893 memcpy(t->text.a, text, txtlen);
1894 free(text);
1895 } else {
1896 t->text.p.ptr = text;
1897 }
1898
1899 return t;
1900}
1901
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001902static Token *dup_Token(Token *next, const Token *src)
1903{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001904 Token *t = alloc_Token();
1905
1906 memcpy(t, src, sizeof *src);
1907 t->next = next;
1908
1909 if (t->len > INLINE_TEXT) {
1910 t->text.p.ptr = nasm_malloc(t->len + 1);
1911 memcpy(t->text.p.ptr, src->text.p.ptr, t->len+1);
1912 }
1913
1914 return t;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001915}
1916
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001917static Token *new_White(Token *next)
1918{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001919 Token *t = alloc_Token();
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001920
H. Peter Anvin8571f062019-09-23 16:40:03 -07001921 t->next = next;
1922 t->type = TOK_WHITESPACE;
1923 t->len = 1;
1924 t->text.a[0] = ' ';
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001925
H. Peter Anvin8571f062019-09-23 16:40:03 -07001926 return t;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001927}
1928
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001929/*
H. Peter Anvin8571f062019-09-23 16:40:03 -07001930 * This *transfers* the content from one token to another, leaving the
1931 * next pointer of the latter intact. Unlike dup_Token(), the old
1932 * token is destroyed, except for its next pointer, and the text
1933 * pointer allocation, if any, is simply transferred.
1934 */
1935static Token *steal_Token(Token *dst, Token *src)
1936{
1937 /* Overwrite everything except the next pointers */
1938 memcpy((char *)dst + sizeof(Token *), (char *)src + sizeof(Token *),
1939 sizeof(Token) - sizeof(Token *));
1940
1941 /* Clear the donor token */
1942 memset((char *)src + sizeof(Token *), 0, sizeof(Token) - sizeof(Token *));
1943
1944 return dst;
1945}
1946
1947/*
1948 * Convert a line of tokens back into text. This modifies the list
1949 * by expanding environment variables.
1950 *
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001951 * If expand_locals is not zero, identifiers of the form "%$*xxx"
H. Peter Anvin8571f062019-09-23 16:40:03 -07001952 * are also transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001953 */
H. Peter Anvin9e200162008-06-04 17:23:14 -07001954static char *detoken(Token * tlist, bool expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001955{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001956 Token *t;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001957 char *line, *p;
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001958 int len = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001959
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001960 list_for_each(t, tlist) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001961 switch (t->type) {
1962 case TOK_ENVIRON:
1963 {
1964 const char *v = pp_getenv(t, true);
1965 set_text(t, v, tok_strlen(v));
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07001966 t->type = TOK_NAKED_STRING;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001967 break;
1968 }
H. Peter Anvin077fb932010-07-20 14:56:30 -07001969
H. Peter Anvin8571f062019-09-23 16:40:03 -07001970 case TOK_LOCAL_MACRO:
1971 case TOK_LOCAL_SYMBOL:
1972 if (expand_locals) {
1973 const char *q;
1974 char *p;
1975 Context *ctx = get_ctx(tok_text(t), &q);
1976 if (ctx) {
1977 p = nasm_asprintf("..@%"PRIu64".%s", ctx->number, q);
1978 set_text_free(t, p, nasm_last_string_len());
1979 t->type = TOK_ID;
1980 }
1981 }
1982 break;
H. Peter Anvin077fb932010-07-20 14:56:30 -07001983
H. Peter Anvin8571f062019-09-23 16:40:03 -07001984 default:
1985 break; /* No modifications */
1986 }
1987
1988 if (debug_level(2)) {
1989 unsigned int t_len = t->len;
1990 unsigned int s_len = tok_strlen(tok_text(t));
1991 if (t_len != s_len) {
1992 nasm_panic("assertion failed: token \"%s\" type %u len %u has t->len %u\n",
1993 tok_text(t), t->type, s_len, t_len);
1994 t->len = s_len;
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001995 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001996 }
H. Peter Anvin077fb932010-07-20 14:56:30 -07001997
H. Peter Anvin8571f062019-09-23 16:40:03 -07001998 len += t->len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001999 }
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04002000
H. Peter Anvin734b1882002-04-30 21:01:08 +00002001 p = line = nasm_malloc(len + 1);
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04002002
H. Peter Anvin8571f062019-09-23 16:40:03 -07002003 list_for_each(t, tlist)
2004 p = mempcpy(p, tok_text(t), t->len);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002005 *p = '\0';
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04002006
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002007 return line;
2008}
2009
2010/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002011 * A scanner, suitable for use by the expression evaluator, which
2012 * operates on a line of Tokens. Expects a pointer to a pointer to
2013 * the first token in the line to be passed in as its private_data
2014 * field.
H. Peter Anvinc2df2822007-10-24 15:29:28 -07002015 *
2016 * FIX: This really needs to be unified with stdscan.
H. Peter Anvin76690a12002-04-30 20:52:49 +00002017 */
H. Peter Anvin8b262472019-02-26 14:00:54 -08002018struct ppscan {
2019 Token *tptr;
2020 int ntokens;
2021};
2022
H. Peter Anvine2c80182005-01-15 22:15:51 +00002023static int ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002024{
H. Peter Anvin8b262472019-02-26 14:00:54 -08002025 struct ppscan *pps = private_data;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002026 Token *tline;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002027 const char *txt;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002028
H. Peter Anvine2c80182005-01-15 22:15:51 +00002029 do {
H. Peter Anvin8b262472019-02-26 14:00:54 -08002030 if (pps->ntokens && (tline = pps->tptr)) {
2031 pps->ntokens--;
2032 pps->tptr = tline->next;
2033 } else {
2034 pps->tptr = NULL;
2035 pps->ntokens = 0;
2036 return tokval->t_type = TOKEN_EOS;
2037 }
2038 } while (tline->type == TOK_WHITESPACE || tline->type == TOK_COMMENT);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002039
H. Peter Anvin8571f062019-09-23 16:40:03 -07002040 txt = tok_text(tline);
2041 tokval->t_charptr = (char *)txt; /* Fix this */
H. Peter Anvinc2df2822007-10-24 15:29:28 -07002042
H. Peter Anvin8571f062019-09-23 16:40:03 -07002043 if (txt[0] == '$') {
2044 if (!txt[1]) {
2045 return tokval->t_type = TOKEN_HERE;
2046 } else if (txt[1] == '$' && !txt[2]) {
2047 return tokval->t_type = TOKEN_BASE;
2048 } else if (tline->type == TOK_ID) {
2049 tokval->t_charptr++;
2050 return tokval->t_type = TOKEN_ID;
2051 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002052 }
2053
H. Peter Anvin8571f062019-09-23 16:40:03 -07002054 switch (tline->type) {
2055 default:
2056 if (tline->len == 1)
2057 return tokval->t_type = txt[0];
2058 /* fall through */
2059 case TOK_ID:
2060 return nasm_token_hash(txt, tokval);
2061
2062 case TOK_NUMBER:
2063 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002064 bool rn_error;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002065 tokval->t_integer = readnum(txt, &rn_error);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002066 if (rn_error)
2067 return tokval->t_type = TOKEN_ERRNUM;
2068 else
2069 return tokval->t_type = TOKEN_NUM;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07002070 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002071
H. Peter Anvin8571f062019-09-23 16:40:03 -07002072 case TOK_FLOAT:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002073 return tokval->t_type = TOKEN_FLOAT;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002074
2075 case TOK_STRING:
2076 tokval->t_charptr = (char *)unquote_token(tline);
2077 tokval->t_inttwo = tline->len;
2078 return tokval->t_type = TOKEN_STR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002079 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002080}
2081
2082/*
H. Peter Anvind2354082019-08-27 16:38:48 -07002083 * 1. An expression (true if nonzero 0)
2084 * 2. The keywords true, on, yes for true
2085 * 3. The keywords false, off, no for false
2086 * 4. An empty line, for true
2087 *
2088 * On error, return defval (usually the previous value)
2089 */
2090static bool pp_get_boolean_option(Token *tline, bool defval)
2091{
2092 static const char * const noyes[] = {
2093 "no", "yes",
2094 "false", "true",
2095 "off", "on"
2096 };
2097 struct ppscan pps;
2098 struct tokenval tokval;
2099 expr *evalresult;
2100
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002101 tline = skip_white(tline);
2102 if (!tline)
H. Peter Anvind2354082019-08-27 16:38:48 -07002103 return true;
2104
2105 if (tline->type == TOK_ID) {
2106 size_t i;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002107 const char *txt = tok_text(tline);
2108
H. Peter Anvind2354082019-08-27 16:38:48 -07002109 for (i = 0; i < ARRAY_SIZE(noyes); i++)
H. Peter Anvin8571f062019-09-23 16:40:03 -07002110 if (!nasm_stricmp(txt, noyes[i]))
H. Peter Anvind2354082019-08-27 16:38:48 -07002111 return i & 1;
2112 }
2113
2114 pps.tptr = NULL;
2115 pps.tptr = tline;
2116 pps.ntokens = -1;
2117 tokval.t_type = TOKEN_INVALID;
2118 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
2119
2120 if (!evalresult)
2121 return true;
2122
2123 if (tokval.t_type)
2124 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
2125 if (!is_really_simple(evalresult)) {
2126 nasm_nonfatal("boolean flag expression must be a constant");
2127 return defval;
2128 }
2129
2130 return reloc_value(evalresult) != 0;
2131}
2132
2133/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002134 * Compare a string to the name of an existing macro; this is a
2135 * simple wrapper which calls either strcmp or nasm_stricmp
2136 * depending on the value of the `casesense' parameter.
2137 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002138static int mstrcmp(const char *p, const char *q, bool casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002139{
H. Peter Anvin734b1882002-04-30 21:01:08 +00002140 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002141}
2142
2143/*
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07002144 * Compare a string to the name of an existing macro; this is a
2145 * simple wrapper which calls either strcmp or nasm_stricmp
2146 * depending on the value of the `casesense' parameter.
2147 */
2148static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
2149{
2150 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
2151}
2152
2153/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002154 * Return the Context structure associated with a %$ token. Return
2155 * NULL, having _already_ reported an error condition, if the
2156 * context stack isn't deep enough for the supplied number of $
2157 * signs.
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002158 *
2159 * If "namep" is non-NULL, set it to the pointer to the macro name
2160 * tail, i.e. the part beyond %$...
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002161 */
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04002162static Context *get_ctx(const char *name, const char **namep)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002163{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002164 Context *ctx;
2165 int i;
2166
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002167 if (namep)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002168 *namep = name;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002169
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002170 if (!name || name[0] != '%' || name[1] != '$')
H. Peter Anvine2c80182005-01-15 22:15:51 +00002171 return NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002172
H. Peter Anvine2c80182005-01-15 22:15:51 +00002173 if (!cstk) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002174 nasm_nonfatal("`%s': context stack is empty", name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002175 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002176 }
2177
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002178 name += 2;
2179 ctx = cstk;
2180 i = 0;
2181 while (ctx && *name == '$') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002182 name++;
2183 i++;
2184 ctx = ctx->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002185 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002186 if (!ctx) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002187 nasm_nonfatal("`%s': context stack is only"
2188 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
H. Peter Anvine2c80182005-01-15 22:15:51 +00002189 return NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002190 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002191
2192 if (namep)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002193 *namep = name;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002194
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04002195 return ctx;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002196}
2197
2198/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002199 * Open an include file. This routine must always return a valid
2200 * file pointer if it returns - it's responsible for throwing an
2201 * ERR_FATAL and bombing out completely if not. It should also try
2202 * the include path one by one until it finds the file or reaches
2203 * the end of the path.
H. Peter Anvind81a2352016-09-21 14:03:18 -07002204 *
2205 * Note: for INC_PROBE the function returns NULL at all times;
2206 * instead look for the
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002207 */
H. Peter Anvind81a2352016-09-21 14:03:18 -07002208enum incopen_mode {
2209 INC_NEEDED, /* File must exist */
2210 INC_OPTIONAL, /* Missing is OK */
2211 INC_PROBE /* Only an existence probe */
2212};
2213
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002214/* This is conducts a full pathname search */
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002215static FILE *inc_fopen_search(const char *file, char **slpath,
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002216 enum incopen_mode omode, enum file_flags fmode)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002217{
H. Peter Anvin (Intel)64471092018-12-11 13:06:14 -08002218 const struct strlist_entry *ip = strlist_head(ipath_list);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002219 FILE *fp;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002220 const char *prefix = "";
night199ukfdb1a1b2018-10-18 23:19:47 +02002221 char *sp;
H. Peter Anvind81a2352016-09-21 14:03:18 -07002222 bool found;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002223
H. Peter Anvine2c80182005-01-15 22:15:51 +00002224 while (1) {
night199ukfdb1a1b2018-10-18 23:19:47 +02002225 sp = nasm_catfile(prefix, file);
H. Peter Anvind81a2352016-09-21 14:03:18 -07002226 if (omode == INC_PROBE) {
2227 fp = NULL;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002228 found = nasm_file_exists(sp);
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07002229 } else {
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002230 fp = nasm_open_read(sp, fmode);
H. Peter Anvind81a2352016-09-21 14:03:18 -07002231 found = (fp != NULL);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002232 }
H. Peter Anvind81a2352016-09-21 14:03:18 -07002233 if (found) {
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002234 *slpath = sp;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002235 return fp;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002236 }
Jim Kukunas65a8afc2016-06-13 16:00:42 -04002237
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002238 nasm_free(sp);
Jim Kukunas65a8afc2016-06-13 16:00:42 -04002239
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002240 if (!ip) {
2241 *slpath = NULL;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002242 return NULL;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002243 }
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002244
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002245 prefix = ip->str;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002246 ip = ip->next;
2247 }
2248}
2249
2250/*
2251 * Open a file, or test for the presence of one (depending on omode),
2252 * considering the include path.
2253 */
2254static FILE *inc_fopen(const char *file,
Cyrill Gorcunovb7bb5ac2018-11-11 21:33:52 +03002255 struct strlist *dhead,
H. Peter Anvinccad6f92016-10-04 00:34:35 -07002256 const char **found_path,
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002257 enum incopen_mode omode,
2258 enum file_flags fmode)
2259{
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002260 struct hash_insert hi;
2261 void **hp;
2262 char *path;
2263 FILE *fp = NULL;
2264
2265 hp = hash_find(&FileHash, file, &hi);
2266 if (hp) {
2267 path = *hp;
Martin Storsjöf283c8f2017-08-13 17:28:46 +03002268 if (path || omode != INC_NEEDED) {
Cyrill Gorcunovb7bb5ac2018-11-11 21:33:52 +03002269 strlist_add(dhead, path ? path : file);
Martin Storsjöf283c8f2017-08-13 17:28:46 +03002270 }
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002271 } else {
2272 /* Need to do the actual path search */
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002273 fp = inc_fopen_search(file, &path, omode, fmode);
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002274
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002275 /* Positive or negative result */
2276 hash_add(&hi, nasm_strdup(file), path);
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002277
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07002278 /*
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002279 * Add file to dependency path.
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07002280 */
2281 if (path || omode != INC_NEEDED)
Cyrill Gorcunovb7bb5ac2018-11-11 21:33:52 +03002282 strlist_add(dhead, file);
H. Peter Anvineba20a72002-04-30 20:53:55 +00002283 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002284
H. Peter Anvin (Intel)5d68f982020-06-01 12:32:35 -07002285 if (path && !fp && omode != INC_PROBE)
2286 fp = nasm_open_read(path, fmode);
2287
2288 if (omode == INC_NEEDED && !fp) {
2289 if (!path)
2290 errno = ENOENT;
2291
2292 nasm_nonfatal("unable to open include file `%s': %s",
2293 file, strerror(errno));
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002294 }
2295
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002296 if (found_path)
H. Peter Anvinccad6f92016-10-04 00:34:35 -07002297 *found_path = path;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002298
2299 return fp;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002300}
2301
2302/*
Fabian Giesen0bbc38d2016-04-28 13:48:14 -07002303 * Opens an include or input file. Public version, for use by modules
2304 * that get a file:lineno pair and need to look at the file again
2305 * (e.g. the CodeView debug backend). Returns NULL on failure.
2306 */
H. Peter Anvin3e83cec2016-05-25 04:28:46 -07002307FILE *pp_input_fopen(const char *filename, enum file_flags mode)
Fabian Giesen0bbc38d2016-04-28 13:48:14 -07002308{
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07002309 return inc_fopen(filename, NULL, NULL, INC_OPTIONAL, mode);
Fabian Giesen0bbc38d2016-04-28 13:48:14 -07002310}
2311
2312/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002313 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002314 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002315 * return true if _any_ single-line macro of that name is defined.
2316 * Otherwise, will return true if a single-line macro with either
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002317 * `nparam' or no parameters is defined.
2318 *
2319 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002320 * defined, or nparam is -1, the address of the definition structure
2321 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002322 * is NULL, no action will be taken regarding its contents, and no
2323 * error will occur.
2324 *
2325 * Note that this is also called with nparam zero to resolve
2326 * `ifdef'.
2327 */
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002328static bool
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002329smacro_defined(Context *ctx, const char *name, int nparam, SMacro **defn,
H. Peter Anvind2354082019-08-27 16:38:48 -07002330 bool nocase, bool find_alias)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002331{
H. Peter Anvin166c2472008-05-28 12:28:58 -07002332 struct hash_table *smtbl;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002333 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002334
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002335 smtbl = ctx ? &ctx->localmac : &smacros;
H. Peter Anvind2354082019-08-27 16:38:48 -07002336
2337restart:
H. Peter Anvin166c2472008-05-28 12:28:58 -07002338 m = (SMacro *) hash_findix(smtbl, name);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002339
H. Peter Anvine2c80182005-01-15 22:15:51 +00002340 while (m) {
2341 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002342 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam ||
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002343 (m->greedy && nparam >= m->nparam-1))) {
H. Peter Anvind2354082019-08-27 16:38:48 -07002344 if (m->alias && !find_alias) {
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002345 if (!ppopt.noaliases) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002346 name = tok_text(m->expansion);
H. Peter Anvind2354082019-08-27 16:38:48 -07002347 goto restart;
2348 } else {
2349 continue;
2350 }
2351 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002352 if (defn) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002353 *defn = (nparam == m->nparam || nparam == -1) ? m : NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002354 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002355 return true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002356 }
2357 m = m->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002358 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002359
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002360 return false;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002361}
2362
Cyrill Gorcunov3079f792018-11-14 10:03:42 +03002363/* param should be a natural number [0; INT_MAX] */
2364static int read_param_count(const char *str)
2365{
2366 int result;
2367 bool err;
2368
2369 result = readnum(str, &err);
2370 if (result < 0 || result > INT_MAX) {
2371 result = 0;
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002372 nasm_nonfatal("parameter count `%s' is out of bounds [%d; %d]",
2373 str, 0, INT_MAX);
2374 } else if (err)
2375 nasm_nonfatal("unable to parse parameter count `%s'", str);
Cyrill Gorcunov3079f792018-11-14 10:03:42 +03002376 return result;
2377}
2378
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002379/*
2380 * Count and mark off the parameters in a multi-line macro call.
2381 * This is called both from within the multi-line macro expansion
2382 * code, and also to mark off the default parameters when provided
2383 * in a %macro definition line.
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002384 *
2385 * Note that we need space in the params array for parameter 0 being
2386 * a possible captured label as well as the final NULL.
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002387 *
2388 * Returns a pointer to the pointer to a terminal comma if present;
2389 * used to drop an empty terminal argument for legacy reasons.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002390 */
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002391static Token **count_mmac_params(Token *tline, int *nparamp, Token ***paramsp)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002392{
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07002393 int paramsize;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002394 int nparam = 0;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002395 Token *t;
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002396 Token **comma = NULL, **maybe_comma = NULL;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002397 Token **params;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002398
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002399 paramsize = PARAM_DELTA;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002400 nasm_newn(params, paramsize);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002401
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002402 t = skip_white(tline);
2403 if (t) {
2404 while (true) {
2405 /* Need two slots for captured label and NULL */
2406 if (unlikely(nparam+2 >= paramsize)) {
2407 paramsize += PARAM_DELTA;
2408 params = nasm_realloc(params, sizeof(*params) * paramsize);
2409 }
2410 params[++nparam] = t;
2411 if (tok_is(t, '{')) {
2412 int brace = 1;
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002413
2414 comma = NULL; /* Non-empty parameter */
2415
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002416 while (brace && (t = t->next)) {
2417 brace += tok_is(t, '{');
2418 brace -= tok_is(t, '}');
2419 }
H. Peter Anvin (Intel)f8639bd2020-06-04 16:29:53 -07002420
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002421 if (t) {
2422 /*
2423 * Now we've found the closing brace, look further
2424 * for the comma.
2425 */
2426 t = skip_white(t->next);
2427 if (tok_isnt(t, ','))
2428 nasm_nonfatal("braces do not enclose all of macro parameter");
2429 } else {
2430 nasm_nonfatal("expecting closing brace in macro parameter");
2431 }
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08002432 }
2433
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002434 /* Advance to the next comma */
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002435 maybe_comma = &t->next;
2436 while (tok_isnt(t, ',')) {
2437 if (!tok_white(t))
2438 comma = NULL; /* Non-empty parameter */
2439 maybe_comma = &t->next;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002440 t = t->next;
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002441 }
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002442
2443 if (!t)
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002444 break; /* End of string, no comma */
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002445
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002446 comma = maybe_comma; /* Point to comma pointer */
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002447 t = skip_white(t->next); /* Eat the comma and whitespace */
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08002448 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002449 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002450
2451 params[nparam+1] = NULL;
2452 *paramsp = params;
2453 *nparamp = nparam;
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002454
2455 return comma;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002456}
2457
2458/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002459 * Determine whether one of the various `if' conditions is true or
2460 * not.
2461 *
2462 * We must free the tline we get passed.
2463 */
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002464static enum cond_state if_condition(Token * tline, enum preproc_token ct)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002465{
H. Peter Anvin70055962007-10-11 00:05:31 -07002466 bool j;
H. Peter Anvin8b262472019-02-26 14:00:54 -08002467 Token *t, *tt, *origline;
2468 struct ppscan pps;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002469 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002470 expr *evalresult;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002471 enum pp_token_type needtype;
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002472 const char *dname = pp_directives[ct];
2473 bool casesense = true;
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002474 enum preproc_token cond = PP_COND(ct);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002475
2476 origline = tline;
2477
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002478 switch (cond) {
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002479 case PP_IFCTX:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002480 j = false; /* have we matched yet? */
Victor van den Elzen0e857f12008-07-23 13:21:29 +02002481 while (true) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002482 tline = skip_white(tline);
Victor van den Elzen0e857f12008-07-23 13:21:29 +02002483 if (!tline)
2484 break;
2485 if (tline->type != TOK_ID) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002486 nasm_nonfatal("`%s' expects context identifiers",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002487 dname);
2488 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002489 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07002490 if (cstk && cstk->name && !nasm_stricmp(tok_text(tline), cstk->name))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002491 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002492 tline = tline->next;
2493 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002494 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002495
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002496 case PP_IFDEF:
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002497 case PP_IFDEFALIAS:
2498 {
2499 bool alias = cond == PP_IFDEFALIAS;
2500 SMacro *smac;
2501 Context *ctx;
2502 const char *mname;
2503
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002504 j = false; /* have we matched yet? */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002505 while (tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002506 tline = skip_white(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002507 if (!tline || (tline->type != TOK_ID &&
H. Peter Anvin8571f062019-09-23 16:40:03 -07002508 tline->type != TOK_LOCAL_MACRO)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002509 nasm_nonfatal("`%s' expects macro identifiers",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002510 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002511 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002512 }
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002513
2514 mname = tok_text(tline);
2515 ctx = get_ctx(mname, &mname);
H. Peter Anvin (Intel)b91e7732020-06-05 12:22:26 -07002516 if (smacro_defined(ctx, mname, -1, &smac, true, alias) && smac
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002517 && smac->alias == alias) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002518 j = true;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002519 break;
2520 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002521 tline = tline->next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002522 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002523 break;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002524 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002525
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002526 case PP_IFENV:
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04002527 tline = expand_smacro(tline);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002528 j = false; /* have we matched yet? */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002529 while (tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002530 tline = skip_white(tline);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002531 if (!tline || (tline->type != TOK_ID &&
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04002532 tline->type != TOK_STRING &&
H. Peter Anvin8571f062019-09-23 16:40:03 -07002533 tline->type != TOK_INTERNAL_STRING &&
2534 tline->type != TOK_ENVIRON)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002535 nasm_nonfatal("`%s' expects environment variable names",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002536 dname);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002537 goto fail;
2538 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07002539
2540 j |= !!pp_getenv(tline, false);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002541 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002542 }
2543 break;
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002544
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002545 case PP_IFIDNI:
2546 casesense = false;
2547 /* fall through */
2548 case PP_IFIDN:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002549 tline = expand_smacro(tline);
2550 t = tt = tline;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002551 while (tok_isnt(tt, ','))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002552 tt = tt->next;
2553 if (!tt) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002554 nasm_nonfatal("`%s' expects two comma-separated arguments",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002555 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002556 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002557 }
2558 tt = tt->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002559 j = true; /* assume equality unless proved not */
H. Peter Anvin8571f062019-09-23 16:40:03 -07002560 while (tok_isnt(t, ',') && tt) {
2561 unsigned int l1, l2;
2562 const char *t1, *t2;
2563
2564 if (tok_is(tt, ',')) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002565 nasm_nonfatal("`%s': more than one comma on line",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002566 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002567 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002568 }
2569 if (t->type == TOK_WHITESPACE) {
2570 t = t->next;
2571 continue;
2572 }
2573 if (tt->type == TOK_WHITESPACE) {
2574 tt = tt->next;
2575 continue;
2576 }
2577 if (tt->type != t->type) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002578 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002579 break;
2580 }
H. Peter Anvind2456592008-06-19 15:04:18 -07002581
H. Peter Anvin8571f062019-09-23 16:40:03 -07002582 t1 = unquote_token(t);
2583 t2 = unquote_token(tt);
2584 l1 = t->len;
2585 l2 = tt->len;
2586
2587 if (l1 != l2 || mmemcmp(t1, t2, l1, casesense)) {
2588 j = false;
2589 break;
2590 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00002591
H. Peter Anvine2c80182005-01-15 22:15:51 +00002592 t = t->next;
2593 tt = tt->next;
2594 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07002595 if (!tok_is(t, ',') || tt)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002596 j = false; /* trailing gunk on one end or other */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002597 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002598
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002599 case PP_IFMACRO:
H. Peter Anvin89cee572009-07-15 09:16:54 -04002600 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002601 bool found = false;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002602 MMacro searching, *mmac;
H. Peter Anvin65747262002-05-07 00:10:05 +00002603
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002604 tline = skip_white(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002605 tline = expand_id(tline);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002606 if (!tok_type(tline, TOK_ID)) {
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002607 nasm_nonfatal("`%s' expects a macro name", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002608 goto fail;
2609 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002610 nasm_zero(searching);
H. Peter Anvin8571f062019-09-23 16:40:03 -07002611 searching.name = dup_text(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002612 searching.casesense = true;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002613 searching.nparam_min = 0;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002614 searching.nparam_max = INT_MAX;
2615 tline = expand_smacro(tline->next);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002616 tline = skip_white(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002617 if (!tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002618 } else if (!tok_type(tline, TOK_NUMBER)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002619 nasm_nonfatal("`%s' expects a parameter count or nothing",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002620 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002621 } else {
2622 searching.nparam_min = searching.nparam_max =
H. Peter Anvin8571f062019-09-23 16:40:03 -07002623 read_param_count(tok_text(tline));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002624 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002625 if (tline && tok_is(tline->next, '-')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002626 tline = tline->next->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002627 if (tok_is(tline, '*'))
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002628 searching.nparam_max = INT_MAX;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002629 else if (!tok_type(tline, TOK_NUMBER))
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002630 nasm_nonfatal("`%s' expects a parameter count after `-'",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002631 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002632 else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002633 searching.nparam_max = read_param_count(tok_text(tline));
Cyrill Gorcunovc9244ea2017-10-22 15:25:48 +03002634 if (searching.nparam_min > searching.nparam_max) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002635 nasm_nonfatal("minimum parameter count exceeds maximum");
Cyrill Gorcunovc9244ea2017-10-22 15:25:48 +03002636 searching.nparam_max = searching.nparam_min;
2637 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002638 }
2639 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002640 if (tline && tok_is(tline->next, '+')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002641 tline = tline->next;
2642 searching.plus = true;
2643 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002644 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
2645 while (mmac) {
2646 if (!strcmp(mmac->name, searching.name) &&
2647 (mmac->nparam_min <= searching.nparam_max
2648 || searching.plus)
2649 && (searching.nparam_min <= mmac->nparam_max
2650 || mmac->plus)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002651 found = true;
2652 break;
2653 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002654 mmac = mmac->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002655 }
2656 if (tline && tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08002657 nasm_warn(WARN_OTHER, "trailing garbage after %%ifmacro ignored");
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002658 nasm_free(searching.name);
2659 j = found;
2660 break;
H. Peter Anvin89cee572009-07-15 09:16:54 -04002661 }
H. Peter Anvin65747262002-05-07 00:10:05 +00002662
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002663 case PP_IFID:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002664 needtype = TOK_ID;
2665 goto iftype;
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002666 case PP_IFNUM:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002667 needtype = TOK_NUMBER;
2668 goto iftype;
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002669 case PP_IFSTR:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002670 needtype = TOK_STRING;
2671 goto iftype;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002672
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002673iftype:
2674 t = tline = expand_smacro(tline);
H. Peter Anvind85d2502008-05-04 17:53:31 -07002675
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002676 while (tok_white(t) ||
2677 (needtype == TOK_NUMBER && (tok_is(t, '-') | tok_is(t, '+'))))
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002678 t = t->next;
H. Peter Anvind85d2502008-05-04 17:53:31 -07002679
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002680 j = tok_type(t, needtype);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002681 break;
H. Peter Anvincbf768d2008-02-16 16:41:25 -08002682
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002683 case PP_IFTOKEN:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002684 tline = expand_smacro(tline);
2685 t = skip_white(tline);
H. Peter Anvincbf768d2008-02-16 16:41:25 -08002686
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002687 j = false;
2688 if (t) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002689 t = skip_white(t->next); /* Skip the actual token + whitespace */
2690 j = !t;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002691 }
2692 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002693
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002694 case PP_IFEMPTY:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002695 tline = expand_smacro(tline);
2696 t = skip_white(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002697 j = !t; /* Should be empty */
2698 break;
H. Peter Anvin134b9462008-02-16 17:01:40 -08002699
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002700 case PP_IF:
H. Peter Anvin8b262472019-02-26 14:00:54 -08002701 pps.tptr = tline = expand_smacro(tline);
2702 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002703 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07002704 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002705 if (!evalresult)
2706 return -1;
2707 if (tokval.t_type)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08002708 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00002709 if (!is_simple(evalresult)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002710 nasm_nonfatal("non-constant value given to `%s'",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002711 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002712 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002713 }
Chuck Crayne60ae75d2007-05-02 01:59:16 +00002714 j = reloc_value(evalresult) != 0;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002715 break;
H. Peter Anvin95e28822007-09-12 04:20:08 +00002716
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002717 case PP_IFUSING:
2718 case PP_IFUSABLE:
2719 {
2720 const struct use_package *pkg;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002721 const char *name;
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002722
H. Peter Anvin8571f062019-09-23 16:40:03 -07002723 pkg = get_use_pkg(tline, dname, &name);
2724 if (!name)
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002725 goto fail;
2726
2727 j = pkg && ((cond == PP_IFUSABLE) | use_loaded[pkg->index]);
2728 break;
2729 }
2730
H. Peter Anvine2c80182005-01-15 22:15:51 +00002731 default:
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002732 nasm_nonfatal("unknown preprocessor directive `%s'", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002733 goto fail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002734 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002735
2736 free_tlist(origline);
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002737 return (j ^ PP_COND_NEGATIVE(ct)) ? COND_IF_TRUE : COND_IF_FALSE;
H. Peter Anvin70653092007-10-19 14:42:29 -07002738
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002739fail:
2740 free_tlist(origline);
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002741 return COND_NEVER;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002742}
2743
2744/*
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07002745 * Default smacro expansion routine: just returns a copy of the
2746 * expansion list.
2747 */
2748static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002749smacro_expand_default(const SMacro *s, Token **params, int nparams)
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07002750{
2751 (void)params;
2752 (void)nparams;
2753
2754 return dup_tlist(s->expansion, NULL);
2755}
2756
2757/*
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002758 * Emit a macro defintion or undef to the listing file, if
2759 * desired. This is similar to detoken(), but it handles the reverse
2760 * expansion list, does not expand %! or local variable tokens, and
2761 * does some special handling for macro parameters.
2762 */
2763static void
2764list_smacro_def(enum preproc_token op, const Context *ctx, const SMacro *m)
2765{
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002766 Token *t;
2767 size_t namelen, size;
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002768 char *def, *p;
H. Peter Anvin6686de22019-08-10 05:33:14 -07002769 char *context_prefix = NULL;
2770 size_t context_len;
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002771
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002772 namelen = strlen(m->name);
2773 size = namelen + 2; /* Include room for space after name + NUL */
2774
2775 if (ctx) {
H. Peter Anvin6686de22019-08-10 05:33:14 -07002776 int context_depth = cstk->depth - ctx->depth + 1;
2777 context_prefix =
2778 nasm_asprintf("[%s::%"PRIu64"] %%%-*s",
2779 ctx->name ? ctx->name : "",
2780 ctx->number, context_depth, "");
2781
2782 context_len = nasm_last_string_len();
2783 memset(context_prefix + context_len - context_depth,
2784 '$', context_depth);
2785 size += context_len;
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002786 }
2787
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002788 list_for_each(t, m->expansion)
H. Peter Anvin8571f062019-09-23 16:40:03 -07002789 size += t->len;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002790
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002791 if (m->nparam) {
2792 /*
2793 * Space for ( and either , or ) around each
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002794 * parameter, plus up to 4 flags.
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002795 */
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002796 int i;
2797
2798 size += 1 + 4 * m->nparam;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002799 for (i = 0; i < m->nparam; i++)
H. Peter Anvin8571f062019-09-23 16:40:03 -07002800 size += m->params[i].name.len;
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002801 }
2802
2803 def = nasm_malloc(size);
2804 p = def+size;
2805 *--p = '\0';
2806
2807 list_for_each(t, m->expansion) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002808 p -= t->len;
2809 memcpy(p, tok_text(t), t->len);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002810 }
2811
2812 *--p = ' ';
2813
2814 if (m->nparam) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002815 int i;
2816
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002817 *--p = ')';
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002818 for (i = m->nparam-1; i >= 0; i--) {
2819 enum sparmflags flags = m->params[i].flags;
2820 if (flags & SPARM_GREEDY)
2821 *--p = '+';
H. Peter Anvin8571f062019-09-23 16:40:03 -07002822 p -= m->params[i].name.len;
2823 memcpy(p, tok_text(&m->params[i].name), m->params[i].name.len);
2824
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002825 if (flags & SPARM_NOSTRIP)
2826 *--p = '!';
2827 if (flags & SPARM_STR)
2828 *--p = '&';
2829 if (flags & SPARM_EVAL)
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002830 *--p = '=';
2831 *--p = ',';
2832 }
2833 *p = '('; /* First parameter starts with ( not , */
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002834 }
2835
2836 p -= namelen;
2837 memcpy(p, m->name, namelen);
2838
H. Peter Anvin6686de22019-08-10 05:33:14 -07002839 if (context_prefix) {
2840 p -= context_len;
2841 memcpy(p, context_prefix, context_len);
2842 nasm_free(context_prefix);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002843 }
2844
2845 nasm_listmsg("%s %s", pp_directives[op], p);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002846 nasm_free(def);
H. Peter Anvin6686de22019-08-10 05:33:14 -07002847}
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002848
2849/*
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002850 * Parse smacro arguments, return argument count. If the tmpl argument
2851 * is set, set the nparam, greedy and params field in the template.
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002852 * *tpp is updated to point to the pointer to the first token after the
2853 * prototype.
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002854 *
2855 * The text values from any argument tokens are "stolen" and the
2856 * corresponding text fields set to NULL.
2857 */
2858static int parse_smacro_template(Token ***tpp, SMacro *tmpl)
2859{
2860 int nparam = 0;
2861 enum sparmflags flags;
2862 struct smac_param *params = NULL;
H. Peter Anvin (Intel)68075f82019-08-20 12:28:05 -07002863 bool err, done;
2864 bool greedy = false;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002865 Token **tn = *tpp;
2866 Token *t = *tn;
2867 Token *name;
2868
H. Peter Anvin (Intel)d4607842019-08-20 16:19:37 -07002869 /*
2870 * DO NOT skip whitespace here, or we won't be able to distinguish:
2871 *
2872 * %define foo (a,b) ; no arguments, (a,b) is the expansion
2873 * %define bar(a,b) ; two arguments, empty expansion
2874 *
2875 * This ambiguity was inherited from C.
2876 */
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002877
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002878 if (!tok_is(t, '('))
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002879 goto finish;
2880
2881 if (tmpl) {
2882 Token *tx = t;
2883 Token **txpp = &tx;
2884 int sparam;
2885
2886 /* Count parameters first */
2887 sparam = parse_smacro_template(&txpp, NULL);
2888 if (!sparam)
2889 goto finish; /* No parameters, we're done */
2890 nasm_newn(params, sparam);
2891 }
2892
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002893 /* Skip leading paren */
2894 tn = &t->next;
2895 t = *tn;
2896
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002897 name = NULL;
2898 flags = 0;
H. Peter Anvin (Intel)68075f82019-08-20 12:28:05 -07002899 err = done = false;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002900
2901 while (!done) {
2902 if (!t || !t->type) {
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002903 if (name || flags)
2904 nasm_nonfatal("`)' expected to terminate macro template");
2905 else
2906 nasm_nonfatal("parameter identifier expected");
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002907 break;
2908 }
2909
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002910 switch (t->type) {
2911 case TOK_ID:
2912 if (name)
2913 goto bad;
2914 name = t;
2915 break;
2916
2917 case TOK_OTHER:
H. Peter Anvin8571f062019-09-23 16:40:03 -07002918 if (t->len != 1)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002919 goto bad;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002920 switch (t->text.a[0]) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002921 case '=':
2922 flags |= SPARM_EVAL;
2923 break;
2924 case '&':
2925 flags |= SPARM_STR;
2926 break;
2927 case '!':
2928 flags |= SPARM_NOSTRIP;
2929 break;
2930 case '+':
2931 flags |= SPARM_GREEDY;
2932 greedy = true;
2933 break;
2934 case ',':
2935 if (greedy)
2936 nasm_nonfatal("greedy parameter must be last");
2937 /* fall through */
2938 case ')':
2939 if (params) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002940 if (name)
2941 steal_Token(&params[nparam].name, name);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002942 params[nparam].flags = flags;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002943 }
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002944 nparam++;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002945 name = NULL;
2946 flags = 0;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002947 done = t->text.a[0] == ')';
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002948 break;
2949 default:
2950 goto bad;
2951 }
2952 break;
2953
2954 case TOK_WHITESPACE:
2955 break;
2956
2957 default:
2958 bad:
2959 if (!err) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002960 nasm_nonfatal("garbage `%s' in macro parameter list", tok_text(t));
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002961 err = true;
2962 }
2963 break;
2964 }
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002965
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002966 tn = &t->next;
2967 t = *tn;
2968 }
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002969
2970finish:
2971 while (t && t->type == TOK_WHITESPACE) {
2972 tn = &t->next;
2973 t = t->next;
2974 }
2975 *tpp = tn;
2976 if (tmpl) {
2977 tmpl->nparam = nparam;
2978 tmpl->greedy = greedy;
2979 tmpl->params = params;
2980 }
2981 return nparam;
2982}
2983
2984/*
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07002985 * Common code for defining an smacro. The tmpl argument, if not NULL,
2986 * contains any macro parameters that aren't explicit arguments;
2987 * those are the more uncommon macro variants.
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002988 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07002989static SMacro *define_smacro(const char *mname, bool casesense,
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002990 Token *expansion, SMacro *tmpl)
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002991{
2992 SMacro *smac, **smhead;
H. Peter Anvin166c2472008-05-28 12:28:58 -07002993 struct hash_table *smtbl;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07002994 Context *ctx;
2995 bool defining_alias = false;
2996 unsigned int nparam = 0;
H. Peter Anvin70653092007-10-19 14:42:29 -07002997
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07002998 if (tmpl) {
2999 defining_alias = tmpl->alias;
3000 nparam = tmpl->nparam;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07003001 if (nparam && !defining_alias)
3002 mark_smac_params(expansion, tmpl, 0);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003003 }
3004
3005 while (1) {
3006 ctx = get_ctx(mname, &mname);
3007
H. Peter Anvind2354082019-08-27 16:38:48 -07003008 if (!smacro_defined(ctx, mname, nparam, &smac, casesense, true)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003009 /* Create a new macro */
3010 smtbl = ctx ? &ctx->localmac : &smacros;
3011 smhead = (SMacro **) hash_findi_add(smtbl, mname);
3012 nasm_new(smac);
3013 smac->next = *smhead;
3014 *smhead = smac;
3015 break;
3016 } else if (!smac) {
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003017 nasm_warn(WARN_OTHER, "single-line macro `%s' defined both with and"
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003018 " without parameters", mname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003019 /*
3020 * Some instances of the old code considered this a failure,
3021 * some others didn't. What is the right thing to do here?
3022 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003023 goto fail;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003024 } else if (!smac->alias || ppopt.noaliases || defining_alias) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003025 /*
3026 * We're redefining, so we have to take over an
3027 * existing SMacro structure. This means freeing
H. Peter Anvin8b262472019-02-26 14:00:54 -08003028 * what was already in it, but not the structure itself.
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003029 */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07003030 clear_smacro(smac);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003031 break;
3032 } else if (smac->in_progress) {
3033 nasm_nonfatal("macro alias loop");
3034 goto fail;
3035 } else {
3036 /* It is an alias macro; follow the alias link */
3037 SMacro *s;
3038
3039 smac->in_progress = true;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003040 s = define_smacro(tok_text(smac->expansion), casesense,
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003041 expansion, tmpl);
3042 smac->in_progress = false;
3043 return s;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003044 }
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003045 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003046
3047 smac->name = nasm_strdup(mname);
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003048 smac->casesense = casesense;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003049 smac->expansion = expansion;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003050 smac->expand = smacro_expand_default;
3051 if (tmpl) {
3052 smac->nparam = tmpl->nparam;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07003053 smac->params = tmpl->params;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003054 smac->alias = tmpl->alias;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07003055 smac->greedy = tmpl->greedy;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003056 if (tmpl->expand)
3057 smac->expand = tmpl->expand;
3058 }
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07003059 if (list_option('s')) {
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07003060 list_smacro_def((smac->alias ? PP_DEFALIAS : PP_DEFINE)
3061 + !casesense, ctx, smac);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003062 }
H. Peter Anvin8b262472019-02-26 14:00:54 -08003063 return smac;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003064
3065fail:
3066 free_tlist(expansion);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07003067 if (tmpl)
3068 free_smacro_members(tmpl);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003069 return NULL;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003070}
3071
3072/*
3073 * Undefine an smacro
3074 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003075static void undef_smacro(const char *mname, bool undefalias)
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003076{
3077 SMacro **smhead, *s, **sp;
H. Peter Anvin166c2472008-05-28 12:28:58 -07003078 struct hash_table *smtbl;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003079 Context *ctx;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003080
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003081 ctx = get_ctx(mname, &mname);
H. Peter Anvin166c2472008-05-28 12:28:58 -07003082 smtbl = ctx ? &ctx->localmac : &smacros;
3083 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
H. Peter Anvin70653092007-10-19 14:42:29 -07003084
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003085 if (smhead) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003086 /*
3087 * We now have a macro name... go hunt for it.
3088 */
3089 sp = smhead;
3090 while ((s = *sp) != NULL) {
3091 if (!mstrcmp(s->name, mname, s->casesense)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003092 if (s->alias && !undefalias) {
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003093 if (!ppopt.noaliases) {
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07003094 if (s->in_progress) {
3095 nasm_nonfatal("macro alias loop");
3096 } else {
3097 s->in_progress = true;
3098 undef_smacro(tok_text(s->expansion), false);
3099 s->in_progress = false;
3100 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003101 }
3102 } else {
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07003103 if (list_option('d'))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003104 list_smacro_def(s->alias ? PP_UNDEFALIAS : PP_UNDEF,
3105 ctx, s);
3106 *sp = s->next;
3107 free_smacro(s);
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07003108 continue;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003109 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003110 }
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07003111 sp = &s->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003112 }
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003113 }
3114}
3115
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003116/*
H. Peter Anvina26433d2008-07-16 14:40:01 -07003117 * Parse a mmacro specification.
3118 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003119static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
H. Peter Anvina26433d2008-07-16 14:40:01 -07003120{
H. Peter Anvina26433d2008-07-16 14:40:01 -07003121 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003122 tline = skip_white(tline);
H. Peter Anvina26433d2008-07-16 14:40:01 -07003123 tline = expand_id(tline);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003124 if (!tok_type(tline, TOK_ID)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003125 nasm_nonfatal("`%s' expects a macro name", directive);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003126 return false;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003127 }
Victor van den Elzenb916ede2008-07-23 15:14:22 +02003128
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07003129#if 0
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003130 def->prev = NULL;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07003131#endif
H. Peter Anvin8571f062019-09-23 16:40:03 -07003132 def->name = dup_text(tline);
H. Peter Anvina26433d2008-07-16 14:40:01 -07003133 def->plus = false;
3134 def->nolist = false;
Victor van den Elzenb916ede2008-07-23 15:14:22 +02003135 def->nparam_min = 0;
3136 def->nparam_max = 0;
3137
H. Peter Anvina26433d2008-07-16 14:40:01 -07003138 tline = expand_smacro(tline->next);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003139 tline = skip_white(tline);
3140 if (!tok_type(tline, TOK_NUMBER))
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003141 nasm_nonfatal("`%s' expects a parameter count", directive);
3142 else
H. Peter Anvin8571f062019-09-23 16:40:03 -07003143 def->nparam_min = def->nparam_max = read_param_count(tok_text(tline));
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003144 if (tline && tok_is(tline->next, '-')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003145 tline = tline->next->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003146 if (tok_is(tline, '*')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003147 def->nparam_max = INT_MAX;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003148 } else if (!tok_type(tline, TOK_NUMBER)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003149 nasm_nonfatal("`%s' expects a parameter count after `-'", directive);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003150 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003151 def->nparam_max = read_param_count(tok_text(tline));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003152 if (def->nparam_min > def->nparam_max) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003153 nasm_nonfatal("minimum parameter count exceeds maximum");
Cyrill Gorcunovc9244ea2017-10-22 15:25:48 +03003154 def->nparam_max = def->nparam_min;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003155 }
3156 }
H. Peter Anvina26433d2008-07-16 14:40:01 -07003157 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003158 if (tline && tok_is(tline->next, '+')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003159 tline = tline->next;
3160 def->plus = true;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003161 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003162 if (tline && tok_type(tline->next, TOK_ID) &&
H. Peter Anvin8571f062019-09-23 16:40:03 -07003163 tline->next->len == 7 &&
3164 !nasm_stricmp(tline->next->text.a, ".nolist")) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003165 tline = tline->next;
H. Peter Anvin6686de22019-08-10 05:33:14 -07003166 def->nolist = !list_option('f') || istk->nolist;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003167 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003168
H. Peter Anvina26433d2008-07-16 14:40:01 -07003169 /*
3170 * Handle default parameters.
3171 */
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07003172 def->ndefs = 0;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003173 if (tline && tline->next) {
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07003174 Token **comma;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003175 def->dlist = tline->next;
3176 tline->next = NULL;
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07003177 comma = count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
3178 if (!ppopt.sane_empty_expansion && comma) {
3179 *comma = NULL;
3180 def->ndefs--;
3181 nasm_warn(WARN_MACRO_PARAMS_LEGACY,
3182 "dropping trailing empty default parameter in defintion of multi-line macro `%s'",
3183 def->name);
3184 }
H. Peter Anvina26433d2008-07-16 14:40:01 -07003185 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003186 def->dlist = NULL;
3187 def->defaults = NULL;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003188 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003189 def->expansion = NULL;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003190
H. Peter Anvin89cee572009-07-15 09:16:54 -04003191 if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -08003192 !def->plus) {
3193 /*
3194 *!macro-defaults [on] macros with more default than optional parameters
3195 *! warns when a macro has more default parameters than optional parameters.
3196 *! See \k{mlmacdef} for why might want to disable this warning.
3197 */
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003198 nasm_warn(WARN_MACRO_DEFAULTS,
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -08003199 "too many default macro parameters in macro `%s'", def->name);
3200 }
Victor van den Elzenb916ede2008-07-23 15:14:22 +02003201
H. Peter Anvina26433d2008-07-16 14:40:01 -07003202 return true;
3203}
3204
3205
3206/*
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003207 * Decode a size directive
3208 */
3209static int parse_size(const char *str) {
3210 static const char *size_names[] =
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003211 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003212 static const int sizes[] =
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003213 { 0, 1, 4, 16, 8, 10, 2, 32 };
Cyrill Gorcunovc713b5f2018-09-29 14:30:14 +03003214 return str ? sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1] : 0;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003215}
3216
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003217/*
3218 * Process a preprocessor %pragma directive. Currently there are none.
3219 * Gets passed the token list starting with the "preproc" token from
3220 * "%pragma preproc".
3221 */
3222static void do_pragma_preproc(Token *tline)
3223{
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003224 const char *txt;
3225
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003226 /* Skip to the real stuff */
3227 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003228 tline = skip_white(tline);
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003229
3230 if (!tok_type(tline, TOK_ID))
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003231 return;
3232
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003233 txt = tok_text(tline);
3234 if (!nasm_stricmp(txt, "sane_empty_expansion")) {
3235 tline = skip_white(tline->next);
3236 ppopt.sane_empty_expansion =
3237 pp_get_boolean_option(tline, ppopt.sane_empty_expansion);
3238 } else {
3239 /* Unknown pragma, ignore for now */
3240 }
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003241}
3242
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003243static bool is_macro_id(const Token *t)
3244{
H. Peter Anvin8571f062019-09-23 16:40:03 -07003245 return tok_type(t, TOK_ID) || tok_type(t, TOK_LOCAL_MACRO);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003246}
3247
H. Peter Anvin8571f062019-09-23 16:40:03 -07003248static const char *get_id(Token **tp, const char *dname)
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003249{
H. Peter Anvin8571f062019-09-23 16:40:03 -07003250 const char *id;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003251 Token *t = *tp;
3252
3253 t = t->next; /* Skip directive */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003254 t = skip_white(t);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003255 t = expand_id(t);
3256
3257 if (!is_macro_id(t)) {
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003258 nasm_nonfatal("`%s' expects a macro identifier", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003259 return NULL;
3260 }
3261
H. Peter Anvin8571f062019-09-23 16:40:03 -07003262 id = tok_text(t);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003263 t = skip_white(t);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003264 *tp = t;
3265 return id;
3266}
3267
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003268/* Parse a %use package name and find the package. Set *err on syntax error. */
3269static const struct use_package *
H. Peter Anvin8571f062019-09-23 16:40:03 -07003270get_use_pkg(Token *t, const char *dname, const char **name)
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003271{
H. Peter Anvin8571f062019-09-23 16:40:03 -07003272 const char *id;
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003273
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003274 t = skip_white(t);
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003275 t = expand_smacro(t);
3276
H. Peter Anvin8571f062019-09-23 16:40:03 -07003277 *name = NULL;
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003278
H. Peter Anvin8571f062019-09-23 16:40:03 -07003279 if (!t) {
3280 nasm_nonfatal("`%s' expects a package name, got end of line", dname);
3281 return NULL;
3282 } else if (t->type != TOK_ID && t->type != TOK_STRING) {
3283 nasm_nonfatal("`%s' expects a package name, got `%s'",
3284 dname, tok_text(t));
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003285 return NULL;
3286 }
3287
H. Peter Anvin8571f062019-09-23 16:40:03 -07003288 *name = id = unquote_token(t);
3289
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003290 t = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003291 t = skip_white(t);
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003292 if (t)
3293 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3294
3295 return nasm_find_use_package(id);
3296}
3297
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003298/*
3299 * Mark parameter tokens in an smacro definition. If the type argument
3300 * is 0, create smac param tokens, otherwise use the type specified;
3301 * normally this is used for TOK_XDEF_PARAM, which is used to protect
3302 * parameter tokens during expansion during %xdefine.
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07003303 *
3304 * tmpl may not be NULL here.
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003305 */
3306static void mark_smac_params(Token *tline, const SMacro *tmpl,
3307 enum pp_token_type type)
3308{
3309 const struct smac_param *params = tmpl->params;
3310 int nparam = tmpl->nparam;
3311 Token *t;
3312 int i;
3313
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003314 list_for_each(t, tline) {
3315 if (t->type != TOK_ID && t->type != TOK_XDEF_PARAM)
3316 continue;
3317
3318 for (i = 0; i < nparam; i++) {
3319 if (tok_text_match(t, &params[i].name))
3320 t->type = type ? type : tok_smac_param(i);
3321 }
3322 }
3323}
3324
Ed Beroset3ab3f412002-06-11 03:31:49 +00003325/**
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003326 * %clear selected macro sets either globally or in contexts
3327 */
3328static void do_clear(enum clear_what what, bool context)
3329{
3330 if (context) {
3331 if (what & CLEAR_ALLDEFINE) {
3332 Context *ctx;
3333 list_for_each(ctx, cstk)
3334 clear_smacro_table(&ctx->localmac, what);
3335 }
3336 /* Nothing else can be context-local */
3337 } else {
3338 if (what & CLEAR_ALLDEFINE)
3339 clear_smacro_table(&smacros, what);
3340 if (what & CLEAR_MMACRO)
3341 free_mmacro_table(&mmacros);
3342 }
3343}
3344
3345/**
Ed Beroset3ab3f412002-06-11 03:31:49 +00003346 * find and process preprocessor directive in passed line
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003347 * Find out if a line contains a preprocessor directive, and deal
3348 * with it if so.
H. Peter Anvin70653092007-10-19 14:42:29 -07003349 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00003350 * If a directive _is_ found, it is the responsibility of this routine
3351 * (and not the caller) to free_tlist() the line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003352 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00003353 * @param tline a pointer to the current tokeninzed line linked list
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003354 * @param output if this directive generated output
Ed Beroset3ab3f412002-06-11 03:31:49 +00003355 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
H. Peter Anvin70653092007-10-19 14:42:29 -07003356 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003357 */
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07003358static int do_directive(Token *tline, Token **output)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003359{
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003360 enum preproc_token op;
H. Peter Anvin4169a472007-09-12 01:29:43 +00003361 int j;
H. Peter Anvin70055962007-10-11 00:05:31 -07003362 bool err;
H. Peter Anvin70055962007-10-11 00:05:31 -07003363 bool nolist;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003364 bool casesense;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -07003365 int k, m;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003366 int offset;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003367 const char *p;
3368 char *q, *qbuf;
H. Peter Anvinccad6f92016-10-04 00:34:35 -07003369 const char *found_path;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003370 const char *mname;
H. Peter Anvin8b262472019-02-26 14:00:54 -08003371 struct ppscan pps;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003372 Include *inc;
3373 Context *ctx;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003374 Cond *cond;
3375 MMacro *mmac, **mmhead;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07003376 Token *t = NULL, *tt, *macro_start, *last, *origline;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003377 Line *l;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003378 struct tokenval tokval;
3379 expr *evalresult;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07003380 int64_t count;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003381 size_t len;
H. Peter Anvin (Intel)6bde2ed2018-12-13 19:39:41 -08003382 errflags severity;
H. Peter Anvin8b262472019-02-26 14:00:54 -08003383 const char *dname; /* Name of directive, for messages */
H. Peter Anvin76690a12002-04-30 20:52:49 +00003384
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003385 *output = NULL; /* No output generated */
H. Peter Anvin76690a12002-04-30 20:52:49 +00003386 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003387
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003388 tline = skip_white(tline);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003389 if (!tline || !tok_type(tline, TOK_PREPROC_ID))
3390 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003391
H. Peter Anvin8571f062019-09-23 16:40:03 -07003392 dname = tok_text(tline);
3393 if (dname[1] == '%')
3394 return NO_DIRECTIVE_FOUND;
3395
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003396 op = pp_token_hash(dname);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003397
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003398 casesense = true;
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003399 if (PP_HAS_CASE(op) & PP_INSENSITIVE(op)) {
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003400 casesense = false;
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003401 op--;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003402 }
3403
3404 /*
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07003405 * %line directives are always processed immediately and
3406 * unconditionally, as they are intended to reflect position
3407 * in externally preprocessed sources.
3408 */
3409 if (op == PP_LINE) {
3410 /*
3411 * Syntax is `%line nnn[+mmm] [filename]'
3412 */
3413 if (pp_noline || istk->mstk.mstk)
3414 goto done;
3415
3416 tline = tline->next;
3417 tline = skip_white(tline);
3418 if (!tok_type(tline, TOK_NUMBER)) {
3419 nasm_nonfatal("`%s' expects line number", dname);
3420 goto done;
3421 }
3422 k = readnum(tok_text(tline), &err);
3423 m = 1;
3424 tline = tline->next;
3425 if (tok_is(tline, '+') || tok_is(tline, '-')) {
3426 bool minus = tok_is(tline, '-');
3427 tline = tline->next;
3428 if (!tok_type(tline, TOK_NUMBER)) {
3429 nasm_nonfatal("`%s' expects line increment", dname);
3430 goto done;
3431 }
3432 m = readnum(tok_text(tline), &err);
3433 if (minus)
3434 m = -m;
3435 tline = tline->next;
3436 }
3437 tline = skip_white(tline);
3438 if (tline) {
3439 if (tline->type == TOK_STRING) {
3440 src_set_fname(unquote_token(tline));
3441 } else {
3442 char *fname = detoken(tline, false);
3443 src_set_fname(fname);
3444 nasm_free(fname);
3445 }
3446 }
3447 src_set_linnum(k);
3448
3449 istk->where = src_where();
3450 istk->lineinc = m;
3451 goto done;
3452 }
3453
3454 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003455 * If we're in a non-emitting branch of a condition construct,
3456 * or walking to the end of an already terminated %rep block,
3457 * we should ignore all directives except for condition
3458 * directives.
3459 */
3460 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07003461 (istk->mstk.mstk && !istk->mstk.mstk->in_progress)) &&
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003462 !is_condition(op)) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003463 return NO_DIRECTIVE_FOUND;
3464 }
3465
3466 /*
3467 * If we're defining a macro or reading a %rep block, we should
3468 * ignore all directives except for %macro/%imacro (which nest),
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07003469 * %endm/%endmacro, %line and (only if we're in a %rep block) %endrep.
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003470 * If we're in a %rep block, another %rep nests, so should be let through.
3471 */
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003472 if (defining && op != PP_MACRO && op != PP_RMACRO &&
3473 op != PP_ENDMACRO && op != PP_ENDM &&
3474 (defining->name || (op != PP_ENDREP && op != PP_REP))) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003475 return NO_DIRECTIVE_FOUND;
3476 }
3477
3478 if (defining) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003479 if (op == PP_MACRO || op == PP_RMACRO) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003480 nested_mac_count++;
3481 return NO_DIRECTIVE_FOUND;
3482 } else if (nested_mac_count > 0) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003483 if (op == PP_ENDMACRO) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003484 nested_mac_count--;
3485 return NO_DIRECTIVE_FOUND;
3486 }
3487 }
3488 if (!defining->name) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003489 if (op == PP_REP) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003490 nested_rep_count++;
3491 return NO_DIRECTIVE_FOUND;
3492 } else if (nested_rep_count > 0) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003493 if (op == PP_ENDREP) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003494 nested_rep_count--;
3495 return NO_DIRECTIVE_FOUND;
3496 }
3497 }
3498 }
3499 }
3500
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003501 switch (op) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003502 default:
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003503 nasm_nonfatal("unknown preprocessor directive `%s'", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003504 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003505
H. Peter Anvin3f87a2a2016-10-04 14:07:19 -07003506 case PP_PRAGMA:
3507 /*
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003508 * %pragma namespace options...
3509 *
3510 * The namespace "preproc" is reserved for the preprocessor;
3511 * all other namespaces generate a [pragma] assembly directive.
3512 *
3513 * Invalid %pragmas are ignored and may have different
3514 * meaning in future versions of NASM.
H. Peter Anvin3f87a2a2016-10-04 14:07:19 -07003515 */
H. Peter Anvinf5d7d902019-08-10 06:21:00 -07003516 t = tline;
3517 tline = tline->next;
3518 t->next = NULL;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003519 tline = zap_white(expand_smacro(tline));
3520 if (tok_type(tline, TOK_ID)) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003521 if (!nasm_stricmp(tok_text(tline), "preproc")) {
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003522 /* Preprocessor pragma */
3523 do_pragma_preproc(tline);
H. Peter Anvin06335872019-08-10 06:42:55 -07003524 free_tlist(tline);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003525 } else {
3526 /* Build the assembler directive */
H. Peter Anvin06335872019-08-10 06:42:55 -07003527
3528 /* Append bracket to the end of the output */
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003529 for (t = tline; t->next; t = t->next)
3530 ;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003531 t->next = make_tok_char(NULL, ']');
H. Peter Anvin06335872019-08-10 06:42:55 -07003532
3533 /* Prepend "[pragma " */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003534 t = new_White(tline);
H. Peter Anvin06335872019-08-10 06:42:55 -07003535 t = new_Token(t, TOK_ID, "pragma", 6);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003536 t = make_tok_char(t, '[');
H. Peter Anvin06335872019-08-10 06:42:55 -07003537 tline = t;
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07003538 *output = tline;
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003539 }
3540 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003541 break;
H. Peter Anvin3f87a2a2016-10-04 14:07:19 -07003542
H. Peter Anvine2c80182005-01-15 22:15:51 +00003543 case PP_STACKSIZE:
3544 /* Directive to tell NASM what the default stack size is. The
3545 * default is for a 16-bit stack, and this can be overriden with
3546 * %stacksize large.
H. Peter Anvine2c80182005-01-15 22:15:51 +00003547 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003548 tline = skip_white(tline->next);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003549 if (!tline || tline->type != TOK_ID) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003550 nasm_nonfatal("`%s' missing size parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003551 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07003552 if (nasm_stricmp(tok_text(tline), "flat") == 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003553 /* All subsequent ARG directives are for a 32-bit stack */
3554 StackSize = 4;
3555 StackPointer = "ebp";
3556 ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003557 LocalOffset = 0;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003558 } else if (nasm_stricmp(tok_text(tline), "flat64") == 0) {
Charles Crayne7eaf9192007-11-08 22:11:14 -08003559 /* All subsequent ARG directives are for a 64-bit stack */
3560 StackSize = 8;
3561 StackPointer = "rbp";
Per Jessen53252e02010-02-11 00:16:59 +03003562 ArgOffset = 16;
Charles Crayne7eaf9192007-11-08 22:11:14 -08003563 LocalOffset = 0;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003564 } else if (nasm_stricmp(tok_text(tline), "large") == 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003565 /* All subsequent ARG directives are for a 16-bit stack,
3566 * far function call.
3567 */
3568 StackSize = 2;
3569 StackPointer = "bp";
3570 ArgOffset = 4;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003571 LocalOffset = 0;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003572 } else if (nasm_stricmp(tok_text(tline), "small") == 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003573 /* All subsequent ARG directives are for a 16-bit stack,
3574 * far function call. We don't support near functions.
3575 */
3576 StackSize = 2;
3577 StackPointer = "bp";
3578 ArgOffset = 6;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003579 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003580 } else {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003581 nasm_nonfatal("`%s' invalid size type", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003582 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003583 break;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003584
H. Peter Anvine2c80182005-01-15 22:15:51 +00003585 case PP_ARG:
3586 /* TASM like ARG directive to define arguments to functions, in
3587 * the following form:
3588 *
3589 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
3590 */
3591 offset = ArgOffset;
3592 do {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003593 const char *arg;
3594 char directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003595 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003596
H. Peter Anvine2c80182005-01-15 22:15:51 +00003597 /* Find the argument name */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003598 tline = skip_white(tline->next);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003599 if (!tline || tline->type != TOK_ID) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003600 nasm_nonfatal("`%s' missing argument parameter", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003601 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003602 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07003603 arg = tok_text(tline);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003604
H. Peter Anvine2c80182005-01-15 22:15:51 +00003605 /* Find the argument size type */
3606 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003607 if (!tok_is(tline, ':')) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003608 nasm_nonfatal("syntax error processing `%s' directive", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003609 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003610 }
3611 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003612 if (!tok_type(tline, TOK_ID)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003613 nasm_nonfatal("`%s' missing size type parameter", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003614 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003615 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003616
H. Peter Anvine2c80182005-01-15 22:15:51 +00003617 /* Allow macro expansion of type parameter */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003618 tt = tokenize(tok_text(tline));
H. Peter Anvine2c80182005-01-15 22:15:51 +00003619 tt = expand_smacro(tt);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003620 size = parse_size(tok_text(tt));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003621 if (!size) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003622 nasm_nonfatal("invalid size type for `%s' missing directive", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003623 free_tlist(tt);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003624 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003625 }
3626 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003627
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003628 /* Round up to even stack slots */
3629 size = ALIGN(size, StackSize);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003630
H. Peter Anvine2c80182005-01-15 22:15:51 +00003631 /* Now define the macro for the argument */
3632 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
3633 arg, StackPointer, offset);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003634 do_directive(tokenize(directive), output);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003635 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003636
H. Peter Anvine2c80182005-01-15 22:15:51 +00003637 /* Move to the next argument in the list */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003638 tline = skip_white(tline->next);
3639 } while (tok_is(tline, ','));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003640 ArgOffset = offset;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003641 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003642
H. Peter Anvine2c80182005-01-15 22:15:51 +00003643 case PP_LOCAL:
3644 /* TASM like LOCAL directive to define local variables for a
3645 * function, in the following form:
3646 *
3647 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
3648 *
3649 * The '= LocalSize' at the end is ignored by NASM, but is
3650 * required by TASM to define the local parameter size (and used
3651 * by the TASM macro package).
3652 */
3653 offset = LocalOffset;
3654 do {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003655 const char *local;
3656 char directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003657 int size = StackSize;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003658
H. Peter Anvine2c80182005-01-15 22:15:51 +00003659 /* Find the argument name */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003660 tline = skip_white(tline->next);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003661 if (!tline || tline->type != TOK_ID) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003662 nasm_nonfatal("`%s' missing argument parameter", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003663 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003664 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07003665 local = tok_text(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003666
H. Peter Anvine2c80182005-01-15 22:15:51 +00003667 /* Find the argument size type */
3668 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003669 if (!tok_is(tline, ':')) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003670 nasm_nonfatal("syntax error processing `%s' directive", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003671 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003672 }
3673 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003674 if (!tok_type(tline, TOK_ID)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003675 nasm_nonfatal("`%s' missing size type parameter", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003676 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003677 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003678
H. Peter Anvine2c80182005-01-15 22:15:51 +00003679 /* Allow macro expansion of type parameter */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003680 tt = tokenize(tok_text(tline));
H. Peter Anvine2c80182005-01-15 22:15:51 +00003681 tt = expand_smacro(tt);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003682 size = parse_size(tok_text(tt));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003683 if (!size) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003684 nasm_nonfatal("invalid size type for `%s' missing directive", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003685 free_tlist(tt);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003686 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003687 }
3688 free_tlist(tt);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003689
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003690 /* Round up to even stack slots */
3691 size = ALIGN(size, StackSize);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003692
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003693 offset += size; /* Negative offset, increment before */
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003694
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003695 /* Now define the macro for the argument */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003696 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
3697 local, StackPointer, offset);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003698 do_directive(tokenize(directive), output);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003699
H. Peter Anvine2c80182005-01-15 22:15:51 +00003700 /* Now define the assign to setup the enter_c macro correctly */
3701 snprintf(directive, sizeof(directive),
3702 "%%assign %%$localsize %%$localsize+%d", size);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003703 do_directive(tokenize(directive), output);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003704
H. Peter Anvine2c80182005-01-15 22:15:51 +00003705 /* Move to the next argument in the list */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003706 tline = skip_white(tline->next);
3707 } while (tok_is(tline, ','));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003708 LocalOffset = offset;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003709 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003710
H. Peter Anvine2c80182005-01-15 22:15:51 +00003711 case PP_CLEAR:
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003712 {
3713 bool context = false;
3714
3715 t = tline->next = expand_smacro(tline->next);
3716 t = skip_white(t);
3717 if (!t) {
3718 /* Emulate legacy behavior */
3719 do_clear(CLEAR_DEFINE|CLEAR_MMACRO, false);
3720 } else {
3721 while ((t = skip_white(t)) && t->type == TOK_ID) {
3722 const char *txt = tok_text(t);
3723 if (!nasm_stricmp(txt, "all")) {
3724 do_clear(CLEAR_ALL, context);
3725 } else if (!nasm_stricmp(txt, "define") ||
3726 !nasm_stricmp(txt, "def") ||
3727 !nasm_stricmp(txt, "smacro")) {
3728 do_clear(CLEAR_DEFINE, context);
3729 } else if (!nasm_stricmp(txt, "defalias") ||
3730 !nasm_stricmp(txt, "alias") ||
3731 !nasm_stricmp(txt, "salias")) {
3732 do_clear(CLEAR_DEFALIAS, context);
3733 } else if (!nasm_stricmp(txt, "alldef") ||
3734 !nasm_stricmp(txt, "alldefine")) {
3735 do_clear(CLEAR_ALLDEFINE, context);
3736 } else if (!nasm_stricmp(txt, "macro") ||
3737 !nasm_stricmp(txt, "mmacro")) {
3738 do_clear(CLEAR_MMACRO, context);
3739 } else if (!nasm_stricmp(txt, "context") ||
3740 !nasm_stricmp(txt, "ctx")) {
3741 context = true;
3742 } else if (!nasm_stricmp(txt, "global")) {
3743 context = false;
3744 } else if (!nasm_stricmp(txt, "nothing") ||
3745 !nasm_stricmp(txt, "none") ||
3746 !nasm_stricmp(txt, "ignore") ||
3747 !nasm_stricmp(txt, "-") ||
3748 !nasm_stricmp(txt, "--")) {
3749 /* Do nothing */
3750 } else {
3751 nasm_nonfatal("invalid option to %s: %s", dname, txt);
3752 t = NULL;
3753 }
3754 }
3755 }
3756
3757 t = skip_white(t);
3758 if (t)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003759 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003760 break;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003761 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003762
H. Peter Anvin418ca702008-05-30 10:42:30 -07003763 case PP_DEPEND:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003764 t = tline->next = expand_smacro(tline->next);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003765 t = skip_white(t);
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003766 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003767 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003768 nasm_nonfatal("`%s' expects a file name", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003769 goto done;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003770 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003771 if (t->next)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003772 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003773
3774 strlist_add(deplist, unquote_token_cstr(t));
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003775 goto done;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003776
3777 case PP_INCLUDE:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003778 t = tline->next = expand_smacro(tline->next);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003779 t = skip_white(t);
H. Peter Anvind2456592008-06-19 15:04:18 -07003780
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003781 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003782 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003783 nasm_nonfatal("`%s' expects a file name", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003784 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003785 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003786 if (t->next)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003787 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003788 p = unquote_token_cstr(t);
H. Peter Anvin6686de22019-08-10 05:33:14 -07003789 nasm_new(inc);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003790 inc->next = istk;
Jim Kukunas65a8afc2016-06-13 16:00:42 -04003791 found_path = NULL;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07003792 inc->fp = inc_fopen(p, deplist, &found_path,
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08003793 (pp_mode == PP_DEPS)
3794 ? INC_OPTIONAL : INC_NEEDED, NF_TEXT);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003795 if (!inc->fp) {
3796 /* -MG given but file not found */
3797 nasm_free(inc);
3798 } else {
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07003799 src_set(0, found_path ? found_path : p);
3800 inc->where = src_where();
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003801 inc->lineinc = 1;
H. Peter Anvin6686de22019-08-10 05:33:14 -07003802 inc->nolist = istk->nolist;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003803 istk = inc;
H. Peter Anvin0d4d4312019-08-07 00:46:27 -07003804 lfmt->uplevel(LIST_INCLUDE, 0);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003805 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003806 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003807
H. Peter Anvind2456592008-06-19 15:04:18 -07003808 case PP_USE:
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07003809 {
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07003810 const struct use_package *pkg;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003811 const char *name;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07003812
H. Peter Anvin8571f062019-09-23 16:40:03 -07003813 pkg = get_use_pkg(tline->next, dname, &name);
3814 if (!name)
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003815 goto done;
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07003816 if (!pkg) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003817 nasm_nonfatal("unknown `%s' package: `%s'", dname, name);
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07003818 } else if (!use_loaded[pkg->index]) {
H. Peter Anvin6686de22019-08-10 05:33:14 -07003819 /*
3820 * Not already included, go ahead and include it.
3821 * Treat it as an include file for the purpose of
3822 * producing a listing.
3823 */
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07003824 use_loaded[pkg->index] = true;
3825 stdmacpos = pkg->macros;
H. Peter Anvin6686de22019-08-10 05:33:14 -07003826 nasm_new(inc);
3827 inc->next = istk;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07003828 src_set(0, NULL);
H. Peter Anvin6686de22019-08-10 05:33:14 -07003829 inc->nolist = !list_option('b') || istk->nolist;
3830 istk = inc;
3831 lfmt->uplevel(LIST_INCLUDE, 0);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003832 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003833 break;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07003834 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003835 case PP_PUSH:
H. Peter Anvine2c80182005-01-15 22:15:51 +00003836 case PP_REPL:
H. Peter Anvin42b56392008-10-24 16:24:21 -07003837 case PP_POP:
H. Peter Anvine2c80182005-01-15 22:15:51 +00003838 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003839 tline = skip_white(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003840 tline = expand_id(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003841 if (tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003842 if (!tok_type(tline, TOK_ID)) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003843 nasm_nonfatal("`%s' expects a context identifier", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003844 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003845 }
3846 if (tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003847 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored",
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003848 dname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003849 p = tok_text(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003850 } else {
3851 p = NULL; /* Anonymous */
3852 }
H. Peter Anvin42b56392008-10-24 16:24:21 -07003853
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003854 if (op == PP_PUSH) {
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08003855 nasm_new(ctx);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07003856 ctx->depth = cstk ? cstk->depth + 1 : 1;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003857 ctx->next = cstk;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003858 ctx->name = p ? nasm_strdup(p) : NULL;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003859 ctx->number = unique++;
3860 cstk = ctx;
3861 } else {
3862 /* %pop or %repl */
3863 if (!cstk) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003864 nasm_nonfatal("`%s': context stack is empty", dname);
3865 } else if (op == PP_POP) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003866 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003867 nasm_nonfatal("`%s' in wrong context: %s, "
H. Peter Anvin8b262472019-02-26 14:00:54 -08003868 "expected %s",
3869 dname, cstk->name ? cstk->name : "anonymous", p);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003870 else
3871 ctx_pop();
3872 } else {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003873 /* op == PP_REPL */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003874 nasm_free((char *)cstk->name);
3875 cstk->name = p ? nasm_strdup(p) : NULL;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003876 p = NULL;
3877 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003878 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003879 break;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07003880 case PP_FATAL:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003881 severity = ERR_FATAL;
3882 goto issue_error;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003883 case PP_ERROR:
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003884 severity = ERR_NONFATAL|ERR_PASS2;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003885 goto issue_error;
H. Peter Anvin7df04172008-06-10 18:27:38 -07003886 case PP_WARNING:
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -08003887 /*!
3888 *!user [on] %warning directives
3889 *! controls output of \c{%warning} directives (see \k{pperror}).
3890 */
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003891 severity = ERR_WARNING|WARN_USER|ERR_PASS2;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003892 goto issue_error;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07003893
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003894issue_error:
H. Peter Anvin7df04172008-06-10 18:27:38 -07003895 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003896 /* Only error out if this is the final pass */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003897 tline->next = expand_smacro(tline->next);
3898 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003899 tline = skip_white(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003900 t = tline ? tline->next : NULL;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003901 t = skip_white(t);
3902 if (tok_type(tline, TOK_STRING) && !t) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003903 /* The line contains only a quoted string */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003904 p = unquote_token(tline); /* Ignore NUL character truncation */
H. Peter Anvin130736c2016-02-17 20:27:41 -08003905 nasm_error(severity, "%s", p);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003906 } else {
3907 /* Not a quoted string, or more than a quoted string */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003908 q = detoken(tline, false);
3909 nasm_error(severity, "%s", q);
3910 nasm_free(q);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003911 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003912 break;
H. Peter Anvin7df04172008-06-10 18:27:38 -07003913 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003914
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00003915 CASE_PP_IF:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003916 if (istk->conds && !emitting(istk->conds->state))
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003917 j = COND_NEVER;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003918 else {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003919 j = if_condition(tline->next, op);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003920 tline->next = NULL; /* it got freed */
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003921 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003922 cond = nasm_malloc(sizeof(Cond));
3923 cond->next = istk->conds;
3924 cond->state = j;
3925 istk->conds = cond;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07003926 if(istk->mstk.mstk)
3927 istk->mstk.mstk->condcnt++;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003928 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003929
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00003930 CASE_PP_ELIF:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003931 if (!istk->conds)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003932 nasm_fatal("`%s': no matching `%%if'", dname);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003933 switch(istk->conds->state) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003934 case COND_IF_TRUE:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003935 istk->conds->state = COND_DONE;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003936 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003937
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003938 case COND_DONE:
3939 case COND_NEVER:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003940 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003941
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003942 case COND_ELSE_TRUE:
3943 case COND_ELSE_FALSE:
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003944 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003945 "`%%elif' after `%%else' ignored");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003946 istk->conds->state = COND_NEVER;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003947 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003948
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003949 case COND_IF_FALSE:
3950 /*
3951 * IMPORTANT: In the case of %if, we will already have
3952 * called expand_mmac_params(); however, if we're
3953 * processing an %elif we must have been in a
3954 * non-emitting mode, which would have inhibited
3955 * the normal invocation of expand_mmac_params().
3956 * Therefore, we have to do it explicitly here.
3957 */
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003958 j = if_condition(expand_mmac_params(tline->next), op);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003959 tline->next = NULL; /* it got freed */
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003960 istk->conds->state = j;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003961 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003962 }
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003963 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003964
H. Peter Anvine2c80182005-01-15 22:15:51 +00003965 case PP_ELSE:
3966 if (tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003967 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003968 "trailing garbage after `%%else' ignored");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003969 if (!istk->conds)
H. Peter Anvinc5136902018-06-15 18:20:17 -07003970 nasm_fatal("`%%else: no matching `%%if'");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003971 switch(istk->conds->state) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003972 case COND_IF_TRUE:
3973 case COND_DONE:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003974 istk->conds->state = COND_ELSE_FALSE;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003975 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003976
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003977 case COND_NEVER:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003978 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003979
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003980 case COND_IF_FALSE:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003981 istk->conds->state = COND_ELSE_TRUE;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003982 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003983
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003984 case COND_ELSE_TRUE:
3985 case COND_ELSE_FALSE:
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003986 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003987 "`%%else' after `%%else' ignored.");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003988 istk->conds->state = COND_NEVER;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003989 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003990 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003991 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003992
H. Peter Anvine2c80182005-01-15 22:15:51 +00003993 case PP_ENDIF:
3994 if (tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003995 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003996 "trailing garbage after `%%endif' ignored");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003997 if (!istk->conds)
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003998 nasm_fatal("`%%endif': no matching `%%if'");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003999 cond = istk->conds;
4000 istk->conds = cond->next;
4001 nasm_free(cond);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004002 if(istk->mstk.mstk)
4003 istk->mstk.mstk->condcnt--;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004004 break;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004005
H. Peter Anvin8b262472019-02-26 14:00:54 -08004006 case PP_RMACRO:
4007 case PP_MACRO:
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07004008 {
4009 MMacro *def;
4010
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004011 nasm_assert(!defining);
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07004012 nasm_new(def);
4013 def->casesense = casesense;
4014 def->dstk.mmac = defining;
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004015 if (op == PP_RMACRO)
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07004016 def->max_depth = nasm_limit[LIMIT_MACRO_LEVELS];
4017 if (!parse_mmacro_spec(tline, def, dname)) {
4018 nasm_free(def);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004019 goto done;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004020 }
H. Peter Anvina26433d2008-07-16 14:40:01 -07004021
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07004022 defining = def;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07004023 defining->where = istk->where;
H. Peter Anvin4def1a82016-05-09 13:59:44 -07004024
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004025 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
4026 while (mmac) {
4027 if (!strcmp(mmac->name, defining->name) &&
4028 (mmac->nparam_min <= defining->nparam_max
4029 || defining->plus)
4030 && (defining->nparam_min <= mmac->nparam_max
4031 || mmac->plus)) {
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08004032 nasm_warn(WARN_OTHER, "redefining multi-line macro `%s'",
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004033 defining->name);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004034 break;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004035 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004036 mmac = mmac->next;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004037 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004038 break;
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07004039 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004040
H. Peter Anvine2c80182005-01-15 22:15:51 +00004041 case PP_ENDM:
4042 case PP_ENDMACRO:
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004043 if (!(defining && defining->name)) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004044 nasm_nonfatal("`%s': not defining a macro", tok_text(tline));
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004045 goto done;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004046 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004047 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
4048 defining->next = *mmhead;
4049 *mmhead = defining;
4050 defining = NULL;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004051 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004052
H. Peter Anvin89cee572009-07-15 09:16:54 -04004053 case PP_EXITMACRO:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004054 /*
4055 * We must search along istk->expansion until we hit a
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004056 * macro-end marker for a macro with a name. Then we
4057 * bypass all lines between exitmacro and endmacro.
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004058 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004059 list_for_each(l, istk->expansion)
4060 if (l->finishes && l->finishes->name)
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004061 break;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004062
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004063 if (l) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004064 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004065 * Remove all conditional entries relative to this
4066 * macro invocation. (safe to do in this context)
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004067 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004068 for ( ; l->finishes->condcnt > 0; l->finishes->condcnt --) {
4069 cond = istk->conds;
4070 istk->conds = cond->next;
4071 nasm_free(cond);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004072 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004073 istk->expansion = l;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004074 } else {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004075 nasm_nonfatal("`%%exitmacro' not within `%%macro' block");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004076 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004077 break;
Keith Kanios852f1ee2009-07-12 00:19:55 -05004078
H. Peter Anvina26433d2008-07-16 14:40:01 -07004079 case PP_UNIMACRO:
H. Peter Anvin8b262472019-02-26 14:00:54 -08004080 casesense = false;
4081 /* fall through */
4082 case PP_UNMACRO:
H. Peter Anvina26433d2008-07-16 14:40:01 -07004083 {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004084 MMacro **mmac_p;
4085 MMacro spec;
H. Peter Anvina26433d2008-07-16 14:40:01 -07004086
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004087 nasm_zero(spec);
H. Peter Anvin8b262472019-02-26 14:00:54 -08004088 spec.casesense = casesense;
4089 if (!parse_mmacro_spec(tline, &spec, dname)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004090 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004091 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004092 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
4093 while (mmac_p && *mmac_p) {
4094 mmac = *mmac_p;
4095 if (mmac->casesense == spec.casesense &&
4096 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
4097 mmac->nparam_min == spec.nparam_min &&
4098 mmac->nparam_max == spec.nparam_max &&
4099 mmac->plus == spec.plus) {
4100 *mmac_p = mmac->next;
4101 free_mmacro(mmac);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004102 } else {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004103 mmac_p = &mmac->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004104 }
4105 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004106 free_tlist(spec.dlist);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004107 break;
H. Peter Anvina26433d2008-07-16 14:40:01 -07004108 }
4109
H. Peter Anvine2c80182005-01-15 22:15:51 +00004110 case PP_ROTATE:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004111 while (tok_white(tline->next))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004112 tline = tline->next;
H. Peter Anvin89cee572009-07-15 09:16:54 -04004113 if (!tline->next) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004114 free_tlist(origline);
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004115 nasm_nonfatal("`%%rotate' missing rotate count");
H. Peter Anvine2c80182005-01-15 22:15:51 +00004116 return DIRECTIVE_FOUND;
4117 }
4118 t = expand_smacro(tline->next);
4119 tline->next = NULL;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004120 pps.tptr = tline = t;
4121 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004122 tokval.t_type = TOKEN_INVALID;
4123 evalresult =
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004124 evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004125 free_tlist(tline);
4126 if (!evalresult)
4127 return DIRECTIVE_FOUND;
4128 if (tokval.t_type)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08004129 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00004130 if (!is_simple(evalresult)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004131 nasm_nonfatal("non-constant value given to `%%rotate'");
H. Peter Anvine2c80182005-01-15 22:15:51 +00004132 return DIRECTIVE_FOUND;
4133 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004134 mmac = istk->mstk.mmac;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004135 if (!mmac) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004136 nasm_nonfatal("`%%rotate' invoked outside a macro call");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004137 } else if (mmac->nparam == 0) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004138 nasm_nonfatal("`%%rotate' invoked within macro without parameters");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004139 } else {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004140 int rotate = mmac->rotate + reloc_value(evalresult);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004141
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004142 rotate %= (int)mmac->nparam;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004143 if (rotate < 0)
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004144 rotate += mmac->nparam;
4145
4146 mmac->rotate = rotate;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004147 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004148 break;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00004149
H. Peter Anvine2c80182005-01-15 22:15:51 +00004150 case PP_REP:
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004151 {
4152 MMacro *tmp_defining;
4153
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004154 nolist = false;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004155 tline = skip_white(tline->next);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004156 if (tok_type(tline, TOK_ID) && tline->len == 7 &&
4157 !nasm_memicmp(tline->text.a, ".nolist", 7)) {
H. Peter Anvin6686de22019-08-10 05:33:14 -07004158 nolist = !list_option('f') || istk->nolist;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004159 tline = skip_white(tline->next);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004160 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00004161
H. Peter Anvine2c80182005-01-15 22:15:51 +00004162 if (tline) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08004163 pps.tptr = expand_smacro(tline);
4164 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004165 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004166 /* XXX: really critical?! */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004167 evalresult =
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004168 evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004169 if (!evalresult)
4170 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004171 if (tokval.t_type)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08004172 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00004173 if (!is_simple(evalresult)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004174 nasm_nonfatal("non-constant value given to `%%rep'");
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004175 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004176 }
Cyrill Gorcunove091d6e2010-08-09 13:58:22 +04004177 count = reloc_value(evalresult);
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07004178 if (count > nasm_limit[LIMIT_REP]) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004179 nasm_nonfatal("`%%rep' count %"PRId64" exceeds limit (currently %"PRId64")",
4180 count, nasm_limit[LIMIT_REP]);
Cyrill Gorcunove091d6e2010-08-09 13:58:22 +04004181 count = 0;
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07004182 } else if (count < 0) {
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -08004183 /*!
4184 *!negative-rep [on] regative %rep count
4185 *! warns about negative counts given to the \c{%rep}
4186 *! preprocessor directive.
4187 */
H. Peter Anvin (Intel)80c4f232018-12-14 13:33:24 -08004188 nasm_warn(ERR_PASS2|WARN_NEGATIVE_REP,
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07004189 "negative `%%rep' count: %"PRId64, count);
4190 count = 0;
4191 } else {
Cyrill Gorcunove091d6e2010-08-09 13:58:22 +04004192 count++;
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07004193 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004194 } else {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004195 nasm_nonfatal("`%%rep' expects a repeat count");
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07004196 count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004197 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004198 tmp_defining = defining;
H. Peter Anvinab6f8312019-08-09 22:31:45 -07004199 nasm_new(defining);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004200 defining->nolist = nolist;
4201 defining->in_progress = count;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004202 defining->mstk = istk->mstk;
4203 defining->dstk.mstk = tmp_defining;
4204 defining->dstk.mmac = tmp_defining ? tmp_defining->dstk.mmac : NULL;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07004205 defining->where = istk->where;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004206 break;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004207 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004208
H. Peter Anvine2c80182005-01-15 22:15:51 +00004209 case PP_ENDREP:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004210 if (!defining || defining->name) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004211 nasm_nonfatal("`%%endrep': no matching `%%rep'");
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004212 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004213 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004214
H. Peter Anvine2c80182005-01-15 22:15:51 +00004215 /*
4216 * Now we have a "macro" defined - although it has no name
4217 * and we won't be entering it in the hash tables - we must
4218 * push a macro-end marker for it on to istk->expansion.
4219 * After that, it will take care of propagating itself (a
4220 * macro-end marker line for a macro which is really a %rep
4221 * block will cause the macro to be re-expanded, complete
4222 * with another macro-end marker to ensure the process
4223 * continues) until the whole expansion is forcibly removed
4224 * from istk->expansion by a %exitrep.
4225 */
H. Peter Anvin6686de22019-08-10 05:33:14 -07004226 nasm_new(l);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004227 l->next = istk->expansion;
4228 l->finishes = defining;
4229 l->first = NULL;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07004230 l->where = src_where();
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004231 istk->expansion = l;
4232
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004233 istk->mstk.mstk = defining;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004234
H. Peter Anvin0d4d4312019-08-07 00:46:27 -07004235 lfmt->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004236 defining = defining->dstk.mstk;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004237 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004238
H. Peter Anvine2c80182005-01-15 22:15:51 +00004239 case PP_EXITREP:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004240 /*
4241 * We must search along istk->expansion until we hit a
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004242 * macro-end marker for a macro with no name. Then we set
4243 * its `in_progress' flag to 0.
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004244 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004245 list_for_each(l, istk->expansion)
4246 if (l->finishes && !l->finishes->name)
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004247 break;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004248
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004249 if (l)
H. Peter Anvind983b622019-10-07 21:19:32 -07004250 l->finishes->in_progress = 0;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004251 else
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004252 nasm_nonfatal("`%%exitrep' not within `%%rep' block");
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004253 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004254
H. Peter Anvin8b262472019-02-26 14:00:54 -08004255 case PP_DEFINE:
4256 case PP_XDEFINE:
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004257 case PP_DEFALIAS:
H. Peter Anvin8b262472019-02-26 14:00:54 -08004258 {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004259 SMacro tmpl;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07004260 Token **lastp;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07004261 int nparam;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07004262
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004263 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004264 goto done;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004265
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004266 nasm_zero(tmpl);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07004267 lastp = &tline->next;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07004268 nparam = parse_smacro_template(&lastp, &tmpl);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07004269 tline = *lastp;
4270 *lastp = NULL;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004271
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004272 if (unlikely(op == PP_DEFALIAS)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004273 macro_start = tline;
4274 if (!is_macro_id(macro_start)) {
4275 nasm_nonfatal("`%s' expects a macro identifier to alias",
4276 dname);
4277 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004278 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004279 tt = macro_start->next;
4280 macro_start->next = NULL;
4281 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004282 tline = skip_white(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004283 if (tline && tline->type) {
4284 nasm_warn(WARN_OTHER,
4285 "trailing garbage after aliasing identifier ignored");
4286 }
4287 free_tlist(tt);
4288 tmpl.alias = true;
4289 } else {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004290 if (op == PP_XDEFINE) {
4291 /* Protect macro parameter tokens */
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07004292 if (nparam)
4293 mark_smac_params(tline, &tmpl, TOK_XDEF_PARAM);
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004294 tline = expand_smacro(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004295 }
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004296 /* NB: Does this still make sense? */
4297 macro_start = reverse_tokens(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004298 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004299
H. Peter Anvine2c80182005-01-15 22:15:51 +00004300 /*
4301 * Good. We now have a macro name, a parameter count, and a
4302 * token list (in reverse order) for an expansion. We ought
4303 * to be OK just to create an SMacro, store it, and let
4304 * free_tlist have the rest of the line (which we have
4305 * carefully re-terminated after chopping off the expansion
4306 * from the end).
4307 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004308 define_smacro(mname, casesense, macro_start, &tmpl);
4309 break;
4310 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004311
H. Peter Anvine2c80182005-01-15 22:15:51 +00004312 case PP_UNDEF:
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004313 case PP_UNDEFALIAS:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004314 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004315 goto done;
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004316 if (tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08004317 nasm_warn(WARN_OTHER, "trailing garbage after macro name ignored");
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004318
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004319 undef_smacro(mname, op == PP_UNDEFALIAS);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004320 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004321
H. Peter Anvin8b262472019-02-26 14:00:54 -08004322 case PP_DEFSTR:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004323 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004324 goto done;
H. Peter Anvin9e200162008-06-04 17:23:14 -07004325
H. Peter Anvin9e200162008-06-04 17:23:14 -07004326 last = tline;
4327 tline = expand_smacro(tline->next);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004328 last->next = NULL;
H. Peter Anvin9e200162008-06-04 17:23:14 -07004329
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004330 tline = zap_white(tline);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004331 q = detoken(tline, false);
4332 macro_start = make_tok_qstr(NULL, q);
4333 nasm_free(q);
H. Peter Anvin9e200162008-06-04 17:23:14 -07004334
4335 /*
4336 * We now have a macro name, an implicit parameter count of
4337 * zero, and a string token to use as an expansion. Create
4338 * and store an SMacro.
4339 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004340 define_smacro(mname, casesense, macro_start, NULL);
4341 break;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004342
H. Peter Anvin8b262472019-02-26 14:00:54 -08004343 case PP_DEFTOK:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004344 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004345 goto done;
4346
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004347 last = tline;
4348 tline = expand_smacro(tline->next);
4349 last->next = NULL;
4350
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004351 t = skip_white(tline);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004352 /* t should now point to the string */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004353 if (!tok_type(t, TOK_STRING)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004354 nasm_nonfatal("`%s' requires string as second parameter", dname);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004355 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004356 goto done;
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004357 }
4358
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04004359 /*
4360 * Convert the string to a token stream. Note that smacros
4361 * are stored with the token stream reversed, so we have to
4362 * reverse the output of tokenize().
4363 */
H. Peter Anvin8571f062019-09-23 16:40:03 -07004364 macro_start = reverse_tokens(tokenize(unquote_token_cstr(t)));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004365
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004366 /*
4367 * We now have a macro name, an implicit parameter count of
4368 * zero, and a numeric token to use as an expansion. Create
4369 * and store an SMacro.
4370 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004371 define_smacro(mname, casesense, macro_start, NULL);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004372 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004373 break;
H. Peter Anvin9e200162008-06-04 17:23:14 -07004374
H. Peter Anvin418ca702008-05-30 10:42:30 -07004375 case PP_PATHSEARCH:
4376 {
H. Peter Anvinccad6f92016-10-04 00:34:35 -07004377 const char *found_path;
H. Peter Anvin418ca702008-05-30 10:42:30 -07004378
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004379 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004380 goto done;
4381
H. Peter Anvin418ca702008-05-30 10:42:30 -07004382 last = tline;
4383 tline = expand_smacro(tline->next);
4384 last->next = NULL;
4385
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004386 t = skip_white(tline);
H. Peter Anvin418ca702008-05-30 10:42:30 -07004387 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004388 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004389 nasm_nonfatal("`%s' expects a file name", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004390 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004391 goto done;
H. Peter Anvin418ca702008-05-30 10:42:30 -07004392 }
4393 if (t->next)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004394 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004395
4396 p = unquote_token_cstr(t);
H. Peter Anvin418ca702008-05-30 10:42:30 -07004397
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07004398 inc_fopen(p, NULL, &found_path, INC_PROBE, NF_BINARY);
H. Peter Anvinccad6f92016-10-04 00:34:35 -07004399 if (!found_path)
4400 found_path = p;
H. Peter Anvin8571f062019-09-23 16:40:03 -07004401 macro_start = make_tok_qstr(NULL, found_path);
H. Peter Anvin418ca702008-05-30 10:42:30 -07004402
4403 /*
4404 * We now have a macro name, an implicit parameter count of
4405 * zero, and a string token to use as an expansion. Create
4406 * and store an SMacro.
4407 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004408 define_smacro(mname, casesense, macro_start, NULL);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004409 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004410 break;
H. Peter Anvin418ca702008-05-30 10:42:30 -07004411 }
4412
H. Peter Anvine2c80182005-01-15 22:15:51 +00004413 case PP_STRLEN:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004414 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004415 goto done;
4416
H. Peter Anvine2c80182005-01-15 22:15:51 +00004417 last = tline;
4418 tline = expand_smacro(tline->next);
4419 last->next = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004420
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004421 t = skip_white(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004422 /* t should now point to the string */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004423 if (!tok_type(t, TOK_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004424 nasm_nonfatal("`%s' requires string as second parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004425 free_tlist(tline);
4426 free_tlist(origline);
4427 return DIRECTIVE_FOUND;
4428 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004429
H. Peter Anvin8571f062019-09-23 16:40:03 -07004430 unquote_token(t);
4431 macro_start = make_tok_num(NULL, t->len);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004432
H. Peter Anvine2c80182005-01-15 22:15:51 +00004433 /*
4434 * We now have a macro name, an implicit parameter count of
4435 * zero, and a numeric token to use as an expansion. Create
4436 * and store an SMacro.
4437 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004438 define_smacro(mname, casesense, macro_start, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004439 free_tlist(tline);
4440 free_tlist(origline);
4441 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004442
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004443 case PP_STRCAT:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004444 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004445 goto done;
4446
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004447 last = tline;
4448 tline = expand_smacro(tline->next);
4449 last->next = NULL;
4450
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004451 len = 0;
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04004452 list_for_each(t, tline) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004453 switch (t->type) {
4454 case TOK_WHITESPACE:
4455 break;
4456 case TOK_STRING:
H. Peter Anvin8571f062019-09-23 16:40:03 -07004457 unquote_token(t);
4458 len += t->len;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004459 break;
4460 case TOK_OTHER:
H. Peter Anvin8571f062019-09-23 16:40:03 -07004461 if (tok_is(t, ',')) /* permit comma separators */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004462 break;
4463 /* else fall through */
4464 default:
H. Peter Anvin8571f062019-09-23 16:40:03 -07004465 nasm_nonfatal("non-string passed to `%s': %s", dname,
4466 tok_text(t));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004467 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004468 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004469 }
4470 }
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004471
H. Peter Anvin (Intel)f770ce82019-10-17 18:22:43 -07004472 q = qbuf = nasm_malloc(len+1);
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04004473 list_for_each(t, tline) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004474 if (t->type == TOK_INTERNAL_STRING)
4475 q = mempcpy(q, tok_text(t), t->len);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004476 }
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07004477 *q = '\0';
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004478
4479 /*
4480 * We now have a macro name, an implicit parameter count of
4481 * zero, and a numeric token to use as an expansion. Create
4482 * and store an SMacro.
4483 */
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07004484 macro_start = make_tok_qstr_len(NULL, qbuf, len);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004485 nasm_free(qbuf);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004486 define_smacro(mname, casesense, macro_start, NULL);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004487 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004488 break;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004489
H. Peter Anvine2c80182005-01-15 22:15:51 +00004490 case PP_SUBSTR:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004491 {
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004492 int64_t start, count;
H. Peter Anvin8571f062019-09-23 16:40:03 -07004493 const char *txt;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004494 size_t len;
H. Peter Anvind2456592008-06-19 15:04:18 -07004495
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004496 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004497 goto done;
4498
H. Peter Anvine2c80182005-01-15 22:15:51 +00004499 last = tline;
4500 tline = expand_smacro(tline->next);
4501 last->next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004502
Cyrill Gorcunov35519d62010-09-06 23:49:52 +04004503 if (tline) /* skip expanded id */
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004504 t = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004505
4506 t = skip_white(t);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004507
H. Peter Anvine2c80182005-01-15 22:15:51 +00004508 /* t should now point to the string */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004509 if (!tok_type(t, TOK_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004510 nasm_nonfatal("`%s' requires string as second parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004511 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004512 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004513 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004514
H. Peter Anvin8b262472019-02-26 14:00:54 -08004515 pps.tptr = t->next;
4516 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004517 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004518 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004519 if (!evalresult) {
4520 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004521 goto done;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004522 } else if (!is_simple(evalresult)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004523 nasm_nonfatal("non-constant value given to `%s'", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004524 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004525 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004526 }
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004527 start = evalresult->value - 1;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004528
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004529 pps.tptr = skip_white(pps.tptr);
H. Peter Anvin8b262472019-02-26 14:00:54 -08004530 if (!pps.tptr) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004531 count = 1; /* Backwards compatibility: one character */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004532 } else {
4533 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004534 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004535 if (!evalresult) {
4536 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004537 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004538 } else if (!is_simple(evalresult)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004539 nasm_nonfatal("non-constant value given to `%s'", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004540 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004541 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004542 }
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004543 count = evalresult->value;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004544 }
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004545
H. Peter Anvin8571f062019-09-23 16:40:03 -07004546 unquote_token(t);
4547 len = t->len;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004548
Cyrill Gorcunovcff031e2010-09-07 20:31:11 +04004549 /* make start and count being in range */
4550 if (start < 0)
4551 start = 0;
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004552 if (count < 0)
4553 count = len + count + 1 - start;
4554 if (start + count > (int64_t)len)
Cyrill Gorcunovcff031e2010-09-07 20:31:11 +04004555 count = len - start;
4556 if (!len || count < 0 || start >=(int64_t)len)
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004557 start = -1, count = 0; /* empty string */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004558
H. Peter Anvin8571f062019-09-23 16:40:03 -07004559 txt = (start < 0) ? "" : tok_text(t) + start;
4560 len = count;
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07004561 macro_start = make_tok_qstr_len(NULL, txt, len);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004562
H. Peter Anvine2c80182005-01-15 22:15:51 +00004563 /*
4564 * We now have a macro name, an implicit parameter count of
4565 * zero, and a numeric token to use as an expansion. Create
4566 * and store an SMacro.
4567 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004568 define_smacro(mname, casesense, macro_start, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004569 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004570 break;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004571 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004572
H. Peter Anvin8b262472019-02-26 14:00:54 -08004573 case PP_ASSIGN:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004574 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004575 goto done;
4576
H. Peter Anvine2c80182005-01-15 22:15:51 +00004577 last = tline;
4578 tline = expand_smacro(tline->next);
4579 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004580
H. Peter Anvin8b262472019-02-26 14:00:54 -08004581 pps.tptr = tline;
4582 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004583 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004584 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004585 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004586 if (!evalresult)
4587 goto done;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004588
H. Peter Anvine2c80182005-01-15 22:15:51 +00004589 if (tokval.t_type)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08004590 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
H. Peter Anvin734b1882002-04-30 21:01:08 +00004591
H. Peter Anvine2c80182005-01-15 22:15:51 +00004592 if (!is_simple(evalresult)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004593 nasm_nonfatal("non-constant value given to `%s'", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004594 free_tlist(origline);
4595 return DIRECTIVE_FOUND;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004596 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004597
H. Peter Anvin8571f062019-09-23 16:40:03 -07004598 macro_start = make_tok_num(NULL, reloc_value(evalresult));
H. Peter Anvin734b1882002-04-30 21:01:08 +00004599
H. Peter Anvine2c80182005-01-15 22:15:51 +00004600 /*
4601 * We now have a macro name, an implicit parameter count of
4602 * zero, and a numeric token to use as an expansion. Create
4603 * and store an SMacro.
4604 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004605 define_smacro(mname, casesense, macro_start, NULL);
4606 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004607
H. Peter Anvind2354082019-08-27 16:38:48 -07004608 case PP_ALIASES:
4609 tline = tline->next;
4610 tline = expand_smacro(tline);
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07004611 ppopt.noaliases = !pp_get_boolean_option(tline, !ppopt.noaliases);
H. Peter Anvind2354082019-08-27 16:38:48 -07004612 break;
4613
H. Peter Anvine2c80182005-01-15 22:15:51 +00004614 case PP_LINE:
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07004615 nasm_panic("`%s' directive not preprocessed early", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004616 break;
4617 }
4618
4619done:
H. Peter Anvine2c80182005-01-15 22:15:51 +00004620 free_tlist(origline);
4621 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004622}
4623
4624/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00004625 * Ensure that a macro parameter contains a condition code and
4626 * nothing else. Return the condition code index if so, or -1
4627 * otherwise.
4628 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004629static int find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004630{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004631 Token *tt;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004632
H. Peter Anvin25a99342007-09-22 17:45:45 -07004633 if (!t)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004634 return -1; /* Probably a %+ without a space */
H. Peter Anvin25a99342007-09-22 17:45:45 -07004635
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004636 t = skip_white(t);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004637 if (!tok_type(t, TOK_ID))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004638 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004639 tt = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004640 tt = skip_white(tt);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004641 if (tok_isnt(tt, ','))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004642 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004643
H. Peter Anvin8571f062019-09-23 16:40:03 -07004644 return bsii(tok_text(t), (const char **)conditions,
4645 ARRAY_SIZE(conditions));
H. Peter Anvin76690a12002-04-30 20:52:49 +00004646}
4647
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004648static inline bool pp_concat_match(const Token *t, unsigned int mask)
4649{
4650 return t && (PP_CONCAT_MASK(t->type) & mask);
4651}
4652
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004653/*
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07004654 * This routines walks over tokens strem and handles tokens
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004655 * pasting, if @handle_explicit passed then explicit pasting
4656 * term is handled, otherwise -- implicit pastings only.
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07004657 * The @m array can contain a series of token types which are
4658 * executed as separate passes.
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004659 */
Cyrill Gorcunov575d4282010-10-06 00:25:55 +04004660static bool paste_tokens(Token **head, const struct tokseq_match *m,
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004661 size_t mnum, bool handle_explicit)
H. Peter Anvind784a082009-04-20 14:01:18 -07004662{
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004663 Token *tok, *t, *next, **prev_next, **prev_nonspace;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004664 bool pasted = false;
4665 char *buf, *p;
4666 size_t len, i;
H. Peter Anvind784a082009-04-20 14:01:18 -07004667
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004668 /*
4669 * The last token before pasting. We need it
4670 * to be able to connect new handled tokens.
4671 * In other words if there were a tokens stream
4672 *
4673 * A -> B -> C -> D
4674 *
4675 * and we've joined tokens B and C, the resulting
4676 * stream should be
4677 *
4678 * A -> BC -> D
4679 */
4680 tok = *head;
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004681 prev_next = prev_nonspace = head;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004682
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004683 if (tok_white(tok) || tok_type(tok, TOK_PASTE))
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004684 prev_nonspace = NULL;
4685
4686 while (tok && (next = tok->next)) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004687 bool did_paste = false;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004688
4689 switch (tok->type) {
H. Peter Anvind784a082009-04-20 14:01:18 -07004690 case TOK_WHITESPACE:
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004691 /* Zap redundant whitespaces */
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004692 tok->next = next = zap_white(next);
H. Peter Anvind784a082009-04-20 14:01:18 -07004693 break;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004694
4695 case TOK_PASTE:
4696 /* Explicit pasting */
4697 if (!handle_explicit)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004698 break;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004699
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004700 /* Left pasting token is start of line */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004701 if (!prev_nonspace) {
4702 nasm_nonfatal("No lvalue found on pasting");
4703 tok = delete_Token(tok);
4704 break;
4705 }
4706
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004707 did_paste = true;
4708
4709 prev_next = prev_nonspace;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004710 t = *prev_nonspace;
4711
4712 /* Delete leading whitespace */
4713 next = zap_white(t->next);
4714
4715 /* Delete the %+ token itself */
4716 nasm_assert(next == tok);
4717 next = delete_Token(next);
4718
4719 /* Delete trailing whitespace */
4720 next = zap_white(next);
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004721
Cyrill Gorcunov8b5c9fb2013-02-04 01:24:54 +04004722 /*
4723 * No ending token, this might happen in two
4724 * cases
4725 *
4726 * 1) There indeed no right token at all
4727 * 2) There is a bare "%define ID" statement,
4728 * and @ID does expand to whitespace.
4729 *
4730 * So technically we need to do a grammar analysis
4731 * in another stage of parsing, but for now lets don't
4732 * change the behaviour people used to. Simply allow
4733 * whitespace after paste token.
4734 */
4735 if (!next) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004736 *prev_nonspace = tok = NULL; /* End of line */
Cyrill Gorcunov8b5c9fb2013-02-04 01:24:54 +04004737 break;
4738 }
4739
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004740 p = buf = nasm_malloc(t->len + next->len + 1);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004741 p = mempcpy(p, tok_text(t), t->len);
4742 p = mempcpy(p, tok_text(next), next->len);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004743 *p = '\0';
4744 delete_Token(t);
4745 t = tokenize(buf);
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004746 nasm_free(buf);
4747
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004748 if (unlikely(!t)) {
4749 /*
4750 * No output at all? Replace with a single whitespace.
4751 * This should never happen.
4752 */
4753 t = new_White(NULL);
4754 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004755
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004756 *prev_nonspace = tok = t;
4757 while (t->next)
4758 t = t->next; /* Find the last token produced */
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004759
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004760 /* Delete the second token and attach to the end of the list */
4761 t->next = delete_Token(next);
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004762
4763 /* We want to restart from the head of the pasted token */
4764 next = tok;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004765 break;
4766
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004767 default:
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004768 /* implicit pasting */
Cyrill Gorcunov575d4282010-10-06 00:25:55 +04004769 for (i = 0; i < mnum; i++) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004770 if (pp_concat_match(tok, m[i].mask_head))
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004771 break;
Cyrill Gorcunov575d4282010-10-06 00:25:55 +04004772 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004773
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004774 if (i >= mnum)
4775 break;
4776
4777 len = tok->len;
4778 while (pp_concat_match(next, m[i].mask_tail)) {
4779 len += next->len;
4780 next = next->next;
4781 }
4782
4783 /* No match or no text to process */
4784 if (len == tok->len)
4785 break;
4786
4787 p = buf = nasm_malloc(len + 1);
4788 while (tok != next) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004789 p = mempcpy(p, tok_text(tok), tok->len);
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004790 tok = delete_Token(tok);
4791 }
4792 *p = '\0';
4793 *prev_next = tok = t = tokenize(buf);
4794 nasm_free(buf);
4795
4796 /*
4797 * Connect pasted into original stream,
4798 * ie A -> new-tokens -> B
4799 */
4800 while (t->next)
4801 t = t->next;
4802 t->next = next;
4803 prev_next = prev_nonspace = &t->next;
4804 did_paste = true;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004805 break;
H. Peter Anvind784a082009-04-20 14:01:18 -07004806 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004807
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004808 if (did_paste) {
4809 pasted = true;
4810 } else {
4811 prev_next = &tok->next;
4812 if (next && next->type != TOK_WHITESPACE && next->type != TOK_PASTE)
4813 prev_nonspace = prev_next;
4814 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004815
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004816 tok = next;
H. Peter Anvind784a082009-04-20 14:01:18 -07004817 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004818
4819 return pasted;
H. Peter Anvind784a082009-04-20 14:01:18 -07004820}
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004821
4822/*
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004823 * Computes the proper rotation of mmacro parameters
4824 */
4825static int mmac_rotate(const MMacro *mac, unsigned int n)
4826{
4827 if (--n < mac->nparam)
4828 n = (n + mac->rotate) % mac->nparam;
4829
4830 return n+1;
4831}
4832
4833/*
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004834 * expands to a list of tokens from %{x:y}
4835 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004836static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004837{
4838 Token *t = tline, **tt, *tm, *head;
4839 char *pos;
4840 int fst, lst, j, i;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004841
H. Peter Anvin8571f062019-09-23 16:40:03 -07004842 pos = strchr(tok_text(tline), ':');
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004843 nasm_assert(pos);
4844
4845 lst = atoi(pos + 1);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004846 fst = atoi(tok_text(tline) + 1);
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004847
4848 /*
4849 * only macros params are accounted so
4850 * if someone passes %0 -- we reject such
4851 * value(s)
4852 */
4853 if (lst == 0 || fst == 0)
4854 goto err;
4855
4856 /* the values should be sane */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004857 if ((fst > (int)mac->nparam || fst < (-(int)mac->nparam)) ||
4858 (lst > (int)mac->nparam || lst < (-(int)mac->nparam)))
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004859 goto err;
4860
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004861 fst = fst < 0 ? fst + (int)mac->nparam + 1: fst;
4862 lst = lst < 0 ? lst + (int)mac->nparam + 1: lst;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004863
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004864 /* count from zero */
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004865 fst--, lst--;
4866
4867 /*
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004868 * It will be at least one token. Note we
4869 * need to scan params until separator, otherwise
4870 * only first token will be passed.
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004871 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004872 j = (fst + mac->rotate) % mac->nparam;
4873 tm = mac->params[j+1];
Cyrill Gorcunov67f2ca22018-10-13 19:41:01 +03004874 if (!tm)
4875 goto err;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07004876 head = dup_Token(NULL, tm);
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004877 tt = &head->next, tm = tm->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004878 while (tok_isnt(tm, ',')) {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07004879 t = dup_Token(NULL, tm);
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004880 *tt = t, tt = &t->next, tm = tm->next;
4881 }
4882
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004883 if (fst < lst) {
4884 for (i = fst + 1; i <= lst; i++) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004885 t = make_tok_char(NULL, ',');
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004886 *tt = t, tt = &t->next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004887 j = (i + mac->rotate) % mac->nparam;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004888 tm = mac->params[j+1];
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004889 while (tok_isnt(tm, ',')) {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07004890 t = dup_Token(NULL, tm);
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004891 *tt = t, tt = &t->next, tm = tm->next;
4892 }
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004893 }
4894 } else {
4895 for (i = fst - 1; i >= lst; i--) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004896 t = make_tok_char(NULL, ',');
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004897 *tt = t, tt = &t->next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004898 j = (i + mac->rotate) % mac->nparam;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004899 tm = mac->params[j+1];
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004900 while (!tok_isnt(tm, ',')) {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07004901 t = dup_Token(NULL, tm);
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004902 *tt = t, tt = &t->next, tm = tm->next;
4903 }
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004904 }
4905 }
4906
4907 *last = tt;
4908 return head;
4909
4910err:
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004911 nasm_nonfatal("`%%{%s}': macro parameters out of range",
H. Peter Anvin8571f062019-09-23 16:40:03 -07004912 tok_text(tline) + 1);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004913 return NULL;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004914}
4915
H. Peter Anvin76690a12002-04-30 20:52:49 +00004916/*
4917 * Expand MMacro-local things: parameter references (%0, %n, %+n,
H. Peter Anvin67c63722008-10-26 23:49:00 -07004918 * %-n) and MMacro-local identifiers (%%foo) as well as
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004919 * macro indirection (%[...]) and range (%{..:..}).
H. Peter Anvin76690a12002-04-30 20:52:49 +00004920 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004921static Token *expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004922{
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004923 Token **tail, *thead;
H. Peter Anvin6125b622009-04-08 14:02:25 -07004924 bool changed = false;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004925 MMacro *mac = istk->mstk.mmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004926
4927 tail = &thead;
4928 thead = NULL;
4929
H. Peter Anvine2c80182005-01-15 22:15:51 +00004930 while (tline) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004931 bool change;
H. Peter Anvin (Intel)a762cd42020-06-01 11:49:08 -07004932 bool err_not_mac = false;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004933 Token *t = tline;
H. Peter Anvin8571f062019-09-23 16:40:03 -07004934 const char *text = tok_text(t);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004935 int type = t->type;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004936
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004937 tline = tline->next;
4938 t->next = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004939
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004940 switch (type) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004941 case TOK_LOCAL_SYMBOL:
H. Peter Anvin (Intel)a762cd42020-06-01 11:49:08 -07004942 change = true;
4943
4944 if (!mac) {
4945 err_not_mac = true;
4946 break;
4947 }
4948
H. Peter Anvin8571f062019-09-23 16:40:03 -07004949 type = TOK_ID;
4950 text = nasm_asprintf("..@%"PRIu64".%s", mac->unique, text+2);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004951 break;
4952 case TOK_MMACRO_PARAM:
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004953 {
4954 Token *tt = NULL;
4955
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004956 change = true;
4957
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004958 if (!mac) {
H. Peter Anvin (Intel)a762cd42020-06-01 11:49:08 -07004959 err_not_mac = true;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004960 break;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004961 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004962
4963 if (strchr(text, ':')) {
4964 /*
4965 * seems we have a parameters range here
4966 */
4967 Token *head, **last;
4968 head = expand_mmac_params_range(mac, t, &last);
4969 if (head) {
4970 *tail = head;
4971 *last = tline;
4972 text = NULL;
4973 }
4974 break;
4975 }
4976
4977 switch (text[1]) {
4978 /*
4979 * We have to make a substitution of one of the
4980 * forms %1, %-1, %+1, %%foo, %0, %00.
4981 */
4982 case '0':
4983 if (!text[2]) {
4984 type = TOK_NUMBER;
4985 text = nasm_asprintf("%d", mac->nparam);
4986 break;
4987 }
4988 if (text[2] != '0' || text[3])
4989 goto invalid;
4990 /* a possible captured label == mac->params[0] */
4991 /* fall through */
4992 default:
4993 {
4994 unsigned long n;
4995 char *ep;
4996
4997 n = strtoul(text + 1, &ep, 10);
4998 if (unlikely(*ep))
4999 goto invalid;
5000
5001 if (n <= mac->nparam) {
5002 n = mmac_rotate(mac, n);
5003 dup_tlistn(mac->params[n], mac->paramlen[n], &tail);
5004 }
5005 text = NULL;
5006 break;
5007 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005008 case '-':
5009 case '+':
5010 {
5011 int cc;
5012 unsigned long n;
5013 char *ep;
5014
H. Peter Anvin8571f062019-09-23 16:40:03 -07005015 n = strtoul(tok_text(t) + 2, &ep, 10);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005016 if (unlikely(*ep))
5017 goto invalid;
5018
Chang S. Bae057b8322020-04-18 23:11:21 +00005019 if (n && n <= mac->nparam) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005020 n = mmac_rotate(mac, n);
5021 tt = mac->params[n];
5022 }
5023 cc = find_cc(tt);
5024 if (cc == -1) {
5025 nasm_nonfatal("macro parameter `%s' is not a condition code",
H. Peter Anvin8571f062019-09-23 16:40:03 -07005026 tok_text(t));
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005027 text = NULL;
5028 break;
5029 }
5030
5031 type = TOK_ID;
5032 if (text[1] == '-') {
5033 int ncc = inverse_ccs[cc];
5034 if (unlikely(ncc == -1)) {
5035 nasm_nonfatal("condition code `%s' is not invertible",
5036 conditions[cc]);
5037 break;
5038 }
5039 cc = ncc;
5040 }
5041 text = nasm_strdup(conditions[cc]);
5042 break;
5043 }
5044
5045 invalid:
5046 nasm_nonfatal("invalid macro parameter: `%s'", text);
5047 text = NULL;
5048 break;
5049 }
5050 break;
5051 }
5052
5053 case TOK_PREPROC_Q:
5054 if (mac) {
5055 type = TOK_ID;
5056 text = nasm_strdup(mac->iname);
5057 change = true;
H. Peter Anvin (Intel)68075f82019-08-20 12:28:05 -07005058 } else {
5059 change = false;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005060 }
5061 break;
5062
5063 case TOK_PREPROC_QQ:
5064 if (mac) {
5065 type = TOK_ID;
5066 text = nasm_strdup(mac->name);
5067 change = true;
H. Peter Anvin (Intel)68075f82019-08-20 12:28:05 -07005068 } else {
5069 change = false;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005070 }
5071 break;
5072
5073 case TOK_INDIRECT:
5074 {
5075 Token *tt;
5076
H. Peter Anvin8571f062019-09-23 16:40:03 -07005077 tt = tokenize(tok_text(t));
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005078 tt = expand_mmac_params(tt);
5079 tt = expand_smacro(tt);
5080 /* Why dup_tlist() here? We should own tt... */
5081 dup_tlist(tt, &tail);
5082 text = NULL;
5083 change = true;
5084 break;
5085 }
5086
5087 default:
5088 change = false;
5089 break;
5090 }
5091
H. Peter Anvin (Intel)a762cd42020-06-01 11:49:08 -07005092 if (err_not_mac) {
5093 nasm_nonfatal("`%s': not in a macro call", text);
5094 text = NULL;
5095 change = true;
5096 }
5097
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005098 if (change) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00005099 if (!text) {
5100 delete_Token(t);
5101 } else {
5102 *tail = t;
5103 tail = &t->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07005104 set_text(t, text, tok_strlen(text));
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005105 t->type = type;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005106 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03005107 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005108 } else {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005109 *tail = t;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005110 tail = &t->next;
5111 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00005112 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005113
H. Peter Anvineba20a72002-04-30 20:53:55 +00005114 *tail = NULL;
H. Peter Anvin67c63722008-10-26 23:49:00 -07005115
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04005116 if (changed) {
5117 const struct tokseq_match t[] = {
5118 {
5119 PP_CONCAT_MASK(TOK_ID) |
5120 PP_CONCAT_MASK(TOK_FLOAT), /* head */
5121 PP_CONCAT_MASK(TOK_ID) |
5122 PP_CONCAT_MASK(TOK_NUMBER) |
5123 PP_CONCAT_MASK(TOK_FLOAT) |
5124 PP_CONCAT_MASK(TOK_OTHER) /* tail */
5125 },
5126 {
5127 PP_CONCAT_MASK(TOK_NUMBER), /* head */
5128 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
5129 }
5130 };
5131 paste_tokens(&thead, t, ARRAY_SIZE(t), false);
5132 }
H. Peter Anvin6125b622009-04-08 14:02:25 -07005133
H. Peter Anvin76690a12002-04-30 20:52:49 +00005134 return thead;
5135}
5136
H. Peter Anvin322bee02019-08-10 01:38:06 -07005137static Token *expand_smacro_noreset(Token * tline);
H. Peter Anvin322bee02019-08-10 01:38:06 -07005138
H. Peter Anvin76690a12002-04-30 20:52:49 +00005139/*
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005140 * Expand *one* single-line macro instance. If the first token is not
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005141 * a macro at all, it is simply copied to the output and the pointer
5142 * advanced. tpp should be a pointer to a pointer (usually the next
5143 * pointer of the previous token) to the first token. **tpp is updated
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005144 * to point to the first token of the expansion, and *tpp updated to
5145 * point to the next pointer of the last token of the expansion.
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005146 *
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005147 * If the expansion is empty, *tpp will be unchanged but **tpp will
5148 * be advanced past the macro call.
5149 *
H. Peter Anvin322bee02019-08-10 01:38:06 -07005150 * Return the macro expanded, or NULL if no expansion took place.
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005151 */
H. Peter Anvin322bee02019-08-10 01:38:06 -07005152static SMacro *expand_one_smacro(Token ***tpp)
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005153{
5154 Token **params = NULL;
5155 const char *mname;
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005156 Token *mstart = **tpp;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005157 Token *tline = mstart;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005158 SMacro *head, *m;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005159 int i;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005160 Token *t, *tup, *tafter;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005161 int nparam = 0;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005162 bool cond_comma;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005163
5164 if (!tline)
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005165 return false; /* Empty line, nothing to do */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005166
H. Peter Anvin8571f062019-09-23 16:40:03 -07005167 mname = tok_text(mstart);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005168
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07005169 smacro_deadman.total--;
H. Peter Anvin322bee02019-08-10 01:38:06 -07005170 smacro_deadman.levels--;
5171
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07005172 if (unlikely(smacro_deadman.total < 0 || smacro_deadman.levels < 0)) {
H. Peter Anvin322bee02019-08-10 01:38:06 -07005173 if (unlikely(!smacro_deadman.triggered)) {
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005174 nasm_nonfatal("interminable macro recursion");
H. Peter Anvin322bee02019-08-10 01:38:06 -07005175 smacro_deadman.triggered = true;
5176 }
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005177 goto not_a_macro;
H. Peter Anvin8571f062019-09-23 16:40:03 -07005178 } else if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID) {
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005179 head = (SMacro *)hash_findix(&smacros, mname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07005180 } else if (tline->type == TOK_LOCAL_MACRO) {
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005181 Context *ctx = get_ctx(mname, &mname);
5182 head = ctx ? (SMacro *)hash_findix(&ctx->localmac, mname) : NULL;
5183 } else {
5184 goto not_a_macro;
5185 }
5186
5187 /*
5188 * We've hit an identifier of some sort. First check whether the
5189 * identifier is a single-line macro at all, then think about
5190 * checking for parameters if necessary.
5191 */
5192 list_for_each(m, head) {
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005193 if (unlikely(m->alias && ppopt.noaliases))
H. Peter Anvind2354082019-08-27 16:38:48 -07005194 continue;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005195 if (!mstrcmp(m->name, mname, m->casesense))
5196 break;
5197 }
5198
5199 if (!m) {
5200 goto not_a_macro;
5201 }
5202
5203 /* Parse parameters, if applicable */
5204
5205 params = NULL;
5206 nparam = 0;
5207
5208 if (m->nparam == 0) {
5209 /*
5210 * Simple case: the macro is parameterless.
5211 * Nothing to parse; the expansion code will
5212 * drop the macro name token.
5213 */
5214 } else {
5215 /*
5216 * Complicated case: at least one macro with this name
5217 * exists and takes parameters. We must find the
5218 * parameters in the call, count them, find the SMacro
5219 * that corresponds to that form of the macro call, and
5220 * substitute for the parameters when we expand. What a
5221 * pain.
5222 */
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005223 Token *t;
5224 int paren, brackets;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005225
5226 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005227 tline = skip_white(tline);
5228 if (!tok_is(tline, '(')) {
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005229 /*
5230 * This macro wasn't called with parameters: ignore
5231 * the call. (Behaviour borrowed from gnu cpp.)
5232 */
5233 goto not_a_macro;
5234 }
5235
5236 paren = 1;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005237 nparam = 1;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005238 brackets = 0;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005239 t = tline; /* tline points to leading ( */
5240
5241 while (paren) {
5242 t = t->next;
5243
5244 if (!t) {
5245 nasm_nonfatal("macro call expects terminating `)'");
5246 goto not_a_macro;
5247 }
5248
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005249 if (t->type != TOK_OTHER || t->len != 1)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005250 continue;
5251
H. Peter Anvin8571f062019-09-23 16:40:03 -07005252 switch (t->text.a[0]) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005253 case ',':
H. Peter Anvinbd00f252020-06-04 21:05:01 -07005254 if (!brackets && paren == 1)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005255 nparam++;
5256 break;
5257
5258 case '{':
5259 brackets++;
5260 break;
5261
5262 case '}':
5263 if (brackets > 0)
5264 brackets--;
5265 break;
5266
5267 case '(':
5268 if (!brackets)
5269 paren++;
5270 break;
5271
5272 case ')':
5273 if (!brackets)
5274 paren--;
5275 break;
5276
5277 default:
5278 break; /* Normal token */
5279 }
5280 }
5281
5282 /*
5283 * Look for a macro matching in both name and parameter count.
5284 * We already know any matches cannot be anywhere before the
5285 * current position of "m", so there is no reason to
5286 * backtrack.
5287 */
5288 while (1) {
5289 if (!m) {
5290 /*!
5291 *!macro-params-single [on] single-line macro calls with wrong parameter count
5292 *! warns about \i{single-line macros} being invoked
5293 *! with the wrong number of parameters.
5294 */
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005295 nasm_warn(WARN_MACRO_PARAMS_SINGLE|ERR_HOLD,
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005296 "single-line macro `%s' exists, "
5297 "but not taking %d parameter%s",
5298 mname, nparam, (nparam == 1) ? "" : "s");
5299 goto not_a_macro;
5300 }
5301
5302 if (!mstrcmp(m->name, mname, m->casesense)) {
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005303 if (nparam == m->nparam)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005304 break; /* It's good */
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005305 if (m->greedy && nparam >= m->nparam-1)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005306 break; /* Also good */
5307 }
5308 m = m->next;
5309 }
5310 }
5311
5312 if (m->in_progress)
5313 goto not_a_macro;
5314
5315 /* Expand the macro */
5316 m->in_progress = true;
5317
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005318 if (nparam) {
5319 /* Extract parameters */
5320 Token **phead, **pep;
5321 int white = 0;
5322 int brackets = 0;
5323 int paren;
5324 bool bracketed = false;
5325 bool bad_bracket = false;
5326 enum sparmflags flags;
5327
5328 nparam = m->nparam;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005329 paren = 1;
5330 nasm_newn(params, nparam);
5331 i = 0;
5332 flags = m->params[i].flags;
5333 phead = pep = &params[i];
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005334 *pep = NULL;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005335
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005336 while (paren) {
5337 bool skip;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005338 char ch;
5339
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005340 tline = tline->next;
5341
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005342 if (!tline)
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005343 nasm_nonfatal("macro call expects terminating `)'");
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005344
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005345 ch = 0;
5346 skip = false;
5347
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005348
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005349 switch (tline->type) {
5350 case TOK_OTHER:
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005351 if (tline->len == 1)
H. Peter Anvin8571f062019-09-23 16:40:03 -07005352 ch = tline->text.a[0];
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005353 break;
5354
5355 case TOK_WHITESPACE:
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005356 if (!(flags & SPARM_NOSTRIP)) {
5357 if (brackets || *phead)
5358 white++; /* Keep interior whitespace */
5359 skip = true;
5360 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005361 break;
5362
5363 default:
5364 break;
5365 }
5366
5367 switch (ch) {
5368 case ',':
H. Peter Anvinbd00f252020-06-04 21:05:01 -07005369 if (!brackets && paren == 1 && !(flags & SPARM_GREEDY)) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005370 i++;
5371 nasm_assert(i < nparam);
5372 phead = pep = &params[i];
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005373 *pep = NULL;
5374 bracketed = false;
5375 skip = true;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005376 flags = m->params[i].flags;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005377 }
5378 break;
5379
5380 case '{':
5381 if (!bracketed) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005382 bracketed = !*phead && !(flags & SPARM_NOSTRIP);
5383 skip = bracketed;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005384 }
5385 brackets++;
5386 break;
5387
5388 case '}':
5389 if (brackets > 0) {
5390 if (!--brackets)
5391 skip = bracketed;
5392 }
5393 break;
5394
5395 case '(':
5396 if (!brackets)
5397 paren++;
5398 break;
5399
5400 case ')':
5401 if (!brackets) {
5402 paren--;
5403 if (!paren) {
5404 skip = true;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005405 i++; /* Found last argument */
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005406 }
5407 }
5408 break;
5409
5410 default:
5411 break; /* Normal token */
5412 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005413
5414 if (!skip) {
5415 Token *t;
5416
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005417 bad_bracket |= bracketed && !brackets;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005418
5419 if (white) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005420 *pep = t = new_White(NULL);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005421 pep = &t->next;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005422 white = 0;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005423 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005424 *pep = t = dup_Token(NULL, tline);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005425 pep = &t->next;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005426 }
5427 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005428
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005429 /*
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005430 * Possible further processing of parameters. Note that the
5431 * ordering matters here.
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005432 */
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005433 for (i = 0; i < nparam; i++) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005434 enum sparmflags flags = m->params[i].flags;
5435
5436 if (flags & SPARM_EVAL) {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005437 /* Evaluate this parameter as a number */
5438 struct ppscan pps;
5439 struct tokenval tokval;
5440 expr *evalresult;
5441 Token *eval_param;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005442
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005443 pps.tptr = eval_param = expand_smacro_noreset(params[i]);
5444 pps.ntokens = -1;
5445 tokval.t_type = TOKEN_INVALID;
5446 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005447
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005448 free_tlist(eval_param);
5449 params[i] = NULL;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005450
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005451 if (!evalresult) {
5452 /* Nothing meaningful to do */
5453 } else if (tokval.t_type) {
5454 nasm_nonfatal("invalid expression in parameter %d of macro `%s'", i, m->name);
5455 } else if (!is_simple(evalresult)) {
5456 nasm_nonfatal("non-constant expression in parameter %d of macro `%s'", i, m->name);
5457 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07005458 params[i] = make_tok_num(NULL, reloc_value(evalresult));
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005459 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005460 }
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005461
5462 if (flags & SPARM_STR) {
5463 /* Convert expansion to a quoted string */
5464 char *arg;
5465 Token *qs;
5466
5467 qs = expand_smacro_noreset(params[i]);
5468 arg = detoken(qs, false);
5469 free_tlist(qs);
H. Peter Anvin8571f062019-09-23 16:40:03 -07005470 params[i] = make_tok_qstr(NULL, arg);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005471 nasm_free(arg);
5472 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005473 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005474 }
5475
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005476 /* Note: we own the expansion this returns. */
5477 t = m->expand(m, params, nparam);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005478
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005479 tafter = tline->next; /* Skip past the macro call */
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07005480 tline->next = NULL; /* Truncate list at the macro call end */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005481 tline = tafter;
5482
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005483 tup = NULL;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005484 cond_comma = false;
5485
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005486 while (t) {
5487 enum pp_token_type type = t->type;
5488 Token *tnext = t->next;
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005489
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005490 switch (type) {
5491 case TOK_PREPROC_Q:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005492 delete_Token(t);
5493 t = dup_Token(tline, mstart);
5494 break;
5495
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005496 case TOK_PREPROC_QQ:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005497 {
H. Peter Anvin8571f062019-09-23 16:40:03 -07005498 size_t mlen = strlen(m->name);
5499 size_t len;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005500 char *p;
5501
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005502 t->type = mstart->type;
H. Peter Anvin8571f062019-09-23 16:40:03 -07005503 if (t->type == TOK_LOCAL_MACRO) {
5504 const char *psp; /* prefix start pointer */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005505 const char *pep; /* prefix end pointer */
H. Peter Anvin8571f062019-09-23 16:40:03 -07005506 size_t plen;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005507
H. Peter Anvin8571f062019-09-23 16:40:03 -07005508 psp = tok_text(mstart);
5509 get_ctx(psp, &pep);
5510 plen = pep - psp;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005511
H. Peter Anvin8571f062019-09-23 16:40:03 -07005512 len = mlen + plen;
5513 p = nasm_malloc(len + 1);
5514 p = mempcpy(p, psp, plen);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005515 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07005516 len = mlen;
5517 p = nasm_malloc(len + 1);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005518 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07005519 p = mempcpy(p, m->name, mlen);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005520 *p = '\0';
H. Peter Anvin8571f062019-09-23 16:40:03 -07005521 set_text_free(t, p, len);
5522
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005523 t->next = tline;
5524 break;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005525 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005526
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005527 case TOK_COND_COMMA:
5528 delete_Token(t);
H. Peter Anvin8571f062019-09-23 16:40:03 -07005529 t = cond_comma ? make_tok_char(tline, ',') : NULL;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005530 break;
5531
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005532 case TOK_ID:
5533 case TOK_PREPROC_ID:
H. Peter Anvin8571f062019-09-23 16:40:03 -07005534 case TOK_LOCAL_MACRO:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005535 {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005536 /*
5537 * Chain this into the target line *before* expanding,
5538 * that way we pick up any arguments to the new macro call,
5539 * if applicable.
5540 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005541 Token **tp = &t;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005542 t->next = tline;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005543 expand_one_smacro(&tp);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005544 tline = *tp; /* First token left after any macro call */
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005545 break;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005546 }
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005547 default:
5548 if (is_smac_param(t->type)) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005549 int param = smac_nparam(t->type);
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005550 nasm_assert(!tup && param < nparam);
5551 delete_Token(t);
5552 t = NULL;
5553 tup = tnext;
5554 tnext = dup_tlist_reverse(params[param], NULL);
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005555 cond_comma = false;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005556 } else {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005557 t->next = tline;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005558 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005559 }
5560
5561 if (t) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005562 Token *endt = tline;
5563
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005564 tline = t;
Chang S. Bae95e54a92020-02-06 14:39:22 -08005565 while (!cond_comma && t && t != endt) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005566 cond_comma = t->type != TOK_WHITESPACE;
Chang S. Bae95e54a92020-02-06 14:39:22 -08005567 t = t->next;
5568 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005569 }
5570
5571 if (tnext) {
5572 t = tnext;
5573 } else {
5574 t = tup;
5575 tup = NULL;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005576 }
5577 }
5578
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005579 **tpp = tline;
H. Peter Anvin (Intel)6e714962020-06-01 12:21:10 -07005580 for (t = tline; t && t != tafter; t = t->next)
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005581 *tpp = &t->next;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005582
5583 m->in_progress = false;
5584
5585 /* Don't do this until after expansion or we will clobber mname */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005586 free_tlist(mstart);
H. Peter Anvin322bee02019-08-10 01:38:06 -07005587 goto done;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005588
5589 /*
5590 * No macro expansion needed; roll back to mstart (if necessary)
H. Peter Anvin322bee02019-08-10 01:38:06 -07005591 * and then advance to the next input token. Note that this is
5592 * by far the common case!
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005593 */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005594not_a_macro:
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005595 *tpp = &mstart->next;
H. Peter Anvin322bee02019-08-10 01:38:06 -07005596 m = NULL;
5597done:
5598 smacro_deadman.levels++;
5599 if (unlikely(params))
5600 free_tlist_array(params, nparam);
5601 return m;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005602}
5603
5604/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005605 * Expand all single-line macro calls made in the given line.
5606 * Return the expanded version of the line. The original is deemed
5607 * to be destroyed in the process. (In reality we'll just move
5608 * Tokens from input to output a lot of the time, rather than
5609 * actually bothering to destroy and replicate.)
5610 */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005611static Token *expand_smacro(Token *tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005612{
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07005613 smacro_deadman.total = nasm_limit[LIMIT_MACRO_TOKENS];
H. Peter Anvin322bee02019-08-10 01:38:06 -07005614 smacro_deadman.levels = nasm_limit[LIMIT_MACRO_LEVELS];
5615 smacro_deadman.triggered = false;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005616 return expand_smacro_noreset(tline);
5617}
5618
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005619static Token *expand_smacro_noreset(Token *org_tline)
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005620{
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005621 Token *tline;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005622 bool expanded;
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005623 errhold errhold; /* Hold warning/errors during expansion */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005624
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005625 if (!org_tline)
5626 return NULL; /* Empty input */
5627
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005628 /*
5629 * Trick: we should avoid changing the start token pointer since it can
5630 * be contained in "next" field of other token. Because of this
5631 * we allocate a copy of first token and work with it; at the end of
5632 * routine we copy it back
5633 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005634 tline = dup_Token(org_tline->next, org_tline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005635
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005636 /*
5637 * Pretend that we always end up doing expansion on the first pass;
5638 * that way %+ get processed. However, if we process %+ before the
5639 * first pass, we end up with things like MACRO %+ TAIL trying to
5640 * look up the macro "MACROTAIL", which we don't want.
5641 */
5642 expanded = true;
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005643
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005644 while (true) {
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005645 static const struct tokseq_match tmatch[] = {
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04005646 {
5647 PP_CONCAT_MASK(TOK_ID) |
H. Peter Anvin8571f062019-09-23 16:40:03 -07005648 PP_CONCAT_MASK(TOK_LOCAL_MACRO) |
5649 PP_CONCAT_MASK(TOK_ENVIRON) |
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04005650 PP_CONCAT_MASK(TOK_PREPROC_ID), /* head */
5651 PP_CONCAT_MASK(TOK_ID) |
H. Peter Anvin8571f062019-09-23 16:40:03 -07005652 PP_CONCAT_MASK(TOK_LOCAL_MACRO) |
5653 PP_CONCAT_MASK(TOK_ENVIRON) |
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04005654 PP_CONCAT_MASK(TOK_PREPROC_ID) |
5655 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
5656 }
5657 };
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005658 Token **tail = &tline;
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005659
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005660 /*
5661 * We hold warnings/errors until we are done this this loop. It is
5662 * possible for nuisance warnings to appear that disappear on later
5663 * passes.
5664 */
5665 errhold = nasm_error_hold_push();
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005666
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005667 while (*tail) /* main token loop */
H. Peter Anvin322bee02019-08-10 01:38:06 -07005668 expanded |= !!expand_one_smacro(&tail);
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005669
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005670 if (!expanded)
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005671 break; /* Done! */
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005672
5673 /*
5674 * Now scan the entire line and look for successive TOK_IDs
5675 * that resulted after expansion (they can't be produced by
5676 * tokenize()). The successive TOK_IDs should be concatenated.
5677 * Also we look for %+ tokens and concatenate the tokens
5678 * before and after them (without white spaces in between).
5679 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005680 if (!paste_tokens(&tline, tmatch, ARRAY_SIZE(tmatch), true))
5681 break; /* Done again! */
5682
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005683 nasm_error_hold_pop(errhold, false);
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005684 expanded = false;
H. Peter Anvin734b1882002-04-30 21:01:08 +00005685 }
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005686 nasm_error_hold_pop(errhold, true);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005687
H. Peter Anvin8571f062019-09-23 16:40:03 -07005688 if (!tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005689 /*
5690 * The expression expanded to empty line;
5691 * we can't return NULL because of the "trick" above.
5692 * Just set the line to a single WHITESPACE token.
H. Peter Anvin8571f062019-09-23 16:40:03 -07005693 */
5694
5695 tline = new_White(NULL);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005696 }
5697
H. Peter Anvin8571f062019-09-23 16:40:03 -07005698 steal_Token(org_tline, tline);
5699 org_tline->next = tline->next;
5700 delete_Token(tline);
5701
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005702 return org_tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005703}
5704
5705/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005706 * Similar to expand_smacro but used exclusively with macro identifiers
5707 * right before they are fetched in. The reason is that there can be
5708 * identifiers consisting of several subparts. We consider that if there
5709 * are more than one element forming the name, user wants a expansion,
5710 * otherwise it will be left as-is. Example:
5711 *
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03005712 * %define %$abc cde
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005713 *
5714 * the identifier %$abc will be left as-is so that the handler for %define
5715 * will suck it and define the corresponding value. Other case:
5716 *
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03005717 * %define _%$abc cde
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005718 *
5719 * In this case user wants name to be expanded *before* %define starts
5720 * working, so we'll expand %$abc into something (if it has a value;
5721 * otherwise it will be left as-is) then concatenate all successive
5722 * PP_IDs into one.
5723 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00005724static Token *expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005725{
5726 Token *cur, *oldnext = NULL;
5727
H. Peter Anvin734b1882002-04-30 21:01:08 +00005728 if (!tline || !tline->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005729 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005730
5731 cur = tline;
5732 while (cur->next &&
H. Peter Anvin8571f062019-09-23 16:40:03 -07005733 (cur->next->type == TOK_ID || cur->next->type == TOK_PREPROC_ID ||
5734 cur->next->type == TOK_LOCAL_MACRO || cur->next->type == TOK_NUMBER))
H. Peter Anvine2c80182005-01-15 22:15:51 +00005735 cur = cur->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005736
5737 /* If identifier consists of just one token, don't expand */
5738 if (cur == tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005739 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005740
H. Peter Anvine2c80182005-01-15 22:15:51 +00005741 if (cur) {
5742 oldnext = cur->next; /* Detach the tail past identifier */
5743 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005744 }
5745
H. Peter Anvin734b1882002-04-30 21:01:08 +00005746 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005747
H. Peter Anvine2c80182005-01-15 22:15:51 +00005748 if (cur) {
5749 /* expand_smacro possibly changhed tline; re-scan for EOL */
5750 cur = tline;
5751 while (cur && cur->next)
5752 cur = cur->next;
5753 if (cur)
5754 cur->next = oldnext;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005755 }
5756
5757 return tline;
5758}
5759
5760/*
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005761 * This is called from find_mmacro_in_list() after finding a suitable macro.
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005762 */
5763static MMacro *use_mmacro(MMacro *m, int *nparamp, Token ***paramsp)
5764{
5765 int nparam = *nparamp;
5766 Token **params = *paramsp;
5767
5768 /*
5769 * This one is right. Just check if cycle removal
5770 * prohibits us using it before we actually celebrate...
5771 */
5772 if (m->in_progress > m->max_depth) {
5773 if (m->max_depth > 0) {
5774 nasm_warn(WARN_OTHER, "reached maximum recursion depth of %i",
5775 m->max_depth);
5776 }
5777 nasm_free(params);
5778 *nparamp = 0;
5779 *paramsp = NULL;
5780 return NULL;
5781 }
5782
5783 /*
5784 * It's right, and we can use it. Add its default
5785 * parameters to the end of our list if necessary.
5786 */
5787 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
5788 int newnparam = m->nparam_min + m->ndefs;
5789 params = nasm_realloc(params, sizeof(*params) * (newnparam+2));
5790 memcpy(&params[nparam+1], &m->defaults[nparam+1-m->nparam_min],
5791 (newnparam - nparam) * sizeof(*params));
5792 nparam = newnparam;
5793 }
5794 /*
5795 * If we've gone over the maximum parameter count (and
5796 * we're in Plus mode), ignore parameters beyond
5797 * nparam_max.
5798 */
5799 if (m->plus && nparam > m->nparam_max)
5800 nparam = m->nparam_max;
5801
5802 /*
5803 * If nparam was adjusted above, make sure the list is still
5804 * NULL-terminated.
5805 */
5806 params[nparam+1] = NULL;
5807
5808 /* Done! */
5809 *paramsp = params;
5810 *nparamp = nparam;
5811 return m;
5812}
5813
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005814/*
5815 * Search a macro list and try to find a match. If matching, call
5816 * use_mmacro() to set up the macro call. m points to the list of
5817 * search, which is_mmacro() sets to the first *possible* match.
5818 */
5819static MMacro *
5820find_mmacro_in_list(MMacro *m, const char *finding,
5821 int *nparamp, Token ***paramsp)
5822{
5823 int nparam = *nparamp;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005824
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005825 while (m) {
5826 if (m->nparam_min <= nparam
5827 && (m->plus || nparam <= m->nparam_max)) {
5828 /*
5829 * This one matches, use it.
5830 */
5831 return use_mmacro(m, nparamp, paramsp);
5832 }
5833
5834 /*
5835 * Otherwise search for the next one with a name match.
5836 */
5837 list_for_each(m, m->next) {
5838 if (!mstrcmp(m->name, finding, m->casesense))
5839 break;
5840 }
5841 }
5842
5843 return NULL;
5844}
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005845
5846/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005847 * Determine whether the given line constitutes a multi-line macro
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005848 * call, and return the MMacro structure called if so. Doesn't have
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005849 * to check for an initial label - that's taken care of in
5850 * expand_mmacro - but must check numbers of parameters. Guaranteed
5851 * to be called with tline->type == TOK_ID, so the putative macro
5852 * name is easy to find.
5853 */
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005854static MMacro *is_mmacro(Token * tline, int *nparamp, Token ***paramsp)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005855{
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005856 MMacro *head, *m, *found;
5857 Token **params, **comma;
5858 int raw_nparam, nparam;
H. Peter Anvin8571f062019-09-23 16:40:03 -07005859 const char *finding = tok_text(tline);
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005860 bool empty_args = !tline->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005861
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005862 *nparamp = 0;
5863 *paramsp = NULL;
5864
H. Peter Anvin8571f062019-09-23 16:40:03 -07005865 head = (MMacro *) hash_findix(&mmacros, finding);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005866
5867 /*
5868 * Efficiency: first we see if any macro exists with the given
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07005869 * name which isn't already excluded by macro cycle removal.
5870 * (The cycle removal test here helps optimize the case of wrapping
5871 * instructions, and is cheap to do here.)
5872 *
5873 * If not, we can return NULL immediately. _Then_ we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005874 * count the parameters, and then we look further along the
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005875 * list if necessary to find the proper MMacro.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005876 */
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07005877 list_for_each(m, head) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07005878 if (!mstrcmp(m->name, finding, m->casesense) &&
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07005879 (m->in_progress != 1 || m->max_depth > 0))
5880 break; /* Found something that needs consideration */
5881 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005882 if (!m)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005883 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005884
5885 /*
5886 * OK, we have a potential macro. Count and demarcate the
5887 * parameters.
5888 */
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005889 comma = count_mmac_params(tline->next, nparamp, paramsp);
5890 raw_nparam = *nparamp;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005891
5892 /*
5893 * Search for an exact match. This cannot come *before* the m
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005894 * found in the list search before, so we can start there.
5895 *
5896 * If found is NULL and *paramsp has been cleared, then we
5897 * encountered an error for which we have already issued a
5898 * diagnostic, so we should not proceed.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005899 */
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005900 found = find_mmacro_in_list(m, finding, nparamp, paramsp);
5901 if (!*paramsp)
5902 return NULL;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005903
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005904 nparam = *nparamp;
5905 params = *paramsp;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005906
5907 /*
5908 * Special weirdness: in NASM < 2.15, an expansion of
5909 * *only* whitespace, as can happen during macro expansion under
5910 * certain circumstances, is counted as zero arguments for the
5911 * purpose of %0, but one argument for the purpose of macro
5912 * matching! In particular, this affects:
5913 *
5914 * foobar %1
5915 *
5916 * ... with %1 being empty; this would call the one-argument
5917 * version of "foobar" with an empty argument, equivalent to
5918 *
5919 * foobar {%1}
5920 *
5921 * ... except that %0 would be set to 0 inside foobar, even if
5922 * foobar is declared with "%macro foobar 1" or equivalent!
5923 *
5924 * The proper way to do that is to define "%macro foobar 0-1".
5925 *
5926 * To be compatible without doing something too stupid, try to
5927 * match a zero-argument macro first, but if that fails, try
5928 * for a one-argument macro with the above behavior.
5929 *
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005930 * Furthermore, NASM < 2.15 will match stripping a tailing empty
5931 * argument, but in that case %0 *does* reflect that this argument
5932 * have been stripped; this is handled in count_mmac_params().
5933 *
5934 * To disable these insane legacy behaviors, use:
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005935 *
5936 * %pragma preproc sane_empty_expansion yes
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005937 *
5938 *!macro-params-legacy [on] improperly calling multi-line macro for legacy support
5939 *! warns about \i{multi-line macros} being invoked
5940 *! with the wrong number of parameters, but for bug-compatibility
5941 *! with NASM versions older than 2.15, NASM tried to fix up the
5942 *! parameters to match the legacy behavior and call the macro anyway.
5943 *! This can happen in certain cases where there are empty arguments
5944 *! without braces, sometimes as a result of macro expansion.
5945 *!-
5946 *! The legacy behavior is quite strange and highly context-dependent,
5947 *! and can be disabled with:
5948 *!-
5949 *! \c %pragma preproc sane_empty_expansion true
5950 *!-
5951 *! It is highly recommended to use this option in new code.
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005952 */
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005953 if (!ppopt.sane_empty_expansion) {
5954 if (!found) {
5955 if (raw_nparam == 0 && !empty_args) {
5956 /*
5957 * A single all-whitespace parameter as the only thing?
5958 * Look for a one-argument macro, but don't adjust
5959 * *nparamp.
5960 */
5961 int bogus_nparam = 1;
5962 params[2] = NULL;
5963 found = find_mmacro_in_list(m, finding, &bogus_nparam, paramsp);
5964 } else if (raw_nparam > 1 && comma) {
5965 Token *comma_tail = *comma;
5966
5967 /*
5968 * Drop the terminal argument and try again.
5969 * If we fail, we need to restore the comma to
5970 * preserve tlist.
5971 */
5972 *comma = NULL;
5973 *nparamp = raw_nparam - 1;
5974 found = find_mmacro_in_list(m, finding, nparamp, paramsp);
5975 if (found)
5976 free_tlist(comma_tail);
5977 else
5978 *comma = comma_tail;
5979 }
5980
5981 if (!*paramsp)
5982 return NULL;
5983 } else if (comma) {
5984 free_tlist(*comma);
5985 *comma = NULL;
5986 if (raw_nparam > found->nparam_min &&
5987 raw_nparam <= found->nparam_min + found->ndefs) {
5988 /* Replace empty argument with default parameter */
5989 params[raw_nparam] =
5990 found->defaults[raw_nparam - found->nparam_min];
5991 } else if (raw_nparam > found->nparam_max && found->plus) {
5992 /* Just drop the comma, don't adjust argument count */
5993 } else {
5994 /* Drop argument. This may cause nparam < nparam_min. */
5995 params[raw_nparam] = NULL;
5996 *nparamp = nparam = raw_nparam - 1;
5997 }
5998 }
5999
6000 if (found) {
6001 if (raw_nparam < found->nparam_min ||
6002 (raw_nparam > found->nparam_max && !found->plus)) {
6003 nasm_warn(WARN_MACRO_PARAMS_LEGACY,
6004 "improperly calling multi-line macro `%s' with %d parameters",
6005 found->name, raw_nparam);
6006 } else if (comma) {
6007 nasm_warn(WARN_MACRO_PARAMS_LEGACY,
6008 "dropping trailing empty parameter in call to multi-line macro `%s'", found->name);
6009 }
6010 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006011 }
6012
6013 /*
6014 * After all that, we didn't find one with the right number of
6015 * parameters. Issue a warning, and fail to expand the macro.
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006016 *!
6017 *!macro-params-multi [on] multi-line macro calls with wrong parameter count
6018 *! warns about \i{multi-line macros} being invoked
6019 *! with the wrong number of parameters. See \k{mlmacover} for an
6020 *! example of why you might want to disable this warning.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006021 */
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07006022 if (found)
6023 return found;
6024
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006025 nasm_warn(WARN_MACRO_PARAMS_MULTI,
6026 "multi-line macro `%s' exists, but not taking %d parameter%s",
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07006027 finding, nparam, (nparam == 1) ? "" : "s");
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07006028 nasm_free(*paramsp);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006029 return NULL;
6030}
6031
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006032
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006033#if 0
6034
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006035/*
6036 * Save MMacro invocation specific fields in
6037 * preparation for a recursive macro expansion
6038 */
6039static void push_mmacro(MMacro *m)
6040{
6041 MMacroInvocation *i;
6042
6043 i = nasm_malloc(sizeof(MMacroInvocation));
6044 i->prev = m->prev;
6045 i->params = m->params;
6046 i->iline = m->iline;
6047 i->nparam = m->nparam;
6048 i->rotate = m->rotate;
6049 i->paramlen = m->paramlen;
6050 i->unique = m->unique;
6051 i->condcnt = m->condcnt;
6052 m->prev = i;
6053}
6054
6055
6056/*
6057 * Restore MMacro invocation specific fields that were
6058 * saved during a previous recursive macro expansion
6059 */
6060static void pop_mmacro(MMacro *m)
6061{
6062 MMacroInvocation *i;
6063
6064 if (m->prev) {
6065 i = m->prev;
6066 m->prev = i->prev;
6067 m->params = i->params;
6068 m->iline = i->iline;
6069 m->nparam = i->nparam;
6070 m->rotate = i->rotate;
6071 m->paramlen = i->paramlen;
6072 m->unique = i->unique;
6073 m->condcnt = i->condcnt;
6074 nasm_free(i);
6075 }
6076}
6077
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006078#endif
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006079
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006080/*
H. Peter Anvin (Intel)ffe89dd2019-08-20 16:06:36 -07006081 * List an mmacro call with arguments (-Lm option)
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07006082 */
6083static void list_mmacro_call(const MMacro *m)
6084{
6085 const char prefix[] = " ;;; [macro] ";
6086 size_t namelen, size;
6087 char *buf, *p;
6088 unsigned int i;
6089 const Token *t;
6090
6091 namelen = strlen(m->iname);
6092 size = namelen + sizeof(prefix); /* Includes final null (from prefix) */
6093
6094 for (i = 1; i <= m->nparam; i++) {
6095 int j = 0;
6096 size += 3; /* Braces and space/comma */
6097 list_for_each(t, m->params[i]) {
6098 if (j++ >= m->paramlen[i])
6099 break;
6100 size += (t->type == TOK_WHITESPACE) ? 1 : t->len;
6101 }
6102 }
6103
6104 buf = p = nasm_malloc(size);
6105 p = mempcpy(p, prefix, sizeof(prefix) - 1);
6106 p = mempcpy(p, m->iname, namelen);
6107 *p++ = ' ';
6108
6109 for (i = 1; i <= m->nparam; i++) {
6110 int j = 0;
6111 *p++ = '{';
6112 list_for_each(t, m->params[i]) {
6113 if (j++ >= m->paramlen[i])
6114 break;
H. Peter Anvin8571f062019-09-23 16:40:03 -07006115 p = mempcpy(p, tok_text(t), t->len);
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07006116 }
6117 *p++ = '}';
6118 *p++ = ',';
6119 }
6120
6121 *--p = '\0'; /* Replace last delimeter with null */
6122 lfmt->line(LIST_MACRO, -1, buf);
6123 nasm_free(buf);
6124}
6125
6126/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006127 * Expand the multi-line macro call made by the given line, if
6128 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006129 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006130 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006131static int expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006132{
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006133 Token *startline = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00006134 Token *label = NULL;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006135 bool dont_prepend = false;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006136 Token **params, *t, *tt;
6137 MMacro *m;
6138 Line *l, *ll;
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07006139 int i, *paramlen;
H. Peter Anvinc751e862008-06-09 10:18:45 -07006140 const char *mname;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006141 int nparam = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006142
6143 t = tline;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006144 t = skip_white(t);
6145 /* if (!tok_type(t, TOK_ID)) Lino 02/25/02 */
H. Peter Anvin8571f062019-09-23 16:40:03 -07006146 if (!tok_type(t, TOK_ID) && !tok_type(t, TOK_LOCAL_MACRO))
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006147 return 0;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006148 m = is_mmacro(t, &nparam, &params);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006149 if (m) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07006150 mname = tok_text(t);
H. Peter Anvinc751e862008-06-09 10:18:45 -07006151 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006152 Token *last;
6153 /*
6154 * We have an id which isn't a macro call. We'll assume
6155 * it might be a label; we'll also check to see if a
6156 * colon follows it. Then, if there's another id after
6157 * that lot, we'll check it again for macro-hood.
6158 */
6159 label = last = t;
6160 t = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006161 if (tok_white(t))
H. Peter Anvine2c80182005-01-15 22:15:51 +00006162 last = t, t = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006163 if (tok_is(t, ':')) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006164 dont_prepend = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006165 last = t, t = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006166 if (tok_white(t))
H. Peter Anvine2c80182005-01-15 22:15:51 +00006167 last = t, t = t->next;
6168 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006169 if (!tok_type(t, TOK_ID) || !(m = is_mmacro(t, &nparam, &params)))
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006170 return 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006171 last->next = NULL;
H. Peter Anvin8571f062019-09-23 16:40:03 -07006172 mname = tok_text(t);
H. Peter Anvine2c80182005-01-15 22:15:51 +00006173 tline = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00006174 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006175
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07006176 if (unlikely(mmacro_deadman.total >= nasm_limit[LIMIT_MMACROS] ||
6177 mmacro_deadman.levels >= nasm_limit[LIMIT_MACRO_LEVELS])) {
6178 if (!mmacro_deadman.triggered) {
6179 nasm_nonfatal("interminable multiline macro recursion");
6180 mmacro_deadman.triggered = true;
6181 }
6182 return 0;
6183 }
6184
6185 mmacro_deadman.total++;
6186 mmacro_deadman.levels++;
6187
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006188 /*
6189 * Fix up the parameters: this involves stripping leading and
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07006190 * trailing whitespace and stripping braces if they are present.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006191 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006192 nasm_newn(paramlen, nparam+1);
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07006193
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006194 for (i = 1; (t = params[i]); i++) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006195 bool braced = false;
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08006196 int brace = 0;
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006197 int white = 0;
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07006198 bool comma = !m->plus || i < nparam;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006199
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006200 t = skip_white(t);
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006201 if (tok_is(t, '{')) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006202 t = t->next;
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006203 brace = 1;
6204 braced = true;
6205 comma = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006206 }
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006207
6208 params[i] = t;
6209 for (; t; t = t->next) {
6210 if (tok_white(t)) {
6211 white++;
6212 continue;
6213 }
6214
6215 if (t->type == TOK_OTHER && t->len == 1) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07006216 switch (t->text.a[0]) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006217 case ',':
6218 if (comma && !brace)
6219 goto endparam;
6220 break;
6221
6222 case '{':
6223 brace++;
6224 break;
6225
6226 case '}':
6227 brace--;
6228 if (braced && !brace) {
6229 paramlen[i] += white;
6230 goto endparam;
6231 }
6232 break;
6233
6234 default:
6235 break;
6236 }
6237 }
6238
6239 paramlen[i] += white + 1;
6240 white = 0;
6241 }
6242 endparam:
6243 ;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006244 }
6245
6246 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006247 * OK, we have a MMacro structure together with a set of
6248 * parameters. We must now go through the expansion and push
6249 * copies of each Line on to istk->expansion. Substitution of
H. Peter Anvin76690a12002-04-30 20:52:49 +00006250 * parameter tokens and macro-local tokens doesn't get done
6251 * until the single-line macro substitution process; this is
6252 * because delaying them allows us to change the semantics
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006253 * later through %rotate and give the right semantics for
6254 * nested mmacros.
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006255 *
6256 * First, push an end marker on to istk->expansion, mark this
6257 * macro as in progress, and set up its invocation-specific
6258 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006259 */
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07006260 nasm_new(ll);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006261 ll->next = istk->expansion;
6262 ll->finishes = m;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006263 ll->where = istk->where;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006264 istk->expansion = ll;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006265
6266 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006267 * Save the previous MMacro expansion in the case of
6268 * macro recursion
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006269 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006270#if 0
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006271 if (m->max_depth && m->in_progress)
6272 push_mmacro(m);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006273#endif
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006274
6275 m->in_progress ++;
6276 m->params = params;
6277 m->iline = tline;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006278 m->iname = nasm_strdup(mname);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006279 m->nparam = nparam;
6280 m->rotate = 0;
6281 m->paramlen = paramlen;
6282 m->unique = unique++;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006283 m->condcnt = 0;
6284
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006285 m->mstk = istk->mstk;
6286 istk->mstk.mstk = istk->mstk.mmac = m;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006287
6288 list_for_each(l, m->expansion) {
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07006289 nasm_new(ll);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006290 ll->next = istk->expansion;
6291 istk->expansion = ll;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006292 ll->first = dup_tlist(l->first, NULL);
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006293 ll->where = l->where;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006294 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006295
6296 /*
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006297 * If we had a label, and this macro definition does not include
6298 * a %00, push it on as the first line of, ot
H. Peter Anvineba20a72002-04-30 20:53:55 +00006299 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006300 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006301 if (label) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006302 /*
6303 * We had a label. If this macro contains an %00 parameter,
6304 * save the value as a special parameter (which is what it
6305 * is), otherwise push it as the first line of the macro
6306 * expansion.
6307 */
6308 if (m->capture_label) {
6309 params[0] = dup_Token(NULL, label);
6310 paramlen[0] = 1;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006311 free_tlist(startline);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006312 } else {
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006313 nasm_new(ll);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006314 ll->finishes = NULL;
6315 ll->next = istk->expansion;
6316 istk->expansion = ll;
6317 ll->first = startline;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006318 ll->where = istk->where;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006319 if (!dont_prepend) {
6320 while (label->next)
6321 label = label->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07006322 label->next = tt = make_tok_char(NULL, ':');
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006323 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006324 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00006325 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006326
H. Peter Anvin0d4d4312019-08-07 00:46:27 -07006327 lfmt->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006328
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07006329 if (list_option('m') && !m->nolist)
6330 list_mmacro_call(m);
6331
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006332 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006333}
6334
H. Peter Anvin130736c2016-02-17 20:27:41 -08006335/*
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006336 * This function decides if an error message should be suppressed.
6337 * It will never be called with a severity level of ERR_FATAL or
6338 * higher.
H. Peter Anvin130736c2016-02-17 20:27:41 -08006339 */
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006340static bool pp_suppress_error(errflags severity)
Victor van den Elzen3b404c02008-09-18 13:51:36 +02006341{
H. Peter Anvin130736c2016-02-17 20:27:41 -08006342 /*
6343 * If we're in a dead branch of IF or something like it, ignore the error.
6344 * However, because %else etc are evaluated in the state context
6345 * of the previous branch, errors might get lost:
6346 * %if 0 ... %else trailing garbage ... %endif
6347 * So %else etc should set the ERR_PP_PRECOND flag.
6348 */
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006349 if (istk && istk->conds &&
H. Peter Anvin130736c2016-02-17 20:27:41 -08006350 ((severity & ERR_PP_PRECOND) ?
6351 istk->conds->state == COND_NEVER :
H. Peter Anvineb6653f2016-04-05 13:03:10 -07006352 !emitting(istk->conds->state)))
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006353 return true;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02006354
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006355 return false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00006356}
6357
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006358static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07006359stdmac_file(const SMacro *s, Token **params, int nparams)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006360{
6361 (void)s;
6362 (void)params;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07006363 (void)nparams;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006364
H. Peter Anvin8571f062019-09-23 16:40:03 -07006365 return make_tok_qstr(NULL, src_get_fname());
H. Peter Anvin8b262472019-02-26 14:00:54 -08006366}
6367
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006368static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07006369stdmac_line(const SMacro *s, Token **params, int nparams)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006370{
6371 (void)s;
6372 (void)params;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07006373 (void)nparams;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006374
H. Peter Anvin8571f062019-09-23 16:40:03 -07006375 return make_tok_num(NULL, src_get_linnum());
H. Peter Anvin8b262472019-02-26 14:00:54 -08006376}
6377
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006378static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07006379stdmac_bits(const SMacro *s, Token **params, int nparams)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006380{
6381 (void)s;
6382 (void)params;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07006383 (void)nparams;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006384
H. Peter Anvin8571f062019-09-23 16:40:03 -07006385 return make_tok_num(NULL, globalbits);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006386}
6387
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006388static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07006389stdmac_ptr(const SMacro *s, Token **params, int nparams)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006390{
H. Peter Anvin8b262472019-02-26 14:00:54 -08006391 (void)s;
6392 (void)params;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07006393 (void)nparams;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006394
6395 switch (globalbits) {
6396 case 16:
H. Peter Anvin8571f062019-09-23 16:40:03 -07006397 return new_Token(NULL, TOK_ID, "word", 4);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006398 case 32:
H. Peter Anvin8571f062019-09-23 16:40:03 -07006399 return new_Token(NULL, TOK_ID, "dword", 5);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006400 case 64:
H. Peter Anvin8571f062019-09-23 16:40:03 -07006401 return new_Token(NULL, TOK_ID, "qword", 5);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006402 default:
6403 panic();
6404 }
H. Peter Anvin8b262472019-02-26 14:00:54 -08006405}
6406
H. Peter Anvin8b262472019-02-26 14:00:54 -08006407/* Add magic standard macros */
6408struct magic_macros {
6409 const char *name;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07006410 int nparam;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006411 ExpandSMacro func;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006412};
6413static const struct magic_macros magic_macros[] =
6414{
H. Peter Anvind2354082019-08-27 16:38:48 -07006415 { "__?FILE?__", 0, stdmac_file },
6416 { "__?LINE?__", 0, stdmac_line },
6417 { "__?BITS?__", 0, stdmac_bits },
6418 { "__?PTR?__", 0, stdmac_ptr },
H. Peter Anvin8b262472019-02-26 14:00:54 -08006419 { NULL, 0, NULL }
6420};
6421
6422static void pp_add_magic_stdmac(void)
6423{
6424 const struct magic_macros *m;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07006425 SMacro tmpl;
6426
6427 nasm_zero(tmpl);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006428
6429 for (m = magic_macros; m->name; m++) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07006430 tmpl.nparam = m->nparam;
6431 tmpl.expand = m->func;
6432 define_smacro(m->name, true, NULL, &tmpl);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006433 }
6434}
6435
H. Peter Anvin734b1882002-04-30 21:01:08 +00006436static void
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006437pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006438{
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006439 int apass;
H. Peter Anvin6686de22019-08-10 05:33:14 -07006440 struct Include *inc;
H. Peter Anvin7383b402008-09-24 10:20:40 -07006441
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006442 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006443 defining = NULL;
Charles Crayned4200be2008-07-12 16:42:33 -07006444 nested_mac_count = 0;
6445 nested_rep_count = 0;
H. Peter Anvin97a23472007-09-16 17:57:25 -07006446 init_macros();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006447 unique = 0;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07006448 deplist = dep_list;
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006449 pp_mode = mode;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07006450
6451 /* Reset options to default */
6452 nasm_zero(ppopt);
H. Peter Anvinf7606612016-07-13 14:23:48 -07006453
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07006454 if (!use_loaded)
6455 use_loaded = nasm_malloc(use_package_count * sizeof(bool));
6456 memset(use_loaded, 0, use_package_count * sizeof(bool));
6457
H. Peter Anvin6686de22019-08-10 05:33:14 -07006458 /* First set up the top level input file */
6459 nasm_new(istk);
6460 istk->fp = nasm_open_read(file, NF_TEXT);
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006461 if (!istk->fp) {
6462 nasm_fatalf(ERR_NOFILE, "unable to open input file `%s'%s%s",
6463 file, errno ? " " : "", errno ? strerror(errno) : "");
6464 }
H. Peter Anvin6686de22019-08-10 05:33:14 -07006465 src_set(0, file);
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006466 istk->where = src_where();
H. Peter Anvin6686de22019-08-10 05:33:14 -07006467 istk->lineinc = 1;
H. Peter Anvin6686de22019-08-10 05:33:14 -07006468
6469 strlist_add(deplist, file);
6470
6471 /*
6472 * Set up the stdmac packages as a virtual include file,
6473 * indicated by a null file pointer.
6474 */
6475 nasm_new(inc);
6476 inc->next = istk;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006477 src_set(0, NULL);
6478 inc->where = src_where();
H. Peter Anvin6686de22019-08-10 05:33:14 -07006479 inc->nolist = !list_option('b');
6480 istk = inc;
6481 lfmt->uplevel(LIST_INCLUDE, 0);
6482
H. Peter Anvin8b262472019-02-26 14:00:54 -08006483 pp_add_magic_stdmac();
6484
H. Peter Anvinf7606612016-07-13 14:23:48 -07006485 if (tasm_compatible_mode)
6486 pp_add_stdmac(nasm_stdmac_tasm);
6487
6488 pp_add_stdmac(nasm_stdmac_nasm);
6489 pp_add_stdmac(nasm_stdmac_version);
6490
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +03006491 if (extrastdmac)
6492 pp_add_stdmac(extrastdmac);
6493
H. Peter Anvinf7606612016-07-13 14:23:48 -07006494 stdmacpos = stdmacros[0];
6495 stdmacnext = &stdmacros[1];
6496
H. Peter Anvind2456592008-06-19 15:04:18 -07006497 do_predef = true;
H. Peter Anvin61f130f2008-09-25 15:45:06 -07006498
H. Peter Anvin61f130f2008-09-25 15:45:06 -07006499 /*
H. Peter Anvind2354082019-08-27 16:38:48 -07006500 * Define the __?PASS?__ macro. This is defined here unlike all the
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07006501 * other builtins, because it is special -- it varies between
6502 * passes -- but there is really no particular reason to make it
6503 * magic.
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006504 *
6505 * 0 = dependencies only
6506 * 1 = preparatory passes
6507 * 2 = final pass
6508 * 3 = preproces only
H. Peter Anvin61f130f2008-09-25 15:45:06 -07006509 */
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006510 switch (mode) {
6511 case PP_NORMAL:
6512 apass = pass_final() ? 2 : 1;
6513 break;
6514 case PP_DEPS:
6515 apass = 0;
6516 break;
6517 case PP_PREPROC:
6518 apass = 3;
6519 break;
6520 default:
6521 panic();
6522 }
6523
H. Peter Anvin8571f062019-09-23 16:40:03 -07006524 define_smacro("__?PASS?__", true, make_tok_num(NULL, apass), NULL);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006525}
6526
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07006527static void pp_init(void)
6528{
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07006529}
6530
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006531/*
6532 * Get a line of tokens. If we popped the macro expansion/include stack,
6533 * we return a pointer to the dummy token tok_pop; at that point if
6534 * istk is NULL then we have reached end of input;
6535 */
6536static Token tok_pop; /* Dummy token placeholder */
6537
6538static Token *pp_tokline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006539{
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006540 while (true) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006541 Line *l = istk->expansion;
6542 Token *tline = NULL;
6543 Token *dtline;
6544
H. Peter Anvine2c80182005-01-15 22:15:51 +00006545 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006546 * Fetch a tokenized line, either from the macro-expansion
H. Peter Anvine2c80182005-01-15 22:15:51 +00006547 * buffer or from the input file.
6548 */
6549 tline = NULL;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006550 while (l && l->finishes) {
6551 MMacro *fm = l->finishes;
H. Peter Anvineba20a72002-04-30 20:53:55 +00006552
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006553 if (!fm->name && fm->in_progress > 1) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006554 /*
6555 * This is a macro-end marker for a macro with no
6556 * name, which means it's not really a macro at all
6557 * but a %rep block, and the `in_progress' field is
6558 * more than 1, meaning that we still need to
6559 * repeat. (1 means the natural last repetition; 0
6560 * means termination by %exitrep.) We have
6561 * therefore expanded up to the %endrep, and must
6562 * push the whole block on to the expansion buffer
6563 * again. We don't bother to remove the macro-end
6564 * marker: we'd only have to generate another one
6565 * if we did.
6566 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006567 fm->in_progress--;
6568 list_for_each(l, fm->expansion) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006569 Line *ll;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006570
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006571 nasm_new(ll);
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006572 ll->next = istk->expansion;
6573 ll->first = dup_tlist(l->first, NULL);
6574 ll->where = l->where;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006575 istk->expansion = ll;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006576 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006577 break;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006578 } else {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006579 MMacro *m = istk->mstk.mstk;
6580
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006581 /*
6582 * Check whether a `%rep' was started and not ended
6583 * within this macro expansion. This can happen and
6584 * should be detected. It's a fatal error because
6585 * I'm too confused to work out how to recover
6586 * sensibly from it.
6587 */
6588 if (defining) {
6589 if (defining->name)
H. Peter Anvinc5136902018-06-15 18:20:17 -07006590 nasm_panic("defining with name in expansion");
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006591 else if (m->name)
H. Peter Anvinc5136902018-06-15 18:20:17 -07006592 nasm_fatal("`%%rep' without `%%endrep' within"
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006593 " expansion of macro `%s'", m->name);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006594 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006595
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006596 /*
6597 * FIXME: investigate the relationship at this point between
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006598 * istk->mstk.mstk and fm
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006599 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006600 istk->mstk = m->mstk;
6601 if (m->name) {
6602 /*
6603 * This was a real macro call, not a %rep, and
6604 * therefore the parameter information needs to
6605 * be freed and the iteration count/nesting
6606 * depth adjusted.
6607 */
6608
6609 if (!--mmacro_deadman.levels) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006610 /*
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006611 * If all mmacro processing done,
6612 * clear all counters and the deadman
6613 * message trigger.
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006614 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006615 nasm_zero(mmacro_deadman); /* Clear all counters */
Adam Majer91e72402017-07-25 10:42:01 +02006616 }
6617
Adam Majer91e72402017-07-25 10:42:01 +02006618#if 0
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006619 if (m->prev) {
6620 pop_mmacro(m);
6621 fm->in_progress --;
6622 } else
Adam Majer91e72402017-07-25 10:42:01 +02006623#endif
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006624 {
6625 nasm_free(m->params);
6626 free_tlist(m->iline);
6627 nasm_free(m->paramlen);
6628 fm->in_progress = 0;
6629 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006630 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006631
6632 /*
6633 * FIXME It is incorrect to always free_mmacro here.
6634 * It leads to usage-after-free.
6635 *
6636 * https://bugzilla.nasm.us/show_bug.cgi?id=3392414
6637 */
6638#if 0
6639 else
6640 free_mmacro(m);
6641#endif
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006642 }
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006643 istk->where = l->where;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006644 istk->expansion = l->next;
6645 nasm_free(l);
6646 lfmt->downlevel(LIST_MACRO);
6647 return &tok_pop;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006648 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006649
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006650 do { /* until we get a line we can use */
6651 char *line;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006652
6653 if (istk->expansion) { /* from a macro expansion */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006654 Line *l = istk->expansion;
H. Peter Anvinab6f8312019-08-09 22:31:45 -07006655
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006656 istk->expansion = l->next;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006657 istk->where = l->where;
6658 tline = l->first;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006659 nasm_free(l);
H. Peter Anvinab6f8312019-08-09 22:31:45 -07006660
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006661 if (!istk->nolist) {
6662 line = detoken(tline, false);
6663 lfmt->line(LIST_MACRO, istk->where.lineno, line);
6664 nasm_free(line);
6665 }
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006666 } else if ((line = read_line())) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006667 line = prepreproc(line);
Keith Kaniosb7a89542007-04-12 02:40:54 +00006668 tline = tokenize(line);
H. Peter Anvine2c80182005-01-15 22:15:51 +00006669 nasm_free(line);
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006670 } else {
6671 /*
6672 * The current file has ended; work down the istk
6673 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00006674 Include *i = istk;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006675 Include *is;
6676
H. Peter Anvin6686de22019-08-10 05:33:14 -07006677 if (i->fp)
6678 fclose(i->fp);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006679 if (i->conds) {
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006680 /* nasm_fatal can't be conditionally suppressed */
H. Peter Anvinc5136902018-06-15 18:20:17 -07006681 nasm_fatal("expected `%%endif' before end of file");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006682 }
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006683
6684 list_for_each(is, i->next) {
6685 if (is->fp) {
6686 lfmt->downlevel(LIST_INCLUDE);
6687 src_update(is->where);
6688 break;
6689 }
6690 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00006691 istk = i->next;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006692 nasm_free(i);
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006693 return &tok_pop;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006694 }
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006695 } while (0);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006696
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006697 /*
6698 * We must expand MMacro parameters and MMacro-local labels
6699 * _before_ we plunge into directive processing, to cope
6700 * with things like `%define something %1' such as STRUC
6701 * uses. Unless we're _defining_ a MMacro, in which case
6702 * those tokens should be left alone to go into the
6703 * definition; and unless we're in a non-emitting
6704 * condition, in which case we don't want to meddle with
6705 * anything.
6706 */
H. Peter Anvin (Intel)bacf04a2020-06-08 13:29:06 -07006707 if (!defining &&
6708 !(istk->conds && !emitting(istk->conds->state)) &&
6709 !(istk->mstk.mmac && !istk->mstk.mmac->in_progress)) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006710 tline = expand_mmac_params(tline);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006711 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006712
H. Peter Anvine2c80182005-01-15 22:15:51 +00006713 /*
6714 * Check the line to see if it's a preprocessor directive.
6715 */
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006716 if (do_directive(tline, &dtline) == DIRECTIVE_FOUND) {
6717 if (dtline)
6718 return dtline;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006719 } else if (defining) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006720 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006721 * We're defining a multi-line macro. We emit nothing
6722 * at all, and just
6723 * shove the tokenized line on to the macro definition.
H. Peter Anvine2c80182005-01-15 22:15:51 +00006724 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006725 MMacro *mmac = defining->dstk.mmac;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006726 Line *l;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006727
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006728 nasm_new(l);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006729 l->next = defining->expansion;
6730 l->first = tline;
6731 l->finishes = NULL;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006732 l->where = istk->where;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006733 defining->expansion = l;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006734
6735 /*
6736 * Remember if this mmacro expansion contains %00:
6737 * if it does, we will have to handle leading labels
6738 * specially.
6739 */
6740 if (mmac) {
6741 const Token *t;
6742 list_for_each(t, tline) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07006743 if (!memcmp(t->text.a, "%00", 4))
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006744 mmac->capture_label = true;
6745 }
6746 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006747 } else if (istk->conds && !emitting(istk->conds->state)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006748 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006749 * We're in a non-emitting branch of a condition block.
H. Peter Anvine2c80182005-01-15 22:15:51 +00006750 * Emit nothing at all, not even a blank line: when we
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006751 * emerge from the condition we'll give a line-number
H. Peter Anvine2c80182005-01-15 22:15:51 +00006752 * directive so we keep our place correctly.
6753 */
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006754 free_tlist(tline);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006755 } else if (istk->mstk.mstk && !istk->mstk.mstk->in_progress) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006756 /*
6757 * We're in a %rep block which has been terminated, so
6758 * we're walking through to the %endrep without
6759 * emitting anything. Emit nothing at all, not even a
6760 * blank line: when we emerge from the %rep block we'll
6761 * give a line-number directive so we keep our place
6762 * correctly.
6763 */
6764 free_tlist(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00006765 } else {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006766 tline = expand_smacro(tline);
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006767 if (!expand_mmacro(tline))
6768 return tline;
6769 }
6770 }
6771}
6772
6773static char *pp_getline(void)
6774{
6775 char *line = NULL;
6776 Token *tline;
6777
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006778 while (true) {
6779 tline = pp_tokline();
6780 if (tline == &tok_pop) {
6781 /*
6782 * We popped the macro/include stack. If istk is empty,
6783 * we are at end of input, otherwise just loop back.
6784 */
6785 if (!istk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006786 break;
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006787 } else {
6788 /*
6789 * De-tokenize the line and emit it.
6790 */
6791 line = detoken(tline, true);
6792 free_tlist(tline);
6793 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006794 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006795 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006796
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006797 if (list_option('e') && istk && !istk->nolist && line && line[0]) {
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07006798 char *buf = nasm_strcat(" ;;; ", line);
H. Peter Anvinab6f8312019-08-09 22:31:45 -07006799 lfmt->line(LIST_MACRO, -1, buf);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07006800 nasm_free(buf);
6801 }
6802
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006803 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006804}
6805
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006806static void pp_cleanup_pass(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006807{
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006808 if (defining) {
6809 if (defining->name) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03006810 nasm_nonfatal("end of file while still defining macro `%s'",
6811 defining->name);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006812 } else {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03006813 nasm_nonfatal("end of file while still in %%rep");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006814 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006815
6816 free_mmacro(defining);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006817 defining = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006818 }
H. Peter Anvin130736c2016-02-17 20:27:41 -08006819
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006820 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006821 ctx_pop();
H. Peter Anvin97a23472007-09-16 17:57:25 -07006822 free_macros();
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006823 while (istk) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006824 Include *i = istk;
6825 istk = istk->next;
6826 fclose(i->fp);
Cyrill Gorcunov8dcfd882011-03-03 09:18:56 +03006827 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006828 }
6829 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006830 ctx_pop();
H. Peter Anvin274cda82016-05-10 02:56:29 -07006831 src_set_fname(NULL);
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006832}
6833
6834static void pp_cleanup_session(void)
6835{
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07006836 nasm_free(use_loaded);
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006837 free_llist(predef);
6838 predef = NULL;
6839 delete_Blocks();
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006840 ipath_list = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006841}
6842
Cyrill Gorcunov8c0666b2018-11-24 14:33:48 +03006843static void pp_include_path(struct strlist *list)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006844{
Cyrill Gorcunov8c0666b2018-11-24 14:33:48 +03006845 ipath_list = list;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006846}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00006847
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04006848static void pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006849{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006850 Token *inc, *space, *name;
6851 Line *l;
6852
H. Peter Anvin734b1882002-04-30 21:01:08 +00006853 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006854 space = new_White(name);
H. Peter Anvin734b1882002-04-30 21:01:08 +00006855 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006856
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006857 l = nasm_malloc(sizeof(Line));
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006858 l->next = predef;
6859 l->first = inc;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006860 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006861 predef = l;
6862}
6863
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04006864static void pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006865{
6866 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006867 Line *l;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00006868 char *equals;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006869
6870 equals = strchr(definition, '=');
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006871 space = new_White(NULL);
H. Peter Anvin734b1882002-04-30 21:01:08 +00006872 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006873 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006874 *equals = ' ';
Keith Kaniosb7a89542007-04-12 02:40:54 +00006875 space->next = tokenize(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006876 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006877 *equals = '=';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006878
H. Peter Anvin8571f062019-09-23 16:40:03 -07006879 /* We can't predefine a TOK_LOCAL_MACRO for obvious reasons... */
Cyrill Gorcunov6d42e9b2015-02-08 11:07:17 +03006880 if (space->next->type != TOK_PREPROC_ID &&
6881 space->next->type != TOK_ID)
H. Peter Anvin (Intel)80c4f232018-12-14 13:33:24 -08006882 nasm_warn(WARN_OTHER, "pre-defining non ID `%s\'\n", definition);
Cyrill Gorcunov6d42e9b2015-02-08 11:07:17 +03006883
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006884 l = nasm_malloc(sizeof(Line));
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006885 l->next = predef;
6886 l->first = def;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006887 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006888 predef = l;
6889}
6890
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04006891static void pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00006892{
6893 Token *def, *space;
6894 Line *l;
6895
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006896 space = new_White(NULL);
H. Peter Anvin734b1882002-04-30 21:01:08 +00006897 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Keith Kaniosb7a89542007-04-12 02:40:54 +00006898 space->next = tokenize(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00006899
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006900 l = nasm_malloc(sizeof(Line));
H. Peter Anvin620515a2002-04-30 20:57:38 +00006901 l->next = predef;
6902 l->first = def;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006903 l->finishes = NULL;
H. Peter Anvin620515a2002-04-30 20:57:38 +00006904 predef = l;
6905}
6906
H. Peter Anvin05990342018-06-11 13:32:42 -07006907/* Insert an early preprocessor command that doesn't need special handling */
6908static void pp_pre_command(const char *what, char *string)
6909{
6910 char *cmd;
6911 Token *def, *space;
6912 Line *l;
6913
6914 def = tokenize(string);
6915 if (what) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006916 space = new_White(def);
H. Peter Anvin8571f062019-09-23 16:40:03 -07006917 cmd = nasm_strcat(what[0] == '%' ? "" : "%", what);
6918 def = new_Token(space, TOK_PREPROC_ID, cmd, nasm_last_string_len());
6919 nasm_free(cmd);
H. Peter Anvin05990342018-06-11 13:32:42 -07006920 }
6921
6922 l = nasm_malloc(sizeof(Line));
6923 l->next = predef;
6924 l->first = def;
6925 l->finishes = NULL;
6926 predef = l;
6927}
6928
H. Peter Anvinf7606612016-07-13 14:23:48 -07006929static void pp_add_stdmac(macros_t *macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006930{
H. Peter Anvinf7606612016-07-13 14:23:48 -07006931 macros_t **mp;
6932
6933 /* Find the end of the list and avoid duplicates */
6934 for (mp = stdmacros; *mp; mp++) {
6935 if (*mp == macros)
6936 return; /* Nothing to do */
6937 }
6938
6939 nasm_assert(mp < &stdmacros[ARRAY_SIZE(stdmacros)-1]);
6940
6941 *mp = macros;
H. Peter Anvin76690a12002-04-30 20:52:49 +00006942}
6943
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +03006944static void pp_extra_stdmac(macros_t *macros)
6945{
6946 extrastdmac = macros;
6947}
6948
H. Peter Anvin8571f062019-09-23 16:40:03 -07006949/* Create a numeric token */
6950static Token *make_tok_num(Token *next, int64_t val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006951{
Cyrill Gorcunovce652742013-05-06 23:43:43 +04006952 char numbuf[32];
H. Peter Anvin8b262472019-02-26 14:00:54 -08006953 int len = snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
H. Peter Anvin8571f062019-09-23 16:40:03 -07006954 return new_Token(next, TOK_NUMBER, numbuf, len);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006955}
6956
H. Peter Anvin8571f062019-09-23 16:40:03 -07006957/* Create a quoted string token */
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07006958static Token *make_tok_qstr_len(Token *next, const char *str, size_t len)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006959{
H. Peter Anvin8571f062019-09-23 16:40:03 -07006960 char *p = nasm_quote(str, &len);
6961 return new_Token_free(next, TOK_STRING, p, len);
6962}
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07006963static Token *make_tok_qstr(Token *next, const char *str)
6964{
6965 return make_tok_qstr_len(next, str, strlen(str));
6966}
H. Peter Anvin8571f062019-09-23 16:40:03 -07006967
6968/* Create a single-character operator token */
6969static Token *make_tok_char(Token *next, char op)
6970{
6971 Token *t = new_Token(next, TOK_OTHER, NULL, 1);
6972 t->text.a[0] = op;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006973 return t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00006974}
6975
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006976/*
6977 * Descend the istk looking for macro definitions; we have to
6978 * recurse because we want to show the messages in top-down order.
6979 */
6980static void pp_list_macro_istk(Include *inc, errflags severity)
H. Peter Anvin37368952016-05-09 14:10:32 -07006981{
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006982 MMacro *m;
6983 Include *inext;
H. Peter Anvin37368952016-05-09 14:10:32 -07006984
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006985 /* Find the next higher level true macro invocation if any */
6986 inext = inc->next;
6987 if (inext && inext->mstk.mmac) {
6988 while (inext) {
6989 if (inext->mstk.mstk->name) {
6990 pp_list_macro_istk(inext, severity);
6991 break;
6992 }
6993 inext = inext->next;
6994 }
6995 }
H. Peter Anvin37368952016-05-09 14:10:32 -07006996
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006997 m = inc->mstk.mstk;
6998 if (m && m->name && !m->nolist) {
6999 src_update(inc->where);
H. Peter Anvinddb29062018-12-11 00:06:29 -08007000 nasm_error(severity, "... from macro `%s' defined", m->name);
H. Peter Anvin37368952016-05-09 14:10:32 -07007001 }
7002}
7003
H. Peter Anvin (Intel)6bde2ed2018-12-13 19:39:41 -08007004static void pp_error_list_macros(errflags severity)
H. Peter Anvin4def1a82016-05-09 13:59:44 -07007005{
H. Peter Anvinddb29062018-12-11 00:06:29 -08007006 struct src_location saved;
H. Peter Anvin4def1a82016-05-09 13:59:44 -07007007
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07007008 if (!istk)
7009 return;
7010
H. Peter Anvinddb29062018-12-11 00:06:29 -08007011 severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE;
7012 saved = src_where();
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07007013 pp_list_macro_istk(istk, severity);
H. Peter Anvinddb29062018-12-11 00:06:29 -08007014 src_update(saved);
H. Peter Anvin4def1a82016-05-09 13:59:44 -07007015}
7016
H. Peter Anvine7469712016-02-18 02:20:59 -08007017const struct preproc_ops nasmpp = {
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07007018 pp_init,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00007019 pp_reset,
7020 pp_getline,
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08007021 pp_cleanup_pass,
7022 pp_cleanup_session,
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +03007023 pp_extra_stdmac,
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04007024 pp_pre_define,
7025 pp_pre_undefine,
7026 pp_pre_include,
H. Peter Anvin05990342018-06-11 13:32:42 -07007027 pp_pre_command,
H. Peter Anvin4def1a82016-05-09 13:59:44 -07007028 pp_include_path,
7029 pp_error_list_macros,
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07007030 pp_suppress_error
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00007031};