blob: 5e71cecb7af68cd98f641d0fcc90bbee8a005590 [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 */
282 unsigned int nparam, rotate;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700283 char *iname; /* name invoked as */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800284 int *paramlen;
285 uint64_t unique;
286 int lineno; /* Current line number on expansion */
287 uint64_t condcnt; /* number of if blocks... */
H. Peter Anvin4def1a82016-05-09 13:59:44 -0700288
H. Peter Anvin274cda82016-05-10 02:56:29 -0700289 const char *fname; /* File where defined */
H. Peter Anvin4def1a82016-05-09 13:59:44 -0700290 int32_t xline; /* First line in macro */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800291};
292
293
294/* Store the definition of a multi-line macro, as defined in a
295 * previous recursive macro expansion.
296 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700297#if 0
298
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800299struct MMacroInvocation {
300 MMacroInvocation *prev; /* previous invocation */
301 Token **params; /* actual parameters */
302 Token *iline; /* invocation line */
303 unsigned int nparam, rotate;
304 int *paramlen;
305 uint64_t unique;
306 uint64_t condcnt;
307};
308
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700309#endif
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800310
311/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000312 * The context stack is composed of a linked list of these.
313 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000314struct Context {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800315 Context *next;
H. Peter Anvin8571f062019-09-23 16:40:03 -0700316 const char *name;
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800317 struct hash_table localmac;
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -0700318 uint64_t number;
319 unsigned int depth;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000320};
321
H. Peter Anvin8571f062019-09-23 16:40:03 -0700322
323static inline const char *tok_text(const struct Token *t)
324{
325 return (t->len <= INLINE_TEXT) ? t->text.a : t->text.p.ptr;
326}
327
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000328/*
H. Peter Anvin8571f062019-09-23 16:40:03 -0700329 * Returns a mutable pointer to the text buffer. The text can be changed,
330 * but the length MUST NOT CHANGE, in either direction; nor is it permitted
331 * to pad with null characters to create an artificially shorter string.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000332 */
H. Peter Anvin8571f062019-09-23 16:40:03 -0700333static inline char *tok_text_buf(struct Token *t)
H. Peter Anvin8b262472019-02-26 14:00:54 -0800334{
H. Peter Anvin8571f062019-09-23 16:40:03 -0700335 return (t->len <= INLINE_TEXT) ? t->text.a : t->text.p.ptr;
H. Peter Anvin8b262472019-02-26 14:00:54 -0800336}
337
H. Peter Anvin8571f062019-09-23 16:40:03 -0700338static inline unsigned int tok_check_len(size_t len)
339{
340 if (unlikely(len > MAX_TEXT))
341 nasm_fatal("impossibly large token");
Cyrill Gorcunov8dcbbd72010-09-25 02:33:20 +0400342
H. Peter Anvin8571f062019-09-23 16:40:03 -0700343 return len;
344}
Cyrill Gorcunov575d4282010-10-06 00:25:55 +0400345
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700346static inline bool tok_text_match(const struct Token *a, const struct Token *b)
347{
348 return a->len == b->len && !memcmp(tok_text(a), tok_text(b), a->len);
349}
350
351static inline bool tok_match(const struct Token *a, const struct Token *b)
352{
353 return a->type == b->type && tok_text_match(a, b);
354}
355
H. Peter Anvin8571f062019-09-23 16:40:03 -0700356/* strlen() variant useful for set_text() and its variants */
357static size_t tok_strlen(const char *str)
358{
359 return strnlen(str, MAX_TEXT+1);
360}
361
362/*
363 * Set the text field to a copy of the given string; the length if
364 * not given should be obtained with tok_strlen().
365 */
366static Token *set_text(struct Token *t, const char *text, size_t len)
367{
368 char *textp;
369
370 if (t->len > INLINE_TEXT)
371 nasm_free(t->text.p.ptr);
372
373 nasm_zero(t->text.a);
374
375 t->len = tok_check_len(len);
376 textp = (len > INLINE_TEXT)
377 ? (t->text.p.ptr = nasm_malloc(len+1)) : t->text.a;
378 memcpy(textp, text, len+1);
379 return t;
380}
381
382/*
383 * Set the text field to the existing pre-allocated string, either
384 * taking over or freeing the allocation in the process.
385 */
386static Token *set_text_free(struct Token *t, char *text, unsigned int len)
387{
388 if (t->len > INLINE_TEXT)
389 nasm_free(t->text.p.ptr);
390
391 nasm_zero(t->text.a);
392
393 t->len = tok_check_len(len);
394 if (len > INLINE_TEXT) {
395 t->text.p.ptr = text;
396 } else {
397 memcpy(t->text.a, text, len+1);
398 nasm_free(text);
399 }
400
401 return t;
402}
403
404/*
405 * Allocate a new buffer containing a copy of the text field
406 * of the token.
407 */
408static char *dup_text(const struct Token *t)
409{
410 size_t size = t->len + 1;
411 char *p = nasm_malloc(size);
412
413 return memcpy(p, tok_text(t), size);
414}
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000415
416/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800417 * Multi-line macro definitions are stored as a linked list of
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000418 * these, which is essentially a container to allow several linked
419 * lists of Tokens.
H. Peter Anvin70653092007-10-19 14:42:29 -0700420 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000421 * Note that in this module, linked lists are treated as stacks
422 * wherever possible. For this reason, Lines are _pushed_ on to the
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800423 * `expansion' field in MMacro structures, so that the linked list,
424 * if walked, would give the macro lines in reverse order; this
425 * means that we can walk the list when expanding a macro, and thus
426 * push the lines on to the `expansion' field in _istk_ in reverse
427 * order (so that when popped back off they are in the right
428 * order). It may seem cockeyed, and it relies on my design having
429 * an even number of steps in, but it works...
430 *
431 * Some of these structures, rather than being actual lines, are
432 * markers delimiting the end of the expansion of a given macro.
433 * This is for use in the cycle-tracking and %rep-handling code.
434 * Such structures have `finishes' non-NULL, and `first' NULL. All
435 * others have `finishes' NULL, but `first' may still be NULL if
436 * the line is blank.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000437 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000438struct Line {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800439 Line *next;
440 MMacro *finishes;
441 Token *first;
Keith Kaniosb307a4f2010-11-06 17:41:51 -0500442};
443
444/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000445 * To handle an arbitrary level of file inclusion, we maintain a
446 * stack (ie linked list) of these things.
447 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000448struct Include {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800449 Include *next;
450 FILE *fp;
451 Cond *conds;
452 Line *expansion;
H. Peter Anvin274cda82016-05-10 02:56:29 -0700453 const char *fname;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700454 struct mstk mstk;
H. Peter Anvin6686de22019-08-10 05:33:14 -0700455 int lineno, lineinc;
456 bool nolist;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000457};
458
459/*
H. Peter Anvin169ac7c2016-09-25 17:08:05 -0700460 * File real name hash, so we don't have to re-search the include
461 * path for every pass (and potentially more than that if a file
462 * is used more than once.)
463 */
464struct hash_table FileHash;
465
466/*
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -0700467 * Counters to trap on insane macro recursion or processing.
468 * Note: for smacros these count *down*, for mmacros they count *up*.
469 */
470struct deadman {
471 int64_t total; /* Total number of macros/tokens */
472 int64_t levels; /* Descent depth across all macros */
473 bool triggered; /* Already triggered, no need for error msg */
474};
475
476static struct deadman smacro_deadman, mmacro_deadman;
477
478/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000479 * Conditional assembly: we maintain a separate stack of these for
480 * each level of file inclusion. (The only reason we keep the
481 * stacks separate is to ensure that a stray `%endif' in a file
482 * included from within the true branch of a `%if' won't terminate
483 * it and cause confusion: instead, rightly, it'll cause an error.)
484 */
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -0700485enum cond_state {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000486 /*
487 * These states are for use just after %if or %elif: IF_TRUE
488 * means the condition has evaluated to truth so we are
489 * currently emitting, whereas IF_FALSE means we are not
490 * currently emitting but will start doing so if a %else comes
491 * up. In these states, all directives are admissible: %elif,
492 * %else and %endif. (And of course %if.)
493 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800494 COND_IF_TRUE, COND_IF_FALSE,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000495 /*
496 * These states come up after a %else: ELSE_TRUE means we're
497 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
498 * any %elif or %else will cause an error.
499 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800500 COND_ELSE_TRUE, COND_ELSE_FALSE,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000501 /*
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200502 * These states mean that we're not emitting now, and also that
503 * nothing until %endif will be emitted at all. COND_DONE is
504 * used when we've had our moment of emission
505 * and have now started seeing %elifs. COND_NEVER is used when
506 * the condition construct in question is contained within a
507 * non-emitting branch of a larger condition construct,
508 * or if there is an error.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000509 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800510 COND_DONE, COND_NEVER
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000511};
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -0700512struct Cond {
513 Cond *next;
514 enum cond_state state;
515};
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800516#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000517
H. Peter Anvin70653092007-10-19 14:42:29 -0700518/*
Ed Beroset3ab3f412002-06-11 03:31:49 +0000519 * These defines are used as the possible return values for do_directive
520 */
521#define NO_DIRECTIVE_FOUND 0
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300522#define DIRECTIVE_FOUND 1
Ed Beroset3ab3f412002-06-11 03:31:49 +0000523
Keith Kanios852f1ee2009-07-12 00:19:55 -0500524/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000525 * Condition codes. Note that we use c_ prefix not C_ because C_ is
526 * used in nasm.h for the "real" condition codes. At _this_ level,
527 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
528 * ones, so we need a different enum...
529 */
H. Peter Anvin476d2862007-10-02 22:04:15 -0700530static const char * const conditions[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000531 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
532 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
H. Peter Anvince9be342007-09-12 00:22:29 +0000533 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000534};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700535enum pp_conds {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000536 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
537 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 -0700538 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
539 c_none = -1
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000540};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700541static const enum pp_conds inverse_ccs[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000542 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
543 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 +0000544 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000545};
546
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800547/*
548 * Directive names.
549 */
550/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
551static int is_condition(enum preproc_token arg)
552{
553 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
554}
555
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000556/* For TASM compatibility we need to be able to recognise TASM compatible
557 * conditional compilation directives. Using the NASM pre-processor does
558 * not work, so we look for them specifically from the following list and
559 * then jam in the equivalent NASM directive into the input stream.
560 */
561
H. Peter Anvine2c80182005-01-15 22:15:51 +0000562enum {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000563 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
564 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
565};
566
H. Peter Anvin476d2862007-10-02 22:04:15 -0700567static const char * const tasm_directives[] = {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000568 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
569 "ifndef", "include", "local"
570};
571
572static int StackSize = 4;
H. Peter Anvin6c8b2be2016-05-24 23:46:50 -0700573static const char *StackPointer = "ebp";
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000574static int ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -0800575static int LocalOffset = 0;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000576
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000577static Context *cstk;
578static Include *istk;
Cyrill Gorcunov8c0666b2018-11-24 14:33:48 +0300579static const struct strlist *ipath_list;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000580
Cyrill Gorcunovb7bb5ac2018-11-11 21:33:52 +0300581static struct strlist *deplist;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000582
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300583static uint64_t unique; /* unique identifier numbers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000584
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800585static Line *predef = NULL;
H. Peter Anvind2456592008-06-19 15:04:18 -0700586static bool do_predef;
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -0800587static enum preproc_mode pp_mode;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000588
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000589/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800590 * The current set of multi-line macros we have defined.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000591 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800592static struct hash_table mmacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000593
594/*
595 * The current set of single-line macros we have defined.
596 */
H. Peter Anvin166c2472008-05-28 12:28:58 -0700597static struct hash_table smacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000598
599/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800600 * The multi-line macro we are currently defining, or the %rep
601 * block we are currently reading, if any.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000602 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800603static MMacro *defining;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000604
Charles Crayned4200be2008-07-12 16:42:33 -0700605static uint64_t nested_mac_count;
606static uint64_t nested_rep_count;
607
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000608/*
609 * The number of macro parameters to allocate space for at a time.
610 */
611#define PARAM_DELTA 16
612
613/*
H. Peter Anvinf7606612016-07-13 14:23:48 -0700614 * The standard macro set: defined in macros.c in a set of arrays.
615 * This gives our position in any macro set, while we are processing it.
616 * The stdmacset is an array of such macro sets.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000617 */
H. Peter Anvina70547f2008-07-19 21:44:26 -0700618static macros_t *stdmacpos;
H. Peter Anvinf7606612016-07-13 14:23:48 -0700619static macros_t **stdmacnext;
620static macros_t *stdmacros[8];
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +0300621static macros_t *extrastdmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000622
623/*
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -0700624 * Map of which %use packages have been loaded
625 */
626static bool *use_loaded;
627
628/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000629 * Forward declarations.
630 */
H. Peter Anvinf7606612016-07-13 14:23:48 -0700631static void pp_add_stdmac(macros_t *macros);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000632static Token *expand_mmac_params(Token * tline);
633static Token *expand_smacro(Token * tline);
634static Token *expand_id(Token * tline);
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +0400635static Context *get_ctx(const char *name, const char **namep);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700636static Token *make_tok_num(Token *next, int64_t val);
637static Token *make_tok_qstr(Token *next, const char *str);
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -0700638static Token *make_tok_qstr_len(Token *next, const char *str, size_t len);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700639static Token *make_tok_char(Token *next, char op);
H. Peter Anvinc751e862008-06-09 10:18:45 -0700640static Token *new_Token(Token * next, enum pp_token_type type,
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -0700641 const char *text, size_t txtlen);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700642static Token *new_Token_free(Token * next, enum pp_token_type type,
643 char *text, size_t txtlen);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -0700644static Token *dup_Token(Token *next, const Token *src);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -0700645static Token *new_White(Token *next);
H. Peter Anvin8571f062019-09-23 16:40:03 -0700646static Token *delete_Token(Token *t);
647static Token *steal_Token(Token *dst, Token *src);
H. Peter Anvindd88aa92019-09-12 19:39:48 -0700648static const struct use_package *
H. Peter Anvin8571f062019-09-23 16:40:03 -0700649get_use_pkg(Token *t, const char *dname, const char **name);
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -0700650static void mark_smac_params(Token *tline, const SMacro *tmpl,
651 enum pp_token_type type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000652
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -0700653/* Safe test for token type, false on x == NULL */
654static inline bool tok_type(const Token *x, enum pp_token_type t)
655{
656 return x && x->type == t;
657}
658
659/* Whitespace token? */
660static inline bool tok_white(const Token *x)
661{
662 return tok_type(x, TOK_WHITESPACE);
663}
664
665/* Skip past any whitespace */
666static inline Token *skip_white(Token *x)
667{
668 while (tok_white(x))
669 x = x->next;
670
671 return x;
672}
673
674/* Delete any whitespace */
675static Token *zap_white(Token *x)
676{
677 while (tok_white(x))
678 x = delete_Token(x);
679
680 return x;
681}
682
H. Peter Anvin8571f062019-09-23 16:40:03 -0700683/*
684 * Single special character tests. The use of & rather than && is intentional; it
685 * tells the compiler that it is safe to access text.a[1] unconditionally; hopefully
686 * a smart compiler should turn it into a 16-bit memory reference.
687 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -0700688static inline bool tok_is(const Token *x, char c)
689{
H. Peter Anvin8571f062019-09-23 16:40:03 -0700690 return x && ((x->text.a[0] == c) & !x->text.a[1]);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -0700691}
692
693/* True if any other kind of token that "c", but not NULL */
694static inline bool tok_isnt(const Token *x, char c)
695{
H. Peter Anvin8571f062019-09-23 16:40:03 -0700696 return x && !((x->text.a[0] == c) & !x->text.a[1]);
697}
698
699/*
700 * Unquote a token if it is a string, and set its type to
701 * TOK_INTERNAL_STRING.
702 */
703static const char *unquote_token(Token *t)
704{
705 if (t->type != TOK_STRING)
706 return tok_text(t);
707
708 t->type = TOK_INTERNAL_STRING;
709
710 if (t->len > INLINE_TEXT) {
711 char *p = t->text.p.ptr;
712
713 t->len = nasm_unquote(p, NULL);
714
715 if (t->len <= INLINE_TEXT) {
716 nasm_zero(t->text.a);
717 memcpy(t->text.a, p, t->len);
718 nasm_free(p);
719 return t->text.a;
720 } else {
721 return p;
722 }
723 } else {
724 t->len = nasm_unquote(t->text.a, NULL);
725 return t->text.a;
726 }
727}
728
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700729/*
730 * Same as unquote_token(), but error out if the resulting string
731 * contains unacceptable control characters.
732 */
H. Peter Anvin8571f062019-09-23 16:40:03 -0700733static const char *unquote_token_cstr(Token *t)
734{
735 if (t->type != TOK_STRING)
736 return tok_text(t);
737
738 t->type = TOK_INTERNAL_STRING;
739
740 if (t->len > INLINE_TEXT) {
741 char *p = t->text.p.ptr;
742
743 t->len = nasm_unquote_cstr(p, NULL);
744
745 if (t->len <= INLINE_TEXT) {
746 nasm_zero(t->text.a);
747 memcpy(t->text.a, p, t->len);
748 nasm_free(p);
749 return t->text.a;
750 } else {
751 return p;
752 }
753 } else {
754 t->len = nasm_unquote_cstr(t->text.a, NULL);
755 return t->text.a;
756 }
757}
758
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700759/*
760 * Convert a TOK_INTERNAL_STRING token to a quoted
761 * TOK_STRING tokens.
762 */
763static Token *quote_any_token(Token *t);
764static inline Token *quote_token(Token *t)
765{
766 if (likely(!tok_is(t, TOK_INTERNAL_STRING)))
767 return t;
768
769 return quote_any_token(t);
770}
771
772/*
773 * Convert *any* kind of token to a quoted
774 * TOK_STRING token.
775 */
776static Token *quote_any_token(Token *t)
H. Peter Anvin8571f062019-09-23 16:40:03 -0700777{
778 size_t len;
779 char *p;
780
781 p = nasm_quote(tok_text(t), &len);
782 t->type = TOK_STRING;
783 return set_text_free(t, p, len);
784}
785
Cyrill Gorcunov194ba892011-06-30 01:16:35 +0400786/*
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700787 * In-place reverse a list of tokens.
788 */
789static Token *reverse_tokens(Token *t)
790{
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800791 Token *prev = NULL;
792 Token *next;
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700793
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800794 while (t) {
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +0400795 next = t->next;
796 t->next = prev;
797 prev = t;
798 t = next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800799 }
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700800
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800801 return prev;
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700802}
803
804/*
H. Peter Anvin8571f062019-09-23 16:40:03 -0700805 * getenv() variant operating on an input token
806 */
807static const char *pp_getenv(const Token *t, bool warn)
808{
809 const char *txt = tok_text(t);
810 const char *v;
811 char *buf = NULL;
812 bool is_string = false;
813
814 if (!t)
815 return NULL;
816
817 switch (t->type) {
818 case TOK_ENVIRON:
819 txt += 2; /* Skip leading %! */
820 is_string = nasm_isquote(*txt);
821 break;
822
823 case TOK_STRING:
824 is_string = true;
825 break;
826
827 case TOK_INTERNAL_STRING:
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -0700828 case TOK_NAKED_STRING:
H. Peter Anvin8571f062019-09-23 16:40:03 -0700829 case TOK_ID:
830 is_string = false;
831 break;
832
833 default:
834 return NULL;
835 }
836
837 if (is_string) {
838 buf = nasm_strdup(txt);
839 nasm_unquote_cstr(buf, NULL);
840 txt = buf;
841 }
842
843 v = getenv(txt);
844 if (warn && !v) {
845 /*!
846 *!environment [on] nonexistent environment variable
847 *! warns if a nonexistent environment variable
848 *! is accessed using the \c{%!} preprocessor
849 *! construct (see \k{getenv}.) Such environment
850 *! variables are treated as empty (with this
851 *! warning issued) starting in NASM 2.15;
852 *! earlier versions of NASM would treat this as
853 *! an error.
854 */
855 nasm_warn(WARN_ENVIRONMENT, "nonexistent environment variable `%s'", txt);
856 v = "";
857 }
858
859 if (buf)
860 nasm_free(buf);
861
862 return v;
863}
864
865/*
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300866 * Handle TASM specific directives, which do not contain a % in
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000867 * front of them. We do it here because I could not find any other
868 * place to do it for the moment, and it is a hack (ideally it would
869 * be nice to be able to use the NASM pre-processor to do it).
870 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000871static char *check_tasm_directive(char *line)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000872{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000873 int32_t i, j, k, m, len;
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400874 char *p, *q, *oldline, oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000875
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400876 p = nasm_skip_spaces(line);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000877
878 /* Binary search for the directive name */
879 i = -1;
Cyrill Gorcunova7319242010-06-03 22:04:36 +0400880 j = ARRAY_SIZE(tasm_directives);
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400881 q = nasm_skip_word(p);
882 len = q - p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000883 if (len) {
884 oldchar = p[len];
885 p[len] = 0;
886 while (j - i > 1) {
887 k = (j + i) / 2;
888 m = nasm_stricmp(p, tasm_directives[k]);
889 if (m == 0) {
890 /* We have found a directive, so jam a % in front of it
891 * so that NASM will then recognise it as one if it's own.
892 */
893 p[len] = oldchar;
894 len = strlen(p);
895 oldline = line;
896 line = nasm_malloc(len + 2);
897 line[0] = '%';
898 if (k == TM_IFDIFI) {
H. Peter Anvin18f48792009-06-27 15:56:27 -0700899 /*
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300900 * NASM does not recognise IFDIFI, so we convert
901 * it to %if 0. This is not used in NASM
902 * compatible code, but does need to parse for the
903 * TASM macro package.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000904 */
H. Peter Anvin18f48792009-06-27 15:56:27 -0700905 strcpy(line + 1, "if 0");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000906 } else {
907 memcpy(line + 1, p, len + 1);
908 }
909 nasm_free(oldline);
910 return line;
911 } else if (m < 0) {
912 j = k;
913 } else
914 i = k;
915 }
916 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000917 }
918 return line;
919}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000920
H. Peter Anvin76690a12002-04-30 20:52:49 +0000921/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000922 * The pre-preprocessing stage... This function translates line
923 * number indications as they emerge from GNU cpp (`# lineno "file"
924 * flags') into NASM preprocessor line number indications (`%line
925 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000926 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000927static char *prepreproc(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000928{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000929 int lineno, fnlen;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000930 char *fname, *oldline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000931
H. Peter Anvine2c80182005-01-15 22:15:51 +0000932 if (line[0] == '#' && line[1] == ' ') {
933 oldline = line;
934 fname = oldline + 2;
935 lineno = atoi(fname);
936 fname += strspn(fname, "0123456789 ");
937 if (*fname == '"')
938 fname++;
939 fnlen = strcspn(fname, "\"");
940 line = nasm_malloc(20 + fnlen);
941 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
942 nasm_free(oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000943 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000944 if (tasm_compatible_mode)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000945 return check_tasm_directive(line);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000946 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000947}
948
949/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000950 * Free a linked list of tokens.
951 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000952static void free_tlist(Token * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000953{
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400954 while (list)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000955 list = delete_Token(list);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000956}
957
958/*
959 * Free a linked list of lines.
960 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000961static void free_llist(Line * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000962{
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400963 Line *l, *tmp;
964 list_for_each_safe(l, tmp, list) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000965 free_tlist(l->first);
966 nasm_free(l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000967 }
968}
969
970/*
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -0700971 * Free an array of linked lists of tokens
972 */
973static void free_tlist_array(Token **array, size_t nlists)
974{
975 Token **listp = array;
976
977 while (nlists--)
978 free_tlist(*listp++);
979
980 nasm_free(array);
981}
982
983/*
984 * Duplicate a linked list of tokens.
985 */
986static Token *dup_tlist(const Token *list, Token ***tailp)
987{
988 Token *newlist = NULL;
989 Token **tailpp = &newlist;
990 const Token *t;
991
992 list_for_each(t, list) {
993 Token *nt;
994 *tailpp = nt = dup_Token(NULL, t);
995 tailpp = &nt->next;
996 }
997
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -0700998 if (tailp) {
999 **tailp = newlist;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07001000 *tailp = tailpp;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001001 }
1002
1003 return newlist;
1004}
1005
1006/*
1007 * Duplicate a linked list of tokens with a maximum count
1008 */
1009static Token *dup_tlistn(const Token *list, size_t cnt, Token ***tailp)
1010{
1011 Token *newlist = NULL;
1012 Token **tailpp = &newlist;
1013 const Token *t;
1014
1015 list_for_each(t, list) {
1016 Token *nt;
1017 if (!cnt--)
1018 break;
1019 *tailpp = nt = dup_Token(NULL, t);
1020 tailpp = &nt->next;
1021 }
1022
1023 if (tailp) {
1024 **tailp = newlist;
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07001025 if (newlist)
1026 *tailp = tailpp;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001027 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07001028
1029 return newlist;
1030}
1031
1032/*
1033 * Duplicate a linked list of tokens in reverse order
1034 */
1035static Token *dup_tlist_reverse(const Token *list, Token *tail)
1036{
1037 const Token *t;
1038
1039 list_for_each(t, list)
1040 tail = dup_Token(tail, t);
1041
1042 return tail;
1043}
1044
1045/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001046 * Free an MMacro
H. Peter Anvineba20a72002-04-30 20:53:55 +00001047 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001048static void free_mmacro(MMacro * m)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001049{
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001050 nasm_free(m->name);
1051 free_tlist(m->dlist);
1052 nasm_free(m->defaults);
1053 free_llist(m->expansion);
1054 nasm_free(m);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001055}
1056
1057/*
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001058 * Clear or free an SMacro
H. Peter Anvin8b262472019-02-26 14:00:54 -08001059 */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001060static void free_smacro_members(SMacro *s)
H. Peter Anvin8b262472019-02-26 14:00:54 -08001061{
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07001062 if (s->params) {
1063 int i;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001064 for (i = 0; i < s->nparam; i++) {
1065 if (s->params[i].name.len > INLINE_TEXT)
1066 nasm_free(s->params[i].name.text.p.ptr);
1067 }
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07001068 nasm_free(s->params);
1069 }
H. Peter Anvin8b262472019-02-26 14:00:54 -08001070 nasm_free(s->name);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001071 free_tlist(s->expansion);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001072}
1073
1074static void clear_smacro(SMacro *s)
1075{
1076 free_smacro_members(s);
1077 /* Wipe everything except the next pointer */
1078 memset(&s->next + 1, 0, sizeof *s - sizeof s->next);
1079}
1080
1081/*
1082 * Free an SMacro
1083 */
1084static void free_smacro(SMacro *s)
1085{
1086 free_smacro_members(s);
1087 nasm_free(s);
H. Peter Anvin8b262472019-02-26 14:00:54 -08001088}
1089
1090/*
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001091 * Free all currently defined macros, and free the hash tables if empty
H. Peter Anvin97a23472007-09-16 17:57:25 -07001092 */
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001093enum clear_what {
1094 CLEAR_NONE = 0,
1095 CLEAR_DEFINE = 1, /* Clear smacros */
1096 CLEAR_DEFALIAS = 2, /* Clear smacro aliases */
1097 CLEAR_ALLDEFINE = CLEAR_DEFINE|CLEAR_DEFALIAS,
1098 CLEAR_MMACRO = 4,
1099 CLEAR_ALL = CLEAR_ALLDEFINE|CLEAR_MMACRO
1100};
1101
1102static void clear_smacro_table(struct hash_table *smt, enum clear_what what)
H. Peter Anvin97a23472007-09-16 17:57:25 -07001103{
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001104 struct hash_iterator it;
1105 const struct hash_node *np;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001106 bool empty = true;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001107
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001108 /*
1109 * Walk the hash table and clear out anything we don't want
1110 */
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001111 hash_for_each(smt, it, np) {
1112 SMacro *tmp;
1113 SMacro *s = np->data;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001114 SMacro **head = (SMacro **)&np->data;
1115
1116 list_for_each_safe(s, tmp, s) {
1117 if (what & ((enum clear_what)s->alias + 1)) {
1118 *head = s->next;
1119 free_smacro(s);
1120 } else {
1121 empty = false;
1122 }
1123 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07001124 }
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07001125
1126 /*
1127 * Free the hash table and keys if and only if it is now empty.
1128 * Note: we cannot free keys even for an empty list above, as that
1129 * mucks up the hash algorithm.
1130 */
1131 if (empty)
1132 hash_free_all(smt, true);
1133}
1134
1135static void free_smacro_table(struct hash_table *smt)
1136{
1137 clear_smacro_table(smt, CLEAR_ALLDEFINE);
H. Peter Anvin072771e2008-05-22 13:17:51 -07001138}
1139
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001140static void free_mmacro_table(struct hash_table *mmt)
H. Peter Anvin072771e2008-05-22 13:17:51 -07001141{
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001142 struct hash_iterator it;
1143 const struct hash_node *np;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001144
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001145 hash_for_each(mmt, it, np) {
1146 MMacro *tmp;
1147 MMacro *m = np->data;
1148 nasm_free((void *)np->key);
1149 list_for_each_safe(m, tmp, m)
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001150 free_mmacro(m);
H. Peter Anvin97a23472007-09-16 17:57:25 -07001151 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001152 hash_free(mmt);
H. Peter Anvin072771e2008-05-22 13:17:51 -07001153}
1154
1155static void free_macros(void)
1156{
H. Peter Anvin166c2472008-05-28 12:28:58 -07001157 free_smacro_table(&smacros);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001158 free_mmacro_table(&mmacros);
H. Peter Anvin97a23472007-09-16 17:57:25 -07001159}
1160
1161/*
1162 * Initialize the hash tables
1163 */
1164static void init_macros(void)
1165{
H. Peter Anvin97a23472007-09-16 17:57:25 -07001166}
1167
1168/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001169 * Pop the context stack.
1170 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001171static void ctx_pop(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001172{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001173 Context *c = cstk;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001174
1175 cstk = cstk->next;
H. Peter Anvin166c2472008-05-28 12:28:58 -07001176 free_smacro_table(&c->localmac);
H. Peter Anvin8571f062019-09-23 16:40:03 -07001177 nasm_free((char *)c->name);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001178 nasm_free(c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001179}
1180
H. Peter Anvin072771e2008-05-22 13:17:51 -07001181/*
1182 * Search for a key in the hash index; adding it if necessary
1183 * (in which case we initialize the data pointer to NULL.)
1184 */
1185static void **
1186hash_findi_add(struct hash_table *hash, const char *str)
1187{
1188 struct hash_insert hi;
1189 void **r;
1190 char *strx;
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001191 size_t l = strlen(str) + 1;
H. Peter Anvin072771e2008-05-22 13:17:51 -07001192
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001193 r = hash_findib(hash, str, l, &hi);
H. Peter Anvin072771e2008-05-22 13:17:51 -07001194 if (r)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001195 return r;
H. Peter Anvin072771e2008-05-22 13:17:51 -07001196
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08001197 strx = nasm_malloc(l); /* Use a more efficient allocator here? */
1198 memcpy(strx, str, l);
H. Peter Anvin072771e2008-05-22 13:17:51 -07001199 return hash_add(&hi, strx, NULL);
1200}
1201
1202/*
1203 * Like hash_findi, but returns the data element rather than a pointer
1204 * to it. Used only when not adding a new element, hence no third
1205 * argument.
1206 */
1207static void *
1208hash_findix(struct hash_table *hash, const char *str)
1209{
1210 void **p;
1211
1212 p = hash_findi(hash, str, NULL);
1213 return p ? *p : NULL;
1214}
1215
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001216/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001217 * read line from standart macros set,
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001218 * if there no more left -- return NULL
1219 */
1220static char *line_from_stdmac(void)
1221{
1222 unsigned char c;
1223 const unsigned char *p = stdmacpos;
1224 char *line, *q;
1225 size_t len = 0;
1226
1227 if (!stdmacpos)
1228 return NULL;
1229
H. Peter Anvin (Intel)6d5c77c2019-08-15 02:29:40 -07001230 /*
1231 * 32-126 is ASCII, 127 is end of line, 128-31 are directives
1232 * (allowed to wrap around) corresponding to PP_* tokens 0-159.
1233 */
1234 while ((c = *p++) != 127) {
1235 uint8_t ndir = c - 128;
1236 if (ndir < 256-96)
1237 len += pp_directives_len[ndir] + 1;
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001238 else
1239 len++;
1240 }
1241
1242 line = nasm_malloc(len + 1);
1243 q = line;
H. Peter Anvin (Intel)6d5c77c2019-08-15 02:29:40 -07001244
1245 while ((c = *stdmacpos++) != 127) {
1246 uint8_t ndir = c - 128;
1247 if (ndir < 256-96) {
1248 memcpy(q, pp_directives[ndir], pp_directives_len[ndir]);
1249 q += pp_directives_len[ndir];
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001250 *q++ = ' ';
1251 } else {
1252 *q++ = c;
1253 }
1254 }
1255 stdmacpos = p;
1256 *q = '\0';
1257
H. Peter Anvin (Intel)6d5c77c2019-08-15 02:29:40 -07001258 if (*stdmacpos == 127) {
H. Peter Anvinf7606612016-07-13 14:23:48 -07001259 /* This was the last of this particular macro set */
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001260 stdmacpos = NULL;
H. Peter Anvinf7606612016-07-13 14:23:48 -07001261 if (*stdmacnext) {
1262 stdmacpos = *stdmacnext++;
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001263 } else if (do_predef) {
1264 Line *pd, *l;
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001265
1266 /*
1267 * Nasty hack: here we push the contents of
1268 * `predef' on to the top-level expansion stack,
1269 * since this is the most convenient way to
1270 * implement the pre-include and pre-define
1271 * features.
1272 */
1273 list_for_each(pd, predef) {
H. Peter Anvin6686de22019-08-10 05:33:14 -07001274 nasm_new(l);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001275 l->next = istk->expansion;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07001276 l->first = dup_tlist(pd->first, NULL);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001277 l->finishes = NULL;
1278
1279 istk->expansion = l;
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +04001280 }
1281 do_predef = false;
1282 }
1283 }
1284
1285 return line;
1286}
1287
H. Peter Anvin6686de22019-08-10 05:33:14 -07001288/*
1289 * Read a line from a file. Return NULL on end of file.
1290 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001291static char *line_from_file(FILE *f)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001292{
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001293 int c;
1294 unsigned int size, next;
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001295 const unsigned int delta = 512;
1296 const unsigned int pad = 8;
1297 unsigned int nr_cont = 0;
1298 bool cont = false;
1299 char *buffer, *p;
H. Peter Anvinab6f8312019-08-09 22:31:45 -07001300 int32_t lineno;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001301
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001302 size = delta;
1303 p = buffer = nasm_malloc(size);
1304
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001305 do {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001306 c = fgetc(f);
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001307
1308 switch (c) {
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001309 case EOF:
1310 if (p == buffer) {
1311 nasm_free(buffer);
1312 return NULL;
1313 }
1314 c = 0;
1315 break;
1316
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001317 case '\r':
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001318 next = fgetc(f);
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001319 if (next != '\n')
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001320 ungetc(next, f);
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001321 if (cont) {
1322 cont = false;
1323 continue;
1324 }
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001325 c = 0;
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001326 break;
1327
1328 case '\n':
1329 if (cont) {
1330 cont = false;
1331 continue;
1332 }
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001333 c = 0;
1334 break;
1335
1336 case 032: /* ^Z = legacy MS-DOS end of file mark */
1337 c = 0;
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001338 break;
1339
1340 case '\\':
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001341 next = fgetc(f);
1342 ungetc(next, f);
Cyrill Gorcunov490f85e2012-12-27 20:02:17 +04001343 if (next == '\r' || next == '\n') {
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001344 cont = true;
1345 nr_cont++;
1346 continue;
1347 }
1348 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001349 }
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001350
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +04001351 if (p >= (buffer + size - pad)) {
1352 buffer = nasm_realloc(buffer, size + delta);
1353 p = buffer + size - pad;
1354 size += delta;
1355 }
1356
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07001357 *p++ = c;
1358 } while (c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001359
H. Peter Anvinab6f8312019-08-09 22:31:45 -07001360 lineno = src_get_linnum() + istk->lineinc +
1361 (nr_cont * istk->lineinc);
1362 src_set_linnum(lineno);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001363
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001364 return buffer;
1365}
1366
1367/*
H. Peter Anvin6686de22019-08-10 05:33:14 -07001368 * Common read routine regardless of source
1369 */
1370static char *read_line(void)
1371{
1372 char *line;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001373 FILE *f = istk->fp;
H. Peter Anvin6686de22019-08-10 05:33:14 -07001374
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07001375 if (f)
1376 line = line_from_file(f);
H. Peter Anvin6686de22019-08-10 05:33:14 -07001377 else
1378 line = line_from_stdmac();
1379
1380 if (!line)
1381 return NULL;
1382
1383 if (!istk->nolist)
1384 lfmt->line(LIST_READ, src_get_linnum(), line);
1385
1386 return line;
1387}
1388
1389/*
Keith Kaniosb7a89542007-04-12 02:40:54 +00001390 * Tokenize a line of text. This is a very simple process since we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001391 * don't need to parse the value out of e.g. numeric tokens: we
1392 * simply split one string into many.
1393 */
H. Peter Anvin8571f062019-09-23 16:40:03 -07001394static Token *tokenize(const char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001395{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001396 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001397 Token *list = NULL;
1398 Token *t, **tail = &list;
1399
H. Peter Anvine2c80182005-01-15 22:15:51 +00001400 while (*line) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001401 const char *p = line;
1402 const char *ep = NULL; /* End of token, for trimming the end */
1403 size_t toklen;
1404 char firstchar = *p; /* Can be used to override the first char */
H. Peter Anvin (Intel)98031bf2019-08-09 16:11:28 -07001405
H. Peter Anvine2c80182005-01-15 22:15:51 +00001406 if (*p == '%') {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001407 /*
1408 * Preprocessor construct; find the end of the token.
1409 * Classification is handled later, because %{...} can be
1410 * used to create any preprocessor token.
1411 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001412 p++;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001413 if (*p == '+' && !nasm_isdigit(p[1])) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001414 /* Paste token */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001415 p++;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001416 } else if (nasm_isdigit(*p) ||
1417 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001418 do {
1419 p++;
1420 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001421 while (nasm_isdigit(*p));
H. Peter Anvin8571f062019-09-23 16:40:03 -07001422 } else if (*p == '{' || *p == '[') {
1423 /* %{...} or %[...] */
1424 char firstchar = *p;
1425 char endchar = *p + 2; /* } or ] */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001426 int lvl = 1;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001427 line += (*p++ == '{'); /* Skip { but not [ (yet) */
1428 while (lvl) {
1429 if (*p == firstchar) {
1430 lvl++;
1431 } else if (*p == endchar) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001432 lvl--;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001433 } else if (nasm_isquote(*p)) {
1434 p = nasm_skip_string(p);
1435 }
1436
1437 /*
1438 * *p can have been advanced to a null character by
1439 * nasm_skip_string()
1440 */
1441 if (!*p) {
1442 nasm_warn(WARN_OTHER, "unterminated %%%c construct",
1443 firstchar);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001444 break;
1445 }
H. Peter Anvin (Intel)98031bf2019-08-09 16:11:28 -07001446 p++;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001447 }
1448 ep = lvl ? p : p-1; /* Terminal character not part of token */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001449 } else if (*p == '?') {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001450 /* %? or %?? */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001451 p++;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001452 if (*p == '?')
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001453 p++;
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001454 } else if (*p == '!') {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001455 /* Environment variable reference */
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001456 p++;
H. Peter Anvin13506202018-11-28 14:55:58 -08001457 if (nasm_isidchar(*p)) {
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001458 do {
1459 p++;
1460 }
H. Peter Anvin13506202018-11-28 14:55:58 -08001461 while (nasm_isidchar(*p));
H. Peter Anvin53e2e4c2018-11-28 15:01:40 -08001462 } else if (nasm_isquote(*p)) {
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001463 p = nasm_skip_string(p);
1464 if (*p)
1465 p++;
1466 else
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03001467 nasm_nonfatalf(ERR_PASS1, "unterminated %%! string");
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001468 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001469 /* %! without anything else... */
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001470 }
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07001471 } else if (*p == ',') {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001472 /* Conditional comma */
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07001473 p++;
H. Peter Anvin13506202018-11-28 14:55:58 -08001474 } else if (nasm_isidchar(*p) ||
H. Peter Anvin8571f062019-09-23 16:40:03 -07001475 ((*p == '%' || *p == '$') && nasm_isidchar(p[1]))) {
1476 /* Identifier or some sort */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001477 do {
1478 p++;
1479 }
H. Peter Anvin13506202018-11-28 14:55:58 -08001480 while (nasm_isidchar(*p));
H. Peter Anvin8571f062019-09-23 16:40:03 -07001481 } else if (*p == '%') {
1482 /* %% operator */
1483 p++;
1484 }
1485
1486 if (!ep)
1487 ep = p;
1488 toklen = ep - line;
1489
1490 /* Classify here, to handle %{...} correctly */
1491 if (toklen < 2) {
1492 type = TOK_OTHER; /* % operator */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001493 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001494 char c0 = line[1];
1495
1496 switch (c0) {
1497 case '+':
1498 type = (toklen == 2) ? TOK_PASTE : TOK_MMACRO_PARAM;
1499 break;
1500
1501 case '-':
1502 type = TOK_MMACRO_PARAM;
1503 break;
1504
1505 case '?':
1506 if (toklen == 2)
1507 type = TOK_PREPROC_Q;
1508 else if (toklen == 3 && line[2] == '?')
1509 type = TOK_PREPROC_QQ;
1510 else
1511 type = TOK_PREPROC_ID;
1512 break;
1513
1514 case '!':
1515 type = (toklen == 2) ? TOK_OTHER : TOK_ENVIRON;
1516 break;
1517
1518 case '%':
1519 type = (toklen == 2) ? TOK_OTHER : TOK_LOCAL_SYMBOL;
1520 break;
1521
1522 case '$':
1523 type = (toklen == 2) ? TOK_OTHER : TOK_LOCAL_MACRO;
1524 break;
1525
1526 case '[':
1527 line += 2; /* Skip %[ */
1528 firstchar = *line; /* Don't clobber */
1529 toklen -= 2;
1530 type = TOK_INDIRECT;
1531 break;
1532
1533 case ',':
1534 type = (toklen == 2) ? TOK_COND_COMMA : TOK_PREPROC_ID;
1535 break;
1536
1537 case '\'':
1538 case '\"':
1539 case '`':
1540 /* %{'string'} */
1541 type = TOK_PREPROC_ID;
1542 break;
1543
1544 case ':':
1545 type = TOK_MMACRO_PARAM; /* %{:..} */
1546 break;
1547
1548 default:
1549 if (nasm_isdigit(c0))
1550 type = TOK_MMACRO_PARAM;
1551 else if (nasm_isidchar(c0) || toklen > 2)
1552 type = TOK_PREPROC_ID;
1553 else
1554 type = TOK_OTHER;
1555 break;
1556 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001557 }
H. Peter Anvin13506202018-11-28 14:55:58 -08001558 } else if (nasm_isidstart(*p) || (*p == '$' && nasm_isidstart(p[1]))) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001559 /*
1560 * An identifier. This includes the ? operator, which is
1561 * treated as a keyword, not as a special character
1562 * operator
1563 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001564 type = TOK_ID;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001565 while (nasm_isidchar(*++p))
1566 ;
1567 } else if (nasm_isquote(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001568 /*
1569 * A string token.
1570 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001571 type = TOK_STRING;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001572 p = nasm_skip_string(p);
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001573
H. Peter Anvine2c80182005-01-15 22:15:51 +00001574 if (*p) {
1575 p++;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001576 } else {
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08001577 nasm_warn(WARN_OTHER, "unterminated string");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001578 /* Handling unterminated strings by UNV */
1579 /* type = -1; */
1580 }
Victor van den Elzenfb5f2512009-04-17 16:17:59 +02001581 } else if (p[0] == '$' && p[1] == '$') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001582 type = TOK_OTHER; /* TOKEN_BASE */
Victor van den Elzenfb5f2512009-04-17 16:17:59 +02001583 p += 2;
H. Peter Anvin13506202018-11-28 14:55:58 -08001584 } else if (nasm_isnumstart(*p)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001585 bool is_hex = false;
1586 bool is_float = false;
1587 bool has_e = false;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001588 char c;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001589
H. Peter Anvine2c80182005-01-15 22:15:51 +00001590 /*
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001591 * A numeric token.
H. Peter Anvine2c80182005-01-15 22:15:51 +00001592 */
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001593
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001594 if (*p == '$') {
1595 p++;
1596 is_hex = true;
1597 }
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001598
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001599 for (;;) {
1600 c = *p++;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001601
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001602 if (!is_hex && (c == 'e' || c == 'E')) {
1603 has_e = true;
1604 if (*p == '+' || *p == '-') {
1605 /*
1606 * e can only be followed by +/- if it is either a
1607 * prefixed hex number or a floating-point number
1608 */
1609 p++;
1610 is_float = true;
1611 }
1612 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
1613 is_hex = true;
1614 } else if (c == 'P' || c == 'p') {
1615 is_float = true;
1616 if (*p == '+' || *p == '-')
1617 p++;
H. Peter Anvin13506202018-11-28 14:55:58 -08001618 } else if (nasm_isnumchar(c))
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001619 ; /* just advance */
1620 else if (c == '.') {
1621 /*
1622 * we need to deal with consequences of the legacy
1623 * parser, like "1.nolist" being two tokens
1624 * (TOK_NUMBER, TOK_ID) here; at least give it
1625 * a shot for now. In the future, we probably need
1626 * a flex-based scanner with proper pattern matching
1627 * to do it as well as it can be done. Nothing in
1628 * the world is going to help the person who wants
1629 * 0x123.p16 interpreted as two tokens, though.
1630 */
H. Peter Anvin8571f062019-09-23 16:40:03 -07001631 const char *r = p;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001632 while (*r == '_')
1633 r++;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001634
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001635 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
1636 (!is_hex && (*r == 'e' || *r == 'E')) ||
1637 (*r == 'p' || *r == 'P')) {
1638 p = r;
1639 is_float = true;
1640 } else
1641 break; /* Terminate the token */
1642 } else
1643 break;
1644 }
1645 p--; /* Point to first character beyond number */
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001646
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001647 if (p == line+1 && *line == '$') {
1648 type = TOK_OTHER; /* TOKEN_HERE */
1649 } else {
1650 if (has_e && !is_hex) {
1651 /* 1e13 is floating-point, but 1e13h is not */
1652 is_float = true;
1653 }
H. Peter Anvind784a082009-04-20 14:01:18 -07001654
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001655 type = is_float ? TOK_FLOAT : TOK_NUMBER;
1656 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001657 } else if (nasm_isspace(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001658 type = TOK_WHITESPACE;
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +04001659 p = nasm_skip_spaces(p);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001660 /*
1661 * Whitespace just before end-of-line is discarded by
1662 * pretending it's a comment; whitespace just before a
1663 * comment gets lumped into the comment.
1664 */
1665 if (!*p || *p == ';') {
1666 type = TOK_COMMENT;
1667 while (*p)
1668 p++;
1669 }
1670 } else if (*p == ';') {
1671 type = TOK_COMMENT;
1672 while (*p)
1673 p++;
1674 } else {
1675 /*
1676 * Anything else is an operator of some kind. We check
1677 * for all the double-character operators (>>, <<, //,
H. Peter Anvin8571f062019-09-23 16:40:03 -07001678 * %%, <=, >=, ==, !=, <>, &&, ||, ^^) and the triple-
1679 * character operators (<<<, >>>, <=>) but anything
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001680 * else is a single-character operator.
H. Peter Anvine2c80182005-01-15 22:15:51 +00001681 */
1682 type = TOK_OTHER;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001683 switch (*p++) {
1684 case '>':
1685 if (*p == '>') {
1686 p++;
1687 if (*p == '>')
1688 p++;
H. Peter Anvind03a6c82019-10-07 21:29:05 -07001689 } else if (*p == '=') {
1690 p++;
1691 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07001692 break;
1693
1694 case '<':
1695 if (*p == '<') {
1696 p++;
1697 if (*p == '<')
1698 p++;
1699 } else if (*p == '=') {
1700 p++;
1701 if (*p == '>')
1702 p++;
1703 } else if (*p == '>') {
1704 p++;
1705 }
1706 break;
1707
1708 case '!':
1709 if (*p == '=')
1710 p++;
1711 break;
1712
1713 case '/':
1714 case '=':
1715 case '&':
1716 case '|':
1717 case '^':
1718 /* These operators can be doubled but nothing else */
1719 if (*p == p[-1])
1720 p++;
1721 break;
1722
1723 default:
1724 break;
1725 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001726 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001727
H. Peter Anvin8571f062019-09-23 16:40:03 -07001728 if (type == TOK_WHITESPACE) {
1729 *tail = t = new_White(NULL);
1730 tail = &t->next;
1731 } else if (type != TOK_COMMENT) {
H. Peter Anvin (Intel)98031bf2019-08-09 16:11:28 -07001732 if (!ep)
1733 ep = p;
1734 *tail = t = new_Token(NULL, type, line, ep - line);
H. Peter Anvin8571f062019-09-23 16:40:03 -07001735 *tok_text_buf(t) = firstchar; /* E.g. %{foo} -> {foo -> %foo */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001736 tail = &t->next;
1737 }
1738 line = p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001739 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001740 return list;
1741}
1742
H. Peter Anvin8571f062019-09-23 16:40:03 -07001743/*
1744 * Tokens are allocated in blocks to improve speed. Set the blocksize
1745 * to 0 to use regular nasm_malloc(); this is useful for debugging.
1746 *
1747 * alloc_Token() returns a zero-initialized token structure.
1748 */
1749#define TOKEN_BLOCKSIZE 4096
1750
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001751#if TOKEN_BLOCKSIZE
H. Peter Anvin8571f062019-09-23 16:40:03 -07001752
1753static Token *freeTokens = NULL;
1754static Token *tokenblocks = NULL;
1755
1756static Token *alloc_Token(void)
H. Peter Anvince616072002-04-30 21:02:23 +00001757{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001758 Token *t = freeTokens;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001759
H. Peter Anvin8571f062019-09-23 16:40:03 -07001760 if (unlikely(!t)) {
1761 Token *block;
1762 size_t i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001763
H. Peter Anvin8571f062019-09-23 16:40:03 -07001764 nasm_newn(block, TOKEN_BLOCKSIZE);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001765
H. Peter Anvin8571f062019-09-23 16:40:03 -07001766 /*
1767 * The first entry in each array are a linked list of
1768 * block allocations and is not used for data.
1769 */
1770 block[0].next = tokenblocks;
1771 block[0].type = TOK_BLOCK;
1772 tokenblocks = block;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001773
H. Peter Anvin8571f062019-09-23 16:40:03 -07001774 /*
1775 * Add the rest to the free list
1776 */
1777 for (i = 2; i < TOKEN_BLOCKSIZE - 1; i++)
1778 block[i].next = &block[i+1];
1779
1780 freeTokens = &block[2];
1781
1782 /*
1783 * Return the topmost usable token
1784 */
1785 return &block[1];
1786 }
1787
1788 freeTokens = t->next;
1789 t->next = NULL;
1790 return t;
H. Peter Anvince616072002-04-30 21:02:23 +00001791}
1792
H. Peter Anvin8571f062019-09-23 16:40:03 -07001793static Token *delete_Token(Token *t)
1794{
1795 Token *next = t->next;
1796
1797 nasm_zero(*t);
1798 t->next = freeTokens;
1799 freeTokens = t;
1800
1801 return next;
1802}
1803
H. Peter Anvine2c80182005-01-15 22:15:51 +00001804static void delete_Blocks(void)
H. Peter Anvince616072002-04-30 21:02:23 +00001805{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001806 Token *block, *blocktmp;
H. Peter Anvince616072002-04-30 21:02:23 +00001807
H. Peter Anvin8571f062019-09-23 16:40:03 -07001808 list_for_each_safe(block, blocktmp, tokenblocks)
1809 nasm_free(block);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001810
H. Peter Anvin8571f062019-09-23 16:40:03 -07001811 freeTokens = tokenblocks = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001812}
H. Peter Anvin734b1882002-04-30 21:01:08 +00001813
H. Peter Anvin8571f062019-09-23 16:40:03 -07001814#else
1815
1816static inline Token *alloc_Token(void)
1817{
1818 Token *t;
1819 nasm_new(*t);
1820 return t;
1821}
1822
1823static Token *delete_Token(Token *t)
1824{
1825 Token *next = t->next;
1826 nasm_free(t);
1827 return next;
1828}
1829
1830static inline void delete_Blocks(void)
1831{
1832 /* Nothing to do */
1833}
1834
1835#endif
1836
H. Peter Anvin734b1882002-04-30 21:01:08 +00001837/*
H. Peter Anvin70653092007-10-19 14:42:29 -07001838 * this function creates a new Token and passes a pointer to it
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001839 * back to the caller. It sets the type, text, and next pointer elements.
H. Peter Anvin734b1882002-04-30 21:01:08 +00001840 */
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001841static Token *new_Token(Token * next, enum pp_token_type type,
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001842 const char *text, size_t txtlen)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001843{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001844 Token *t = alloc_Token();
1845 char *textp;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001846
H. Peter Anvin734b1882002-04-30 21:01:08 +00001847 t->next = next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001848 t->type = type;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001849 if (type == TOK_WHITESPACE) {
1850 t->len = 1;
1851 t->text.a[0] = ' ';
H. Peter Anvine2c80182005-01-15 22:15:51 +00001852 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001853 if (text && text[0] && !txtlen)
1854 txtlen = tok_strlen(text);
1855
1856 t->len = tok_check_len(txtlen);
1857
1858 if (text) {
1859 textp = (txtlen > INLINE_TEXT)
1860 ? (t->text.p.ptr = nasm_malloc(txtlen+1)) : t->text.a;
1861 memcpy(textp, text, txtlen);
1862 textp[txtlen] = '\0'; /* In case we needed malloc() */
1863 } else {
1864 /*
1865 * Allocate a buffer but do not fill it. The caller
1866 * can fill in text, but must not change the length.
1867 * The filled in text must be exactly txtlen once
1868 * the buffer is filled and before the token is added
1869 * to any line lists.
1870 */
1871 if (txtlen > INLINE_TEXT)
1872 t->text.p.ptr = nasm_zalloc(txtlen+1);
1873 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001874 }
1875 return t;
1876}
1877
H. Peter Anvin8571f062019-09-23 16:40:03 -07001878/*
1879 * Same as new_Token(), but text belongs to the new token and is
1880 * either taken over or freed. This function MUST be called
1881 * with valid txt and txtlen, unlike new_Token().
1882 */
1883static Token *new_Token_free(Token * next, enum pp_token_type type,
1884 char *text, size_t txtlen)
1885{
1886 Token *t = alloc_Token();
1887
1888 t->next = next;
1889 t->type = type;
1890 t->len = tok_check_len(txtlen);
1891
1892 if (txtlen <= INLINE_TEXT) {
1893 memcpy(t->text.a, text, txtlen);
1894 free(text);
1895 } else {
1896 t->text.p.ptr = text;
1897 }
1898
1899 return t;
1900}
1901
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001902static Token *dup_Token(Token *next, const Token *src)
1903{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001904 Token *t = alloc_Token();
1905
1906 memcpy(t, src, sizeof *src);
1907 t->next = next;
1908
1909 if (t->len > INLINE_TEXT) {
1910 t->text.p.ptr = nasm_malloc(t->len + 1);
1911 memcpy(t->text.p.ptr, src->text.p.ptr, t->len+1);
1912 }
1913
1914 return t;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07001915}
1916
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001917static Token *new_White(Token *next)
1918{
H. Peter Anvin8571f062019-09-23 16:40:03 -07001919 Token *t = alloc_Token();
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001920
H. Peter Anvin8571f062019-09-23 16:40:03 -07001921 t->next = next;
1922 t->type = TOK_WHITESPACE;
1923 t->len = 1;
1924 t->text.a[0] = ' ';
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07001925
H. Peter Anvin8571f062019-09-23 16:40:03 -07001926 return t;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001927}
1928
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001929/*
H. Peter Anvin8571f062019-09-23 16:40:03 -07001930 * This *transfers* the content from one token to another, leaving the
1931 * next pointer of the latter intact. Unlike dup_Token(), the old
1932 * token is destroyed, except for its next pointer, and the text
1933 * pointer allocation, if any, is simply transferred.
1934 */
1935static Token *steal_Token(Token *dst, Token *src)
1936{
1937 /* Overwrite everything except the next pointers */
1938 memcpy((char *)dst + sizeof(Token *), (char *)src + sizeof(Token *),
1939 sizeof(Token) - sizeof(Token *));
1940
1941 /* Clear the donor token */
1942 memset((char *)src + sizeof(Token *), 0, sizeof(Token) - sizeof(Token *));
1943
1944 return dst;
1945}
1946
1947/*
1948 * Convert a line of tokens back into text. This modifies the list
1949 * by expanding environment variables.
1950 *
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001951 * If expand_locals is not zero, identifiers of the form "%$*xxx"
H. Peter Anvin8571f062019-09-23 16:40:03 -07001952 * are also transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001953 */
H. Peter Anvin9e200162008-06-04 17:23:14 -07001954static char *detoken(Token * tlist, bool expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001955{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001956 Token *t;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001957 char *line, *p;
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001958 int len = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001959
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001960 list_for_each(t, tlist) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07001961 switch (t->type) {
1962 case TOK_ENVIRON:
1963 {
1964 const char *v = pp_getenv(t, true);
1965 set_text(t, v, tok_strlen(v));
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07001966 t->type = TOK_NAKED_STRING;
H. Peter Anvin8571f062019-09-23 16:40:03 -07001967 break;
1968 }
H. Peter Anvin077fb932010-07-20 14:56:30 -07001969
H. Peter Anvin8571f062019-09-23 16:40:03 -07001970 case TOK_LOCAL_MACRO:
1971 case TOK_LOCAL_SYMBOL:
1972 if (expand_locals) {
1973 const char *q;
1974 char *p;
1975 Context *ctx = get_ctx(tok_text(t), &q);
1976 if (ctx) {
1977 p = nasm_asprintf("..@%"PRIu64".%s", ctx->number, q);
1978 set_text_free(t, p, nasm_last_string_len());
1979 t->type = TOK_ID;
1980 }
1981 }
1982 break;
H. Peter Anvin077fb932010-07-20 14:56:30 -07001983
H. Peter Anvin8571f062019-09-23 16:40:03 -07001984 default:
1985 break; /* No modifications */
1986 }
1987
1988 if (debug_level(2)) {
1989 unsigned int t_len = t->len;
1990 unsigned int s_len = tok_strlen(tok_text(t));
1991 if (t_len != s_len) {
1992 nasm_panic("assertion failed: token \"%s\" type %u len %u has t->len %u\n",
1993 tok_text(t), t->type, s_len, t_len);
1994 t->len = s_len;
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001995 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001996 }
H. Peter Anvin077fb932010-07-20 14:56:30 -07001997
H. Peter Anvin8571f062019-09-23 16:40:03 -07001998 len += t->len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001999 }
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04002000
H. Peter Anvin734b1882002-04-30 21:01:08 +00002001 p = line = nasm_malloc(len + 1);
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04002002
H. Peter Anvin8571f062019-09-23 16:40:03 -07002003 list_for_each(t, tlist)
2004 p = mempcpy(p, tok_text(t), t->len);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002005 *p = '\0';
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04002006
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002007 return line;
2008}
2009
2010/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002011 * A scanner, suitable for use by the expression evaluator, which
2012 * operates on a line of Tokens. Expects a pointer to a pointer to
2013 * the first token in the line to be passed in as its private_data
2014 * field.
H. Peter Anvinc2df2822007-10-24 15:29:28 -07002015 *
2016 * FIX: This really needs to be unified with stdscan.
H. Peter Anvin76690a12002-04-30 20:52:49 +00002017 */
H. Peter Anvin8b262472019-02-26 14:00:54 -08002018struct ppscan {
2019 Token *tptr;
2020 int ntokens;
2021};
2022
H. Peter Anvine2c80182005-01-15 22:15:51 +00002023static int ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002024{
H. Peter Anvin8b262472019-02-26 14:00:54 -08002025 struct ppscan *pps = private_data;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002026 Token *tline;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002027 const char *txt;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002028
H. Peter Anvine2c80182005-01-15 22:15:51 +00002029 do {
H. Peter Anvin8b262472019-02-26 14:00:54 -08002030 if (pps->ntokens && (tline = pps->tptr)) {
2031 pps->ntokens--;
2032 pps->tptr = tline->next;
2033 } else {
2034 pps->tptr = NULL;
2035 pps->ntokens = 0;
2036 return tokval->t_type = TOKEN_EOS;
2037 }
2038 } while (tline->type == TOK_WHITESPACE || tline->type == TOK_COMMENT);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002039
H. Peter Anvin8571f062019-09-23 16:40:03 -07002040 txt = tok_text(tline);
2041 tokval->t_charptr = (char *)txt; /* Fix this */
H. Peter Anvinc2df2822007-10-24 15:29:28 -07002042
H. Peter Anvin8571f062019-09-23 16:40:03 -07002043 if (txt[0] == '$') {
2044 if (!txt[1]) {
2045 return tokval->t_type = TOKEN_HERE;
2046 } else if (txt[1] == '$' && !txt[2]) {
2047 return tokval->t_type = TOKEN_BASE;
2048 } else if (tline->type == TOK_ID) {
2049 tokval->t_charptr++;
2050 return tokval->t_type = TOKEN_ID;
2051 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002052 }
2053
H. Peter Anvin8571f062019-09-23 16:40:03 -07002054 switch (tline->type) {
2055 default:
2056 if (tline->len == 1)
2057 return tokval->t_type = txt[0];
2058 /* fall through */
2059 case TOK_ID:
2060 return nasm_token_hash(txt, tokval);
2061
2062 case TOK_NUMBER:
2063 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002064 bool rn_error;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002065 tokval->t_integer = readnum(txt, &rn_error);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002066 if (rn_error)
2067 return tokval->t_type = TOKEN_ERRNUM;
2068 else
2069 return tokval->t_type = TOKEN_NUM;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07002070 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002071
H. Peter Anvin8571f062019-09-23 16:40:03 -07002072 case TOK_FLOAT:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002073 return tokval->t_type = TOKEN_FLOAT;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002074
2075 case TOK_STRING:
2076 tokval->t_charptr = (char *)unquote_token(tline);
2077 tokval->t_inttwo = tline->len;
2078 return tokval->t_type = TOKEN_STR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002079 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002080}
2081
2082/*
H. Peter Anvind2354082019-08-27 16:38:48 -07002083 * 1. An expression (true if nonzero 0)
2084 * 2. The keywords true, on, yes for true
2085 * 3. The keywords false, off, no for false
2086 * 4. An empty line, for true
2087 *
2088 * On error, return defval (usually the previous value)
2089 */
2090static bool pp_get_boolean_option(Token *tline, bool defval)
2091{
2092 static const char * const noyes[] = {
2093 "no", "yes",
2094 "false", "true",
2095 "off", "on"
2096 };
2097 struct ppscan pps;
2098 struct tokenval tokval;
2099 expr *evalresult;
2100
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002101 tline = skip_white(tline);
2102 if (!tline)
H. Peter Anvind2354082019-08-27 16:38:48 -07002103 return true;
2104
2105 if (tline->type == TOK_ID) {
2106 size_t i;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002107 const char *txt = tok_text(tline);
2108
H. Peter Anvind2354082019-08-27 16:38:48 -07002109 for (i = 0; i < ARRAY_SIZE(noyes); i++)
H. Peter Anvin8571f062019-09-23 16:40:03 -07002110 if (!nasm_stricmp(txt, noyes[i]))
H. Peter Anvind2354082019-08-27 16:38:48 -07002111 return i & 1;
2112 }
2113
2114 pps.tptr = NULL;
2115 pps.tptr = tline;
2116 pps.ntokens = -1;
2117 tokval.t_type = TOKEN_INVALID;
2118 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
2119
2120 if (!evalresult)
2121 return true;
2122
2123 if (tokval.t_type)
2124 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
2125 if (!is_really_simple(evalresult)) {
2126 nasm_nonfatal("boolean flag expression must be a constant");
2127 return defval;
2128 }
2129
2130 return reloc_value(evalresult) != 0;
2131}
2132
2133/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002134 * Compare a string to the name of an existing macro; this is a
2135 * simple wrapper which calls either strcmp or nasm_stricmp
2136 * depending on the value of the `casesense' parameter.
2137 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002138static int mstrcmp(const char *p, const char *q, bool casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002139{
H. Peter Anvin734b1882002-04-30 21:01:08 +00002140 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002141}
2142
2143/*
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07002144 * Compare a string to the name of an existing macro; this is a
2145 * simple wrapper which calls either strcmp or nasm_stricmp
2146 * depending on the value of the `casesense' parameter.
2147 */
2148static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
2149{
2150 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
2151}
2152
2153/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002154 * Return the Context structure associated with a %$ token. Return
2155 * NULL, having _already_ reported an error condition, if the
2156 * context stack isn't deep enough for the supplied number of $
2157 * signs.
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002158 *
2159 * If "namep" is non-NULL, set it to the pointer to the macro name
2160 * tail, i.e. the part beyond %$...
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002161 */
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04002162static Context *get_ctx(const char *name, const char **namep)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002163{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002164 Context *ctx;
2165 int i;
2166
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002167 if (namep)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002168 *namep = name;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002169
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002170 if (!name || name[0] != '%' || name[1] != '$')
H. Peter Anvine2c80182005-01-15 22:15:51 +00002171 return NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002172
H. Peter Anvine2c80182005-01-15 22:15:51 +00002173 if (!cstk) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002174 nasm_nonfatal("`%s': context stack is empty", name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002175 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002176 }
2177
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002178 name += 2;
2179 ctx = cstk;
2180 i = 0;
2181 while (ctx && *name == '$') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002182 name++;
2183 i++;
2184 ctx = ctx->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002185 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002186 if (!ctx) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002187 nasm_nonfatal("`%s': context stack is only"
2188 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
H. Peter Anvine2c80182005-01-15 22:15:51 +00002189 return NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002190 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002191
2192 if (namep)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002193 *namep = name;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002194
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04002195 return ctx;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002196}
2197
2198/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002199 * Open an include file. This routine must always return a valid
2200 * file pointer if it returns - it's responsible for throwing an
2201 * ERR_FATAL and bombing out completely if not. It should also try
2202 * the include path one by one until it finds the file or reaches
2203 * the end of the path.
H. Peter Anvind81a2352016-09-21 14:03:18 -07002204 *
2205 * Note: for INC_PROBE the function returns NULL at all times;
2206 * instead look for the
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002207 */
H. Peter Anvind81a2352016-09-21 14:03:18 -07002208enum incopen_mode {
2209 INC_NEEDED, /* File must exist */
2210 INC_OPTIONAL, /* Missing is OK */
2211 INC_PROBE /* Only an existence probe */
2212};
2213
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002214/* This is conducts a full pathname search */
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002215static FILE *inc_fopen_search(const char *file, char **slpath,
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002216 enum incopen_mode omode, enum file_flags fmode)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002217{
H. Peter Anvin (Intel)64471092018-12-11 13:06:14 -08002218 const struct strlist_entry *ip = strlist_head(ipath_list);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002219 FILE *fp;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002220 const char *prefix = "";
night199ukfdb1a1b2018-10-18 23:19:47 +02002221 char *sp;
H. Peter Anvind81a2352016-09-21 14:03:18 -07002222 bool found;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002223
H. Peter Anvine2c80182005-01-15 22:15:51 +00002224 while (1) {
night199ukfdb1a1b2018-10-18 23:19:47 +02002225 sp = nasm_catfile(prefix, file);
H. Peter Anvind81a2352016-09-21 14:03:18 -07002226 if (omode == INC_PROBE) {
2227 fp = NULL;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002228 found = nasm_file_exists(sp);
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07002229 } else {
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002230 fp = nasm_open_read(sp, fmode);
H. Peter Anvind81a2352016-09-21 14:03:18 -07002231 found = (fp != NULL);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002232 }
H. Peter Anvind81a2352016-09-21 14:03:18 -07002233 if (found) {
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002234 *slpath = sp;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002235 return fp;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002236 }
Jim Kukunas65a8afc2016-06-13 16:00:42 -04002237
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002238 nasm_free(sp);
Jim Kukunas65a8afc2016-06-13 16:00:42 -04002239
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002240 if (!ip) {
2241 *slpath = NULL;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002242 return NULL;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002243 }
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002244
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002245 prefix = ip->str;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002246 ip = ip->next;
2247 }
2248}
2249
2250/*
2251 * Open a file, or test for the presence of one (depending on omode),
2252 * considering the include path.
2253 */
2254static FILE *inc_fopen(const char *file,
Cyrill Gorcunovb7bb5ac2018-11-11 21:33:52 +03002255 struct strlist *dhead,
H. Peter Anvinccad6f92016-10-04 00:34:35 -07002256 const char **found_path,
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002257 enum incopen_mode omode,
2258 enum file_flags fmode)
2259{
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002260 struct hash_insert hi;
2261 void **hp;
2262 char *path;
2263 FILE *fp = NULL;
2264
2265 hp = hash_find(&FileHash, file, &hi);
2266 if (hp) {
2267 path = *hp;
Martin Storsjöf283c8f2017-08-13 17:28:46 +03002268 if (path || omode != INC_NEEDED) {
Cyrill Gorcunovb7bb5ac2018-11-11 21:33:52 +03002269 strlist_add(dhead, path ? path : file);
Martin Storsjöf283c8f2017-08-13 17:28:46 +03002270 }
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002271 } else {
2272 /* Need to do the actual path search */
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002273 fp = inc_fopen_search(file, &path, omode, fmode);
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002274
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002275 /* Positive or negative result */
2276 hash_add(&hi, nasm_strdup(file), path);
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002277
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07002278 /*
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07002279 * Add file to dependency path.
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07002280 */
2281 if (path || omode != INC_NEEDED)
Cyrill Gorcunovb7bb5ac2018-11-11 21:33:52 +03002282 strlist_add(dhead, file);
H. Peter Anvineba20a72002-04-30 20:53:55 +00002283 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002284
H. Peter Anvin (Intel)5d68f982020-06-01 12:32:35 -07002285 if (path && !fp && omode != INC_PROBE)
2286 fp = nasm_open_read(path, fmode);
2287
2288 if (omode == INC_NEEDED && !fp) {
2289 if (!path)
2290 errno = ENOENT;
2291
2292 nasm_nonfatal("unable to open include file `%s': %s",
2293 file, strerror(errno));
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002294 }
2295
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002296 if (found_path)
H. Peter Anvinccad6f92016-10-04 00:34:35 -07002297 *found_path = path;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07002298
2299 return fp;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00002300}
2301
2302/*
Fabian Giesen0bbc38d2016-04-28 13:48:14 -07002303 * Opens an include or input file. Public version, for use by modules
2304 * that get a file:lineno pair and need to look at the file again
2305 * (e.g. the CodeView debug backend). Returns NULL on failure.
2306 */
H. Peter Anvin3e83cec2016-05-25 04:28:46 -07002307FILE *pp_input_fopen(const char *filename, enum file_flags mode)
Fabian Giesen0bbc38d2016-04-28 13:48:14 -07002308{
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07002309 return inc_fopen(filename, NULL, NULL, INC_OPTIONAL, mode);
Fabian Giesen0bbc38d2016-04-28 13:48:14 -07002310}
2311
2312/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002313 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002314 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002315 * return true if _any_ single-line macro of that name is defined.
2316 * Otherwise, will return true if a single-line macro with either
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002317 * `nparam' or no parameters is defined.
2318 *
2319 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002320 * defined, or nparam is -1, the address of the definition structure
2321 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002322 * is NULL, no action will be taken regarding its contents, and no
2323 * error will occur.
2324 *
2325 * Note that this is also called with nparam zero to resolve
2326 * `ifdef'.
2327 */
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002328static bool
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002329smacro_defined(Context *ctx, const char *name, int nparam, SMacro **defn,
H. Peter Anvind2354082019-08-27 16:38:48 -07002330 bool nocase, bool find_alias)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002331{
H. Peter Anvin166c2472008-05-28 12:28:58 -07002332 struct hash_table *smtbl;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002333 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002334
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002335 smtbl = ctx ? &ctx->localmac : &smacros;
H. Peter Anvind2354082019-08-27 16:38:48 -07002336
2337restart:
H. Peter Anvin166c2472008-05-28 12:28:58 -07002338 m = (SMacro *) hash_findix(smtbl, name);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002339
H. Peter Anvine2c80182005-01-15 22:15:51 +00002340 while (m) {
2341 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002342 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam ||
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002343 (m->greedy && nparam >= m->nparam-1))) {
H. Peter Anvind2354082019-08-27 16:38:48 -07002344 if (m->alias && !find_alias) {
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002345 if (!ppopt.noaliases) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002346 name = tok_text(m->expansion);
H. Peter Anvind2354082019-08-27 16:38:48 -07002347 goto restart;
2348 } else {
2349 continue;
2350 }
2351 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002352 if (defn) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002353 *defn = (nparam == m->nparam || nparam == -1) ? m : NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002354 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002355 return true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002356 }
2357 m = m->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002358 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002359
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002360 return false;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002361}
2362
Cyrill Gorcunov3079f792018-11-14 10:03:42 +03002363/* param should be a natural number [0; INT_MAX] */
2364static int read_param_count(const char *str)
2365{
2366 int result;
2367 bool err;
2368
2369 result = readnum(str, &err);
2370 if (result < 0 || result > INT_MAX) {
2371 result = 0;
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002372 nasm_nonfatal("parameter count `%s' is out of bounds [%d; %d]",
2373 str, 0, INT_MAX);
2374 } else if (err)
2375 nasm_nonfatal("unable to parse parameter count `%s'", str);
Cyrill Gorcunov3079f792018-11-14 10:03:42 +03002376 return result;
2377}
2378
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002379/*
2380 * Count and mark off the parameters in a multi-line macro call.
2381 * This is called both from within the multi-line macro expansion
2382 * code, and also to mark off the default parameters when provided
2383 * in a %macro definition line.
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002384 *
2385 * Note that we need space in the params array for parameter 0 being
2386 * a possible captured label as well as the final NULL.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002387 */
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002388static void count_mmac_params(Token *tline, int *nparamp, Token ***paramsp)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002389{
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07002390 int paramsize;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002391 int nparam = 0;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002392 Token *t;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002393 Token **params;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002394
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002395 paramsize = PARAM_DELTA;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002396 nasm_newn(params, paramsize);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002397
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002398 t = skip_white(tline);
2399 if (t) {
2400 while (true) {
2401 /* Need two slots for captured label and NULL */
2402 if (unlikely(nparam+2 >= paramsize)) {
2403 paramsize += PARAM_DELTA;
2404 params = nasm_realloc(params, sizeof(*params) * paramsize);
2405 }
2406 params[++nparam] = t;
2407 if (tok_is(t, '{')) {
2408 int brace = 1;
2409 while (brace && (t = t->next)) {
2410 brace += tok_is(t, '{');
2411 brace -= tok_is(t, '}');
2412 }
H. Peter Anvin (Intel)f8639bd2020-06-04 16:29:53 -07002413
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002414 if (t) {
2415 /*
2416 * Now we've found the closing brace, look further
2417 * for the comma.
2418 */
2419 t = skip_white(t->next);
2420 if (tok_isnt(t, ','))
2421 nasm_nonfatal("braces do not enclose all of macro parameter");
2422 } else {
2423 nasm_nonfatal("expecting closing brace in macro parameter");
2424 }
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08002425 }
2426
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07002427 /* Advance to the next comma */
2428 while (tok_isnt(t, ','))
2429 t = t->next;
2430
2431 if (!t)
2432 break; /* End of string */
2433
2434 t = skip_white(t->next); /* Eat the comma and whitespace */
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08002435 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002436 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002437
2438 params[nparam+1] = NULL;
2439 *paramsp = params;
2440 *nparamp = nparam;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002441}
2442
2443/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002444 * Determine whether one of the various `if' conditions is true or
2445 * not.
2446 *
2447 * We must free the tline we get passed.
2448 */
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002449static enum cond_state if_condition(Token * tline, enum preproc_token ct)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002450{
H. Peter Anvin70055962007-10-11 00:05:31 -07002451 bool j;
H. Peter Anvin8b262472019-02-26 14:00:54 -08002452 Token *t, *tt, *origline;
2453 struct ppscan pps;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002454 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002455 expr *evalresult;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002456 enum pp_token_type needtype;
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002457 const char *dname = pp_directives[ct];
2458 bool casesense = true;
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002459 enum preproc_token cond = PP_COND(ct);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002460
2461 origline = tline;
2462
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002463 switch (cond) {
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002464 case PP_IFCTX:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002465 j = false; /* have we matched yet? */
Victor van den Elzen0e857f12008-07-23 13:21:29 +02002466 while (true) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002467 tline = skip_white(tline);
Victor van den Elzen0e857f12008-07-23 13:21:29 +02002468 if (!tline)
2469 break;
2470 if (tline->type != TOK_ID) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002471 nasm_nonfatal("`%s' expects context identifiers",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002472 dname);
2473 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002474 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07002475 if (cstk && cstk->name && !nasm_stricmp(tok_text(tline), cstk->name))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002476 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002477 tline = tline->next;
2478 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002479 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002480
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002481 case PP_IFDEF:
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002482 case PP_IFDEFALIAS:
2483 {
2484 bool alias = cond == PP_IFDEFALIAS;
2485 SMacro *smac;
2486 Context *ctx;
2487 const char *mname;
2488
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002489 j = false; /* have we matched yet? */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002490 while (tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002491 tline = skip_white(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002492 if (!tline || (tline->type != TOK_ID &&
H. Peter Anvin8571f062019-09-23 16:40:03 -07002493 tline->type != TOK_LOCAL_MACRO)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002494 nasm_nonfatal("`%s' expects macro identifiers",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002495 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002496 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002497 }
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002498
2499 mname = tok_text(tline);
2500 ctx = get_ctx(mname, &mname);
H. Peter Anvin (Intel)b91e7732020-06-05 12:22:26 -07002501 if (smacro_defined(ctx, mname, -1, &smac, true, alias) && smac
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002502 && smac->alias == alias) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002503 j = true;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002504 break;
2505 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002506 tline = tline->next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002507 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002508 break;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002509 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002510
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002511 case PP_IFENV:
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04002512 tline = expand_smacro(tline);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002513 j = false; /* have we matched yet? */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002514 while (tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002515 tline = skip_white(tline);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002516 if (!tline || (tline->type != TOK_ID &&
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04002517 tline->type != TOK_STRING &&
H. Peter Anvin8571f062019-09-23 16:40:03 -07002518 tline->type != TOK_INTERNAL_STRING &&
2519 tline->type != TOK_ENVIRON)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002520 nasm_nonfatal("`%s' expects environment variable names",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002521 dname);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002522 goto fail;
2523 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07002524
2525 j |= !!pp_getenv(tline, false);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002526 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002527 }
2528 break;
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07002529
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002530 case PP_IFIDNI:
2531 casesense = false;
2532 /* fall through */
2533 case PP_IFIDN:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002534 tline = expand_smacro(tline);
2535 t = tt = tline;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002536 while (tok_isnt(tt, ','))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002537 tt = tt->next;
2538 if (!tt) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002539 nasm_nonfatal("`%s' expects two comma-separated arguments",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002540 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002541 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002542 }
2543 tt = tt->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002544 j = true; /* assume equality unless proved not */
H. Peter Anvin8571f062019-09-23 16:40:03 -07002545 while (tok_isnt(t, ',') && tt) {
2546 unsigned int l1, l2;
2547 const char *t1, *t2;
2548
2549 if (tok_is(tt, ',')) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002550 nasm_nonfatal("`%s': more than one comma on line",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002551 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002552 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002553 }
2554 if (t->type == TOK_WHITESPACE) {
2555 t = t->next;
2556 continue;
2557 }
2558 if (tt->type == TOK_WHITESPACE) {
2559 tt = tt->next;
2560 continue;
2561 }
2562 if (tt->type != t->type) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002563 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002564 break;
2565 }
H. Peter Anvind2456592008-06-19 15:04:18 -07002566
H. Peter Anvin8571f062019-09-23 16:40:03 -07002567 t1 = unquote_token(t);
2568 t2 = unquote_token(tt);
2569 l1 = t->len;
2570 l2 = tt->len;
2571
2572 if (l1 != l2 || mmemcmp(t1, t2, l1, casesense)) {
2573 j = false;
2574 break;
2575 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00002576
H. Peter Anvine2c80182005-01-15 22:15:51 +00002577 t = t->next;
2578 tt = tt->next;
2579 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07002580 if (!tok_is(t, ',') || tt)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002581 j = false; /* trailing gunk on one end or other */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002582 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002583
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002584 case PP_IFMACRO:
H. Peter Anvin89cee572009-07-15 09:16:54 -04002585 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002586 bool found = false;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002587 MMacro searching, *mmac;
H. Peter Anvin65747262002-05-07 00:10:05 +00002588
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002589 tline = skip_white(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002590 tline = expand_id(tline);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002591 if (!tok_type(tline, TOK_ID)) {
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002592 nasm_nonfatal("`%s' expects a macro name", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002593 goto fail;
2594 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07002595 nasm_zero(searching);
H. Peter Anvin8571f062019-09-23 16:40:03 -07002596 searching.name = dup_text(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002597 searching.casesense = true;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002598 searching.nparam_min = 0;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002599 searching.nparam_max = INT_MAX;
2600 tline = expand_smacro(tline->next);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002601 tline = skip_white(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002602 if (!tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002603 } else if (!tok_type(tline, TOK_NUMBER)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002604 nasm_nonfatal("`%s' expects a parameter count or nothing",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002605 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002606 } else {
2607 searching.nparam_min = searching.nparam_max =
H. Peter Anvin8571f062019-09-23 16:40:03 -07002608 read_param_count(tok_text(tline));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002609 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002610 if (tline && tok_is(tline->next, '-')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002611 tline = tline->next->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002612 if (tok_is(tline, '*'))
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002613 searching.nparam_max = INT_MAX;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002614 else if (!tok_type(tline, TOK_NUMBER))
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002615 nasm_nonfatal("`%s' expects a parameter count after `-'",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002616 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002617 else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002618 searching.nparam_max = read_param_count(tok_text(tline));
Cyrill Gorcunovc9244ea2017-10-22 15:25:48 +03002619 if (searching.nparam_min > searching.nparam_max) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002620 nasm_nonfatal("minimum parameter count exceeds maximum");
Cyrill Gorcunovc9244ea2017-10-22 15:25:48 +03002621 searching.nparam_max = searching.nparam_min;
2622 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002623 }
2624 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002625 if (tline && tok_is(tline->next, '+')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002626 tline = tline->next;
2627 searching.plus = true;
2628 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002629 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
2630 while (mmac) {
2631 if (!strcmp(mmac->name, searching.name) &&
2632 (mmac->nparam_min <= searching.nparam_max
2633 || searching.plus)
2634 && (searching.nparam_min <= mmac->nparam_max
2635 || mmac->plus)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002636 found = true;
2637 break;
2638 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002639 mmac = mmac->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002640 }
2641 if (tline && tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08002642 nasm_warn(WARN_OTHER, "trailing garbage after %%ifmacro ignored");
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002643 nasm_free(searching.name);
2644 j = found;
2645 break;
H. Peter Anvin89cee572009-07-15 09:16:54 -04002646 }
H. Peter Anvin65747262002-05-07 00:10:05 +00002647
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002648 case PP_IFID:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002649 needtype = TOK_ID;
2650 goto iftype;
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002651 case PP_IFNUM:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002652 needtype = TOK_NUMBER;
2653 goto iftype;
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002654 case PP_IFSTR:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002655 needtype = TOK_STRING;
2656 goto iftype;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002657
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002658iftype:
2659 t = tline = expand_smacro(tline);
H. Peter Anvind85d2502008-05-04 17:53:31 -07002660
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002661 while (tok_white(t) ||
2662 (needtype == TOK_NUMBER && (tok_is(t, '-') | tok_is(t, '+'))))
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002663 t = t->next;
H. Peter Anvind85d2502008-05-04 17:53:31 -07002664
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002665 j = tok_type(t, needtype);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002666 break;
H. Peter Anvincbf768d2008-02-16 16:41:25 -08002667
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002668 case PP_IFTOKEN:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002669 tline = expand_smacro(tline);
2670 t = skip_white(tline);
H. Peter Anvincbf768d2008-02-16 16:41:25 -08002671
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002672 j = false;
2673 if (t) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002674 t = skip_white(t->next); /* Skip the actual token + whitespace */
2675 j = !t;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002676 }
2677 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002678
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002679 case PP_IFEMPTY:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002680 tline = expand_smacro(tline);
2681 t = skip_white(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002682 j = !t; /* Should be empty */
2683 break;
H. Peter Anvin134b9462008-02-16 17:01:40 -08002684
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002685 case PP_IF:
H. Peter Anvin8b262472019-02-26 14:00:54 -08002686 pps.tptr = tline = expand_smacro(tline);
2687 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002688 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07002689 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002690 if (!evalresult)
2691 return -1;
2692 if (tokval.t_type)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08002693 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00002694 if (!is_simple(evalresult)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03002695 nasm_nonfatal("non-constant value given to `%s'",
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002696 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002697 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002698 }
Chuck Crayne60ae75d2007-05-02 01:59:16 +00002699 j = reloc_value(evalresult) != 0;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002700 break;
H. Peter Anvin95e28822007-09-12 04:20:08 +00002701
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002702 case PP_IFUSING:
2703 case PP_IFUSABLE:
2704 {
2705 const struct use_package *pkg;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002706 const char *name;
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002707
H. Peter Anvin8571f062019-09-23 16:40:03 -07002708 pkg = get_use_pkg(tline, dname, &name);
2709 if (!name)
H. Peter Anvindd88aa92019-09-12 19:39:48 -07002710 goto fail;
2711
2712 j = pkg && ((cond == PP_IFUSABLE) | use_loaded[pkg->index]);
2713 break;
2714 }
2715
H. Peter Anvine2c80182005-01-15 22:15:51 +00002716 default:
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002717 nasm_nonfatal("unknown preprocessor directive `%s'", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002718 goto fail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002719 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002720
2721 free_tlist(origline);
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002722 return (j ^ PP_COND_NEGATIVE(ct)) ? COND_IF_TRUE : COND_IF_FALSE;
H. Peter Anvin70653092007-10-19 14:42:29 -07002723
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002724fail:
2725 free_tlist(origline);
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07002726 return COND_NEVER;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002727}
2728
2729/*
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07002730 * Default smacro expansion routine: just returns a copy of the
2731 * expansion list.
2732 */
2733static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002734smacro_expand_default(const SMacro *s, Token **params, int nparams)
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07002735{
2736 (void)params;
2737 (void)nparams;
2738
2739 return dup_tlist(s->expansion, NULL);
2740}
2741
2742/*
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002743 * Emit a macro defintion or undef to the listing file, if
2744 * desired. This is similar to detoken(), but it handles the reverse
2745 * expansion list, does not expand %! or local variable tokens, and
2746 * does some special handling for macro parameters.
2747 */
2748static void
2749list_smacro_def(enum preproc_token op, const Context *ctx, const SMacro *m)
2750{
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002751 Token *t;
2752 size_t namelen, size;
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002753 char *def, *p;
H. Peter Anvin6686de22019-08-10 05:33:14 -07002754 char *context_prefix = NULL;
2755 size_t context_len;
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002756
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002757 namelen = strlen(m->name);
2758 size = namelen + 2; /* Include room for space after name + NUL */
2759
2760 if (ctx) {
H. Peter Anvin6686de22019-08-10 05:33:14 -07002761 int context_depth = cstk->depth - ctx->depth + 1;
2762 context_prefix =
2763 nasm_asprintf("[%s::%"PRIu64"] %%%-*s",
2764 ctx->name ? ctx->name : "",
2765 ctx->number, context_depth, "");
2766
2767 context_len = nasm_last_string_len();
2768 memset(context_prefix + context_len - context_depth,
2769 '$', context_depth);
2770 size += context_len;
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002771 }
2772
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002773 list_for_each(t, m->expansion)
H. Peter Anvin8571f062019-09-23 16:40:03 -07002774 size += t->len;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002775
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002776 if (m->nparam) {
2777 /*
2778 * Space for ( and either , or ) around each
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002779 * parameter, plus up to 4 flags.
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002780 */
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002781 int i;
2782
2783 size += 1 + 4 * m->nparam;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002784 for (i = 0; i < m->nparam; i++)
H. Peter Anvin8571f062019-09-23 16:40:03 -07002785 size += m->params[i].name.len;
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002786 }
2787
2788 def = nasm_malloc(size);
2789 p = def+size;
2790 *--p = '\0';
2791
2792 list_for_each(t, m->expansion) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002793 p -= t->len;
2794 memcpy(p, tok_text(t), t->len);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002795 }
2796
2797 *--p = ' ';
2798
2799 if (m->nparam) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002800 int i;
2801
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002802 *--p = ')';
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002803 for (i = m->nparam-1; i >= 0; i--) {
2804 enum sparmflags flags = m->params[i].flags;
2805 if (flags & SPARM_GREEDY)
2806 *--p = '+';
H. Peter Anvin8571f062019-09-23 16:40:03 -07002807 p -= m->params[i].name.len;
2808 memcpy(p, tok_text(&m->params[i].name), m->params[i].name.len);
2809
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002810 if (flags & SPARM_NOSTRIP)
2811 *--p = '!';
2812 if (flags & SPARM_STR)
2813 *--p = '&';
2814 if (flags & SPARM_EVAL)
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002815 *--p = '=';
2816 *--p = ',';
2817 }
2818 *p = '('; /* First parameter starts with ( not , */
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002819 }
2820
2821 p -= namelen;
2822 memcpy(p, m->name, namelen);
2823
H. Peter Anvin6686de22019-08-10 05:33:14 -07002824 if (context_prefix) {
2825 p -= context_len;
2826 memcpy(p, context_prefix, context_len);
2827 nasm_free(context_prefix);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002828 }
2829
2830 nasm_listmsg("%s %s", pp_directives[op], p);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002831 nasm_free(def);
H. Peter Anvin6686de22019-08-10 05:33:14 -07002832}
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07002833
2834/*
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002835 * Parse smacro arguments, return argument count. If the tmpl argument
2836 * is set, set the nparam, greedy and params field in the template.
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002837 * *tpp is updated to point to the pointer to the first token after the
2838 * prototype.
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002839 *
2840 * The text values from any argument tokens are "stolen" and the
2841 * corresponding text fields set to NULL.
2842 */
2843static int parse_smacro_template(Token ***tpp, SMacro *tmpl)
2844{
2845 int nparam = 0;
2846 enum sparmflags flags;
2847 struct smac_param *params = NULL;
H. Peter Anvin (Intel)68075f82019-08-20 12:28:05 -07002848 bool err, done;
2849 bool greedy = false;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002850 Token **tn = *tpp;
2851 Token *t = *tn;
2852 Token *name;
2853
H. Peter Anvin (Intel)d4607842019-08-20 16:19:37 -07002854 /*
2855 * DO NOT skip whitespace here, or we won't be able to distinguish:
2856 *
2857 * %define foo (a,b) ; no arguments, (a,b) is the expansion
2858 * %define bar(a,b) ; two arguments, empty expansion
2859 *
2860 * This ambiguity was inherited from C.
2861 */
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002862
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07002863 if (!tok_is(t, '('))
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002864 goto finish;
2865
2866 if (tmpl) {
2867 Token *tx = t;
2868 Token **txpp = &tx;
2869 int sparam;
2870
2871 /* Count parameters first */
2872 sparam = parse_smacro_template(&txpp, NULL);
2873 if (!sparam)
2874 goto finish; /* No parameters, we're done */
2875 nasm_newn(params, sparam);
2876 }
2877
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002878 /* Skip leading paren */
2879 tn = &t->next;
2880 t = *tn;
2881
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002882 name = NULL;
2883 flags = 0;
H. Peter Anvin (Intel)68075f82019-08-20 12:28:05 -07002884 err = done = false;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002885
2886 while (!done) {
2887 if (!t || !t->type) {
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002888 if (name || flags)
2889 nasm_nonfatal("`)' expected to terminate macro template");
2890 else
2891 nasm_nonfatal("parameter identifier expected");
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002892 break;
2893 }
2894
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002895 switch (t->type) {
2896 case TOK_ID:
2897 if (name)
2898 goto bad;
2899 name = t;
2900 break;
2901
2902 case TOK_OTHER:
H. Peter Anvin8571f062019-09-23 16:40:03 -07002903 if (t->len != 1)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002904 goto bad;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002905 switch (t->text.a[0]) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002906 case '=':
2907 flags |= SPARM_EVAL;
2908 break;
2909 case '&':
2910 flags |= SPARM_STR;
2911 break;
2912 case '!':
2913 flags |= SPARM_NOSTRIP;
2914 break;
2915 case '+':
2916 flags |= SPARM_GREEDY;
2917 greedy = true;
2918 break;
2919 case ',':
2920 if (greedy)
2921 nasm_nonfatal("greedy parameter must be last");
2922 /* fall through */
2923 case ')':
2924 if (params) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002925 if (name)
2926 steal_Token(&params[nparam].name, name);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002927 params[nparam].flags = flags;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002928 }
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002929 nparam++;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002930 name = NULL;
2931 flags = 0;
H. Peter Anvin8571f062019-09-23 16:40:03 -07002932 done = t->text.a[0] == ')';
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002933 break;
2934 default:
2935 goto bad;
2936 }
2937 break;
2938
2939 case TOK_WHITESPACE:
2940 break;
2941
2942 default:
2943 bad:
2944 if (!err) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07002945 nasm_nonfatal("garbage `%s' in macro parameter list", tok_text(t));
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002946 err = true;
2947 }
2948 break;
2949 }
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002950
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07002951 tn = &t->next;
2952 t = *tn;
2953 }
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002954
2955finish:
2956 while (t && t->type == TOK_WHITESPACE) {
2957 tn = &t->next;
2958 t = t->next;
2959 }
2960 *tpp = tn;
2961 if (tmpl) {
2962 tmpl->nparam = nparam;
2963 tmpl->greedy = greedy;
2964 tmpl->params = params;
2965 }
2966 return nparam;
2967}
2968
2969/*
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07002970 * Common code for defining an smacro. The tmpl argument, if not NULL,
2971 * contains any macro parameters that aren't explicit arguments;
2972 * those are the more uncommon macro variants.
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002973 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07002974static SMacro *define_smacro(const char *mname, bool casesense,
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07002975 Token *expansion, SMacro *tmpl)
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002976{
2977 SMacro *smac, **smhead;
H. Peter Anvin166c2472008-05-28 12:28:58 -07002978 struct hash_table *smtbl;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07002979 Context *ctx;
2980 bool defining_alias = false;
2981 unsigned int nparam = 0;
H. Peter Anvin70653092007-10-19 14:42:29 -07002982
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07002983 if (tmpl) {
2984 defining_alias = tmpl->alias;
2985 nparam = tmpl->nparam;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07002986 if (nparam && !defining_alias)
2987 mark_smac_params(expansion, tmpl, 0);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07002988 }
2989
2990 while (1) {
2991 ctx = get_ctx(mname, &mname);
2992
H. Peter Anvind2354082019-08-27 16:38:48 -07002993 if (!smacro_defined(ctx, mname, nparam, &smac, casesense, true)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07002994 /* Create a new macro */
2995 smtbl = ctx ? &ctx->localmac : &smacros;
2996 smhead = (SMacro **) hash_findi_add(smtbl, mname);
2997 nasm_new(smac);
2998 smac->next = *smhead;
2999 *smhead = smac;
3000 break;
3001 } else if (!smac) {
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003002 nasm_warn(WARN_OTHER, "single-line macro `%s' defined both with and"
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003003 " without parameters", mname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003004 /*
3005 * Some instances of the old code considered this a failure,
3006 * some others didn't. What is the right thing to do here?
3007 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003008 goto fail;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003009 } else if (!smac->alias || ppopt.noaliases || defining_alias) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003010 /*
3011 * We're redefining, so we have to take over an
3012 * existing SMacro structure. This means freeing
H. Peter Anvin8b262472019-02-26 14:00:54 -08003013 * what was already in it, but not the structure itself.
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003014 */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07003015 clear_smacro(smac);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003016 break;
3017 } else if (smac->in_progress) {
3018 nasm_nonfatal("macro alias loop");
3019 goto fail;
3020 } else {
3021 /* It is an alias macro; follow the alias link */
3022 SMacro *s;
3023
3024 smac->in_progress = true;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003025 s = define_smacro(tok_text(smac->expansion), casesense,
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003026 expansion, tmpl);
3027 smac->in_progress = false;
3028 return s;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003029 }
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003030 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003031
3032 smac->name = nasm_strdup(mname);
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003033 smac->casesense = casesense;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003034 smac->expansion = expansion;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003035 smac->expand = smacro_expand_default;
3036 if (tmpl) {
3037 smac->nparam = tmpl->nparam;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07003038 smac->params = tmpl->params;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003039 smac->alias = tmpl->alias;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07003040 smac->greedy = tmpl->greedy;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003041 if (tmpl->expand)
3042 smac->expand = tmpl->expand;
3043 }
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07003044 if (list_option('s')) {
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07003045 list_smacro_def((smac->alias ? PP_DEFALIAS : PP_DEFINE)
3046 + !casesense, ctx, smac);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003047 }
H. Peter Anvin8b262472019-02-26 14:00:54 -08003048 return smac;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003049
3050fail:
3051 free_tlist(expansion);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07003052 if (tmpl)
3053 free_smacro_members(tmpl);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003054 return NULL;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003055}
3056
3057/*
3058 * Undefine an smacro
3059 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003060static void undef_smacro(const char *mname, bool undefalias)
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003061{
3062 SMacro **smhead, *s, **sp;
H. Peter Anvin166c2472008-05-28 12:28:58 -07003063 struct hash_table *smtbl;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003064 Context *ctx;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003065
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003066 ctx = get_ctx(mname, &mname);
H. Peter Anvin166c2472008-05-28 12:28:58 -07003067 smtbl = ctx ? &ctx->localmac : &smacros;
3068 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
H. Peter Anvin70653092007-10-19 14:42:29 -07003069
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003070 if (smhead) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003071 /*
3072 * We now have a macro name... go hunt for it.
3073 */
3074 sp = smhead;
3075 while ((s = *sp) != NULL) {
3076 if (!mstrcmp(s->name, mname, s->casesense)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003077 if (s->alias && !undefalias) {
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003078 if (!ppopt.noaliases) {
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07003079 if (s->in_progress) {
3080 nasm_nonfatal("macro alias loop");
3081 } else {
3082 s->in_progress = true;
3083 undef_smacro(tok_text(s->expansion), false);
3084 s->in_progress = false;
3085 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003086 }
3087 } else {
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07003088 if (list_option('d'))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003089 list_smacro_def(s->alias ? PP_UNDEFALIAS : PP_UNDEF,
3090 ctx, s);
3091 *sp = s->next;
3092 free_smacro(s);
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07003093 continue;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003094 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003095 }
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07003096 sp = &s->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003097 }
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003098 }
3099}
3100
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003101/*
H. Peter Anvina26433d2008-07-16 14:40:01 -07003102 * Parse a mmacro specification.
3103 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003104static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
H. Peter Anvina26433d2008-07-16 14:40:01 -07003105{
H. Peter Anvina26433d2008-07-16 14:40:01 -07003106 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003107 tline = skip_white(tline);
H. Peter Anvina26433d2008-07-16 14:40:01 -07003108 tline = expand_id(tline);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003109 if (!tok_type(tline, TOK_ID)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003110 nasm_nonfatal("`%s' expects a macro name", directive);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003111 return false;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003112 }
Victor van den Elzenb916ede2008-07-23 15:14:22 +02003113
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07003114#if 0
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003115 def->prev = NULL;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07003116#endif
H. Peter Anvin8571f062019-09-23 16:40:03 -07003117 def->name = dup_text(tline);
H. Peter Anvina26433d2008-07-16 14:40:01 -07003118 def->plus = false;
3119 def->nolist = false;
Victor van den Elzenb916ede2008-07-23 15:14:22 +02003120 def->nparam_min = 0;
3121 def->nparam_max = 0;
3122
H. Peter Anvina26433d2008-07-16 14:40:01 -07003123 tline = expand_smacro(tline->next);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003124 tline = skip_white(tline);
3125 if (!tok_type(tline, TOK_NUMBER))
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003126 nasm_nonfatal("`%s' expects a parameter count", directive);
3127 else
H. Peter Anvin8571f062019-09-23 16:40:03 -07003128 def->nparam_min = def->nparam_max = read_param_count(tok_text(tline));
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003129 if (tline && tok_is(tline->next, '-')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003130 tline = tline->next->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003131 if (tok_is(tline, '*')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003132 def->nparam_max = INT_MAX;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003133 } else if (!tok_type(tline, TOK_NUMBER)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003134 nasm_nonfatal("`%s' expects a parameter count after `-'", directive);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003135 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003136 def->nparam_max = read_param_count(tok_text(tline));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003137 if (def->nparam_min > def->nparam_max) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003138 nasm_nonfatal("minimum parameter count exceeds maximum");
Cyrill Gorcunovc9244ea2017-10-22 15:25:48 +03003139 def->nparam_max = def->nparam_min;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003140 }
3141 }
H. Peter Anvina26433d2008-07-16 14:40:01 -07003142 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003143 if (tline && tok_is(tline->next, '+')) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003144 tline = tline->next;
3145 def->plus = true;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003146 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003147 if (tline && tok_type(tline->next, TOK_ID) &&
H. Peter Anvin8571f062019-09-23 16:40:03 -07003148 tline->next->len == 7 &&
3149 !nasm_stricmp(tline->next->text.a, ".nolist")) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003150 tline = tline->next;
H. Peter Anvin6686de22019-08-10 05:33:14 -07003151 def->nolist = !list_option('f') || istk->nolist;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003152 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003153
H. Peter Anvina26433d2008-07-16 14:40:01 -07003154 /*
3155 * Handle default parameters.
3156 */
3157 if (tline && tline->next) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003158 def->dlist = tline->next;
3159 tline->next = NULL;
3160 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
H. Peter Anvina26433d2008-07-16 14:40:01 -07003161 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003162 def->dlist = NULL;
3163 def->defaults = NULL;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003164 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003165 def->expansion = NULL;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003166
H. Peter Anvin89cee572009-07-15 09:16:54 -04003167 if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -08003168 !def->plus) {
3169 /*
3170 *!macro-defaults [on] macros with more default than optional parameters
3171 *! warns when a macro has more default parameters than optional parameters.
3172 *! See \k{mlmacdef} for why might want to disable this warning.
3173 */
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003174 nasm_warn(WARN_MACRO_DEFAULTS,
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -08003175 "too many default macro parameters in macro `%s'", def->name);
3176 }
Victor van den Elzenb916ede2008-07-23 15:14:22 +02003177
H. Peter Anvina26433d2008-07-16 14:40:01 -07003178 return true;
3179}
3180
3181
3182/*
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003183 * Decode a size directive
3184 */
3185static int parse_size(const char *str) {
3186 static const char *size_names[] =
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003187 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003188 static const int sizes[] =
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003189 { 0, 1, 4, 16, 8, 10, 2, 32 };
Cyrill Gorcunovc713b5f2018-09-29 14:30:14 +03003190 return str ? sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1] : 0;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003191}
3192
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003193/*
3194 * Process a preprocessor %pragma directive. Currently there are none.
3195 * Gets passed the token list starting with the "preproc" token from
3196 * "%pragma preproc".
3197 */
3198static void do_pragma_preproc(Token *tline)
3199{
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003200 const char *txt;
3201
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003202 /* Skip to the real stuff */
3203 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003204 tline = skip_white(tline);
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003205
3206 if (!tok_type(tline, TOK_ID))
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003207 return;
3208
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003209 txt = tok_text(tline);
3210 if (!nasm_stricmp(txt, "sane_empty_expansion")) {
3211 tline = skip_white(tline->next);
3212 ppopt.sane_empty_expansion =
3213 pp_get_boolean_option(tline, ppopt.sane_empty_expansion);
3214 } else {
3215 /* Unknown pragma, ignore for now */
3216 }
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003217}
3218
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003219static bool is_macro_id(const Token *t)
3220{
H. Peter Anvin8571f062019-09-23 16:40:03 -07003221 return tok_type(t, TOK_ID) || tok_type(t, TOK_LOCAL_MACRO);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003222}
3223
H. Peter Anvin8571f062019-09-23 16:40:03 -07003224static const char *get_id(Token **tp, const char *dname)
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003225{
H. Peter Anvin8571f062019-09-23 16:40:03 -07003226 const char *id;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003227 Token *t = *tp;
3228
3229 t = t->next; /* Skip directive */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003230 t = skip_white(t);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003231 t = expand_id(t);
3232
3233 if (!is_macro_id(t)) {
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003234 nasm_nonfatal("`%s' expects a macro identifier", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003235 return NULL;
3236 }
3237
H. Peter Anvin8571f062019-09-23 16:40:03 -07003238 id = tok_text(t);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003239 t = skip_white(t);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003240 *tp = t;
3241 return id;
3242}
3243
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003244/* Parse a %use package name and find the package. Set *err on syntax error. */
3245static const struct use_package *
H. Peter Anvin8571f062019-09-23 16:40:03 -07003246get_use_pkg(Token *t, const char *dname, const char **name)
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003247{
H. Peter Anvin8571f062019-09-23 16:40:03 -07003248 const char *id;
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003249
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003250 t = skip_white(t);
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003251 t = expand_smacro(t);
3252
H. Peter Anvin8571f062019-09-23 16:40:03 -07003253 *name = NULL;
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003254
H. Peter Anvin8571f062019-09-23 16:40:03 -07003255 if (!t) {
3256 nasm_nonfatal("`%s' expects a package name, got end of line", dname);
3257 return NULL;
3258 } else if (t->type != TOK_ID && t->type != TOK_STRING) {
3259 nasm_nonfatal("`%s' expects a package name, got `%s'",
3260 dname, tok_text(t));
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003261 return NULL;
3262 }
3263
H. Peter Anvin8571f062019-09-23 16:40:03 -07003264 *name = id = unquote_token(t);
3265
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003266 t = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003267 t = skip_white(t);
H. Peter Anvina039fcd2019-09-12 19:27:42 -07003268 if (t)
3269 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
3270
3271 return nasm_find_use_package(id);
3272}
3273
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003274/*
3275 * Mark parameter tokens in an smacro definition. If the type argument
3276 * is 0, create smac param tokens, otherwise use the type specified;
3277 * normally this is used for TOK_XDEF_PARAM, which is used to protect
3278 * parameter tokens during expansion during %xdefine.
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07003279 *
3280 * tmpl may not be NULL here.
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003281 */
3282static void mark_smac_params(Token *tline, const SMacro *tmpl,
3283 enum pp_token_type type)
3284{
3285 const struct smac_param *params = tmpl->params;
3286 int nparam = tmpl->nparam;
3287 Token *t;
3288 int i;
3289
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003290 list_for_each(t, tline) {
3291 if (t->type != TOK_ID && t->type != TOK_XDEF_PARAM)
3292 continue;
3293
3294 for (i = 0; i < nparam; i++) {
3295 if (tok_text_match(t, &params[i].name))
3296 t->type = type ? type : tok_smac_param(i);
3297 }
3298 }
3299}
3300
Ed Beroset3ab3f412002-06-11 03:31:49 +00003301/**
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003302 * %clear selected macro sets either globally or in contexts
3303 */
3304static void do_clear(enum clear_what what, bool context)
3305{
3306 if (context) {
3307 if (what & CLEAR_ALLDEFINE) {
3308 Context *ctx;
3309 list_for_each(ctx, cstk)
3310 clear_smacro_table(&ctx->localmac, what);
3311 }
3312 /* Nothing else can be context-local */
3313 } else {
3314 if (what & CLEAR_ALLDEFINE)
3315 clear_smacro_table(&smacros, what);
3316 if (what & CLEAR_MMACRO)
3317 free_mmacro_table(&mmacros);
3318 }
3319}
3320
3321/**
Ed Beroset3ab3f412002-06-11 03:31:49 +00003322 * find and process preprocessor directive in passed line
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003323 * Find out if a line contains a preprocessor directive, and deal
3324 * with it if so.
H. Peter Anvin70653092007-10-19 14:42:29 -07003325 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00003326 * If a directive _is_ found, it is the responsibility of this routine
3327 * (and not the caller) to free_tlist() the line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003328 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00003329 * @param tline a pointer to the current tokeninzed line linked list
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003330 * @param output if this directive generated output
Ed Beroset3ab3f412002-06-11 03:31:49 +00003331 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
H. Peter Anvin70653092007-10-19 14:42:29 -07003332 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003333 */
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07003334static int do_directive(Token *tline, Token **output)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003335{
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003336 enum preproc_token op;
H. Peter Anvin4169a472007-09-12 01:29:43 +00003337 int j;
H. Peter Anvin70055962007-10-11 00:05:31 -07003338 bool err;
H. Peter Anvin70055962007-10-11 00:05:31 -07003339 bool nolist;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003340 bool casesense;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -07003341 int k, m;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003342 int offset;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003343 const char *p;
3344 char *q, *qbuf;
H. Peter Anvinccad6f92016-10-04 00:34:35 -07003345 const char *found_path;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003346 const char *mname;
H. Peter Anvin8b262472019-02-26 14:00:54 -08003347 struct ppscan pps;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003348 Include *inc;
3349 Context *ctx;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003350 Cond *cond;
3351 MMacro *mmac, **mmhead;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07003352 Token *t = NULL, *tt, *macro_start, *last, *origline;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003353 Line *l;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003354 struct tokenval tokval;
3355 expr *evalresult;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07003356 int64_t count;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003357 size_t len;
H. Peter Anvin (Intel)6bde2ed2018-12-13 19:39:41 -08003358 errflags severity;
H. Peter Anvin8b262472019-02-26 14:00:54 -08003359 const char *dname; /* Name of directive, for messages */
H. Peter Anvin76690a12002-04-30 20:52:49 +00003360
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003361 *output = NULL; /* No output generated */
H. Peter Anvin76690a12002-04-30 20:52:49 +00003362 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003363
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003364 tline = skip_white(tline);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003365 if (!tline || !tok_type(tline, TOK_PREPROC_ID))
3366 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003367
H. Peter Anvin8571f062019-09-23 16:40:03 -07003368 dname = tok_text(tline);
3369 if (dname[1] == '%')
3370 return NO_DIRECTIVE_FOUND;
3371
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003372 op = pp_token_hash(dname);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003373
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003374 casesense = true;
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003375 if (PP_HAS_CASE(op) & PP_INSENSITIVE(op)) {
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003376 casesense = false;
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003377 op--;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003378 }
3379
3380 /*
3381 * If we're in a non-emitting branch of a condition construct,
3382 * or walking to the end of an already terminated %rep block,
3383 * we should ignore all directives except for condition
3384 * directives.
3385 */
3386 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07003387 (istk->mstk.mstk && !istk->mstk.mstk->in_progress)) &&
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003388 !is_condition(op)) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003389 return NO_DIRECTIVE_FOUND;
3390 }
3391
3392 /*
3393 * If we're defining a macro or reading a %rep block, we should
3394 * ignore all directives except for %macro/%imacro (which nest),
3395 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
3396 * If we're in a %rep block, another %rep nests, so should be let through.
3397 */
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003398 if (defining && op != PP_MACRO && op != PP_RMACRO &&
3399 op != PP_ENDMACRO && op != PP_ENDM &&
3400 (defining->name || (op != PP_ENDREP && op != PP_REP))) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003401 return NO_DIRECTIVE_FOUND;
3402 }
3403
3404 if (defining) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003405 if (op == PP_MACRO || op == PP_RMACRO) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003406 nested_mac_count++;
3407 return NO_DIRECTIVE_FOUND;
3408 } else if (nested_mac_count > 0) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003409 if (op == PP_ENDMACRO) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003410 nested_mac_count--;
3411 return NO_DIRECTIVE_FOUND;
3412 }
3413 }
3414 if (!defining->name) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003415 if (op == PP_REP) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003416 nested_rep_count++;
3417 return NO_DIRECTIVE_FOUND;
3418 } else if (nested_rep_count > 0) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003419 if (op == PP_ENDREP) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003420 nested_rep_count--;
3421 return NO_DIRECTIVE_FOUND;
3422 }
3423 }
3424 }
3425 }
3426
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003427 switch (op) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003428 default:
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003429 nasm_nonfatal("unknown preprocessor directive `%s'", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003430 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003431
H. Peter Anvin3f87a2a2016-10-04 14:07:19 -07003432 case PP_PRAGMA:
3433 /*
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003434 * %pragma namespace options...
3435 *
3436 * The namespace "preproc" is reserved for the preprocessor;
3437 * all other namespaces generate a [pragma] assembly directive.
3438 *
3439 * Invalid %pragmas are ignored and may have different
3440 * meaning in future versions of NASM.
H. Peter Anvin3f87a2a2016-10-04 14:07:19 -07003441 */
H. Peter Anvinf5d7d902019-08-10 06:21:00 -07003442 t = tline;
3443 tline = tline->next;
3444 t->next = NULL;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003445 tline = zap_white(expand_smacro(tline));
3446 if (tok_type(tline, TOK_ID)) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003447 if (!nasm_stricmp(tok_text(tline), "preproc")) {
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003448 /* Preprocessor pragma */
3449 do_pragma_preproc(tline);
H. Peter Anvin06335872019-08-10 06:42:55 -07003450 free_tlist(tline);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003451 } else {
3452 /* Build the assembler directive */
H. Peter Anvin06335872019-08-10 06:42:55 -07003453
3454 /* Append bracket to the end of the output */
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003455 for (t = tline; t->next; t = t->next)
3456 ;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003457 t->next = make_tok_char(NULL, ']');
H. Peter Anvin06335872019-08-10 06:42:55 -07003458
3459 /* Prepend "[pragma " */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003460 t = new_White(tline);
H. Peter Anvin06335872019-08-10 06:42:55 -07003461 t = new_Token(t, TOK_ID, "pragma", 6);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003462 t = make_tok_char(t, '[');
H. Peter Anvin06335872019-08-10 06:42:55 -07003463 tline = t;
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07003464 *output = tline;
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003465 }
3466 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003467 break;
H. Peter Anvin3f87a2a2016-10-04 14:07:19 -07003468
H. Peter Anvine2c80182005-01-15 22:15:51 +00003469 case PP_STACKSIZE:
3470 /* Directive to tell NASM what the default stack size is. The
3471 * default is for a 16-bit stack, and this can be overriden with
3472 * %stacksize large.
H. Peter Anvine2c80182005-01-15 22:15:51 +00003473 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003474 tline = skip_white(tline->next);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003475 if (!tline || tline->type != TOK_ID) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003476 nasm_nonfatal("`%s' missing size parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003477 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07003478 if (nasm_stricmp(tok_text(tline), "flat") == 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003479 /* All subsequent ARG directives are for a 32-bit stack */
3480 StackSize = 4;
3481 StackPointer = "ebp";
3482 ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003483 LocalOffset = 0;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003484 } else if (nasm_stricmp(tok_text(tline), "flat64") == 0) {
Charles Crayne7eaf9192007-11-08 22:11:14 -08003485 /* All subsequent ARG directives are for a 64-bit stack */
3486 StackSize = 8;
3487 StackPointer = "rbp";
Per Jessen53252e02010-02-11 00:16:59 +03003488 ArgOffset = 16;
Charles Crayne7eaf9192007-11-08 22:11:14 -08003489 LocalOffset = 0;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003490 } else if (nasm_stricmp(tok_text(tline), "large") == 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003491 /* All subsequent ARG directives are for a 16-bit stack,
3492 * far function call.
3493 */
3494 StackSize = 2;
3495 StackPointer = "bp";
3496 ArgOffset = 4;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003497 LocalOffset = 0;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003498 } else if (nasm_stricmp(tok_text(tline), "small") == 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003499 /* All subsequent ARG directives are for a 16-bit stack,
3500 * far function call. We don't support near functions.
3501 */
3502 StackSize = 2;
3503 StackPointer = "bp";
3504 ArgOffset = 6;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003505 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003506 } else {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003507 nasm_nonfatal("`%s' invalid size type", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003508 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003509 break;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003510
H. Peter Anvine2c80182005-01-15 22:15:51 +00003511 case PP_ARG:
3512 /* TASM like ARG directive to define arguments to functions, in
3513 * the following form:
3514 *
3515 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
3516 */
3517 offset = ArgOffset;
3518 do {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003519 const char *arg;
3520 char directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003521 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003522
H. Peter Anvine2c80182005-01-15 22:15:51 +00003523 /* Find the argument name */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003524 tline = skip_white(tline->next);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003525 if (!tline || tline->type != TOK_ID) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003526 nasm_nonfatal("`%s' missing argument parameter", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003527 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003528 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07003529 arg = tok_text(tline);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003530
H. Peter Anvine2c80182005-01-15 22:15:51 +00003531 /* Find the argument size type */
3532 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003533 if (!tok_is(tline, ':')) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003534 nasm_nonfatal("syntax error processing `%s' directive", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003535 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003536 }
3537 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003538 if (!tok_type(tline, TOK_ID)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003539 nasm_nonfatal("`%s' missing size type parameter", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003540 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003541 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003542
H. Peter Anvine2c80182005-01-15 22:15:51 +00003543 /* Allow macro expansion of type parameter */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003544 tt = tokenize(tok_text(tline));
H. Peter Anvine2c80182005-01-15 22:15:51 +00003545 tt = expand_smacro(tt);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003546 size = parse_size(tok_text(tt));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003547 if (!size) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003548 nasm_nonfatal("invalid size type for `%s' missing directive", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003549 free_tlist(tt);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003550 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003551 }
3552 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003553
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003554 /* Round up to even stack slots */
3555 size = ALIGN(size, StackSize);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003556
H. Peter Anvine2c80182005-01-15 22:15:51 +00003557 /* Now define the macro for the argument */
3558 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
3559 arg, StackPointer, offset);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003560 do_directive(tokenize(directive), output);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003561 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003562
H. Peter Anvine2c80182005-01-15 22:15:51 +00003563 /* Move to the next argument in the list */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003564 tline = skip_white(tline->next);
3565 } while (tok_is(tline, ','));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003566 ArgOffset = offset;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003567 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003568
H. Peter Anvine2c80182005-01-15 22:15:51 +00003569 case PP_LOCAL:
3570 /* TASM like LOCAL directive to define local variables for a
3571 * function, in the following form:
3572 *
3573 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
3574 *
3575 * The '= LocalSize' at the end is ignored by NASM, but is
3576 * required by TASM to define the local parameter size (and used
3577 * by the TASM macro package).
3578 */
3579 offset = LocalOffset;
3580 do {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003581 const char *local;
3582 char directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003583 int size = StackSize;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003584
H. Peter Anvine2c80182005-01-15 22:15:51 +00003585 /* Find the argument name */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003586 tline = skip_white(tline->next);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003587 if (!tline || tline->type != TOK_ID) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003588 nasm_nonfatal("`%s' missing argument parameter", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003589 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003590 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07003591 local = tok_text(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003592
H. Peter Anvine2c80182005-01-15 22:15:51 +00003593 /* Find the argument size type */
3594 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003595 if (!tok_is(tline, ':')) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003596 nasm_nonfatal("syntax error processing `%s' directive", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003597 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003598 }
3599 tline = tline->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003600 if (!tok_type(tline, TOK_ID)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003601 nasm_nonfatal("`%s' missing size type parameter", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003602 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003603 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003604
H. Peter Anvine2c80182005-01-15 22:15:51 +00003605 /* Allow macro expansion of type parameter */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003606 tt = tokenize(tok_text(tline));
H. Peter Anvine2c80182005-01-15 22:15:51 +00003607 tt = expand_smacro(tt);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003608 size = parse_size(tok_text(tt));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003609 if (!size) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003610 nasm_nonfatal("invalid size type for `%s' missing directive", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003611 free_tlist(tt);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003612 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003613 }
3614 free_tlist(tt);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003615
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003616 /* Round up to even stack slots */
3617 size = ALIGN(size, StackSize);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003618
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003619 offset += size; /* Negative offset, increment before */
H. Peter Anvin8781cb02007-11-08 20:01:11 -08003620
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003621 /* Now define the macro for the argument */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003622 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
3623 local, StackPointer, offset);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003624 do_directive(tokenize(directive), output);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003625
H. Peter Anvine2c80182005-01-15 22:15:51 +00003626 /* Now define the assign to setup the enter_c macro correctly */
3627 snprintf(directive, sizeof(directive),
3628 "%%assign %%$localsize %%$localsize+%d", size);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07003629 do_directive(tokenize(directive), output);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003630
H. Peter Anvine2c80182005-01-15 22:15:51 +00003631 /* Move to the next argument in the list */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003632 tline = skip_white(tline->next);
3633 } while (tok_is(tline, ','));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003634 LocalOffset = offset;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003635 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003636
H. Peter Anvine2c80182005-01-15 22:15:51 +00003637 case PP_CLEAR:
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003638 {
3639 bool context = false;
3640
3641 t = tline->next = expand_smacro(tline->next);
3642 t = skip_white(t);
3643 if (!t) {
3644 /* Emulate legacy behavior */
3645 do_clear(CLEAR_DEFINE|CLEAR_MMACRO, false);
3646 } else {
3647 while ((t = skip_white(t)) && t->type == TOK_ID) {
3648 const char *txt = tok_text(t);
3649 if (!nasm_stricmp(txt, "all")) {
3650 do_clear(CLEAR_ALL, context);
3651 } else if (!nasm_stricmp(txt, "define") ||
3652 !nasm_stricmp(txt, "def") ||
3653 !nasm_stricmp(txt, "smacro")) {
3654 do_clear(CLEAR_DEFINE, context);
3655 } else if (!nasm_stricmp(txt, "defalias") ||
3656 !nasm_stricmp(txt, "alias") ||
3657 !nasm_stricmp(txt, "salias")) {
3658 do_clear(CLEAR_DEFALIAS, context);
3659 } else if (!nasm_stricmp(txt, "alldef") ||
3660 !nasm_stricmp(txt, "alldefine")) {
3661 do_clear(CLEAR_ALLDEFINE, context);
3662 } else if (!nasm_stricmp(txt, "macro") ||
3663 !nasm_stricmp(txt, "mmacro")) {
3664 do_clear(CLEAR_MMACRO, context);
3665 } else if (!nasm_stricmp(txt, "context") ||
3666 !nasm_stricmp(txt, "ctx")) {
3667 context = true;
3668 } else if (!nasm_stricmp(txt, "global")) {
3669 context = false;
3670 } else if (!nasm_stricmp(txt, "nothing") ||
3671 !nasm_stricmp(txt, "none") ||
3672 !nasm_stricmp(txt, "ignore") ||
3673 !nasm_stricmp(txt, "-") ||
3674 !nasm_stricmp(txt, "--")) {
3675 /* Do nothing */
3676 } else {
3677 nasm_nonfatal("invalid option to %s: %s", dname, txt);
3678 t = NULL;
3679 }
3680 }
3681 }
3682
3683 t = skip_white(t);
3684 if (t)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003685 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003686 break;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07003687 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003688
H. Peter Anvin418ca702008-05-30 10:42:30 -07003689 case PP_DEPEND:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003690 t = tline->next = expand_smacro(tline->next);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003691 t = skip_white(t);
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003692 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003693 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003694 nasm_nonfatal("`%s' expects a file name", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003695 goto done;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003696 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003697 if (t->next)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003698 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003699
3700 strlist_add(deplist, unquote_token_cstr(t));
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003701 goto done;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003702
3703 case PP_INCLUDE:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003704 t = tline->next = expand_smacro(tline->next);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003705 t = skip_white(t);
H. Peter Anvind2456592008-06-19 15:04:18 -07003706
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003707 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003708 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003709 nasm_nonfatal("`%s' expects a file name", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003710 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003711 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003712 if (t->next)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003713 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003714 p = unquote_token_cstr(t);
H. Peter Anvin6686de22019-08-10 05:33:14 -07003715 nasm_new(inc);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003716 inc->next = istk;
Jim Kukunas65a8afc2016-06-13 16:00:42 -04003717 found_path = NULL;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07003718 inc->fp = inc_fopen(p, deplist, &found_path,
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08003719 (pp_mode == PP_DEPS)
3720 ? INC_OPTIONAL : INC_NEEDED, NF_TEXT);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003721 if (!inc->fp) {
3722 /* -MG given but file not found */
3723 nasm_free(inc);
3724 } else {
Jim Kukunas65a8afc2016-06-13 16:00:42 -04003725 inc->fname = src_set_fname(found_path ? found_path : p);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003726 inc->lineno = src_set_linnum(0);
3727 inc->lineinc = 1;
H. Peter Anvin6686de22019-08-10 05:33:14 -07003728 inc->nolist = istk->nolist;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003729 istk = inc;
H. Peter Anvin0d4d4312019-08-07 00:46:27 -07003730 lfmt->uplevel(LIST_INCLUDE, 0);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003731 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003732 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003733
H. Peter Anvind2456592008-06-19 15:04:18 -07003734 case PP_USE:
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07003735 {
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07003736 const struct use_package *pkg;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003737 const char *name;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07003738
H. Peter Anvin8571f062019-09-23 16:40:03 -07003739 pkg = get_use_pkg(tline->next, dname, &name);
3740 if (!name)
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003741 goto done;
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07003742 if (!pkg) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003743 nasm_nonfatal("unknown `%s' package: `%s'", dname, name);
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07003744 } else if (!use_loaded[pkg->index]) {
H. Peter Anvin6686de22019-08-10 05:33:14 -07003745 /*
3746 * Not already included, go ahead and include it.
3747 * Treat it as an include file for the purpose of
3748 * producing a listing.
3749 */
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07003750 use_loaded[pkg->index] = true;
3751 stdmacpos = pkg->macros;
H. Peter Anvin6686de22019-08-10 05:33:14 -07003752 nasm_new(inc);
3753 inc->next = istk;
3754 inc->fname = src_set_fname(NULL);
3755 inc->lineno = src_set_linnum(0);
H. Peter Anvin6686de22019-08-10 05:33:14 -07003756 inc->nolist = !list_option('b') || istk->nolist;
3757 istk = inc;
3758 lfmt->uplevel(LIST_INCLUDE, 0);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003759 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003760 break;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07003761 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003762 case PP_PUSH:
H. Peter Anvine2c80182005-01-15 22:15:51 +00003763 case PP_REPL:
H. Peter Anvin42b56392008-10-24 16:24:21 -07003764 case PP_POP:
H. Peter Anvine2c80182005-01-15 22:15:51 +00003765 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003766 tline = skip_white(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003767 tline = expand_id(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003768 if (tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003769 if (!tok_type(tline, TOK_ID)) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003770 nasm_nonfatal("`%s' expects a context identifier", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003771 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003772 }
3773 if (tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003774 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored",
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003775 dname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07003776 p = tok_text(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003777 } else {
3778 p = NULL; /* Anonymous */
3779 }
H. Peter Anvin42b56392008-10-24 16:24:21 -07003780
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003781 if (op == PP_PUSH) {
H. Peter Anvin (Intel)ebb05a02018-12-11 12:30:25 -08003782 nasm_new(ctx);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07003783 ctx->depth = cstk ? cstk->depth + 1 : 1;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003784 ctx->next = cstk;
H. Peter Anvin8571f062019-09-23 16:40:03 -07003785 ctx->name = p ? nasm_strdup(p) : NULL;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003786 ctx->number = unique++;
3787 cstk = ctx;
3788 } else {
3789 /* %pop or %repl */
3790 if (!cstk) {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003791 nasm_nonfatal("`%s': context stack is empty", dname);
3792 } else if (op == PP_POP) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003793 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003794 nasm_nonfatal("`%s' in wrong context: %s, "
H. Peter Anvin8b262472019-02-26 14:00:54 -08003795 "expected %s",
3796 dname, cstk->name ? cstk->name : "anonymous", p);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003797 else
3798 ctx_pop();
3799 } else {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003800 /* op == PP_REPL */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003801 nasm_free((char *)cstk->name);
3802 cstk->name = p ? nasm_strdup(p) : NULL;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003803 p = NULL;
3804 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003805 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003806 break;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07003807 case PP_FATAL:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003808 severity = ERR_FATAL;
3809 goto issue_error;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003810 case PP_ERROR:
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003811 severity = ERR_NONFATAL|ERR_PASS2;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003812 goto issue_error;
H. Peter Anvin7df04172008-06-10 18:27:38 -07003813 case PP_WARNING:
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -08003814 /*!
3815 *!user [on] %warning directives
3816 *! controls output of \c{%warning} directives (see \k{pperror}).
3817 */
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003818 severity = ERR_WARNING|WARN_USER|ERR_PASS2;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003819 goto issue_error;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07003820
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003821issue_error:
H. Peter Anvin7df04172008-06-10 18:27:38 -07003822 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003823 /* Only error out if this is the final pass */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003824 tline->next = expand_smacro(tline->next);
3825 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003826 tline = skip_white(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003827 t = tline ? tline->next : NULL;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07003828 t = skip_white(t);
3829 if (tok_type(tline, TOK_STRING) && !t) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003830 /* The line contains only a quoted string */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003831 p = unquote_token(tline); /* Ignore NUL character truncation */
H. Peter Anvin130736c2016-02-17 20:27:41 -08003832 nasm_error(severity, "%s", p);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003833 } else {
3834 /* Not a quoted string, or more than a quoted string */
H. Peter Anvin8571f062019-09-23 16:40:03 -07003835 q = detoken(tline, false);
3836 nasm_error(severity, "%s", q);
3837 nasm_free(q);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003838 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003839 break;
H. Peter Anvin7df04172008-06-10 18:27:38 -07003840 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003841
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00003842 CASE_PP_IF:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003843 if (istk->conds && !emitting(istk->conds->state))
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003844 j = COND_NEVER;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003845 else {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003846 j = if_condition(tline->next, op);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003847 tline->next = NULL; /* it got freed */
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003848 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003849 cond = nasm_malloc(sizeof(Cond));
3850 cond->next = istk->conds;
3851 cond->state = j;
3852 istk->conds = cond;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07003853 if(istk->mstk.mstk)
3854 istk->mstk.mstk->condcnt++;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003855 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003856
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00003857 CASE_PP_ELIF:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003858 if (!istk->conds)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07003859 nasm_fatal("`%s': no matching `%%if'", dname);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003860 switch(istk->conds->state) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003861 case COND_IF_TRUE:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003862 istk->conds->state = COND_DONE;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003863 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003864
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003865 case COND_DONE:
3866 case COND_NEVER:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003867 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003868
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003869 case COND_ELSE_TRUE:
3870 case COND_ELSE_FALSE:
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003871 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003872 "`%%elif' after `%%else' ignored");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003873 istk->conds->state = COND_NEVER;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003874 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003875
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003876 case COND_IF_FALSE:
3877 /*
3878 * IMPORTANT: In the case of %if, we will already have
3879 * called expand_mmac_params(); however, if we're
3880 * processing an %elif we must have been in a
3881 * non-emitting mode, which would have inhibited
3882 * the normal invocation of expand_mmac_params().
3883 * Therefore, we have to do it explicitly here.
3884 */
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003885 j = if_condition(expand_mmac_params(tline->next), op);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003886 tline->next = NULL; /* it got freed */
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003887 istk->conds->state = j;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003888 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003889 }
H. Peter Anvin (Intel)97cbdd32019-08-15 01:14:23 -07003890 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003891
H. Peter Anvine2c80182005-01-15 22:15:51 +00003892 case PP_ELSE:
3893 if (tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003894 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003895 "trailing garbage after `%%else' ignored");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003896 if (!istk->conds)
H. Peter Anvinc5136902018-06-15 18:20:17 -07003897 nasm_fatal("`%%else: no matching `%%if'");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003898 switch(istk->conds->state) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003899 case COND_IF_TRUE:
3900 case COND_DONE:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003901 istk->conds->state = COND_ELSE_FALSE;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003902 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003903
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003904 case COND_NEVER:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003905 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003906
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003907 case COND_IF_FALSE:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003908 istk->conds->state = COND_ELSE_TRUE;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003909 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003910
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003911 case COND_ELSE_TRUE:
3912 case COND_ELSE_FALSE:
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003913 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003914 "`%%else' after `%%else' ignored.");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003915 istk->conds->state = COND_NEVER;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003916 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02003917 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003918 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003919
H. Peter Anvine2c80182005-01-15 22:15:51 +00003920 case PP_ENDIF:
3921 if (tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003922 nasm_warn(WARN_OTHER|ERR_PP_PRECOND,
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003923 "trailing garbage after `%%endif' ignored");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003924 if (!istk->conds)
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003925 nasm_fatal("`%%endif': no matching `%%if'");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003926 cond = istk->conds;
3927 istk->conds = cond->next;
3928 nasm_free(cond);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07003929 if(istk->mstk.mstk)
3930 istk->mstk.mstk->condcnt--;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003931 break;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003932
H. Peter Anvin8b262472019-02-26 14:00:54 -08003933 case PP_RMACRO:
3934 case PP_MACRO:
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07003935 {
3936 MMacro *def;
3937
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07003938 nasm_assert(!defining);
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07003939 nasm_new(def);
3940 def->casesense = casesense;
3941 def->dstk.mmac = defining;
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07003942 if (op == PP_RMACRO)
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07003943 def->max_depth = nasm_limit[LIMIT_MACRO_LEVELS];
3944 if (!parse_mmacro_spec(tline, def, dname)) {
3945 nasm_free(def);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003946 goto done;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003947 }
H. Peter Anvina26433d2008-07-16 14:40:01 -07003948
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07003949 defining = def;
H. Peter Anvin4def1a82016-05-09 13:59:44 -07003950 src_get(&defining->xline, &defining->fname);
3951
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003952 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
3953 while (mmac) {
3954 if (!strcmp(mmac->name, defining->name) &&
3955 (mmac->nparam_min <= defining->nparam_max
3956 || defining->plus)
3957 && (defining->nparam_min <= mmac->nparam_max
3958 || mmac->plus)) {
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08003959 nasm_warn(WARN_OTHER, "redefining multi-line macro `%s'",
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03003960 defining->name);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003961 break;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003962 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003963 mmac = mmac->next;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003964 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003965 break;
H. Peter Anvin (Intel)7cfd0182020-06-01 12:04:35 -07003966 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003967
H. Peter Anvine2c80182005-01-15 22:15:51 +00003968 case PP_ENDM:
3969 case PP_ENDMACRO:
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003970 if (!(defining && defining->name)) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07003971 nasm_nonfatal("`%s': not defining a macro", tok_text(tline));
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003972 goto done;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003973 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003974 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
3975 defining->next = *mmhead;
3976 *mmhead = defining;
3977 defining = NULL;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07003978 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003979
H. Peter Anvin89cee572009-07-15 09:16:54 -04003980 case PP_EXITMACRO:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003981 /*
3982 * We must search along istk->expansion until we hit a
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003983 * macro-end marker for a macro with a name. Then we
3984 * bypass all lines between exitmacro and endmacro.
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003985 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003986 list_for_each(l, istk->expansion)
3987 if (l->finishes && l->finishes->name)
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003988 break;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003989
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003990 if (l) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003991 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003992 * Remove all conditional entries relative to this
3993 * macro invocation. (safe to do in this context)
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003994 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003995 for ( ; l->finishes->condcnt > 0; l->finishes->condcnt --) {
3996 cond = istk->conds;
3997 istk->conds = cond->next;
3998 nasm_free(cond);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003999 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004000 istk->expansion = l;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004001 } else {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004002 nasm_nonfatal("`%%exitmacro' not within `%%macro' block");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004003 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004004 break;
Keith Kanios852f1ee2009-07-12 00:19:55 -05004005
H. Peter Anvina26433d2008-07-16 14:40:01 -07004006 case PP_UNIMACRO:
H. Peter Anvin8b262472019-02-26 14:00:54 -08004007 casesense = false;
4008 /* fall through */
4009 case PP_UNMACRO:
H. Peter Anvina26433d2008-07-16 14:40:01 -07004010 {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004011 MMacro **mmac_p;
4012 MMacro spec;
H. Peter Anvina26433d2008-07-16 14:40:01 -07004013
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004014 nasm_zero(spec);
H. Peter Anvin8b262472019-02-26 14:00:54 -08004015 spec.casesense = casesense;
4016 if (!parse_mmacro_spec(tline, &spec, dname)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004017 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004018 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004019 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
4020 while (mmac_p && *mmac_p) {
4021 mmac = *mmac_p;
4022 if (mmac->casesense == spec.casesense &&
4023 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
4024 mmac->nparam_min == spec.nparam_min &&
4025 mmac->nparam_max == spec.nparam_max &&
4026 mmac->plus == spec.plus) {
4027 *mmac_p = mmac->next;
4028 free_mmacro(mmac);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004029 } else {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004030 mmac_p = &mmac->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004031 }
4032 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004033 free_tlist(spec.dlist);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004034 break;
H. Peter Anvina26433d2008-07-16 14:40:01 -07004035 }
4036
H. Peter Anvine2c80182005-01-15 22:15:51 +00004037 case PP_ROTATE:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004038 while (tok_white(tline->next))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004039 tline = tline->next;
H. Peter Anvin89cee572009-07-15 09:16:54 -04004040 if (!tline->next) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004041 free_tlist(origline);
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004042 nasm_nonfatal("`%%rotate' missing rotate count");
H. Peter Anvine2c80182005-01-15 22:15:51 +00004043 return DIRECTIVE_FOUND;
4044 }
4045 t = expand_smacro(tline->next);
4046 tline->next = NULL;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004047 pps.tptr = tline = t;
4048 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004049 tokval.t_type = TOKEN_INVALID;
4050 evalresult =
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004051 evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004052 free_tlist(tline);
4053 if (!evalresult)
4054 return DIRECTIVE_FOUND;
4055 if (tokval.t_type)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08004056 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00004057 if (!is_simple(evalresult)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004058 nasm_nonfatal("non-constant value given to `%%rotate'");
H. Peter Anvine2c80182005-01-15 22:15:51 +00004059 return DIRECTIVE_FOUND;
4060 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004061 mmac = istk->mstk.mmac;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004062 if (!mmac) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004063 nasm_nonfatal("`%%rotate' invoked outside a macro call");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004064 } else if (mmac->nparam == 0) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004065 nasm_nonfatal("`%%rotate' invoked within macro without parameters");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004066 } else {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004067 int rotate = mmac->rotate + reloc_value(evalresult);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004068
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004069 rotate %= (int)mmac->nparam;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004070 if (rotate < 0)
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004071 rotate += mmac->nparam;
4072
4073 mmac->rotate = rotate;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004074 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004075 break;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00004076
H. Peter Anvine2c80182005-01-15 22:15:51 +00004077 case PP_REP:
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004078 {
4079 MMacro *tmp_defining;
4080
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004081 nolist = false;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004082 tline = skip_white(tline->next);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004083 if (tok_type(tline, TOK_ID) && tline->len == 7 &&
4084 !nasm_memicmp(tline->text.a, ".nolist", 7)) {
H. Peter Anvin6686de22019-08-10 05:33:14 -07004085 nolist = !list_option('f') || istk->nolist;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004086 tline = skip_white(tline->next);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004087 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00004088
H. Peter Anvine2c80182005-01-15 22:15:51 +00004089 if (tline) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08004090 pps.tptr = expand_smacro(tline);
4091 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004092 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004093 /* XXX: really critical?! */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004094 evalresult =
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004095 evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004096 if (!evalresult)
4097 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004098 if (tokval.t_type)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08004099 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00004100 if (!is_simple(evalresult)) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004101 nasm_nonfatal("non-constant value given to `%%rep'");
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004102 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004103 }
Cyrill Gorcunove091d6e2010-08-09 13:58:22 +04004104 count = reloc_value(evalresult);
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07004105 if (count > nasm_limit[LIMIT_REP]) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004106 nasm_nonfatal("`%%rep' count %"PRId64" exceeds limit (currently %"PRId64")",
4107 count, nasm_limit[LIMIT_REP]);
Cyrill Gorcunove091d6e2010-08-09 13:58:22 +04004108 count = 0;
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07004109 } else if (count < 0) {
H. Peter Anvin (Intel)723ab482018-12-13 21:53:31 -08004110 /*!
4111 *!negative-rep [on] regative %rep count
4112 *! warns about negative counts given to the \c{%rep}
4113 *! preprocessor directive.
4114 */
H. Peter Anvin (Intel)80c4f232018-12-14 13:33:24 -08004115 nasm_warn(ERR_PASS2|WARN_NEGATIVE_REP,
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07004116 "negative `%%rep' count: %"PRId64, count);
4117 count = 0;
4118 } else {
Cyrill Gorcunove091d6e2010-08-09 13:58:22 +04004119 count++;
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07004120 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004121 } else {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004122 nasm_nonfatal("`%%rep' expects a repeat count");
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07004123 count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004124 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004125 tmp_defining = defining;
H. Peter Anvinab6f8312019-08-09 22:31:45 -07004126 nasm_new(defining);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004127 defining->nolist = nolist;
4128 defining->in_progress = count;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004129 defining->mstk = istk->mstk;
4130 defining->dstk.mstk = tmp_defining;
4131 defining->dstk.mmac = tmp_defining ? tmp_defining->dstk.mmac : NULL;
H. Peter Anvinab6f8312019-08-09 22:31:45 -07004132 src_get(&defining->xline, &defining->fname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004133 break;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004134 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004135
H. Peter Anvine2c80182005-01-15 22:15:51 +00004136 case PP_ENDREP:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004137 if (!defining || defining->name) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004138 nasm_nonfatal("`%%endrep': no matching `%%rep'");
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004139 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004140 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004141
H. Peter Anvine2c80182005-01-15 22:15:51 +00004142 /*
4143 * Now we have a "macro" defined - although it has no name
4144 * and we won't be entering it in the hash tables - we must
4145 * push a macro-end marker for it on to istk->expansion.
4146 * After that, it will take care of propagating itself (a
4147 * macro-end marker line for a macro which is really a %rep
4148 * block will cause the macro to be re-expanded, complete
4149 * with another macro-end marker to ensure the process
4150 * continues) until the whole expansion is forcibly removed
4151 * from istk->expansion by a %exitrep.
4152 */
H. Peter Anvin6686de22019-08-10 05:33:14 -07004153 nasm_new(l);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004154 l->next = istk->expansion;
4155 l->finishes = defining;
4156 l->first = NULL;
4157 istk->expansion = l;
4158
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004159 istk->mstk.mstk = defining;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004160
H. Peter Anvin0d4d4312019-08-07 00:46:27 -07004161 lfmt->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004162 defining = defining->dstk.mstk;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004163 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004164
H. Peter Anvine2c80182005-01-15 22:15:51 +00004165 case PP_EXITREP:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004166 /*
4167 * We must search along istk->expansion until we hit a
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004168 * macro-end marker for a macro with no name. Then we set
4169 * its `in_progress' flag to 0.
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004170 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004171 list_for_each(l, istk->expansion)
4172 if (l->finishes && !l->finishes->name)
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004173 break;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004174
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004175 if (l)
H. Peter Anvind983b622019-10-07 21:19:32 -07004176 l->finishes->in_progress = 0;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004177 else
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004178 nasm_nonfatal("`%%exitrep' not within `%%rep' block");
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004179 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004180
H. Peter Anvin8b262472019-02-26 14:00:54 -08004181 case PP_DEFINE:
4182 case PP_XDEFINE:
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004183 case PP_DEFALIAS:
H. Peter Anvin8b262472019-02-26 14:00:54 -08004184 {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004185 SMacro tmpl;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07004186 Token **lastp;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07004187 int nparam;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07004188
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004189 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004190 goto done;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004191
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004192 nasm_zero(tmpl);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07004193 lastp = &tline->next;
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07004194 nparam = parse_smacro_template(&lastp, &tmpl);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07004195 tline = *lastp;
4196 *lastp = NULL;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004197
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004198 if (unlikely(op == PP_DEFALIAS)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004199 macro_start = tline;
4200 if (!is_macro_id(macro_start)) {
4201 nasm_nonfatal("`%s' expects a macro identifier to alias",
4202 dname);
4203 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004204 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004205 tt = macro_start->next;
4206 macro_start->next = NULL;
4207 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004208 tline = skip_white(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004209 if (tline && tline->type) {
4210 nasm_warn(WARN_OTHER,
4211 "trailing garbage after aliasing identifier ignored");
4212 }
4213 free_tlist(tt);
4214 tmpl.alias = true;
4215 } else {
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004216 if (op == PP_XDEFINE) {
4217 /* Protect macro parameter tokens */
H. Peter Anvin (Intel)e91f5cc2019-10-23 12:59:06 -07004218 if (nparam)
4219 mark_smac_params(tline, &tmpl, TOK_XDEF_PARAM);
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004220 tline = expand_smacro(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004221 }
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004222 /* NB: Does this still make sense? */
4223 macro_start = reverse_tokens(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004224 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004225
H. Peter Anvine2c80182005-01-15 22:15:51 +00004226 /*
4227 * Good. We now have a macro name, a parameter count, and a
4228 * token list (in reverse order) for an expansion. We ought
4229 * to be OK just to create an SMacro, store it, and let
4230 * free_tlist have the rest of the line (which we have
4231 * carefully re-terminated after chopping off the expansion
4232 * from the end).
4233 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004234 define_smacro(mname, casesense, macro_start, &tmpl);
4235 break;
4236 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004237
H. Peter Anvine2c80182005-01-15 22:15:51 +00004238 case PP_UNDEF:
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004239 case PP_UNDEFALIAS:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004240 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004241 goto done;
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004242 if (tline->next)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08004243 nasm_warn(WARN_OTHER, "trailing garbage after macro name ignored");
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004244
H. Peter Anvin (Intel)4b58ec12019-10-23 12:00:50 -07004245 undef_smacro(mname, op == PP_UNDEFALIAS);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004246 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004247
H. Peter Anvin8b262472019-02-26 14:00:54 -08004248 case PP_DEFSTR:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004249 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004250 goto done;
H. Peter Anvin9e200162008-06-04 17:23:14 -07004251
H. Peter Anvin9e200162008-06-04 17:23:14 -07004252 last = tline;
4253 tline = expand_smacro(tline->next);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004254 last->next = NULL;
H. Peter Anvin9e200162008-06-04 17:23:14 -07004255
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004256 tline = zap_white(tline);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004257 q = detoken(tline, false);
4258 macro_start = make_tok_qstr(NULL, q);
4259 nasm_free(q);
H. Peter Anvin9e200162008-06-04 17:23:14 -07004260
4261 /*
4262 * We now have a macro name, an implicit parameter count of
4263 * zero, and a string token to use as an expansion. Create
4264 * and store an SMacro.
4265 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004266 define_smacro(mname, casesense, macro_start, NULL);
4267 break;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004268
H. Peter Anvin8b262472019-02-26 14:00:54 -08004269 case PP_DEFTOK:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004270 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004271 goto done;
4272
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004273 last = tline;
4274 tline = expand_smacro(tline->next);
4275 last->next = NULL;
4276
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004277 t = skip_white(tline);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004278 /* t should now point to the string */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004279 if (!tok_type(t, TOK_STRING)) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004280 nasm_nonfatal("`%s' requires string as second parameter", dname);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004281 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004282 goto done;
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004283 }
4284
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04004285 /*
4286 * Convert the string to a token stream. Note that smacros
4287 * are stored with the token stream reversed, so we have to
4288 * reverse the output of tokenize().
4289 */
H. Peter Anvin8571f062019-09-23 16:40:03 -07004290 macro_start = reverse_tokens(tokenize(unquote_token_cstr(t)));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004291
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004292 /*
4293 * We now have a macro name, an implicit parameter count of
4294 * zero, and a numeric token to use as an expansion. Create
4295 * and store an SMacro.
4296 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004297 define_smacro(mname, casesense, macro_start, NULL);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05004298 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004299 break;
H. Peter Anvin9e200162008-06-04 17:23:14 -07004300
H. Peter Anvin418ca702008-05-30 10:42:30 -07004301 case PP_PATHSEARCH:
4302 {
H. Peter Anvinccad6f92016-10-04 00:34:35 -07004303 const char *found_path;
H. Peter Anvin418ca702008-05-30 10:42:30 -07004304
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004305 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004306 goto done;
4307
H. Peter Anvin418ca702008-05-30 10:42:30 -07004308 last = tline;
4309 tline = expand_smacro(tline->next);
4310 last->next = NULL;
4311
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004312 t = skip_white(tline);
H. Peter Anvin418ca702008-05-30 10:42:30 -07004313 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004314 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004315 nasm_nonfatal("`%s' expects a file name", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004316 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004317 goto done;
H. Peter Anvin418ca702008-05-30 10:42:30 -07004318 }
4319 if (t->next)
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004320 nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004321
4322 p = unquote_token_cstr(t);
H. Peter Anvin418ca702008-05-30 10:42:30 -07004323
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07004324 inc_fopen(p, NULL, &found_path, INC_PROBE, NF_BINARY);
H. Peter Anvinccad6f92016-10-04 00:34:35 -07004325 if (!found_path)
4326 found_path = p;
H. Peter Anvin8571f062019-09-23 16:40:03 -07004327 macro_start = make_tok_qstr(NULL, found_path);
H. Peter Anvin418ca702008-05-30 10:42:30 -07004328
4329 /*
4330 * We now have a macro name, an implicit parameter count of
4331 * zero, and a string token to use as an expansion. Create
4332 * and store an SMacro.
4333 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004334 define_smacro(mname, casesense, macro_start, NULL);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004335 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004336 break;
H. Peter Anvin418ca702008-05-30 10:42:30 -07004337 }
4338
H. Peter Anvine2c80182005-01-15 22:15:51 +00004339 case PP_STRLEN:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004340 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004341 goto done;
4342
H. Peter Anvine2c80182005-01-15 22:15:51 +00004343 last = tline;
4344 tline = expand_smacro(tline->next);
4345 last->next = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004346
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004347 t = skip_white(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004348 /* t should now point to the string */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004349 if (!tok_type(t, TOK_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004350 nasm_nonfatal("`%s' requires string as second parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004351 free_tlist(tline);
4352 free_tlist(origline);
4353 return DIRECTIVE_FOUND;
4354 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004355
H. Peter Anvin8571f062019-09-23 16:40:03 -07004356 unquote_token(t);
4357 macro_start = make_tok_num(NULL, t->len);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004358
H. Peter Anvine2c80182005-01-15 22:15:51 +00004359 /*
4360 * We now have a macro name, an implicit parameter count of
4361 * zero, and a numeric token to use as an expansion. Create
4362 * and store an SMacro.
4363 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004364 define_smacro(mname, casesense, macro_start, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004365 free_tlist(tline);
4366 free_tlist(origline);
4367 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004368
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004369 case PP_STRCAT:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004370 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004371 goto done;
4372
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004373 last = tline;
4374 tline = expand_smacro(tline->next);
4375 last->next = NULL;
4376
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004377 len = 0;
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04004378 list_for_each(t, tline) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004379 switch (t->type) {
4380 case TOK_WHITESPACE:
4381 break;
4382 case TOK_STRING:
H. Peter Anvin8571f062019-09-23 16:40:03 -07004383 unquote_token(t);
4384 len += t->len;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004385 break;
4386 case TOK_OTHER:
H. Peter Anvin8571f062019-09-23 16:40:03 -07004387 if (tok_is(t, ',')) /* permit comma separators */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004388 break;
4389 /* else fall through */
4390 default:
H. Peter Anvin8571f062019-09-23 16:40:03 -07004391 nasm_nonfatal("non-string passed to `%s': %s", dname,
4392 tok_text(t));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004393 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004394 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004395 }
4396 }
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004397
H. Peter Anvin (Intel)f770ce82019-10-17 18:22:43 -07004398 q = qbuf = nasm_malloc(len+1);
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04004399 list_for_each(t, tline) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004400 if (t->type == TOK_INTERNAL_STRING)
4401 q = mempcpy(q, tok_text(t), t->len);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004402 }
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07004403 *q = '\0';
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004404
4405 /*
4406 * We now have a macro name, an implicit parameter count of
4407 * zero, and a numeric token to use as an expansion. Create
4408 * and store an SMacro.
4409 */
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07004410 macro_start = make_tok_qstr_len(NULL, qbuf, len);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004411 nasm_free(qbuf);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004412 define_smacro(mname, casesense, macro_start, NULL);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004413 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004414 break;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004415
H. Peter Anvine2c80182005-01-15 22:15:51 +00004416 case PP_SUBSTR:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004417 {
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004418 int64_t start, count;
H. Peter Anvin8571f062019-09-23 16:40:03 -07004419 const char *txt;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004420 size_t len;
H. Peter Anvind2456592008-06-19 15:04:18 -07004421
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004422 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004423 goto done;
4424
H. Peter Anvine2c80182005-01-15 22:15:51 +00004425 last = tline;
4426 tline = expand_smacro(tline->next);
4427 last->next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004428
Cyrill Gorcunov35519d62010-09-06 23:49:52 +04004429 if (tline) /* skip expanded id */
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004430 t = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004431
4432 t = skip_white(t);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004433
H. Peter Anvine2c80182005-01-15 22:15:51 +00004434 /* t should now point to the string */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004435 if (!tok_type(t, TOK_STRING)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004436 nasm_nonfatal("`%s' requires string as second parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004437 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004438 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004439 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004440
H. Peter Anvin8b262472019-02-26 14:00:54 -08004441 pps.tptr = t->next;
4442 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004443 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004444 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004445 if (!evalresult) {
4446 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004447 goto done;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004448 } else if (!is_simple(evalresult)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004449 nasm_nonfatal("non-constant value given to `%s'", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004450 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004451 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004452 }
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004453 start = evalresult->value - 1;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004454
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004455 pps.tptr = skip_white(pps.tptr);
H. Peter Anvin8b262472019-02-26 14:00:54 -08004456 if (!pps.tptr) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004457 count = 1; /* Backwards compatibility: one character */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004458 } else {
4459 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004460 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004461 if (!evalresult) {
4462 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004463 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004464 } else if (!is_simple(evalresult)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004465 nasm_nonfatal("non-constant value given to `%s'", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004466 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004467 goto done;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004468 }
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004469 count = evalresult->value;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004470 }
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004471
H. Peter Anvin8571f062019-09-23 16:40:03 -07004472 unquote_token(t);
4473 len = t->len;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004474
Cyrill Gorcunovcff031e2010-09-07 20:31:11 +04004475 /* make start and count being in range */
4476 if (start < 0)
4477 start = 0;
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004478 if (count < 0)
4479 count = len + count + 1 - start;
4480 if (start + count > (int64_t)len)
Cyrill Gorcunovcff031e2010-09-07 20:31:11 +04004481 count = len - start;
4482 if (!len || count < 0 || start >=(int64_t)len)
Cyrill Gorcunovab122872010-09-07 10:42:02 +04004483 start = -1, count = 0; /* empty string */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00004484
H. Peter Anvin8571f062019-09-23 16:40:03 -07004485 txt = (start < 0) ? "" : tok_text(t) + start;
4486 len = count;
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07004487 macro_start = make_tok_qstr_len(NULL, txt, len);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004488
H. Peter Anvine2c80182005-01-15 22:15:51 +00004489 /*
4490 * We now have a macro name, an implicit parameter count of
4491 * zero, and a numeric token to use as an expansion. Create
4492 * and store an SMacro.
4493 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004494 define_smacro(mname, casesense, macro_start, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004495 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004496 break;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07004497 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004498
H. Peter Anvin8b262472019-02-26 14:00:54 -08004499 case PP_ASSIGN:
H. Peter Anvina039fcd2019-09-12 19:27:42 -07004500 if (!(mname = get_id(&tline, dname)))
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004501 goto done;
4502
H. Peter Anvine2c80182005-01-15 22:15:51 +00004503 last = tline;
4504 tline = expand_smacro(tline->next);
4505 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004506
H. Peter Anvin8b262472019-02-26 14:00:54 -08004507 pps.tptr = tline;
4508 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004509 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004510 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004511 free_tlist(tline);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004512 if (!evalresult)
4513 goto done;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004514
H. Peter Anvine2c80182005-01-15 22:15:51 +00004515 if (tokval.t_type)
H. Peter Anvin (Intel)5df6ca72018-12-18 12:25:11 -08004516 nasm_warn(WARN_OTHER, "trailing garbage after expression ignored");
H. Peter Anvin734b1882002-04-30 21:01:08 +00004517
H. Peter Anvine2c80182005-01-15 22:15:51 +00004518 if (!is_simple(evalresult)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004519 nasm_nonfatal("non-constant value given to `%s'", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004520 free_tlist(origline);
4521 return DIRECTIVE_FOUND;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004522 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004523
H. Peter Anvin8571f062019-09-23 16:40:03 -07004524 macro_start = make_tok_num(NULL, reloc_value(evalresult));
H. Peter Anvin734b1882002-04-30 21:01:08 +00004525
H. Peter Anvine2c80182005-01-15 22:15:51 +00004526 /*
4527 * We now have a macro name, an implicit parameter count of
4528 * zero, and a numeric token to use as an expansion. Create
4529 * and store an SMacro.
4530 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004531 define_smacro(mname, casesense, macro_start, NULL);
4532 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004533
H. Peter Anvind2354082019-08-27 16:38:48 -07004534 case PP_ALIASES:
4535 tline = tline->next;
4536 tline = expand_smacro(tline);
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07004537 ppopt.noaliases = !pp_get_boolean_option(tline, !ppopt.noaliases);
H. Peter Anvind2354082019-08-27 16:38:48 -07004538 break;
4539
H. Peter Anvine2c80182005-01-15 22:15:51 +00004540 case PP_LINE:
4541 /*
4542 * Syntax is `%line nnn[+mmm] [filename]'
4543 */
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004544 if (unlikely(pp_noline))
4545 goto done;
4546
H. Peter Anvine2c80182005-01-15 22:15:51 +00004547 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004548 tline = skip_white(tline);
4549 if (!tok_type(tline, TOK_NUMBER)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004550 nasm_nonfatal("`%s' expects line number", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004551 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004552 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07004553 k = readnum(tok_text(tline), &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004554 m = 1;
4555 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004556 if (tok_is(tline, '+')) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004557 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004558 if (!tok_type(tline, TOK_NUMBER)) {
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07004559 nasm_nonfatal("`%s' expects line increment", dname);
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004560 goto done;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004561 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07004562 m = readnum(tok_text(tline), &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004563 tline = tline->next;
4564 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004565 tline = skip_white(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004566 src_set_linnum(k);
4567 istk->lineinc = m;
4568 if (tline) {
H. Peter Anvin274cda82016-05-10 02:56:29 -07004569 char *fname = detoken(tline, false);
4570 src_set_fname(fname);
4571 nasm_free(fname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004572 }
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07004573 break;
4574 }
4575
4576done:
H. Peter Anvine2c80182005-01-15 22:15:51 +00004577 free_tlist(origline);
4578 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004579}
4580
4581/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00004582 * Ensure that a macro parameter contains a condition code and
4583 * nothing else. Return the condition code index if so, or -1
4584 * otherwise.
4585 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004586static int find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004587{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004588 Token *tt;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004589
H. Peter Anvin25a99342007-09-22 17:45:45 -07004590 if (!t)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004591 return -1; /* Probably a %+ without a space */
H. Peter Anvin25a99342007-09-22 17:45:45 -07004592
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004593 t = skip_white(t);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004594 if (!tok_type(t, TOK_ID))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004595 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004596 tt = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004597 tt = skip_white(tt);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004598 if (tok_isnt(tt, ','))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004599 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004600
H. Peter Anvin8571f062019-09-23 16:40:03 -07004601 return bsii(tok_text(t), (const char **)conditions,
4602 ARRAY_SIZE(conditions));
H. Peter Anvin76690a12002-04-30 20:52:49 +00004603}
4604
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004605static inline bool pp_concat_match(const Token *t, unsigned int mask)
4606{
4607 return t && (PP_CONCAT_MASK(t->type) & mask);
4608}
4609
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004610/*
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07004611 * This routines walks over tokens strem and handles tokens
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004612 * pasting, if @handle_explicit passed then explicit pasting
4613 * term is handled, otherwise -- implicit pastings only.
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07004614 * The @m array can contain a series of token types which are
4615 * executed as separate passes.
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004616 */
Cyrill Gorcunov575d4282010-10-06 00:25:55 +04004617static bool paste_tokens(Token **head, const struct tokseq_match *m,
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004618 size_t mnum, bool handle_explicit)
H. Peter Anvind784a082009-04-20 14:01:18 -07004619{
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004620 Token *tok, *t, *next, **prev_next, **prev_nonspace;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004621 bool pasted = false;
4622 char *buf, *p;
4623 size_t len, i;
H. Peter Anvind784a082009-04-20 14:01:18 -07004624
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004625 /*
4626 * The last token before pasting. We need it
4627 * to be able to connect new handled tokens.
4628 * In other words if there were a tokens stream
4629 *
4630 * A -> B -> C -> D
4631 *
4632 * and we've joined tokens B and C, the resulting
4633 * stream should be
4634 *
4635 * A -> BC -> D
4636 */
4637 tok = *head;
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004638 prev_next = prev_nonspace = head;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004639
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004640 if (tok_white(tok) || tok_type(tok, TOK_PASTE))
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004641 prev_nonspace = NULL;
4642
4643 while (tok && (next = tok->next)) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004644 bool did_paste = false;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004645
4646 switch (tok->type) {
H. Peter Anvind784a082009-04-20 14:01:18 -07004647 case TOK_WHITESPACE:
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004648 /* Zap redundant whitespaces */
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004649 tok->next = next = zap_white(next);
H. Peter Anvind784a082009-04-20 14:01:18 -07004650 break;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004651
4652 case TOK_PASTE:
4653 /* Explicit pasting */
4654 if (!handle_explicit)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004655 break;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004656
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004657 /* Left pasting token is start of line */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004658 if (!prev_nonspace) {
4659 nasm_nonfatal("No lvalue found on pasting");
4660 tok = delete_Token(tok);
4661 break;
4662 }
4663
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004664 did_paste = true;
4665
4666 prev_next = prev_nonspace;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004667 t = *prev_nonspace;
4668
4669 /* Delete leading whitespace */
4670 next = zap_white(t->next);
4671
4672 /* Delete the %+ token itself */
4673 nasm_assert(next == tok);
4674 next = delete_Token(next);
4675
4676 /* Delete trailing whitespace */
4677 next = zap_white(next);
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004678
Cyrill Gorcunov8b5c9fb2013-02-04 01:24:54 +04004679 /*
4680 * No ending token, this might happen in two
4681 * cases
4682 *
4683 * 1) There indeed no right token at all
4684 * 2) There is a bare "%define ID" statement,
4685 * and @ID does expand to whitespace.
4686 *
4687 * So technically we need to do a grammar analysis
4688 * in another stage of parsing, but for now lets don't
4689 * change the behaviour people used to. Simply allow
4690 * whitespace after paste token.
4691 */
4692 if (!next) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004693 *prev_nonspace = tok = NULL; /* End of line */
Cyrill Gorcunov8b5c9fb2013-02-04 01:24:54 +04004694 break;
4695 }
4696
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004697 p = buf = nasm_malloc(t->len + next->len + 1);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004698 p = mempcpy(p, tok_text(t), t->len);
4699 p = mempcpy(p, tok_text(next), next->len);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004700 *p = '\0';
4701 delete_Token(t);
4702 t = tokenize(buf);
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004703 nasm_free(buf);
4704
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004705 if (unlikely(!t)) {
4706 /*
4707 * No output at all? Replace with a single whitespace.
4708 * This should never happen.
4709 */
4710 t = new_White(NULL);
4711 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004712
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004713 *prev_nonspace = tok = t;
4714 while (t->next)
4715 t = t->next; /* Find the last token produced */
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004716
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004717 /* Delete the second token and attach to the end of the list */
4718 t->next = delete_Token(next);
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004719
4720 /* We want to restart from the head of the pasted token */
4721 next = tok;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004722 break;
4723
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004724 default:
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004725 /* implicit pasting */
Cyrill Gorcunov575d4282010-10-06 00:25:55 +04004726 for (i = 0; i < mnum; i++) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004727 if (pp_concat_match(tok, m[i].mask_head))
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004728 break;
Cyrill Gorcunov575d4282010-10-06 00:25:55 +04004729 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004730
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004731 if (i >= mnum)
4732 break;
4733
4734 len = tok->len;
4735 while (pp_concat_match(next, m[i].mask_tail)) {
4736 len += next->len;
4737 next = next->next;
4738 }
4739
4740 /* No match or no text to process */
4741 if (len == tok->len)
4742 break;
4743
4744 p = buf = nasm_malloc(len + 1);
4745 while (tok != next) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004746 p = mempcpy(p, tok_text(tok), tok->len);
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004747 tok = delete_Token(tok);
4748 }
4749 *p = '\0';
4750 *prev_next = tok = t = tokenize(buf);
4751 nasm_free(buf);
4752
4753 /*
4754 * Connect pasted into original stream,
4755 * ie A -> new-tokens -> B
4756 */
4757 while (t->next)
4758 t = t->next;
4759 t->next = next;
4760 prev_next = prev_nonspace = &t->next;
4761 did_paste = true;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004762 break;
H. Peter Anvind784a082009-04-20 14:01:18 -07004763 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004764
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004765 if (did_paste) {
4766 pasted = true;
4767 } else {
4768 prev_next = &tok->next;
4769 if (next && next->type != TOK_WHITESPACE && next->type != TOK_PASTE)
4770 prev_nonspace = prev_next;
4771 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004772
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07004773 tok = next;
H. Peter Anvind784a082009-04-20 14:01:18 -07004774 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04004775
4776 return pasted;
H. Peter Anvind784a082009-04-20 14:01:18 -07004777}
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004778
4779/*
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004780 * Computes the proper rotation of mmacro parameters
4781 */
4782static int mmac_rotate(const MMacro *mac, unsigned int n)
4783{
4784 if (--n < mac->nparam)
4785 n = (n + mac->rotate) % mac->nparam;
4786
4787 return n+1;
4788}
4789
4790/*
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004791 * expands to a list of tokens from %{x:y}
4792 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004793static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004794{
4795 Token *t = tline, **tt, *tm, *head;
4796 char *pos;
4797 int fst, lst, j, i;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004798
H. Peter Anvin8571f062019-09-23 16:40:03 -07004799 pos = strchr(tok_text(tline), ':');
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004800 nasm_assert(pos);
4801
4802 lst = atoi(pos + 1);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004803 fst = atoi(tok_text(tline) + 1);
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004804
4805 /*
4806 * only macros params are accounted so
4807 * if someone passes %0 -- we reject such
4808 * value(s)
4809 */
4810 if (lst == 0 || fst == 0)
4811 goto err;
4812
4813 /* the values should be sane */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004814 if ((fst > (int)mac->nparam || fst < (-(int)mac->nparam)) ||
4815 (lst > (int)mac->nparam || lst < (-(int)mac->nparam)))
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004816 goto err;
4817
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004818 fst = fst < 0 ? fst + (int)mac->nparam + 1: fst;
4819 lst = lst < 0 ? lst + (int)mac->nparam + 1: lst;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004820
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004821 /* count from zero */
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004822 fst--, lst--;
4823
4824 /*
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004825 * It will be at least one token. Note we
4826 * need to scan params until separator, otherwise
4827 * only first token will be passed.
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004828 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004829 j = (fst + mac->rotate) % mac->nparam;
4830 tm = mac->params[j+1];
Cyrill Gorcunov67f2ca22018-10-13 19:41:01 +03004831 if (!tm)
4832 goto err;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07004833 head = dup_Token(NULL, tm);
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004834 tt = &head->next, tm = tm->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004835 while (tok_isnt(tm, ',')) {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07004836 t = dup_Token(NULL, tm);
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004837 *tt = t, tt = &t->next, tm = tm->next;
4838 }
4839
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004840 if (fst < lst) {
4841 for (i = fst + 1; i <= lst; i++) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004842 t = make_tok_char(NULL, ',');
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004843 *tt = t, tt = &t->next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004844 j = (i + mac->rotate) % mac->nparam;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004845 tm = mac->params[j+1];
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004846 while (tok_isnt(tm, ',')) {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07004847 t = dup_Token(NULL, tm);
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004848 *tt = t, tt = &t->next, tm = tm->next;
4849 }
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004850 }
4851 } else {
4852 for (i = fst - 1; i >= lst; i--) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004853 t = make_tok_char(NULL, ',');
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004854 *tt = t, tt = &t->next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004855 j = (i + mac->rotate) % mac->nparam;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004856 tm = mac->params[j+1];
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07004857 while (!tok_isnt(tm, ',')) {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07004858 t = dup_Token(NULL, tm);
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004859 *tt = t, tt = &t->next, tm = tm->next;
4860 }
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004861 }
4862 }
4863
4864 *last = tt;
4865 return head;
4866
4867err:
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03004868 nasm_nonfatal("`%%{%s}': macro parameters out of range",
H. Peter Anvin8571f062019-09-23 16:40:03 -07004869 tok_text(tline) + 1);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004870 return NULL;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004871}
4872
H. Peter Anvin76690a12002-04-30 20:52:49 +00004873/*
4874 * Expand MMacro-local things: parameter references (%0, %n, %+n,
H. Peter Anvin67c63722008-10-26 23:49:00 -07004875 * %-n) and MMacro-local identifiers (%%foo) as well as
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004876 * macro indirection (%[...]) and range (%{..:..}).
H. Peter Anvin76690a12002-04-30 20:52:49 +00004877 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004878static Token *expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004879{
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004880 Token **tail, *thead;
H. Peter Anvin6125b622009-04-08 14:02:25 -07004881 bool changed = false;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004882 MMacro *mac = istk->mstk.mmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004883
4884 tail = &thead;
4885 thead = NULL;
4886
H. Peter Anvine2c80182005-01-15 22:15:51 +00004887 while (tline) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004888 bool change;
H. Peter Anvin (Intel)a762cd42020-06-01 11:49:08 -07004889 bool err_not_mac = false;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004890 Token *t = tline;
H. Peter Anvin8571f062019-09-23 16:40:03 -07004891 const char *text = tok_text(t);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004892 int type = t->type;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004893
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004894 tline = tline->next;
4895 t->next = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004896
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004897 switch (type) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07004898 case TOK_LOCAL_SYMBOL:
H. Peter Anvin (Intel)a762cd42020-06-01 11:49:08 -07004899 change = true;
4900
4901 if (!mac) {
4902 err_not_mac = true;
4903 break;
4904 }
4905
H. Peter Anvin8571f062019-09-23 16:40:03 -07004906 type = TOK_ID;
4907 text = nasm_asprintf("..@%"PRIu64".%s", mac->unique, text+2);
H. Peter Anvin8571f062019-09-23 16:40:03 -07004908 break;
4909 case TOK_MMACRO_PARAM:
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004910 {
4911 Token *tt = NULL;
4912
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004913 change = true;
4914
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004915 if (!mac) {
H. Peter Anvin (Intel)a762cd42020-06-01 11:49:08 -07004916 err_not_mac = true;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004917 break;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004918 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004919
4920 if (strchr(text, ':')) {
4921 /*
4922 * seems we have a parameters range here
4923 */
4924 Token *head, **last;
4925 head = expand_mmac_params_range(mac, t, &last);
4926 if (head) {
4927 *tail = head;
4928 *last = tline;
4929 text = NULL;
4930 }
4931 break;
4932 }
4933
4934 switch (text[1]) {
4935 /*
4936 * We have to make a substitution of one of the
4937 * forms %1, %-1, %+1, %%foo, %0, %00.
4938 */
4939 case '0':
4940 if (!text[2]) {
4941 type = TOK_NUMBER;
4942 text = nasm_asprintf("%d", mac->nparam);
4943 break;
4944 }
4945 if (text[2] != '0' || text[3])
4946 goto invalid;
4947 /* a possible captured label == mac->params[0] */
4948 /* fall through */
4949 default:
4950 {
4951 unsigned long n;
4952 char *ep;
4953
4954 n = strtoul(text + 1, &ep, 10);
4955 if (unlikely(*ep))
4956 goto invalid;
4957
4958 if (n <= mac->nparam) {
4959 n = mmac_rotate(mac, n);
4960 dup_tlistn(mac->params[n], mac->paramlen[n], &tail);
4961 }
4962 text = NULL;
4963 break;
4964 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004965 case '-':
4966 case '+':
4967 {
4968 int cc;
4969 unsigned long n;
4970 char *ep;
4971
H. Peter Anvin8571f062019-09-23 16:40:03 -07004972 n = strtoul(tok_text(t) + 2, &ep, 10);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004973 if (unlikely(*ep))
4974 goto invalid;
4975
Chang S. Bae057b8322020-04-18 23:11:21 +00004976 if (n && n <= mac->nparam) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004977 n = mmac_rotate(mac, n);
4978 tt = mac->params[n];
4979 }
4980 cc = find_cc(tt);
4981 if (cc == -1) {
4982 nasm_nonfatal("macro parameter `%s' is not a condition code",
H. Peter Anvin8571f062019-09-23 16:40:03 -07004983 tok_text(t));
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07004984 text = NULL;
4985 break;
4986 }
4987
4988 type = TOK_ID;
4989 if (text[1] == '-') {
4990 int ncc = inverse_ccs[cc];
4991 if (unlikely(ncc == -1)) {
4992 nasm_nonfatal("condition code `%s' is not invertible",
4993 conditions[cc]);
4994 break;
4995 }
4996 cc = ncc;
4997 }
4998 text = nasm_strdup(conditions[cc]);
4999 break;
5000 }
5001
5002 invalid:
5003 nasm_nonfatal("invalid macro parameter: `%s'", text);
5004 text = NULL;
5005 break;
5006 }
5007 break;
5008 }
5009
5010 case TOK_PREPROC_Q:
5011 if (mac) {
5012 type = TOK_ID;
5013 text = nasm_strdup(mac->iname);
5014 change = true;
H. Peter Anvin (Intel)68075f82019-08-20 12:28:05 -07005015 } else {
5016 change = false;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005017 }
5018 break;
5019
5020 case TOK_PREPROC_QQ:
5021 if (mac) {
5022 type = TOK_ID;
5023 text = nasm_strdup(mac->name);
5024 change = true;
H. Peter Anvin (Intel)68075f82019-08-20 12:28:05 -07005025 } else {
5026 change = false;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005027 }
5028 break;
5029
5030 case TOK_INDIRECT:
5031 {
5032 Token *tt;
5033
H. Peter Anvin8571f062019-09-23 16:40:03 -07005034 tt = tokenize(tok_text(t));
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005035 tt = expand_mmac_params(tt);
5036 tt = expand_smacro(tt);
5037 /* Why dup_tlist() here? We should own tt... */
5038 dup_tlist(tt, &tail);
5039 text = NULL;
5040 change = true;
5041 break;
5042 }
5043
5044 default:
5045 change = false;
5046 break;
5047 }
5048
H. Peter Anvin (Intel)a762cd42020-06-01 11:49:08 -07005049 if (err_not_mac) {
5050 nasm_nonfatal("`%s': not in a macro call", text);
5051 text = NULL;
5052 change = true;
5053 }
5054
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005055 if (change) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00005056 if (!text) {
5057 delete_Token(t);
5058 } else {
5059 *tail = t;
5060 tail = &t->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07005061 set_text(t, text, tok_strlen(text));
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005062 t->type = type;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005063 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03005064 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005065 } else {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005066 *tail = t;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005067 tail = &t->next;
5068 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00005069 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005070
H. Peter Anvineba20a72002-04-30 20:53:55 +00005071 *tail = NULL;
H. Peter Anvin67c63722008-10-26 23:49:00 -07005072
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04005073 if (changed) {
5074 const struct tokseq_match t[] = {
5075 {
5076 PP_CONCAT_MASK(TOK_ID) |
5077 PP_CONCAT_MASK(TOK_FLOAT), /* head */
5078 PP_CONCAT_MASK(TOK_ID) |
5079 PP_CONCAT_MASK(TOK_NUMBER) |
5080 PP_CONCAT_MASK(TOK_FLOAT) |
5081 PP_CONCAT_MASK(TOK_OTHER) /* tail */
5082 },
5083 {
5084 PP_CONCAT_MASK(TOK_NUMBER), /* head */
5085 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
5086 }
5087 };
5088 paste_tokens(&thead, t, ARRAY_SIZE(t), false);
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005089
5090 /*
5091 * For backwards compatibility reasons, if we expanded
5092 * anything, we cannot return an empty token list. Legacy
5093 * NASM behavior is that:
5094 *
5095 * foobar %1
5096 *
5097 * ... where foobar is a macro is treated as a one-
5098 * parameter macro call with an empty argument, instead
5099 * of the far more sensible zero-argument call... except
5100 * that %0 is set to zero, which is illegal according to the
5101 * macro definition!
5102 *
5103 * This applies ONLY to the case of zero arguments, which
5104 * is what makes it completely brain damaged. If this is
5105 * the actual desired behavior, the correct way to code it
5106 * is:
5107 *
5108 * foobar {%1}
5109 *
5110 * This rather brain damaged backwards compatibility hack can
5111 * be disabled with:
5112 *
5113 * %pragma preproc sane_empty_expansion true
5114 */
5115 if (!ppopt.sane_empty_expansion) {
5116 for (tail = &thead; tok_white(*tail); tail = &((*tail)->next)) {
5117 /* See if we can find anything not whitespace... */
5118 }
5119 if (!*tail)
5120 *tail = new_White(NULL);
5121 }
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04005122 }
H. Peter Anvin6125b622009-04-08 14:02:25 -07005123
H. Peter Anvin76690a12002-04-30 20:52:49 +00005124 return thead;
5125}
5126
H. Peter Anvin322bee02019-08-10 01:38:06 -07005127static Token *expand_smacro_noreset(Token * tline);
H. Peter Anvin322bee02019-08-10 01:38:06 -07005128
H. Peter Anvin76690a12002-04-30 20:52:49 +00005129/*
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005130 * Expand *one* single-line macro instance. If the first token is not
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005131 * a macro at all, it is simply copied to the output and the pointer
5132 * advanced. tpp should be a pointer to a pointer (usually the next
5133 * pointer of the previous token) to the first token. **tpp is updated
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005134 * to point to the first token of the expansion, and *tpp updated to
5135 * point to the next pointer of the last token of the expansion.
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005136 *
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005137 * If the expansion is empty, *tpp will be unchanged but **tpp will
5138 * be advanced past the macro call.
5139 *
H. Peter Anvin322bee02019-08-10 01:38:06 -07005140 * Return the macro expanded, or NULL if no expansion took place.
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005141 */
H. Peter Anvin322bee02019-08-10 01:38:06 -07005142static SMacro *expand_one_smacro(Token ***tpp)
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005143{
5144 Token **params = NULL;
5145 const char *mname;
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005146 Token *mstart = **tpp;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005147 Token *tline = mstart;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005148 SMacro *head, *m;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005149 int i;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005150 Token *t, *tup, *tafter;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005151 int nparam = 0;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005152 bool cond_comma;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005153
5154 if (!tline)
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005155 return false; /* Empty line, nothing to do */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005156
H. Peter Anvin8571f062019-09-23 16:40:03 -07005157 mname = tok_text(mstart);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005158
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07005159 smacro_deadman.total--;
H. Peter Anvin322bee02019-08-10 01:38:06 -07005160 smacro_deadman.levels--;
5161
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07005162 if (unlikely(smacro_deadman.total < 0 || smacro_deadman.levels < 0)) {
H. Peter Anvin322bee02019-08-10 01:38:06 -07005163 if (unlikely(!smacro_deadman.triggered)) {
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005164 nasm_nonfatal("interminable macro recursion");
H. Peter Anvin322bee02019-08-10 01:38:06 -07005165 smacro_deadman.triggered = true;
5166 }
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005167 goto not_a_macro;
H. Peter Anvin8571f062019-09-23 16:40:03 -07005168 } else if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID) {
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005169 head = (SMacro *)hash_findix(&smacros, mname);
H. Peter Anvin8571f062019-09-23 16:40:03 -07005170 } else if (tline->type == TOK_LOCAL_MACRO) {
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005171 Context *ctx = get_ctx(mname, &mname);
5172 head = ctx ? (SMacro *)hash_findix(&ctx->localmac, mname) : NULL;
5173 } else {
5174 goto not_a_macro;
5175 }
5176
5177 /*
5178 * We've hit an identifier of some sort. First check whether the
5179 * identifier is a single-line macro at all, then think about
5180 * checking for parameters if necessary.
5181 */
5182 list_for_each(m, head) {
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005183 if (unlikely(m->alias && ppopt.noaliases))
H. Peter Anvind2354082019-08-27 16:38:48 -07005184 continue;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005185 if (!mstrcmp(m->name, mname, m->casesense))
5186 break;
5187 }
5188
5189 if (!m) {
5190 goto not_a_macro;
5191 }
5192
5193 /* Parse parameters, if applicable */
5194
5195 params = NULL;
5196 nparam = 0;
5197
5198 if (m->nparam == 0) {
5199 /*
5200 * Simple case: the macro is parameterless.
5201 * Nothing to parse; the expansion code will
5202 * drop the macro name token.
5203 */
5204 } else {
5205 /*
5206 * Complicated case: at least one macro with this name
5207 * exists and takes parameters. We must find the
5208 * parameters in the call, count them, find the SMacro
5209 * that corresponds to that form of the macro call, and
5210 * substitute for the parameters when we expand. What a
5211 * pain.
5212 */
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005213 Token *t;
5214 int paren, brackets;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005215
5216 tline = tline->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005217 tline = skip_white(tline);
5218 if (!tok_is(tline, '(')) {
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005219 /*
5220 * This macro wasn't called with parameters: ignore
5221 * the call. (Behaviour borrowed from gnu cpp.)
5222 */
5223 goto not_a_macro;
5224 }
5225
5226 paren = 1;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005227 nparam = 1;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005228 brackets = 0;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005229 t = tline; /* tline points to leading ( */
5230
5231 while (paren) {
5232 t = t->next;
5233
5234 if (!t) {
5235 nasm_nonfatal("macro call expects terminating `)'");
5236 goto not_a_macro;
5237 }
5238
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005239 if (t->type != TOK_OTHER || t->len != 1)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005240 continue;
5241
H. Peter Anvin8571f062019-09-23 16:40:03 -07005242 switch (t->text.a[0]) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005243 case ',':
H. Peter Anvinbd00f252020-06-04 21:05:01 -07005244 if (!brackets && paren == 1)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005245 nparam++;
5246 break;
5247
5248 case '{':
5249 brackets++;
5250 break;
5251
5252 case '}':
5253 if (brackets > 0)
5254 brackets--;
5255 break;
5256
5257 case '(':
5258 if (!brackets)
5259 paren++;
5260 break;
5261
5262 case ')':
5263 if (!brackets)
5264 paren--;
5265 break;
5266
5267 default:
5268 break; /* Normal token */
5269 }
5270 }
5271
5272 /*
5273 * Look for a macro matching in both name and parameter count.
5274 * We already know any matches cannot be anywhere before the
5275 * current position of "m", so there is no reason to
5276 * backtrack.
5277 */
5278 while (1) {
5279 if (!m) {
5280 /*!
5281 *!macro-params-single [on] single-line macro calls with wrong parameter count
5282 *! warns about \i{single-line macros} being invoked
5283 *! with the wrong number of parameters.
5284 */
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005285 nasm_warn(WARN_MACRO_PARAMS_SINGLE|ERR_HOLD,
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005286 "single-line macro `%s' exists, "
5287 "but not taking %d parameter%s",
5288 mname, nparam, (nparam == 1) ? "" : "s");
5289 goto not_a_macro;
5290 }
5291
5292 if (!mstrcmp(m->name, mname, m->casesense)) {
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005293 if (nparam == m->nparam)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005294 break; /* It's good */
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005295 if (m->greedy && nparam >= m->nparam-1)
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005296 break; /* Also good */
5297 }
5298 m = m->next;
5299 }
5300 }
5301
5302 if (m->in_progress)
5303 goto not_a_macro;
5304
5305 /* Expand the macro */
5306 m->in_progress = true;
5307
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005308 if (nparam) {
5309 /* Extract parameters */
5310 Token **phead, **pep;
5311 int white = 0;
5312 int brackets = 0;
5313 int paren;
5314 bool bracketed = false;
5315 bool bad_bracket = false;
5316 enum sparmflags flags;
5317
5318 nparam = m->nparam;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005319 paren = 1;
5320 nasm_newn(params, nparam);
5321 i = 0;
5322 flags = m->params[i].flags;
5323 phead = pep = &params[i];
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005324 *pep = NULL;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005325
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005326 while (paren) {
5327 bool skip;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005328 char ch;
5329
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005330 tline = tline->next;
5331
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005332 if (!tline)
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005333 nasm_nonfatal("macro call expects terminating `)'");
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005334
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005335 ch = 0;
5336 skip = false;
5337
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005338
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005339 switch (tline->type) {
5340 case TOK_OTHER:
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005341 if (tline->len == 1)
H. Peter Anvin8571f062019-09-23 16:40:03 -07005342 ch = tline->text.a[0];
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005343 break;
5344
5345 case TOK_WHITESPACE:
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005346 if (!(flags & SPARM_NOSTRIP)) {
5347 if (brackets || *phead)
5348 white++; /* Keep interior whitespace */
5349 skip = true;
5350 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005351 break;
5352
5353 default:
5354 break;
5355 }
5356
5357 switch (ch) {
5358 case ',':
H. Peter Anvinbd00f252020-06-04 21:05:01 -07005359 if (!brackets && paren == 1 && !(flags & SPARM_GREEDY)) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005360 i++;
5361 nasm_assert(i < nparam);
5362 phead = pep = &params[i];
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005363 *pep = NULL;
5364 bracketed = false;
5365 skip = true;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005366 flags = m->params[i].flags;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005367 }
5368 break;
5369
5370 case '{':
5371 if (!bracketed) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005372 bracketed = !*phead && !(flags & SPARM_NOSTRIP);
5373 skip = bracketed;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005374 }
5375 brackets++;
5376 break;
5377
5378 case '}':
5379 if (brackets > 0) {
5380 if (!--brackets)
5381 skip = bracketed;
5382 }
5383 break;
5384
5385 case '(':
5386 if (!brackets)
5387 paren++;
5388 break;
5389
5390 case ')':
5391 if (!brackets) {
5392 paren--;
5393 if (!paren) {
5394 skip = true;
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005395 i++; /* Found last argument */
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005396 }
5397 }
5398 break;
5399
5400 default:
5401 break; /* Normal token */
5402 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005403
5404 if (!skip) {
5405 Token *t;
5406
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005407 bad_bracket |= bracketed && !brackets;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005408
5409 if (white) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005410 *pep = t = new_White(NULL);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005411 pep = &t->next;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005412 white = 0;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005413 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005414 *pep = t = dup_Token(NULL, tline);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005415 pep = &t->next;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005416 }
5417 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005418
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005419 /*
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005420 * Possible further processing of parameters. Note that the
5421 * ordering matters here.
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005422 */
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005423 for (i = 0; i < nparam; i++) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005424 enum sparmflags flags = m->params[i].flags;
5425
5426 if (flags & SPARM_EVAL) {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005427 /* Evaluate this parameter as a number */
5428 struct ppscan pps;
5429 struct tokenval tokval;
5430 expr *evalresult;
5431 Token *eval_param;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005432
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005433 pps.tptr = eval_param = expand_smacro_noreset(params[i]);
5434 pps.ntokens = -1;
5435 tokval.t_type = TOKEN_INVALID;
5436 evalresult = evaluate(ppscan, &pps, &tokval, NULL, true, NULL);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005437
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005438 free_tlist(eval_param);
5439 params[i] = NULL;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005440
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005441 if (!evalresult) {
5442 /* Nothing meaningful to do */
5443 } else if (tokval.t_type) {
5444 nasm_nonfatal("invalid expression in parameter %d of macro `%s'", i, m->name);
5445 } else if (!is_simple(evalresult)) {
5446 nasm_nonfatal("non-constant expression in parameter %d of macro `%s'", i, m->name);
5447 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07005448 params[i] = make_tok_num(NULL, reloc_value(evalresult));
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005449 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005450 }
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005451
5452 if (flags & SPARM_STR) {
5453 /* Convert expansion to a quoted string */
5454 char *arg;
5455 Token *qs;
5456
5457 qs = expand_smacro_noreset(params[i]);
5458 arg = detoken(qs, false);
5459 free_tlist(qs);
H. Peter Anvin8571f062019-09-23 16:40:03 -07005460 params[i] = make_tok_qstr(NULL, arg);
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005461 nasm_free(arg);
5462 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005463 }
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005464 }
5465
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005466 /* Note: we own the expansion this returns. */
5467 t = m->expand(m, params, nparam);
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005468
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005469 tafter = tline->next; /* Skip past the macro call */
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07005470 tline->next = NULL; /* Truncate list at the macro call end */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005471 tline = tafter;
5472
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005473 tup = NULL;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005474 cond_comma = false;
5475
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005476 while (t) {
5477 enum pp_token_type type = t->type;
5478 Token *tnext = t->next;
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005479
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005480 switch (type) {
5481 case TOK_PREPROC_Q:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005482 delete_Token(t);
5483 t = dup_Token(tline, mstart);
5484 break;
5485
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005486 case TOK_PREPROC_QQ:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005487 {
H. Peter Anvin8571f062019-09-23 16:40:03 -07005488 size_t mlen = strlen(m->name);
5489 size_t len;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005490 char *p;
5491
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005492 t->type = mstart->type;
H. Peter Anvin8571f062019-09-23 16:40:03 -07005493 if (t->type == TOK_LOCAL_MACRO) {
5494 const char *psp; /* prefix start pointer */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005495 const char *pep; /* prefix end pointer */
H. Peter Anvin8571f062019-09-23 16:40:03 -07005496 size_t plen;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005497
H. Peter Anvin8571f062019-09-23 16:40:03 -07005498 psp = tok_text(mstart);
5499 get_ctx(psp, &pep);
5500 plen = pep - psp;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005501
H. Peter Anvin8571f062019-09-23 16:40:03 -07005502 len = mlen + plen;
5503 p = nasm_malloc(len + 1);
5504 p = mempcpy(p, psp, plen);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005505 } else {
H. Peter Anvin8571f062019-09-23 16:40:03 -07005506 len = mlen;
5507 p = nasm_malloc(len + 1);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005508 }
H. Peter Anvin8571f062019-09-23 16:40:03 -07005509 p = mempcpy(p, m->name, mlen);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005510 *p = '\0';
H. Peter Anvin8571f062019-09-23 16:40:03 -07005511 set_text_free(t, p, len);
5512
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005513 t->next = tline;
5514 break;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005515 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005516
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005517 case TOK_COND_COMMA:
5518 delete_Token(t);
H. Peter Anvin8571f062019-09-23 16:40:03 -07005519 t = cond_comma ? make_tok_char(tline, ',') : NULL;
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005520 break;
5521
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005522 case TOK_ID:
5523 case TOK_PREPROC_ID:
H. Peter Anvin8571f062019-09-23 16:40:03 -07005524 case TOK_LOCAL_MACRO:
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005525 {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005526 /*
5527 * Chain this into the target line *before* expanding,
5528 * that way we pick up any arguments to the new macro call,
5529 * if applicable.
5530 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005531 Token **tp = &t;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005532 t->next = tline;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005533 expand_one_smacro(&tp);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005534 tline = *tp; /* First token left after any macro call */
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005535 break;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005536 }
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005537 default:
5538 if (is_smac_param(t->type)) {
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07005539 int param = smac_nparam(t->type);
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005540 nasm_assert(!tup && param < nparam);
5541 delete_Token(t);
5542 t = NULL;
5543 tup = tnext;
5544 tnext = dup_tlist_reverse(params[param], NULL);
H. Peter Anvin (Intel)a1a84462019-08-20 01:32:28 -07005545 cond_comma = false;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005546 } else {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005547 t->next = tline;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005548 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005549 }
5550
5551 if (t) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005552 Token *endt = tline;
5553
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005554 tline = t;
Chang S. Bae95e54a92020-02-06 14:39:22 -08005555 while (!cond_comma && t && t != endt) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005556 cond_comma = t->type != TOK_WHITESPACE;
Chang S. Bae95e54a92020-02-06 14:39:22 -08005557 t = t->next;
5558 }
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005559 }
5560
5561 if (tnext) {
5562 t = tnext;
5563 } else {
5564 t = tup;
5565 tup = NULL;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005566 }
5567 }
5568
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005569 **tpp = tline;
H. Peter Anvin (Intel)6e714962020-06-01 12:21:10 -07005570 for (t = tline; t && t != tafter; t = t->next)
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005571 *tpp = &t->next;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005572
5573 m->in_progress = false;
5574
5575 /* Don't do this until after expansion or we will clobber mname */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005576 free_tlist(mstart);
H. Peter Anvin322bee02019-08-10 01:38:06 -07005577 goto done;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005578
5579 /*
5580 * No macro expansion needed; roll back to mstart (if necessary)
H. Peter Anvin322bee02019-08-10 01:38:06 -07005581 * and then advance to the next input token. Note that this is
5582 * by far the common case!
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005583 */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005584not_a_macro:
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005585 *tpp = &mstart->next;
H. Peter Anvin322bee02019-08-10 01:38:06 -07005586 m = NULL;
5587done:
5588 smacro_deadman.levels++;
5589 if (unlikely(params))
5590 free_tlist_array(params, nparam);
5591 return m;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005592}
5593
5594/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005595 * Expand all single-line macro calls made in the given line.
5596 * Return the expanded version of the line. The original is deemed
5597 * to be destroyed in the process. (In reality we'll just move
5598 * Tokens from input to output a lot of the time, rather than
5599 * actually bothering to destroy and replicate.)
5600 */
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005601static Token *expand_smacro(Token *tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005602{
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07005603 smacro_deadman.total = nasm_limit[LIMIT_MACRO_TOKENS];
H. Peter Anvin322bee02019-08-10 01:38:06 -07005604 smacro_deadman.levels = nasm_limit[LIMIT_MACRO_LEVELS];
5605 smacro_deadman.triggered = false;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005606 return expand_smacro_noreset(tline);
5607}
5608
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005609static Token *expand_smacro_noreset(Token *org_tline)
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07005610{
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005611 Token *tline;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005612 bool expanded;
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005613 errhold errhold; /* Hold warning/errors during expansion */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005614
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005615 if (!org_tline)
5616 return NULL; /* Empty input */
5617
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005618 /*
5619 * Trick: we should avoid changing the start token pointer since it can
5620 * be contained in "next" field of other token. Because of this
5621 * we allocate a copy of first token and work with it; at the end of
5622 * routine we copy it back
5623 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005624 tline = dup_Token(org_tline->next, org_tline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005625
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005626 /*
5627 * Pretend that we always end up doing expansion on the first pass;
5628 * that way %+ get processed. However, if we process %+ before the
5629 * first pass, we end up with things like MACRO %+ TAIL trying to
5630 * look up the macro "MACROTAIL", which we don't want.
5631 */
5632 expanded = true;
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005633
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005634 while (true) {
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005635 static const struct tokseq_match tmatch[] = {
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04005636 {
5637 PP_CONCAT_MASK(TOK_ID) |
H. Peter Anvin8571f062019-09-23 16:40:03 -07005638 PP_CONCAT_MASK(TOK_LOCAL_MACRO) |
5639 PP_CONCAT_MASK(TOK_ENVIRON) |
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04005640 PP_CONCAT_MASK(TOK_PREPROC_ID), /* head */
5641 PP_CONCAT_MASK(TOK_ID) |
H. Peter Anvin8571f062019-09-23 16:40:03 -07005642 PP_CONCAT_MASK(TOK_LOCAL_MACRO) |
5643 PP_CONCAT_MASK(TOK_ENVIRON) |
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04005644 PP_CONCAT_MASK(TOK_PREPROC_ID) |
5645 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
5646 }
5647 };
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005648 Token **tail = &tline;
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005649
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005650 /*
5651 * We hold warnings/errors until we are done this this loop. It is
5652 * possible for nuisance warnings to appear that disappear on later
5653 * passes.
5654 */
5655 errhold = nasm_error_hold_push();
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005656 while (*tail) /* main token loop */
H. Peter Anvin322bee02019-08-10 01:38:06 -07005657 expanded |= !!expand_one_smacro(&tail);
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005658
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005659 if (!expanded)
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005660 break; /* Done! */
H. Peter Anvin (Intel)875eb242019-08-07 17:12:24 -07005661
5662 /*
5663 * Now scan the entire line and look for successive TOK_IDs
5664 * that resulted after expansion (they can't be produced by
5665 * tokenize()). The successive TOK_IDs should be concatenated.
5666 * Also we look for %+ tokens and concatenate the tokens
5667 * before and after them (without white spaces in between).
5668 */
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005669 if (!paste_tokens(&tline, tmatch, ARRAY_SIZE(tmatch), true))
5670 break; /* Done again! */
5671
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005672 expanded = false;
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005673 nasm_error_hold_pop(errhold, false);
H. Peter Anvin734b1882002-04-30 21:01:08 +00005674 }
H. Peter Anvin (Intel)4964d802020-06-04 15:53:31 -07005675 nasm_error_hold_pop(errhold, true);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005676
H. Peter Anvin8571f062019-09-23 16:40:03 -07005677 if (!tline) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005678 /*
5679 * The expression expanded to empty line;
5680 * we can't return NULL because of the "trick" above.
5681 * Just set the line to a single WHITESPACE token.
H. Peter Anvin8571f062019-09-23 16:40:03 -07005682 */
5683
5684 tline = new_White(NULL);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005685 }
5686
H. Peter Anvin8571f062019-09-23 16:40:03 -07005687 steal_Token(org_tline, tline);
5688 org_tline->next = tline->next;
5689 delete_Token(tline);
5690
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07005691 return org_tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005692}
5693
5694/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005695 * Similar to expand_smacro but used exclusively with macro identifiers
5696 * right before they are fetched in. The reason is that there can be
5697 * identifiers consisting of several subparts. We consider that if there
5698 * are more than one element forming the name, user wants a expansion,
5699 * otherwise it will be left as-is. Example:
5700 *
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03005701 * %define %$abc cde
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005702 *
5703 * the identifier %$abc will be left as-is so that the handler for %define
5704 * will suck it and define the corresponding value. Other case:
5705 *
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03005706 * %define _%$abc cde
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005707 *
5708 * In this case user wants name to be expanded *before* %define starts
5709 * working, so we'll expand %$abc into something (if it has a value;
5710 * otherwise it will be left as-is) then concatenate all successive
5711 * PP_IDs into one.
5712 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00005713static Token *expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005714{
5715 Token *cur, *oldnext = NULL;
5716
H. Peter Anvin734b1882002-04-30 21:01:08 +00005717 if (!tline || !tline->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005718 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005719
5720 cur = tline;
5721 while (cur->next &&
H. Peter Anvin8571f062019-09-23 16:40:03 -07005722 (cur->next->type == TOK_ID || cur->next->type == TOK_PREPROC_ID ||
5723 cur->next->type == TOK_LOCAL_MACRO || cur->next->type == TOK_NUMBER))
H. Peter Anvine2c80182005-01-15 22:15:51 +00005724 cur = cur->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005725
5726 /* If identifier consists of just one token, don't expand */
5727 if (cur == tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005728 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005729
H. Peter Anvine2c80182005-01-15 22:15:51 +00005730 if (cur) {
5731 oldnext = cur->next; /* Detach the tail past identifier */
5732 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005733 }
5734
H. Peter Anvin734b1882002-04-30 21:01:08 +00005735 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005736
H. Peter Anvine2c80182005-01-15 22:15:51 +00005737 if (cur) {
5738 /* expand_smacro possibly changhed tline; re-scan for EOL */
5739 cur = tline;
5740 while (cur && cur->next)
5741 cur = cur->next;
5742 if (cur)
5743 cur->next = oldnext;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005744 }
5745
5746 return tline;
5747}
5748
5749/*
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005750 * This is called from is_mmacro() after finding a suitable macro.
5751 */
5752static MMacro *use_mmacro(MMacro *m, int *nparamp, Token ***paramsp)
5753{
5754 int nparam = *nparamp;
5755 Token **params = *paramsp;
5756
5757 /*
5758 * This one is right. Just check if cycle removal
5759 * prohibits us using it before we actually celebrate...
5760 */
5761 if (m->in_progress > m->max_depth) {
5762 if (m->max_depth > 0) {
5763 nasm_warn(WARN_OTHER, "reached maximum recursion depth of %i",
5764 m->max_depth);
5765 }
5766 nasm_free(params);
5767 *nparamp = 0;
5768 *paramsp = NULL;
5769 return NULL;
5770 }
5771
5772 /*
5773 * It's right, and we can use it. Add its default
5774 * parameters to the end of our list if necessary.
5775 */
5776 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
5777 int newnparam = m->nparam_min + m->ndefs;
5778 params = nasm_realloc(params, sizeof(*params) * (newnparam+2));
5779 memcpy(&params[nparam+1], &m->defaults[nparam+1-m->nparam_min],
5780 (newnparam - nparam) * sizeof(*params));
5781 nparam = newnparam;
5782 }
5783 /*
5784 * If we've gone over the maximum parameter count (and
5785 * we're in Plus mode), ignore parameters beyond
5786 * nparam_max.
5787 */
5788 if (m->plus && nparam > m->nparam_max)
5789 nparam = m->nparam_max;
5790
5791 /*
5792 * If nparam was adjusted above, make sure the list is still
5793 * NULL-terminated.
5794 */
5795 params[nparam+1] = NULL;
5796
5797 /* Done! */
5798 *paramsp = params;
5799 *nparamp = nparam;
5800 return m;
5801}
5802
5803
5804
5805/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005806 * Determine whether the given line constitutes a multi-line macro
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005807 * call, and return the MMacro structure called if so. Doesn't have
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005808 * to check for an initial label - that's taken care of in
5809 * expand_mmacro - but must check numbers of parameters. Guaranteed
5810 * to be called with tline->type == TOK_ID, so the putative macro
5811 * name is easy to find.
5812 */
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005813static MMacro *is_mmacro(Token * tline, int *nparamp, Token ***paramsp)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005814{
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005815 MMacro *head, *m, *mone;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005816 Token **params;
5817 int nparam;
H. Peter Anvin8571f062019-09-23 16:40:03 -07005818 const char *finding = tok_text(tline);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005819
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005820 *nparamp = 0;
5821 *paramsp = NULL;
5822
H. Peter Anvin8571f062019-09-23 16:40:03 -07005823 head = (MMacro *) hash_findix(&mmacros, finding);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005824
5825 /*
5826 * Efficiency: first we see if any macro exists with the given
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07005827 * name which isn't already excluded by macro cycle removal.
5828 * (The cycle removal test here helps optimize the case of wrapping
5829 * instructions, and is cheap to do here.)
5830 *
5831 * If not, we can return NULL immediately. _Then_ we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005832 * count the parameters, and then we look further along the
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005833 * list if necessary to find the proper MMacro.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005834 */
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07005835 list_for_each(m, head) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07005836 if (!mstrcmp(m->name, finding, m->casesense) &&
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07005837 (m->in_progress != 1 || m->max_depth > 0))
5838 break; /* Found something that needs consideration */
5839 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005840 if (!m)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005841 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005842
5843 /*
5844 * OK, we have a potential macro. Count and demarcate the
5845 * parameters.
5846 */
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005847 count_mmac_params(tline->next, nparamp, paramsp);
5848 nparam = *nparamp;
5849 params = *paramsp;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005850
5851 /*
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005852 * If we find a macro which doesn't match, but accepts one argument
5853 * but not zero, remember it for the special handling below.
5854 */
5855 mone = NULL;
5856
5857 /*
5858 * Search for an exact match. This cannot come *before* the m
5859 * found in the list search before.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005860 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005861 while (m) {
5862 if (m->nparam_min <= nparam
5863 && (m->plus || nparam <= m->nparam_max)) {
5864 /*
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005865 * This one matches, use it.
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005866 */
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005867 return use_mmacro(m, nparamp, paramsp);
5868 } else if (m->nparam_min == 1 && !mone) {
5869 mone = m;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005870 }
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005871
H. Peter Anvine2c80182005-01-15 22:15:51 +00005872 /*
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005873 * Otherwise search for the next one with a name match.
H. Peter Anvine2c80182005-01-15 22:15:51 +00005874 */
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005875 list_for_each(m, m->next) {
5876 if (!mstrcmp(m->name, finding, m->casesense))
H. Peter Anvine2c80182005-01-15 22:15:51 +00005877 break;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005878 }
5879 }
5880
5881 /*
5882 * Special weirdness: in NASM < 2.15, an expansion of
5883 * *only* whitespace, as can happen during macro expansion under
5884 * certain circumstances, is counted as zero arguments for the
5885 * purpose of %0, but one argument for the purpose of macro
5886 * matching! In particular, this affects:
5887 *
5888 * foobar %1
5889 *
5890 * ... with %1 being empty; this would call the one-argument
5891 * version of "foobar" with an empty argument, equivalent to
5892 *
5893 * foobar {%1}
5894 *
5895 * ... except that %0 would be set to 0 inside foobar, even if
5896 * foobar is declared with "%macro foobar 1" or equivalent!
5897 *
5898 * The proper way to do that is to define "%macro foobar 0-1".
5899 *
5900 * To be compatible without doing something too stupid, try to
5901 * match a zero-argument macro first, but if that fails, try
5902 * for a one-argument macro with the above behavior.
5903 *
5904 * To disable this insane legacy behavior, use:
5905 *
5906 * %pragma preproc sane_empty_expansion yes
5907 */
5908 if (!nparam && tline->next && !ppopt.sane_empty_expansion && mone) {
5909 nasm_warn(WARN_MACRO_PARAMS_MULTI,
5910 "improperly calling multi-line macro `%s' with 0 parameters (legacy hack)",
5911 finding);
5912 return use_mmacro(mone, nparamp, paramsp);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005913 }
5914
5915 /*
5916 * After all that, we didn't find one with the right number of
5917 * parameters. Issue a warning, and fail to expand the macro.
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005918 *!
5919 *!macro-params-multi [on] multi-line macro calls with wrong parameter count
5920 *! warns about \i{multi-line macros} being invoked
5921 *! with the wrong number of parameters. See \k{mlmacover} for an
5922 *! example of why you might want to disable this warning.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005923 */
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07005924 nasm_warn(WARN_MACRO_PARAMS_MULTI,
5925 "multi-line macro `%s' exists, but not taking %d parameter%s",
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07005926 finding, nparam, (nparam == 1) ? "" : "s");
H. Peter Anvin734b1882002-04-30 21:01:08 +00005927 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005928 return NULL;
5929}
5930
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005931
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005932#if 0
5933
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005934/*
5935 * Save MMacro invocation specific fields in
5936 * preparation for a recursive macro expansion
5937 */
5938static void push_mmacro(MMacro *m)
5939{
5940 MMacroInvocation *i;
5941
5942 i = nasm_malloc(sizeof(MMacroInvocation));
5943 i->prev = m->prev;
5944 i->params = m->params;
5945 i->iline = m->iline;
5946 i->nparam = m->nparam;
5947 i->rotate = m->rotate;
5948 i->paramlen = m->paramlen;
5949 i->unique = m->unique;
5950 i->condcnt = m->condcnt;
5951 m->prev = i;
5952}
5953
5954
5955/*
5956 * Restore MMacro invocation specific fields that were
5957 * saved during a previous recursive macro expansion
5958 */
5959static void pop_mmacro(MMacro *m)
5960{
5961 MMacroInvocation *i;
5962
5963 if (m->prev) {
5964 i = m->prev;
5965 m->prev = i->prev;
5966 m->params = i->params;
5967 m->iline = i->iline;
5968 m->nparam = i->nparam;
5969 m->rotate = i->rotate;
5970 m->paramlen = i->paramlen;
5971 m->unique = i->unique;
5972 m->condcnt = i->condcnt;
5973 nasm_free(i);
5974 }
5975}
5976
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07005977#endif
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005978
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005979/*
H. Peter Anvin (Intel)ffe89dd2019-08-20 16:06:36 -07005980 * List an mmacro call with arguments (-Lm option)
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07005981 */
5982static void list_mmacro_call(const MMacro *m)
5983{
5984 const char prefix[] = " ;;; [macro] ";
5985 size_t namelen, size;
5986 char *buf, *p;
5987 unsigned int i;
5988 const Token *t;
5989
5990 namelen = strlen(m->iname);
5991 size = namelen + sizeof(prefix); /* Includes final null (from prefix) */
5992
5993 for (i = 1; i <= m->nparam; i++) {
5994 int j = 0;
5995 size += 3; /* Braces and space/comma */
5996 list_for_each(t, m->params[i]) {
5997 if (j++ >= m->paramlen[i])
5998 break;
5999 size += (t->type == TOK_WHITESPACE) ? 1 : t->len;
6000 }
6001 }
6002
6003 buf = p = nasm_malloc(size);
6004 p = mempcpy(p, prefix, sizeof(prefix) - 1);
6005 p = mempcpy(p, m->iname, namelen);
6006 *p++ = ' ';
6007
6008 for (i = 1; i <= m->nparam; i++) {
6009 int j = 0;
6010 *p++ = '{';
6011 list_for_each(t, m->params[i]) {
6012 if (j++ >= m->paramlen[i])
6013 break;
H. Peter Anvin8571f062019-09-23 16:40:03 -07006014 p = mempcpy(p, tok_text(t), t->len);
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07006015 }
6016 *p++ = '}';
6017 *p++ = ',';
6018 }
6019
6020 *--p = '\0'; /* Replace last delimeter with null */
6021 lfmt->line(LIST_MACRO, -1, buf);
6022 nasm_free(buf);
6023}
6024
6025/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006026 * Expand the multi-line macro call made by the given line, if
6027 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006028 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006029 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006030static int expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006031{
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006032 Token *startline = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00006033 Token *label = NULL;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006034 bool dont_prepend = false;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006035 Token **params, *t, *tt;
6036 MMacro *m;
6037 Line *l, *ll;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07006038 int i, last_nonempty, *paramlen;
H. Peter Anvinc751e862008-06-09 10:18:45 -07006039 const char *mname;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006040 int nparam = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006041
6042 t = tline;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006043 t = skip_white(t);
6044 /* if (!tok_type(t, TOK_ID)) Lino 02/25/02 */
H. Peter Anvin8571f062019-09-23 16:40:03 -07006045 if (!tok_type(t, TOK_ID) && !tok_type(t, TOK_LOCAL_MACRO))
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006046 return 0;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006047 m = is_mmacro(t, &nparam, &params);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006048 if (m) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07006049 mname = tok_text(t);
H. Peter Anvinc751e862008-06-09 10:18:45 -07006050 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006051 Token *last;
6052 /*
6053 * We have an id which isn't a macro call. We'll assume
6054 * it might be a label; we'll also check to see if a
6055 * colon follows it. Then, if there's another id after
6056 * that lot, we'll check it again for macro-hood.
6057 */
6058 label = last = t;
6059 t = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006060 if (tok_white(t))
H. Peter Anvine2c80182005-01-15 22:15:51 +00006061 last = t, t = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006062 if (tok_is(t, ':')) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006063 dont_prepend = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006064 last = t, t = t->next;
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006065 if (tok_white(t))
H. Peter Anvine2c80182005-01-15 22:15:51 +00006066 last = t, t = t->next;
6067 }
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006068 if (!tok_type(t, TOK_ID) || !(m = is_mmacro(t, &nparam, &params)))
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006069 return 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006070 last->next = NULL;
H. Peter Anvin8571f062019-09-23 16:40:03 -07006071 mname = tok_text(t);
H. Peter Anvine2c80182005-01-15 22:15:51 +00006072 tline = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00006073 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006074
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07006075 if (unlikely(mmacro_deadman.total >= nasm_limit[LIMIT_MMACROS] ||
6076 mmacro_deadman.levels >= nasm_limit[LIMIT_MACRO_LEVELS])) {
6077 if (!mmacro_deadman.triggered) {
6078 nasm_nonfatal("interminable multiline macro recursion");
6079 mmacro_deadman.triggered = true;
6080 }
6081 return 0;
6082 }
6083
6084 mmacro_deadman.total++;
6085 mmacro_deadman.levels++;
6086
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006087 /*
6088 * Fix up the parameters: this involves stripping leading and
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07006089 * trailing whitespace and stripping braces if they are present.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006090 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006091 nasm_newn(paramlen, nparam+1);
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07006092 nasm_assert(params[nparam+1] == NULL);
6093
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07006094 /* Last nonempty *unbraced* parameter */
6095 last_nonempty = 0;
6096
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006097 for (i = 1; (t = params[i]); i++) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006098 bool braced = false;
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08006099 int brace = 0;
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006100 int white = 0;
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07006101 bool comma = !m->plus || i < nparam;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006102
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006103 t = skip_white(t);
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006104 if (tok_is(t, '{')) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006105 t = t->next;
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006106 brace = 1;
6107 braced = true;
6108 comma = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006109 }
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006110
6111 params[i] = t;
6112 for (; t; t = t->next) {
6113 if (tok_white(t)) {
6114 white++;
6115 continue;
6116 }
6117
6118 if (t->type == TOK_OTHER && t->len == 1) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07006119 switch (t->text.a[0]) {
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006120 case ',':
6121 if (comma && !brace)
6122 goto endparam;
6123 break;
6124
6125 case '{':
6126 brace++;
6127 break;
6128
6129 case '}':
6130 brace--;
6131 if (braced && !brace) {
6132 paramlen[i] += white;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07006133 last_nonempty = i;
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006134 goto endparam;
6135 }
6136 break;
6137
6138 default:
6139 break;
6140 }
6141 }
6142
6143 paramlen[i] += white + 1;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07006144 last_nonempty = i;
H. Peter Anvin (Intel)f7dbdb22019-09-18 21:20:52 -07006145 white = 0;
6146 }
6147 endparam:
6148 ;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006149 }
6150
6151 /*
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07006152 * NASM < 2.15 would not count terminal empty arguemnts
6153 * in %0, even though it counted for matching.
6154 * This implements this legacy behavior.
6155 *
6156 * Use:
6157 *
6158 * %pragma preproc sane_empty_expansion true
6159 *
6160 * ... to disable this rather crazy legacy behavior.
6161 */
6162 if (!ppopt.sane_empty_expansion)
6163 nparam = last_nonempty;
6164
6165 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006166 * OK, we have a MMacro structure together with a set of
6167 * parameters. We must now go through the expansion and push
6168 * copies of each Line on to istk->expansion. Substitution of
H. Peter Anvin76690a12002-04-30 20:52:49 +00006169 * parameter tokens and macro-local tokens doesn't get done
6170 * until the single-line macro substitution process; this is
6171 * because delaying them allows us to change the semantics
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006172 * later through %rotate and give the right semantics for
6173 * nested mmacros.
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006174 *
6175 * First, push an end marker on to istk->expansion, mark this
6176 * macro as in progress, and set up its invocation-specific
6177 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006178 */
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07006179 nasm_new(ll);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006180 ll->next = istk->expansion;
6181 ll->finishes = m;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006182 istk->expansion = ll;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006183
6184 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006185 * Save the previous MMacro expansion in the case of
6186 * macro recursion
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006187 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006188#if 0
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006189 if (m->max_depth && m->in_progress)
6190 push_mmacro(m);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006191#endif
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006192
6193 m->in_progress ++;
6194 m->params = params;
6195 m->iline = tline;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006196 m->iname = nasm_strdup(mname);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006197 m->nparam = nparam;
6198 m->rotate = 0;
6199 m->paramlen = paramlen;
6200 m->unique = unique++;
6201 m->lineno = 0;
6202 m->condcnt = 0;
6203
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006204 m->mstk = istk->mstk;
6205 istk->mstk.mstk = istk->mstk.mmac = m;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006206
6207 list_for_each(l, m->expansion) {
H. Peter Anvin (Intel)9fbd9fb2019-08-15 19:26:52 -07006208 nasm_new(ll);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006209 ll->next = istk->expansion;
6210 istk->expansion = ll;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006211 ll->first = dup_tlist(l->first, NULL);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006212 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006213
6214 /*
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006215 * If we had a label, and this macro definition does not include
6216 * a %00, push it on as the first line of, ot
H. Peter Anvineba20a72002-04-30 20:53:55 +00006217 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006218 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006219 if (label) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006220 /*
6221 * We had a label. If this macro contains an %00 parameter,
6222 * save the value as a special parameter (which is what it
6223 * is), otherwise push it as the first line of the macro
6224 * expansion.
6225 */
6226 if (m->capture_label) {
6227 params[0] = dup_Token(NULL, label);
6228 paramlen[0] = 1;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006229 free_tlist(startline);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006230 } else {
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006231 nasm_new(ll);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006232 ll->finishes = NULL;
6233 ll->next = istk->expansion;
6234 istk->expansion = ll;
6235 ll->first = startline;
6236 if (!dont_prepend) {
6237 while (label->next)
6238 label = label->next;
H. Peter Anvin8571f062019-09-23 16:40:03 -07006239 label->next = tt = make_tok_char(NULL, ':');
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006240 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006241 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00006242 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006243
H. Peter Anvin0d4d4312019-08-07 00:46:27 -07006244 lfmt->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006245
H. Peter Anvin (Intel)41d91a92019-08-20 16:00:57 -07006246 if (list_option('m') && !m->nolist)
6247 list_mmacro_call(m);
6248
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006249 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006250}
6251
H. Peter Anvin130736c2016-02-17 20:27:41 -08006252/*
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006253 * This function decides if an error message should be suppressed.
6254 * It will never be called with a severity level of ERR_FATAL or
6255 * higher.
H. Peter Anvin130736c2016-02-17 20:27:41 -08006256 */
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006257static bool pp_suppress_error(errflags severity)
Victor van den Elzen3b404c02008-09-18 13:51:36 +02006258{
H. Peter Anvin130736c2016-02-17 20:27:41 -08006259 /*
6260 * If we're in a dead branch of IF or something like it, ignore the error.
6261 * However, because %else etc are evaluated in the state context
6262 * of the previous branch, errors might get lost:
6263 * %if 0 ... %else trailing garbage ... %endif
6264 * So %else etc should set the ERR_PP_PRECOND flag.
6265 */
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006266 if (istk && istk->conds &&
H. Peter Anvin130736c2016-02-17 20:27:41 -08006267 ((severity & ERR_PP_PRECOND) ?
6268 istk->conds->state == COND_NEVER :
H. Peter Anvineb6653f2016-04-05 13:03:10 -07006269 !emitting(istk->conds->state)))
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006270 return true;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02006271
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006272 return false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00006273}
6274
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006275static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07006276stdmac_file(const SMacro *s, Token **params, int nparams)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006277{
6278 (void)s;
6279 (void)params;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07006280 (void)nparams;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006281
H. Peter Anvin8571f062019-09-23 16:40:03 -07006282 return make_tok_qstr(NULL, src_get_fname());
H. Peter Anvin8b262472019-02-26 14:00:54 -08006283}
6284
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006285static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07006286stdmac_line(const SMacro *s, Token **params, int nparams)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006287{
6288 (void)s;
6289 (void)params;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07006290 (void)nparams;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006291
H. Peter Anvin8571f062019-09-23 16:40:03 -07006292 return make_tok_num(NULL, src_get_linnum());
H. Peter Anvin8b262472019-02-26 14:00:54 -08006293}
6294
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006295static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07006296stdmac_bits(const SMacro *s, Token **params, int nparams)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006297{
6298 (void)s;
6299 (void)params;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07006300 (void)nparams;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006301
H. Peter Anvin8571f062019-09-23 16:40:03 -07006302 return make_tok_num(NULL, globalbits);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006303}
6304
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006305static Token *
H. Peter Anvin (Intel)62cf4aa2019-08-20 00:05:41 -07006306stdmac_ptr(const SMacro *s, Token **params, int nparams)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006307{
H. Peter Anvin8b262472019-02-26 14:00:54 -08006308 (void)s;
6309 (void)params;
H. Peter Anvin (Intel)41e96822019-04-25 18:00:32 -07006310 (void)nparams;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006311
6312 switch (globalbits) {
6313 case 16:
H. Peter Anvin8571f062019-09-23 16:40:03 -07006314 return new_Token(NULL, TOK_ID, "word", 4);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006315 case 32:
H. Peter Anvin8571f062019-09-23 16:40:03 -07006316 return new_Token(NULL, TOK_ID, "dword", 5);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006317 case 64:
H. Peter Anvin8571f062019-09-23 16:40:03 -07006318 return new_Token(NULL, TOK_ID, "qword", 5);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006319 default:
6320 panic();
6321 }
H. Peter Anvin8b262472019-02-26 14:00:54 -08006322}
6323
H. Peter Anvin8b262472019-02-26 14:00:54 -08006324/* Add magic standard macros */
6325struct magic_macros {
6326 const char *name;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07006327 int nparam;
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006328 ExpandSMacro func;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006329};
6330static const struct magic_macros magic_macros[] =
6331{
H. Peter Anvind2354082019-08-27 16:38:48 -07006332 { "__?FILE?__", 0, stdmac_file },
6333 { "__?LINE?__", 0, stdmac_line },
6334 { "__?BITS?__", 0, stdmac_bits },
6335 { "__?PTR?__", 0, stdmac_ptr },
H. Peter Anvin8b262472019-02-26 14:00:54 -08006336 { NULL, 0, NULL }
6337};
6338
6339static void pp_add_magic_stdmac(void)
6340{
6341 const struct magic_macros *m;
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07006342 SMacro tmpl;
6343
6344 nasm_zero(tmpl);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006345
6346 for (m = magic_macros; m->name; m++) {
H. Peter Anvin (Intel)5e3d7412019-08-14 23:45:57 -07006347 tmpl.nparam = m->nparam;
6348 tmpl.expand = m->func;
6349 define_smacro(m->name, true, NULL, &tmpl);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006350 }
6351}
6352
H. Peter Anvin734b1882002-04-30 21:01:08 +00006353static void
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006354pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006355{
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006356 int apass;
H. Peter Anvin6686de22019-08-10 05:33:14 -07006357 struct Include *inc;
H. Peter Anvin7383b402008-09-24 10:20:40 -07006358
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006359 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006360 defining = NULL;
Charles Crayned4200be2008-07-12 16:42:33 -07006361 nested_mac_count = 0;
6362 nested_rep_count = 0;
H. Peter Anvin97a23472007-09-16 17:57:25 -07006363 init_macros();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006364 unique = 0;
H. Peter Anvin (Intel)f7106d02018-10-25 12:33:58 -07006365 deplist = dep_list;
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006366 pp_mode = mode;
H. Peter Anvin (Intel)ee0e3ec2020-06-08 19:01:48 -07006367
6368 /* Reset options to default */
6369 nasm_zero(ppopt);
H. Peter Anvinf7606612016-07-13 14:23:48 -07006370
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07006371 if (!use_loaded)
6372 use_loaded = nasm_malloc(use_package_count * sizeof(bool));
6373 memset(use_loaded, 0, use_package_count * sizeof(bool));
6374
H. Peter Anvin6686de22019-08-10 05:33:14 -07006375 /* First set up the top level input file */
6376 nasm_new(istk);
6377 istk->fp = nasm_open_read(file, NF_TEXT);
6378 src_set(0, file);
6379 istk->lineinc = 1;
6380 if (!istk->fp)
6381 nasm_fatalf(ERR_NOFILE, "unable to open input file `%s'", file);
6382
6383 strlist_add(deplist, file);
6384
6385 /*
6386 * Set up the stdmac packages as a virtual include file,
6387 * indicated by a null file pointer.
6388 */
6389 nasm_new(inc);
6390 inc->next = istk;
6391 inc->fname = src_set_fname(NULL);
6392 inc->nolist = !list_option('b');
6393 istk = inc;
6394 lfmt->uplevel(LIST_INCLUDE, 0);
6395
H. Peter Anvin8b262472019-02-26 14:00:54 -08006396 pp_add_magic_stdmac();
6397
H. Peter Anvinf7606612016-07-13 14:23:48 -07006398 if (tasm_compatible_mode)
6399 pp_add_stdmac(nasm_stdmac_tasm);
6400
6401 pp_add_stdmac(nasm_stdmac_nasm);
6402 pp_add_stdmac(nasm_stdmac_version);
6403
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +03006404 if (extrastdmac)
6405 pp_add_stdmac(extrastdmac);
6406
H. Peter Anvinf7606612016-07-13 14:23:48 -07006407 stdmacpos = stdmacros[0];
6408 stdmacnext = &stdmacros[1];
6409
H. Peter Anvind2456592008-06-19 15:04:18 -07006410 do_predef = true;
H. Peter Anvin61f130f2008-09-25 15:45:06 -07006411
H. Peter Anvin61f130f2008-09-25 15:45:06 -07006412 /*
H. Peter Anvind2354082019-08-27 16:38:48 -07006413 * Define the __?PASS?__ macro. This is defined here unlike all the
H. Peter Anvin (Intel)9bb55bd2019-04-24 11:14:43 -07006414 * other builtins, because it is special -- it varies between
6415 * passes -- but there is really no particular reason to make it
6416 * magic.
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006417 *
6418 * 0 = dependencies only
6419 * 1 = preparatory passes
6420 * 2 = final pass
6421 * 3 = preproces only
H. Peter Anvin61f130f2008-09-25 15:45:06 -07006422 */
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006423 switch (mode) {
6424 case PP_NORMAL:
6425 apass = pass_final() ? 2 : 1;
6426 break;
6427 case PP_DEPS:
6428 apass = 0;
6429 break;
6430 case PP_PREPROC:
6431 apass = 3;
6432 break;
6433 default:
6434 panic();
6435 }
6436
H. Peter Anvin8571f062019-09-23 16:40:03 -07006437 define_smacro("__?PASS?__", true, make_tok_num(NULL, apass), NULL);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006438}
6439
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07006440static void pp_init(void)
6441{
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07006442}
6443
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006444/*
6445 * Get a line of tokens. If we popped the macro expansion/include stack,
6446 * we return a pointer to the dummy token tok_pop; at that point if
6447 * istk is NULL then we have reached end of input;
6448 */
6449static Token tok_pop; /* Dummy token placeholder */
6450
6451static Token *pp_tokline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006452{
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006453 while (true) {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006454 Line *l = istk->expansion;
6455 Token *tline = NULL;
6456 Token *dtline;
6457
H. Peter Anvine2c80182005-01-15 22:15:51 +00006458 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006459 * Fetch a tokenized line, either from the macro-expansion
H. Peter Anvine2c80182005-01-15 22:15:51 +00006460 * buffer or from the input file.
6461 */
6462 tline = NULL;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006463 while (l && l->finishes) {
6464 MMacro *fm = l->finishes;
H. Peter Anvineba20a72002-04-30 20:53:55 +00006465
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006466 if (!fm->name && fm->in_progress > 1) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006467 /*
6468 * This is a macro-end marker for a macro with no
6469 * name, which means it's not really a macro at all
6470 * but a %rep block, and the `in_progress' field is
6471 * more than 1, meaning that we still need to
6472 * repeat. (1 means the natural last repetition; 0
6473 * means termination by %exitrep.) We have
6474 * therefore expanded up to the %endrep, and must
6475 * push the whole block on to the expansion buffer
6476 * again. We don't bother to remove the macro-end
6477 * marker: we'd only have to generate another one
6478 * if we did.
6479 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006480 fm->in_progress--;
6481 list_for_each(l, fm->expansion) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006482 Token *t, *tt, **tail;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006483 Line *ll;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006484
Chang S. Baebec812f2020-02-07 15:49:38 -08006485 istk->mstk.mstk->lineno = 0;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006486 nasm_new(ll);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006487 ll->next = istk->expansion;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006488 tail = &ll->first;
6489
6490 list_for_each(t, l->first) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07006491 if (t->len) {
H. Peter Anvin (Intel)1c21a532019-08-09 02:34:21 -07006492 tt = *tail = dup_Token(NULL, t);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006493 tail = &tt->next;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006494 }
6495 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006496 istk->expansion = ll;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006497 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006498 break;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006499 } else {
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006500 MMacro *m = istk->mstk.mstk;
6501
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006502 /*
6503 * Check whether a `%rep' was started and not ended
6504 * within this macro expansion. This can happen and
6505 * should be detected. It's a fatal error because
6506 * I'm too confused to work out how to recover
6507 * sensibly from it.
6508 */
6509 if (defining) {
6510 if (defining->name)
H. Peter Anvinc5136902018-06-15 18:20:17 -07006511 nasm_panic("defining with name in expansion");
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006512 else if (m->name)
H. Peter Anvinc5136902018-06-15 18:20:17 -07006513 nasm_fatal("`%%rep' without `%%endrep' within"
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006514 " expansion of macro `%s'", m->name);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006515 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006516
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006517 /*
6518 * FIXME: investigate the relationship at this point between
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006519 * istk->mstk.mstk and fm
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006520 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006521 istk->mstk = m->mstk;
6522 if (m->name) {
6523 /*
6524 * This was a real macro call, not a %rep, and
6525 * therefore the parameter information needs to
6526 * be freed and the iteration count/nesting
6527 * depth adjusted.
6528 */
6529
6530 if (!--mmacro_deadman.levels) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006531 /*
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006532 * If all mmacro processing done,
6533 * clear all counters and the deadman
6534 * message trigger.
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006535 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006536 nasm_zero(mmacro_deadman); /* Clear all counters */
Adam Majer91e72402017-07-25 10:42:01 +02006537 }
6538
Adam Majer91e72402017-07-25 10:42:01 +02006539#if 0
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006540 if (m->prev) {
6541 pop_mmacro(m);
6542 fm->in_progress --;
6543 } else
Adam Majer91e72402017-07-25 10:42:01 +02006544#endif
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006545 {
6546 nasm_free(m->params);
6547 free_tlist(m->iline);
6548 nasm_free(m->paramlen);
6549 fm->in_progress = 0;
6550 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006551 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006552
6553 /*
6554 * FIXME It is incorrect to always free_mmacro here.
6555 * It leads to usage-after-free.
6556 *
6557 * https://bugzilla.nasm.us/show_bug.cgi?id=3392414
6558 */
6559#if 0
6560 else
6561 free_mmacro(m);
6562#endif
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006563 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006564 istk->expansion = l->next;
6565 nasm_free(l);
6566 lfmt->downlevel(LIST_MACRO);
6567 return &tok_pop;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006568 }
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006569
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006570 do { /* until we get a line we can use */
6571 char *line;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006572
6573 if (istk->expansion) { /* from a macro expansion */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006574 Line *l = istk->expansion;
H. Peter Anvinab6f8312019-08-09 22:31:45 -07006575 int32_t lineno;
6576
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006577 if (istk->mstk.mstk) {
6578 istk->mstk.mstk->lineno++;
6579 if (istk->mstk.mstk->fname)
6580 lineno = istk->mstk.mstk->lineno +
6581 istk->mstk.mstk->xline;
H. Peter Anvin6686de22019-08-10 05:33:14 -07006582 else
6583 lineno = 0; /* Defined at init time or builtin */
6584 } else {
H. Peter Anvinab6f8312019-08-09 22:31:45 -07006585 lineno = src_get_linnum();
H. Peter Anvin6686de22019-08-10 05:33:14 -07006586 }
H. Peter Anvinab6f8312019-08-09 22:31:45 -07006587
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006588 tline = l->first;
6589 istk->expansion = l->next;
6590 nasm_free(l);
H. Peter Anvinab6f8312019-08-09 22:31:45 -07006591
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006592 line = detoken(tline, false);
H. Peter Anvin6686de22019-08-10 05:33:14 -07006593 if (!istk->nolist)
6594 lfmt->line(LIST_MACRO, lineno, line);
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006595 nasm_free(line);
6596 } else if ((line = read_line())) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006597 line = prepreproc(line);
Keith Kaniosb7a89542007-04-12 02:40:54 +00006598 tline = tokenize(line);
H. Peter Anvine2c80182005-01-15 22:15:51 +00006599 nasm_free(line);
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006600 } else {
6601 /*
6602 * The current file has ended; work down the istk
6603 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00006604 Include *i = istk;
H. Peter Anvin6686de22019-08-10 05:33:14 -07006605 if (i->fp)
6606 fclose(i->fp);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006607 if (i->conds) {
6608 /* nasm_error can't be conditionally suppressed */
H. Peter Anvinc5136902018-06-15 18:20:17 -07006609 nasm_fatal("expected `%%endif' before end of file");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006610 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00006611 /* only set line and file name if there's a next node */
H. Peter Anvin274cda82016-05-10 02:56:29 -07006612 if (i->next)
6613 src_set(i->lineno, i->fname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00006614 istk = i->next;
H. Peter Anvin8ac25aa2016-02-18 01:16:18 -08006615 lfmt->downlevel(LIST_INCLUDE);
H. Peter Anvine2c80182005-01-15 22:15:51 +00006616 nasm_free(i);
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006617 return &tok_pop;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006618 }
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006619 } while (0);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006620
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006621 /*
6622 * We must expand MMacro parameters and MMacro-local labels
6623 * _before_ we plunge into directive processing, to cope
6624 * with things like `%define something %1' such as STRUC
6625 * uses. Unless we're _defining_ a MMacro, in which case
6626 * those tokens should be left alone to go into the
6627 * definition; and unless we're in a non-emitting
6628 * condition, in which case we don't want to meddle with
6629 * anything.
6630 */
H. Peter Anvin (Intel)bacf04a2020-06-08 13:29:06 -07006631 if (!defining &&
6632 !(istk->conds && !emitting(istk->conds->state)) &&
6633 !(istk->mstk.mmac && !istk->mstk.mmac->in_progress)) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006634 tline = expand_mmac_params(tline);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006635 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006636
H. Peter Anvine2c80182005-01-15 22:15:51 +00006637 /*
6638 * Check the line to see if it's a preprocessor directive.
6639 */
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006640 if (do_directive(tline, &dtline) == DIRECTIVE_FOUND) {
6641 if (dtline)
6642 return dtline;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006643 } else if (defining) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006644 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006645 * We're defining a multi-line macro. We emit nothing
6646 * at all, and just
6647 * shove the tokenized line on to the macro definition.
H. Peter Anvine2c80182005-01-15 22:15:51 +00006648 */
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006649 MMacro *mmac = defining->dstk.mmac;
6650
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006651 Line *l = nasm_malloc(sizeof(Line));
6652 l->next = defining->expansion;
6653 l->first = tline;
6654 l->finishes = NULL;
6655 defining->expansion = l;
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006656
6657 /*
6658 * Remember if this mmacro expansion contains %00:
6659 * if it does, we will have to handle leading labels
6660 * specially.
6661 */
6662 if (mmac) {
6663 const Token *t;
6664 list_for_each(t, tline) {
H. Peter Anvin8571f062019-09-23 16:40:03 -07006665 if (!memcmp(t->text.a, "%00", 4))
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006666 mmac->capture_label = true;
6667 }
6668 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006669 } else if (istk->conds && !emitting(istk->conds->state)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006670 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006671 * We're in a non-emitting branch of a condition block.
H. Peter Anvine2c80182005-01-15 22:15:51 +00006672 * Emit nothing at all, not even a blank line: when we
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006673 * emerge from the condition we'll give a line-number
H. Peter Anvine2c80182005-01-15 22:15:51 +00006674 * directive so we keep our place correctly.
6675 */
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006676 free_tlist(tline);
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006677 } else if (istk->mstk.mstk && !istk->mstk.mstk->in_progress) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006678 /*
6679 * We're in a %rep block which has been terminated, so
6680 * we're walking through to the %endrep without
6681 * emitting anything. Emit nothing at all, not even a
6682 * blank line: when we emerge from the %rep block we'll
6683 * give a line-number directive so we keep our place
6684 * correctly.
6685 */
6686 free_tlist(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00006687 } else {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006688 tline = expand_smacro(tline);
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006689 if (!expand_mmacro(tline))
6690 return tline;
6691 }
6692 }
6693}
6694
6695static char *pp_getline(void)
6696{
6697 char *line = NULL;
6698 Token *tline;
6699
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006700 while (true) {
6701 tline = pp_tokline();
6702 if (tline == &tok_pop) {
6703 /*
6704 * We popped the macro/include stack. If istk is empty,
6705 * we are at end of input, otherwise just loop back.
6706 */
6707 if (!istk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006708 break;
H. Peter Anvin (Intel)a7afe272019-04-26 00:34:04 -07006709 } else {
6710 /*
6711 * De-tokenize the line and emit it.
6712 */
6713 line = detoken(tline, true);
6714 free_tlist(tline);
6715 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00006716 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006717 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006718
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006719 if (list_option('e') && istk && !istk->nolist && line && line[0]) {
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07006720 char *buf = nasm_strcat(" ;;; ", line);
H. Peter Anvinab6f8312019-08-09 22:31:45 -07006721 lfmt->line(LIST_MACRO, -1, buf);
H. Peter Anvin (Intel)d6e81772019-08-09 08:06:39 -07006722 nasm_free(buf);
6723 }
6724
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006725 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006726}
6727
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006728static void pp_cleanup_pass(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006729{
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006730 if (defining) {
6731 if (defining->name) {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03006732 nasm_nonfatal("end of file while still defining macro `%s'",
6733 defining->name);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006734 } else {
Cyrill Gorcunov295b7952018-11-25 12:55:48 +03006735 nasm_nonfatal("end of file while still in %%rep");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006736 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006737
6738 free_mmacro(defining);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03006739 defining = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006740 }
H. Peter Anvin130736c2016-02-17 20:27:41 -08006741
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006742 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006743 ctx_pop();
H. Peter Anvin97a23472007-09-16 17:57:25 -07006744 free_macros();
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006745 while (istk) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00006746 Include *i = istk;
6747 istk = istk->next;
6748 fclose(i->fp);
Cyrill Gorcunov8dcfd882011-03-03 09:18:56 +03006749 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006750 }
6751 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006752 ctx_pop();
H. Peter Anvin274cda82016-05-10 02:56:29 -07006753 src_set_fname(NULL);
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006754}
6755
6756static void pp_cleanup_session(void)
6757{
H. Peter Anvin (Intel)4b282d02019-08-15 11:53:19 -07006758 nasm_free(use_loaded);
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006759 free_llist(predef);
6760 predef = NULL;
6761 delete_Blocks();
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006762 ipath_list = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006763}
6764
Cyrill Gorcunov8c0666b2018-11-24 14:33:48 +03006765static void pp_include_path(struct strlist *list)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006766{
Cyrill Gorcunov8c0666b2018-11-24 14:33:48 +03006767 ipath_list = list;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006768}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00006769
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04006770static void pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006771{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006772 Token *inc, *space, *name;
6773 Line *l;
6774
H. Peter Anvin734b1882002-04-30 21:01:08 +00006775 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006776 space = new_White(name);
H. Peter Anvin734b1882002-04-30 21:01:08 +00006777 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006778
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006779 l = nasm_malloc(sizeof(Line));
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006780 l->next = predef;
6781 l->first = inc;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006782 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006783 predef = l;
6784}
6785
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04006786static void pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006787{
6788 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006789 Line *l;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00006790 char *equals;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006791
6792 equals = strchr(definition, '=');
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006793 space = new_White(NULL);
H. Peter Anvin734b1882002-04-30 21:01:08 +00006794 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006795 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006796 *equals = ' ';
Keith Kaniosb7a89542007-04-12 02:40:54 +00006797 space->next = tokenize(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006798 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00006799 *equals = '=';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006800
H. Peter Anvin8571f062019-09-23 16:40:03 -07006801 /* We can't predefine a TOK_LOCAL_MACRO for obvious reasons... */
Cyrill Gorcunov6d42e9b2015-02-08 11:07:17 +03006802 if (space->next->type != TOK_PREPROC_ID &&
6803 space->next->type != TOK_ID)
H. Peter Anvin (Intel)80c4f232018-12-14 13:33:24 -08006804 nasm_warn(WARN_OTHER, "pre-defining non ID `%s\'\n", definition);
Cyrill Gorcunov6d42e9b2015-02-08 11:07:17 +03006805
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006806 l = nasm_malloc(sizeof(Line));
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006807 l->next = predef;
6808 l->first = def;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006809 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00006810 predef = l;
6811}
6812
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04006813static void pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00006814{
6815 Token *def, *space;
6816 Line *l;
6817
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006818 space = new_White(NULL);
H. Peter Anvin734b1882002-04-30 21:01:08 +00006819 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Keith Kaniosb7a89542007-04-12 02:40:54 +00006820 space->next = tokenize(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00006821
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006822 l = nasm_malloc(sizeof(Line));
H. Peter Anvin620515a2002-04-30 20:57:38 +00006823 l->next = predef;
6824 l->first = def;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08006825 l->finishes = NULL;
H. Peter Anvin620515a2002-04-30 20:57:38 +00006826 predef = l;
6827}
6828
H. Peter Anvin05990342018-06-11 13:32:42 -07006829/* Insert an early preprocessor command that doesn't need special handling */
6830static void pp_pre_command(const char *what, char *string)
6831{
6832 char *cmd;
6833 Token *def, *space;
6834 Line *l;
6835
6836 def = tokenize(string);
6837 if (what) {
H. Peter Anvin (Intel)f24d9752019-09-18 18:17:26 -07006838 space = new_White(def);
H. Peter Anvin8571f062019-09-23 16:40:03 -07006839 cmd = nasm_strcat(what[0] == '%' ? "" : "%", what);
6840 def = new_Token(space, TOK_PREPROC_ID, cmd, nasm_last_string_len());
6841 nasm_free(cmd);
H. Peter Anvin05990342018-06-11 13:32:42 -07006842 }
6843
6844 l = nasm_malloc(sizeof(Line));
6845 l->next = predef;
6846 l->first = def;
6847 l->finishes = NULL;
6848 predef = l;
6849}
6850
H. Peter Anvinf7606612016-07-13 14:23:48 -07006851static void pp_add_stdmac(macros_t *macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006852{
H. Peter Anvinf7606612016-07-13 14:23:48 -07006853 macros_t **mp;
6854
6855 /* Find the end of the list and avoid duplicates */
6856 for (mp = stdmacros; *mp; mp++) {
6857 if (*mp == macros)
6858 return; /* Nothing to do */
6859 }
6860
6861 nasm_assert(mp < &stdmacros[ARRAY_SIZE(stdmacros)-1]);
6862
6863 *mp = macros;
H. Peter Anvin76690a12002-04-30 20:52:49 +00006864}
6865
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +03006866static void pp_extra_stdmac(macros_t *macros)
6867{
6868 extrastdmac = macros;
6869}
6870
H. Peter Anvin8571f062019-09-23 16:40:03 -07006871/* Create a numeric token */
6872static Token *make_tok_num(Token *next, int64_t val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00006873{
Cyrill Gorcunovce652742013-05-06 23:43:43 +04006874 char numbuf[32];
H. Peter Anvin8b262472019-02-26 14:00:54 -08006875 int len = snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
H. Peter Anvin8571f062019-09-23 16:40:03 -07006876 return new_Token(next, TOK_NUMBER, numbuf, len);
H. Peter Anvin8b262472019-02-26 14:00:54 -08006877}
6878
H. Peter Anvin8571f062019-09-23 16:40:03 -07006879/* Create a quoted string token */
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07006880static Token *make_tok_qstr_len(Token *next, const char *str, size_t len)
H. Peter Anvin8b262472019-02-26 14:00:54 -08006881{
H. Peter Anvin8571f062019-09-23 16:40:03 -07006882 char *p = nasm_quote(str, &len);
6883 return new_Token_free(next, TOK_STRING, p, len);
6884}
H. Peter Anvin (Intel)18f41342019-10-16 15:02:44 -07006885static Token *make_tok_qstr(Token *next, const char *str)
6886{
6887 return make_tok_qstr_len(next, str, strlen(str));
6888}
H. Peter Anvin8571f062019-09-23 16:40:03 -07006889
6890/* Create a single-character operator token */
6891static Token *make_tok_char(Token *next, char op)
6892{
6893 Token *t = new_Token(next, TOK_OTHER, NULL, 1);
6894 t->text.a[0] = op;
H. Peter Anvin8b262472019-02-26 14:00:54 -08006895 return t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00006896}
6897
H. Peter Anvin (Intel)6bde2ed2018-12-13 19:39:41 -08006898static void pp_list_one_macro(MMacro *m, errflags severity)
H. Peter Anvin37368952016-05-09 14:10:32 -07006899{
6900 if (!m)
6901 return;
6902
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006903 /* We need to print the mstk.mmac list in reverse order */
6904 pp_list_one_macro(m->mstk.mmac, severity);
H. Peter Anvin37368952016-05-09 14:10:32 -07006905
6906 if (m->name && !m->nolist) {
H. Peter Anvin274cda82016-05-10 02:56:29 -07006907 src_set(m->xline + m->lineno, m->fname);
H. Peter Anvinddb29062018-12-11 00:06:29 -08006908 nasm_error(severity, "... from macro `%s' defined", m->name);
H. Peter Anvin37368952016-05-09 14:10:32 -07006909 }
6910}
6911
H. Peter Anvin (Intel)6bde2ed2018-12-13 19:39:41 -08006912static void pp_error_list_macros(errflags severity)
H. Peter Anvin4def1a82016-05-09 13:59:44 -07006913{
H. Peter Anvinddb29062018-12-11 00:06:29 -08006914 struct src_location saved;
H. Peter Anvin4def1a82016-05-09 13:59:44 -07006915
H. Peter Anvinddb29062018-12-11 00:06:29 -08006916 severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE;
6917 saved = src_where();
H. Peter Anvin4def1a82016-05-09 13:59:44 -07006918
Cyrill Gorcunov771d04e2016-05-10 23:27:03 +03006919 if (istk)
H. Peter Anvin (Intel)de7acc32019-08-19 17:52:55 -07006920 pp_list_one_macro(istk->mstk.mmac, severity);
H. Peter Anvin4def1a82016-05-09 13:59:44 -07006921
H. Peter Anvinddb29062018-12-11 00:06:29 -08006922 src_update(saved);
H. Peter Anvin4def1a82016-05-09 13:59:44 -07006923}
6924
H. Peter Anvine7469712016-02-18 02:20:59 -08006925const struct preproc_ops nasmpp = {
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07006926 pp_init,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006927 pp_reset,
6928 pp_getline,
H. Peter Anvin (Intel)e55d03d2018-12-18 11:12:46 -08006929 pp_cleanup_pass,
6930 pp_cleanup_session,
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +03006931 pp_extra_stdmac,
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04006932 pp_pre_define,
6933 pp_pre_undefine,
6934 pp_pre_include,
H. Peter Anvin05990342018-06-11 13:32:42 -07006935 pp_pre_command,
H. Peter Anvin4def1a82016-05-09 13:59:44 -07006936 pp_include_path,
6937 pp_error_list_macros,
H. Peter Anvina73ccfe2019-08-28 19:02:47 -07006938 pp_suppress_error
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006939};