blob: 2165fa121af20b48525c45d82815fab6fa88e0a3 [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
H. Peter Anvin (Intel)65ab3ab2020-06-30 10:14:21 -0700348static inline unused bool
349tok_match(const struct Token *a, const struct Token *b)
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700350{
351 return a->type == b->type && tok_text_match(a, b);
352}
353
H. Peter Anvin8571f062019-09-23 16:40:03 -0700354/* strlen() variant useful for set_text() and its variants */
355static size_t tok_strlen(const char *str)
356{
357 return strnlen(str, MAX_TEXT+1);
358}
359
360/*
361 * Set the text field to a copy of the given string; the length if
362 * not given should be obtained with tok_strlen().
363 */
364static Token *set_text(struct Token *t, const char *text, size_t len)
365{
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700366 char *textp;
367
H. Peter Anvin8571f062019-09-23 16:40:03 -0700368 if (t->len > INLINE_TEXT)
369 nasm_free(t->text.p.ptr);
370
H. Peter Anvin (Intel)00335e42020-06-14 19:49:19 -0700371 nasm_zero(t->text);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700372
H. Peter Anvin (Intel)00335e42020-06-14 19:49:19 -0700373 t->len = len = tok_check_len(len);
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700374 textp = (len > INLINE_TEXT)
375 ? (t->text.p.ptr = nasm_malloc(len+1)) : t->text.a;
376 memcpy(textp, text, len);
377 textp[len] = '\0';
H. Peter Anvin8571f062019-09-23 16:40:03 -0700378 return t;
379}
380
381/*
382 * Set the text field to the existing pre-allocated string, either
383 * taking over or freeing the allocation in the process.
384 */
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700385static Token *set_text_free(struct Token *t, char *text, unsigned int len)
H. Peter Anvin8571f062019-09-23 16:40:03 -0700386{
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700387 char *textp;
388
H. Peter Anvin8571f062019-09-23 16:40:03 -0700389 if (t->len > INLINE_TEXT)
390 nasm_free(t->text.p.ptr);
391
H. Peter Anvin (Intel)00335e42020-06-14 19:49:19 -0700392 nasm_zero(t->text);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700393
H. Peter Anvin (Intel)00335e42020-06-14 19:49:19 -0700394 t->len = len = tok_check_len(len);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700395 if (len > INLINE_TEXT) {
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700396 textp = t->text.p.ptr = text;
H. Peter Anvin8571f062019-09-23 16:40:03 -0700397 } else {
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700398 textp = memcpy(t->text.a, text, len);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700399 nasm_free(text);
400 }
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700401 textp[len] = '\0';
H. Peter Anvin8571f062019-09-23 16:40:03 -0700402
403 return t;
404}
405
406/*
407 * Allocate a new buffer containing a copy of the text field
408 * of the token.
409 */
410static char *dup_text(const struct Token *t)
411{
412 size_t size = t->len + 1;
413 char *p = nasm_malloc(size);
414
415 return memcpy(p, tok_text(t), size);
416}
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000417
418/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800419 * Multi-line macro definitions are stored as a linked list of
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000420 * these, which is essentially a container to allow several linked
421 * lists of Tokens.
H. Peter Anvin70653092007-10-19 14:42:29 -0700422 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000423 * Note that in this module, linked lists are treated as stacks
424 * wherever possible. For this reason, Lines are _pushed_ on to the
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800425 * `expansion' field in MMacro structures, so that the linked list,
426 * if walked, would give the macro lines in reverse order; this
427 * means that we can walk the list when expanding a macro, and thus
428 * push the lines on to the `expansion' field in _istk_ in reverse
429 * order (so that when popped back off they are in the right
430 * order). It may seem cockeyed, and it relies on my design having
431 * an even number of steps in, but it works...
432 *
433 * Some of these structures, rather than being actual lines, are
434 * markers delimiting the end of the expansion of a given macro.
435 * This is for use in the cycle-tracking and %rep-handling code.
436 * Such structures have `finishes' non-NULL, and `first' NULL. All
437 * others have `finishes' NULL, but `first' may still be NULL if
438 * the line is blank.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000439 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000440struct Line {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800441 Line *next;
442 MMacro *finishes;
443 Token *first;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700444 struct src_location where; /* Where defined */
Keith Kaniosb307a4f2010-11-06 17:41:51 -0500445};
446
447/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000448 * To handle an arbitrary level of file inclusion, we maintain a
449 * stack (ie linked list) of these things.
450 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000451struct Include {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800452 Include *next;
453 FILE *fp;
454 Cond *conds;
455 Line *expansion;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700456 struct mstk mstk;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -0700457 struct src_location where; /* Filename and current line number */
458 int32_t lineinc; /* Increment given by %line */
H. Peter Anvin6686de22019-08-10 05:33:14 -0700459 bool nolist;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000460};
461
462/*
H. Peter Anvin169ac7c2016-09-25 17:08:05 -0700463 * File real name hash, so we don't have to re-search the include
464 * path for every pass (and potentially more than that if a file
465 * is used more than once.)
466 */
467struct hash_table FileHash;
468
469/*
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -0700470 * Counters to trap on insane macro recursion or processing.
471 * Note: for smacros these count *down*, for mmacros they count *up*.
472 */
473struct deadman {
474 int64_t total; /* Total number of macros/tokens */
475 int64_t levels; /* Descent depth across all macros */
476 bool triggered; /* Already triggered, no need for error msg */
477};
478
479static struct deadman smacro_deadman, mmacro_deadman;
480
481/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000482 * Conditional assembly: we maintain a separate stack of these for
483 * each level of file inclusion. (The only reason we keep the
484 * stacks separate is to ensure that a stray `%endif' in a file
485 * included from within the true branch of a `%if' won't terminate
486 * it and cause confusion: instead, rightly, it'll cause an error.)
487 */
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -0700488enum cond_state {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000489 /*
490 * These states are for use just after %if or %elif: IF_TRUE
491 * means the condition has evaluated to truth so we are
492 * currently emitting, whereas IF_FALSE means we are not
493 * currently emitting but will start doing so if a %else comes
494 * up. In these states, all directives are admissible: %elif,
495 * %else and %endif. (And of course %if.)
496 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800497 COND_IF_TRUE, COND_IF_FALSE,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000498 /*
499 * These states come up after a %else: ELSE_TRUE means we're
500 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
501 * any %elif or %else will cause an error.
502 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800503 COND_ELSE_TRUE, COND_ELSE_FALSE,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000504 /*
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200505 * These states mean that we're not emitting now, and also that
506 * nothing until %endif will be emitted at all. COND_DONE is
507 * used when we've had our moment of emission
508 * and have now started seeing %elifs. COND_NEVER is used when
509 * the condition construct in question is contained within a
510 * non-emitting branch of a larger condition construct,
511 * or if there is an error.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000512 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800513 COND_DONE, COND_NEVER
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000514};
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -0700515struct Cond {
516 Cond *next;
517 enum cond_state state;
518};
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800519#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000520
H. Peter Anvin70653092007-10-19 14:42:29 -0700521/*
Ed Beroset3ab3f412002-06-11 03:31:49 +0000522 * These defines are used as the possible return values for do_directive
523 */
524#define NO_DIRECTIVE_FOUND 0
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300525#define DIRECTIVE_FOUND 1
Ed Beroset3ab3f412002-06-11 03:31:49 +0000526
Keith Kanios852f1ee2009-07-12 00:19:55 -0500527/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000528 * Condition codes. Note that we use c_ prefix not C_ because C_ is
529 * used in nasm.h for the "real" condition codes. At _this_ level,
530 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
531 * ones, so we need a different enum...
532 */
H. Peter Anvin476d2862007-10-02 22:04:15 -0700533static const char * const conditions[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000534 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
535 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
H. Peter Anvince9be342007-09-12 00:22:29 +0000536 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000537};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700538enum pp_conds {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000539 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
540 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 -0700541 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
542 c_none = -1
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000543};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700544static const enum pp_conds inverse_ccs[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000545 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
546 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 +0000547 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000548};
549
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800550/*
551 * Directive names.
552 */
553/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
554static int is_condition(enum preproc_token arg)
555{
556 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
557}
558
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000559/* For TASM compatibility we need to be able to recognise TASM compatible
560 * conditional compilation directives. Using the NASM pre-processor does
561 * not work, so we look for them specifically from the following list and
562 * then jam in the equivalent NASM directive into the input stream.
563 */
564
H. Peter Anvine2c80182005-01-15 22:15:51 +0000565enum {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000566 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
567 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
568};
569
H. Peter Anvin476d2862007-10-02 22:04:15 -0700570static const char * const tasm_directives[] = {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000571 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
572 "ifndef", "include", "local"
573};
574
575static int StackSize = 4;
H. Peter Anvin6c8b2be2016-05-24 23:46:50 -0700576static const char *StackPointer = "ebp";
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000577static int ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -0800578static int LocalOffset = 0;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000579
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000580static Context *cstk;
581static Include *istk;
Cyrill Gorcunov8c0666b2018-11-24 14:33:48 +0300582static const struct strlist *ipath_list;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000583
Cyrill Gorcunovb7bb5ac2018-11-11 21:33:52 +0300584static struct strlist *deplist;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000585
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300586static uint64_t unique; /* unique identifier numbers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000587
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800588static Line *predef = NULL;
H. Peter Anvind2456592008-06-19 15:04:18 -0700589static bool do_predef;
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800590static enum preproc_mode pp_mode;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000591
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000592/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800593 * The current set of multi-line macros we have defined.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000594 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800595static struct hash_table mmacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000596
597/*
598 * The current set of single-line macros we have defined.
599 */
H. Peter Anvin166c2472008-05-28 12:28:58 -0700600static struct hash_table smacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000601
602/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800603 * The multi-line macro we are currently defining, or the %rep
604 * block we are currently reading, if any.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000605 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800606static MMacro *defining;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000607
Charles Crayned4200be2008-07-12 16:42:33 -0700608static uint64_t nested_mac_count;
609static uint64_t nested_rep_count;
610
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000611/*
612 * The number of macro parameters to allocate space for at a time.
613 */
614#define PARAM_DELTA 16
615
616/*
H. Peter Anvinf7606612016-07-13 14:23:48 -0700617 * The standard macro set: defined in macros.c in a set of arrays.
618 * This gives our position in any macro set, while we are processing it.
619 * The stdmacset is an array of such macro sets.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000620 */
H. Peter Anvina70547f2008-07-19 21:44:26 -0700621static macros_t *stdmacpos;
H. Peter Anvinf7606612016-07-13 14:23:48 -0700622static macros_t **stdmacnext;
623static macros_t *stdmacros[8];
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +0300624static macros_t *extrastdmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000625
626/*
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -0700627 * Map of which %use packages have been loaded
628 */
629static bool *use_loaded;
630
631/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000632 * Forward declarations.
633 */
H. Peter Anvinf7606612016-07-13 14:23:48 -0700634static void pp_add_stdmac(macros_t *macros);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000635static Token *expand_mmac_params(Token * tline);
636static Token *expand_smacro(Token * tline);
637static Token *expand_id(Token * tline);
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +0400638static Context *get_ctx(const char *name, const char **namep);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700639static Token *make_tok_num(Token *next, int64_t val);
640static Token *make_tok_qstr(Token *next, const char *str);
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -0700641static Token *make_tok_qstr_len(Token *next, const char *str, size_t len);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700642static Token *make_tok_char(Token *next, char op);
H. Peter Anvinc751e862008-06-09 10:18:45 -0700643static Token *new_Token(Token * next, enum pp_token_type type,
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -0700644 const char *text, size_t txtlen);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700645static Token *new_Token_free(Token * next, enum pp_token_type type,
646 char *text, size_t txtlen);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -0700647static Token *dup_Token(Token *next, const Token *src);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -0700648static Token *new_White(Token *next);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700649static Token *delete_Token(Token *t);
650static Token *steal_Token(Token *dst, Token *src);
H. Peter Anvindd88aa92019-09-12 19:39:48 -0700651static const struct use_package *
H. Peter Anvin8571f062019-09-23 16:40:03 -0700652get_use_pkg(Token *t, const char *dname, const char **name);
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -0700653static void mark_smac_params(Token *tline, const SMacro *tmpl,
654 enum pp_token_type type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000655
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -0700656/* Safe test for token type, false on x == NULL */
657static inline bool tok_type(const Token *x, enum pp_token_type t)
658{
659 return x && x->type == t;
660}
661
662/* Whitespace token? */
663static inline bool tok_white(const Token *x)
664{
665 return tok_type(x, TOK_WHITESPACE);
666}
667
668/* Skip past any whitespace */
669static inline Token *skip_white(Token *x)
670{
671 while (tok_white(x))
672 x = x->next;
673
674 return x;
675}
676
677/* Delete any whitespace */
678static Token *zap_white(Token *x)
679{
680 while (tok_white(x))
681 x = delete_Token(x);
682
683 return x;
684}
685
H. Peter Anvin8571f062019-09-23 16:40:03 -0700686/*
687 * Single special character tests. The use of & rather than && is intentional; it
688 * tells the compiler that it is safe to access text.a[1] unconditionally; hopefully
689 * a smart compiler should turn it into a 16-bit memory reference.
690 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -0700691static inline bool tok_is(const Token *x, char c)
692{
H. Peter Anvin8571f062019-09-23 16:40:03 -0700693 return x && ((x->text.a[0] == c) & !x->text.a[1]);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -0700694}
695
696/* True if any other kind of token that "c", but not NULL */
697static inline bool tok_isnt(const Token *x, char c)
698{
H. Peter Anvin8571f062019-09-23 16:40:03 -0700699 return x && !((x->text.a[0] == c) & !x->text.a[1]);
700}
701
702/*
703 * Unquote a token if it is a string, and set its type to
704 * TOK_INTERNAL_STRING.
705 */
706static const char *unquote_token(Token *t)
707{
708 if (t->type != TOK_STRING)
709 return tok_text(t);
710
711 t->type = TOK_INTERNAL_STRING;
712
713 if (t->len > INLINE_TEXT) {
714 char *p = t->text.p.ptr;
715
716 t->len = nasm_unquote(p, NULL);
717
718 if (t->len <= INLINE_TEXT) {
719 nasm_zero(t->text.a);
720 memcpy(t->text.a, p, t->len);
721 nasm_free(p);
722 return t->text.a;
723 } else {
724 return p;
725 }
726 } else {
727 t->len = nasm_unquote(t->text.a, NULL);
728 return t->text.a;
729 }
730}
731
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700732/*
733 * Same as unquote_token(), but error out if the resulting string
734 * contains unacceptable control characters.
735 */
H. Peter Anvin8571f062019-09-23 16:40:03 -0700736static const char *unquote_token_cstr(Token *t)
737{
738 if (t->type != TOK_STRING)
739 return tok_text(t);
740
741 t->type = TOK_INTERNAL_STRING;
742
743 if (t->len > INLINE_TEXT) {
744 char *p = t->text.p.ptr;
745
746 t->len = nasm_unquote_cstr(p, NULL);
747
748 if (t->len <= INLINE_TEXT) {
749 nasm_zero(t->text.a);
750 memcpy(t->text.a, p, t->len);
751 nasm_free(p);
752 return t->text.a;
753 } else {
754 return p;
755 }
756 } else {
757 t->len = nasm_unquote_cstr(t->text.a, NULL);
758 return t->text.a;
759 }
760}
761
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700762/*
763 * Convert a TOK_INTERNAL_STRING token to a quoted
764 * TOK_STRING tokens.
765 */
766static Token *quote_any_token(Token *t);
H. Peter Anvin (Intel)65ab3ab2020-06-30 10:14:21 -0700767static inline unused
768Token *quote_token(Token *t)
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700769{
770 if (likely(!tok_is(t, TOK_INTERNAL_STRING)))
771 return t;
772
773 return quote_any_token(t);
774}
775
776/*
777 * Convert *any* kind of token to a quoted
778 * TOK_STRING token.
779 */
780static Token *quote_any_token(Token *t)
H. Peter Anvin8571f062019-09-23 16:40:03 -0700781{
782 size_t len;
783 char *p;
784
785 p = nasm_quote(tok_text(t), &len);
786 t->type = TOK_STRING;
787 return set_text_free(t, p, len);
788}
789
Cyrill Gorcunov194ba892011-06-30 01:16:35 +0400790/*
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700791 * In-place reverse a list of tokens.
792 */
793static Token *reverse_tokens(Token *t)
794{
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800795 Token *prev = NULL;
796 Token *next;
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700797
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800798 while (t) {
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +0400799 next = t->next;
800 t->next = prev;
801 prev = t;
802 t = next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800803 }
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700804
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800805 return prev;
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700806}
807
808/*
H. Peter Anvin8571f062019-09-23 16:40:03 -0700809 * getenv() variant operating on an input token
810 */
811static const char *pp_getenv(const Token *t, bool warn)
812{
813 const char *txt = tok_text(t);
814 const char *v;
815 char *buf = NULL;
816 bool is_string = false;
817
818 if (!t)
819 return NULL;
820
821 switch (t->type) {
822 case TOK_ENVIRON:
823 txt += 2; /* Skip leading %! */
824 is_string = nasm_isquote(*txt);
825 break;
826
827 case TOK_STRING:
828 is_string = true;
829 break;
830
831 case TOK_INTERNAL_STRING:
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700832 case TOK_NAKED_STRING:
H. Peter Anvin8571f062019-09-23 16:40:03 -0700833 case TOK_ID:
834 is_string = false;
835 break;
836
837 default:
838 return NULL;
839 }
840
841 if (is_string) {
842 buf = nasm_strdup(txt);
843 nasm_unquote_cstr(buf, NULL);
844 txt = buf;
845 }
846
847 v = getenv(txt);
848 if (warn && !v) {
849 /*!
850 *!environment [on] nonexistent environment variable
851 *! warns if a nonexistent environment variable
852 *! is accessed using the \c{%!} preprocessor
853 *! construct (see \k{getenv}.) Such environment
854 *! variables are treated as empty (with this
855 *! warning issued) starting in NASM 2.15;
856 *! earlier versions of NASM would treat this as
857 *! an error.
858 */
859 nasm_warn(WARN_ENVIRONMENT, "nonexistent environment variable `%s'", txt);
860 v = "";
861 }
862
863 if (buf)
864 nasm_free(buf);
865
866 return v;
867}
868
869/*
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300870 * Handle TASM specific directives, which do not contain a % in
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000871 * front of them. We do it here because I could not find any other
872 * place to do it for the moment, and it is a hack (ideally it would
873 * be nice to be able to use the NASM pre-processor to do it).
874 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000875static char *check_tasm_directive(char *line)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000876{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000877 int32_t i, j, k, m, len;
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400878 char *p, *q, *oldline, oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000879
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400880 p = nasm_skip_spaces(line);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000881
882 /* Binary search for the directive name */
883 i = -1;
Cyrill Gorcunova7319242010-06-03 22:04:36 +0400884 j = ARRAY_SIZE(tasm_directives);
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400885 q = nasm_skip_word(p);
886 len = q - p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000887 if (len) {
888 oldchar = p[len];
889 p[len] = 0;
890 while (j - i > 1) {
891 k = (j + i) / 2;
892 m = nasm_stricmp(p, tasm_directives[k]);
893 if (m == 0) {
894 /* We have found a directive, so jam a % in front of it
895 * so that NASM will then recognise it as one if it's own.
896 */
897 p[len] = oldchar;
898 len = strlen(p);
899 oldline = line;
900 line = nasm_malloc(len + 2);
901 line[0] = '%';
902 if (k == TM_IFDIFI) {
H. Peter Anvin18f48792009-06-27 15:56:27 -0700903 /*
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300904 * NASM does not recognise IFDIFI, so we convert
905 * it to %if 0. This is not used in NASM
906 * compatible code, but does need to parse for the
907 * TASM macro package.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000908 */
H. Peter Anvin18f48792009-06-27 15:56:27 -0700909 strcpy(line + 1, "if 0");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000910 } else {
911 memcpy(line + 1, p, len + 1);
912 }
913 nasm_free(oldline);
914 return line;
915 } else if (m < 0) {
916 j = k;
917 } else
918 i = k;
919 }
920 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000921 }
922 return line;
923}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000924
H. Peter Anvin76690a12002-04-30 20:52:49 +0000925/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000926 * The pre-preprocessing stage... This function translates line
927 * number indications as they emerge from GNU cpp (`# lineno "file"
928 * flags') into NASM preprocessor line number indications (`%line
929 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000930 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000931static char *prepreproc(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000932{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000933 int lineno, fnlen;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000934 char *fname, *oldline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000935
H. Peter Anvine2c80182005-01-15 22:15:51 +0000936 if (line[0] == '#' && line[1] == ' ') {
937 oldline = line;
938 fname = oldline + 2;
939 lineno = atoi(fname);
940 fname += strspn(fname, "0123456789 ");
941 if (*fname == '"')
942 fname++;
943 fnlen = strcspn(fname, "\"");
944 line = nasm_malloc(20 + fnlen);
945 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
946 nasm_free(oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000947 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000948 if (tasm_compatible_mode)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000949 return check_tasm_directive(line);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000950 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000951}
952
953/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000954 * Free a linked list of tokens.
955 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000956static void free_tlist(Token * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000957{
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400958 while (list)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000959 list = delete_Token(list);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000960}
961
962/*
963 * Free a linked list of lines.
964 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000965static void free_llist(Line * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000966{
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400967 Line *l, *tmp;
968 list_for_each_safe(l, tmp, list) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000969 free_tlist(l->first);
970 nasm_free(l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000971 }
972}
973
974/*
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -0700975 * Free an array of linked lists of tokens
976 */
977static void free_tlist_array(Token **array, size_t nlists)
978{
979 Token **listp = array;
980
981 while (nlists--)
982 free_tlist(*listp++);
983
984 nasm_free(array);
985}
986
987/*
988 * Duplicate a linked list of tokens.
989 */
990static Token *dup_tlist(const Token *list, Token ***tailp)
991{
992 Token *newlist = NULL;
993 Token **tailpp = &newlist;
994 const Token *t;
995
996 list_for_each(t, list) {
997 Token *nt;
998 *tailpp = nt = dup_Token(NULL, t);
999 tailpp = &nt->next;
1000 }
1001
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001002 if (tailp) {
1003 **tailp = newlist;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07001004 *tailp = tailpp;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001005 }
1006
1007 return newlist;
1008}
1009
1010/*
1011 * Duplicate a linked list of tokens with a maximum count
1012 */
1013static Token *dup_tlistn(const Token *list, size_t cnt, Token ***tailp)
1014{
1015 Token *newlist = NULL;
1016 Token **tailpp = &newlist;
1017 const Token *t;
1018
1019 list_for_each(t, list) {
1020 Token *nt;
1021 if (!cnt--)
1022 break;
1023 *tailpp = nt = dup_Token(NULL, t);
1024 tailpp = &nt->next;
1025 }
1026
1027 if (tailp) {
1028 **tailp = newlist;
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07001029 if (newlist)
1030 *tailp = tailpp;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001031 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07001032
1033 return newlist;
1034}
1035
1036/*
1037 * Duplicate a linked list of tokens in reverse order
1038 */
1039static Token *dup_tlist_reverse(const Token *list, Token *tail)
1040{
1041 const Token *t;
1042
1043 list_for_each(t, list)
1044 tail = dup_Token(tail, t);
1045
1046 return tail;
1047}
1048
1049/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001050 * Free an MMacro
H. Peter Anvineba20a72002-04-30 20:53:55 +00001051 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001052static void free_mmacro(MMacro * m)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001053{
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001054 nasm_free(m->name);
1055 free_tlist(m->dlist);
1056 nasm_free(m->defaults);
1057 free_llist(m->expansion);
1058 nasm_free(m);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001059}
1060
1061/*
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001062 * Clear or free an SMacro
H. Peter Anvin8b262472019-02-26 14:00:54 -08001063 */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001064static void free_smacro_members(SMacro *s)
H. Peter Anvin8b262472019-02-26 14:00:54 -08001065{
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07001066 if (s->params) {
1067 int i;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001068 for (i = 0; i < s->nparam; i++) {
1069 if (s->params[i].name.len > INLINE_TEXT)
1070 nasm_free(s->params[i].name.text.p.ptr);
1071 }
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07001072 nasm_free(s->params);
1073 }
H. Peter Anvin8b262472019-02-26 14:00:54 -08001074 nasm_free(s->name);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001075 free_tlist(s->expansion);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001076}
1077
1078static void clear_smacro(SMacro *s)
1079{
1080 free_smacro_members(s);
1081 /* Wipe everything except the next pointer */
1082 memset(&s->next + 1, 0, sizeof *s - sizeof s->next);
1083}
1084
1085/*
1086 * Free an SMacro
1087 */
1088static void free_smacro(SMacro *s)
1089{
1090 free_smacro_members(s);
1091 nasm_free(s);
H. Peter Anvin8b262472019-02-26 14:00:54 -08001092}
1093
1094/*
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001095 * Free all currently defined macros, and free the hash tables if empty
H. Peter Anvin97a23472007-09-16 17:57:25 -07001096 */
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001097enum clear_what {
1098 CLEAR_NONE = 0,
1099 CLEAR_DEFINE = 1, /* Clear smacros */
1100 CLEAR_DEFALIAS = 2, /* Clear smacro aliases */
1101 CLEAR_ALLDEFINE = CLEAR_DEFINE|CLEAR_DEFALIAS,
1102 CLEAR_MMACRO = 4,
1103 CLEAR_ALL = CLEAR_ALLDEFINE|CLEAR_MMACRO
1104};
1105
1106static void clear_smacro_table(struct hash_table *smt, enum clear_what what)
H. Peter Anvin97a23472007-09-16 17:57:25 -07001107{
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001108 struct hash_iterator it;
1109 const struct hash_node *np;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001110 bool empty = true;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001111
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001112 /*
1113 * Walk the hash table and clear out anything we don't want
1114 */
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001115 hash_for_each(smt, it, np) {
1116 SMacro *tmp;
1117 SMacro *s = np->data;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001118 SMacro **head = (SMacro **)&np->data;
1119
1120 list_for_each_safe(s, tmp, s) {
1121 if (what & ((enum clear_what)s->alias + 1)) {
1122 *head = s->next;
1123 free_smacro(s);
1124 } else {
1125 empty = false;
1126 }
1127 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07001128 }
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001129
1130 /*
1131 * Free the hash table and keys if and only if it is now empty.
1132 * Note: we cannot free keys even for an empty list above, as that
1133 * mucks up the hash algorithm.
1134 */
1135 if (empty)
1136 hash_free_all(smt, true);
1137}
1138
1139static void free_smacro_table(struct hash_table *smt)
1140{
1141 clear_smacro_table(smt, CLEAR_ALLDEFINE);
H. Peter Anvin072771e2008-05-22 13:17:51 -07001142}
1143
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001144static void free_mmacro_table(struct hash_table *mmt)
H. Peter Anvin072771e2008-05-22 13:17:51 -07001145{
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001146 struct hash_iterator it;
1147 const struct hash_node *np;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001148
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001149 hash_for_each(mmt, it, np) {
1150 MMacro *tmp;
1151 MMacro *m = np->data;
1152 nasm_free((void *)np->key);
1153 list_for_each_safe(m, tmp, m)
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001154 free_mmacro(m);
H. Peter Anvin97a23472007-09-16 17:57:25 -07001155 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001156 hash_free(mmt);
H. Peter Anvin072771e2008-05-22 13:17:51 -07001157}
1158
1159static void free_macros(void)
1160{
H. Peter Anvin166c2472008-05-28 12:28:58 -07001161 free_smacro_table(&smacros);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001162 free_mmacro_table(&mmacros);
H. Peter Anvin97a23472007-09-16 17:57:25 -07001163}
1164
1165/*
1166 * Initialize the hash tables
1167 */
1168static void init_macros(void)
1169{
H. Peter Anvin97a23472007-09-16 17:57:25 -07001170}
1171
1172/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001173 * Pop the context stack.
1174 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001175static void ctx_pop(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001176{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001177 Context *c = cstk;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001178
1179 cstk = cstk->next;
H. Peter Anvin166c2472008-05-28 12:28:58 -07001180 free_smacro_table(&c->localmac);
H. Peter Anvin8571f062019-09-23 16:40:03 -07001181 nasm_free((char *)c->name);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001182 nasm_free(c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001183}
1184
H. Peter Anvin072771e2008-05-22 13:17:51 -07001185/*
1186 * Search for a key in the hash index; adding it if necessary
1187 * (in which case we initialize the data pointer to NULL.)
1188 */
1189static void **
1190hash_findi_add(struct hash_table *hash, const char *str)
1191{
1192 struct hash_insert hi;
1193 void **r;
1194 char *strx;
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001195 size_t l = strlen(str) + 1;
H. Peter Anvin072771e2008-05-22 13:17:51 -07001196
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001197 r = hash_findib(hash, str, l, &hi);
H. Peter Anvin072771e2008-05-22 13:17:51 -07001198 if (r)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001199 return r;
H. Peter Anvin072771e2008-05-22 13:17:51 -07001200
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001201 strx = nasm_malloc(l); /* Use a more efficient allocator here? */
1202 memcpy(strx, str, l);
H. Peter Anvin072771e2008-05-22 13:17:51 -07001203 return hash_add(&hi, strx, NULL);
1204}
1205
1206/*
1207 * Like hash_findi, but returns the data element rather than a pointer
1208 * to it. Used only when not adding a new element, hence no third
1209 * argument.
1210 */
1211static void *
1212hash_findix(struct hash_table *hash, const char *str)
1213{
1214 void **p;
1215
1216 p = hash_findi(hash, str, NULL);
1217 return p ? *p : NULL;
1218}
1219
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001220/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001221 * read line from standart macros set,
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001222 * if there no more left -- return NULL
1223 */
1224static char *line_from_stdmac(void)
1225{
1226 unsigned char c;
1227 const unsigned char *p = stdmacpos;
1228 char *line, *q;
1229 size_t len = 0;
1230
1231 if (!stdmacpos)
1232 return NULL;
1233
H. Peter Anvin (Intel)6d5c77c2019-08-15 02:29:40 -07001234 /*
1235 * 32-126 is ASCII, 127 is end of line, 128-31 are directives
1236 * (allowed to wrap around) corresponding to PP_* tokens 0-159.
1237 */
1238 while ((c = *p++) != 127) {
1239 uint8_t ndir = c - 128;
1240 if (ndir < 256-96)
1241 len += pp_directives_len[ndir] + 1;
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001242 else
1243 len++;
1244 }
1245
1246 line = nasm_malloc(len + 1);
1247 q = line;
H. Peter Anvin (Intel)6d5c77c2019-08-15 02:29:40 -07001248
1249 while ((c = *stdmacpos++) != 127) {
1250 uint8_t ndir = c - 128;
1251 if (ndir < 256-96) {
1252 memcpy(q, pp_directives[ndir], pp_directives_len[ndir]);
1253 q += pp_directives_len[ndir];
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001254 *q++ = ' ';
1255 } else {
1256 *q++ = c;
1257 }
1258 }
1259 stdmacpos = p;
1260 *q = '\0';
1261
H. Peter Anvin (Intel)6d5c77c2019-08-15 02:29:40 -07001262 if (*stdmacpos == 127) {
H. Peter Anvinf7606612016-07-13 14:23:48 -07001263 /* This was the last of this particular macro set */
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001264 stdmacpos = NULL;
H. Peter Anvinf7606612016-07-13 14:23:48 -07001265 if (*stdmacnext) {
1266 stdmacpos = *stdmacnext++;
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001267 } else if (do_predef) {
1268 Line *pd, *l;
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001269
1270 /*
1271 * Nasty hack: here we push the contents of
1272 * `predef' on to the top-level expansion stack,
1273 * since this is the most convenient way to
1274 * implement the pre-include and pre-define
1275 * features.
1276 */
1277 list_for_each(pd, predef) {
H. Peter Anvin6686de22019-08-10 05:33:14 -07001278 nasm_new(l);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001279 l->next = istk->expansion;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07001280 l->first = dup_tlist(pd->first, NULL);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001281 l->finishes = NULL;
1282
1283 istk->expansion = l;
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001284 }
1285 do_predef = false;
1286 }
1287 }
1288
1289 return line;
1290}
1291
H. Peter Anvin6686de22019-08-10 05:33:14 -07001292/*
1293 * Read a line from a file. Return NULL on end of file.
1294 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001295static char *line_from_file(FILE *f)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001296{
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001297 int c;
1298 unsigned int size, next;
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001299 const unsigned int delta = 512;
1300 const unsigned int pad = 8;
1301 unsigned int nr_cont = 0;
1302 bool cont = false;
1303 char *buffer, *p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001304
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001305 size = delta;
1306 p = buffer = nasm_malloc(size);
1307
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001308 do {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001309 c = fgetc(f);
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001310
1311 switch (c) {
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001312 case EOF:
1313 if (p == buffer) {
1314 nasm_free(buffer);
1315 return NULL;
1316 }
1317 c = 0;
1318 break;
1319
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001320 case '\r':
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001321 next = fgetc(f);
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001322 if (next != '\n')
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001323 ungetc(next, f);
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001324 if (cont) {
1325 cont = false;
1326 continue;
1327 }
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001328 c = 0;
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001329 break;
1330
1331 case '\n':
1332 if (cont) {
1333 cont = false;
1334 continue;
1335 }
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001336 c = 0;
1337 break;
1338
1339 case 032: /* ^Z = legacy MS-DOS end of file mark */
1340 c = 0;
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001341 break;
1342
1343 case '\\':
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001344 next = fgetc(f);
1345 ungetc(next, f);
Cyrill Gorcunov490f85e2012-12-27 20:02:17 +04001346 if (next == '\r' || next == '\n') {
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001347 cont = true;
1348 nr_cont++;
1349 continue;
1350 }
1351 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001352 }
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001353
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001354 if (p >= (buffer + size - pad)) {
1355 buffer = nasm_realloc(buffer, size + delta);
1356 p = buffer + size - pad;
1357 size += delta;
1358 }
1359
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001360 *p++ = c;
1361 } while (c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001362
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07001363 istk->where.lineno += (nr_cont + 1) * istk->lineinc;
1364 src_set_linnum(istk->where.lineno);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001365
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001366 return buffer;
1367}
1368
1369/*
H. Peter Anvin6686de22019-08-10 05:33:14 -07001370 * Common read routine regardless of source
1371 */
1372static char *read_line(void)
1373{
1374 char *line;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001375 FILE *f = istk->fp;
H. Peter Anvin6686de22019-08-10 05:33:14 -07001376
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001377 if (f)
1378 line = line_from_file(f);
H. Peter Anvin6686de22019-08-10 05:33:14 -07001379 else
1380 line = line_from_stdmac();
1381
1382 if (!line)
1383 return NULL;
1384
1385 if (!istk->nolist)
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07001386 lfmt->line(LIST_READ, istk->where.lineno, line);
H. Peter Anvin6686de22019-08-10 05:33:14 -07001387
1388 return line;
1389}
1390
1391/*
Keith Kaniosb7a89542007-04-12 02:40:54 +00001392 * Tokenize a line of text. This is a very simple process since we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001393 * don't need to parse the value out of e.g. numeric tokens: we
1394 * simply split one string into many.
1395 */
H. Peter Anvin8571f062019-09-23 16:40:03 -07001396static Token *tokenize(const char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001397{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001398 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001399 Token *list = NULL;
1400 Token *t, **tail = &list;
1401
H. Peter Anvine2c80182005-01-15 22:15:51 +00001402 while (*line) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001403 const char *p = line;
1404 const char *ep = NULL; /* End of token, for trimming the end */
1405 size_t toklen;
1406 char firstchar = *p; /* Can be used to override the first char */
H. Peter Anvin (Intel)98031bf2019-08-09 16:11:28 -07001407
H. Peter Anvine2c80182005-01-15 22:15:51 +00001408 if (*p == '%') {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001409 /*
1410 * Preprocessor construct; find the end of the token.
1411 * Classification is handled later, because %{...} can be
1412 * used to create any preprocessor token.
1413 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001414 p++;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001415 if (*p == '+' && !nasm_isdigit(p[1])) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001416 /* Paste token */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001417 p++;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001418 } else if (nasm_isdigit(*p) ||
1419 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001420 do {
1421 p++;
1422 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001423 while (nasm_isdigit(*p));
H. Peter Anvin8571f062019-09-23 16:40:03 -07001424 } else if (*p == '{' || *p == '[') {
1425 /* %{...} or %[...] */
1426 char firstchar = *p;
1427 char endchar = *p + 2; /* } or ] */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001428 int lvl = 1;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001429 line += (*p++ == '{'); /* Skip { but not [ (yet) */
1430 while (lvl) {
1431 if (*p == firstchar) {
1432 lvl++;
1433 } else if (*p == endchar) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001434 lvl--;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001435 } else if (nasm_isquote(*p)) {
1436 p = nasm_skip_string(p);
1437 }
1438
1439 /*
1440 * *p can have been advanced to a null character by
1441 * nasm_skip_string()
1442 */
1443 if (!*p) {
1444 nasm_warn(WARN_OTHER, "unterminated %%%c construct",
1445 firstchar);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001446 break;
1447 }
H. Peter Anvin (Intel)98031bf2019-08-09 16:11:28 -07001448 p++;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001449 }
1450 ep = lvl ? p : p-1; /* Terminal character not part of token */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001451 } else if (*p == '?') {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001452 /* %? or %?? */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001453 p++;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001454 if (*p == '?')
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001455 p++;
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001456 } else if (*p == '!') {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001457 /* Environment variable reference */
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001458 p++;
H. Peter Anvin13506202018-11-28 14:55:58 -08001459 if (nasm_isidchar(*p)) {
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001460 do {
1461 p++;
1462 }
H. Peter Anvin13506202018-11-28 14:55:58 -08001463 while (nasm_isidchar(*p));
H. Peter Anvin53e2e4c2018-11-28 15:01:40 -08001464 } else if (nasm_isquote(*p)) {
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001465 p = nasm_skip_string(p);
1466 if (*p)
1467 p++;
1468 else
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03001469 nasm_nonfatalf(ERR_PASS1, "unterminated %%! string");
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001470 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001471 /* %! without anything else... */
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001472 }
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07001473 } else if (*p == ',') {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001474 /* Conditional comma */
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07001475 p++;
H. Peter Anvin13506202018-11-28 14:55:58 -08001476 } else if (nasm_isidchar(*p) ||
H. Peter Anvin8571f062019-09-23 16:40:03 -07001477 ((*p == '%' || *p == '$') && nasm_isidchar(p[1]))) {
1478 /* Identifier or some sort */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001479 do {
1480 p++;
1481 }
H. Peter Anvin13506202018-11-28 14:55:58 -08001482 while (nasm_isidchar(*p));
H. Peter Anvin8571f062019-09-23 16:40:03 -07001483 } else if (*p == '%') {
1484 /* %% operator */
1485 p++;
1486 }
1487
1488 if (!ep)
1489 ep = p;
1490 toklen = ep - line;
1491
1492 /* Classify here, to handle %{...} correctly */
1493 if (toklen < 2) {
1494 type = TOK_OTHER; /* % operator */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001495 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001496 char c0 = line[1];
1497
1498 switch (c0) {
1499 case '+':
1500 type = (toklen == 2) ? TOK_PASTE : TOK_MMACRO_PARAM;
1501 break;
1502
1503 case '-':
1504 type = TOK_MMACRO_PARAM;
1505 break;
1506
1507 case '?':
1508 if (toklen == 2)
1509 type = TOK_PREPROC_Q;
1510 else if (toklen == 3 && line[2] == '?')
1511 type = TOK_PREPROC_QQ;
1512 else
1513 type = TOK_PREPROC_ID;
1514 break;
1515
1516 case '!':
1517 type = (toklen == 2) ? TOK_OTHER : TOK_ENVIRON;
1518 break;
1519
1520 case '%':
1521 type = (toklen == 2) ? TOK_OTHER : TOK_LOCAL_SYMBOL;
1522 break;
1523
1524 case '$':
1525 type = (toklen == 2) ? TOK_OTHER : TOK_LOCAL_MACRO;
1526 break;
1527
1528 case '[':
1529 line += 2; /* Skip %[ */
1530 firstchar = *line; /* Don't clobber */
1531 toklen -= 2;
1532 type = TOK_INDIRECT;
1533 break;
1534
1535 case ',':
1536 type = (toklen == 2) ? TOK_COND_COMMA : TOK_PREPROC_ID;
1537 break;
1538
1539 case '\'':
1540 case '\"':
1541 case '`':
1542 /* %{'string'} */
1543 type = TOK_PREPROC_ID;
1544 break;
1545
1546 case ':':
1547 type = TOK_MMACRO_PARAM; /* %{:..} */
1548 break;
1549
1550 default:
1551 if (nasm_isdigit(c0))
1552 type = TOK_MMACRO_PARAM;
1553 else if (nasm_isidchar(c0) || toklen > 2)
1554 type = TOK_PREPROC_ID;
1555 else
1556 type = TOK_OTHER;
1557 break;
1558 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001559 }
H. Peter Anvin13506202018-11-28 14:55:58 -08001560 } else if (nasm_isidstart(*p) || (*p == '$' && nasm_isidstart(p[1]))) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001561 /*
1562 * An identifier. This includes the ? operator, which is
1563 * treated as a keyword, not as a special character
1564 * operator
1565 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001566 type = TOK_ID;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001567 while (nasm_isidchar(*++p))
1568 ;
1569 } else if (nasm_isquote(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001570 /*
1571 * A string token.
1572 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001573 type = TOK_STRING;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001574 p = nasm_skip_string(p);
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001575
H. Peter Anvine2c80182005-01-15 22:15:51 +00001576 if (*p) {
1577 p++;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001578 } else {
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08001579 nasm_warn(WARN_OTHER, "unterminated string");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001580 /* Handling unterminated strings by UNV */
1581 /* type = -1; */
1582 }
Victor van den Elzenfb5f2512009-04-17 16:17:59 +02001583 } else if (p[0] == '$' && p[1] == '$') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001584 type = TOK_OTHER; /* TOKEN_BASE */
Victor van den Elzenfb5f2512009-04-17 16:17:59 +02001585 p += 2;
H. Peter Anvin13506202018-11-28 14:55:58 -08001586 } else if (nasm_isnumstart(*p)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001587 bool is_hex = false;
1588 bool is_float = false;
1589 bool has_e = false;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001590 char c;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001591
H. Peter Anvine2c80182005-01-15 22:15:51 +00001592 /*
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001593 * A numeric token.
H. Peter Anvine2c80182005-01-15 22:15:51 +00001594 */
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001595
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001596 if (*p == '$') {
1597 p++;
1598 is_hex = true;
1599 }
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001600
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001601 for (;;) {
1602 c = *p++;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001603
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001604 if (!is_hex && (c == 'e' || c == 'E')) {
1605 has_e = true;
1606 if (*p == '+' || *p == '-') {
1607 /*
1608 * e can only be followed by +/- if it is either a
1609 * prefixed hex number or a floating-point number
1610 */
1611 p++;
1612 is_float = true;
1613 }
1614 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
1615 is_hex = true;
1616 } else if (c == 'P' || c == 'p') {
1617 is_float = true;
1618 if (*p == '+' || *p == '-')
1619 p++;
H. Peter Anvin13506202018-11-28 14:55:58 -08001620 } else if (nasm_isnumchar(c))
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001621 ; /* just advance */
1622 else if (c == '.') {
1623 /*
1624 * we need to deal with consequences of the legacy
1625 * parser, like "1.nolist" being two tokens
1626 * (TOK_NUMBER, TOK_ID) here; at least give it
1627 * a shot for now. In the future, we probably need
1628 * a flex-based scanner with proper pattern matching
1629 * to do it as well as it can be done. Nothing in
1630 * the world is going to help the person who wants
1631 * 0x123.p16 interpreted as two tokens, though.
1632 */
H. Peter Anvin8571f062019-09-23 16:40:03 -07001633 const char *r = p;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001634 while (*r == '_')
1635 r++;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001636
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001637 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
1638 (!is_hex && (*r == 'e' || *r == 'E')) ||
1639 (*r == 'p' || *r == 'P')) {
1640 p = r;
1641 is_float = true;
1642 } else
1643 break; /* Terminate the token */
1644 } else
1645 break;
1646 }
1647 p--; /* Point to first character beyond number */
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001648
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001649 if (p == line+1 && *line == '$') {
1650 type = TOK_OTHER; /* TOKEN_HERE */
1651 } else {
1652 if (has_e && !is_hex) {
1653 /* 1e13 is floating-point, but 1e13h is not */
1654 is_float = true;
1655 }
H. Peter Anvind784a082009-04-20 14:01:18 -07001656
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001657 type = is_float ? TOK_FLOAT : TOK_NUMBER;
1658 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001659 } else if (nasm_isspace(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001660 type = TOK_WHITESPACE;
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +04001661 p = nasm_skip_spaces(p);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001662 /*
1663 * Whitespace just before end-of-line is discarded by
1664 * pretending it's a comment; whitespace just before a
1665 * comment gets lumped into the comment.
1666 */
1667 if (!*p || *p == ';') {
1668 type = TOK_COMMENT;
1669 while (*p)
1670 p++;
1671 }
1672 } else if (*p == ';') {
1673 type = TOK_COMMENT;
1674 while (*p)
1675 p++;
1676 } else {
1677 /*
1678 * Anything else is an operator of some kind. We check
1679 * for all the double-character operators (>>, <<, //,
H. Peter Anvin8571f062019-09-23 16:40:03 -07001680 * %%, <=, >=, ==, !=, <>, &&, ||, ^^) and the triple-
1681 * character operators (<<<, >>>, <=>) but anything
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001682 * else is a single-character operator.
H. Peter Anvine2c80182005-01-15 22:15:51 +00001683 */
1684 type = TOK_OTHER;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001685 switch (*p++) {
1686 case '>':
1687 if (*p == '>') {
1688 p++;
1689 if (*p == '>')
1690 p++;
H. Peter Anvind03a6c82019-10-07 21:29:05 -07001691 } else if (*p == '=') {
1692 p++;
1693 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07001694 break;
1695
1696 case '<':
1697 if (*p == '<') {
1698 p++;
1699 if (*p == '<')
1700 p++;
1701 } else if (*p == '=') {
1702 p++;
1703 if (*p == '>')
1704 p++;
1705 } else if (*p == '>') {
1706 p++;
1707 }
1708 break;
1709
1710 case '!':
1711 if (*p == '=')
1712 p++;
1713 break;
1714
1715 case '/':
1716 case '=':
1717 case '&':
1718 case '|':
1719 case '^':
1720 /* These operators can be doubled but nothing else */
1721 if (*p == p[-1])
1722 p++;
1723 break;
1724
1725 default:
1726 break;
1727 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001728 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001729
H. Peter Anvin8571f062019-09-23 16:40:03 -07001730 if (type == TOK_WHITESPACE) {
1731 *tail = t = new_White(NULL);
1732 tail = &t->next;
1733 } else if (type != TOK_COMMENT) {
H. Peter Anvin (Intel)98031bf2019-08-09 16:11:28 -07001734 if (!ep)
1735 ep = p;
1736 *tail = t = new_Token(NULL, type, line, ep - line);
H. Peter Anvin8571f062019-09-23 16:40:03 -07001737 *tok_text_buf(t) = firstchar; /* E.g. %{foo} -> {foo -> %foo */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001738 tail = &t->next;
1739 }
1740 line = p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001741 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001742 return list;
1743}
1744
H. Peter Anvin8571f062019-09-23 16:40:03 -07001745/*
1746 * Tokens are allocated in blocks to improve speed. Set the blocksize
1747 * to 0 to use regular nasm_malloc(); this is useful for debugging.
1748 *
1749 * alloc_Token() returns a zero-initialized token structure.
1750 */
1751#define TOKEN_BLOCKSIZE 4096
1752
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001753#if TOKEN_BLOCKSIZE
H. Peter Anvin8571f062019-09-23 16:40:03 -07001754
1755static Token *freeTokens = NULL;
1756static Token *tokenblocks = NULL;
1757
1758static Token *alloc_Token(void)
H. Peter Anvince616072002-04-30 21:02:23 +00001759{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001760 Token *t = freeTokens;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001761
H. Peter Anvin8571f062019-09-23 16:40:03 -07001762 if (unlikely(!t)) {
1763 Token *block;
1764 size_t i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001765
H. Peter Anvin8571f062019-09-23 16:40:03 -07001766 nasm_newn(block, TOKEN_BLOCKSIZE);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001767
H. Peter Anvin8571f062019-09-23 16:40:03 -07001768 /*
1769 * The first entry in each array are a linked list of
1770 * block allocations and is not used for data.
1771 */
1772 block[0].next = tokenblocks;
1773 block[0].type = TOK_BLOCK;
1774 tokenblocks = block;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001775
H. Peter Anvin8571f062019-09-23 16:40:03 -07001776 /*
1777 * Add the rest to the free list
1778 */
1779 for (i = 2; i < TOKEN_BLOCKSIZE - 1; i++)
1780 block[i].next = &block[i+1];
1781
1782 freeTokens = &block[2];
1783
1784 /*
1785 * Return the topmost usable token
1786 */
1787 return &block[1];
1788 }
1789
1790 freeTokens = t->next;
1791 t->next = NULL;
1792 return t;
H. Peter Anvince616072002-04-30 21:02:23 +00001793}
1794
H. Peter Anvin8571f062019-09-23 16:40:03 -07001795static Token *delete_Token(Token *t)
1796{
1797 Token *next = t->next;
1798
1799 nasm_zero(*t);
1800 t->next = freeTokens;
1801 freeTokens = t;
1802
1803 return next;
1804}
1805
H. Peter Anvine2c80182005-01-15 22:15:51 +00001806static void delete_Blocks(void)
H. Peter Anvince616072002-04-30 21:02:23 +00001807{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001808 Token *block, *blocktmp;
H. Peter Anvince616072002-04-30 21:02:23 +00001809
H. Peter Anvin8571f062019-09-23 16:40:03 -07001810 list_for_each_safe(block, blocktmp, tokenblocks)
1811 nasm_free(block);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001812
H. Peter Anvin8571f062019-09-23 16:40:03 -07001813 freeTokens = tokenblocks = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001814}
H. Peter Anvin734b1882002-04-30 21:01:08 +00001815
H. Peter Anvin8571f062019-09-23 16:40:03 -07001816#else
1817
1818static inline Token *alloc_Token(void)
1819{
1820 Token *t;
1821 nasm_new(*t);
1822 return t;
1823}
1824
1825static Token *delete_Token(Token *t)
1826{
1827 Token *next = t->next;
1828 nasm_free(t);
1829 return next;
1830}
1831
1832static inline void delete_Blocks(void)
1833{
1834 /* Nothing to do */
1835}
1836
1837#endif
1838
H. Peter Anvin734b1882002-04-30 21:01:08 +00001839/*
H. Peter Anvin70653092007-10-19 14:42:29 -07001840 * this function creates a new Token and passes a pointer to it
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001841 * back to the caller. It sets the type, text, and next pointer elements.
H. Peter Anvin734b1882002-04-30 21:01:08 +00001842 */
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001843static Token *new_Token(Token * next, enum pp_token_type type,
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001844 const char *text, size_t txtlen)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001845{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001846 Token *t = alloc_Token();
1847 char *textp;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001848
H. Peter Anvin734b1882002-04-30 21:01:08 +00001849 t->next = next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001850 t->type = type;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001851 if (type == TOK_WHITESPACE) {
1852 t->len = 1;
1853 t->text.a[0] = ' ';
H. Peter Anvine2c80182005-01-15 22:15:51 +00001854 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001855 if (text && text[0] && !txtlen)
1856 txtlen = tok_strlen(text);
1857
1858 t->len = tok_check_len(txtlen);
1859
1860 if (text) {
1861 textp = (txtlen > INLINE_TEXT)
1862 ? (t->text.p.ptr = nasm_malloc(txtlen+1)) : t->text.a;
1863 memcpy(textp, text, txtlen);
1864 textp[txtlen] = '\0'; /* In case we needed malloc() */
1865 } else {
1866 /*
1867 * Allocate a buffer but do not fill it. The caller
1868 * can fill in text, but must not change the length.
1869 * The filled in text must be exactly txtlen once
1870 * the buffer is filled and before the token is added
1871 * to any line lists.
1872 */
1873 if (txtlen > INLINE_TEXT)
1874 t->text.p.ptr = nasm_zalloc(txtlen+1);
1875 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001876 }
1877 return t;
1878}
1879
H. Peter Anvin8571f062019-09-23 16:40:03 -07001880/*
1881 * Same as new_Token(), but text belongs to the new token and is
1882 * either taken over or freed. This function MUST be called
1883 * with valid txt and txtlen, unlike new_Token().
1884 */
1885static Token *new_Token_free(Token * next, enum pp_token_type type,
1886 char *text, size_t txtlen)
1887{
1888 Token *t = alloc_Token();
1889
1890 t->next = next;
1891 t->type = type;
1892 t->len = tok_check_len(txtlen);
1893
1894 if (txtlen <= INLINE_TEXT) {
1895 memcpy(t->text.a, text, txtlen);
1896 free(text);
1897 } else {
1898 t->text.p.ptr = text;
1899 }
1900
1901 return t;
1902}
1903
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001904static Token *dup_Token(Token *next, const Token *src)
1905{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001906 Token *t = alloc_Token();
1907
1908 memcpy(t, src, sizeof *src);
1909 t->next = next;
1910
1911 if (t->len > INLINE_TEXT) {
1912 t->text.p.ptr = nasm_malloc(t->len + 1);
1913 memcpy(t->text.p.ptr, src->text.p.ptr, t->len+1);
1914 }
1915
1916 return t;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001917}
1918
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001919static Token *new_White(Token *next)
1920{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001921 Token *t = alloc_Token();
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001922
H. Peter Anvin8571f062019-09-23 16:40:03 -07001923 t->next = next;
1924 t->type = TOK_WHITESPACE;
1925 t->len = 1;
1926 t->text.a[0] = ' ';
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001927
H. Peter Anvin8571f062019-09-23 16:40:03 -07001928 return t;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001929}
1930
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001931/*
H. Peter Anvin8571f062019-09-23 16:40:03 -07001932 * This *transfers* the content from one token to another, leaving the
1933 * next pointer of the latter intact. Unlike dup_Token(), the old
1934 * token is destroyed, except for its next pointer, and the text
1935 * pointer allocation, if any, is simply transferred.
1936 */
1937static Token *steal_Token(Token *dst, Token *src)
1938{
1939 /* Overwrite everything except the next pointers */
1940 memcpy((char *)dst + sizeof(Token *), (char *)src + sizeof(Token *),
1941 sizeof(Token) - sizeof(Token *));
1942
1943 /* Clear the donor token */
1944 memset((char *)src + sizeof(Token *), 0, sizeof(Token) - sizeof(Token *));
1945
1946 return dst;
1947}
1948
1949/*
1950 * Convert a line of tokens back into text. This modifies the list
1951 * by expanding environment variables.
1952 *
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001953 * If expand_locals is not zero, identifiers of the form "%$*xxx"
H. Peter Anvin8571f062019-09-23 16:40:03 -07001954 * are also transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001955 */
H. Peter Anvin9e200162008-06-04 17:23:14 -07001956static char *detoken(Token * tlist, bool expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001957{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001958 Token *t;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001959 char *line, *p;
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001960 int len = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001961
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001962 list_for_each(t, tlist) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001963 switch (t->type) {
1964 case TOK_ENVIRON:
1965 {
1966 const char *v = pp_getenv(t, true);
1967 set_text(t, v, tok_strlen(v));
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07001968 t->type = TOK_NAKED_STRING;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001969 break;
1970 }
H. Peter Anvin077fb932010-07-20 14:56:30 -07001971
H. Peter Anvin8571f062019-09-23 16:40:03 -07001972 case TOK_LOCAL_MACRO:
1973 case TOK_LOCAL_SYMBOL:
1974 if (expand_locals) {
1975 const char *q;
1976 char *p;
1977 Context *ctx = get_ctx(tok_text(t), &q);
1978 if (ctx) {
1979 p = nasm_asprintf("..@%"PRIu64".%s", ctx->number, q);
1980 set_text_free(t, p, nasm_last_string_len());
1981 t->type = TOK_ID;
1982 }
1983 }
1984 break;
H. Peter Anvin077fb932010-07-20 14:56:30 -07001985
H. Peter Anvin8571f062019-09-23 16:40:03 -07001986 default:
1987 break; /* No modifications */
1988 }
1989
1990 if (debug_level(2)) {
1991 unsigned int t_len = t->len;
1992 unsigned int s_len = tok_strlen(tok_text(t));
1993 if (t_len != s_len) {
1994 nasm_panic("assertion failed: token \"%s\" type %u len %u has t->len %u\n",
1995 tok_text(t), t->type, s_len, t_len);
1996 t->len = s_len;
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001997 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001998 }
H. Peter Anvin077fb932010-07-20 14:56:30 -07001999
H. Peter Anvin8571f062019-09-23 16:40:03 -07002000 len += t->len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002001 }
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04002002
H. Peter Anvin734b1882002-04-30 21:01:08 +00002003 p = line = nasm_malloc(len + 1);
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04002004
H. Peter Anvin8571f062019-09-23 16:40:03 -07002005 list_for_each(t, tlist)
2006 p = mempcpy(p, tok_text(t), t->len);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002007 *p = '\0';
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04002008
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002009 return line;
2010}
2011
2012/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002013 * A scanner, suitable for use by the expression evaluator, which
2014 * operates on a line of Tokens. Expects a pointer to a pointer to
2015 * the first token in the line to be passed in as its private_data
2016 * field.
H. Peter Anvinc2df2822007-10-24 15:29:28 -07002017 *
2018 * FIX: This really needs to be unified with stdscan.
H. Peter Anvin76690a12002-04-30 20:52:49 +00002019 */
H. Peter Anvin8b262472019-02-26 14:00:54 -08002020struct ppscan {
2021 Token *tptr;
2022 int ntokens;
2023};
2024
H. Peter Anvine2c80182005-01-15 22:15:51 +00002025static int ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002026{
H. Peter Anvin8b262472019-02-26 14:00:54 -08002027 struct ppscan *pps = private_data;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002028 Token *tline;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002029 const char *txt;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002030
H. Peter Anvine2c80182005-01-15 22:15:51 +00002031 do {
H. Peter Anvin8b262472019-02-26 14:00:54 -08002032 if (pps->ntokens && (tline = pps->tptr)) {
2033 pps->ntokens--;
2034 pps->tptr = tline->next;
2035 } else {
2036 pps->tptr = NULL;
2037 pps->ntokens = 0;
2038 return tokval->t_type = TOKEN_EOS;
2039 }
2040 } while (tline->type == TOK_WHITESPACE || tline->type == TOK_COMMENT);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002041
H. Peter Anvin8571f062019-09-23 16:40:03 -07002042 txt = tok_text(tline);
2043 tokval->t_charptr = (char *)txt; /* Fix this */
H. Peter Anvinc2df2822007-10-24 15:29:28 -07002044
H. Peter Anvin8571f062019-09-23 16:40:03 -07002045 if (txt[0] == '$') {
2046 if (!txt[1]) {
2047 return tokval->t_type = TOKEN_HERE;
2048 } else if (txt[1] == '$' && !txt[2]) {
2049 return tokval->t_type = TOKEN_BASE;
2050 } else if (tline->type == TOK_ID) {
2051 tokval->t_charptr++;
2052 return tokval->t_type = TOKEN_ID;
2053 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002054 }
2055
H. Peter Anvin8571f062019-09-23 16:40:03 -07002056 switch (tline->type) {
2057 default:
2058 if (tline->len == 1)
2059 return tokval->t_type = txt[0];
2060 /* fall through */
2061 case TOK_ID:
2062 return nasm_token_hash(txt, tokval);
2063
2064 case TOK_NUMBER:
2065 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002066 bool rn_error;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002067 tokval->t_integer = readnum(txt, &rn_error);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002068 if (rn_error)
2069 return tokval->t_type = TOKEN_ERRNUM;
2070 else
2071 return tokval->t_type = TOKEN_NUM;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07002072 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002073
H. Peter Anvin8571f062019-09-23 16:40:03 -07002074 case TOK_FLOAT:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002075 return tokval->t_type = TOKEN_FLOAT;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002076
2077 case TOK_STRING:
2078 tokval->t_charptr = (char *)unquote_token(tline);
2079 tokval->t_inttwo = tline->len;
2080 return tokval->t_type = TOKEN_STR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002081 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002082}
2083
2084/*
H. Peter Anvind2354082019-08-27 16:38:48 -07002085 * 1. An expression (true if nonzero 0)
2086 * 2. The keywords true, on, yes for true
2087 * 3. The keywords false, off, no for false
2088 * 4. An empty line, for true
2089 *
2090 * On error, return defval (usually the previous value)
2091 */
2092static bool pp_get_boolean_option(Token *tline, bool defval)
2093{
2094 static const char * const noyes[] = {
2095 "no", "yes",
2096 "false", "true",
2097 "off", "on"
2098 };
2099 struct ppscan pps;
2100 struct tokenval tokval;
2101 expr *evalresult;
2102
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002103 tline = skip_white(tline);
2104 if (!tline)
H. Peter Anvind2354082019-08-27 16:38:48 -07002105 return true;
2106
2107 if (tline->type == TOK_ID) {
2108 size_t i;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002109 const char *txt = tok_text(tline);
2110
H. Peter Anvind2354082019-08-27 16:38:48 -07002111 for (i = 0; i < ARRAY_SIZE(noyes); i++)
H. Peter Anvin8571f062019-09-23 16:40:03 -07002112 if (!nasm_stricmp(txt, noyes[i]))
H. Peter Anvind2354082019-08-27 16:38:48 -07002113 return i & 1;
2114 }
2115
2116 pps.tptr = NULL;
2117 pps.tptr = tline;
2118 pps.ntokens = -1;
2119 tokval.t_type = TOKEN_INVALID;
2120 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
2121
2122 if (!evalresult)
2123 return true;
2124
2125 if (tokval.t_type)
2126 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
2127 if (!is_really_simple(evalresult)) {
2128 nasm_nonfatal("boolean flag expression must be a constant");
2129 return defval;
2130 }
2131
2132 return reloc_value(evalresult) != 0;
2133}
2134
2135/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002136 * Compare a string to the name of an existing macro; this is a
2137 * simple wrapper which calls either strcmp or nasm_stricmp
2138 * depending on the value of the `casesense' parameter.
2139 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002140static int mstrcmp(const char *p, const char *q, bool casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002141{
H. Peter Anvin734b1882002-04-30 21:01:08 +00002142 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002143}
2144
2145/*
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07002146 * Compare a string to the name of an existing macro; this is a
2147 * simple wrapper which calls either strcmp or nasm_stricmp
2148 * depending on the value of the `casesense' parameter.
2149 */
2150static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
2151{
2152 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
2153}
2154
2155/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002156 * Return the Context structure associated with a %$ token. Return
2157 * NULL, having _already_ reported an error condition, if the
2158 * context stack isn't deep enough for the supplied number of $
2159 * signs.
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002160 *
2161 * If "namep" is non-NULL, set it to the pointer to the macro name
2162 * tail, i.e. the part beyond %$...
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002163 */
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04002164static Context *get_ctx(const char *name, const char **namep)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002165{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002166 Context *ctx;
2167 int i;
2168
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002169 if (namep)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002170 *namep = name;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002171
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002172 if (!name || name[0] != '%' || name[1] != '$')
H. Peter Anvine2c80182005-01-15 22:15:51 +00002173 return NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002174
H. Peter Anvine2c80182005-01-15 22:15:51 +00002175 if (!cstk) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002176 nasm_nonfatal("`%s': context stack is empty", name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002177 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002178 }
2179
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002180 name += 2;
2181 ctx = cstk;
2182 i = 0;
2183 while (ctx && *name == '$') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002184 name++;
2185 i++;
2186 ctx = ctx->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002187 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002188 if (!ctx) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002189 nasm_nonfatal("`%s': context stack is only"
2190 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
H. Peter Anvine2c80182005-01-15 22:15:51 +00002191 return NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002192 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002193
2194 if (namep)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002195 *namep = name;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002196
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04002197 return ctx;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002198}
2199
2200/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002201 * Open an include file. This routine must always return a valid
2202 * file pointer if it returns - it's responsible for throwing an
2203 * ERR_FATAL and bombing out completely if not. It should also try
2204 * the include path one by one until it finds the file or reaches
2205 * the end of the path.
H. Peter Anvind81a2352016-09-21 14:03:18 -07002206 *
2207 * Note: for INC_PROBE the function returns NULL at all times;
2208 * instead look for the
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002209 */
H. Peter Anvind81a2352016-09-21 14:03:18 -07002210enum incopen_mode {
2211 INC_NEEDED, /* File must exist */
2212 INC_OPTIONAL, /* Missing is OK */
2213 INC_PROBE /* Only an existence probe */
2214};
2215
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002216/* This is conducts a full pathname search */
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002217static FILE *inc_fopen_search(const char *file, char **slpath,
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002218 enum incopen_mode omode, enum file_flags fmode)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002219{
H. Peter Anvin (Intel)64471092018-12-11 13:06:14 -08002220 const struct strlist_entry *ip = strlist_head(ipath_list);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002221 FILE *fp;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002222 const char *prefix = "";
night199ukfdb1a1b2018-10-18 23:19:47 +02002223 char *sp;
H. Peter Anvind81a2352016-09-21 14:03:18 -07002224 bool found;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002225
H. Peter Anvine2c80182005-01-15 22:15:51 +00002226 while (1) {
night199ukfdb1a1b2018-10-18 23:19:47 +02002227 sp = nasm_catfile(prefix, file);
H. Peter Anvind81a2352016-09-21 14:03:18 -07002228 if (omode == INC_PROBE) {
2229 fp = NULL;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002230 found = nasm_file_exists(sp);
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07002231 } else {
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002232 fp = nasm_open_read(sp, fmode);
H. Peter Anvind81a2352016-09-21 14:03:18 -07002233 found = (fp != NULL);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002234 }
H. Peter Anvind81a2352016-09-21 14:03:18 -07002235 if (found) {
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002236 *slpath = sp;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002237 return fp;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002238 }
Jim Kukunas65a8afc2016-06-13 16:00:42 -04002239
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002240 nasm_free(sp);
Jim Kukunas65a8afc2016-06-13 16:00:42 -04002241
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002242 if (!ip) {
2243 *slpath = NULL;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002244 return NULL;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002245 }
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002246
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002247 prefix = ip->str;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002248 ip = ip->next;
2249 }
2250}
2251
2252/*
2253 * Open a file, or test for the presence of one (depending on omode),
2254 * considering the include path.
2255 */
2256static FILE *inc_fopen(const char *file,
Cyrill Gorcunovb7bb5ac2018-11-11 21:33:52 +03002257 struct strlist *dhead,
H. Peter Anvinccad6f92016-10-04 00:34:35 -07002258 const char **found_path,
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002259 enum incopen_mode omode,
2260 enum file_flags fmode)
2261{
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002262 struct hash_insert hi;
2263 void **hp;
2264 char *path;
2265 FILE *fp = NULL;
2266
2267 hp = hash_find(&FileHash, file, &hi);
2268 if (hp) {
2269 path = *hp;
Martin Storsjöf283c8f2017-08-13 17:28:46 +03002270 if (path || omode != INC_NEEDED) {
Cyrill Gorcunovb7bb5ac2018-11-11 21:33:52 +03002271 strlist_add(dhead, path ? path : file);
Martin Storsjöf283c8f2017-08-13 17:28:46 +03002272 }
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002273 } else {
2274 /* Need to do the actual path search */
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002275 fp = inc_fopen_search(file, &path, omode, fmode);
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002276
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002277 /* Positive or negative result */
2278 hash_add(&hi, nasm_strdup(file), path);
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002279
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07002280 /*
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002281 * Add file to dependency path.
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07002282 */
2283 if (path || omode != INC_NEEDED)
Cyrill Gorcunovb7bb5ac2018-11-11 21:33:52 +03002284 strlist_add(dhead, file);
H. Peter Anvineba20a72002-04-30 20:53:55 +00002285 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002286
H. Peter Anvin (Intel)5d68f982020-06-01 12:32:35 -07002287 if (path && !fp && omode != INC_PROBE)
2288 fp = nasm_open_read(path, fmode);
2289
2290 if (omode == INC_NEEDED && !fp) {
2291 if (!path)
2292 errno = ENOENT;
2293
2294 nasm_nonfatal("unable to open include file `%s': %s",
2295 file, strerror(errno));
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002296 }
2297
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002298 if (found_path)
H. Peter Anvinccad6f92016-10-04 00:34:35 -07002299 *found_path = path;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002300
2301 return fp;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002302}
2303
2304/*
Fabian Giesen0bbc38d2016-04-28 13:48:14 -07002305 * Opens an include or input file. Public version, for use by modules
2306 * that get a file:lineno pair and need to look at the file again
2307 * (e.g. the CodeView debug backend). Returns NULL on failure.
2308 */
H. Peter Anvin3e83cec2016-05-25 04:28:46 -07002309FILE *pp_input_fopen(const char *filename, enum file_flags mode)
Fabian Giesen0bbc38d2016-04-28 13:48:14 -07002310{
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07002311 return inc_fopen(filename, NULL, NULL, INC_OPTIONAL, mode);
Fabian Giesen0bbc38d2016-04-28 13:48:14 -07002312}
2313
2314/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002315 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002316 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002317 * return true if _any_ single-line macro of that name is defined.
2318 * Otherwise, will return true if a single-line macro with either
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002319 * `nparam' or no parameters is defined.
2320 *
2321 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002322 * defined, or nparam is -1, the address of the definition structure
2323 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002324 * is NULL, no action will be taken regarding its contents, and no
2325 * error will occur.
2326 *
2327 * Note that this is also called with nparam zero to resolve
2328 * `ifdef'.
2329 */
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002330static bool
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002331smacro_defined(Context *ctx, const char *name, int nparam, SMacro **defn,
H. Peter Anvind2354082019-08-27 16:38:48 -07002332 bool nocase, bool find_alias)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002333{
H. Peter Anvin166c2472008-05-28 12:28:58 -07002334 struct hash_table *smtbl;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002335 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002336
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002337 smtbl = ctx ? &ctx->localmac : &smacros;
H. Peter Anvind2354082019-08-27 16:38:48 -07002338
2339restart:
H. Peter Anvin166c2472008-05-28 12:28:58 -07002340 m = (SMacro *) hash_findix(smtbl, name);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002341
H. Peter Anvine2c80182005-01-15 22:15:51 +00002342 while (m) {
2343 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002344 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam ||
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002345 (m->greedy && nparam >= m->nparam-1))) {
H. Peter Anvind2354082019-08-27 16:38:48 -07002346 if (m->alias && !find_alias) {
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002347 if (!ppopt.noaliases) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002348 name = tok_text(m->expansion);
H. Peter Anvind2354082019-08-27 16:38:48 -07002349 goto restart;
2350 } else {
2351 continue;
2352 }
2353 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002354 if (defn) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002355 *defn = (nparam == m->nparam || nparam == -1) ? m : NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002356 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002357 return true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002358 }
2359 m = m->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002360 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002361
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002362 return false;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002363}
2364
Cyrill Gorcunov3079f792018-11-14 10:03:42 +03002365/* param should be a natural number [0; INT_MAX] */
2366static int read_param_count(const char *str)
2367{
2368 int result;
2369 bool err;
2370
2371 result = readnum(str, &err);
2372 if (result < 0 || result > INT_MAX) {
2373 result = 0;
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002374 nasm_nonfatal("parameter count `%s' is out of bounds [%d; %d]",
2375 str, 0, INT_MAX);
2376 } else if (err)
2377 nasm_nonfatal("unable to parse parameter count `%s'", str);
Cyrill Gorcunov3079f792018-11-14 10:03:42 +03002378 return result;
2379}
2380
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002381/*
2382 * Count and mark off the parameters in a multi-line macro call.
2383 * This is called both from within the multi-line macro expansion
2384 * code, and also to mark off the default parameters when provided
2385 * in a %macro definition line.
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002386 *
2387 * Note that we need space in the params array for parameter 0 being
2388 * a possible captured label as well as the final NULL.
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002389 *
2390 * Returns a pointer to the pointer to a terminal comma if present;
2391 * used to drop an empty terminal argument for legacy reasons.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002392 */
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002393static Token **count_mmac_params(Token *tline, int *nparamp, Token ***paramsp)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002394{
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07002395 int paramsize;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002396 int nparam = 0;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002397 Token *t;
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002398 Token **comma = NULL, **maybe_comma = NULL;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002399 Token **params;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002400
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002401 paramsize = PARAM_DELTA;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002402 nasm_newn(params, paramsize);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002403
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002404 t = skip_white(tline);
2405 if (t) {
2406 while (true) {
2407 /* Need two slots for captured label and NULL */
2408 if (unlikely(nparam+2 >= paramsize)) {
2409 paramsize += PARAM_DELTA;
2410 params = nasm_realloc(params, sizeof(*params) * paramsize);
2411 }
2412 params[++nparam] = t;
2413 if (tok_is(t, '{')) {
2414 int brace = 1;
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002415
2416 comma = NULL; /* Non-empty parameter */
2417
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002418 while (brace && (t = t->next)) {
2419 brace += tok_is(t, '{');
2420 brace -= tok_is(t, '}');
2421 }
H. Peter Anvin (Intel)f8639bd2020-06-04 16:29:53 -07002422
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002423 if (t) {
2424 /*
2425 * Now we've found the closing brace, look further
2426 * for the comma.
2427 */
2428 t = skip_white(t->next);
2429 if (tok_isnt(t, ','))
2430 nasm_nonfatal("braces do not enclose all of macro parameter");
2431 } else {
2432 nasm_nonfatal("expecting closing brace in macro parameter");
2433 }
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08002434 }
2435
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002436 /* Advance to the next comma */
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002437 maybe_comma = &t->next;
2438 while (tok_isnt(t, ',')) {
2439 if (!tok_white(t))
2440 comma = NULL; /* Non-empty parameter */
2441 maybe_comma = &t->next;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002442 t = t->next;
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002443 }
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002444
2445 if (!t)
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002446 break; /* End of string, no comma */
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002447
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002448 comma = maybe_comma; /* Point to comma pointer */
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002449 t = skip_white(t->next); /* Eat the comma and whitespace */
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08002450 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002451 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002452
2453 params[nparam+1] = NULL;
2454 *paramsp = params;
2455 *nparamp = nparam;
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07002456
2457 return comma;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002458}
2459
2460/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002461 * Determine whether one of the various `if' conditions is true or
2462 * not.
2463 *
2464 * We must free the tline we get passed.
2465 */
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002466static enum cond_state if_condition(Token * tline, enum preproc_token ct)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002467{
H. Peter Anvin70055962007-10-11 00:05:31 -07002468 bool j;
H. Peter Anvin8b262472019-02-26 14:00:54 -08002469 Token *t, *tt, *origline;
2470 struct ppscan pps;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002471 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002472 expr *evalresult;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002473 enum pp_token_type needtype;
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002474 const char *dname = pp_directives[ct];
2475 bool casesense = true;
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002476 enum preproc_token cond = PP_COND(ct);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002477
2478 origline = tline;
2479
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002480 switch (cond) {
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002481 case PP_IFCTX:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002482 j = false; /* have we matched yet? */
Victor van den Elzen0e857f12008-07-23 13:21:29 +02002483 while (true) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002484 tline = skip_white(tline);
Victor van den Elzen0e857f12008-07-23 13:21:29 +02002485 if (!tline)
2486 break;
2487 if (tline->type != TOK_ID) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002488 nasm_nonfatal("`%s' expects context identifiers",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002489 dname);
2490 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002491 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07002492 if (cstk && cstk->name && !nasm_stricmp(tok_text(tline), cstk->name))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002493 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002494 tline = tline->next;
2495 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002496 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002497
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002498 case PP_IFDEF:
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002499 case PP_IFDEFALIAS:
2500 {
2501 bool alias = cond == PP_IFDEFALIAS;
2502 SMacro *smac;
2503 Context *ctx;
2504 const char *mname;
2505
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002506 j = false; /* have we matched yet? */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002507 while (tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002508 tline = skip_white(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002509 if (!tline || (tline->type != TOK_ID &&
H. Peter Anvin8571f062019-09-23 16:40:03 -07002510 tline->type != TOK_LOCAL_MACRO)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002511 nasm_nonfatal("`%s' expects macro identifiers",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002512 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002513 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002514 }
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002515
2516 mname = tok_text(tline);
2517 ctx = get_ctx(mname, &mname);
H. Peter Anvin (Intel)b91e7732020-06-05 12:22:26 -07002518 if (smacro_defined(ctx, mname, -1, &smac, true, alias) && smac
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002519 && smac->alias == alias) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002520 j = true;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002521 break;
2522 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002523 tline = tline->next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002524 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002525 break;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002526 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002527
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002528 case PP_IFENV:
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04002529 tline = expand_smacro(tline);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002530 j = false; /* have we matched yet? */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002531 while (tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002532 tline = skip_white(tline);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002533 if (!tline || (tline->type != TOK_ID &&
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04002534 tline->type != TOK_STRING &&
H. Peter Anvin8571f062019-09-23 16:40:03 -07002535 tline->type != TOK_INTERNAL_STRING &&
2536 tline->type != TOK_ENVIRON)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002537 nasm_nonfatal("`%s' expects environment variable names",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002538 dname);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002539 goto fail;
2540 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07002541
2542 j |= !!pp_getenv(tline, false);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002543 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002544 }
2545 break;
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002546
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002547 case PP_IFIDNI:
2548 casesense = false;
2549 /* fall through */
2550 case PP_IFIDN:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002551 tline = expand_smacro(tline);
2552 t = tt = tline;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002553 while (tok_isnt(tt, ','))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002554 tt = tt->next;
2555 if (!tt) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002556 nasm_nonfatal("`%s' expects two comma-separated arguments",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002557 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002558 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002559 }
2560 tt = tt->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002561 j = true; /* assume equality unless proved not */
H. Peter Anvin8571f062019-09-23 16:40:03 -07002562 while (tok_isnt(t, ',') && tt) {
2563 unsigned int l1, l2;
2564 const char *t1, *t2;
2565
2566 if (tok_is(tt, ',')) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002567 nasm_nonfatal("`%s': more than one comma on line",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002568 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002569 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002570 }
2571 if (t->type == TOK_WHITESPACE) {
2572 t = t->next;
2573 continue;
2574 }
2575 if (tt->type == TOK_WHITESPACE) {
2576 tt = tt->next;
2577 continue;
2578 }
2579 if (tt->type != t->type) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002580 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002581 break;
2582 }
H. Peter Anvind2456592008-06-19 15:04:18 -07002583
H. Peter Anvin8571f062019-09-23 16:40:03 -07002584 t1 = unquote_token(t);
2585 t2 = unquote_token(tt);
2586 l1 = t->len;
2587 l2 = tt->len;
2588
2589 if (l1 != l2 || mmemcmp(t1, t2, l1, casesense)) {
2590 j = false;
2591 break;
2592 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00002593
H. Peter Anvine2c80182005-01-15 22:15:51 +00002594 t = t->next;
2595 tt = tt->next;
2596 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07002597 if (!tok_is(t, ',') || tt)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002598 j = false; /* trailing gunk on one end or other */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002599 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002600
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002601 case PP_IFMACRO:
H. Peter Anvin89cee572009-07-15 09:16:54 -04002602 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002603 bool found = false;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002604 MMacro searching, *mmac;
H. Peter Anvin65747262002-05-07 00:10:05 +00002605
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002606 tline = skip_white(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002607 tline = expand_id(tline);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002608 if (!tok_type(tline, TOK_ID)) {
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002609 nasm_nonfatal("`%s' expects a macro name", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002610 goto fail;
2611 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002612 nasm_zero(searching);
H. Peter Anvin8571f062019-09-23 16:40:03 -07002613 searching.name = dup_text(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002614 searching.casesense = true;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002615 searching.nparam_min = 0;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002616 searching.nparam_max = INT_MAX;
2617 tline = expand_smacro(tline->next);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002618 tline = skip_white(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002619 if (!tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002620 } else if (!tok_type(tline, TOK_NUMBER)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002621 nasm_nonfatal("`%s' expects a parameter count or nothing",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002622 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002623 } else {
2624 searching.nparam_min = searching.nparam_max =
H. Peter Anvin8571f062019-09-23 16:40:03 -07002625 read_param_count(tok_text(tline));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002626 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002627 if (tline && tok_is(tline->next, '-')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002628 tline = tline->next->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002629 if (tok_is(tline, '*'))
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002630 searching.nparam_max = INT_MAX;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002631 else if (!tok_type(tline, TOK_NUMBER))
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002632 nasm_nonfatal("`%s' expects a parameter count after `-'",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002633 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002634 else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002635 searching.nparam_max = read_param_count(tok_text(tline));
Cyrill Gorcunovc9244ea2017-10-22 15:25:48 +03002636 if (searching.nparam_min > searching.nparam_max) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002637 nasm_nonfatal("minimum parameter count exceeds maximum");
Cyrill Gorcunovc9244ea2017-10-22 15:25:48 +03002638 searching.nparam_max = searching.nparam_min;
2639 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002640 }
2641 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002642 if (tline && tok_is(tline->next, '+')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002643 tline = tline->next;
2644 searching.plus = true;
2645 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002646 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
2647 while (mmac) {
2648 if (!strcmp(mmac->name, searching.name) &&
2649 (mmac->nparam_min <= searching.nparam_max
2650 || searching.plus)
2651 && (searching.nparam_min <= mmac->nparam_max
2652 || mmac->plus)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002653 found = true;
2654 break;
2655 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002656 mmac = mmac->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002657 }
2658 if (tline && tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08002659 nasm_warn(WARN_OTHER, "trailing garbage after %%ifmacro ignored");
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002660 nasm_free(searching.name);
2661 j = found;
2662 break;
H. Peter Anvin89cee572009-07-15 09:16:54 -04002663 }
H. Peter Anvin65747262002-05-07 00:10:05 +00002664
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002665 case PP_IFID:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002666 needtype = TOK_ID;
2667 goto iftype;
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002668 case PP_IFNUM:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002669 needtype = TOK_NUMBER;
2670 goto iftype;
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002671 case PP_IFSTR:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002672 needtype = TOK_STRING;
2673 goto iftype;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002674
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002675iftype:
2676 t = tline = expand_smacro(tline);
H. Peter Anvind85d2502008-05-04 17:53:31 -07002677
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002678 while (tok_white(t) ||
2679 (needtype == TOK_NUMBER && (tok_is(t, '-') | tok_is(t, '+'))))
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002680 t = t->next;
H. Peter Anvind85d2502008-05-04 17:53:31 -07002681
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002682 j = tok_type(t, needtype);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002683 break;
H. Peter Anvincbf768d2008-02-16 16:41:25 -08002684
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002685 case PP_IFTOKEN:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002686 tline = expand_smacro(tline);
2687 t = skip_white(tline);
H. Peter Anvincbf768d2008-02-16 16:41:25 -08002688
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002689 j = false;
2690 if (t) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002691 t = skip_white(t->next); /* Skip the actual token + whitespace */
2692 j = !t;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002693 }
2694 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002695
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002696 case PP_IFEMPTY:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002697 tline = expand_smacro(tline);
2698 t = skip_white(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002699 j = !t; /* Should be empty */
2700 break;
H. Peter Anvin134b9462008-02-16 17:01:40 -08002701
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002702 case PP_IF:
H. Peter Anvin8b262472019-02-26 14:00:54 -08002703 pps.tptr = tline = expand_smacro(tline);
2704 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002705 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07002706 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002707 if (!evalresult)
2708 return -1;
2709 if (tokval.t_type)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08002710 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00002711 if (!is_simple(evalresult)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002712 nasm_nonfatal("non-constant value given to `%s'",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002713 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002714 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002715 }
Chuck Crayne60ae75d2007-05-02 01:59:16 +00002716 j = reloc_value(evalresult) != 0;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002717 break;
H. Peter Anvin95e28822007-09-12 04:20:08 +00002718
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002719 case PP_IFUSING:
2720 case PP_IFUSABLE:
2721 {
2722 const struct use_package *pkg;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002723 const char *name;
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002724
H. Peter Anvin8571f062019-09-23 16:40:03 -07002725 pkg = get_use_pkg(tline, dname, &name);
2726 if (!name)
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002727 goto fail;
2728
2729 j = pkg && ((cond == PP_IFUSABLE) | use_loaded[pkg->index]);
2730 break;
2731 }
2732
H. Peter Anvine2c80182005-01-15 22:15:51 +00002733 default:
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002734 nasm_nonfatal("unknown preprocessor directive `%s'", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002735 goto fail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002736 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002737
2738 free_tlist(origline);
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002739 return (j ^ PP_COND_NEGATIVE(ct)) ? COND_IF_TRUE : COND_IF_FALSE;
H. Peter Anvin70653092007-10-19 14:42:29 -07002740
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002741fail:
2742 free_tlist(origline);
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002743 return COND_NEVER;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002744}
2745
2746/*
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07002747 * Default smacro expansion routine: just returns a copy of the
2748 * expansion list.
2749 */
2750static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002751smacro_expand_default(const SMacro *s, Token **params, int nparams)
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07002752{
2753 (void)params;
2754 (void)nparams;
2755
2756 return dup_tlist(s->expansion, NULL);
2757}
2758
2759/*
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002760 * Emit a macro defintion or undef to the listing file, if
2761 * desired. This is similar to detoken(), but it handles the reverse
2762 * expansion list, does not expand %! or local variable tokens, and
2763 * does some special handling for macro parameters.
2764 */
2765static void
2766list_smacro_def(enum preproc_token op, const Context *ctx, const SMacro *m)
2767{
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002768 Token *t;
2769 size_t namelen, size;
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002770 char *def, *p;
H. Peter Anvin6686de22019-08-10 05:33:14 -07002771 char *context_prefix = NULL;
2772 size_t context_len;
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002773
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002774 namelen = strlen(m->name);
2775 size = namelen + 2; /* Include room for space after name + NUL */
2776
2777 if (ctx) {
H. Peter Anvin6686de22019-08-10 05:33:14 -07002778 int context_depth = cstk->depth - ctx->depth + 1;
2779 context_prefix =
2780 nasm_asprintf("[%s::%"PRIu64"] %%%-*s",
2781 ctx->name ? ctx->name : "",
2782 ctx->number, context_depth, "");
2783
2784 context_len = nasm_last_string_len();
2785 memset(context_prefix + context_len - context_depth,
2786 '$', context_depth);
2787 size += context_len;
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002788 }
2789
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002790 list_for_each(t, m->expansion)
H. Peter Anvin8571f062019-09-23 16:40:03 -07002791 size += t->len;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002792
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002793 if (m->nparam) {
2794 /*
2795 * Space for ( and either , or ) around each
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002796 * parameter, plus up to 4 flags.
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002797 */
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002798 int i;
2799
2800 size += 1 + 4 * m->nparam;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002801 for (i = 0; i < m->nparam; i++)
H. Peter Anvin8571f062019-09-23 16:40:03 -07002802 size += m->params[i].name.len;
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002803 }
2804
2805 def = nasm_malloc(size);
2806 p = def+size;
2807 *--p = '\0';
2808
2809 list_for_each(t, m->expansion) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002810 p -= t->len;
2811 memcpy(p, tok_text(t), t->len);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002812 }
2813
2814 *--p = ' ';
2815
2816 if (m->nparam) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002817 int i;
2818
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002819 *--p = ')';
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002820 for (i = m->nparam-1; i >= 0; i--) {
2821 enum sparmflags flags = m->params[i].flags;
2822 if (flags & SPARM_GREEDY)
2823 *--p = '+';
H. Peter Anvin8571f062019-09-23 16:40:03 -07002824 p -= m->params[i].name.len;
2825 memcpy(p, tok_text(&m->params[i].name), m->params[i].name.len);
2826
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002827 if (flags & SPARM_NOSTRIP)
2828 *--p = '!';
2829 if (flags & SPARM_STR)
2830 *--p = '&';
2831 if (flags & SPARM_EVAL)
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002832 *--p = '=';
2833 *--p = ',';
2834 }
2835 *p = '('; /* First parameter starts with ( not , */
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002836 }
2837
2838 p -= namelen;
2839 memcpy(p, m->name, namelen);
2840
H. Peter Anvin6686de22019-08-10 05:33:14 -07002841 if (context_prefix) {
2842 p -= context_len;
2843 memcpy(p, context_prefix, context_len);
2844 nasm_free(context_prefix);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002845 }
2846
2847 nasm_listmsg("%s %s", pp_directives[op], p);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002848 nasm_free(def);
H. Peter Anvin6686de22019-08-10 05:33:14 -07002849}
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002850
2851/*
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002852 * Parse smacro arguments, return argument count. If the tmpl argument
2853 * is set, set the nparam, greedy and params field in the template.
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002854 * *tpp is updated to point to the pointer to the first token after the
2855 * prototype.
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002856 *
2857 * The text values from any argument tokens are "stolen" and the
2858 * corresponding text fields set to NULL.
2859 */
2860static int parse_smacro_template(Token ***tpp, SMacro *tmpl)
2861{
2862 int nparam = 0;
2863 enum sparmflags flags;
2864 struct smac_param *params = NULL;
H. Peter Anvin (Intel)68075f82019-08-20 12:28:05 -07002865 bool err, done;
2866 bool greedy = false;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002867 Token **tn = *tpp;
2868 Token *t = *tn;
2869 Token *name;
2870
H. Peter Anvin (Intel)d4607842019-08-20 16:19:37 -07002871 /*
2872 * DO NOT skip whitespace here, or we won't be able to distinguish:
2873 *
2874 * %define foo (a,b) ; no arguments, (a,b) is the expansion
2875 * %define bar(a,b) ; two arguments, empty expansion
2876 *
2877 * This ambiguity was inherited from C.
2878 */
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002879
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002880 if (!tok_is(t, '('))
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002881 goto finish;
2882
2883 if (tmpl) {
2884 Token *tx = t;
2885 Token **txpp = &tx;
2886 int sparam;
2887
2888 /* Count parameters first */
2889 sparam = parse_smacro_template(&txpp, NULL);
2890 if (!sparam)
2891 goto finish; /* No parameters, we're done */
2892 nasm_newn(params, sparam);
2893 }
2894
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002895 /* Skip leading paren */
2896 tn = &t->next;
2897 t = *tn;
2898
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002899 name = NULL;
2900 flags = 0;
H. Peter Anvin (Intel)68075f82019-08-20 12:28:05 -07002901 err = done = false;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002902
2903 while (!done) {
2904 if (!t || !t->type) {
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002905 if (name || flags)
2906 nasm_nonfatal("`)' expected to terminate macro template");
2907 else
2908 nasm_nonfatal("parameter identifier expected");
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002909 break;
2910 }
2911
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002912 switch (t->type) {
2913 case TOK_ID:
2914 if (name)
2915 goto bad;
2916 name = t;
2917 break;
2918
2919 case TOK_OTHER:
H. Peter Anvin8571f062019-09-23 16:40:03 -07002920 if (t->len != 1)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002921 goto bad;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002922 switch (t->text.a[0]) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002923 case '=':
2924 flags |= SPARM_EVAL;
2925 break;
2926 case '&':
2927 flags |= SPARM_STR;
2928 break;
2929 case '!':
2930 flags |= SPARM_NOSTRIP;
2931 break;
2932 case '+':
2933 flags |= SPARM_GREEDY;
2934 greedy = true;
2935 break;
2936 case ',':
2937 if (greedy)
2938 nasm_nonfatal("greedy parameter must be last");
2939 /* fall through */
2940 case ')':
2941 if (params) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002942 if (name)
2943 steal_Token(&params[nparam].name, name);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002944 params[nparam].flags = flags;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002945 }
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002946 nparam++;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002947 name = NULL;
2948 flags = 0;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002949 done = t->text.a[0] == ')';
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002950 break;
2951 default:
2952 goto bad;
2953 }
2954 break;
2955
2956 case TOK_WHITESPACE:
2957 break;
2958
2959 default:
2960 bad:
2961 if (!err) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002962 nasm_nonfatal("garbage `%s' in macro parameter list", tok_text(t));
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002963 err = true;
2964 }
2965 break;
2966 }
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002967
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002968 tn = &t->next;
2969 t = *tn;
2970 }
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002971
2972finish:
2973 while (t && t->type == TOK_WHITESPACE) {
2974 tn = &t->next;
2975 t = t->next;
2976 }
2977 *tpp = tn;
2978 if (tmpl) {
2979 tmpl->nparam = nparam;
2980 tmpl->greedy = greedy;
2981 tmpl->params = params;
2982 }
2983 return nparam;
2984}
2985
2986/*
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07002987 * Common code for defining an smacro. The tmpl argument, if not NULL,
2988 * contains any macro parameters that aren't explicit arguments;
2989 * those are the more uncommon macro variants.
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002990 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07002991static SMacro *define_smacro(const char *mname, bool casesense,
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002992 Token *expansion, SMacro *tmpl)
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002993{
2994 SMacro *smac, **smhead;
H. Peter Anvin166c2472008-05-28 12:28:58 -07002995 struct hash_table *smtbl;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07002996 Context *ctx;
2997 bool defining_alias = false;
2998 unsigned int nparam = 0;
H. Peter Anvin70653092007-10-19 14:42:29 -07002999
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003000 if (tmpl) {
3001 defining_alias = tmpl->alias;
3002 nparam = tmpl->nparam;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07003003 if (nparam && !defining_alias)
3004 mark_smac_params(expansion, tmpl, 0);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003005 }
3006
3007 while (1) {
3008 ctx = get_ctx(mname, &mname);
3009
H. Peter Anvind2354082019-08-27 16:38:48 -07003010 if (!smacro_defined(ctx, mname, nparam, &smac, casesense, true)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003011 /* Create a new macro */
3012 smtbl = ctx ? &ctx->localmac : &smacros;
3013 smhead = (SMacro **) hash_findi_add(smtbl, mname);
3014 nasm_new(smac);
3015 smac->next = *smhead;
3016 *smhead = smac;
3017 break;
3018 } else if (!smac) {
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003019 nasm_warn(WARN_OTHER, "single-line macro `%s' defined both with and"
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003020 " without parameters", mname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003021 /*
3022 * Some instances of the old code considered this a failure,
3023 * some others didn't. What is the right thing to do here?
3024 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003025 goto fail;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003026 } else if (!smac->alias || ppopt.noaliases || defining_alias) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003027 /*
3028 * We're redefining, so we have to take over an
3029 * existing SMacro structure. This means freeing
H. Peter Anvin8b262472019-02-26 14:00:54 -08003030 * what was already in it, but not the structure itself.
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003031 */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07003032 clear_smacro(smac);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003033 break;
3034 } else if (smac->in_progress) {
3035 nasm_nonfatal("macro alias loop");
3036 goto fail;
3037 } else {
3038 /* It is an alias macro; follow the alias link */
3039 SMacro *s;
3040
3041 smac->in_progress = true;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003042 s = define_smacro(tok_text(smac->expansion), casesense,
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003043 expansion, tmpl);
3044 smac->in_progress = false;
3045 return s;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003046 }
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003047 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003048
3049 smac->name = nasm_strdup(mname);
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003050 smac->casesense = casesense;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003051 smac->expansion = expansion;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003052 smac->expand = smacro_expand_default;
3053 if (tmpl) {
3054 smac->nparam = tmpl->nparam;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07003055 smac->params = tmpl->params;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003056 smac->alias = tmpl->alias;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07003057 smac->greedy = tmpl->greedy;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003058 if (tmpl->expand)
3059 smac->expand = tmpl->expand;
3060 }
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07003061 if (list_option('s')) {
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07003062 list_smacro_def((smac->alias ? PP_DEFALIAS : PP_DEFINE)
3063 + !casesense, ctx, smac);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003064 }
H. Peter Anvin8b262472019-02-26 14:00:54 -08003065 return smac;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003066
3067fail:
3068 free_tlist(expansion);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07003069 if (tmpl)
3070 free_smacro_members(tmpl);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003071 return NULL;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003072}
3073
3074/*
3075 * Undefine an smacro
3076 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003077static void undef_smacro(const char *mname, bool undefalias)
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003078{
3079 SMacro **smhead, *s, **sp;
H. Peter Anvin166c2472008-05-28 12:28:58 -07003080 struct hash_table *smtbl;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003081 Context *ctx;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003082
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003083 ctx = get_ctx(mname, &mname);
H. Peter Anvin166c2472008-05-28 12:28:58 -07003084 smtbl = ctx ? &ctx->localmac : &smacros;
3085 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
H. Peter Anvin70653092007-10-19 14:42:29 -07003086
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003087 if (smhead) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003088 /*
3089 * We now have a macro name... go hunt for it.
3090 */
3091 sp = smhead;
3092 while ((s = *sp) != NULL) {
3093 if (!mstrcmp(s->name, mname, s->casesense)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003094 if (s->alias && !undefalias) {
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003095 if (!ppopt.noaliases) {
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07003096 if (s->in_progress) {
3097 nasm_nonfatal("macro alias loop");
3098 } else {
3099 s->in_progress = true;
3100 undef_smacro(tok_text(s->expansion), false);
3101 s->in_progress = false;
3102 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003103 }
3104 } else {
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07003105 if (list_option('d'))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003106 list_smacro_def(s->alias ? PP_UNDEFALIAS : PP_UNDEF,
3107 ctx, s);
3108 *sp = s->next;
3109 free_smacro(s);
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07003110 continue;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003111 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003112 }
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07003113 sp = &s->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003114 }
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003115 }
3116}
3117
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003118/*
H. Peter Anvina26433d2008-07-16 14:40:01 -07003119 * Parse a mmacro specification.
3120 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003121static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
H. Peter Anvina26433d2008-07-16 14:40:01 -07003122{
H. Peter Anvina26433d2008-07-16 14:40:01 -07003123 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003124 tline = skip_white(tline);
H. Peter Anvina26433d2008-07-16 14:40:01 -07003125 tline = expand_id(tline);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003126 if (!tok_type(tline, TOK_ID)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003127 nasm_nonfatal("`%s' expects a macro name", directive);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003128 return false;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003129 }
Victor van den Elzenb916ede2008-07-23 15:14:22 +02003130
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07003131#if 0
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003132 def->prev = NULL;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07003133#endif
H. Peter Anvin8571f062019-09-23 16:40:03 -07003134 def->name = dup_text(tline);
H. Peter Anvina26433d2008-07-16 14:40:01 -07003135 def->plus = false;
3136 def->nolist = false;
Victor van den Elzenb916ede2008-07-23 15:14:22 +02003137 def->nparam_min = 0;
3138 def->nparam_max = 0;
3139
H. Peter Anvina26433d2008-07-16 14:40:01 -07003140 tline = expand_smacro(tline->next);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003141 tline = skip_white(tline);
3142 if (!tok_type(tline, TOK_NUMBER))
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003143 nasm_nonfatal("`%s' expects a parameter count", directive);
3144 else
H. Peter Anvin8571f062019-09-23 16:40:03 -07003145 def->nparam_min = def->nparam_max = read_param_count(tok_text(tline));
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003146 if (tline && tok_is(tline->next, '-')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003147 tline = tline->next->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003148 if (tok_is(tline, '*')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003149 def->nparam_max = INT_MAX;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003150 } else if (!tok_type(tline, TOK_NUMBER)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003151 nasm_nonfatal("`%s' expects a parameter count after `-'", directive);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003152 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003153 def->nparam_max = read_param_count(tok_text(tline));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003154 if (def->nparam_min > def->nparam_max) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003155 nasm_nonfatal("minimum parameter count exceeds maximum");
Cyrill Gorcunovc9244ea2017-10-22 15:25:48 +03003156 def->nparam_max = def->nparam_min;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003157 }
3158 }
H. Peter Anvina26433d2008-07-16 14:40:01 -07003159 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003160 if (tline && tok_is(tline->next, '+')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003161 tline = tline->next;
3162 def->plus = true;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003163 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003164 if (tline && tok_type(tline->next, TOK_ID) &&
H. Peter Anvin8571f062019-09-23 16:40:03 -07003165 tline->next->len == 7 &&
3166 !nasm_stricmp(tline->next->text.a, ".nolist")) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003167 tline = tline->next;
H. Peter Anvin6686de22019-08-10 05:33:14 -07003168 def->nolist = !list_option('f') || istk->nolist;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003169 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003170
H. Peter Anvina26433d2008-07-16 14:40:01 -07003171 /*
3172 * Handle default parameters.
3173 */
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07003174 def->ndefs = 0;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003175 if (tline && tline->next) {
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07003176 Token **comma;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003177 def->dlist = tline->next;
3178 tline->next = NULL;
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07003179 comma = count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
3180 if (!ppopt.sane_empty_expansion && comma) {
3181 *comma = NULL;
3182 def->ndefs--;
3183 nasm_warn(WARN_MACRO_PARAMS_LEGACY,
3184 "dropping trailing empty default parameter in defintion of multi-line macro `%s'",
3185 def->name);
3186 }
H. Peter Anvina26433d2008-07-16 14:40:01 -07003187 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003188 def->dlist = NULL;
3189 def->defaults = NULL;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003190 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003191 def->expansion = NULL;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003192
H. Peter Anvin89cee572009-07-15 09:16:54 -04003193 if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -08003194 !def->plus) {
3195 /*
3196 *!macro-defaults [on] macros with more default than optional parameters
3197 *! warns when a macro has more default parameters than optional parameters.
3198 *! See \k{mlmacdef} for why might want to disable this warning.
3199 */
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003200 nasm_warn(WARN_MACRO_DEFAULTS,
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -08003201 "too many default macro parameters in macro `%s'", def->name);
3202 }
Victor van den Elzenb916ede2008-07-23 15:14:22 +02003203
H. Peter Anvina26433d2008-07-16 14:40:01 -07003204 return true;
3205}
3206
3207
3208/*
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003209 * Decode a size directive
3210 */
3211static int parse_size(const char *str) {
3212 static const char *size_names[] =
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003213 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003214 static const int sizes[] =
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003215 { 0, 1, 4, 16, 8, 10, 2, 32 };
Cyrill Gorcunovc713b5f2018-09-29 14:30:14 +03003216 return str ? sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1] : 0;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003217}
3218
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003219/*
3220 * Process a preprocessor %pragma directive. Currently there are none.
3221 * Gets passed the token list starting with the "preproc" token from
3222 * "%pragma preproc".
3223 */
3224static void do_pragma_preproc(Token *tline)
3225{
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003226 const char *txt;
3227
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003228 /* Skip to the real stuff */
3229 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003230 tline = skip_white(tline);
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003231
3232 if (!tok_type(tline, TOK_ID))
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003233 return;
3234
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003235 txt = tok_text(tline);
3236 if (!nasm_stricmp(txt, "sane_empty_expansion")) {
3237 tline = skip_white(tline->next);
3238 ppopt.sane_empty_expansion =
3239 pp_get_boolean_option(tline, ppopt.sane_empty_expansion);
3240 } else {
3241 /* Unknown pragma, ignore for now */
3242 }
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003243}
3244
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003245static bool is_macro_id(const Token *t)
3246{
H. Peter Anvin8571f062019-09-23 16:40:03 -07003247 return tok_type(t, TOK_ID) || tok_type(t, TOK_LOCAL_MACRO);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003248}
3249
H. Peter Anvin8571f062019-09-23 16:40:03 -07003250static const char *get_id(Token **tp, const char *dname)
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003251{
H. Peter Anvin8571f062019-09-23 16:40:03 -07003252 const char *id;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003253 Token *t = *tp;
3254
3255 t = t->next; /* Skip directive */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003256 t = skip_white(t);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003257 t = expand_id(t);
3258
3259 if (!is_macro_id(t)) {
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003260 nasm_nonfatal("`%s' expects a macro identifier", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003261 return NULL;
3262 }
3263
H. Peter Anvin8571f062019-09-23 16:40:03 -07003264 id = tok_text(t);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003265 t = skip_white(t);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003266 *tp = t;
3267 return id;
3268}
3269
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003270/* Parse a %use package name and find the package. Set *err on syntax error. */
3271static const struct use_package *
H. Peter Anvin8571f062019-09-23 16:40:03 -07003272get_use_pkg(Token *t, const char *dname, const char **name)
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003273{
H. Peter Anvin8571f062019-09-23 16:40:03 -07003274 const char *id;
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003275
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003276 t = skip_white(t);
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003277 t = expand_smacro(t);
3278
H. Peter Anvin8571f062019-09-23 16:40:03 -07003279 *name = NULL;
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003280
H. Peter Anvin8571f062019-09-23 16:40:03 -07003281 if (!t) {
3282 nasm_nonfatal("`%s' expects a package name, got end of line", dname);
3283 return NULL;
3284 } else if (t->type != TOK_ID && t->type != TOK_STRING) {
3285 nasm_nonfatal("`%s' expects a package name, got `%s'",
3286 dname, tok_text(t));
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003287 return NULL;
3288 }
3289
H. Peter Anvin8571f062019-09-23 16:40:03 -07003290 *name = id = unquote_token(t);
3291
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003292 t = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003293 t = skip_white(t);
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003294 if (t)
3295 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3296
3297 return nasm_find_use_package(id);
3298}
3299
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003300/*
3301 * Mark parameter tokens in an smacro definition. If the type argument
3302 * is 0, create smac param tokens, otherwise use the type specified;
3303 * normally this is used for TOK_XDEF_PARAM, which is used to protect
3304 * parameter tokens during expansion during %xdefine.
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07003305 *
3306 * tmpl may not be NULL here.
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003307 */
3308static void mark_smac_params(Token *tline, const SMacro *tmpl,
3309 enum pp_token_type type)
3310{
3311 const struct smac_param *params = tmpl->params;
3312 int nparam = tmpl->nparam;
3313 Token *t;
3314 int i;
3315
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003316 list_for_each(t, tline) {
3317 if (t->type != TOK_ID && t->type != TOK_XDEF_PARAM)
3318 continue;
3319
3320 for (i = 0; i < nparam; i++) {
3321 if (tok_text_match(t, &params[i].name))
3322 t->type = type ? type : tok_smac_param(i);
3323 }
3324 }
3325}
3326
Ed Beroset3ab3f412002-06-11 03:31:49 +00003327/**
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003328 * %clear selected macro sets either globally or in contexts
3329 */
3330static void do_clear(enum clear_what what, bool context)
3331{
3332 if (context) {
3333 if (what & CLEAR_ALLDEFINE) {
3334 Context *ctx;
3335 list_for_each(ctx, cstk)
3336 clear_smacro_table(&ctx->localmac, what);
3337 }
3338 /* Nothing else can be context-local */
3339 } else {
3340 if (what & CLEAR_ALLDEFINE)
3341 clear_smacro_table(&smacros, what);
3342 if (what & CLEAR_MMACRO)
3343 free_mmacro_table(&mmacros);
3344 }
3345}
3346
3347/**
Ed Beroset3ab3f412002-06-11 03:31:49 +00003348 * find and process preprocessor directive in passed line
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003349 * Find out if a line contains a preprocessor directive, and deal
3350 * with it if so.
H. Peter Anvin70653092007-10-19 14:42:29 -07003351 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00003352 * If a directive _is_ found, it is the responsibility of this routine
3353 * (and not the caller) to free_tlist() the line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003354 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00003355 * @param tline a pointer to the current tokeninzed line linked list
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003356 * @param output if this directive generated output
Ed Beroset3ab3f412002-06-11 03:31:49 +00003357 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
H. Peter Anvin70653092007-10-19 14:42:29 -07003358 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003359 */
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07003360static int do_directive(Token *tline, Token **output)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003361{
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003362 enum preproc_token op;
H. Peter Anvin4169a472007-09-12 01:29:43 +00003363 int j;
H. Peter Anvin70055962007-10-11 00:05:31 -07003364 bool err;
H. Peter Anvin70055962007-10-11 00:05:31 -07003365 bool nolist;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003366 bool casesense;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -07003367 int k, m;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003368 int offset;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003369 const char *p;
3370 char *q, *qbuf;
H. Peter Anvinccad6f92016-10-04 00:34:35 -07003371 const char *found_path;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003372 const char *mname;
H. Peter Anvin8b262472019-02-26 14:00:54 -08003373 struct ppscan pps;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003374 Include *inc;
3375 Context *ctx;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003376 Cond *cond;
3377 MMacro *mmac, **mmhead;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07003378 Token *t = NULL, *tt, *macro_start, *last, *origline;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003379 Line *l;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003380 struct tokenval tokval;
3381 expr *evalresult;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07003382 int64_t count;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003383 size_t len;
H. Peter Anvin (Intel)6bde2ed2018-12-13 19:39:41 -08003384 errflags severity;
H. Peter Anvin8b262472019-02-26 14:00:54 -08003385 const char *dname; /* Name of directive, for messages */
H. Peter Anvin76690a12002-04-30 20:52:49 +00003386
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003387 *output = NULL; /* No output generated */
H. Peter Anvin76690a12002-04-30 20:52:49 +00003388 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003389
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003390 tline = skip_white(tline);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003391 if (!tline || !tok_type(tline, TOK_PREPROC_ID))
3392 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003393
H. Peter Anvin8571f062019-09-23 16:40:03 -07003394 dname = tok_text(tline);
3395 if (dname[1] == '%')
3396 return NO_DIRECTIVE_FOUND;
3397
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003398 op = pp_token_hash(dname);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003399
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003400 casesense = true;
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003401 if (PP_HAS_CASE(op) & PP_INSENSITIVE(op)) {
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003402 casesense = false;
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003403 op--;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003404 }
3405
3406 /*
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07003407 * %line directives are always processed immediately and
3408 * unconditionally, as they are intended to reflect position
3409 * in externally preprocessed sources.
3410 */
3411 if (op == PP_LINE) {
3412 /*
3413 * Syntax is `%line nnn[+mmm] [filename]'
3414 */
3415 if (pp_noline || istk->mstk.mstk)
3416 goto done;
3417
3418 tline = tline->next;
3419 tline = skip_white(tline);
3420 if (!tok_type(tline, TOK_NUMBER)) {
3421 nasm_nonfatal("`%s' expects line number", dname);
3422 goto done;
3423 }
3424 k = readnum(tok_text(tline), &err);
3425 m = 1;
3426 tline = tline->next;
3427 if (tok_is(tline, '+') || tok_is(tline, '-')) {
3428 bool minus = tok_is(tline, '-');
3429 tline = tline->next;
3430 if (!tok_type(tline, TOK_NUMBER)) {
3431 nasm_nonfatal("`%s' expects line increment", dname);
3432 goto done;
3433 }
3434 m = readnum(tok_text(tline), &err);
3435 if (minus)
3436 m = -m;
3437 tline = tline->next;
3438 }
3439 tline = skip_white(tline);
3440 if (tline) {
3441 if (tline->type == TOK_STRING) {
3442 src_set_fname(unquote_token(tline));
3443 } else {
3444 char *fname = detoken(tline, false);
3445 src_set_fname(fname);
3446 nasm_free(fname);
3447 }
3448 }
3449 src_set_linnum(k);
3450
3451 istk->where = src_where();
3452 istk->lineinc = m;
3453 goto done;
3454 }
3455
3456 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003457 * If we're in a non-emitting branch of a condition construct,
3458 * or walking to the end of an already terminated %rep block,
3459 * we should ignore all directives except for condition
3460 * directives.
3461 */
3462 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07003463 (istk->mstk.mstk && !istk->mstk.mstk->in_progress)) &&
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003464 !is_condition(op)) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003465 return NO_DIRECTIVE_FOUND;
3466 }
3467
3468 /*
3469 * If we're defining a macro or reading a %rep block, we should
3470 * ignore all directives except for %macro/%imacro (which nest),
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07003471 * %endm/%endmacro, %line and (only if we're in a %rep block) %endrep.
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003472 * If we're in a %rep block, another %rep nests, so should be let through.
3473 */
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003474 if (defining && op != PP_MACRO && op != PP_RMACRO &&
3475 op != PP_ENDMACRO && op != PP_ENDM &&
3476 (defining->name || (op != PP_ENDREP && op != PP_REP))) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003477 return NO_DIRECTIVE_FOUND;
3478 }
3479
3480 if (defining) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003481 if (op == PP_MACRO || op == PP_RMACRO) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003482 nested_mac_count++;
3483 return NO_DIRECTIVE_FOUND;
3484 } else if (nested_mac_count > 0) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003485 if (op == PP_ENDMACRO) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003486 nested_mac_count--;
3487 return NO_DIRECTIVE_FOUND;
3488 }
3489 }
3490 if (!defining->name) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003491 if (op == PP_REP) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003492 nested_rep_count++;
3493 return NO_DIRECTIVE_FOUND;
3494 } else if (nested_rep_count > 0) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003495 if (op == PP_ENDREP) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003496 nested_rep_count--;
3497 return NO_DIRECTIVE_FOUND;
3498 }
3499 }
3500 }
3501 }
3502
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003503 switch (op) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003504 default:
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003505 nasm_nonfatal("unknown preprocessor directive `%s'", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003506 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003507
H. Peter Anvin3f87a2a2016-10-04 14:07:19 -07003508 case PP_PRAGMA:
3509 /*
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003510 * %pragma namespace options...
3511 *
3512 * The namespace "preproc" is reserved for the preprocessor;
3513 * all other namespaces generate a [pragma] assembly directive.
3514 *
3515 * Invalid %pragmas are ignored and may have different
3516 * meaning in future versions of NASM.
H. Peter Anvin3f87a2a2016-10-04 14:07:19 -07003517 */
H. Peter Anvinf5d7d902019-08-10 06:21:00 -07003518 t = tline;
3519 tline = tline->next;
3520 t->next = NULL;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003521 tline = zap_white(expand_smacro(tline));
3522 if (tok_type(tline, TOK_ID)) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003523 if (!nasm_stricmp(tok_text(tline), "preproc")) {
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003524 /* Preprocessor pragma */
3525 do_pragma_preproc(tline);
H. Peter Anvin06335872019-08-10 06:42:55 -07003526 free_tlist(tline);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003527 } else {
3528 /* Build the assembler directive */
H. Peter Anvin06335872019-08-10 06:42:55 -07003529
3530 /* Append bracket to the end of the output */
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003531 for (t = tline; t->next; t = t->next)
3532 ;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003533 t->next = make_tok_char(NULL, ']');
H. Peter Anvin06335872019-08-10 06:42:55 -07003534
3535 /* Prepend "[pragma " */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003536 t = new_White(tline);
H. Peter Anvin06335872019-08-10 06:42:55 -07003537 t = new_Token(t, TOK_ID, "pragma", 6);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003538 t = make_tok_char(t, '[');
H. Peter Anvin06335872019-08-10 06:42:55 -07003539 tline = t;
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07003540 *output = tline;
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003541 }
3542 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003543 break;
H. Peter Anvin3f87a2a2016-10-04 14:07:19 -07003544
H. Peter Anvine2c80182005-01-15 22:15:51 +00003545 case PP_STACKSIZE:
3546 /* Directive to tell NASM what the default stack size is. The
3547 * default is for a 16-bit stack, and this can be overriden with
3548 * %stacksize large.
H. Peter Anvine2c80182005-01-15 22:15:51 +00003549 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003550 tline = skip_white(tline->next);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003551 if (!tline || tline->type != TOK_ID) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003552 nasm_nonfatal("`%s' missing size parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003553 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07003554 if (nasm_stricmp(tok_text(tline), "flat") == 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003555 /* All subsequent ARG directives are for a 32-bit stack */
3556 StackSize = 4;
3557 StackPointer = "ebp";
3558 ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003559 LocalOffset = 0;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003560 } else if (nasm_stricmp(tok_text(tline), "flat64") == 0) {
Charles Crayne7eaf9192007-11-08 22:11:14 -08003561 /* All subsequent ARG directives are for a 64-bit stack */
3562 StackSize = 8;
3563 StackPointer = "rbp";
Per Jessen53252e02010-02-11 00:16:59 +03003564 ArgOffset = 16;
Charles Crayne7eaf9192007-11-08 22:11:14 -08003565 LocalOffset = 0;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003566 } else if (nasm_stricmp(tok_text(tline), "large") == 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003567 /* All subsequent ARG directives are for a 16-bit stack,
3568 * far function call.
3569 */
3570 StackSize = 2;
3571 StackPointer = "bp";
3572 ArgOffset = 4;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003573 LocalOffset = 0;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003574 } else if (nasm_stricmp(tok_text(tline), "small") == 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003575 /* All subsequent ARG directives are for a 16-bit stack,
3576 * far function call. We don't support near functions.
3577 */
3578 StackSize = 2;
3579 StackPointer = "bp";
3580 ArgOffset = 6;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003581 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003582 } else {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003583 nasm_nonfatal("`%s' invalid size type", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003584 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003585 break;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003586
H. Peter Anvine2c80182005-01-15 22:15:51 +00003587 case PP_ARG:
3588 /* TASM like ARG directive to define arguments to functions, in
3589 * the following form:
3590 *
3591 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
3592 */
3593 offset = ArgOffset;
3594 do {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003595 const char *arg;
3596 char directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003597 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003598
H. Peter Anvine2c80182005-01-15 22:15:51 +00003599 /* Find the argument name */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003600 tline = skip_white(tline->next);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003601 if (!tline || tline->type != TOK_ID) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003602 nasm_nonfatal("`%s' missing argument parameter", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003603 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003604 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07003605 arg = tok_text(tline);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003606
H. Peter Anvine2c80182005-01-15 22:15:51 +00003607 /* Find the argument size type */
3608 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003609 if (!tok_is(tline, ':')) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003610 nasm_nonfatal("syntax error processing `%s' directive", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003611 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003612 }
3613 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003614 if (!tok_type(tline, TOK_ID)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003615 nasm_nonfatal("`%s' missing size type parameter", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003616 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003617 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003618
H. Peter Anvine2c80182005-01-15 22:15:51 +00003619 /* Allow macro expansion of type parameter */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003620 tt = tokenize(tok_text(tline));
H. Peter Anvine2c80182005-01-15 22:15:51 +00003621 tt = expand_smacro(tt);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003622 size = parse_size(tok_text(tt));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003623 if (!size) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003624 nasm_nonfatal("invalid size type for `%s' missing directive", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003625 free_tlist(tt);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003626 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003627 }
3628 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003629
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003630 /* Round up to even stack slots */
3631 size = ALIGN(size, StackSize);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003632
H. Peter Anvine2c80182005-01-15 22:15:51 +00003633 /* Now define the macro for the argument */
3634 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
3635 arg, StackPointer, offset);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003636 do_directive(tokenize(directive), output);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003637 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003638
H. Peter Anvine2c80182005-01-15 22:15:51 +00003639 /* Move to the next argument in the list */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003640 tline = skip_white(tline->next);
3641 } while (tok_is(tline, ','));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003642 ArgOffset = offset;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003643 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003644
H. Peter Anvine2c80182005-01-15 22:15:51 +00003645 case PP_LOCAL:
3646 /* TASM like LOCAL directive to define local variables for a
3647 * function, in the following form:
3648 *
3649 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
3650 *
3651 * The '= LocalSize' at the end is ignored by NASM, but is
3652 * required by TASM to define the local parameter size (and used
3653 * by the TASM macro package).
3654 */
3655 offset = LocalOffset;
3656 do {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003657 const char *local;
3658 char directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003659 int size = StackSize;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003660
H. Peter Anvine2c80182005-01-15 22:15:51 +00003661 /* Find the argument name */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003662 tline = skip_white(tline->next);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003663 if (!tline || tline->type != TOK_ID) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003664 nasm_nonfatal("`%s' missing argument parameter", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003665 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003666 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07003667 local = tok_text(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003668
H. Peter Anvine2c80182005-01-15 22:15:51 +00003669 /* Find the argument size type */
3670 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003671 if (!tok_is(tline, ':')) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003672 nasm_nonfatal("syntax error processing `%s' directive", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003673 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003674 }
3675 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003676 if (!tok_type(tline, TOK_ID)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003677 nasm_nonfatal("`%s' missing size type parameter", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003678 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003679 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003680
H. Peter Anvine2c80182005-01-15 22:15:51 +00003681 /* Allow macro expansion of type parameter */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003682 tt = tokenize(tok_text(tline));
H. Peter Anvine2c80182005-01-15 22:15:51 +00003683 tt = expand_smacro(tt);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003684 size = parse_size(tok_text(tt));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003685 if (!size) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003686 nasm_nonfatal("invalid size type for `%s' missing directive", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003687 free_tlist(tt);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003688 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003689 }
3690 free_tlist(tt);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003691
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003692 /* Round up to even stack slots */
3693 size = ALIGN(size, StackSize);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003694
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003695 offset += size; /* Negative offset, increment before */
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003696
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003697 /* Now define the macro for the argument */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003698 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
3699 local, StackPointer, offset);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003700 do_directive(tokenize(directive), output);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003701
H. Peter Anvine2c80182005-01-15 22:15:51 +00003702 /* Now define the assign to setup the enter_c macro correctly */
3703 snprintf(directive, sizeof(directive),
3704 "%%assign %%$localsize %%$localsize+%d", size);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003705 do_directive(tokenize(directive), output);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003706
H. Peter Anvine2c80182005-01-15 22:15:51 +00003707 /* Move to the next argument in the list */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003708 tline = skip_white(tline->next);
3709 } while (tok_is(tline, ','));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003710 LocalOffset = offset;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003711 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003712
H. Peter Anvine2c80182005-01-15 22:15:51 +00003713 case PP_CLEAR:
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003714 {
3715 bool context = false;
3716
3717 t = tline->next = expand_smacro(tline->next);
3718 t = skip_white(t);
3719 if (!t) {
3720 /* Emulate legacy behavior */
3721 do_clear(CLEAR_DEFINE|CLEAR_MMACRO, false);
3722 } else {
3723 while ((t = skip_white(t)) && t->type == TOK_ID) {
3724 const char *txt = tok_text(t);
3725 if (!nasm_stricmp(txt, "all")) {
3726 do_clear(CLEAR_ALL, context);
3727 } else if (!nasm_stricmp(txt, "define") ||
3728 !nasm_stricmp(txt, "def") ||
3729 !nasm_stricmp(txt, "smacro")) {
3730 do_clear(CLEAR_DEFINE, context);
3731 } else if (!nasm_stricmp(txt, "defalias") ||
3732 !nasm_stricmp(txt, "alias") ||
3733 !nasm_stricmp(txt, "salias")) {
3734 do_clear(CLEAR_DEFALIAS, context);
3735 } else if (!nasm_stricmp(txt, "alldef") ||
3736 !nasm_stricmp(txt, "alldefine")) {
3737 do_clear(CLEAR_ALLDEFINE, context);
3738 } else if (!nasm_stricmp(txt, "macro") ||
3739 !nasm_stricmp(txt, "mmacro")) {
3740 do_clear(CLEAR_MMACRO, context);
3741 } else if (!nasm_stricmp(txt, "context") ||
3742 !nasm_stricmp(txt, "ctx")) {
3743 context = true;
3744 } else if (!nasm_stricmp(txt, "global")) {
3745 context = false;
3746 } else if (!nasm_stricmp(txt, "nothing") ||
3747 !nasm_stricmp(txt, "none") ||
3748 !nasm_stricmp(txt, "ignore") ||
3749 !nasm_stricmp(txt, "-") ||
3750 !nasm_stricmp(txt, "--")) {
3751 /* Do nothing */
3752 } else {
3753 nasm_nonfatal("invalid option to %s: %s", dname, txt);
3754 t = NULL;
3755 }
3756 }
3757 }
3758
3759 t = skip_white(t);
3760 if (t)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003761 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003762 break;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003763 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003764
H. Peter Anvin418ca702008-05-30 10:42:30 -07003765 case PP_DEPEND:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003766 t = tline->next = expand_smacro(tline->next);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003767 t = skip_white(t);
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003768 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003769 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003770 nasm_nonfatal("`%s' expects a file name", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003771 goto done;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003772 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003773 if (t->next)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003774 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003775
3776 strlist_add(deplist, unquote_token_cstr(t));
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003777 goto done;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003778
3779 case PP_INCLUDE:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003780 t = tline->next = expand_smacro(tline->next);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003781 t = skip_white(t);
H. Peter Anvind2456592008-06-19 15:04:18 -07003782
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003783 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003784 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003785 nasm_nonfatal("`%s' expects a file name", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003786 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003787 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003788 if (t->next)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003789 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003790 p = unquote_token_cstr(t);
H. Peter Anvin6686de22019-08-10 05:33:14 -07003791 nasm_new(inc);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003792 inc->next = istk;
Jim Kukunas65a8afc2016-06-13 16:00:42 -04003793 found_path = NULL;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07003794 inc->fp = inc_fopen(p, deplist, &found_path,
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08003795 (pp_mode == PP_DEPS)
3796 ? INC_OPTIONAL : INC_NEEDED, NF_TEXT);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003797 if (!inc->fp) {
3798 /* -MG given but file not found */
3799 nasm_free(inc);
3800 } else {
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07003801 src_set(0, found_path ? found_path : p);
3802 inc->where = src_where();
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003803 inc->lineinc = 1;
H. Peter Anvin6686de22019-08-10 05:33:14 -07003804 inc->nolist = istk->nolist;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003805 istk = inc;
H. Peter Anvin0d4d4312019-08-07 00:46:27 -07003806 lfmt->uplevel(LIST_INCLUDE, 0);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003807 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003808 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003809
H. Peter Anvind2456592008-06-19 15:04:18 -07003810 case PP_USE:
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07003811 {
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07003812 const struct use_package *pkg;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003813 const char *name;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07003814
H. Peter Anvin8571f062019-09-23 16:40:03 -07003815 pkg = get_use_pkg(tline->next, dname, &name);
3816 if (!name)
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003817 goto done;
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07003818 if (!pkg) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003819 nasm_nonfatal("unknown `%s' package: `%s'", dname, name);
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07003820 } else if (!use_loaded[pkg->index]) {
H. Peter Anvin6686de22019-08-10 05:33:14 -07003821 /*
3822 * Not already included, go ahead and include it.
3823 * Treat it as an include file for the purpose of
3824 * producing a listing.
3825 */
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07003826 use_loaded[pkg->index] = true;
3827 stdmacpos = pkg->macros;
H. Peter Anvin6686de22019-08-10 05:33:14 -07003828 nasm_new(inc);
3829 inc->next = istk;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07003830 src_set(0, NULL);
H. Peter Anvin6686de22019-08-10 05:33:14 -07003831 inc->nolist = !list_option('b') || istk->nolist;
3832 istk = inc;
3833 lfmt->uplevel(LIST_INCLUDE, 0);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003834 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003835 break;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07003836 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003837 case PP_PUSH:
H. Peter Anvine2c80182005-01-15 22:15:51 +00003838 case PP_REPL:
H. Peter Anvin42b56392008-10-24 16:24:21 -07003839 case PP_POP:
H. Peter Anvine2c80182005-01-15 22:15:51 +00003840 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003841 tline = skip_white(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003842 tline = expand_id(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003843 if (tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003844 if (!tok_type(tline, TOK_ID)) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003845 nasm_nonfatal("`%s' expects a context identifier", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003846 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003847 }
3848 if (tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003849 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored",
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003850 dname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003851 p = tok_text(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003852 } else {
3853 p = NULL; /* Anonymous */
3854 }
H. Peter Anvin42b56392008-10-24 16:24:21 -07003855
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003856 if (op == PP_PUSH) {
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08003857 nasm_new(ctx);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07003858 ctx->depth = cstk ? cstk->depth + 1 : 1;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003859 ctx->next = cstk;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003860 ctx->name = p ? nasm_strdup(p) : NULL;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003861 ctx->number = unique++;
3862 cstk = ctx;
3863 } else {
3864 /* %pop or %repl */
3865 if (!cstk) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003866 nasm_nonfatal("`%s': context stack is empty", dname);
3867 } else if (op == PP_POP) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003868 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003869 nasm_nonfatal("`%s' in wrong context: %s, "
H. Peter Anvin8b262472019-02-26 14:00:54 -08003870 "expected %s",
3871 dname, cstk->name ? cstk->name : "anonymous", p);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003872 else
3873 ctx_pop();
3874 } else {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003875 /* op == PP_REPL */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003876 nasm_free((char *)cstk->name);
3877 cstk->name = p ? nasm_strdup(p) : NULL;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003878 p = NULL;
3879 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003880 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003881 break;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07003882 case PP_FATAL:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003883 severity = ERR_FATAL;
3884 goto issue_error;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003885 case PP_ERROR:
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003886 severity = ERR_NONFATAL|ERR_PASS2;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003887 goto issue_error;
H. Peter Anvin7df04172008-06-10 18:27:38 -07003888 case PP_WARNING:
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -08003889 /*!
3890 *!user [on] %warning directives
3891 *! controls output of \c{%warning} directives (see \k{pperror}).
3892 */
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003893 severity = ERR_WARNING|WARN_USER|ERR_PASS2;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003894 goto issue_error;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07003895
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003896issue_error:
H. Peter Anvin7df04172008-06-10 18:27:38 -07003897 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003898 /* Only error out if this is the final pass */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003899 tline->next = expand_smacro(tline->next);
3900 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003901 tline = skip_white(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003902 t = tline ? tline->next : NULL;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003903 t = skip_white(t);
3904 if (tok_type(tline, TOK_STRING) && !t) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003905 /* The line contains only a quoted string */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003906 p = unquote_token(tline); /* Ignore NUL character truncation */
H. Peter Anvin130736c2016-02-17 20:27:41 -08003907 nasm_error(severity, "%s", p);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003908 } else {
3909 /* Not a quoted string, or more than a quoted string */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003910 q = detoken(tline, false);
3911 nasm_error(severity, "%s", q);
3912 nasm_free(q);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003913 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003914 break;
H. Peter Anvin7df04172008-06-10 18:27:38 -07003915 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003916
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00003917 CASE_PP_IF:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003918 if (istk->conds && !emitting(istk->conds->state))
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003919 j = COND_NEVER;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003920 else {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003921 j = if_condition(tline->next, op);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003922 tline->next = NULL; /* it got freed */
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003923 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003924 cond = nasm_malloc(sizeof(Cond));
3925 cond->next = istk->conds;
3926 cond->state = j;
3927 istk->conds = cond;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07003928 if(istk->mstk.mstk)
3929 istk->mstk.mstk->condcnt++;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003930 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003931
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00003932 CASE_PP_ELIF:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003933 if (!istk->conds)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003934 nasm_fatal("`%s': no matching `%%if'", dname);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003935 switch(istk->conds->state) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003936 case COND_IF_TRUE:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003937 istk->conds->state = COND_DONE;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003938 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003939
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003940 case COND_DONE:
3941 case COND_NEVER:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003942 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003943
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003944 case COND_ELSE_TRUE:
3945 case COND_ELSE_FALSE:
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003946 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003947 "`%%elif' after `%%else' ignored");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003948 istk->conds->state = COND_NEVER;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003949 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003950
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003951 case COND_IF_FALSE:
3952 /*
3953 * IMPORTANT: In the case of %if, we will already have
3954 * called expand_mmac_params(); however, if we're
3955 * processing an %elif we must have been in a
3956 * non-emitting mode, which would have inhibited
3957 * the normal invocation of expand_mmac_params().
3958 * Therefore, we have to do it explicitly here.
3959 */
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003960 j = if_condition(expand_mmac_params(tline->next), op);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003961 tline->next = NULL; /* it got freed */
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003962 istk->conds->state = j;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003963 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003964 }
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003965 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003966
H. Peter Anvine2c80182005-01-15 22:15:51 +00003967 case PP_ELSE:
3968 if (tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003969 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003970 "trailing garbage after `%%else' ignored");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003971 if (!istk->conds)
H. Peter Anvinc5136902018-06-15 18:20:17 -07003972 nasm_fatal("`%%else: no matching `%%if'");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003973 switch(istk->conds->state) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003974 case COND_IF_TRUE:
3975 case COND_DONE:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003976 istk->conds->state = COND_ELSE_FALSE;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003977 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003978
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003979 case COND_NEVER:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003980 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003981
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003982 case COND_IF_FALSE:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003983 istk->conds->state = COND_ELSE_TRUE;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003984 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003985
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003986 case COND_ELSE_TRUE:
3987 case COND_ELSE_FALSE:
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003988 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003989 "`%%else' after `%%else' ignored.");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003990 istk->conds->state = COND_NEVER;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003991 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003992 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003993 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003994
H. Peter Anvine2c80182005-01-15 22:15:51 +00003995 case PP_ENDIF:
3996 if (tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003997 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003998 "trailing garbage after `%%endif' ignored");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003999 if (!istk->conds)
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004000 nasm_fatal("`%%endif': no matching `%%if'");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004001 cond = istk->conds;
4002 istk->conds = cond->next;
4003 nasm_free(cond);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004004 if(istk->mstk.mstk)
4005 istk->mstk.mstk->condcnt--;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004006 break;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004007
H. Peter Anvin8b262472019-02-26 14:00:54 -08004008 case PP_RMACRO:
4009 case PP_MACRO:
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07004010 {
4011 MMacro *def;
4012
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004013 nasm_assert(!defining);
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07004014 nasm_new(def);
4015 def->casesense = casesense;
4016 def->dstk.mmac = defining;
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004017 if (op == PP_RMACRO)
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07004018 def->max_depth = nasm_limit[LIMIT_MACRO_LEVELS];
4019 if (!parse_mmacro_spec(tline, def, dname)) {
4020 nasm_free(def);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004021 goto done;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004022 }
H. Peter Anvina26433d2008-07-16 14:40:01 -07004023
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07004024 defining = def;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07004025 defining->where = istk->where;
H. Peter Anvin4def1a82016-05-09 13:59:44 -07004026
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004027 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
4028 while (mmac) {
4029 if (!strcmp(mmac->name, defining->name) &&
4030 (mmac->nparam_min <= defining->nparam_max
4031 || defining->plus)
4032 && (defining->nparam_min <= mmac->nparam_max
4033 || mmac->plus)) {
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08004034 nasm_warn(WARN_OTHER, "redefining multi-line macro `%s'",
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004035 defining->name);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004036 break;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004037 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004038 mmac = mmac->next;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004039 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004040 break;
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07004041 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004042
H. Peter Anvine2c80182005-01-15 22:15:51 +00004043 case PP_ENDM:
4044 case PP_ENDMACRO:
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004045 if (!(defining && defining->name)) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004046 nasm_nonfatal("`%s': not defining a macro", tok_text(tline));
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004047 goto done;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004048 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004049 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
4050 defining->next = *mmhead;
4051 *mmhead = defining;
4052 defining = NULL;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004053 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004054
H. Peter Anvin89cee572009-07-15 09:16:54 -04004055 case PP_EXITMACRO:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004056 /*
4057 * We must search along istk->expansion until we hit a
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004058 * macro-end marker for a macro with a name. Then we
4059 * bypass all lines between exitmacro and endmacro.
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004060 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004061 list_for_each(l, istk->expansion)
4062 if (l->finishes && l->finishes->name)
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004063 break;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004064
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004065 if (l) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004066 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004067 * Remove all conditional entries relative to this
4068 * macro invocation. (safe to do in this context)
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004069 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004070 for ( ; l->finishes->condcnt > 0; l->finishes->condcnt --) {
4071 cond = istk->conds;
4072 istk->conds = cond->next;
4073 nasm_free(cond);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004074 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004075 istk->expansion = l;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004076 } else {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004077 nasm_nonfatal("`%%exitmacro' not within `%%macro' block");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004078 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004079 break;
Keith Kanios852f1ee2009-07-12 00:19:55 -05004080
H. Peter Anvina26433d2008-07-16 14:40:01 -07004081 case PP_UNIMACRO:
H. Peter Anvin8b262472019-02-26 14:00:54 -08004082 casesense = false;
4083 /* fall through */
4084 case PP_UNMACRO:
H. Peter Anvina26433d2008-07-16 14:40:01 -07004085 {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004086 MMacro **mmac_p;
4087 MMacro spec;
H. Peter Anvina26433d2008-07-16 14:40:01 -07004088
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004089 nasm_zero(spec);
H. Peter Anvin8b262472019-02-26 14:00:54 -08004090 spec.casesense = casesense;
4091 if (!parse_mmacro_spec(tline, &spec, dname)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004092 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004093 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004094 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
4095 while (mmac_p && *mmac_p) {
4096 mmac = *mmac_p;
4097 if (mmac->casesense == spec.casesense &&
4098 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
4099 mmac->nparam_min == spec.nparam_min &&
4100 mmac->nparam_max == spec.nparam_max &&
4101 mmac->plus == spec.plus) {
4102 *mmac_p = mmac->next;
4103 free_mmacro(mmac);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004104 } else {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004105 mmac_p = &mmac->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004106 }
4107 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004108 free_tlist(spec.dlist);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004109 break;
H. Peter Anvina26433d2008-07-16 14:40:01 -07004110 }
4111
H. Peter Anvine2c80182005-01-15 22:15:51 +00004112 case PP_ROTATE:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004113 while (tok_white(tline->next))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004114 tline = tline->next;
H. Peter Anvin89cee572009-07-15 09:16:54 -04004115 if (!tline->next) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004116 free_tlist(origline);
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004117 nasm_nonfatal("`%%rotate' missing rotate count");
H. Peter Anvine2c80182005-01-15 22:15:51 +00004118 return DIRECTIVE_FOUND;
4119 }
4120 t = expand_smacro(tline->next);
4121 tline->next = NULL;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004122 pps.tptr = tline = t;
4123 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004124 tokval.t_type = TOKEN_INVALID;
4125 evalresult =
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004126 evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004127 free_tlist(tline);
4128 if (!evalresult)
4129 return DIRECTIVE_FOUND;
4130 if (tokval.t_type)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08004131 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00004132 if (!is_simple(evalresult)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004133 nasm_nonfatal("non-constant value given to `%%rotate'");
H. Peter Anvine2c80182005-01-15 22:15:51 +00004134 return DIRECTIVE_FOUND;
4135 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004136 mmac = istk->mstk.mmac;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004137 if (!mmac) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004138 nasm_nonfatal("`%%rotate' invoked outside a macro call");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004139 } else if (mmac->nparam == 0) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004140 nasm_nonfatal("`%%rotate' invoked within macro without parameters");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004141 } else {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004142 int rotate = mmac->rotate + reloc_value(evalresult);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004143
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004144 rotate %= (int)mmac->nparam;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004145 if (rotate < 0)
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004146 rotate += mmac->nparam;
4147
4148 mmac->rotate = rotate;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004149 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004150 break;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00004151
H. Peter Anvine2c80182005-01-15 22:15:51 +00004152 case PP_REP:
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004153 {
4154 MMacro *tmp_defining;
4155
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004156 nolist = false;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004157 tline = skip_white(tline->next);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004158 if (tok_type(tline, TOK_ID) && tline->len == 7 &&
4159 !nasm_memicmp(tline->text.a, ".nolist", 7)) {
H. Peter Anvin6686de22019-08-10 05:33:14 -07004160 nolist = !list_option('f') || istk->nolist;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004161 tline = skip_white(tline->next);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004162 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00004163
H. Peter Anvine2c80182005-01-15 22:15:51 +00004164 if (tline) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08004165 pps.tptr = expand_smacro(tline);
4166 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004167 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004168 /* XXX: really critical?! */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004169 evalresult =
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004170 evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004171 if (!evalresult)
4172 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004173 if (tokval.t_type)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08004174 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00004175 if (!is_simple(evalresult)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004176 nasm_nonfatal("non-constant value given to `%%rep'");
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004177 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004178 }
Cyrill Gorcunove091d6e2010-08-09 13:58:22 +04004179 count = reloc_value(evalresult);
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07004180 if (count > nasm_limit[LIMIT_REP]) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004181 nasm_nonfatal("`%%rep' count %"PRId64" exceeds limit (currently %"PRId64")",
4182 count, nasm_limit[LIMIT_REP]);
Cyrill Gorcunove091d6e2010-08-09 13:58:22 +04004183 count = 0;
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07004184 } else if (count < 0) {
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -08004185 /*!
4186 *!negative-rep [on] regative %rep count
4187 *! warns about negative counts given to the \c{%rep}
4188 *! preprocessor directive.
4189 */
H. Peter Anvin (Intel)80c4f232018-12-14 13:33:24 -08004190 nasm_warn(ERR_PASS2|WARN_NEGATIVE_REP,
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07004191 "negative `%%rep' count: %"PRId64, count);
4192 count = 0;
4193 } else {
Cyrill Gorcunove091d6e2010-08-09 13:58:22 +04004194 count++;
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07004195 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004196 } else {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004197 nasm_nonfatal("`%%rep' expects a repeat count");
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07004198 count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004199 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004200 tmp_defining = defining;
H. Peter Anvinab6f8312019-08-09 22:31:45 -07004201 nasm_new(defining);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004202 defining->nolist = nolist;
4203 defining->in_progress = count;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004204 defining->mstk = istk->mstk;
4205 defining->dstk.mstk = tmp_defining;
4206 defining->dstk.mmac = tmp_defining ? tmp_defining->dstk.mmac : NULL;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07004207 defining->where = istk->where;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004208 break;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004209 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004210
H. Peter Anvine2c80182005-01-15 22:15:51 +00004211 case PP_ENDREP:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004212 if (!defining || defining->name) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004213 nasm_nonfatal("`%%endrep': no matching `%%rep'");
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004214 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004215 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004216
H. Peter Anvine2c80182005-01-15 22:15:51 +00004217 /*
4218 * Now we have a "macro" defined - although it has no name
4219 * and we won't be entering it in the hash tables - we must
4220 * push a macro-end marker for it on to istk->expansion.
4221 * After that, it will take care of propagating itself (a
4222 * macro-end marker line for a macro which is really a %rep
4223 * block will cause the macro to be re-expanded, complete
4224 * with another macro-end marker to ensure the process
4225 * continues) until the whole expansion is forcibly removed
4226 * from istk->expansion by a %exitrep.
4227 */
H. Peter Anvin6686de22019-08-10 05:33:14 -07004228 nasm_new(l);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004229 l->next = istk->expansion;
4230 l->finishes = defining;
4231 l->first = NULL;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07004232 l->where = src_where();
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004233 istk->expansion = l;
4234
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004235 istk->mstk.mstk = defining;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004236
H. Peter Anvin0d4d4312019-08-07 00:46:27 -07004237 lfmt->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004238 defining = defining->dstk.mstk;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004239 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004240
H. Peter Anvine2c80182005-01-15 22:15:51 +00004241 case PP_EXITREP:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004242 /*
4243 * We must search along istk->expansion until we hit a
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004244 * macro-end marker for a macro with no name. Then we set
4245 * its `in_progress' flag to 0.
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004246 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004247 list_for_each(l, istk->expansion)
4248 if (l->finishes && !l->finishes->name)
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004249 break;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004250
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004251 if (l)
H. Peter Anvind983b622019-10-07 21:19:32 -07004252 l->finishes->in_progress = 0;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004253 else
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004254 nasm_nonfatal("`%%exitrep' not within `%%rep' block");
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004255 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004256
H. Peter Anvin8b262472019-02-26 14:00:54 -08004257 case PP_DEFINE:
4258 case PP_XDEFINE:
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004259 case PP_DEFALIAS:
H. Peter Anvin8b262472019-02-26 14:00:54 -08004260 {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004261 SMacro tmpl;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07004262 Token **lastp;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07004263 int nparam;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07004264
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004265 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004266 goto done;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004267
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004268 nasm_zero(tmpl);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07004269 lastp = &tline->next;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07004270 nparam = parse_smacro_template(&lastp, &tmpl);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07004271 tline = *lastp;
4272 *lastp = NULL;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004273
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004274 if (unlikely(op == PP_DEFALIAS)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004275 macro_start = tline;
4276 if (!is_macro_id(macro_start)) {
4277 nasm_nonfatal("`%s' expects a macro identifier to alias",
4278 dname);
4279 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004280 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004281 tt = macro_start->next;
4282 macro_start->next = NULL;
4283 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004284 tline = skip_white(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004285 if (tline && tline->type) {
4286 nasm_warn(WARN_OTHER,
4287 "trailing garbage after aliasing identifier ignored");
4288 }
4289 free_tlist(tt);
4290 tmpl.alias = true;
4291 } else {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004292 if (op == PP_XDEFINE) {
4293 /* Protect macro parameter tokens */
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07004294 if (nparam)
4295 mark_smac_params(tline, &tmpl, TOK_XDEF_PARAM);
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004296 tline = expand_smacro(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004297 }
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004298 /* NB: Does this still make sense? */
4299 macro_start = reverse_tokens(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004300 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004301
H. Peter Anvine2c80182005-01-15 22:15:51 +00004302 /*
4303 * Good. We now have a macro name, a parameter count, and a
4304 * token list (in reverse order) for an expansion. We ought
4305 * to be OK just to create an SMacro, store it, and let
4306 * free_tlist have the rest of the line (which we have
4307 * carefully re-terminated after chopping off the expansion
4308 * from the end).
4309 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004310 define_smacro(mname, casesense, macro_start, &tmpl);
4311 break;
4312 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004313
H. Peter Anvine2c80182005-01-15 22:15:51 +00004314 case PP_UNDEF:
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004315 case PP_UNDEFALIAS:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004316 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004317 goto done;
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004318 if (tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08004319 nasm_warn(WARN_OTHER, "trailing garbage after macro name ignored");
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004320
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004321 undef_smacro(mname, op == PP_UNDEFALIAS);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004322 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004323
H. Peter Anvin8b262472019-02-26 14:00:54 -08004324 case PP_DEFSTR:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004325 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004326 goto done;
H. Peter Anvin9e200162008-06-04 17:23:14 -07004327
H. Peter Anvin9e200162008-06-04 17:23:14 -07004328 last = tline;
4329 tline = expand_smacro(tline->next);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004330 last->next = NULL;
H. Peter Anvin9e200162008-06-04 17:23:14 -07004331
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004332 tline = zap_white(tline);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004333 q = detoken(tline, false);
4334 macro_start = make_tok_qstr(NULL, q);
4335 nasm_free(q);
H. Peter Anvin9e200162008-06-04 17:23:14 -07004336
4337 /*
4338 * We now have a macro name, an implicit parameter count of
4339 * zero, and a string token to use as an expansion. Create
4340 * and store an SMacro.
4341 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004342 define_smacro(mname, casesense, macro_start, NULL);
4343 break;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004344
H. Peter Anvin8b262472019-02-26 14:00:54 -08004345 case PP_DEFTOK:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004346 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004347 goto done;
4348
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004349 last = tline;
4350 tline = expand_smacro(tline->next);
4351 last->next = NULL;
4352
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004353 t = skip_white(tline);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004354 /* t should now point to the string */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004355 if (!tok_type(t, TOK_STRING)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004356 nasm_nonfatal("`%s' requires string as second parameter", dname);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004357 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004358 goto done;
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004359 }
4360
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04004361 /*
4362 * Convert the string to a token stream. Note that smacros
4363 * are stored with the token stream reversed, so we have to
4364 * reverse the output of tokenize().
4365 */
H. Peter Anvin8571f062019-09-23 16:40:03 -07004366 macro_start = reverse_tokens(tokenize(unquote_token_cstr(t)));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004367
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004368 /*
4369 * We now have a macro name, an implicit parameter count of
4370 * zero, and a numeric token to use as an expansion. Create
4371 * and store an SMacro.
4372 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004373 define_smacro(mname, casesense, macro_start, NULL);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004374 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004375 break;
H. Peter Anvin9e200162008-06-04 17:23:14 -07004376
H. Peter Anvin418ca702008-05-30 10:42:30 -07004377 case PP_PATHSEARCH:
4378 {
H. Peter Anvinccad6f92016-10-04 00:34:35 -07004379 const char *found_path;
H. Peter Anvin418ca702008-05-30 10:42:30 -07004380
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004381 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004382 goto done;
4383
H. Peter Anvin418ca702008-05-30 10:42:30 -07004384 last = tline;
4385 tline = expand_smacro(tline->next);
4386 last->next = NULL;
4387
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004388 t = skip_white(tline);
H. Peter Anvin418ca702008-05-30 10:42:30 -07004389 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004390 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004391 nasm_nonfatal("`%s' expects a file name", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004392 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004393 goto done;
H. Peter Anvin418ca702008-05-30 10:42:30 -07004394 }
4395 if (t->next)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004396 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004397
4398 p = unquote_token_cstr(t);
H. Peter Anvin418ca702008-05-30 10:42:30 -07004399
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07004400 inc_fopen(p, NULL, &found_path, INC_PROBE, NF_BINARY);
H. Peter Anvinccad6f92016-10-04 00:34:35 -07004401 if (!found_path)
4402 found_path = p;
H. Peter Anvin8571f062019-09-23 16:40:03 -07004403 macro_start = make_tok_qstr(NULL, found_path);
H. Peter Anvin418ca702008-05-30 10:42:30 -07004404
4405 /*
4406 * We now have a macro name, an implicit parameter count of
4407 * zero, and a string token to use as an expansion. Create
4408 * and store an SMacro.
4409 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004410 define_smacro(mname, casesense, macro_start, NULL);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004411 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004412 break;
H. Peter Anvin418ca702008-05-30 10:42:30 -07004413 }
4414
H. Peter Anvine2c80182005-01-15 22:15:51 +00004415 case PP_STRLEN:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004416 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004417 goto done;
4418
H. Peter Anvine2c80182005-01-15 22:15:51 +00004419 last = tline;
4420 tline = expand_smacro(tline->next);
4421 last->next = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004422
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004423 t = skip_white(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004424 /* t should now point to the string */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004425 if (!tok_type(t, TOK_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004426 nasm_nonfatal("`%s' requires string as second parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004427 free_tlist(tline);
4428 free_tlist(origline);
4429 return DIRECTIVE_FOUND;
4430 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004431
H. Peter Anvin8571f062019-09-23 16:40:03 -07004432 unquote_token(t);
4433 macro_start = make_tok_num(NULL, t->len);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004434
H. Peter Anvine2c80182005-01-15 22:15:51 +00004435 /*
4436 * We now have a macro name, an implicit parameter count of
4437 * zero, and a numeric token to use as an expansion. Create
4438 * and store an SMacro.
4439 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004440 define_smacro(mname, casesense, macro_start, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004441 free_tlist(tline);
4442 free_tlist(origline);
4443 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004444
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004445 case PP_STRCAT:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004446 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004447 goto done;
4448
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004449 last = tline;
4450 tline = expand_smacro(tline->next);
4451 last->next = NULL;
4452
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004453 len = 0;
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04004454 list_for_each(t, tline) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004455 switch (t->type) {
4456 case TOK_WHITESPACE:
4457 break;
4458 case TOK_STRING:
H. Peter Anvin8571f062019-09-23 16:40:03 -07004459 unquote_token(t);
4460 len += t->len;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004461 break;
4462 case TOK_OTHER:
H. Peter Anvin8571f062019-09-23 16:40:03 -07004463 if (tok_is(t, ',')) /* permit comma separators */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004464 break;
4465 /* else fall through */
4466 default:
H. Peter Anvin8571f062019-09-23 16:40:03 -07004467 nasm_nonfatal("non-string passed to `%s': %s", dname,
4468 tok_text(t));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004469 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004470 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004471 }
4472 }
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004473
H. Peter Anvin (Intel)f770ce82019-10-17 18:22:43 -07004474 q = qbuf = nasm_malloc(len+1);
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04004475 list_for_each(t, tline) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004476 if (t->type == TOK_INTERNAL_STRING)
4477 q = mempcpy(q, tok_text(t), t->len);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004478 }
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07004479 *q = '\0';
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004480
4481 /*
4482 * We now have a macro name, an implicit parameter count of
4483 * zero, and a numeric token to use as an expansion. Create
4484 * and store an SMacro.
4485 */
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07004486 macro_start = make_tok_qstr_len(NULL, qbuf, len);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004487 nasm_free(qbuf);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004488 define_smacro(mname, casesense, macro_start, NULL);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004489 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004490 break;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004491
H. Peter Anvine2c80182005-01-15 22:15:51 +00004492 case PP_SUBSTR:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004493 {
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004494 int64_t start, count;
H. Peter Anvin8571f062019-09-23 16:40:03 -07004495 const char *txt;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004496 size_t len;
H. Peter Anvind2456592008-06-19 15:04:18 -07004497
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004498 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004499 goto done;
4500
H. Peter Anvine2c80182005-01-15 22:15:51 +00004501 last = tline;
4502 tline = expand_smacro(tline->next);
4503 last->next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004504
Cyrill Gorcunov35519d62010-09-06 23:49:52 +04004505 if (tline) /* skip expanded id */
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004506 t = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004507
4508 t = skip_white(t);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004509
H. Peter Anvine2c80182005-01-15 22:15:51 +00004510 /* t should now point to the string */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004511 if (!tok_type(t, TOK_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004512 nasm_nonfatal("`%s' requires string as second parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004513 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004514 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004515 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004516
H. Peter Anvin8b262472019-02-26 14:00:54 -08004517 pps.tptr = t->next;
4518 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004519 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004520 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004521 if (!evalresult) {
4522 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004523 goto done;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004524 } else if (!is_simple(evalresult)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004525 nasm_nonfatal("non-constant value given to `%s'", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004526 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004527 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004528 }
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004529 start = evalresult->value - 1;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004530
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004531 pps.tptr = skip_white(pps.tptr);
H. Peter Anvin8b262472019-02-26 14:00:54 -08004532 if (!pps.tptr) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004533 count = 1; /* Backwards compatibility: one character */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004534 } else {
4535 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004536 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004537 if (!evalresult) {
4538 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004539 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004540 } else if (!is_simple(evalresult)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004541 nasm_nonfatal("non-constant value given to `%s'", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004542 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004543 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004544 }
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004545 count = evalresult->value;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004546 }
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004547
H. Peter Anvin8571f062019-09-23 16:40:03 -07004548 unquote_token(t);
4549 len = t->len;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004550
Cyrill Gorcunovcff031e2010-09-07 20:31:11 +04004551 /* make start and count being in range */
4552 if (start < 0)
4553 start = 0;
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004554 if (count < 0)
4555 count = len + count + 1 - start;
4556 if (start + count > (int64_t)len)
Cyrill Gorcunovcff031e2010-09-07 20:31:11 +04004557 count = len - start;
4558 if (!len || count < 0 || start >=(int64_t)len)
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004559 start = -1, count = 0; /* empty string */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004560
H. Peter Anvin8571f062019-09-23 16:40:03 -07004561 txt = (start < 0) ? "" : tok_text(t) + start;
4562 len = count;
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07004563 macro_start = make_tok_qstr_len(NULL, txt, len);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004564
H. Peter Anvine2c80182005-01-15 22:15:51 +00004565 /*
4566 * We now have a macro name, an implicit parameter count of
4567 * zero, and a numeric token to use as an expansion. Create
4568 * and store an SMacro.
4569 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004570 define_smacro(mname, casesense, macro_start, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004571 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004572 break;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004573 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004574
H. Peter Anvin8b262472019-02-26 14:00:54 -08004575 case PP_ASSIGN:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004576 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004577 goto done;
4578
H. Peter Anvine2c80182005-01-15 22:15:51 +00004579 last = tline;
4580 tline = expand_smacro(tline->next);
4581 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004582
H. Peter Anvin8b262472019-02-26 14:00:54 -08004583 pps.tptr = tline;
4584 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004585 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004586 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004587 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004588 if (!evalresult)
4589 goto done;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004590
H. Peter Anvine2c80182005-01-15 22:15:51 +00004591 if (tokval.t_type)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08004592 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
H. Peter Anvin734b1882002-04-30 21:01:08 +00004593
H. Peter Anvine2c80182005-01-15 22:15:51 +00004594 if (!is_simple(evalresult)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004595 nasm_nonfatal("non-constant value given to `%s'", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004596 free_tlist(origline);
4597 return DIRECTIVE_FOUND;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004598 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004599
H. Peter Anvin8571f062019-09-23 16:40:03 -07004600 macro_start = make_tok_num(NULL, reloc_value(evalresult));
H. Peter Anvin734b1882002-04-30 21:01:08 +00004601
H. Peter Anvine2c80182005-01-15 22:15:51 +00004602 /*
4603 * We now have a macro name, an implicit parameter count of
4604 * zero, and a numeric token to use as an expansion. Create
4605 * and store an SMacro.
4606 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004607 define_smacro(mname, casesense, macro_start, NULL);
4608 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004609
H. Peter Anvind2354082019-08-27 16:38:48 -07004610 case PP_ALIASES:
4611 tline = tline->next;
4612 tline = expand_smacro(tline);
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07004613 ppopt.noaliases = !pp_get_boolean_option(tline, !ppopt.noaliases);
H. Peter Anvind2354082019-08-27 16:38:48 -07004614 break;
4615
H. Peter Anvine2c80182005-01-15 22:15:51 +00004616 case PP_LINE:
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07004617 nasm_panic("`%s' directive not preprocessed early", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004618 break;
4619 }
4620
4621done:
H. Peter Anvine2c80182005-01-15 22:15:51 +00004622 free_tlist(origline);
4623 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004624}
4625
4626/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00004627 * Ensure that a macro parameter contains a condition code and
4628 * nothing else. Return the condition code index if so, or -1
4629 * otherwise.
4630 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004631static int find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004632{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004633 Token *tt;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004634
H. Peter Anvin25a99342007-09-22 17:45:45 -07004635 if (!t)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004636 return -1; /* Probably a %+ without a space */
H. Peter Anvin25a99342007-09-22 17:45:45 -07004637
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004638 t = skip_white(t);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004639 if (!tok_type(t, TOK_ID))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004640 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004641 tt = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004642 tt = skip_white(tt);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004643 if (tok_isnt(tt, ','))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004644 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004645
H. Peter Anvin8571f062019-09-23 16:40:03 -07004646 return bsii(tok_text(t), (const char **)conditions,
4647 ARRAY_SIZE(conditions));
H. Peter Anvin76690a12002-04-30 20:52:49 +00004648}
4649
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004650static inline bool pp_concat_match(const Token *t, unsigned int mask)
4651{
4652 return t && (PP_CONCAT_MASK(t->type) & mask);
4653}
4654
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004655/*
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07004656 * This routines walks over tokens strem and handles tokens
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004657 * pasting, if @handle_explicit passed then explicit pasting
4658 * term is handled, otherwise -- implicit pastings only.
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07004659 * The @m array can contain a series of token types which are
4660 * executed as separate passes.
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004661 */
Cyrill Gorcunov575d4282010-10-06 00:25:55 +04004662static bool paste_tokens(Token **head, const struct tokseq_match *m,
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004663 size_t mnum, bool handle_explicit)
H. Peter Anvind784a082009-04-20 14:01:18 -07004664{
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004665 Token *tok, *t, *next, **prev_next, **prev_nonspace;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004666 bool pasted = false;
4667 char *buf, *p;
4668 size_t len, i;
H. Peter Anvind784a082009-04-20 14:01:18 -07004669
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004670 /*
4671 * The last token before pasting. We need it
4672 * to be able to connect new handled tokens.
4673 * In other words if there were a tokens stream
4674 *
4675 * A -> B -> C -> D
4676 *
4677 * and we've joined tokens B and C, the resulting
4678 * stream should be
4679 *
4680 * A -> BC -> D
4681 */
4682 tok = *head;
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004683 prev_next = prev_nonspace = head;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004684
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004685 if (tok_white(tok) || tok_type(tok, TOK_PASTE))
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004686 prev_nonspace = NULL;
4687
4688 while (tok && (next = tok->next)) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004689 bool did_paste = false;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004690
4691 switch (tok->type) {
H. Peter Anvind784a082009-04-20 14:01:18 -07004692 case TOK_WHITESPACE:
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004693 /* Zap redundant whitespaces */
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004694 tok->next = next = zap_white(next);
H. Peter Anvind784a082009-04-20 14:01:18 -07004695 break;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004696
4697 case TOK_PASTE:
4698 /* Explicit pasting */
4699 if (!handle_explicit)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004700 break;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004701
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004702 /* Left pasting token is start of line */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004703 if (!prev_nonspace) {
4704 nasm_nonfatal("No lvalue found on pasting");
4705 tok = delete_Token(tok);
4706 break;
4707 }
4708
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004709 did_paste = true;
4710
4711 prev_next = prev_nonspace;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004712 t = *prev_nonspace;
4713
4714 /* Delete leading whitespace */
4715 next = zap_white(t->next);
4716
4717 /* Delete the %+ token itself */
4718 nasm_assert(next == tok);
4719 next = delete_Token(next);
4720
4721 /* Delete trailing whitespace */
4722 next = zap_white(next);
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004723
Cyrill Gorcunov8b5c9fb2013-02-04 01:24:54 +04004724 /*
4725 * No ending token, this might happen in two
4726 * cases
4727 *
4728 * 1) There indeed no right token at all
4729 * 2) There is a bare "%define ID" statement,
4730 * and @ID does expand to whitespace.
4731 *
4732 * So technically we need to do a grammar analysis
4733 * in another stage of parsing, but for now lets don't
4734 * change the behaviour people used to. Simply allow
4735 * whitespace after paste token.
4736 */
4737 if (!next) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004738 *prev_nonspace = tok = NULL; /* End of line */
Cyrill Gorcunov8b5c9fb2013-02-04 01:24:54 +04004739 break;
4740 }
4741
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004742 p = buf = nasm_malloc(t->len + next->len + 1);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004743 p = mempcpy(p, tok_text(t), t->len);
4744 p = mempcpy(p, tok_text(next), next->len);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004745 *p = '\0';
4746 delete_Token(t);
4747 t = tokenize(buf);
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004748 nasm_free(buf);
4749
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004750 if (unlikely(!t)) {
4751 /*
4752 * No output at all? Replace with a single whitespace.
4753 * This should never happen.
4754 */
4755 t = new_White(NULL);
4756 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004757
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004758 *prev_nonspace = tok = t;
4759 while (t->next)
4760 t = t->next; /* Find the last token produced */
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004761
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004762 /* Delete the second token and attach to the end of the list */
4763 t->next = delete_Token(next);
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004764
4765 /* We want to restart from the head of the pasted token */
4766 next = tok;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004767 break;
4768
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004769 default:
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004770 /* implicit pasting */
Cyrill Gorcunov575d4282010-10-06 00:25:55 +04004771 for (i = 0; i < mnum; i++) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004772 if (pp_concat_match(tok, m[i].mask_head))
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004773 break;
Cyrill Gorcunov575d4282010-10-06 00:25:55 +04004774 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004775
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004776 if (i >= mnum)
4777 break;
4778
4779 len = tok->len;
4780 while (pp_concat_match(next, m[i].mask_tail)) {
4781 len += next->len;
4782 next = next->next;
4783 }
4784
4785 /* No match or no text to process */
4786 if (len == tok->len)
4787 break;
4788
4789 p = buf = nasm_malloc(len + 1);
4790 while (tok != next) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004791 p = mempcpy(p, tok_text(tok), tok->len);
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004792 tok = delete_Token(tok);
4793 }
4794 *p = '\0';
4795 *prev_next = tok = t = tokenize(buf);
4796 nasm_free(buf);
4797
4798 /*
4799 * Connect pasted into original stream,
4800 * ie A -> new-tokens -> B
4801 */
4802 while (t->next)
4803 t = t->next;
4804 t->next = next;
4805 prev_next = prev_nonspace = &t->next;
4806 did_paste = true;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004807 break;
H. Peter Anvind784a082009-04-20 14:01:18 -07004808 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004809
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004810 if (did_paste) {
4811 pasted = true;
4812 } else {
4813 prev_next = &tok->next;
4814 if (next && next->type != TOK_WHITESPACE && next->type != TOK_PASTE)
4815 prev_nonspace = prev_next;
4816 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004817
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004818 tok = next;
H. Peter Anvind784a082009-04-20 14:01:18 -07004819 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004820
4821 return pasted;
H. Peter Anvind784a082009-04-20 14:01:18 -07004822}
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004823
4824/*
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004825 * Computes the proper rotation of mmacro parameters
4826 */
4827static int mmac_rotate(const MMacro *mac, unsigned int n)
4828{
4829 if (--n < mac->nparam)
4830 n = (n + mac->rotate) % mac->nparam;
4831
4832 return n+1;
4833}
4834
4835/*
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004836 * expands to a list of tokens from %{x:y}
4837 */
H. Peter Anvin (Intel)e99a9462020-06-30 11:51:41 -07004838void expand_mmac_params_range(MMacro *mac, Token *tline, Token ***tail)
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004839{
H. Peter Anvin (Intel)e99a9462020-06-30 11:51:41 -07004840 Token *t;
4841 const char *arg = tok_text(tline) + 1;
4842 int fst, lst, incr, n;
4843 int parsed;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004844
H. Peter Anvin (Intel)e99a9462020-06-30 11:51:41 -07004845 parsed = sscanf(arg, "%d:%d", &fst, &lst);
4846 nasm_assert(parsed == 2);
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
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004864 /*
H. Peter Anvin (Intel)e99a9462020-06-30 11:51:41 -07004865 * It will be at least one parameter, as we can loop
4866 * in either direction.
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004867 */
H. Peter Anvin (Intel)e99a9462020-06-30 11:51:41 -07004868 incr = (fst < lst) ? 1 : -1;
4869
4870 while (true) {
4871 n = mmac_rotate(mac, fst);
4872 dup_tlistn(mac->params[n], mac->paramlen[n], tail);
4873 if (fst == lst)
4874 break;
4875 t = make_tok_char(NULL, ',');
4876 **tail = t;
4877 *tail = &t->next;
4878 fst += incr;
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004879 }
4880
H. Peter Anvin (Intel)e99a9462020-06-30 11:51:41 -07004881 return;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004882
4883err:
H. Peter Anvin (Intel)e99a9462020-06-30 11:51:41 -07004884 nasm_nonfatal("`%%{%s}': macro parameters out of range", arg);
4885 return;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004886}
4887
H. Peter Anvin76690a12002-04-30 20:52:49 +00004888/*
4889 * Expand MMacro-local things: parameter references (%0, %n, %+n,
H. Peter Anvin67c63722008-10-26 23:49:00 -07004890 * %-n) and MMacro-local identifiers (%%foo) as well as
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004891 * macro indirection (%[...]) and range (%{..:..}).
H. Peter Anvin76690a12002-04-30 20:52:49 +00004892 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004893static Token *expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004894{
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004895 Token **tail, *thead;
H. Peter Anvin6125b622009-04-08 14:02:25 -07004896 bool changed = false;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004897 MMacro *mac = istk->mstk.mmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004898
4899 tail = &thead;
4900 thead = NULL;
4901
H. Peter Anvine2c80182005-01-15 22:15:51 +00004902 while (tline) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004903 bool change;
H. Peter Anvin (Intel)a762cd42020-06-01 11:49:08 -07004904 bool err_not_mac = false;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004905 Token *t = tline;
H. Peter Anvin8571f062019-09-23 16:40:03 -07004906 const char *text = tok_text(t);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004907 int type = t->type;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004908
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004909 tline = tline->next;
4910 t->next = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004911
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004912 switch (type) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004913 case TOK_LOCAL_SYMBOL:
H. Peter Anvin (Intel)a762cd42020-06-01 11:49:08 -07004914 change = true;
4915
4916 if (!mac) {
4917 err_not_mac = true;
4918 break;
4919 }
4920
H. Peter Anvin8571f062019-09-23 16:40:03 -07004921 type = TOK_ID;
4922 text = nasm_asprintf("..@%"PRIu64".%s", mac->unique, text+2);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004923 break;
4924 case TOK_MMACRO_PARAM:
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004925 {
4926 Token *tt = NULL;
4927
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004928 change = true;
4929
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004930 if (!mac) {
H. Peter Anvin (Intel)a762cd42020-06-01 11:49:08 -07004931 err_not_mac = true;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004932 break;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004933 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004934
4935 if (strchr(text, ':')) {
H. Peter Anvin (Intel)e99a9462020-06-30 11:51:41 -07004936 /* It is a range */
4937 expand_mmac_params_range(mac, t, &tail);
4938 text = NULL;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004939 break;
4940 }
4941
4942 switch (text[1]) {
4943 /*
4944 * We have to make a substitution of one of the
4945 * forms %1, %-1, %+1, %%foo, %0, %00.
4946 */
4947 case '0':
4948 if (!text[2]) {
4949 type = TOK_NUMBER;
4950 text = nasm_asprintf("%d", mac->nparam);
4951 break;
4952 }
4953 if (text[2] != '0' || text[3])
4954 goto invalid;
4955 /* a possible captured label == mac->params[0] */
4956 /* fall through */
4957 default:
4958 {
4959 unsigned long n;
4960 char *ep;
4961
4962 n = strtoul(text + 1, &ep, 10);
4963 if (unlikely(*ep))
4964 goto invalid;
4965
4966 if (n <= mac->nparam) {
4967 n = mmac_rotate(mac, n);
4968 dup_tlistn(mac->params[n], mac->paramlen[n], &tail);
4969 }
4970 text = NULL;
4971 break;
4972 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004973 case '-':
4974 case '+':
4975 {
4976 int cc;
4977 unsigned long n;
4978 char *ep;
4979
H. Peter Anvin8571f062019-09-23 16:40:03 -07004980 n = strtoul(tok_text(t) + 2, &ep, 10);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004981 if (unlikely(*ep))
4982 goto invalid;
4983
Chang S. Bae057b8322020-04-18 23:11:21 +00004984 if (n && n <= mac->nparam) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004985 n = mmac_rotate(mac, n);
4986 tt = mac->params[n];
4987 }
4988 cc = find_cc(tt);
4989 if (cc == -1) {
4990 nasm_nonfatal("macro parameter `%s' is not a condition code",
H. Peter Anvin8571f062019-09-23 16:40:03 -07004991 tok_text(t));
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004992 text = NULL;
4993 break;
4994 }
4995
4996 type = TOK_ID;
4997 if (text[1] == '-') {
4998 int ncc = inverse_ccs[cc];
4999 if (unlikely(ncc == -1)) {
5000 nasm_nonfatal("condition code `%s' is not invertible",
5001 conditions[cc]);
5002 break;
5003 }
5004 cc = ncc;
5005 }
5006 text = nasm_strdup(conditions[cc]);
5007 break;
5008 }
5009
5010 invalid:
5011 nasm_nonfatal("invalid macro parameter: `%s'", text);
5012 text = NULL;
5013 break;
5014 }
5015 break;
5016 }
5017
5018 case TOK_PREPROC_Q:
5019 if (mac) {
5020 type = TOK_ID;
5021 text = nasm_strdup(mac->iname);
5022 change = true;
H. Peter Anvin (Intel)68075f82019-08-20 12:28:05 -07005023 } else {
5024 change = false;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005025 }
5026 break;
5027
5028 case TOK_PREPROC_QQ:
5029 if (mac) {
5030 type = TOK_ID;
5031 text = nasm_strdup(mac->name);
5032 change = true;
H. Peter Anvin (Intel)68075f82019-08-20 12:28:05 -07005033 } else {
5034 change = false;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005035 }
5036 break;
5037
5038 case TOK_INDIRECT:
5039 {
5040 Token *tt;
5041
H. Peter Anvin8571f062019-09-23 16:40:03 -07005042 tt = tokenize(tok_text(t));
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005043 tt = expand_mmac_params(tt);
5044 tt = expand_smacro(tt);
5045 /* Why dup_tlist() here? We should own tt... */
5046 dup_tlist(tt, &tail);
5047 text = NULL;
5048 change = true;
5049 break;
5050 }
5051
5052 default:
5053 change = false;
5054 break;
5055 }
5056
H. Peter Anvin (Intel)a762cd42020-06-01 11:49:08 -07005057 if (err_not_mac) {
5058 nasm_nonfatal("`%s': not in a macro call", text);
5059 text = NULL;
5060 change = true;
5061 }
5062
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005063 if (change) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00005064 if (!text) {
5065 delete_Token(t);
5066 } else {
5067 *tail = t;
5068 tail = &t->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07005069 set_text(t, text, tok_strlen(text));
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005070 t->type = type;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005071 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03005072 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005073 } else {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005074 *tail = t;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005075 tail = &t->next;
5076 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00005077 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005078
H. Peter Anvineba20a72002-04-30 20:53:55 +00005079 *tail = NULL;
H. Peter Anvin67c63722008-10-26 23:49:00 -07005080
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04005081 if (changed) {
5082 const struct tokseq_match t[] = {
5083 {
5084 PP_CONCAT_MASK(TOK_ID) |
5085 PP_CONCAT_MASK(TOK_FLOAT), /* head */
5086 PP_CONCAT_MASK(TOK_ID) |
5087 PP_CONCAT_MASK(TOK_NUMBER) |
5088 PP_CONCAT_MASK(TOK_FLOAT) |
5089 PP_CONCAT_MASK(TOK_OTHER) /* tail */
5090 },
5091 {
5092 PP_CONCAT_MASK(TOK_NUMBER), /* head */
5093 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
5094 }
5095 };
5096 paste_tokens(&thead, t, ARRAY_SIZE(t), false);
5097 }
H. Peter Anvin6125b622009-04-08 14:02:25 -07005098
H. Peter Anvin76690a12002-04-30 20:52:49 +00005099 return thead;
5100}
5101
H. Peter Anvin322bee02019-08-10 01:38:06 -07005102static Token *expand_smacro_noreset(Token * tline);
H. Peter Anvin322bee02019-08-10 01:38:06 -07005103
H. Peter Anvin76690a12002-04-30 20:52:49 +00005104/*
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005105 * Expand *one* single-line macro instance. If the first token is not
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005106 * a macro at all, it is simply copied to the output and the pointer
5107 * advanced. tpp should be a pointer to a pointer (usually the next
5108 * pointer of the previous token) to the first token. **tpp is updated
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005109 * to point to the first token of the expansion, and *tpp updated to
5110 * point to the next pointer of the last token of the expansion.
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005111 *
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005112 * If the expansion is empty, *tpp will be unchanged but **tpp will
5113 * be advanced past the macro call.
5114 *
H. Peter Anvin322bee02019-08-10 01:38:06 -07005115 * Return the macro expanded, or NULL if no expansion took place.
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005116 */
H. Peter Anvin322bee02019-08-10 01:38:06 -07005117static SMacro *expand_one_smacro(Token ***tpp)
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005118{
5119 Token **params = NULL;
5120 const char *mname;
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005121 Token *mstart = **tpp;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005122 Token *tline = mstart;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005123 SMacro *head, *m;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005124 int i;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005125 Token *t, *tup, *tafter;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005126 int nparam = 0;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005127 bool cond_comma;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005128
5129 if (!tline)
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005130 return false; /* Empty line, nothing to do */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005131
H. Peter Anvin8571f062019-09-23 16:40:03 -07005132 mname = tok_text(mstart);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005133
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07005134 smacro_deadman.total--;
H. Peter Anvin322bee02019-08-10 01:38:06 -07005135 smacro_deadman.levels--;
5136
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07005137 if (unlikely(smacro_deadman.total < 0 || smacro_deadman.levels < 0)) {
H. Peter Anvin322bee02019-08-10 01:38:06 -07005138 if (unlikely(!smacro_deadman.triggered)) {
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005139 nasm_nonfatal("interminable macro recursion");
H. Peter Anvin322bee02019-08-10 01:38:06 -07005140 smacro_deadman.triggered = true;
5141 }
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005142 goto not_a_macro;
H. Peter Anvin8571f062019-09-23 16:40:03 -07005143 } else if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID) {
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005144 head = (SMacro *)hash_findix(&smacros, mname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07005145 } else if (tline->type == TOK_LOCAL_MACRO) {
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005146 Context *ctx = get_ctx(mname, &mname);
5147 head = ctx ? (SMacro *)hash_findix(&ctx->localmac, mname) : NULL;
5148 } else {
5149 goto not_a_macro;
5150 }
5151
5152 /*
5153 * We've hit an identifier of some sort. First check whether the
5154 * identifier is a single-line macro at all, then think about
5155 * checking for parameters if necessary.
5156 */
5157 list_for_each(m, head) {
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005158 if (unlikely(m->alias && ppopt.noaliases))
H. Peter Anvind2354082019-08-27 16:38:48 -07005159 continue;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005160 if (!mstrcmp(m->name, mname, m->casesense))
5161 break;
5162 }
5163
5164 if (!m) {
5165 goto not_a_macro;
5166 }
5167
5168 /* Parse parameters, if applicable */
5169
5170 params = NULL;
5171 nparam = 0;
5172
5173 if (m->nparam == 0) {
5174 /*
5175 * Simple case: the macro is parameterless.
5176 * Nothing to parse; the expansion code will
5177 * drop the macro name token.
5178 */
5179 } else {
5180 /*
5181 * Complicated case: at least one macro with this name
5182 * exists and takes parameters. We must find the
5183 * parameters in the call, count them, find the SMacro
5184 * that corresponds to that form of the macro call, and
5185 * substitute for the parameters when we expand. What a
5186 * pain.
5187 */
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005188 Token *t;
5189 int paren, brackets;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005190
5191 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005192 tline = skip_white(tline);
5193 if (!tok_is(tline, '(')) {
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005194 /*
5195 * This macro wasn't called with parameters: ignore
5196 * the call. (Behaviour borrowed from gnu cpp.)
5197 */
5198 goto not_a_macro;
5199 }
5200
5201 paren = 1;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005202 nparam = 1;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005203 brackets = 0;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005204 t = tline; /* tline points to leading ( */
5205
5206 while (paren) {
5207 t = t->next;
5208
5209 if (!t) {
5210 nasm_nonfatal("macro call expects terminating `)'");
5211 goto not_a_macro;
5212 }
5213
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005214 if (t->type != TOK_OTHER || t->len != 1)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005215 continue;
5216
H. Peter Anvin8571f062019-09-23 16:40:03 -07005217 switch (t->text.a[0]) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005218 case ',':
H. Peter Anvinbd00f252020-06-04 21:05:01 -07005219 if (!brackets && paren == 1)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005220 nparam++;
5221 break;
5222
5223 case '{':
5224 brackets++;
5225 break;
5226
5227 case '}':
5228 if (brackets > 0)
5229 brackets--;
5230 break;
5231
5232 case '(':
5233 if (!brackets)
5234 paren++;
5235 break;
5236
5237 case ')':
5238 if (!brackets)
5239 paren--;
5240 break;
5241
5242 default:
5243 break; /* Normal token */
5244 }
5245 }
5246
5247 /*
5248 * Look for a macro matching in both name and parameter count.
5249 * We already know any matches cannot be anywhere before the
5250 * current position of "m", so there is no reason to
5251 * backtrack.
5252 */
5253 while (1) {
5254 if (!m) {
5255 /*!
5256 *!macro-params-single [on] single-line macro calls with wrong parameter count
5257 *! warns about \i{single-line macros} being invoked
5258 *! with the wrong number of parameters.
5259 */
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005260 nasm_warn(WARN_MACRO_PARAMS_SINGLE|ERR_HOLD,
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005261 "single-line macro `%s' exists, "
5262 "but not taking %d parameter%s",
5263 mname, nparam, (nparam == 1) ? "" : "s");
5264 goto not_a_macro;
5265 }
5266
5267 if (!mstrcmp(m->name, mname, m->casesense)) {
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005268 if (nparam == m->nparam)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005269 break; /* It's good */
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005270 if (m->greedy && nparam >= m->nparam-1)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005271 break; /* Also good */
5272 }
5273 m = m->next;
5274 }
5275 }
5276
5277 if (m->in_progress)
5278 goto not_a_macro;
5279
5280 /* Expand the macro */
5281 m->in_progress = true;
5282
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005283 if (nparam) {
5284 /* Extract parameters */
5285 Token **phead, **pep;
5286 int white = 0;
5287 int brackets = 0;
5288 int paren;
5289 bool bracketed = false;
5290 bool bad_bracket = false;
5291 enum sparmflags flags;
5292
5293 nparam = m->nparam;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005294 paren = 1;
5295 nasm_newn(params, nparam);
5296 i = 0;
5297 flags = m->params[i].flags;
5298 phead = pep = &params[i];
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005299 *pep = NULL;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005300
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005301 while (paren) {
5302 bool skip;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005303 char ch;
5304
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005305 tline = tline->next;
5306
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005307 if (!tline)
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005308 nasm_nonfatal("macro call expects terminating `)'");
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005309
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005310 ch = 0;
5311 skip = false;
5312
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005313
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005314 switch (tline->type) {
5315 case TOK_OTHER:
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005316 if (tline->len == 1)
H. Peter Anvin8571f062019-09-23 16:40:03 -07005317 ch = tline->text.a[0];
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005318 break;
5319
5320 case TOK_WHITESPACE:
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005321 if (!(flags & SPARM_NOSTRIP)) {
5322 if (brackets || *phead)
5323 white++; /* Keep interior whitespace */
5324 skip = true;
5325 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005326 break;
5327
5328 default:
5329 break;
5330 }
5331
5332 switch (ch) {
5333 case ',':
H. Peter Anvinbd00f252020-06-04 21:05:01 -07005334 if (!brackets && paren == 1 && !(flags & SPARM_GREEDY)) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005335 i++;
5336 nasm_assert(i < nparam);
5337 phead = pep = &params[i];
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005338 *pep = NULL;
5339 bracketed = false;
5340 skip = true;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005341 flags = m->params[i].flags;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005342 }
5343 break;
5344
5345 case '{':
5346 if (!bracketed) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005347 bracketed = !*phead && !(flags & SPARM_NOSTRIP);
5348 skip = bracketed;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005349 }
5350 brackets++;
5351 break;
5352
5353 case '}':
5354 if (brackets > 0) {
5355 if (!--brackets)
5356 skip = bracketed;
5357 }
5358 break;
5359
5360 case '(':
5361 if (!brackets)
5362 paren++;
5363 break;
5364
5365 case ')':
5366 if (!brackets) {
5367 paren--;
5368 if (!paren) {
5369 skip = true;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005370 i++; /* Found last argument */
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005371 }
5372 }
5373 break;
5374
5375 default:
5376 break; /* Normal token */
5377 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005378
5379 if (!skip) {
5380 Token *t;
5381
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005382 bad_bracket |= bracketed && !brackets;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005383
5384 if (white) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005385 *pep = t = new_White(NULL);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005386 pep = &t->next;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005387 white = 0;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005388 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005389 *pep = t = dup_Token(NULL, tline);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005390 pep = &t->next;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005391 }
5392 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005393
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005394 /*
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005395 * Possible further processing of parameters. Note that the
5396 * ordering matters here.
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005397 */
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005398 for (i = 0; i < nparam; i++) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005399 enum sparmflags flags = m->params[i].flags;
5400
5401 if (flags & SPARM_EVAL) {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005402 /* Evaluate this parameter as a number */
5403 struct ppscan pps;
5404 struct tokenval tokval;
5405 expr *evalresult;
5406 Token *eval_param;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005407
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005408 pps.tptr = eval_param = expand_smacro_noreset(params[i]);
5409 pps.ntokens = -1;
5410 tokval.t_type = TOKEN_INVALID;
5411 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005412
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005413 free_tlist(eval_param);
5414 params[i] = NULL;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005415
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005416 if (!evalresult) {
5417 /* Nothing meaningful to do */
5418 } else if (tokval.t_type) {
5419 nasm_nonfatal("invalid expression in parameter %d of macro `%s'", i, m->name);
5420 } else if (!is_simple(evalresult)) {
5421 nasm_nonfatal("non-constant expression in parameter %d of macro `%s'", i, m->name);
5422 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07005423 params[i] = make_tok_num(NULL, reloc_value(evalresult));
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005424 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005425 }
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005426
5427 if (flags & SPARM_STR) {
5428 /* Convert expansion to a quoted string */
5429 char *arg;
5430 Token *qs;
5431
5432 qs = expand_smacro_noreset(params[i]);
5433 arg = detoken(qs, false);
5434 free_tlist(qs);
H. Peter Anvin8571f062019-09-23 16:40:03 -07005435 params[i] = make_tok_qstr(NULL, arg);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005436 nasm_free(arg);
5437 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005438 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005439 }
5440
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005441 /* Note: we own the expansion this returns. */
5442 t = m->expand(m, params, nparam);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005443
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005444 tafter = tline->next; /* Skip past the macro call */
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07005445 tline->next = NULL; /* Truncate list at the macro call end */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005446 tline = tafter;
5447
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005448 tup = NULL;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005449 cond_comma = false;
5450
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005451 while (t) {
5452 enum pp_token_type type = t->type;
5453 Token *tnext = t->next;
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005454
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005455 switch (type) {
5456 case TOK_PREPROC_Q:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005457 delete_Token(t);
5458 t = dup_Token(tline, mstart);
5459 break;
5460
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005461 case TOK_PREPROC_QQ:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005462 {
H. Peter Anvin8571f062019-09-23 16:40:03 -07005463 size_t mlen = strlen(m->name);
5464 size_t len;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005465 char *p;
5466
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005467 t->type = mstart->type;
H. Peter Anvin8571f062019-09-23 16:40:03 -07005468 if (t->type == TOK_LOCAL_MACRO) {
5469 const char *psp; /* prefix start pointer */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005470 const char *pep; /* prefix end pointer */
H. Peter Anvin8571f062019-09-23 16:40:03 -07005471 size_t plen;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005472
H. Peter Anvin8571f062019-09-23 16:40:03 -07005473 psp = tok_text(mstart);
5474 get_ctx(psp, &pep);
5475 plen = pep - psp;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005476
H. Peter Anvin8571f062019-09-23 16:40:03 -07005477 len = mlen + plen;
5478 p = nasm_malloc(len + 1);
5479 p = mempcpy(p, psp, plen);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005480 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07005481 len = mlen;
5482 p = nasm_malloc(len + 1);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005483 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07005484 p = mempcpy(p, m->name, mlen);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005485 *p = '\0';
H. Peter Anvin8571f062019-09-23 16:40:03 -07005486 set_text_free(t, p, len);
5487
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005488 t->next = tline;
5489 break;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005490 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005491
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005492 case TOK_COND_COMMA:
5493 delete_Token(t);
H. Peter Anvin8571f062019-09-23 16:40:03 -07005494 t = cond_comma ? make_tok_char(tline, ',') : NULL;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005495 break;
5496
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005497 case TOK_ID:
5498 case TOK_PREPROC_ID:
H. Peter Anvin8571f062019-09-23 16:40:03 -07005499 case TOK_LOCAL_MACRO:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005500 {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005501 /*
5502 * Chain this into the target line *before* expanding,
5503 * that way we pick up any arguments to the new macro call,
5504 * if applicable.
5505 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005506 Token **tp = &t;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005507 t->next = tline;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005508 expand_one_smacro(&tp);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005509 tline = *tp; /* First token left after any macro call */
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005510 break;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005511 }
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005512 default:
5513 if (is_smac_param(t->type)) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005514 int param = smac_nparam(t->type);
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005515 nasm_assert(!tup && param < nparam);
5516 delete_Token(t);
5517 t = NULL;
5518 tup = tnext;
5519 tnext = dup_tlist_reverse(params[param], NULL);
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005520 cond_comma = false;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005521 } else {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005522 t->next = tline;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005523 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005524 }
5525
5526 if (t) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005527 Token *endt = tline;
5528
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005529 tline = t;
Chang S. Bae95e54a92020-02-06 14:39:22 -08005530 while (!cond_comma && t && t != endt) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005531 cond_comma = t->type != TOK_WHITESPACE;
Chang S. Bae95e54a92020-02-06 14:39:22 -08005532 t = t->next;
5533 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005534 }
5535
5536 if (tnext) {
5537 t = tnext;
5538 } else {
5539 t = tup;
5540 tup = NULL;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005541 }
5542 }
5543
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005544 **tpp = tline;
H. Peter Anvin (Intel)6e714962020-06-01 12:21:10 -07005545 for (t = tline; t && t != tafter; t = t->next)
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005546 *tpp = &t->next;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005547
5548 m->in_progress = false;
5549
5550 /* Don't do this until after expansion or we will clobber mname */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005551 free_tlist(mstart);
H. Peter Anvin322bee02019-08-10 01:38:06 -07005552 goto done;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005553
5554 /*
5555 * No macro expansion needed; roll back to mstart (if necessary)
H. Peter Anvin322bee02019-08-10 01:38:06 -07005556 * and then advance to the next input token. Note that this is
5557 * by far the common case!
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005558 */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005559not_a_macro:
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005560 *tpp = &mstart->next;
H. Peter Anvin322bee02019-08-10 01:38:06 -07005561 m = NULL;
5562done:
5563 smacro_deadman.levels++;
5564 if (unlikely(params))
5565 free_tlist_array(params, nparam);
5566 return m;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005567}
5568
5569/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005570 * Expand all single-line macro calls made in the given line.
5571 * Return the expanded version of the line. The original is deemed
5572 * to be destroyed in the process. (In reality we'll just move
5573 * Tokens from input to output a lot of the time, rather than
5574 * actually bothering to destroy and replicate.)
5575 */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005576static Token *expand_smacro(Token *tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005577{
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07005578 smacro_deadman.total = nasm_limit[LIMIT_MACRO_TOKENS];
H. Peter Anvin322bee02019-08-10 01:38:06 -07005579 smacro_deadman.levels = nasm_limit[LIMIT_MACRO_LEVELS];
5580 smacro_deadman.triggered = false;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005581 return expand_smacro_noreset(tline);
5582}
5583
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005584static Token *expand_smacro_noreset(Token *org_tline)
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005585{
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005586 Token *tline;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005587 bool expanded;
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005588 errhold errhold; /* Hold warning/errors during expansion */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005589
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005590 if (!org_tline)
5591 return NULL; /* Empty input */
5592
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005593 /*
5594 * Trick: we should avoid changing the start token pointer since it can
5595 * be contained in "next" field of other token. Because of this
5596 * we allocate a copy of first token and work with it; at the end of
5597 * routine we copy it back
5598 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005599 tline = dup_Token(org_tline->next, org_tline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005600
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005601 /*
5602 * Pretend that we always end up doing expansion on the first pass;
5603 * that way %+ get processed. However, if we process %+ before the
5604 * first pass, we end up with things like MACRO %+ TAIL trying to
5605 * look up the macro "MACROTAIL", which we don't want.
5606 */
5607 expanded = true;
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005608
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005609 while (true) {
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005610 static const struct tokseq_match tmatch[] = {
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04005611 {
5612 PP_CONCAT_MASK(TOK_ID) |
H. Peter Anvin8571f062019-09-23 16:40:03 -07005613 PP_CONCAT_MASK(TOK_LOCAL_MACRO) |
5614 PP_CONCAT_MASK(TOK_ENVIRON) |
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04005615 PP_CONCAT_MASK(TOK_PREPROC_ID), /* head */
5616 PP_CONCAT_MASK(TOK_ID) |
H. Peter Anvin8571f062019-09-23 16:40:03 -07005617 PP_CONCAT_MASK(TOK_LOCAL_MACRO) |
5618 PP_CONCAT_MASK(TOK_ENVIRON) |
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04005619 PP_CONCAT_MASK(TOK_PREPROC_ID) |
5620 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
5621 }
5622 };
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005623 Token **tail = &tline;
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005624
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005625 /*
5626 * We hold warnings/errors until we are done this this loop. It is
5627 * possible for nuisance warnings to appear that disappear on later
5628 * passes.
5629 */
5630 errhold = nasm_error_hold_push();
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005631
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005632 while (*tail) /* main token loop */
H. Peter Anvin322bee02019-08-10 01:38:06 -07005633 expanded |= !!expand_one_smacro(&tail);
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005634
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005635 if (!expanded)
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005636 break; /* Done! */
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005637
5638 /*
5639 * Now scan the entire line and look for successive TOK_IDs
5640 * that resulted after expansion (they can't be produced by
5641 * tokenize()). The successive TOK_IDs should be concatenated.
5642 * Also we look for %+ tokens and concatenate the tokens
5643 * before and after them (without white spaces in between).
5644 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005645 if (!paste_tokens(&tline, tmatch, ARRAY_SIZE(tmatch), true))
5646 break; /* Done again! */
5647
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005648 nasm_error_hold_pop(errhold, false);
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005649 expanded = false;
H. Peter Anvin734b1882002-04-30 21:01:08 +00005650 }
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005651 nasm_error_hold_pop(errhold, true);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005652
H. Peter Anvin8571f062019-09-23 16:40:03 -07005653 if (!tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005654 /*
5655 * The expression expanded to empty line;
5656 * we can't return NULL because of the "trick" above.
5657 * Just set the line to a single WHITESPACE token.
H. Peter Anvin8571f062019-09-23 16:40:03 -07005658 */
5659
5660 tline = new_White(NULL);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005661 }
5662
H. Peter Anvin8571f062019-09-23 16:40:03 -07005663 steal_Token(org_tline, tline);
5664 org_tline->next = tline->next;
5665 delete_Token(tline);
5666
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005667 return org_tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005668}
5669
5670/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005671 * Similar to expand_smacro but used exclusively with macro identifiers
5672 * right before they are fetched in. The reason is that there can be
5673 * identifiers consisting of several subparts. We consider that if there
5674 * are more than one element forming the name, user wants a expansion,
5675 * otherwise it will be left as-is. Example:
5676 *
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03005677 * %define %$abc cde
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005678 *
5679 * the identifier %$abc will be left as-is so that the handler for %define
5680 * will suck it and define the corresponding value. Other case:
5681 *
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03005682 * %define _%$abc cde
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005683 *
5684 * In this case user wants name to be expanded *before* %define starts
5685 * working, so we'll expand %$abc into something (if it has a value;
5686 * otherwise it will be left as-is) then concatenate all successive
5687 * PP_IDs into one.
5688 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00005689static Token *expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005690{
5691 Token *cur, *oldnext = NULL;
5692
H. Peter Anvin734b1882002-04-30 21:01:08 +00005693 if (!tline || !tline->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005694 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005695
5696 cur = tline;
5697 while (cur->next &&
H. Peter Anvin8571f062019-09-23 16:40:03 -07005698 (cur->next->type == TOK_ID || cur->next->type == TOK_PREPROC_ID ||
5699 cur->next->type == TOK_LOCAL_MACRO || cur->next->type == TOK_NUMBER))
H. Peter Anvine2c80182005-01-15 22:15:51 +00005700 cur = cur->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005701
5702 /* If identifier consists of just one token, don't expand */
5703 if (cur == tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005704 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005705
H. Peter Anvine2c80182005-01-15 22:15:51 +00005706 if (cur) {
5707 oldnext = cur->next; /* Detach the tail past identifier */
5708 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005709 }
5710
H. Peter Anvin734b1882002-04-30 21:01:08 +00005711 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005712
H. Peter Anvine2c80182005-01-15 22:15:51 +00005713 if (cur) {
5714 /* expand_smacro possibly changhed tline; re-scan for EOL */
5715 cur = tline;
5716 while (cur && cur->next)
5717 cur = cur->next;
5718 if (cur)
5719 cur->next = oldnext;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005720 }
5721
5722 return tline;
5723}
5724
5725/*
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005726 * This is called from find_mmacro_in_list() after finding a suitable macro.
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005727 */
5728static MMacro *use_mmacro(MMacro *m, int *nparamp, Token ***paramsp)
5729{
5730 int nparam = *nparamp;
5731 Token **params = *paramsp;
5732
5733 /*
5734 * This one is right. Just check if cycle removal
5735 * prohibits us using it before we actually celebrate...
5736 */
5737 if (m->in_progress > m->max_depth) {
5738 if (m->max_depth > 0) {
5739 nasm_warn(WARN_OTHER, "reached maximum recursion depth of %i",
5740 m->max_depth);
5741 }
5742 nasm_free(params);
5743 *nparamp = 0;
5744 *paramsp = NULL;
5745 return NULL;
5746 }
5747
5748 /*
5749 * It's right, and we can use it. Add its default
5750 * parameters to the end of our list if necessary.
5751 */
5752 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
5753 int newnparam = m->nparam_min + m->ndefs;
5754 params = nasm_realloc(params, sizeof(*params) * (newnparam+2));
5755 memcpy(&params[nparam+1], &m->defaults[nparam+1-m->nparam_min],
5756 (newnparam - nparam) * sizeof(*params));
5757 nparam = newnparam;
5758 }
5759 /*
5760 * If we've gone over the maximum parameter count (and
5761 * we're in Plus mode), ignore parameters beyond
5762 * nparam_max.
5763 */
5764 if (m->plus && nparam > m->nparam_max)
5765 nparam = m->nparam_max;
5766
5767 /*
5768 * If nparam was adjusted above, make sure the list is still
5769 * NULL-terminated.
5770 */
5771 params[nparam+1] = NULL;
5772
5773 /* Done! */
5774 *paramsp = params;
5775 *nparamp = nparam;
5776 return m;
5777}
5778
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005779/*
5780 * Search a macro list and try to find a match. If matching, call
5781 * use_mmacro() to set up the macro call. m points to the list of
5782 * search, which is_mmacro() sets to the first *possible* match.
5783 */
5784static MMacro *
5785find_mmacro_in_list(MMacro *m, const char *finding,
5786 int *nparamp, Token ***paramsp)
5787{
5788 int nparam = *nparamp;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005789
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005790 while (m) {
5791 if (m->nparam_min <= nparam
5792 && (m->plus || nparam <= m->nparam_max)) {
5793 /*
5794 * This one matches, use it.
5795 */
5796 return use_mmacro(m, nparamp, paramsp);
5797 }
5798
5799 /*
5800 * Otherwise search for the next one with a name match.
5801 */
5802 list_for_each(m, m->next) {
5803 if (!mstrcmp(m->name, finding, m->casesense))
5804 break;
5805 }
5806 }
5807
5808 return NULL;
5809}
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005810
5811/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005812 * Determine whether the given line constitutes a multi-line macro
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005813 * call, and return the MMacro structure called if so. Doesn't have
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005814 * to check for an initial label - that's taken care of in
5815 * expand_mmacro - but must check numbers of parameters. Guaranteed
5816 * to be called with tline->type == TOK_ID, so the putative macro
5817 * name is easy to find.
5818 */
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005819static MMacro *is_mmacro(Token * tline, int *nparamp, Token ***paramsp)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005820{
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005821 MMacro *head, *m, *found;
5822 Token **params, **comma;
5823 int raw_nparam, nparam;
H. Peter Anvin8571f062019-09-23 16:40:03 -07005824 const char *finding = tok_text(tline);
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005825 bool empty_args = !tline->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005826
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005827 *nparamp = 0;
5828 *paramsp = NULL;
5829
H. Peter Anvin8571f062019-09-23 16:40:03 -07005830 head = (MMacro *) hash_findix(&mmacros, finding);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005831
5832 /*
5833 * Efficiency: first we see if any macro exists with the given
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07005834 * name which isn't already excluded by macro cycle removal.
5835 * (The cycle removal test here helps optimize the case of wrapping
5836 * instructions, and is cheap to do here.)
5837 *
5838 * If not, we can return NULL immediately. _Then_ we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005839 * count the parameters, and then we look further along the
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005840 * list if necessary to find the proper MMacro.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005841 */
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07005842 list_for_each(m, head) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07005843 if (!mstrcmp(m->name, finding, m->casesense) &&
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07005844 (m->in_progress != 1 || m->max_depth > 0))
5845 break; /* Found something that needs consideration */
5846 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005847 if (!m)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005848 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005849
5850 /*
5851 * OK, we have a potential macro. Count and demarcate the
5852 * parameters.
5853 */
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005854 comma = count_mmac_params(tline->next, nparamp, paramsp);
5855 raw_nparam = *nparamp;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005856
5857 /*
5858 * Search for an exact match. This cannot come *before* the m
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005859 * found in the list search before, so we can start there.
5860 *
5861 * If found is NULL and *paramsp has been cleared, then we
5862 * encountered an error for which we have already issued a
5863 * diagnostic, so we should not proceed.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005864 */
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005865 found = find_mmacro_in_list(m, finding, nparamp, paramsp);
5866 if (!*paramsp)
5867 return NULL;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005868
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005869 nparam = *nparamp;
5870 params = *paramsp;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005871
5872 /*
5873 * Special weirdness: in NASM < 2.15, an expansion of
5874 * *only* whitespace, as can happen during macro expansion under
5875 * certain circumstances, is counted as zero arguments for the
5876 * purpose of %0, but one argument for the purpose of macro
5877 * matching! In particular, this affects:
5878 *
5879 * foobar %1
5880 *
5881 * ... with %1 being empty; this would call the one-argument
5882 * version of "foobar" with an empty argument, equivalent to
5883 *
5884 * foobar {%1}
5885 *
5886 * ... except that %0 would be set to 0 inside foobar, even if
5887 * foobar is declared with "%macro foobar 1" or equivalent!
5888 *
5889 * The proper way to do that is to define "%macro foobar 0-1".
5890 *
5891 * To be compatible without doing something too stupid, try to
5892 * match a zero-argument macro first, but if that fails, try
5893 * for a one-argument macro with the above behavior.
5894 *
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005895 * Furthermore, NASM < 2.15 will match stripping a tailing empty
5896 * argument, but in that case %0 *does* reflect that this argument
5897 * have been stripped; this is handled in count_mmac_params().
5898 *
5899 * To disable these insane legacy behaviors, use:
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005900 *
5901 * %pragma preproc sane_empty_expansion yes
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005902 *
5903 *!macro-params-legacy [on] improperly calling multi-line macro for legacy support
5904 *! warns about \i{multi-line macros} being invoked
5905 *! with the wrong number of parameters, but for bug-compatibility
5906 *! with NASM versions older than 2.15, NASM tried to fix up the
5907 *! parameters to match the legacy behavior and call the macro anyway.
5908 *! This can happen in certain cases where there are empty arguments
5909 *! without braces, sometimes as a result of macro expansion.
5910 *!-
5911 *! The legacy behavior is quite strange and highly context-dependent,
5912 *! and can be disabled with:
5913 *!-
H. Peter Anvin (Intel)de8817d2020-06-27 22:30:50 -07005914 *! \c %pragma preproc sane_empty_expansion true
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005915 *!-
5916 *! It is highly recommended to use this option in new code.
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005917 */
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005918 if (!ppopt.sane_empty_expansion) {
5919 if (!found) {
5920 if (raw_nparam == 0 && !empty_args) {
5921 /*
5922 * A single all-whitespace parameter as the only thing?
5923 * Look for a one-argument macro, but don't adjust
5924 * *nparamp.
5925 */
5926 int bogus_nparam = 1;
5927 params[2] = NULL;
5928 found = find_mmacro_in_list(m, finding, &bogus_nparam, paramsp);
5929 } else if (raw_nparam > 1 && comma) {
5930 Token *comma_tail = *comma;
5931
5932 /*
5933 * Drop the terminal argument and try again.
5934 * If we fail, we need to restore the comma to
5935 * preserve tlist.
5936 */
5937 *comma = NULL;
5938 *nparamp = raw_nparam - 1;
5939 found = find_mmacro_in_list(m, finding, nparamp, paramsp);
5940 if (found)
5941 free_tlist(comma_tail);
5942 else
5943 *comma = comma_tail;
5944 }
5945
5946 if (!*paramsp)
5947 return NULL;
5948 } else if (comma) {
5949 free_tlist(*comma);
5950 *comma = NULL;
5951 if (raw_nparam > found->nparam_min &&
5952 raw_nparam <= found->nparam_min + found->ndefs) {
5953 /* Replace empty argument with default parameter */
5954 params[raw_nparam] =
5955 found->defaults[raw_nparam - found->nparam_min];
5956 } else if (raw_nparam > found->nparam_max && found->plus) {
5957 /* Just drop the comma, don't adjust argument count */
5958 } else {
5959 /* Drop argument. This may cause nparam < nparam_min. */
5960 params[raw_nparam] = NULL;
5961 *nparamp = nparam = raw_nparam - 1;
5962 }
5963 }
5964
5965 if (found) {
5966 if (raw_nparam < found->nparam_min ||
5967 (raw_nparam > found->nparam_max && !found->plus)) {
5968 nasm_warn(WARN_MACRO_PARAMS_LEGACY,
5969 "improperly calling multi-line macro `%s' with %d parameters",
5970 found->name, raw_nparam);
5971 } else if (comma) {
5972 nasm_warn(WARN_MACRO_PARAMS_LEGACY,
5973 "dropping trailing empty parameter in call to multi-line macro `%s'", found->name);
5974 }
5975 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005976 }
5977
5978 /*
5979 * After all that, we didn't find one with the right number of
5980 * parameters. Issue a warning, and fail to expand the macro.
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005981 *!
5982 *!macro-params-multi [on] multi-line macro calls with wrong parameter count
5983 *! warns about \i{multi-line macros} being invoked
5984 *! with the wrong number of parameters. See \k{mlmacover} for an
5985 *! example of why you might want to disable this warning.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005986 */
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005987 if (found)
5988 return found;
5989
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005990 nasm_warn(WARN_MACRO_PARAMS_MULTI,
5991 "multi-line macro `%s' exists, but not taking %d parameter%s",
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005992 finding, nparam, (nparam == 1) ? "" : "s");
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07005993 nasm_free(*paramsp);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005994 return NULL;
5995}
5996
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005997
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005998#if 0
5999
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006000/*
6001 * Save MMacro invocation specific fields in
6002 * preparation for a recursive macro expansion
6003 */
6004static void push_mmacro(MMacro *m)
6005{
6006 MMacroInvocation *i;
6007
6008 i = nasm_malloc(sizeof(MMacroInvocation));
6009 i->prev = m->prev;
6010 i->params = m->params;
6011 i->iline = m->iline;
6012 i->nparam = m->nparam;
6013 i->rotate = m->rotate;
6014 i->paramlen = m->paramlen;
6015 i->unique = m->unique;
6016 i->condcnt = m->condcnt;
6017 m->prev = i;
6018}
6019
6020
6021/*
6022 * Restore MMacro invocation specific fields that were
6023 * saved during a previous recursive macro expansion
6024 */
6025static void pop_mmacro(MMacro *m)
6026{
6027 MMacroInvocation *i;
6028
6029 if (m->prev) {
6030 i = m->prev;
6031 m->prev = i->prev;
6032 m->params = i->params;
6033 m->iline = i->iline;
6034 m->nparam = i->nparam;
6035 m->rotate = i->rotate;
6036 m->paramlen = i->paramlen;
6037 m->unique = i->unique;
6038 m->condcnt = i->condcnt;
6039 nasm_free(i);
6040 }
6041}
6042
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006043#endif
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006044
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006045/*
H. Peter Anvin (Intel)ffe89dd2019-08-20 16:06:36 -07006046 * List an mmacro call with arguments (-Lm option)
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07006047 */
6048static void list_mmacro_call(const MMacro *m)
6049{
6050 const char prefix[] = " ;;; [macro] ";
6051 size_t namelen, size;
6052 char *buf, *p;
6053 unsigned int i;
6054 const Token *t;
6055
6056 namelen = strlen(m->iname);
6057 size = namelen + sizeof(prefix); /* Includes final null (from prefix) */
6058
6059 for (i = 1; i <= m->nparam; i++) {
6060 int j = 0;
6061 size += 3; /* Braces and space/comma */
6062 list_for_each(t, m->params[i]) {
6063 if (j++ >= m->paramlen[i])
6064 break;
6065 size += (t->type == TOK_WHITESPACE) ? 1 : t->len;
6066 }
6067 }
6068
6069 buf = p = nasm_malloc(size);
6070 p = mempcpy(p, prefix, sizeof(prefix) - 1);
6071 p = mempcpy(p, m->iname, namelen);
6072 *p++ = ' ';
6073
6074 for (i = 1; i <= m->nparam; i++) {
6075 int j = 0;
6076 *p++ = '{';
6077 list_for_each(t, m->params[i]) {
6078 if (j++ >= m->paramlen[i])
6079 break;
H. Peter Anvin8571f062019-09-23 16:40:03 -07006080 p = mempcpy(p, tok_text(t), t->len);
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07006081 }
6082 *p++ = '}';
6083 *p++ = ',';
6084 }
6085
6086 *--p = '\0'; /* Replace last delimeter with null */
6087 lfmt->line(LIST_MACRO, -1, buf);
6088 nasm_free(buf);
6089}
6090
6091/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006092 * Expand the multi-line macro call made by the given line, if
6093 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006094 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006095 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006096static int expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006097{
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006098 Token *startline = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00006099 Token *label = NULL;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006100 bool dont_prepend = false;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006101 Token **params, *t, *tt;
6102 MMacro *m;
6103 Line *l, *ll;
H. Peter Anvin (Intel)42894382020-06-14 19:42:22 -07006104 int i, *paramlen;
H. Peter Anvinc751e862008-06-09 10:18:45 -07006105 const char *mname;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006106 int nparam = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006107
6108 t = tline;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006109 t = skip_white(t);
6110 /* if (!tok_type(t, TOK_ID)) Lino 02/25/02 */
H. Peter Anvin8571f062019-09-23 16:40:03 -07006111 if (!tok_type(t, TOK_ID) && !tok_type(t, TOK_LOCAL_MACRO))
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006112 return 0;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006113 m = is_mmacro(t, &nparam, &params);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006114 if (m) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07006115 mname = tok_text(t);
H. Peter Anvinc751e862008-06-09 10:18:45 -07006116 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006117 Token *last;
6118 /*
6119 * We have an id which isn't a macro call. We'll assume
6120 * it might be a label; we'll also check to see if a
6121 * colon follows it. Then, if there's another id after
6122 * that lot, we'll check it again for macro-hood.
6123 */
6124 label = last = t;
6125 t = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006126 if (tok_white(t))
H. Peter Anvine2c80182005-01-15 22:15:51 +00006127 last = t, t = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006128 if (tok_is(t, ':')) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006129 dont_prepend = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006130 last = t, t = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006131 if (tok_white(t))
H. Peter Anvine2c80182005-01-15 22:15:51 +00006132 last = t, t = t->next;
6133 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006134 if (!tok_type(t, TOK_ID) || !(m = is_mmacro(t, &nparam, &params)))
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006135 return 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006136 last->next = NULL;
H. Peter Anvin8571f062019-09-23 16:40:03 -07006137 mname = tok_text(t);
H. Peter Anvine2c80182005-01-15 22:15:51 +00006138 tline = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00006139 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006140
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07006141 if (unlikely(mmacro_deadman.total >= nasm_limit[LIMIT_MMACROS] ||
6142 mmacro_deadman.levels >= nasm_limit[LIMIT_MACRO_LEVELS])) {
6143 if (!mmacro_deadman.triggered) {
6144 nasm_nonfatal("interminable multiline macro recursion");
6145 mmacro_deadman.triggered = true;
6146 }
6147 return 0;
6148 }
6149
6150 mmacro_deadman.total++;
6151 mmacro_deadman.levels++;
6152
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006153 /*
6154 * Fix up the parameters: this involves stripping leading and
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07006155 * trailing whitespace and stripping braces if they are present.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006156 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006157 nasm_newn(paramlen, nparam+1);
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07006158
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006159 for (i = 1; (t = params[i]); i++) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006160 bool braced = false;
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08006161 int brace = 0;
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006162 int white = 0;
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07006163 bool comma = !m->plus || i < nparam;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006164
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006165 t = skip_white(t);
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006166 if (tok_is(t, '{')) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006167 t = t->next;
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006168 brace = 1;
6169 braced = true;
6170 comma = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006171 }
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006172
6173 params[i] = t;
6174 for (; t; t = t->next) {
6175 if (tok_white(t)) {
6176 white++;
6177 continue;
6178 }
6179
6180 if (t->type == TOK_OTHER && t->len == 1) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07006181 switch (t->text.a[0]) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006182 case ',':
6183 if (comma && !brace)
6184 goto endparam;
6185 break;
6186
6187 case '{':
6188 brace++;
6189 break;
6190
6191 case '}':
6192 brace--;
6193 if (braced && !brace) {
6194 paramlen[i] += white;
6195 goto endparam;
6196 }
6197 break;
6198
6199 default:
6200 break;
6201 }
6202 }
6203
6204 paramlen[i] += white + 1;
6205 white = 0;
6206 }
6207 endparam:
6208 ;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006209 }
6210
6211 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006212 * OK, we have a MMacro structure together with a set of
6213 * parameters. We must now go through the expansion and push
6214 * copies of each Line on to istk->expansion. Substitution of
H. Peter Anvin76690a12002-04-30 20:52:49 +00006215 * parameter tokens and macro-local tokens doesn't get done
6216 * until the single-line macro substitution process; this is
6217 * because delaying them allows us to change the semantics
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006218 * later through %rotate and give the right semantics for
6219 * nested mmacros.
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006220 *
6221 * First, push an end marker on to istk->expansion, mark this
6222 * macro as in progress, and set up its invocation-specific
6223 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006224 */
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07006225 nasm_new(ll);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006226 ll->next = istk->expansion;
6227 ll->finishes = m;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006228 ll->where = istk->where;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006229 istk->expansion = ll;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006230
6231 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006232 * Save the previous MMacro expansion in the case of
6233 * macro recursion
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006234 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006235#if 0
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006236 if (m->max_depth && m->in_progress)
6237 push_mmacro(m);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006238#endif
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006239
6240 m->in_progress ++;
6241 m->params = params;
6242 m->iline = tline;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006243 m->iname = nasm_strdup(mname);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006244 m->nparam = nparam;
6245 m->rotate = 0;
6246 m->paramlen = paramlen;
6247 m->unique = unique++;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006248 m->condcnt = 0;
6249
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006250 m->mstk = istk->mstk;
6251 istk->mstk.mstk = istk->mstk.mmac = m;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006252
6253 list_for_each(l, m->expansion) {
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07006254 nasm_new(ll);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006255 ll->next = istk->expansion;
6256 istk->expansion = ll;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006257 ll->first = dup_tlist(l->first, NULL);
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006258 ll->where = l->where;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006259 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006260
6261 /*
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006262 * If we had a label, and this macro definition does not include
6263 * a %00, push it on as the first line of, ot
H. Peter Anvineba20a72002-04-30 20:53:55 +00006264 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006265 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006266 if (label) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006267 /*
6268 * We had a label. If this macro contains an %00 parameter,
6269 * save the value as a special parameter (which is what it
6270 * is), otherwise push it as the first line of the macro
6271 * expansion.
6272 */
6273 if (m->capture_label) {
6274 params[0] = dup_Token(NULL, label);
6275 paramlen[0] = 1;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006276 free_tlist(startline);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006277 } else {
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006278 nasm_new(ll);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006279 ll->finishes = NULL;
6280 ll->next = istk->expansion;
6281 istk->expansion = ll;
6282 ll->first = startline;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006283 ll->where = istk->where;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006284 if (!dont_prepend) {
6285 while (label->next)
6286 label = label->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07006287 label->next = tt = make_tok_char(NULL, ':');
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006288 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006289 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00006290 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006291
H. Peter Anvin0d4d4312019-08-07 00:46:27 -07006292 lfmt->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006293
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07006294 if (list_option('m') && !m->nolist)
6295 list_mmacro_call(m);
6296
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006297 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006298}
6299
H. Peter Anvin130736c2016-02-17 20:27:41 -08006300/*
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006301 * This function decides if an error message should be suppressed.
6302 * It will never be called with a severity level of ERR_FATAL or
6303 * higher.
H. Peter Anvin130736c2016-02-17 20:27:41 -08006304 */
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006305static bool pp_suppress_error(errflags severity)
Victor van den Elzen3b404c02008-09-18 13:51:36 +02006306{
H. Peter Anvin130736c2016-02-17 20:27:41 -08006307 /*
6308 * If we're in a dead branch of IF or something like it, ignore the error.
6309 * However, because %else etc are evaluated in the state context
6310 * of the previous branch, errors might get lost:
6311 * %if 0 ... %else trailing garbage ... %endif
6312 * So %else etc should set the ERR_PP_PRECOND flag.
6313 */
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006314 if (istk && istk->conds &&
H. Peter Anvin130736c2016-02-17 20:27:41 -08006315 ((severity & ERR_PP_PRECOND) ?
6316 istk->conds->state == COND_NEVER :
H. Peter Anvineb6653f2016-04-05 13:03:10 -07006317 !emitting(istk->conds->state)))
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006318 return true;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02006319
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006320 return false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00006321}
6322
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006323static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07006324stdmac_file(const SMacro *s, Token **params, int nparams)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006325{
6326 (void)s;
6327 (void)params;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07006328 (void)nparams;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006329
H. Peter Anvin8571f062019-09-23 16:40:03 -07006330 return make_tok_qstr(NULL, src_get_fname());
H. Peter Anvin8b262472019-02-26 14:00:54 -08006331}
6332
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006333static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07006334stdmac_line(const SMacro *s, Token **params, int nparams)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006335{
6336 (void)s;
6337 (void)params;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07006338 (void)nparams;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006339
H. Peter Anvin8571f062019-09-23 16:40:03 -07006340 return make_tok_num(NULL, src_get_linnum());
H. Peter Anvin8b262472019-02-26 14:00:54 -08006341}
6342
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006343static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07006344stdmac_bits(const SMacro *s, Token **params, int nparams)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006345{
6346 (void)s;
6347 (void)params;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07006348 (void)nparams;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006349
H. Peter Anvin8571f062019-09-23 16:40:03 -07006350 return make_tok_num(NULL, globalbits);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006351}
6352
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006353static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07006354stdmac_ptr(const SMacro *s, Token **params, int nparams)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006355{
H. Peter Anvin8b262472019-02-26 14:00:54 -08006356 (void)s;
6357 (void)params;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07006358 (void)nparams;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006359
6360 switch (globalbits) {
6361 case 16:
H. Peter Anvin8571f062019-09-23 16:40:03 -07006362 return new_Token(NULL, TOK_ID, "word", 4);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006363 case 32:
H. Peter Anvin8571f062019-09-23 16:40:03 -07006364 return new_Token(NULL, TOK_ID, "dword", 5);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006365 case 64:
H. Peter Anvin8571f062019-09-23 16:40:03 -07006366 return new_Token(NULL, TOK_ID, "qword", 5);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006367 default:
6368 panic();
6369 }
H. Peter Anvin8b262472019-02-26 14:00:54 -08006370}
6371
H. Peter Anvin8b262472019-02-26 14:00:54 -08006372/* Add magic standard macros */
6373struct magic_macros {
6374 const char *name;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07006375 int nparam;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006376 ExpandSMacro func;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006377};
6378static const struct magic_macros magic_macros[] =
6379{
H. Peter Anvind2354082019-08-27 16:38:48 -07006380 { "__?FILE?__", 0, stdmac_file },
6381 { "__?LINE?__", 0, stdmac_line },
6382 { "__?BITS?__", 0, stdmac_bits },
6383 { "__?PTR?__", 0, stdmac_ptr },
H. Peter Anvin8b262472019-02-26 14:00:54 -08006384 { NULL, 0, NULL }
6385};
6386
6387static void pp_add_magic_stdmac(void)
6388{
6389 const struct magic_macros *m;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07006390 SMacro tmpl;
6391
6392 nasm_zero(tmpl);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006393
6394 for (m = magic_macros; m->name; m++) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07006395 tmpl.nparam = m->nparam;
6396 tmpl.expand = m->func;
6397 define_smacro(m->name, true, NULL, &tmpl);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006398 }
6399}
6400
H. Peter Anvin734b1882002-04-30 21:01:08 +00006401static void
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006402pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006403{
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006404 int apass;
H. Peter Anvin6686de22019-08-10 05:33:14 -07006405 struct Include *inc;
H. Peter Anvin7383b402008-09-24 10:20:40 -07006406
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006407 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006408 defining = NULL;
Charles Crayned4200be2008-07-12 16:42:33 -07006409 nested_mac_count = 0;
6410 nested_rep_count = 0;
H. Peter Anvin97a23472007-09-16 17:57:25 -07006411 init_macros();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006412 unique = 0;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07006413 deplist = dep_list;
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006414 pp_mode = mode;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07006415
6416 /* Reset options to default */
6417 nasm_zero(ppopt);
H. Peter Anvinf7606612016-07-13 14:23:48 -07006418
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07006419 if (!use_loaded)
6420 use_loaded = nasm_malloc(use_package_count * sizeof(bool));
6421 memset(use_loaded, 0, use_package_count * sizeof(bool));
6422
H. Peter Anvin6686de22019-08-10 05:33:14 -07006423 /* First set up the top level input file */
6424 nasm_new(istk);
6425 istk->fp = nasm_open_read(file, NF_TEXT);
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006426 if (!istk->fp) {
6427 nasm_fatalf(ERR_NOFILE, "unable to open input file `%s'%s%s",
6428 file, errno ? " " : "", errno ? strerror(errno) : "");
6429 }
H. Peter Anvin6686de22019-08-10 05:33:14 -07006430 src_set(0, file);
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006431 istk->where = src_where();
H. Peter Anvin6686de22019-08-10 05:33:14 -07006432 istk->lineinc = 1;
H. Peter Anvin6686de22019-08-10 05:33:14 -07006433
6434 strlist_add(deplist, file);
6435
6436 /*
6437 * Set up the stdmac packages as a virtual include file,
6438 * indicated by a null file pointer.
6439 */
6440 nasm_new(inc);
6441 inc->next = istk;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006442 src_set(0, NULL);
6443 inc->where = src_where();
H. Peter Anvin6686de22019-08-10 05:33:14 -07006444 inc->nolist = !list_option('b');
6445 istk = inc;
6446 lfmt->uplevel(LIST_INCLUDE, 0);
6447
H. Peter Anvin8b262472019-02-26 14:00:54 -08006448 pp_add_magic_stdmac();
6449
H. Peter Anvinf7606612016-07-13 14:23:48 -07006450 if (tasm_compatible_mode)
6451 pp_add_stdmac(nasm_stdmac_tasm);
6452
6453 pp_add_stdmac(nasm_stdmac_nasm);
6454 pp_add_stdmac(nasm_stdmac_version);
6455
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +03006456 if (extrastdmac)
6457 pp_add_stdmac(extrastdmac);
6458
H. Peter Anvinf7606612016-07-13 14:23:48 -07006459 stdmacpos = stdmacros[0];
6460 stdmacnext = &stdmacros[1];
6461
H. Peter Anvind2456592008-06-19 15:04:18 -07006462 do_predef = true;
H. Peter Anvin61f130f2008-09-25 15:45:06 -07006463
H. Peter Anvin61f130f2008-09-25 15:45:06 -07006464 /*
H. Peter Anvind2354082019-08-27 16:38:48 -07006465 * Define the __?PASS?__ macro. This is defined here unlike all the
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07006466 * other builtins, because it is special -- it varies between
6467 * passes -- but there is really no particular reason to make it
6468 * magic.
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006469 *
6470 * 0 = dependencies only
6471 * 1 = preparatory passes
6472 * 2 = final pass
6473 * 3 = preproces only
H. Peter Anvin61f130f2008-09-25 15:45:06 -07006474 */
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006475 switch (mode) {
6476 case PP_NORMAL:
6477 apass = pass_final() ? 2 : 1;
6478 break;
6479 case PP_DEPS:
6480 apass = 0;
6481 break;
6482 case PP_PREPROC:
6483 apass = 3;
6484 break;
6485 default:
6486 panic();
6487 }
6488
H. Peter Anvin8571f062019-09-23 16:40:03 -07006489 define_smacro("__?PASS?__", true, make_tok_num(NULL, apass), NULL);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006490}
6491
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07006492static void pp_init(void)
6493{
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07006494}
6495
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006496/*
6497 * Get a line of tokens. If we popped the macro expansion/include stack,
6498 * we return a pointer to the dummy token tok_pop; at that point if
6499 * istk is NULL then we have reached end of input;
6500 */
6501static Token tok_pop; /* Dummy token placeholder */
6502
6503static Token *pp_tokline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006504{
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006505 while (true) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006506 Line *l = istk->expansion;
6507 Token *tline = NULL;
6508 Token *dtline;
6509
H. Peter Anvine2c80182005-01-15 22:15:51 +00006510 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006511 * Fetch a tokenized line, either from the macro-expansion
H. Peter Anvine2c80182005-01-15 22:15:51 +00006512 * buffer or from the input file.
6513 */
6514 tline = NULL;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006515 while (l && l->finishes) {
6516 MMacro *fm = l->finishes;
H. Peter Anvineba20a72002-04-30 20:53:55 +00006517
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006518 if (!fm->name && fm->in_progress > 1) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006519 /*
6520 * This is a macro-end marker for a macro with no
6521 * name, which means it's not really a macro at all
6522 * but a %rep block, and the `in_progress' field is
6523 * more than 1, meaning that we still need to
6524 * repeat. (1 means the natural last repetition; 0
6525 * means termination by %exitrep.) We have
6526 * therefore expanded up to the %endrep, and must
6527 * push the whole block on to the expansion buffer
6528 * again. We don't bother to remove the macro-end
6529 * marker: we'd only have to generate another one
6530 * if we did.
6531 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006532 fm->in_progress--;
6533 list_for_each(l, fm->expansion) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006534 Line *ll;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006535
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006536 nasm_new(ll);
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006537 ll->next = istk->expansion;
6538 ll->first = dup_tlist(l->first, NULL);
6539 ll->where = l->where;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006540 istk->expansion = ll;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006541 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006542 break;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006543 } else {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006544 MMacro *m = istk->mstk.mstk;
6545
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006546 /*
6547 * Check whether a `%rep' was started and not ended
6548 * within this macro expansion. This can happen and
6549 * should be detected. It's a fatal error because
6550 * I'm too confused to work out how to recover
6551 * sensibly from it.
6552 */
6553 if (defining) {
6554 if (defining->name)
H. Peter Anvinc5136902018-06-15 18:20:17 -07006555 nasm_panic("defining with name in expansion");
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006556 else if (m->name)
H. Peter Anvinc5136902018-06-15 18:20:17 -07006557 nasm_fatal("`%%rep' without `%%endrep' within"
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006558 " expansion of macro `%s'", m->name);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006559 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006560
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006561 /*
6562 * FIXME: investigate the relationship at this point between
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006563 * istk->mstk.mstk and fm
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006564 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006565 istk->mstk = m->mstk;
6566 if (m->name) {
6567 /*
6568 * This was a real macro call, not a %rep, and
6569 * therefore the parameter information needs to
6570 * be freed and the iteration count/nesting
6571 * depth adjusted.
6572 */
6573
6574 if (!--mmacro_deadman.levels) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006575 /*
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006576 * If all mmacro processing done,
6577 * clear all counters and the deadman
6578 * message trigger.
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006579 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006580 nasm_zero(mmacro_deadman); /* Clear all counters */
Adam Majer91e72402017-07-25 10:42:01 +02006581 }
6582
Adam Majer91e72402017-07-25 10:42:01 +02006583#if 0
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006584 if (m->prev) {
6585 pop_mmacro(m);
6586 fm->in_progress --;
6587 } else
Adam Majer91e72402017-07-25 10:42:01 +02006588#endif
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006589 {
6590 nasm_free(m->params);
6591 free_tlist(m->iline);
6592 nasm_free(m->paramlen);
6593 fm->in_progress = 0;
6594 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006595 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006596
6597 /*
6598 * FIXME It is incorrect to always free_mmacro here.
6599 * It leads to usage-after-free.
6600 *
6601 * https://bugzilla.nasm.us/show_bug.cgi?id=3392414
6602 */
6603#if 0
6604 else
6605 free_mmacro(m);
6606#endif
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006607 }
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006608 istk->where = l->where;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006609 istk->expansion = l->next;
6610 nasm_free(l);
6611 lfmt->downlevel(LIST_MACRO);
6612 return &tok_pop;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006613 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006614
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006615 do { /* until we get a line we can use */
6616 char *line;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006617
6618 if (istk->expansion) { /* from a macro expansion */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006619 Line *l = istk->expansion;
H. Peter Anvinab6f8312019-08-09 22:31:45 -07006620
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006621 istk->expansion = l->next;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006622 istk->where = l->where;
6623 tline = l->first;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006624 nasm_free(l);
H. Peter Anvinab6f8312019-08-09 22:31:45 -07006625
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006626 if (!istk->nolist) {
6627 line = detoken(tline, false);
6628 lfmt->line(LIST_MACRO, istk->where.lineno, line);
6629 nasm_free(line);
6630 }
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006631 } else if ((line = read_line())) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006632 line = prepreproc(line);
Keith Kaniosb7a89542007-04-12 02:40:54 +00006633 tline = tokenize(line);
H. Peter Anvine2c80182005-01-15 22:15:51 +00006634 nasm_free(line);
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006635 } else {
6636 /*
6637 * The current file has ended; work down the istk
6638 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00006639 Include *i = istk;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006640 Include *is;
6641
H. Peter Anvin6686de22019-08-10 05:33:14 -07006642 if (i->fp)
6643 fclose(i->fp);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006644 if (i->conds) {
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006645 /* nasm_fatal can't be conditionally suppressed */
H. Peter Anvinc5136902018-06-15 18:20:17 -07006646 nasm_fatal("expected `%%endif' before end of file");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006647 }
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006648
6649 list_for_each(is, i->next) {
6650 if (is->fp) {
6651 lfmt->downlevel(LIST_INCLUDE);
6652 src_update(is->where);
6653 break;
6654 }
6655 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00006656 istk = i->next;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006657 nasm_free(i);
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006658 return &tok_pop;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006659 }
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006660 } while (0);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006661
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006662 /*
6663 * We must expand MMacro parameters and MMacro-local labels
6664 * _before_ we plunge into directive processing, to cope
6665 * with things like `%define something %1' such as STRUC
6666 * uses. Unless we're _defining_ a MMacro, in which case
6667 * those tokens should be left alone to go into the
6668 * definition; and unless we're in a non-emitting
6669 * condition, in which case we don't want to meddle with
6670 * anything.
6671 */
H. Peter Anvin (Intel)bacf04a2020-06-08 13:29:06 -07006672 if (!defining &&
6673 !(istk->conds && !emitting(istk->conds->state)) &&
6674 !(istk->mstk.mmac && !istk->mstk.mmac->in_progress)) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006675 tline = expand_mmac_params(tline);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006676 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006677
H. Peter Anvine2c80182005-01-15 22:15:51 +00006678 /*
6679 * Check the line to see if it's a preprocessor directive.
6680 */
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006681 if (do_directive(tline, &dtline) == DIRECTIVE_FOUND) {
6682 if (dtline)
6683 return dtline;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006684 } else if (defining) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006685 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006686 * We're defining a multi-line macro. We emit nothing
6687 * at all, and just
6688 * shove the tokenized line on to the macro definition.
H. Peter Anvine2c80182005-01-15 22:15:51 +00006689 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006690 MMacro *mmac = defining->dstk.mmac;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006691 Line *l;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006692
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006693 nasm_new(l);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006694 l->next = defining->expansion;
6695 l->first = tline;
6696 l->finishes = NULL;
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006697 l->where = istk->where;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006698 defining->expansion = l;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006699
6700 /*
6701 * Remember if this mmacro expansion contains %00:
6702 * if it does, we will have to handle leading labels
6703 * specially.
6704 */
6705 if (mmac) {
6706 const Token *t;
6707 list_for_each(t, tline) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07006708 if (!memcmp(t->text.a, "%00", 4))
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006709 mmac->capture_label = true;
6710 }
6711 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006712 } else if (istk->conds && !emitting(istk->conds->state)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006713 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006714 * We're in a non-emitting branch of a condition block.
H. Peter Anvine2c80182005-01-15 22:15:51 +00006715 * Emit nothing at all, not even a blank line: when we
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006716 * emerge from the condition we'll give a line-number
H. Peter Anvine2c80182005-01-15 22:15:51 +00006717 * directive so we keep our place correctly.
6718 */
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006719 free_tlist(tline);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006720 } else if (istk->mstk.mstk && !istk->mstk.mstk->in_progress) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006721 /*
6722 * We're in a %rep block which has been terminated, so
6723 * we're walking through to the %endrep without
6724 * emitting anything. Emit nothing at all, not even a
6725 * blank line: when we emerge from the %rep block we'll
6726 * give a line-number directive so we keep our place
6727 * correctly.
6728 */
6729 free_tlist(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00006730 } else {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006731 tline = expand_smacro(tline);
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006732 if (!expand_mmacro(tline))
6733 return tline;
6734 }
6735 }
6736}
6737
6738static char *pp_getline(void)
6739{
6740 char *line = NULL;
6741 Token *tline;
6742
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006743 while (true) {
6744 tline = pp_tokline();
6745 if (tline == &tok_pop) {
6746 /*
6747 * We popped the macro/include stack. If istk is empty,
6748 * we are at end of input, otherwise just loop back.
6749 */
6750 if (!istk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006751 break;
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006752 } else {
6753 /*
6754 * De-tokenize the line and emit it.
6755 */
6756 line = detoken(tline, true);
6757 free_tlist(tline);
6758 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006759 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006760 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006761
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006762 if (list_option('e') && istk && !istk->nolist && line && line[0]) {
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07006763 char *buf = nasm_strcat(" ;;; ", line);
H. Peter Anvinab6f8312019-08-09 22:31:45 -07006764 lfmt->line(LIST_MACRO, -1, buf);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07006765 nasm_free(buf);
6766 }
6767
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006768 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006769}
6770
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006771static void pp_cleanup_pass(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006772{
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006773 if (defining) {
6774 if (defining->name) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03006775 nasm_nonfatal("end of file while still defining macro `%s'",
6776 defining->name);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006777 } else {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03006778 nasm_nonfatal("end of file while still in %%rep");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006779 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006780
6781 free_mmacro(defining);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006782 defining = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006783 }
H. Peter Anvin130736c2016-02-17 20:27:41 -08006784
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006785 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006786 ctx_pop();
H. Peter Anvin97a23472007-09-16 17:57:25 -07006787 free_macros();
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006788 while (istk) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006789 Include *i = istk;
6790 istk = istk->next;
6791 fclose(i->fp);
Cyrill Gorcunov8dcfd882011-03-03 09:18:56 +03006792 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006793 }
6794 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006795 ctx_pop();
H. Peter Anvin274cda82016-05-10 02:56:29 -07006796 src_set_fname(NULL);
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006797}
6798
6799static void pp_cleanup_session(void)
6800{
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07006801 nasm_free(use_loaded);
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006802 free_llist(predef);
6803 predef = NULL;
6804 delete_Blocks();
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006805 ipath_list = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006806}
6807
Cyrill Gorcunov8c0666b2018-11-24 14:33:48 +03006808static void pp_include_path(struct strlist *list)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006809{
Cyrill Gorcunov8c0666b2018-11-24 14:33:48 +03006810 ipath_list = list;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006811}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00006812
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04006813static void pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006814{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006815 Token *inc, *space, *name;
6816 Line *l;
6817
H. Peter Anvin734b1882002-04-30 21:01:08 +00006818 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006819 space = new_White(name);
H. Peter Anvin734b1882002-04-30 21:01:08 +00006820 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006821
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006822 l = nasm_malloc(sizeof(Line));
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006823 l->next = predef;
6824 l->first = inc;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006825 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006826 predef = l;
6827}
6828
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04006829static void pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006830{
6831 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006832 Line *l;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00006833 char *equals;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006834
6835 equals = strchr(definition, '=');
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006836 space = new_White(NULL);
H. Peter Anvin734b1882002-04-30 21:01:08 +00006837 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006838 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006839 *equals = ' ';
Keith Kaniosb7a89542007-04-12 02:40:54 +00006840 space->next = tokenize(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006841 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006842 *equals = '=';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006843
H. Peter Anvin8571f062019-09-23 16:40:03 -07006844 /* We can't predefine a TOK_LOCAL_MACRO for obvious reasons... */
Cyrill Gorcunov6d42e9b2015-02-08 11:07:17 +03006845 if (space->next->type != TOK_PREPROC_ID &&
6846 space->next->type != TOK_ID)
H. Peter Anvin (Intel)80c4f232018-12-14 13:33:24 -08006847 nasm_warn(WARN_OTHER, "pre-defining non ID `%s\'\n", definition);
Cyrill Gorcunov6d42e9b2015-02-08 11:07:17 +03006848
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006849 l = nasm_malloc(sizeof(Line));
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006850 l->next = predef;
6851 l->first = def;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006852 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006853 predef = l;
6854}
6855
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04006856static void pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00006857{
6858 Token *def, *space;
6859 Line *l;
6860
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006861 space = new_White(NULL);
H. Peter Anvin734b1882002-04-30 21:01:08 +00006862 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Keith Kaniosb7a89542007-04-12 02:40:54 +00006863 space->next = tokenize(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00006864
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006865 l = nasm_malloc(sizeof(Line));
H. Peter Anvin620515a2002-04-30 20:57:38 +00006866 l->next = predef;
6867 l->first = def;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006868 l->finishes = NULL;
H. Peter Anvin620515a2002-04-30 20:57:38 +00006869 predef = l;
6870}
6871
H. Peter Anvin05990342018-06-11 13:32:42 -07006872/* Insert an early preprocessor command that doesn't need special handling */
6873static void pp_pre_command(const char *what, char *string)
6874{
6875 char *cmd;
6876 Token *def, *space;
6877 Line *l;
6878
6879 def = tokenize(string);
6880 if (what) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006881 space = new_White(def);
H. Peter Anvin8571f062019-09-23 16:40:03 -07006882 cmd = nasm_strcat(what[0] == '%' ? "" : "%", what);
6883 def = new_Token(space, TOK_PREPROC_ID, cmd, nasm_last_string_len());
6884 nasm_free(cmd);
H. Peter Anvin05990342018-06-11 13:32:42 -07006885 }
6886
6887 l = nasm_malloc(sizeof(Line));
6888 l->next = predef;
6889 l->first = def;
6890 l->finishes = NULL;
6891 predef = l;
6892}
6893
H. Peter Anvinf7606612016-07-13 14:23:48 -07006894static void pp_add_stdmac(macros_t *macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006895{
H. Peter Anvinf7606612016-07-13 14:23:48 -07006896 macros_t **mp;
6897
6898 /* Find the end of the list and avoid duplicates */
6899 for (mp = stdmacros; *mp; mp++) {
6900 if (*mp == macros)
6901 return; /* Nothing to do */
6902 }
6903
6904 nasm_assert(mp < &stdmacros[ARRAY_SIZE(stdmacros)-1]);
6905
6906 *mp = macros;
H. Peter Anvin76690a12002-04-30 20:52:49 +00006907}
6908
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +03006909static void pp_extra_stdmac(macros_t *macros)
6910{
6911 extrastdmac = macros;
6912}
6913
H. Peter Anvin8571f062019-09-23 16:40:03 -07006914/* Create a numeric token */
6915static Token *make_tok_num(Token *next, int64_t val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006916{
Cyrill Gorcunovce652742013-05-06 23:43:43 +04006917 char numbuf[32];
H. Peter Anvin8b262472019-02-26 14:00:54 -08006918 int len = snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
H. Peter Anvin8571f062019-09-23 16:40:03 -07006919 return new_Token(next, TOK_NUMBER, numbuf, len);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006920}
6921
H. Peter Anvin8571f062019-09-23 16:40:03 -07006922/* Create a quoted string token */
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07006923static Token *make_tok_qstr_len(Token *next, const char *str, size_t len)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006924{
H. Peter Anvin8571f062019-09-23 16:40:03 -07006925 char *p = nasm_quote(str, &len);
6926 return new_Token_free(next, TOK_STRING, p, len);
6927}
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07006928static Token *make_tok_qstr(Token *next, const char *str)
6929{
6930 return make_tok_qstr_len(next, str, strlen(str));
6931}
H. Peter Anvin8571f062019-09-23 16:40:03 -07006932
6933/* Create a single-character operator token */
6934static Token *make_tok_char(Token *next, char op)
6935{
6936 Token *t = new_Token(next, TOK_OTHER, NULL, 1);
6937 t->text.a[0] = op;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006938 return t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00006939}
6940
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006941/*
6942 * Descend the istk looking for macro definitions; we have to
6943 * recurse because we want to show the messages in top-down order.
6944 */
6945static void pp_list_macro_istk(Include *inc, errflags severity)
H. Peter Anvin37368952016-05-09 14:10:32 -07006946{
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006947 MMacro *m;
6948 Include *inext;
H. Peter Anvin37368952016-05-09 14:10:32 -07006949
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006950 /* Find the next higher level true macro invocation if any */
6951 inext = inc->next;
6952 if (inext && inext->mstk.mmac) {
6953 while (inext) {
6954 if (inext->mstk.mstk->name) {
6955 pp_list_macro_istk(inext, severity);
6956 break;
6957 }
6958 inext = inext->next;
6959 }
6960 }
H. Peter Anvin37368952016-05-09 14:10:32 -07006961
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006962 m = inc->mstk.mstk;
6963 if (m && m->name && !m->nolist) {
6964 src_update(inc->where);
H. Peter Anvinddb29062018-12-11 00:06:29 -08006965 nasm_error(severity, "... from macro `%s' defined", m->name);
H. Peter Anvin37368952016-05-09 14:10:32 -07006966 }
6967}
6968
H. Peter Anvin (Intel)6bde2ed2018-12-13 19:39:41 -08006969static void pp_error_list_macros(errflags severity)
H. Peter Anvin4def1a82016-05-09 13:59:44 -07006970{
H. Peter Anvinddb29062018-12-11 00:06:29 -08006971 struct src_location saved;
H. Peter Anvin4def1a82016-05-09 13:59:44 -07006972
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006973 if (!istk)
6974 return;
6975
H. Peter Anvinddb29062018-12-11 00:06:29 -08006976 severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE;
6977 saved = src_where();
H. Peter Anvin (Intel)b2927482020-06-14 20:09:11 -07006978 pp_list_macro_istk(istk, severity);
H. Peter Anvinddb29062018-12-11 00:06:29 -08006979 src_update(saved);
H. Peter Anvin4def1a82016-05-09 13:59:44 -07006980}
6981
H. Peter Anvine7469712016-02-18 02:20:59 -08006982const struct preproc_ops nasmpp = {
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07006983 pp_init,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006984 pp_reset,
6985 pp_getline,
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006986 pp_cleanup_pass,
6987 pp_cleanup_session,
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +03006988 pp_extra_stdmac,
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04006989 pp_pre_define,
6990 pp_pre_undefine,
6991 pp_pre_include,
H. Peter Anvin05990342018-06-11 13:32:42 -07006992 pp_pre_command,
H. Peter Anvin4def1a82016-05-09 13:59:44 -07006993 pp_include_path,
6994 pp_error_list_macros,
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006995 pp_suppress_error
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006996};