blob: 5ae2587d9aca32692c0fdb3851329a908d209203 [file] [log] [blame]
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07001/* ----------------------------------------------------------------------- *
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002 *
H. Peter Anvin05990342018-06-11 13:32:42 -07003 * Copyright 1996-2018 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 Anvind7ed89e2002-04-30 20:52:08 +000065#include <stdio.h>
H. Peter Anvinaf535c12002-04-30 20:59:21 +000066#include <stdarg.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000067#include <stdlib.h>
68#include <stddef.h>
69#include <string.h>
70#include <ctype.h>
H. Peter Anvin76690a12002-04-30 20:52:49 +000071#include <limits.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000072
73#include "nasm.h"
74#include "nasmlib.h"
H. Peter Anvinb20bc732017-03-07 19:23:03 -080075#include "error.h"
H. Peter Anvin4169a472007-09-12 01:29:43 +000076#include "preproc.h"
H. Peter Anvin97a23472007-09-16 17:57:25 -070077#include "hashtbl.h"
H. Peter Anvin8cad14b2008-06-01 17:23:51 -070078#include "quote.h"
H. Peter Anvinc2df2822007-10-24 15:29:28 -070079#include "stdscan.h"
H. Peter Anvindbb640b2009-07-18 18:57:16 -070080#include "eval.h"
H. Peter Anvinc2df2822007-10-24 15:29:28 -070081#include "tokens.h"
H. Peter Anvina4835d42008-05-20 14:21:29 -070082#include "tables.h"
H. Peter Anvin8ac25aa2016-02-18 01:16:18 -080083#include "listing.h"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000084
85typedef struct SMacro SMacro;
H. Peter Anvin36206cd2012-03-03 16:14:51 -080086typedef struct MMacro MMacro;
87typedef struct MMacroInvocation MMacroInvocation;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000088typedef struct Context Context;
89typedef struct Token Token;
H. Peter Anvince616072002-04-30 21:02:23 +000090typedef struct Blocks Blocks;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000091typedef struct Line Line;
92typedef struct Include Include;
H. Peter Anvin36206cd2012-03-03 16:14:51 -080093typedef struct Cond Cond;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000094typedef struct IncPath IncPath;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000095
96/*
H. Peter Anvin97a23472007-09-16 17:57:25 -070097 * Note on the storage of both SMacro and MMacros: the hash table
98 * indexes them case-insensitively, and we then have to go through a
99 * linked list of potential case aliases (and, for MMacros, parameter
100 * ranges); this is to preserve the matching semantics of the earlier
101 * code. If the number of case aliases for a specific macro is a
102 * performance issue, you may want to reconsider your coding style.
103 */
104
105/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000106 * Store the definition of a single-line macro.
107 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000108struct SMacro {
H. Peter Anvin8b262472019-02-26 14:00:54 -0800109 SMacro *next; /* MUST BE FIRST - see free_smacro() */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800110 char *name;
H. Peter Anvin8b262472019-02-26 14:00:54 -0800111 union {
112 Token *expansion;
113 Token *(*magic)(const SMacro *s, Token **params, int *paramsize);
114 } e;
115 bool *eval_param;
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800116 unsigned int nparam;
H. Peter Anvin8b262472019-02-26 14:00:54 -0800117 bool casesense;
118 bool magic;
119 bool in_progress;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000120};
121
122/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800123 * Store the definition of a multi-line macro. This is also used to
124 * store the interiors of `%rep...%endrep' blocks, which are
125 * effectively self-re-invoking multi-line macros which simply
126 * don't have a name or bother to appear in the hash tables. %rep
127 * blocks are signified by having a NULL `name' field.
128 *
129 * In a MMacro describing a `%rep' block, the `in_progress' field
130 * isn't merely boolean, but gives the number of repeats left to
131 * run.
132 *
133 * The `next' field is used for storing MMacros in hash tables; the
134 * `next_active' field is for stacking them on istk entries.
135 *
136 * When a MMacro is being expanded, `params', `iline', `nparam',
137 * `paramlen', `rotate' and `unique' are local to the invocation.
138 */
139struct MMacro {
140 MMacro *next;
141 MMacroInvocation *prev; /* previous invocation */
142 char *name;
143 int nparam_min, nparam_max;
144 bool casesense;
145 bool plus; /* is the last parameter greedy? */
146 bool nolist; /* is this macro listing-inhibited? */
147 int64_t in_progress; /* is this macro currently being expanded? */
148 int32_t max_depth; /* maximum number of recursive expansions allowed */
149 Token *dlist; /* All defaults as one list */
150 Token **defaults; /* Parameter default pointers */
151 int ndefs; /* number of default parameters */
152 Line *expansion;
153
154 MMacro *next_active;
155 MMacro *rep_nest; /* used for nesting %rep */
156 Token **params; /* actual parameters */
157 Token *iline; /* invocation line */
158 unsigned int nparam, rotate;
159 int *paramlen;
160 uint64_t unique;
161 int lineno; /* Current line number on expansion */
162 uint64_t condcnt; /* number of if blocks... */
H. Peter Anvin4def1a82016-05-09 13:59:44 -0700163
H. Peter Anvin274cda82016-05-10 02:56:29 -0700164 const char *fname; /* File where defined */
H. Peter Anvin4def1a82016-05-09 13:59:44 -0700165 int32_t xline; /* First line in macro */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800166};
167
168
169/* Store the definition of a multi-line macro, as defined in a
170 * previous recursive macro expansion.
171 */
172struct MMacroInvocation {
173 MMacroInvocation *prev; /* previous invocation */
174 Token **params; /* actual parameters */
175 Token *iline; /* invocation line */
176 unsigned int nparam, rotate;
177 int *paramlen;
178 uint64_t unique;
179 uint64_t condcnt;
180};
181
182
183/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000184 * The context stack is composed of a linked list of these.
185 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000186struct Context {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800187 Context *next;
188 char *name;
189 struct hash_table localmac;
190 uint32_t number;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000191};
192
193/*
194 * This is the internal form which we break input lines up into.
195 * Typically stored in linked lists.
196 *
H. Peter Anvin8b262472019-02-26 14:00:54 -0800197 * Note that `type' serves a double meaning: TOK_SMAC_START_PARAMS is
198 * not necessarily used as-is, but is also used to encode the number
199 * and expansion type of substituted parameter. So in the definition
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000200 *
H. Peter Anvin8b262472019-02-26 14:00:54 -0800201 * %define a(x,=y) ( (x) & ~(y) )
H. Peter Anvin70653092007-10-19 14:42:29 -0700202 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000203 * the token representing `x' will have its type changed to
H. Peter Anvin8b262472019-02-26 14:00:54 -0800204 * tok_smac_param(0) but the one representing `y' will be
205 * tok_smac_param(1); see the accessor functions below.
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000206 *
207 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
208 * which doesn't need quotes around it. Used in the pre-include
209 * mechanism as an alternative to trying to find a sensible type of
210 * quote to use on the filename we were passed.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000211 */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000212enum pp_token_type {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800213 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID,
214 TOK_PREPROC_ID, TOK_STRING,
H. Peter Anvin8b262472019-02-26 14:00:54 -0800215 TOK_NUMBER, TOK_FLOAT, TOK_OTHER,
H. Peter Anvin6c81f0a2008-05-25 21:46:17 -0700216 TOK_INTERNAL_STRING,
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800217 TOK_PREPROC_Q, TOK_PREPROC_QQ,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300218 TOK_PASTE, /* %+ */
219 TOK_INDIRECT, /* %[...] */
H. Peter Anvin8b262472019-02-26 14:00:54 -0800220 TOK_SMAC_END, /* Marker for the end of smacro expansion */
221 TOK_SMAC_START_PARAMS, /* MUST BE LAST IN THE LIST!!! */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300222 TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000223};
224
H. Peter Anvin8b262472019-02-26 14:00:54 -0800225static inline enum pp_token_type tok_smac_param(int param)
226{
227 return TOK_SMAC_START_PARAMS + param;
228}
229static int smac_nparam(enum pp_token_type toktype)
230{
231 return toktype - TOK_SMAC_START_PARAMS;
232}
233static bool is_smac_param(enum pp_token_type toktype)
234{
235 return toktype >= TOK_SMAC_START_PARAMS;
236}
237
Cyrill Gorcunov8dcbbd72010-09-25 02:33:20 +0400238#define PP_CONCAT_MASK(x) (1 << (x))
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +0400239#define PP_CONCAT_MATCH(t, mask) (PP_CONCAT_MASK((t)->type) & mask)
Cyrill Gorcunov8dcbbd72010-09-25 02:33:20 +0400240
Cyrill Gorcunov575d4282010-10-06 00:25:55 +0400241struct tokseq_match {
242 int mask_head;
243 int mask_tail;
244};
245
H. Peter Anvine2c80182005-01-15 22:15:51 +0000246struct Token {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800247 Token *next;
248 char *text;
H. Peter Anvinf26e0972008-07-01 21:26:27 -0700249 union {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800250 SMacro *mac; /* associated macro for TOK_SMAC_END */
251 size_t len; /* scratch length field */
252 } a; /* Auxiliary data */
253 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000254};
255
256/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800257 * Multi-line macro definitions are stored as a linked list of
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000258 * these, which is essentially a container to allow several linked
259 * lists of Tokens.
H. Peter Anvin70653092007-10-19 14:42:29 -0700260 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000261 * Note that in this module, linked lists are treated as stacks
262 * wherever possible. For this reason, Lines are _pushed_ on to the
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800263 * `expansion' field in MMacro structures, so that the linked list,
264 * if walked, would give the macro lines in reverse order; this
265 * means that we can walk the list when expanding a macro, and thus
266 * push the lines on to the `expansion' field in _istk_ in reverse
267 * order (so that when popped back off they are in the right
268 * order). It may seem cockeyed, and it relies on my design having
269 * an even number of steps in, but it works...
270 *
271 * Some of these structures, rather than being actual lines, are
272 * markers delimiting the end of the expansion of a given macro.
273 * This is for use in the cycle-tracking and %rep-handling code.
274 * Such structures have `finishes' non-NULL, and `first' NULL. All
275 * others have `finishes' NULL, but `first' may still be NULL if
276 * the line is blank.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000277 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000278struct Line {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800279 Line *next;
280 MMacro *finishes;
281 Token *first;
Keith Kaniosb307a4f2010-11-06 17:41:51 -0500282};
283
284/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000285 * To handle an arbitrary level of file inclusion, we maintain a
286 * stack (ie linked list) of these things.
287 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000288struct Include {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800289 Include *next;
290 FILE *fp;
291 Cond *conds;
292 Line *expansion;
H. Peter Anvin274cda82016-05-10 02:56:29 -0700293 const char *fname;
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800294 int lineno, lineinc;
295 MMacro *mstk; /* stack of active macros/reps */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000296};
297
298/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000299 * Include search path. This is simply a list of strings which get
300 * prepended, in turn, to the name of an include file, in an
301 * attempt to find the file if it's not in the current directory.
302 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000303struct IncPath {
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800304 IncPath *next;
305 char *path;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000306};
307
308/*
H. Peter Anvin169ac7c2016-09-25 17:08:05 -0700309 * File real name hash, so we don't have to re-search the include
310 * path for every pass (and potentially more than that if a file
311 * is used more than once.)
312 */
313struct hash_table FileHash;
314
315/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000316 * Conditional assembly: we maintain a separate stack of these for
317 * each level of file inclusion. (The only reason we keep the
318 * stacks separate is to ensure that a stray `%endif' in a file
319 * included from within the true branch of a `%if' won't terminate
320 * it and cause confusion: instead, rightly, it'll cause an error.)
321 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800322struct Cond {
323 Cond *next;
324 int state;
325};
H. Peter Anvine2c80182005-01-15 22:15:51 +0000326enum {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000327 /*
328 * These states are for use just after %if or %elif: IF_TRUE
329 * means the condition has evaluated to truth so we are
330 * currently emitting, whereas IF_FALSE means we are not
331 * currently emitting but will start doing so if a %else comes
332 * up. In these states, all directives are admissible: %elif,
333 * %else and %endif. (And of course %if.)
334 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800335 COND_IF_TRUE, COND_IF_FALSE,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000336 /*
337 * These states come up after a %else: ELSE_TRUE means we're
338 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
339 * any %elif or %else will cause an error.
340 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800341 COND_ELSE_TRUE, COND_ELSE_FALSE,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000342 /*
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200343 * These states mean that we're not emitting now, and also that
344 * nothing until %endif will be emitted at all. COND_DONE is
345 * used when we've had our moment of emission
346 * and have now started seeing %elifs. COND_NEVER is used when
347 * the condition construct in question is contained within a
348 * non-emitting branch of a larger condition construct,
349 * or if there is an error.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000350 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800351 COND_DONE, COND_NEVER
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000352};
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800353#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000354
H. Peter Anvin70653092007-10-19 14:42:29 -0700355/*
Ed Beroset3ab3f412002-06-11 03:31:49 +0000356 * These defines are used as the possible return values for do_directive
357 */
358#define NO_DIRECTIVE_FOUND 0
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300359#define DIRECTIVE_FOUND 1
Ed Beroset3ab3f412002-06-11 03:31:49 +0000360
Cyrill Gorcunove091d6e2010-08-09 13:58:22 +0400361/* max reps */
362#define REP_LIMIT ((INT64_C(1) << 62))
363
Keith Kanios852f1ee2009-07-12 00:19:55 -0500364/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000365 * Condition codes. Note that we use c_ prefix not C_ because C_ is
366 * used in nasm.h for the "real" condition codes. At _this_ level,
367 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
368 * ones, so we need a different enum...
369 */
H. Peter Anvin476d2862007-10-02 22:04:15 -0700370static const char * const conditions[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000371 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
372 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
H. Peter Anvince9be342007-09-12 00:22:29 +0000373 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000374};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700375enum pp_conds {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000376 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
377 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 -0700378 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
379 c_none = -1
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000380};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700381static const enum pp_conds inverse_ccs[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000382 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
383 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 +0000384 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000385};
386
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800387/*
388 * Directive names.
389 */
390/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
391static int is_condition(enum preproc_token arg)
392{
393 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
394}
395
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000396/* For TASM compatibility we need to be able to recognise TASM compatible
397 * conditional compilation directives. Using the NASM pre-processor does
398 * not work, so we look for them specifically from the following list and
399 * then jam in the equivalent NASM directive into the input stream.
400 */
401
H. Peter Anvine2c80182005-01-15 22:15:51 +0000402enum {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000403 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
404 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
405};
406
H. Peter Anvin476d2862007-10-02 22:04:15 -0700407static const char * const tasm_directives[] = {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000408 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
409 "ifndef", "include", "local"
410};
411
412static int StackSize = 4;
H. Peter Anvin6c8b2be2016-05-24 23:46:50 -0700413static const char *StackPointer = "ebp";
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000414static int ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -0800415static int LocalOffset = 0;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000416
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000417static Context *cstk;
418static Include *istk;
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800419static IncPath *ipath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000420
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300421static int pass; /* HACK: pass 0 = generate dependencies only */
H. Peter Anvin9924d1e2016-10-04 00:59:39 -0700422static StrList **dephead;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000423
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300424static uint64_t unique; /* unique identifier numbers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000425
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800426static Line *predef = NULL;
H. Peter Anvind2456592008-06-19 15:04:18 -0700427static bool do_predef;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000428
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000429/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800430 * The current set of multi-line macros we have defined.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000431 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800432static struct hash_table mmacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000433
434/*
435 * The current set of single-line macros we have defined.
436 */
H. Peter Anvin166c2472008-05-28 12:28:58 -0700437static struct hash_table smacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000438
439/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800440 * The multi-line macro we are currently defining, or the %rep
441 * block we are currently reading, if any.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000442 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800443static MMacro *defining;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000444
Charles Crayned4200be2008-07-12 16:42:33 -0700445static uint64_t nested_mac_count;
446static uint64_t nested_rep_count;
447
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000448/*
449 * The number of macro parameters to allocate space for at a time.
450 */
451#define PARAM_DELTA 16
452
453/*
H. Peter Anvinf7606612016-07-13 14:23:48 -0700454 * The standard macro set: defined in macros.c in a set of arrays.
455 * This gives our position in any macro set, while we are processing it.
456 * The stdmacset is an array of such macro sets.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000457 */
H. Peter Anvina70547f2008-07-19 21:44:26 -0700458static macros_t *stdmacpos;
H. Peter Anvinf7606612016-07-13 14:23:48 -0700459static macros_t **stdmacnext;
460static macros_t *stdmacros[8];
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +0300461static macros_t *extrastdmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000462
463/*
H. Peter Anvin734b1882002-04-30 21:01:08 +0000464 * Tokens are allocated in blocks to improve speed
465 */
466#define TOKEN_BLOCKSIZE 4096
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800467static Token *freeTokens = NULL;
H. Peter Anvince616072002-04-30 21:02:23 +0000468struct Blocks {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000469 Blocks *next;
470 void *chunk;
H. Peter Anvince616072002-04-30 21:02:23 +0000471};
472
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800473static Blocks blocks = { NULL, NULL };
H. Peter Anvin734b1882002-04-30 21:01:08 +0000474
475/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000476 * Forward declarations.
477 */
H. Peter Anvinf7606612016-07-13 14:23:48 -0700478static void pp_add_stdmac(macros_t *macros);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000479static Token *expand_mmac_params(Token * tline);
480static Token *expand_smacro(Token * tline);
481static Token *expand_id(Token * tline);
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +0400482static Context *get_ctx(const char *name, const char **namep);
H. Peter Anvin8b262472019-02-26 14:00:54 -0800483static Token *make_tok_num(int64_t val);
484static Token *make_tok_qstr(const char *str);
H. Peter Anvin130736c2016-02-17 20:27:41 -0800485static void pp_verror(int severity, const char *fmt, va_list ap);
486static vefunc real_verror;
H. Peter Anvince616072002-04-30 21:02:23 +0000487static void *new_Block(size_t size);
488static void delete_Blocks(void);
H. Peter Anvinc751e862008-06-09 10:18:45 -0700489static Token *new_Token(Token * next, enum pp_token_type type,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300490 const char *text, int txtlen);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000491static Token *delete_Token(Token * t);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000492
493/*
494 * Macros for safe checking of token pointers, avoid *(NULL)
495 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300496#define tok_type_(x,t) ((x) && (x)->type == (t))
497#define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
498#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
499#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
H. Peter Anvin76690a12002-04-30 20:52:49 +0000500
Cyrill Gorcunov194ba892011-06-30 01:16:35 +0400501/*
H. Peter Anvin077fb932010-07-20 14:56:30 -0700502 * nasm_unquote with error if the string contains NUL characters.
503 * If the string contains NUL characters, issue an error and return
504 * the C len, i.e. truncate at the NUL.
505 */
506static size_t nasm_unquote_cstr(char *qstr, enum preproc_token directive)
507{
508 size_t len = nasm_unquote(qstr, NULL);
509 size_t clen = strlen(qstr);
510
511 if (len != clen)
H. Peter Anvin130736c2016-02-17 20:27:41 -0800512 nasm_error(ERR_NONFATAL, "NUL character in `%s' directive",
H. Peter Anvin077fb932010-07-20 14:56:30 -0700513 pp_directives[directive]);
514
515 return clen;
516}
517
518/*
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700519 * In-place reverse a list of tokens.
520 */
521static Token *reverse_tokens(Token *t)
522{
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800523 Token *prev = NULL;
524 Token *next;
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700525
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800526 while (t) {
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +0400527 next = t->next;
528 t->next = prev;
529 prev = t;
530 t = next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800531 }
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700532
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800533 return prev;
H. Peter Anvinb40992c2010-09-15 08:57:21 -0700534}
535
536/*
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300537 * Handle TASM specific directives, which do not contain a % in
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000538 * front of them. We do it here because I could not find any other
539 * place to do it for the moment, and it is a hack (ideally it would
540 * be nice to be able to use the NASM pre-processor to do it).
541 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000542static char *check_tasm_directive(char *line)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000543{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000544 int32_t i, j, k, m, len;
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400545 char *p, *q, *oldline, oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000546
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400547 p = nasm_skip_spaces(line);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000548
549 /* Binary search for the directive name */
550 i = -1;
Cyrill Gorcunova7319242010-06-03 22:04:36 +0400551 j = ARRAY_SIZE(tasm_directives);
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +0400552 q = nasm_skip_word(p);
553 len = q - p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000554 if (len) {
555 oldchar = p[len];
556 p[len] = 0;
557 while (j - i > 1) {
558 k = (j + i) / 2;
559 m = nasm_stricmp(p, tasm_directives[k]);
560 if (m == 0) {
561 /* We have found a directive, so jam a % in front of it
562 * so that NASM will then recognise it as one if it's own.
563 */
564 p[len] = oldchar;
565 len = strlen(p);
566 oldline = line;
567 line = nasm_malloc(len + 2);
568 line[0] = '%';
569 if (k == TM_IFDIFI) {
H. Peter Anvin18f48792009-06-27 15:56:27 -0700570 /*
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300571 * NASM does not recognise IFDIFI, so we convert
572 * it to %if 0. This is not used in NASM
573 * compatible code, but does need to parse for the
574 * TASM macro package.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000575 */
H. Peter Anvin18f48792009-06-27 15:56:27 -0700576 strcpy(line + 1, "if 0");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000577 } else {
578 memcpy(line + 1, p, len + 1);
579 }
580 nasm_free(oldline);
581 return line;
582 } else if (m < 0) {
583 j = k;
584 } else
585 i = k;
586 }
587 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000588 }
589 return line;
590}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000591
H. Peter Anvin76690a12002-04-30 20:52:49 +0000592/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000593 * The pre-preprocessing stage... This function translates line
594 * number indications as they emerge from GNU cpp (`# lineno "file"
595 * flags') into NASM preprocessor line number indications (`%line
596 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000597 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000598static char *prepreproc(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000599{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000600 int lineno, fnlen;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000601 char *fname, *oldline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000602
H. Peter Anvine2c80182005-01-15 22:15:51 +0000603 if (line[0] == '#' && line[1] == ' ') {
604 oldline = line;
605 fname = oldline + 2;
606 lineno = atoi(fname);
607 fname += strspn(fname, "0123456789 ");
608 if (*fname == '"')
609 fname++;
610 fnlen = strcspn(fname, "\"");
611 line = nasm_malloc(20 + fnlen);
612 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
613 nasm_free(oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000614 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000615 if (tasm_compatible_mode)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000616 return check_tasm_directive(line);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000617 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000618}
619
620/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000621 * Free a linked list of tokens.
622 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000623static void free_tlist(Token * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000624{
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400625 while (list)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000626 list = delete_Token(list);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000627}
628
629/*
630 * Free a linked list of lines.
631 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000632static void free_llist(Line * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000633{
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400634 Line *l, *tmp;
635 list_for_each_safe(l, tmp, list) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000636 free_tlist(l->first);
637 nasm_free(l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000638 }
639}
640
641/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800642 * Free an MMacro
H. Peter Anvineba20a72002-04-30 20:53:55 +0000643 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800644static void free_mmacro(MMacro * m)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000645{
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800646 nasm_free(m->name);
647 free_tlist(m->dlist);
648 nasm_free(m->defaults);
649 free_llist(m->expansion);
650 nasm_free(m);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000651}
652
653/*
H. Peter Anvin8b262472019-02-26 14:00:54 -0800654 * Free an SMacro
655 */
656static void free_smacro(SMacro *s, bool really)
657{
658 nasm_free(s->name);
659 if (!s->magic)
660 free_tlist(s->e.expansion);
661 nasm_free(s->eval_param);
662 if (really) {
663 nasm_free(s);
664 } else {
665 /* Wipe everything except the next pointer */
666 memset(&s->next + 1, 0, sizeof *s - sizeof s->next);
667 }
668}
669
670/*
H. Peter Anvin97a23472007-09-16 17:57:25 -0700671 * Free all currently defined macros, and free the hash tables
672 */
H. Peter Anvin072771e2008-05-22 13:17:51 -0700673static void free_smacro_table(struct hash_table *smt)
H. Peter Anvin97a23472007-09-16 17:57:25 -0700674{
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +0400675 SMacro *s, *tmp;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700676 const char *key;
677 struct hash_tbl_node *it = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -0700678
H. Peter Anvin072771e2008-05-22 13:17:51 -0700679 while ((s = hash_iterate(smt, &it, &key)) != NULL) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300680 nasm_free((void *)key);
H. Peter Anvin8b262472019-02-26 14:00:54 -0800681 list_for_each_safe(s, tmp, s)
682 free_smacro(s, true);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700683 }
H. Peter Anvin072771e2008-05-22 13:17:51 -0700684 hash_free(smt);
685}
686
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800687static void free_mmacro_table(struct hash_table *mmt)
H. Peter Anvin072771e2008-05-22 13:17:51 -0700688{
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800689 MMacro *m, *tmp;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700690 const char *key;
691 struct hash_tbl_node *it = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -0700692
693 it = NULL;
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800694 while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300695 nasm_free((void *)key);
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800696 list_for_each_safe(m ,tmp, m)
697 free_mmacro(m);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700698 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800699 hash_free(mmt);
H. Peter Anvin072771e2008-05-22 13:17:51 -0700700}
701
702static void free_macros(void)
703{
H. Peter Anvin166c2472008-05-28 12:28:58 -0700704 free_smacro_table(&smacros);
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800705 free_mmacro_table(&mmacros);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700706}
707
708/*
709 * Initialize the hash tables
710 */
711static void init_macros(void)
712{
H. Peter Anvin166c2472008-05-28 12:28:58 -0700713 hash_init(&smacros, HASH_LARGE);
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800714 hash_init(&mmacros, HASH_LARGE);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700715}
716
717/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000718 * Pop the context stack.
719 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000720static void ctx_pop(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000721{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000722 Context *c = cstk;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000723
724 cstk = cstk->next;
H. Peter Anvin166c2472008-05-28 12:28:58 -0700725 free_smacro_table(&c->localmac);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000726 nasm_free(c->name);
727 nasm_free(c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000728}
729
H. Peter Anvin072771e2008-05-22 13:17:51 -0700730/*
731 * Search for a key in the hash index; adding it if necessary
732 * (in which case we initialize the data pointer to NULL.)
733 */
734static void **
735hash_findi_add(struct hash_table *hash, const char *str)
736{
737 struct hash_insert hi;
738 void **r;
739 char *strx;
740
741 r = hash_findi(hash, str, &hi);
742 if (r)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300743 return r;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700744
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300745 strx = nasm_strdup(str); /* Use a more efficient allocator here? */
H. Peter Anvin072771e2008-05-22 13:17:51 -0700746 return hash_add(&hi, strx, NULL);
747}
748
749/*
750 * Like hash_findi, but returns the data element rather than a pointer
751 * to it. Used only when not adding a new element, hence no third
752 * argument.
753 */
754static void *
755hash_findix(struct hash_table *hash, const char *str)
756{
757 void **p;
758
759 p = hash_findi(hash, str, NULL);
760 return p ? *p : NULL;
761}
762
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +0400763/*
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800764 * read line from standart macros set,
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +0400765 * if there no more left -- return NULL
766 */
767static char *line_from_stdmac(void)
768{
769 unsigned char c;
770 const unsigned char *p = stdmacpos;
771 char *line, *q;
772 size_t len = 0;
773
774 if (!stdmacpos)
775 return NULL;
776
777 while ((c = *p++)) {
778 if (c >= 0x80)
779 len += pp_directives_len[c - 0x80] + 1;
780 else
781 len++;
782 }
783
784 line = nasm_malloc(len + 1);
785 q = line;
786 while ((c = *stdmacpos++)) {
787 if (c >= 0x80) {
788 memcpy(q, pp_directives[c - 0x80], pp_directives_len[c - 0x80]);
789 q += pp_directives_len[c - 0x80];
790 *q++ = ' ';
791 } else {
792 *q++ = c;
793 }
794 }
795 stdmacpos = p;
796 *q = '\0';
797
798 if (!*stdmacpos) {
H. Peter Anvinf7606612016-07-13 14:23:48 -0700799 /* This was the last of this particular macro set */
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +0400800 stdmacpos = NULL;
H. Peter Anvinf7606612016-07-13 14:23:48 -0700801 if (*stdmacnext) {
802 stdmacpos = *stdmacnext++;
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +0400803 } else if (do_predef) {
804 Line *pd, *l;
805 Token *head, **tail, *t;
806
807 /*
808 * Nasty hack: here we push the contents of
809 * `predef' on to the top-level expansion stack,
810 * since this is the most convenient way to
811 * implement the pre-include and pre-define
812 * features.
813 */
814 list_for_each(pd, predef) {
815 head = NULL;
816 tail = &head;
817 list_for_each(t, pd->first) {
818 *tail = new_Token(NULL, t->type, t->text, 0);
819 tail = &(*tail)->next;
820 }
821
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800822 l = nasm_malloc(sizeof(Line));
823 l->next = istk->expansion;
824 l->first = head;
825 l->finishes = NULL;
826
827 istk->expansion = l;
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +0400828 }
829 do_predef = false;
830 }
831 }
832
833 return line;
834}
835
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000836static char *read_line(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000837{
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +0400838 unsigned int size, c, next;
839 const unsigned int delta = 512;
840 const unsigned int pad = 8;
841 unsigned int nr_cont = 0;
842 bool cont = false;
843 char *buffer, *p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000844
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +0400845 /* Standart macros set (predefined) goes first */
Cyrill Gorcunov15bdc512010-07-13 11:27:41 +0400846 p = line_from_stdmac();
847 if (p)
848 return p;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700849
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +0400850 size = delta;
851 p = buffer = nasm_malloc(size);
852
853 for (;;) {
854 c = fgetc(istk->fp);
855 if ((int)(c) == EOF) {
856 p[0] = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000857 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000858 }
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +0400859
860 switch (c) {
861 case '\r':
862 next = fgetc(istk->fp);
863 if (next != '\n')
864 ungetc(next, istk->fp);
865 if (cont) {
866 cont = false;
867 continue;
868 }
869 break;
870
871 case '\n':
872 if (cont) {
873 cont = false;
874 continue;
875 }
876 break;
877
878 case '\\':
879 next = fgetc(istk->fp);
880 ungetc(next, istk->fp);
Cyrill Gorcunov490f85e2012-12-27 20:02:17 +0400881 if (next == '\r' || next == '\n') {
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +0400882 cont = true;
883 nr_cont++;
884 continue;
885 }
886 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000887 }
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +0400888
889 if (c == '\r' || c == '\n') {
890 *p++ = 0;
891 break;
892 }
893
894 if (p >= (buffer + size - pad)) {
895 buffer = nasm_realloc(buffer, size + delta);
896 p = buffer + size - pad;
897 size += delta;
898 }
899
900 *p++ = (unsigned char)c;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000901 }
902
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +0400903 if (p == buffer) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000904 nasm_free(buffer);
905 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000906 }
907
Cyrill Gorcunova5aea572010-11-11 10:14:45 +0300908 src_set_linnum(src_get_linnum() + istk->lineinc +
Cyrill Gorcunovf1fe4fd2012-10-27 19:27:18 +0400909 (nr_cont * istk->lineinc));
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000910
911 /*
912 * Handle spurious ^Z, which may be inserted into source files
913 * by some file transfer utilities.
914 */
915 buffer[strcspn(buffer, "\032")] = '\0';
916
H. Peter Anvin8ac25aa2016-02-18 01:16:18 -0800917 lfmt->line(LIST_READ, buffer);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000918
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000919 return buffer;
920}
921
922/*
Keith Kaniosb7a89542007-04-12 02:40:54 +0000923 * Tokenize a line of text. This is a very simple process since we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000924 * don't need to parse the value out of e.g. numeric tokens: we
925 * simply split one string into many.
926 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000927static Token *tokenize(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000928{
H. Peter Anvinca544db2008-10-19 19:30:11 -0700929 char c, *p = line;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000930 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000931 Token *list = NULL;
932 Token *t, **tail = &list;
933
H. Peter Anvine2c80182005-01-15 22:15:51 +0000934 while (*line) {
935 p = line;
936 if (*p == '%') {
937 p++;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300938 if (*p == '+' && !nasm_isdigit(p[1])) {
939 p++;
940 type = TOK_PASTE;
941 } else if (nasm_isdigit(*p) ||
942 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000943 do {
944 p++;
945 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700946 while (nasm_isdigit(*p));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000947 type = TOK_PREPROC_ID;
948 } else if (*p == '{') {
949 p++;
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800950 while (*p) {
951 if (*p == '}')
952 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000953 p[-1] = *p;
954 p++;
955 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800956 if (*p != '}')
H. Peter Anvin130736c2016-02-17 20:27:41 -0800957 nasm_error(ERR_WARNING | ERR_PASS1,
958 "unterminated %%{ construct");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000959 p[-1] = '\0';
960 if (*p)
961 p++;
962 type = TOK_PREPROC_ID;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300963 } else if (*p == '[') {
964 int lvl = 1;
965 line += 2; /* Skip the leading %[ */
966 p++;
967 while (lvl && (c = *p++)) {
968 switch (c) {
969 case ']':
970 lvl--;
971 break;
972 case '%':
973 if (*p == '[')
974 lvl++;
975 break;
976 case '\'':
977 case '\"':
978 case '`':
Cyrill Gorcunov3144e842017-10-22 10:50:55 +0300979 p = nasm_skip_string(p - 1);
980 if (*p)
981 p++;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300982 break;
983 default:
984 break;
985 }
986 }
987 p--;
988 if (*p)
989 *p++ = '\0';
H. Peter Anvin36206cd2012-03-03 16:14:51 -0800990 if (lvl)
H. Peter Anvin130736c2016-02-17 20:27:41 -0800991 nasm_error(ERR_NONFATAL|ERR_PASS1,
992 "unterminated %%[ construct");
Cyrill Gorcunovaccda192010-02-16 10:27:56 +0300993 type = TOK_INDIRECT;
994 } else if (*p == '?') {
995 type = TOK_PREPROC_Q; /* %? */
996 p++;
997 if (*p == '?') {
998 type = TOK_PREPROC_QQ; /* %?? */
999 p++;
1000 }
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001001 } else if (*p == '!') {
1002 type = TOK_PREPROC_ID;
1003 p++;
1004 if (isidchar(*p)) {
1005 do {
1006 p++;
1007 }
1008 while (isidchar(*p));
1009 } else if (*p == '\'' || *p == '\"' || *p == '`') {
1010 p = nasm_skip_string(p);
1011 if (*p)
1012 p++;
1013 else
H. Peter Anvin130736c2016-02-17 20:27:41 -08001014 nasm_error(ERR_NONFATAL|ERR_PASS1,
1015 "unterminated %%! string");
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001016 } else {
1017 /* %! without string or identifier */
1018 type = TOK_OTHER; /* Legacy behavior... */
1019 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001020 } else if (isidchar(*p) ||
1021 ((*p == '!' || *p == '%' || *p == '$') &&
1022 isidchar(p[1]))) {
1023 do {
1024 p++;
1025 }
1026 while (isidchar(*p));
1027 type = TOK_PREPROC_ID;
1028 } else {
1029 type = TOK_OTHER;
1030 if (*p == '%')
1031 p++;
1032 }
1033 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
1034 type = TOK_ID;
1035 p++;
1036 while (*p && isidchar(*p))
1037 p++;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07001038 } else if (*p == '\'' || *p == '"' || *p == '`') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001039 /*
1040 * A string token.
1041 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001042 type = TOK_STRING;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001043 p = nasm_skip_string(p);
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001044
H. Peter Anvine2c80182005-01-15 22:15:51 +00001045 if (*p) {
1046 p++;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001047 } else {
H. Peter Anvin130736c2016-02-17 20:27:41 -08001048 nasm_error(ERR_WARNING|ERR_PASS1, "unterminated string");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001049 /* Handling unterminated strings by UNV */
1050 /* type = -1; */
1051 }
Victor van den Elzenfb5f2512009-04-17 16:17:59 +02001052 } else if (p[0] == '$' && p[1] == '$') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001053 type = TOK_OTHER; /* TOKEN_BASE */
Victor van den Elzenfb5f2512009-04-17 16:17:59 +02001054 p += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001055 } else if (isnumstart(*p)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001056 bool is_hex = false;
1057 bool is_float = false;
1058 bool has_e = false;
1059 char c, *r;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001060
H. Peter Anvine2c80182005-01-15 22:15:51 +00001061 /*
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001062 * A numeric token.
H. Peter Anvine2c80182005-01-15 22:15:51 +00001063 */
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001064
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001065 if (*p == '$') {
1066 p++;
1067 is_hex = true;
1068 }
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001069
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001070 for (;;) {
1071 c = *p++;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001072
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001073 if (!is_hex && (c == 'e' || c == 'E')) {
1074 has_e = true;
1075 if (*p == '+' || *p == '-') {
1076 /*
1077 * e can only be followed by +/- if it is either a
1078 * prefixed hex number or a floating-point number
1079 */
1080 p++;
1081 is_float = true;
1082 }
1083 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
1084 is_hex = true;
1085 } else if (c == 'P' || c == 'p') {
1086 is_float = true;
1087 if (*p == '+' || *p == '-')
1088 p++;
Martin Lindheb150e382016-11-16 15:36:53 +01001089 } else if (isnumchar(c))
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001090 ; /* just advance */
1091 else if (c == '.') {
1092 /*
1093 * we need to deal with consequences of the legacy
1094 * parser, like "1.nolist" being two tokens
1095 * (TOK_NUMBER, TOK_ID) here; at least give it
1096 * a shot for now. In the future, we probably need
1097 * a flex-based scanner with proper pattern matching
1098 * to do it as well as it can be done. Nothing in
1099 * the world is going to help the person who wants
1100 * 0x123.p16 interpreted as two tokens, though.
1101 */
1102 r = p;
1103 while (*r == '_')
1104 r++;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001105
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001106 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
1107 (!is_hex && (*r == 'e' || *r == 'E')) ||
1108 (*r == 'p' || *r == 'P')) {
1109 p = r;
1110 is_float = true;
1111 } else
1112 break; /* Terminate the token */
1113 } else
1114 break;
1115 }
1116 p--; /* Point to first character beyond number */
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001117
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001118 if (p == line+1 && *line == '$') {
1119 type = TOK_OTHER; /* TOKEN_HERE */
1120 } else {
1121 if (has_e && !is_hex) {
1122 /* 1e13 is floating-point, but 1e13h is not */
1123 is_float = true;
1124 }
H. Peter Anvind784a082009-04-20 14:01:18 -07001125
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001126 type = is_float ? TOK_FLOAT : TOK_NUMBER;
1127 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -07001128 } else if (nasm_isspace(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001129 type = TOK_WHITESPACE;
Cyrill Gorcunovf66ac7d2009-10-12 20:41:13 +04001130 p = nasm_skip_spaces(p);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001131 /*
1132 * Whitespace just before end-of-line is discarded by
1133 * pretending it's a comment; whitespace just before a
1134 * comment gets lumped into the comment.
1135 */
1136 if (!*p || *p == ';') {
1137 type = TOK_COMMENT;
1138 while (*p)
1139 p++;
1140 }
1141 } else if (*p == ';') {
1142 type = TOK_COMMENT;
1143 while (*p)
1144 p++;
1145 } else {
1146 /*
1147 * Anything else is an operator of some kind. We check
1148 * for all the double-character operators (>>, <<, //,
1149 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001150 * else is a single-character operator.
H. Peter Anvine2c80182005-01-15 22:15:51 +00001151 */
1152 type = TOK_OTHER;
1153 if ((p[0] == '>' && p[1] == '>') ||
1154 (p[0] == '<' && p[1] == '<') ||
1155 (p[0] == '/' && p[1] == '/') ||
1156 (p[0] == '<' && p[1] == '=') ||
1157 (p[0] == '>' && p[1] == '=') ||
1158 (p[0] == '=' && p[1] == '=') ||
1159 (p[0] == '!' && p[1] == '=') ||
1160 (p[0] == '<' && p[1] == '>') ||
1161 (p[0] == '&' && p[1] == '&') ||
1162 (p[0] == '|' && p[1] == '|') ||
1163 (p[0] == '^' && p[1] == '^')) {
1164 p++;
1165 }
1166 p++;
1167 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001168
H. Peter Anvine2c80182005-01-15 22:15:51 +00001169 /* Handling unterminated string by UNV */
1170 /*if (type == -1)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001171 {
1172 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
1173 t->text[p-line] = *line;
1174 tail = &t->next;
1175 }
1176 else */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001177 if (type != TOK_COMMENT) {
1178 *tail = t = new_Token(NULL, type, line, p - line);
1179 tail = &t->next;
1180 }
1181 line = p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001182 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001183 return list;
1184}
1185
H. Peter Anvince616072002-04-30 21:02:23 +00001186/*
1187 * this function allocates a new managed block of memory and
H. Peter Anvin70653092007-10-19 14:42:29 -07001188 * returns a pointer to the block. The managed blocks are
H. Peter Anvince616072002-04-30 21:02:23 +00001189 * deleted only all at once by the delete_Blocks function.
1190 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001191static void *new_Block(size_t size)
H. Peter Anvince616072002-04-30 21:02:23 +00001192{
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001193 Blocks *b = &blocks;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001194
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001195 /* first, get to the end of the linked list */
1196 while (b->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001197 b = b->next;
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001198 /* now allocate the requested chunk */
1199 b->chunk = nasm_malloc(size);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001200
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001201 /* now allocate a new block for the next request */
Cyrill Gorcunovc31767c2014-06-28 02:22:17 +04001202 b->next = nasm_zalloc(sizeof(Blocks));
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001203 return b->chunk;
H. Peter Anvince616072002-04-30 21:02:23 +00001204}
1205
1206/*
1207 * this function deletes all managed blocks of memory
1208 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001209static void delete_Blocks(void)
H. Peter Anvince616072002-04-30 21:02:23 +00001210{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001211 Blocks *a, *b = &blocks;
H. Peter Anvince616072002-04-30 21:02:23 +00001212
H. Peter Anvin70653092007-10-19 14:42:29 -07001213 /*
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001214 * keep in mind that the first block, pointed to by blocks
H. Peter Anvin70653092007-10-19 14:42:29 -07001215 * is a static and not dynamically allocated, so we don't
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001216 * free it.
1217 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001218 while (b) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001219 if (b->chunk)
1220 nasm_free(b->chunk);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001221 a = b;
1222 b = b->next;
1223 if (a != &blocks)
1224 nasm_free(a);
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001225 }
Cyrill Gorcunovdae24d72014-06-28 10:17:39 +04001226 memset(&blocks, 0, sizeof(blocks));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001227}
H. Peter Anvin734b1882002-04-30 21:01:08 +00001228
1229/*
H. Peter Anvin70653092007-10-19 14:42:29 -07001230 * this function creates a new Token and passes a pointer to it
H. Peter Anvin734b1882002-04-30 21:01:08 +00001231 * back to the caller. It sets the type and text elements, and
H. Peter Anvinf26e0972008-07-01 21:26:27 -07001232 * also the a.mac and next elements to NULL.
H. Peter Anvin734b1882002-04-30 21:01:08 +00001233 */
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001234static Token *new_Token(Token * next, enum pp_token_type type,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001235 const char *text, int txtlen)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001236{
1237 Token *t;
1238 int i;
1239
H. Peter Anvin89cee572009-07-15 09:16:54 -04001240 if (!freeTokens) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001241 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
1242 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
1243 freeTokens[i].next = &freeTokens[i + 1];
1244 freeTokens[i].next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001245 }
1246 t = freeTokens;
1247 freeTokens = t->next;
1248 t->next = next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07001249 t->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001250 t->type = type;
H. Peter Anvin89cee572009-07-15 09:16:54 -04001251 if (type == TOK_WHITESPACE || !text) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001252 t->text = NULL;
1253 } else {
1254 if (txtlen == 0)
1255 txtlen = strlen(text);
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001256 t->text = nasm_malloc(txtlen+1);
1257 memcpy(t->text, text, txtlen);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001258 t->text[txtlen] = '\0';
H. Peter Anvin734b1882002-04-30 21:01:08 +00001259 }
1260 return t;
1261}
1262
H. Peter Anvine2c80182005-01-15 22:15:51 +00001263static Token *delete_Token(Token * t)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001264{
1265 Token *next = t->next;
1266 nasm_free(t->text);
H. Peter Anvin788e6c12002-04-30 21:02:01 +00001267 t->next = freeTokens;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001268 freeTokens = t;
1269 return next;
1270}
1271
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001272/*
1273 * Convert a line of tokens back into text.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001274 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1275 * will be transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001276 */
H. Peter Anvin9e200162008-06-04 17:23:14 -07001277static char *detoken(Token * tlist, bool expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001278{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001279 Token *t;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001280 char *line, *p;
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001281 const char *q;
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001282 int len = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001283
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001284 list_for_each(t, tlist) {
Cyrill Gorcunov9b7ee092017-10-22 21:42:59 +03001285 if (t->type == TOK_PREPROC_ID && t->text &&
1286 t->text[0] && t->text[1] == '!') {
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001287 char *v;
1288 char *q = t->text;
H. Peter Anvin077fb932010-07-20 14:56:30 -07001289
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001290 v = t->text + 2;
1291 if (*v == '\'' || *v == '\"' || *v == '`') {
1292 size_t len = nasm_unquote(v, NULL);
1293 size_t clen = strlen(v);
H. Peter Anvin077fb932010-07-20 14:56:30 -07001294
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001295 if (len != clen) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08001296 nasm_error(ERR_NONFATAL | ERR_PASS1,
1297 "NUL character in %%! string");
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001298 v = NULL;
1299 }
1300 }
H. Peter Anvin077fb932010-07-20 14:56:30 -07001301
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001302 if (v) {
1303 char *p = getenv(v);
1304 if (!p) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08001305 nasm_error(ERR_NONFATAL | ERR_PASS1,
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001306 "nonexistent environment variable `%s'", v);
Cyrill Gorcunovbbb7a1a2016-06-19 12:15:24 +03001307 /*
1308 * FIXME We better should investigate if accessing
1309 * ->text[1] without ->text[0] is safe enough.
1310 */
1311 t->text = nasm_zalloc(2);
1312 } else
1313 t->text = nasm_strdup(p);
Cyrill Gorcunov75004872017-07-26 01:21:16 +03001314 nasm_free(q);
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001315 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001316 }
H. Peter Anvin077fb932010-07-20 14:56:30 -07001317
H. Peter Anvine2c80182005-01-15 22:15:51 +00001318 /* Expand local macros here and not during preprocessing */
1319 if (expand_locals &&
1320 t->type == TOK_PREPROC_ID && t->text &&
1321 t->text[0] == '%' && t->text[1] == '$') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001322 const char *q;
1323 char *p;
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04001324 Context *ctx = get_ctx(t->text, &q);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001325 if (ctx) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001326 char buffer[40];
Keith Kanios93f2e9a2007-04-14 00:10:59 +00001327 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001328 p = nasm_strcat(buffer, q);
1329 nasm_free(t->text);
1330 t->text = p;
1331 }
1332 }
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001333 if (t->type == TOK_WHITESPACE)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001334 len++;
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001335 else if (t->text)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001336 len += strlen(t->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001337 }
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001338
H. Peter Anvin734b1882002-04-30 21:01:08 +00001339 p = line = nasm_malloc(len + 1);
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001340
1341 list_for_each(t, tlist) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001342 if (t->type == TOK_WHITESPACE) {
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001343 *p++ = ' ';
H. Peter Anvine2c80182005-01-15 22:15:51 +00001344 } else if (t->text) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001345 q = t->text;
1346 while (*q)
1347 *p++ = *q++;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001348 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001349 }
1350 *p = '\0';
Cyrill Gorcunovf32ed142010-04-09 15:41:48 +04001351
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001352 return line;
1353}
1354
1355/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001356 * A scanner, suitable for use by the expression evaluator, which
1357 * operates on a line of Tokens. Expects a pointer to a pointer to
1358 * the first token in the line to be passed in as its private_data
1359 * field.
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001360 *
1361 * FIX: This really needs to be unified with stdscan.
H. Peter Anvin76690a12002-04-30 20:52:49 +00001362 */
H. Peter Anvin8b262472019-02-26 14:00:54 -08001363struct ppscan {
1364 Token *tptr;
1365 int ntokens;
1366};
1367
H. Peter Anvine2c80182005-01-15 22:15:51 +00001368static int ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001369{
H. Peter Anvin8b262472019-02-26 14:00:54 -08001370 struct ppscan *pps = private_data;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001371 Token *tline;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001372 char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001373
H. Peter Anvine2c80182005-01-15 22:15:51 +00001374 do {
H. Peter Anvin8b262472019-02-26 14:00:54 -08001375 if (pps->ntokens && (tline = pps->tptr)) {
1376 pps->ntokens--;
1377 pps->tptr = tline->next;
1378 } else {
1379 pps->tptr = NULL;
1380 pps->ntokens = 0;
1381 return tokval->t_type = TOKEN_EOS;
1382 }
1383 } while (tline->type == TOK_WHITESPACE || tline->type == TOK_COMMENT);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001384
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001385 tokval->t_charptr = tline->text;
1386
H. Peter Anvin76690a12002-04-30 20:52:49 +00001387 if (tline->text[0] == '$' && !tline->text[1])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001388 return tokval->t_type = TOKEN_HERE;
H. Peter Anvin7cf897e2002-05-30 21:30:33 +00001389 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001390 return tokval->t_type = TOKEN_BASE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001391
H. Peter Anvine2c80182005-01-15 22:15:51 +00001392 if (tline->type == TOK_ID) {
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001393 p = tokval->t_charptr = tline->text;
1394 if (p[0] == '$') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001395 tokval->t_charptr++;
1396 return tokval->t_type = TOKEN_ID;
1397 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001398
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001399 for (r = p, s = ourcopy; *r; r++) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001400 if (r >= p+MAX_KEYWORD)
1401 return tokval->t_type = TOKEN_ID; /* Not a keyword */
H. Peter Anvinac8f8fc2008-06-11 15:49:41 -07001402 *s++ = nasm_tolower(*r);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001403 }
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001404 *s = '\0';
1405 /* right, so we have an identifier sitting in temp storage. now,
1406 * is it actually a register or instruction name, or what? */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001407 return nasm_token_hash(ourcopy, tokval);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001408 }
1409
H. Peter Anvine2c80182005-01-15 22:15:51 +00001410 if (tline->type == TOK_NUMBER) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001411 bool rn_error;
1412 tokval->t_integer = readnum(tline->text, &rn_error);
1413 tokval->t_charptr = tline->text;
1414 if (rn_error)
1415 return tokval->t_type = TOKEN_ERRNUM;
1416 else
1417 return tokval->t_type = TOKEN_NUM;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001418 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001419
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001420 if (tline->type == TOK_FLOAT) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001421 return tokval->t_type = TOKEN_FLOAT;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001422 }
1423
H. Peter Anvine2c80182005-01-15 22:15:51 +00001424 if (tline->type == TOK_STRING) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001425 char bq, *ep;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001426
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001427 bq = tline->text[0];
H. Peter Anvin11627042008-06-09 20:45:19 -07001428 tokval->t_charptr = tline->text;
1429 tokval->t_inttwo = nasm_unquote(tline->text, &ep);
H. Peter Anvind2456592008-06-19 15:04:18 -07001430
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001431 if (ep[0] != bq || ep[1] != '\0')
1432 return tokval->t_type = TOKEN_ERRSTR;
1433 else
1434 return tokval->t_type = TOKEN_STR;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001435 }
1436
H. Peter Anvine2c80182005-01-15 22:15:51 +00001437 if (tline->type == TOK_OTHER) {
1438 if (!strcmp(tline->text, "<<"))
1439 return tokval->t_type = TOKEN_SHL;
1440 if (!strcmp(tline->text, ">>"))
1441 return tokval->t_type = TOKEN_SHR;
1442 if (!strcmp(tline->text, "//"))
1443 return tokval->t_type = TOKEN_SDIV;
1444 if (!strcmp(tline->text, "%%"))
1445 return tokval->t_type = TOKEN_SMOD;
1446 if (!strcmp(tline->text, "=="))
1447 return tokval->t_type = TOKEN_EQ;
1448 if (!strcmp(tline->text, "<>"))
1449 return tokval->t_type = TOKEN_NE;
1450 if (!strcmp(tline->text, "!="))
1451 return tokval->t_type = TOKEN_NE;
1452 if (!strcmp(tline->text, "<="))
1453 return tokval->t_type = TOKEN_LE;
1454 if (!strcmp(tline->text, ">="))
1455 return tokval->t_type = TOKEN_GE;
1456 if (!strcmp(tline->text, "&&"))
1457 return tokval->t_type = TOKEN_DBL_AND;
1458 if (!strcmp(tline->text, "^^"))
1459 return tokval->t_type = TOKEN_DBL_XOR;
1460 if (!strcmp(tline->text, "||"))
1461 return tokval->t_type = TOKEN_DBL_OR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001462 }
1463
1464 /*
1465 * We have no other options: just return the first character of
1466 * the token text.
1467 */
1468 return tokval->t_type = tline->text[0];
1469}
1470
1471/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001472 * Compare a string to the name of an existing macro; this is a
1473 * simple wrapper which calls either strcmp or nasm_stricmp
1474 * depending on the value of the `casesense' parameter.
1475 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001476static int mstrcmp(const char *p, const char *q, bool casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001477{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001478 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001479}
1480
1481/*
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001482 * Compare a string to the name of an existing macro; this is a
1483 * simple wrapper which calls either strcmp or nasm_stricmp
1484 * depending on the value of the `casesense' parameter.
1485 */
1486static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
1487{
1488 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
1489}
1490
1491/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001492 * Return the Context structure associated with a %$ token. Return
1493 * NULL, having _already_ reported an error condition, if the
1494 * context stack isn't deep enough for the supplied number of $
1495 * signs.
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001496 *
1497 * If "namep" is non-NULL, set it to the pointer to the macro name
1498 * tail, i.e. the part beyond %$...
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001499 */
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04001500static Context *get_ctx(const char *name, const char **namep)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001501{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001502 Context *ctx;
1503 int i;
1504
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001505 if (namep)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001506 *namep = name;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001507
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001508 if (!name || name[0] != '%' || name[1] != '$')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001509 return NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001510
H. Peter Anvine2c80182005-01-15 22:15:51 +00001511 if (!cstk) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08001512 nasm_error(ERR_NONFATAL, "`%s': context stack is empty", name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001513 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001514 }
1515
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001516 name += 2;
1517 ctx = cstk;
1518 i = 0;
1519 while (ctx && *name == '$') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001520 name++;
1521 i++;
1522 ctx = ctx->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001523 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001524 if (!ctx) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08001525 nasm_error(ERR_NONFATAL, "`%s': context stack is only"
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001526 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001527 return NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001528 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001529
1530 if (namep)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001531 *namep = name;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001532
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04001533 return ctx;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001534}
1535
1536/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001537 * Open an include file. This routine must always return a valid
1538 * file pointer if it returns - it's responsible for throwing an
1539 * ERR_FATAL and bombing out completely if not. It should also try
1540 * the include path one by one until it finds the file or reaches
1541 * the end of the path.
H. Peter Anvind81a2352016-09-21 14:03:18 -07001542 *
1543 * Note: for INC_PROBE the function returns NULL at all times;
1544 * instead look for the
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001545 */
H. Peter Anvind81a2352016-09-21 14:03:18 -07001546enum incopen_mode {
1547 INC_NEEDED, /* File must exist */
1548 INC_OPTIONAL, /* Missing is OK */
1549 INC_PROBE /* Only an existence probe */
1550};
1551
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07001552/* This is conducts a full pathname search */
1553static FILE *inc_fopen_search(const char *file, StrList **slpath,
1554 enum incopen_mode omode, enum file_flags fmode)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001555{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001556 FILE *fp;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001557 char *prefix = "";
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07001558 const IncPath *ip = ipath;
night199ukfdb1a1b2018-10-18 23:19:47 +02001559 int len;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001560 StrList *sl;
night199ukfdb1a1b2018-10-18 23:19:47 +02001561 char *sp;
H. Peter Anvind81a2352016-09-21 14:03:18 -07001562 bool found;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001563
H. Peter Anvine2c80182005-01-15 22:15:51 +00001564 while (1) {
night199ukfdb1a1b2018-10-18 23:19:47 +02001565 sp = nasm_catfile(prefix, file);
1566 len = strlen(sp) + 1;
1567 sl = nasm_malloc(len + sizeof sl->next);
1568 memcpy(sl->str, sp, len);
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07001569 sl->next = NULL;
night199ukfdb1a1b2018-10-18 23:19:47 +02001570 nasm_free(sp);
Jim Kukunas65a8afc2016-06-13 16:00:42 -04001571
H. Peter Anvind81a2352016-09-21 14:03:18 -07001572 if (omode == INC_PROBE) {
1573 fp = NULL;
1574 found = nasm_file_exists(sl->str);
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001575 } else {
H. Peter Anvind81a2352016-09-21 14:03:18 -07001576 fp = nasm_open_read(sl->str, fmode);
1577 found = (fp != NULL);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001578 }
H. Peter Anvind81a2352016-09-21 14:03:18 -07001579 if (found) {
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07001580 *slpath = sl;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001581 return fp;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07001582 }
Jim Kukunas65a8afc2016-06-13 16:00:42 -04001583
H. Peter Anvind81a2352016-09-21 14:03:18 -07001584 nasm_free(sl);
Jim Kukunas65a8afc2016-06-13 16:00:42 -04001585
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07001586 if (!ip)
1587 return NULL;
1588
1589 prefix = ip->path;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07001590 ip = ip->next;
1591 }
1592}
1593
1594/*
1595 * Open a file, or test for the presence of one (depending on omode),
1596 * considering the include path.
1597 */
1598static FILE *inc_fopen(const char *file,
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07001599 StrList **dhead,
H. Peter Anvinccad6f92016-10-04 00:34:35 -07001600 const char **found_path,
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07001601 enum incopen_mode omode,
1602 enum file_flags fmode)
1603{
1604 StrList *sl;
1605 struct hash_insert hi;
1606 void **hp;
1607 char *path;
1608 FILE *fp = NULL;
1609
1610 hp = hash_find(&FileHash, file, &hi);
1611 if (hp) {
1612 path = *hp;
Martin Storsjöf283c8f2017-08-13 17:28:46 +03001613 if (path || omode != INC_NEEDED) {
H. Peter Anvin97fda4c2017-08-16 15:52:51 -07001614 nasm_add_string_to_strlist(dhead, path ? path : file);
Martin Storsjöf283c8f2017-08-13 17:28:46 +03001615 }
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07001616 } else {
1617 /* Need to do the actual path search */
1618 size_t file_len;
1619
1620 sl = NULL;
1621 fp = inc_fopen_search(file, &sl, omode, fmode);
1622
1623 file_len = strlen(file);
1624
1625 if (!sl) {
1626 /* Store negative result for this file */
1627 sl = nasm_malloc(file_len + 1 + sizeof sl->next);
1628 memcpy(sl->str, file, file_len+1);
1629 sl->next = NULL;
1630 file = sl->str;
1631 path = NULL;
1632 } else {
1633 path = sl->str;
1634 file = strchr(path, '\0') - file_len;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001635 }
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07001636
1637 hash_add(&hi, file, path); /* Positive or negative result */
1638
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07001639 /*
1640 * Add file to dependency path. The in_list() is needed
1641 * in case the file was already added with %depend.
1642 */
1643 if (path || omode != INC_NEEDED)
H. Peter Anvin436e3672016-10-04 01:12:28 -07001644 nasm_add_to_strlist(dhead, sl);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001645 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001646
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07001647 if (!path) {
1648 if (omode == INC_NEEDED)
1649 nasm_fatal(0, "unable to open include file `%s'", file);
1650
1651 if (found_path)
1652 *found_path = NULL;
1653
1654 return NULL;
1655 }
1656
1657 if (!fp && omode != INC_PROBE)
Cyrill Gorcunov4ff8c632017-01-06 00:36:23 +03001658 fp = nasm_open_read(path, fmode);
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07001659
1660 if (found_path)
H. Peter Anvinccad6f92016-10-04 00:34:35 -07001661 *found_path = path;
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07001662
1663 return fp;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001664}
1665
1666/*
Fabian Giesen0bbc38d2016-04-28 13:48:14 -07001667 * Opens an include or input file. Public version, for use by modules
1668 * that get a file:lineno pair and need to look at the file again
1669 * (e.g. the CodeView debug backend). Returns NULL on failure.
1670 */
H. Peter Anvin3e83cec2016-05-25 04:28:46 -07001671FILE *pp_input_fopen(const char *filename, enum file_flags mode)
Fabian Giesen0bbc38d2016-04-28 13:48:14 -07001672{
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07001673 return inc_fopen(filename, NULL, NULL, INC_OPTIONAL, mode);
Fabian Giesen0bbc38d2016-04-28 13:48:14 -07001674}
1675
1676/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001677 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001678 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001679 * return true if _any_ single-line macro of that name is defined.
1680 * Otherwise, will return true if a single-line macro with either
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001681 * `nparam' or no parameters is defined.
1682 *
1683 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001684 * defined, or nparam is -1, the address of the definition structure
1685 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001686 * is NULL, no action will be taken regarding its contents, and no
1687 * error will occur.
1688 *
1689 * Note that this is also called with nparam zero to resolve
1690 * `ifdef'.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001691 *
1692 * If you already know which context macro belongs to, you can pass
1693 * the context pointer as first parameter; if you won't but name begins
1694 * with %$ the context will be automatically computed. If all_contexts
1695 * is true, macro will be searched in outer contexts as well.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001696 */
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001697static bool
H. Peter Anvinb2a5fda2008-06-19 21:42:42 -07001698smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001699 bool nocase)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001700{
H. Peter Anvin166c2472008-05-28 12:28:58 -07001701 struct hash_table *smtbl;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001702 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001703
H. Peter Anvin97a23472007-09-16 17:57:25 -07001704 if (ctx) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001705 smtbl = &ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001706 } else if (name[0] == '%' && name[1] == '$') {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001707 if (cstk)
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04001708 ctx = get_ctx(name, &name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001709 if (!ctx)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001710 return false; /* got to return _something_ */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001711 smtbl = &ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001712 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001713 smtbl = &smacros;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001714 }
H. Peter Anvin166c2472008-05-28 12:28:58 -07001715 m = (SMacro *) hash_findix(smtbl, name);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001716
H. Peter Anvine2c80182005-01-15 22:15:51 +00001717 while (m) {
1718 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
Charles Crayne192d5b52007-10-18 19:02:42 -07001719 (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001720 if (defn) {
Charles Crayne192d5b52007-10-18 19:02:42 -07001721 if (nparam == (int) m->nparam || nparam == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001722 *defn = m;
1723 else
1724 *defn = NULL;
1725 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001726 return true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001727 }
1728 m = m->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001729 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001730
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001731 return false;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001732}
1733
1734/*
1735 * Count and mark off the parameters in a multi-line macro call.
1736 * This is called both from within the multi-line macro expansion
1737 * code, and also to mark off the default parameters when provided
1738 * in a %macro definition line.
1739 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001740static void count_mmac_params(Token * t, int *nparam, Token *** params)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001741{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001742 int paramsize, brace;
1743
1744 *nparam = paramsize = 0;
1745 *params = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001746 while (t) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001747 /* +1: we need space for the final NULL */
H. Peter Anvin91fb6f12008-09-01 10:56:33 -07001748 if (*nparam+1 >= paramsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001749 paramsize += PARAM_DELTA;
1750 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1751 }
1752 skip_white_(t);
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08001753 brace = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001754 if (tok_is_(t, "{"))
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08001755 brace++;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001756 (*params)[(*nparam)++] = t;
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08001757 if (brace) {
1758 while (brace && (t = t->next) != NULL) {
1759 if (tok_is_(t, "{"))
1760 brace++;
1761 else if (tok_is_(t, "}"))
1762 brace--;
1763 }
1764
1765 if (t) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001766 /*
1767 * Now we've found the closing brace, look further
1768 * for the comma.
1769 */
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08001770 t = t->next;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001771 skip_white_(t);
1772 if (tok_isnt_(t, ",")) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08001773 nasm_error(ERR_NONFATAL,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001774 "braces do not enclose all of macro parameter");
1775 while (tok_isnt_(t, ","))
1776 t = t->next;
1777 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001778 }
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08001779 } else {
1780 while (tok_isnt_(t, ","))
1781 t = t->next;
1782 }
1783 if (t) { /* got a comma/brace */
1784 t = t->next; /* eat the comma */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001785 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001786 }
1787}
1788
1789/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001790 * Determine whether one of the various `if' conditions is true or
1791 * not.
1792 *
1793 * We must free the tline we get passed.
1794 */
H. Peter Anvin70055962007-10-11 00:05:31 -07001795static bool if_condition(Token * tline, enum preproc_token ct)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001796{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001797 enum pp_conditional i = PP_COND(ct);
H. Peter Anvin70055962007-10-11 00:05:31 -07001798 bool j;
H. Peter Anvin8b262472019-02-26 14:00:54 -08001799 Token *t, *tt, *origline;
1800 struct ppscan pps;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001801 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001802 expr *evalresult;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001803 enum pp_token_type needtype;
H. Peter Anvin077fb932010-07-20 14:56:30 -07001804 char *p;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001805
1806 origline = tline;
1807
H. Peter Anvine2c80182005-01-15 22:15:51 +00001808 switch (i) {
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001809 case PPC_IFCTX:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001810 j = false; /* have we matched yet? */
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001811 while (true) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001812 skip_white_(tline);
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001813 if (!tline)
1814 break;
1815 if (tline->type != TOK_ID) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08001816 nasm_error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001817 "`%s' expects context identifiers", pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001818 free_tlist(origline);
1819 return -1;
1820 }
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001821 if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001822 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001823 tline = tline->next;
1824 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001825 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001826
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001827 case PPC_IFDEF:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001828 j = false; /* have we matched yet? */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001829 while (tline) {
1830 skip_white_(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001831 if (!tline || (tline->type != TOK_ID &&
1832 (tline->type != TOK_PREPROC_ID ||
1833 tline->text[1] != '$'))) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08001834 nasm_error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001835 "`%s' expects macro identifiers", pp_directives[ct]);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001836 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001837 }
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001838 if (smacro_defined(NULL, tline->text, 0, NULL, true))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001839 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001840 tline = tline->next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001841 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001842 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001843
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07001844 case PPC_IFENV:
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001845 tline = expand_smacro(tline);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07001846 j = false; /* have we matched yet? */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001847 while (tline) {
1848 skip_white_(tline);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07001849 if (!tline || (tline->type != TOK_ID &&
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001850 tline->type != TOK_STRING &&
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07001851 (tline->type != TOK_PREPROC_ID ||
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001852 tline->text[1] != '!'))) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08001853 nasm_error(ERR_NONFATAL,
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07001854 "`%s' expects environment variable names",
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001855 pp_directives[ct]);
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07001856 goto fail;
1857 }
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04001858 p = tline->text;
1859 if (tline->type == TOK_PREPROC_ID)
1860 p += 2; /* Skip leading %! */
1861 if (*p == '\'' || *p == '\"' || *p == '`')
1862 nasm_unquote_cstr(p, ct);
1863 if (getenv(p))
1864 j = true;
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07001865 tline = tline->next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001866 }
H. Peter Anvin6d9b2b52010-07-13 12:00:58 -07001867 break;
1868
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001869 case PPC_IFIDN:
1870 case PPC_IFIDNI:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001871 tline = expand_smacro(tline);
1872 t = tt = tline;
1873 while (tok_isnt_(tt, ","))
1874 tt = tt->next;
1875 if (!tt) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08001876 nasm_error(ERR_NONFATAL,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001877 "`%s' expects two comma-separated arguments",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001878 pp_directives[ct]);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001879 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001880 }
1881 tt = tt->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001882 j = true; /* assume equality unless proved not */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001883 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1884 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08001885 nasm_error(ERR_NONFATAL, "`%s': more than one comma on line",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001886 pp_directives[ct]);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001887 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001888 }
1889 if (t->type == TOK_WHITESPACE) {
1890 t = t->next;
1891 continue;
1892 }
1893 if (tt->type == TOK_WHITESPACE) {
1894 tt = tt->next;
1895 continue;
1896 }
1897 if (tt->type != t->type) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001898 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001899 break;
1900 }
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001901 /* When comparing strings, need to unquote them first */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001902 if (t->type == TOK_STRING) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001903 size_t l1 = nasm_unquote(t->text, NULL);
1904 size_t l2 = nasm_unquote(tt->text, NULL);
H. Peter Anvind2456592008-06-19 15:04:18 -07001905
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001906 if (l1 != l2) {
1907 j = false;
1908 break;
1909 }
1910 if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
1911 j = false;
1912 break;
1913 }
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001914 } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001915 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001916 break;
1917 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001918
H. Peter Anvine2c80182005-01-15 22:15:51 +00001919 t = t->next;
1920 tt = tt->next;
1921 }
1922 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001923 j = false; /* trailing gunk on one end or other */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001924 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001925
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001926 case PPC_IFMACRO:
H. Peter Anvin89cee572009-07-15 09:16:54 -04001927 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001928 bool found = false;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001929 MMacro searching, *mmac;
H. Peter Anvin65747262002-05-07 00:10:05 +00001930
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001931 skip_white_(tline);
1932 tline = expand_id(tline);
1933 if (!tok_type_(tline, TOK_ID)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08001934 nasm_error(ERR_NONFATAL,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001935 "`%s' expects a macro name", pp_directives[ct]);
1936 goto fail;
1937 }
1938 searching.name = nasm_strdup(tline->text);
1939 searching.casesense = true;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001940 searching.plus = false;
1941 searching.nolist = false;
1942 searching.in_progress = 0;
1943 searching.max_depth = 0;
1944 searching.rep_nest = NULL;
1945 searching.nparam_min = 0;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001946 searching.nparam_max = INT_MAX;
1947 tline = expand_smacro(tline->next);
1948 skip_white_(tline);
1949 if (!tline) {
1950 } else if (!tok_type_(tline, TOK_NUMBER)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08001951 nasm_error(ERR_NONFATAL,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001952 "`%s' expects a parameter count or nothing",
1953 pp_directives[ct]);
1954 } else {
1955 searching.nparam_min = searching.nparam_max =
1956 readnum(tline->text, &j);
1957 if (j)
H. Peter Anvin130736c2016-02-17 20:27:41 -08001958 nasm_error(ERR_NONFATAL,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001959 "unable to parse parameter count `%s'",
1960 tline->text);
1961 }
1962 if (tline && tok_is_(tline->next, "-")) {
1963 tline = tline->next->next;
1964 if (tok_is_(tline, "*"))
1965 searching.nparam_max = INT_MAX;
1966 else if (!tok_type_(tline, TOK_NUMBER))
H. Peter Anvin130736c2016-02-17 20:27:41 -08001967 nasm_error(ERR_NONFATAL,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001968 "`%s' expects a parameter count after `-'",
1969 pp_directives[ct]);
1970 else {
1971 searching.nparam_max = readnum(tline->text, &j);
1972 if (j)
H. Peter Anvin130736c2016-02-17 20:27:41 -08001973 nasm_error(ERR_NONFATAL,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001974 "unable to parse parameter count `%s'",
1975 tline->text);
Cyrill Gorcunovc9244ea2017-10-22 15:25:48 +03001976 if (searching.nparam_min > searching.nparam_max) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08001977 nasm_error(ERR_NONFATAL,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001978 "minimum parameter count exceeds maximum");
Cyrill Gorcunovc9244ea2017-10-22 15:25:48 +03001979 searching.nparam_max = searching.nparam_min;
1980 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001981 }
1982 }
1983 if (tline && tok_is_(tline->next, "+")) {
1984 tline = tline->next;
1985 searching.plus = true;
1986 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001987 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
1988 while (mmac) {
1989 if (!strcmp(mmac->name, searching.name) &&
1990 (mmac->nparam_min <= searching.nparam_max
1991 || searching.plus)
1992 && (searching.nparam_min <= mmac->nparam_max
1993 || mmac->plus)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001994 found = true;
1995 break;
1996 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08001997 mmac = mmac->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03001998 }
1999 if (tline && tline->next)
H. Peter Anvin130736c2016-02-17 20:27:41 -08002000 nasm_error(ERR_WARNING|ERR_PASS1,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002001 "trailing garbage after %%ifmacro ignored");
2002 nasm_free(searching.name);
2003 j = found;
2004 break;
H. Peter Anvin89cee572009-07-15 09:16:54 -04002005 }
H. Peter Anvin65747262002-05-07 00:10:05 +00002006
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002007 case PPC_IFID:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002008 needtype = TOK_ID;
2009 goto iftype;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002010 case PPC_IFNUM:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002011 needtype = TOK_NUMBER;
2012 goto iftype;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002013 case PPC_IFSTR:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002014 needtype = TOK_STRING;
2015 goto iftype;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002016
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002017iftype:
2018 t = tline = expand_smacro(tline);
H. Peter Anvind85d2502008-05-04 17:53:31 -07002019
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002020 while (tok_type_(t, TOK_WHITESPACE) ||
2021 (needtype == TOK_NUMBER &&
2022 tok_type_(t, TOK_OTHER) &&
2023 (t->text[0] == '-' || t->text[0] == '+') &&
2024 !t->text[1]))
2025 t = t->next;
H. Peter Anvind85d2502008-05-04 17:53:31 -07002026
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002027 j = tok_type_(t, needtype);
2028 break;
H. Peter Anvincbf768d2008-02-16 16:41:25 -08002029
2030 case PPC_IFTOKEN:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002031 t = tline = expand_smacro(tline);
2032 while (tok_type_(t, TOK_WHITESPACE))
2033 t = t->next;
H. Peter Anvincbf768d2008-02-16 16:41:25 -08002034
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002035 j = false;
2036 if (t) {
2037 t = t->next; /* Skip the actual token */
2038 while (tok_type_(t, TOK_WHITESPACE))
2039 t = t->next;
2040 j = !t; /* Should be nothing left */
2041 }
2042 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002043
H. Peter Anvin134b9462008-02-16 17:01:40 -08002044 case PPC_IFEMPTY:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002045 t = tline = expand_smacro(tline);
2046 while (tok_type_(t, TOK_WHITESPACE))
2047 t = t->next;
H. Peter Anvin134b9462008-02-16 17:01:40 -08002048
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002049 j = !t; /* Should be empty */
2050 break;
H. Peter Anvin134b9462008-02-16 17:01:40 -08002051
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002052 case PPC_IF:
H. Peter Anvin8b262472019-02-26 14:00:54 -08002053 pps.tptr = tline = expand_smacro(tline);
2054 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002055 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin8b262472019-02-26 14:00:54 -08002056 evalresult = evaluate(ppscan, &pps, &tokval,
H. Peter Anvin130736c2016-02-17 20:27:41 -08002057 NULL, pass | CRITICAL, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002058 if (!evalresult)
2059 return -1;
2060 if (tokval.t_type)
H. Peter Anvin130736c2016-02-17 20:27:41 -08002061 nasm_error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002062 "trailing garbage after expression ignored");
2063 if (!is_simple(evalresult)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002064 nasm_error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002065 "non-constant value given to `%s'", pp_directives[ct]);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002066 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002067 }
Chuck Crayne60ae75d2007-05-02 01:59:16 +00002068 j = reloc_value(evalresult) != 0;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002069 break;
H. Peter Anvin95e28822007-09-12 04:20:08 +00002070
H. Peter Anvine2c80182005-01-15 22:15:51 +00002071 default:
H. Peter Anvin130736c2016-02-17 20:27:41 -08002072 nasm_error(ERR_FATAL,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002073 "preprocessor directive `%s' not yet implemented",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002074 pp_directives[ct]);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002075 goto fail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002076 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002077
2078 free_tlist(origline);
2079 return j ^ PP_NEGATIVE(ct);
H. Peter Anvin70653092007-10-19 14:42:29 -07002080
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002081fail:
2082 free_tlist(origline);
2083 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002084}
2085
2086/*
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002087 * Common code for defining an smacro
2088 */
H. Peter Anvin8b262472019-02-26 14:00:54 -08002089static SMacro *define_smacro(Context *ctx, const char *mname,
2090 bool casesense, int nparam, Token *expansion)
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002091{
2092 SMacro *smac, **smhead;
H. Peter Anvin166c2472008-05-28 12:28:58 -07002093 struct hash_table *smtbl;
H. Peter Anvin70653092007-10-19 14:42:29 -07002094
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002095 if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002096 if (!smac) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002097 nasm_error(ERR_WARNING|ERR_PASS1,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002098 "single-line macro `%s' defined both with and"
2099 " without parameters", mname);
2100 /*
2101 * Some instances of the old code considered this a failure,
2102 * some others didn't. What is the right thing to do here?
2103 */
2104 free_tlist(expansion);
H. Peter Anvin8b262472019-02-26 14:00:54 -08002105 return NULL; /* Failure */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002106 } else {
2107 /*
2108 * We're redefining, so we have to take over an
2109 * existing SMacro structure. This means freeing
H. Peter Anvin8b262472019-02-26 14:00:54 -08002110 * what was already in it, but not the structure itself.
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002111 */
H. Peter Anvin8b262472019-02-26 14:00:54 -08002112 free_smacro(smac, false);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002113 }
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002114 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002115 smtbl = ctx ? &ctx->localmac : &smacros;
2116 smhead = (SMacro **) hash_findi_add(smtbl, mname);
H. Peter Anvin8b262472019-02-26 14:00:54 -08002117 nasm_new(smac);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002118 smac->next = *smhead;
2119 *smhead = smac;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002120 }
2121 smac->name = nasm_strdup(mname);
2122 smac->casesense = casesense;
2123 smac->nparam = nparam;
H. Peter Anvin8b262472019-02-26 14:00:54 -08002124 smac->e.expansion = expansion;
2125 return smac;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002126}
2127
2128/*
2129 * Undefine an smacro
2130 */
2131static void undef_smacro(Context *ctx, const char *mname)
2132{
2133 SMacro **smhead, *s, **sp;
H. Peter Anvin166c2472008-05-28 12:28:58 -07002134 struct hash_table *smtbl;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002135
H. Peter Anvin166c2472008-05-28 12:28:58 -07002136 smtbl = ctx ? &ctx->localmac : &smacros;
2137 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
H. Peter Anvin70653092007-10-19 14:42:29 -07002138
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002139 if (smhead) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002140 /*
2141 * We now have a macro name... go hunt for it.
2142 */
2143 sp = smhead;
2144 while ((s = *sp) != NULL) {
2145 if (!mstrcmp(s->name, mname, s->casesense)) {
2146 *sp = s->next;
H. Peter Anvin8b262472019-02-26 14:00:54 -08002147 free_smacro(s, true);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002148 } else {
2149 sp = &s->next;
2150 }
2151 }
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002152 }
2153}
2154
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002155/*
H. Peter Anvina26433d2008-07-16 14:40:01 -07002156 * Parse a mmacro specification.
2157 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002158static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
H. Peter Anvina26433d2008-07-16 14:40:01 -07002159{
2160 bool err;
2161
2162 tline = tline->next;
2163 skip_white_(tline);
2164 tline = expand_id(tline);
2165 if (!tok_type_(tline, TOK_ID)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002166 nasm_error(ERR_NONFATAL, "`%s' expects a macro name", directive);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002167 return false;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002168 }
Victor van den Elzenb916ede2008-07-23 15:14:22 +02002169
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002170 def->prev = NULL;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002171 def->name = nasm_strdup(tline->text);
2172 def->plus = false;
2173 def->nolist = false;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002174 def->in_progress = 0;
2175 def->rep_nest = NULL;
Victor van den Elzenb916ede2008-07-23 15:14:22 +02002176 def->nparam_min = 0;
2177 def->nparam_max = 0;
2178
H. Peter Anvina26433d2008-07-16 14:40:01 -07002179 tline = expand_smacro(tline->next);
2180 skip_white_(tline);
2181 if (!tok_type_(tline, TOK_NUMBER)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002182 nasm_error(ERR_NONFATAL, "`%s' expects a parameter count", directive);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002183 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002184 def->nparam_min = def->nparam_max =
2185 readnum(tline->text, &err);
2186 if (err)
H. Peter Anvin130736c2016-02-17 20:27:41 -08002187 nasm_error(ERR_NONFATAL,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002188 "unable to parse parameter count `%s'", tline->text);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002189 }
2190 if (tline && tok_is_(tline->next, "-")) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002191 tline = tline->next->next;
2192 if (tok_is_(tline, "*")) {
2193 def->nparam_max = INT_MAX;
2194 } else if (!tok_type_(tline, TOK_NUMBER)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002195 nasm_error(ERR_NONFATAL,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002196 "`%s' expects a parameter count after `-'", directive);
2197 } else {
2198 def->nparam_max = readnum(tline->text, &err);
2199 if (err) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002200 nasm_error(ERR_NONFATAL, "unable to parse parameter count `%s'",
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002201 tline->text);
2202 }
2203 if (def->nparam_min > def->nparam_max) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002204 nasm_error(ERR_NONFATAL, "minimum parameter count exceeds maximum");
Cyrill Gorcunovc9244ea2017-10-22 15:25:48 +03002205 def->nparam_max = def->nparam_min;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002206 }
2207 }
H. Peter Anvina26433d2008-07-16 14:40:01 -07002208 }
2209 if (tline && tok_is_(tline->next, "+")) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002210 tline = tline->next;
2211 def->plus = true;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002212 }
2213 if (tline && tok_type_(tline->next, TOK_ID) &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002214 !nasm_stricmp(tline->next->text, ".nolist")) {
2215 tline = tline->next;
2216 def->nolist = true;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002217 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002218
H. Peter Anvina26433d2008-07-16 14:40:01 -07002219 /*
2220 * Handle default parameters.
2221 */
2222 if (tline && tline->next) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002223 def->dlist = tline->next;
2224 tline->next = NULL;
2225 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002226 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002227 def->dlist = NULL;
2228 def->defaults = NULL;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002229 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002230 def->expansion = NULL;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002231
H. Peter Anvin89cee572009-07-15 09:16:54 -04002232 if (def->defaults && def->ndefs > def->nparam_max - def->nparam_min &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002233 !def->plus)
H. Peter Anvin (Intel)77f53ba2018-12-12 14:38:50 -08002234 nasm_error(ERR_WARNING|ERR_PASS1|WARN_MDP,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002235 "too many default macro parameters");
Victor van den Elzenb916ede2008-07-23 15:14:22 +02002236
H. Peter Anvina26433d2008-07-16 14:40:01 -07002237 return true;
2238}
2239
2240
2241/*
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002242 * Decode a size directive
2243 */
2244static int parse_size(const char *str) {
2245 static const char *size_names[] =
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002246 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002247 static const int sizes[] =
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002248 { 0, 1, 4, 16, 8, 10, 2, 32 };
Cyrill Gorcunovc713b5f2018-09-29 14:30:14 +03002249 return str ? sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1] : 0;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002250}
2251
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07002252/*
2253 * Process a preprocessor %pragma directive. Currently there are none.
2254 * Gets passed the token list starting with the "preproc" token from
2255 * "%pragma preproc".
2256 */
2257static void do_pragma_preproc(Token *tline)
2258{
2259 /* Skip to the real stuff */
2260 tline = tline->next;
2261 skip_white_(tline);
2262 if (!tline)
2263 return;
2264
2265 (void)tline; /* Nothing else to do at present */
2266}
2267
Ed Beroset3ab3f412002-06-11 03:31:49 +00002268/**
2269 * find and process preprocessor directive in passed line
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002270 * Find out if a line contains a preprocessor directive, and deal
2271 * with it if so.
H. Peter Anvin70653092007-10-19 14:42:29 -07002272 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00002273 * If a directive _is_ found, it is the responsibility of this routine
2274 * (and not the caller) to free_tlist() the line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002275 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00002276 * @param tline a pointer to the current tokeninzed line linked list
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07002277 * @param output if this directive generated output
Ed Beroset3ab3f412002-06-11 03:31:49 +00002278 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
H. Peter Anvin70653092007-10-19 14:42:29 -07002279 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002280 */
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07002281static int do_directive(Token *tline, char **output)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002282{
H. Peter Anvin4169a472007-09-12 01:29:43 +00002283 enum preproc_token i;
2284 int j;
H. Peter Anvin70055962007-10-11 00:05:31 -07002285 bool err;
2286 int nparam;
2287 bool nolist;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002288 bool casesense;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -07002289 int k, m;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002290 int offset;
H. Peter Anvinccad6f92016-10-04 00:34:35 -07002291 char *p, *pp;
2292 const char *found_path;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002293 const char *mname;
H. Peter Anvin8b262472019-02-26 14:00:54 -08002294 struct ppscan pps;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002295 Include *inc;
2296 Context *ctx;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002297 Cond *cond;
2298 MMacro *mmac, **mmhead;
H. Peter Anvin8b262472019-02-26 14:00:54 -08002299 Token *t = NULL, *tt, *param_start, *macro_start, *last, *origline;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002300 Line *l;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002301 struct tokenval tokval;
2302 expr *evalresult;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002303 MMacro *tmp_defining; /* Used when manipulating rep_nest */
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002304 int64_t count;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07002305 size_t len;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002306 int severity;
H. Peter Anvin8b262472019-02-26 14:00:54 -08002307 const char *dname; /* Name of directive, for messages */
H. Peter Anvin76690a12002-04-30 20:52:49 +00002308
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07002309 *output = NULL; /* No output generated */
H. Peter Anvin76690a12002-04-30 20:52:49 +00002310 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002311
H. Peter Anvineba20a72002-04-30 20:53:55 +00002312 skip_white_(tline);
H. Peter Anvinf2936d72008-06-04 15:11:23 -07002313 if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
Cyrill Gorcunov4b5b7372018-10-29 22:54:08 +03002314 (tline->text[0] && (tline->text[1] == '%' ||
2315 tline->text[1] == '$' ||
2316 tline->text[1] == '!')))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002317 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002318
H. Peter Anvin4169a472007-09-12 01:29:43 +00002319 i = pp_token_hash(tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002320
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002321 /*
2322 * FIXME: We zap execution of PP_RMACRO, PP_IRMACRO, PP_EXITMACRO
2323 * since they are known to be buggy at moment, we need to fix them
2324 * in future release (2.09-2.10)
2325 */
Philipp Klokeb432f572013-03-31 12:01:23 +02002326 if (i == PP_RMACRO || i == PP_IRMACRO || i == PP_EXITMACRO) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002327 nasm_error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002328 tline->text);
2329 return NO_DIRECTIVE_FOUND;
2330 }
2331
2332 /*
2333 * If we're in a non-emitting branch of a condition construct,
2334 * or walking to the end of an already terminated %rep block,
2335 * we should ignore all directives except for condition
2336 * directives.
2337 */
2338 if (((istk->conds && !emitting(istk->conds->state)) ||
2339 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
2340 return NO_DIRECTIVE_FOUND;
2341 }
2342
2343 /*
2344 * If we're defining a macro or reading a %rep block, we should
2345 * ignore all directives except for %macro/%imacro (which nest),
2346 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2347 * If we're in a %rep block, another %rep nests, so should be let through.
2348 */
2349 if (defining && i != PP_MACRO && i != PP_IMACRO &&
2350 i != PP_RMACRO && i != PP_IRMACRO &&
2351 i != PP_ENDMACRO && i != PP_ENDM &&
2352 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
2353 return NO_DIRECTIVE_FOUND;
2354 }
2355
2356 if (defining) {
2357 if (i == PP_MACRO || i == PP_IMACRO ||
2358 i == PP_RMACRO || i == PP_IRMACRO) {
2359 nested_mac_count++;
2360 return NO_DIRECTIVE_FOUND;
2361 } else if (nested_mac_count > 0) {
2362 if (i == PP_ENDMACRO) {
2363 nested_mac_count--;
2364 return NO_DIRECTIVE_FOUND;
2365 }
2366 }
2367 if (!defining->name) {
2368 if (i == PP_REP) {
2369 nested_rep_count++;
2370 return NO_DIRECTIVE_FOUND;
2371 } else if (nested_rep_count > 0) {
2372 if (i == PP_ENDREP) {
2373 nested_rep_count--;
2374 return NO_DIRECTIVE_FOUND;
2375 }
2376 }
2377 }
2378 }
2379
H. Peter Anvin8b262472019-02-26 14:00:54 -08002380 dname = pp_directives[i]; /* Directive name, for error messages */
2381 casesense = true; /* Default to case sensitive */
H. Peter Anvin4169a472007-09-12 01:29:43 +00002382 switch (i) {
2383 case PP_INVALID:
H. Peter Anvin130736c2016-02-17 20:27:41 -08002384 nasm_error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
H. Peter Anvine2c80182005-01-15 22:15:51 +00002385 tline->text);
2386 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002387
H. Peter Anvin3f87a2a2016-10-04 14:07:19 -07002388 case PP_PRAGMA:
2389 /*
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07002390 * %pragma namespace options...
2391 *
2392 * The namespace "preproc" is reserved for the preprocessor;
2393 * all other namespaces generate a [pragma] assembly directive.
2394 *
2395 * Invalid %pragmas are ignored and may have different
2396 * meaning in future versions of NASM.
H. Peter Anvin3f87a2a2016-10-04 14:07:19 -07002397 */
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07002398 tline = tline->next;
2399 skip_white_(tline);
2400 tline = expand_smacro(tline);
2401 if (tok_type_(tline, TOK_ID)) {
2402 if (!nasm_stricmp(tline->text, "preproc")) {
2403 /* Preprocessor pragma */
2404 do_pragma_preproc(tline);
2405 } else {
2406 /* Build the assembler directive */
2407 t = new_Token(NULL, TOK_OTHER, "[", 1);
2408 t->next = new_Token(NULL, TOK_ID, "pragma", 6);
2409 t->next->next = new_Token(tline, TOK_WHITESPACE, NULL, 0);
2410 tline = t;
2411 for (t = tline; t->next; t = t->next)
2412 ;
2413 t->next = new_Token(NULL, TOK_OTHER, "]", 1);
2414 /* true here can be revisited in the future */
2415 *output = detoken(tline, true);
2416 }
2417 }
H. Peter Anvin3f87a2a2016-10-04 14:07:19 -07002418 free_tlist(origline);
2419 return DIRECTIVE_FOUND;
2420
H. Peter Anvine2c80182005-01-15 22:15:51 +00002421 case PP_STACKSIZE:
2422 /* Directive to tell NASM what the default stack size is. The
2423 * default is for a 16-bit stack, and this can be overriden with
2424 * %stacksize large.
H. Peter Anvine2c80182005-01-15 22:15:51 +00002425 */
2426 tline = tline->next;
2427 if (tline && tline->type == TOK_WHITESPACE)
2428 tline = tline->next;
2429 if (!tline || tline->type != TOK_ID) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08002430 nasm_error(ERR_NONFATAL, "`%s' missing size parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002431 free_tlist(origline);
2432 return DIRECTIVE_FOUND;
2433 }
2434 if (nasm_stricmp(tline->text, "flat") == 0) {
2435 /* All subsequent ARG directives are for a 32-bit stack */
2436 StackSize = 4;
2437 StackPointer = "ebp";
2438 ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002439 LocalOffset = 0;
Charles Crayne7eaf9192007-11-08 22:11:14 -08002440 } else if (nasm_stricmp(tline->text, "flat64") == 0) {
2441 /* All subsequent ARG directives are for a 64-bit stack */
2442 StackSize = 8;
2443 StackPointer = "rbp";
Per Jessen53252e02010-02-11 00:16:59 +03002444 ArgOffset = 16;
Charles Crayne7eaf9192007-11-08 22:11:14 -08002445 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002446 } else if (nasm_stricmp(tline->text, "large") == 0) {
2447 /* All subsequent ARG directives are for a 16-bit stack,
2448 * far function call.
2449 */
2450 StackSize = 2;
2451 StackPointer = "bp";
2452 ArgOffset = 4;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002453 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002454 } else if (nasm_stricmp(tline->text, "small") == 0) {
2455 /* All subsequent ARG directives are for a 16-bit stack,
2456 * far function call. We don't support near functions.
2457 */
2458 StackSize = 2;
2459 StackPointer = "bp";
2460 ArgOffset = 6;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002461 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002462 } else {
H. Peter Anvin8b262472019-02-26 14:00:54 -08002463 nasm_error(ERR_NONFATAL, "`%s' invalid size type", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002464 free_tlist(origline);
2465 return DIRECTIVE_FOUND;
2466 }
2467 free_tlist(origline);
2468 return DIRECTIVE_FOUND;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002469
H. Peter Anvine2c80182005-01-15 22:15:51 +00002470 case PP_ARG:
2471 /* TASM like ARG directive to define arguments to functions, in
2472 * the following form:
2473 *
2474 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2475 */
2476 offset = ArgOffset;
2477 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002478 char *arg, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00002479 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002480
H. Peter Anvine2c80182005-01-15 22:15:51 +00002481 /* Find the argument name */
2482 tline = tline->next;
2483 if (tline && tline->type == TOK_WHITESPACE)
2484 tline = tline->next;
2485 if (!tline || tline->type != TOK_ID) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08002486 nasm_error(ERR_NONFATAL, "`%s' missing argument parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002487 free_tlist(origline);
2488 return DIRECTIVE_FOUND;
2489 }
2490 arg = tline->text;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002491
H. Peter Anvine2c80182005-01-15 22:15:51 +00002492 /* Find the argument size type */
2493 tline = tline->next;
2494 if (!tline || tline->type != TOK_OTHER
2495 || tline->text[0] != ':') {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002496 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08002497 "syntax error processing `%s' directive", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002498 free_tlist(origline);
2499 return DIRECTIVE_FOUND;
2500 }
2501 tline = tline->next;
2502 if (!tline || tline->type != TOK_ID) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08002503 nasm_error(ERR_NONFATAL, "`%s' missing size type parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002504 free_tlist(origline);
2505 return DIRECTIVE_FOUND;
2506 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002507
H. Peter Anvine2c80182005-01-15 22:15:51 +00002508 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002509 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002510 tt = expand_smacro(tt);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002511 size = parse_size(tt->text);
2512 if (!size) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002513 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08002514 "invalid size type for `%s' missing directive", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002515 free_tlist(tt);
2516 free_tlist(origline);
2517 return DIRECTIVE_FOUND;
2518 }
2519 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002520
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002521 /* Round up to even stack slots */
2522 size = ALIGN(size, StackSize);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002523
H. Peter Anvine2c80182005-01-15 22:15:51 +00002524 /* Now define the macro for the argument */
2525 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
2526 arg, StackPointer, offset);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07002527 do_directive(tokenize(directive), output);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002528 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002529
H. Peter Anvine2c80182005-01-15 22:15:51 +00002530 /* Move to the next argument in the list */
2531 tline = tline->next;
2532 if (tline && tline->type == TOK_WHITESPACE)
2533 tline = tline->next;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002534 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002535 ArgOffset = offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002536 free_tlist(origline);
2537 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002538
H. Peter Anvine2c80182005-01-15 22:15:51 +00002539 case PP_LOCAL:
2540 /* TASM like LOCAL directive to define local variables for a
2541 * function, in the following form:
2542 *
2543 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2544 *
2545 * The '= LocalSize' at the end is ignored by NASM, but is
2546 * required by TASM to define the local parameter size (and used
2547 * by the TASM macro package).
2548 */
2549 offset = LocalOffset;
2550 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002551 char *local, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00002552 int size = StackSize;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002553
H. Peter Anvine2c80182005-01-15 22:15:51 +00002554 /* Find the argument name */
2555 tline = tline->next;
2556 if (tline && tline->type == TOK_WHITESPACE)
2557 tline = tline->next;
2558 if (!tline || tline->type != TOK_ID) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002559 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08002560 "`%s' missing argument parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002561 free_tlist(origline);
2562 return DIRECTIVE_FOUND;
2563 }
2564 local = tline->text;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002565
H. Peter Anvine2c80182005-01-15 22:15:51 +00002566 /* Find the argument size type */
2567 tline = tline->next;
2568 if (!tline || tline->type != TOK_OTHER
2569 || tline->text[0] != ':') {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002570 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08002571 "syntax error processing `%s' directive", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002572 free_tlist(origline);
2573 return DIRECTIVE_FOUND;
2574 }
2575 tline = tline->next;
2576 if (!tline || tline->type != TOK_ID) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002577 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08002578 "`%s' missing size type parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002579 free_tlist(origline);
2580 return DIRECTIVE_FOUND;
2581 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002582
H. Peter Anvine2c80182005-01-15 22:15:51 +00002583 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002584 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002585 tt = expand_smacro(tt);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002586 size = parse_size(tt->text);
2587 if (!size) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002588 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08002589 "invalid size type for `%s' missing directive", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002590 free_tlist(tt);
2591 free_tlist(origline);
2592 return DIRECTIVE_FOUND;
2593 }
2594 free_tlist(tt);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002595
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002596 /* Round up to even stack slots */
2597 size = ALIGN(size, StackSize);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002598
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002599 offset += size; /* Negative offset, increment before */
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002600
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002601 /* Now define the macro for the argument */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002602 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
2603 local, StackPointer, offset);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07002604 do_directive(tokenize(directive), output);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002605
H. Peter Anvine2c80182005-01-15 22:15:51 +00002606 /* Now define the assign to setup the enter_c macro correctly */
2607 snprintf(directive, sizeof(directive),
2608 "%%assign %%$localsize %%$localsize+%d", size);
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07002609 do_directive(tokenize(directive), output);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002610
H. Peter Anvine2c80182005-01-15 22:15:51 +00002611 /* Move to the next argument in the list */
2612 tline = tline->next;
2613 if (tline && tline->type == TOK_WHITESPACE)
2614 tline = tline->next;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002615 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002616 LocalOffset = offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002617 free_tlist(origline);
2618 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002619
H. Peter Anvine2c80182005-01-15 22:15:51 +00002620 case PP_CLEAR:
2621 if (tline->next)
H. Peter Anvin130736c2016-02-17 20:27:41 -08002622 nasm_error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin8b262472019-02-26 14:00:54 -08002623 "trailing garbage after `%s' ignored", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002624 free_macros();
2625 init_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00002626 free_tlist(origline);
2627 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002628
H. Peter Anvin418ca702008-05-30 10:42:30 -07002629 case PP_DEPEND:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002630 t = tline->next = expand_smacro(tline->next);
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002631 skip_white_(t);
2632 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002633 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08002634 nasm_error(ERR_NONFATAL, "`%s' expects a file name", dname);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002635 free_tlist(origline);
2636 return DIRECTIVE_FOUND; /* but we did _something_ */
2637 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002638 if (t->next)
H. Peter Anvin130736c2016-02-17 20:27:41 -08002639 nasm_error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin8b262472019-02-26 14:00:54 -08002640 "trailing garbage after `%s' ignored", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002641 p = t->text;
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002642 if (t->type != TOK_INTERNAL_STRING)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002643 nasm_unquote_cstr(p, i);
H. Peter Anvin436e3672016-10-04 01:12:28 -07002644 nasm_add_string_to_strlist(dephead, p);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002645 free_tlist(origline);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002646 return DIRECTIVE_FOUND;
2647
2648 case PP_INCLUDE:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002649 t = tline->next = expand_smacro(tline->next);
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002650 skip_white_(t);
H. Peter Anvind2456592008-06-19 15:04:18 -07002651
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002652 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002653 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08002654 nasm_error(ERR_NONFATAL, "`%s' expects a file name", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002655 free_tlist(origline);
2656 return DIRECTIVE_FOUND; /* but we did _something_ */
2657 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002658 if (t->next)
H. Peter Anvin130736c2016-02-17 20:27:41 -08002659 nasm_error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin8b262472019-02-26 14:00:54 -08002660 "trailing garbage after `%s' ignored", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002661 p = t->text;
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002662 if (t->type != TOK_INTERNAL_STRING)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002663 nasm_unquote_cstr(p, i);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002664 inc = nasm_malloc(sizeof(Include));
H. Peter Anvine2c80182005-01-15 22:15:51 +00002665 inc->next = istk;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002666 inc->conds = NULL;
Jim Kukunas65a8afc2016-06-13 16:00:42 -04002667 found_path = NULL;
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07002668 inc->fp = inc_fopen(p, dephead, &found_path,
H. Peter Anvind81a2352016-09-21 14:03:18 -07002669 pass == 0 ? INC_OPTIONAL : INC_NEEDED, NF_TEXT);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002670 if (!inc->fp) {
2671 /* -MG given but file not found */
2672 nasm_free(inc);
2673 } else {
Jim Kukunas65a8afc2016-06-13 16:00:42 -04002674 inc->fname = src_set_fname(found_path ? found_path : p);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002675 inc->lineno = src_set_linnum(0);
2676 inc->lineinc = 1;
2677 inc->expansion = NULL;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002678 inc->mstk = NULL;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002679 istk = inc;
H. Peter Anvin8ac25aa2016-02-18 01:16:18 -08002680 lfmt->uplevel(LIST_INCLUDE);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002681 }
2682 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002683 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002684
H. Peter Anvind2456592008-06-19 15:04:18 -07002685 case PP_USE:
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002686 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002687 static macros_t *use_pkg;
2688 const char *pkg_macro = NULL;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002689
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002690 tline = tline->next;
2691 skip_white_(tline);
2692 tline = expand_id(tline);
H. Peter Anvind2456592008-06-19 15:04:18 -07002693
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002694 if (!tline || (tline->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002695 tline->type != TOK_INTERNAL_STRING &&
2696 tline->type != TOK_ID)) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08002697 nasm_error(ERR_NONFATAL, "`%s' expects a package name", dname);
H. Peter Anvind2456592008-06-19 15:04:18 -07002698 free_tlist(origline);
2699 return DIRECTIVE_FOUND; /* but we did _something_ */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002700 }
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002701 if (tline->next)
H. Peter Anvin130736c2016-02-17 20:27:41 -08002702 nasm_error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin8b262472019-02-26 14:00:54 -08002703 "trailing garbage after `%s' ignored", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002704 if (tline->type == TOK_STRING)
2705 nasm_unquote_cstr(tline->text, i);
2706 use_pkg = nasm_stdmac_find_package(tline->text);
2707 if (!use_pkg)
H. Peter Anvin8b262472019-02-26 14:00:54 -08002708 nasm_error(ERR_NONFATAL, "unknown `%s' package: %s", dname, tline->text);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002709 else
2710 pkg_macro = (char *)use_pkg + 1; /* The first string will be <%define>__USE_*__ */
Victor van den Elzen35eb2ea2010-03-10 22:33:48 +01002711 if (use_pkg && ! smacro_defined(NULL, pkg_macro, 0, NULL, true)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002712 /* Not already included, go ahead and include it */
2713 stdmacpos = use_pkg;
2714 }
2715 free_tlist(origline);
H. Peter Anvind2456592008-06-19 15:04:18 -07002716 return DIRECTIVE_FOUND;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002717 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002718 case PP_PUSH:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002719 case PP_REPL:
H. Peter Anvin42b56392008-10-24 16:24:21 -07002720 case PP_POP:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002721 tline = tline->next;
2722 skip_white_(tline);
2723 tline = expand_id(tline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002724 if (tline) {
2725 if (!tok_type_(tline, TOK_ID)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002726 nasm_error(ERR_NONFATAL, "`%s' expects a context identifier",
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002727 pp_directives[i]);
2728 free_tlist(origline);
2729 return DIRECTIVE_FOUND; /* but we did _something_ */
2730 }
2731 if (tline->next)
H. Peter Anvin130736c2016-02-17 20:27:41 -08002732 nasm_error(ERR_WARNING|ERR_PASS1,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002733 "trailing garbage after `%s' ignored",
2734 pp_directives[i]);
2735 p = nasm_strdup(tline->text);
2736 } else {
2737 p = NULL; /* Anonymous */
2738 }
H. Peter Anvin42b56392008-10-24 16:24:21 -07002739
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002740 if (i == PP_PUSH) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002741 ctx = nasm_malloc(sizeof(Context));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002742 ctx->next = cstk;
2743 hash_init(&ctx->localmac, HASH_SMALL);
2744 ctx->name = p;
2745 ctx->number = unique++;
2746 cstk = ctx;
2747 } else {
2748 /* %pop or %repl */
2749 if (!cstk) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002750 nasm_error(ERR_NONFATAL, "`%s': context stack is empty",
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002751 pp_directives[i]);
2752 } else if (i == PP_POP) {
2753 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
H. Peter Anvin8b262472019-02-26 14:00:54 -08002754 nasm_error(ERR_NONFATAL, "`%s' in wrong context: %s, "
2755 "expected %s",
2756 dname, cstk->name ? cstk->name : "anonymous", p);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002757 else
2758 ctx_pop();
2759 } else {
2760 /* i == PP_REPL */
2761 nasm_free(cstk->name);
2762 cstk->name = p;
2763 p = NULL;
2764 }
2765 nasm_free(p);
2766 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002767 free_tlist(origline);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002768 return DIRECTIVE_FOUND;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002769 case PP_FATAL:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002770 severity = ERR_FATAL;
2771 goto issue_error;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002772 case PP_ERROR:
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002773 severity = ERR_NONFATAL;
2774 goto issue_error;
H. Peter Anvin7df04172008-06-10 18:27:38 -07002775 case PP_WARNING:
H. Peter Anvin (Intel)77f53ba2018-12-12 14:38:50 -08002776 severity = ERR_WARNING|WARN_USER;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002777 goto issue_error;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002778
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002779issue_error:
H. Peter Anvin7df04172008-06-10 18:27:38 -07002780 {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002781 /* Only error out if this is the final pass */
2782 if (pass != 2 && i != PP_FATAL)
2783 return DIRECTIVE_FOUND;
2784
2785 tline->next = expand_smacro(tline->next);
2786 tline = tline->next;
2787 skip_white_(tline);
2788 t = tline ? tline->next : NULL;
2789 skip_white_(t);
2790 if (tok_type_(tline, TOK_STRING) && !t) {
2791 /* The line contains only a quoted string */
2792 p = tline->text;
2793 nasm_unquote(p, NULL); /* Ignore NUL character truncation */
H. Peter Anvin130736c2016-02-17 20:27:41 -08002794 nasm_error(severity, "%s", p);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002795 } else {
2796 /* Not a quoted string, or more than a quoted string */
2797 p = detoken(tline, false);
H. Peter Anvin130736c2016-02-17 20:27:41 -08002798 nasm_error(severity, "%s", p);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002799 nasm_free(p);
2800 }
2801 free_tlist(origline);
2802 return DIRECTIVE_FOUND;
H. Peter Anvin7df04172008-06-10 18:27:38 -07002803 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002804
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002805 CASE_PP_IF:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002806 if (istk->conds && !emitting(istk->conds->state))
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002807 j = COND_NEVER;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002808 else {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002809 j = if_condition(tline->next, i);
2810 tline->next = NULL; /* it got freed */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002811 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002812 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002813 cond = nasm_malloc(sizeof(Cond));
2814 cond->next = istk->conds;
2815 cond->state = j;
2816 istk->conds = cond;
2817 if(istk->mstk)
2818 istk->mstk->condcnt ++;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002819 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002820 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002821
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002822 CASE_PP_ELIF:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002823 if (!istk->conds)
H. Peter Anvin8b262472019-02-26 14:00:54 -08002824 nasm_error(ERR_FATAL, "`%s': no matching `%%if'", dname);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002825 switch(istk->conds->state) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002826 case COND_IF_TRUE:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002827 istk->conds->state = COND_DONE;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002828 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002829
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002830 case COND_DONE:
2831 case COND_NEVER:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002832 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002833
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002834 case COND_ELSE_TRUE:
2835 case COND_ELSE_FALSE:
H. Peter Anvin130736c2016-02-17 20:27:41 -08002836 nasm_error(ERR_WARNING|ERR_PASS1|ERR_PP_PRECOND,
2837 "`%%elif' after `%%else' ignored");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002838 istk->conds->state = COND_NEVER;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002839 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002840
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002841 case COND_IF_FALSE:
2842 /*
2843 * IMPORTANT: In the case of %if, we will already have
2844 * called expand_mmac_params(); however, if we're
2845 * processing an %elif we must have been in a
2846 * non-emitting mode, which would have inhibited
2847 * the normal invocation of expand_mmac_params().
2848 * Therefore, we have to do it explicitly here.
2849 */
2850 j = if_condition(expand_mmac_params(tline->next), i);
2851 tline->next = NULL; /* it got freed */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002852 istk->conds->state =
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002853 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2854 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002855 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002856 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002857 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002858
H. Peter Anvine2c80182005-01-15 22:15:51 +00002859 case PP_ELSE:
2860 if (tline->next)
H. Peter Anvin130736c2016-02-17 20:27:41 -08002861 nasm_error(ERR_WARNING|ERR_PASS1|ERR_PP_PRECOND,
2862 "trailing garbage after `%%else' ignored");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002863 if (!istk->conds)
H. Peter Anvin130736c2016-02-17 20:27:41 -08002864 nasm_fatal(0, "`%%else: no matching `%%if'");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002865 switch(istk->conds->state) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002866 case COND_IF_TRUE:
2867 case COND_DONE:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002868 istk->conds->state = COND_ELSE_FALSE;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002869 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002870
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002871 case COND_NEVER:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002872 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002873
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002874 case COND_IF_FALSE:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002875 istk->conds->state = COND_ELSE_TRUE;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002876 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002877
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002878 case COND_ELSE_TRUE:
2879 case COND_ELSE_FALSE:
H. Peter Anvin130736c2016-02-17 20:27:41 -08002880 nasm_error(ERR_WARNING|ERR_PASS1|ERR_PP_PRECOND,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002881 "`%%else' after `%%else' ignored.");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002882 istk->conds->state = COND_NEVER;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002883 break;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002884 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002885 free_tlist(origline);
2886 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002887
H. Peter Anvine2c80182005-01-15 22:15:51 +00002888 case PP_ENDIF:
2889 if (tline->next)
H. Peter Anvin130736c2016-02-17 20:27:41 -08002890 nasm_error(ERR_WARNING|ERR_PASS1|ERR_PP_PRECOND,
2891 "trailing garbage after `%%endif' ignored");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002892 if (!istk->conds)
H. Peter Anvin130736c2016-02-17 20:27:41 -08002893 nasm_error(ERR_FATAL, "`%%endif': no matching `%%if'");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002894 cond = istk->conds;
2895 istk->conds = cond->next;
2896 nasm_free(cond);
2897 if(istk->mstk)
2898 istk->mstk->condcnt --;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002899 free_tlist(origline);
2900 return DIRECTIVE_FOUND;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002901
H. Peter Anvindb8f96e2009-07-15 09:07:29 -04002902 case PP_IRMACRO:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002903 case PP_IMACRO:
H. Peter Anvin8b262472019-02-26 14:00:54 -08002904 casesense = false;
2905 /* fall through */
2906 case PP_RMACRO:
2907 case PP_MACRO:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002908 if (defining) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002909 nasm_error(ERR_FATAL, "`%s': already defining a macro",
H. Peter Anvin8b262472019-02-26 14:00:54 -08002910 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002911 return DIRECTIVE_FOUND;
2912 }
H. Peter Anvin4def1a82016-05-09 13:59:44 -07002913 defining = nasm_zalloc(sizeof(MMacro));
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07002914 defining->max_depth = ((i == PP_RMACRO) || (i == PP_IRMACRO))
2915 ? nasm_limit[LIMIT_MACROS] : 0;
H. Peter Anvin8b262472019-02-26 14:00:54 -08002916 defining->casesense = casesense;
2917 if (!parse_mmacro_spec(tline, defining, dname)) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002918 nasm_free(defining);
2919 defining = NULL;
2920 return DIRECTIVE_FOUND;
2921 }
H. Peter Anvina26433d2008-07-16 14:40:01 -07002922
H. Peter Anvin4def1a82016-05-09 13:59:44 -07002923 src_get(&defining->xline, &defining->fname);
2924
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002925 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
2926 while (mmac) {
2927 if (!strcmp(mmac->name, defining->name) &&
2928 (mmac->nparam_min <= defining->nparam_max
2929 || defining->plus)
2930 && (defining->nparam_min <= mmac->nparam_max
2931 || mmac->plus)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002932 nasm_error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002933 "redefining multi-line macro `%s'", defining->name);
2934 return DIRECTIVE_FOUND;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002935 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002936 mmac = mmac->next;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002937 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002938 free_tlist(origline);
2939 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002940
H. Peter Anvine2c80182005-01-15 22:15:51 +00002941 case PP_ENDM:
2942 case PP_ENDMACRO:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002943 if (! (defining && defining->name)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002944 nasm_error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002945 return DIRECTIVE_FOUND;
2946 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002947 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
2948 defining->next = *mmhead;
2949 *mmhead = defining;
2950 defining = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002951 free_tlist(origline);
2952 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002953
H. Peter Anvin89cee572009-07-15 09:16:54 -04002954 case PP_EXITMACRO:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002955 /*
2956 * We must search along istk->expansion until we hit a
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002957 * macro-end marker for a macro with a name. Then we
2958 * bypass all lines between exitmacro and endmacro.
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002959 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002960 list_for_each(l, istk->expansion)
2961 if (l->finishes && l->finishes->name)
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002962 break;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002963
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002964 if (l) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002965 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002966 * Remove all conditional entries relative to this
2967 * macro invocation. (safe to do in this context)
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002968 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002969 for ( ; l->finishes->condcnt > 0; l->finishes->condcnt --) {
2970 cond = istk->conds;
2971 istk->conds = cond->next;
2972 nasm_free(cond);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002973 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002974 istk->expansion = l;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002975 } else {
H. Peter Anvin130736c2016-02-17 20:27:41 -08002976 nasm_error(ERR_NONFATAL, "`%%exitmacro' not within `%%macro' block");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03002977 }
Keith Kanios852f1ee2009-07-12 00:19:55 -05002978 free_tlist(origline);
2979 return DIRECTIVE_FOUND;
2980
H. Peter Anvina26433d2008-07-16 14:40:01 -07002981 case PP_UNIMACRO:
H. Peter Anvin8b262472019-02-26 14:00:54 -08002982 casesense = false;
2983 /* fall through */
2984 case PP_UNMACRO:
H. Peter Anvina26433d2008-07-16 14:40:01 -07002985 {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002986 MMacro **mmac_p;
2987 MMacro spec;
H. Peter Anvina26433d2008-07-16 14:40:01 -07002988
H. Peter Anvin8b262472019-02-26 14:00:54 -08002989 spec.casesense = casesense;
2990 if (!parse_mmacro_spec(tline, &spec, dname)) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03002991 return DIRECTIVE_FOUND;
2992 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08002993 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
2994 while (mmac_p && *mmac_p) {
2995 mmac = *mmac_p;
2996 if (mmac->casesense == spec.casesense &&
2997 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
2998 mmac->nparam_min == spec.nparam_min &&
2999 mmac->nparam_max == spec.nparam_max &&
3000 mmac->plus == spec.plus) {
3001 *mmac_p = mmac->next;
3002 free_mmacro(mmac);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003003 } else {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003004 mmac_p = &mmac->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003005 }
3006 }
3007 free_tlist(origline);
3008 free_tlist(spec.dlist);
3009 return DIRECTIVE_FOUND;
H. Peter Anvina26433d2008-07-16 14:40:01 -07003010 }
3011
H. Peter Anvine2c80182005-01-15 22:15:51 +00003012 case PP_ROTATE:
3013 if (tline->next && tline->next->type == TOK_WHITESPACE)
3014 tline = tline->next;
H. Peter Anvin89cee572009-07-15 09:16:54 -04003015 if (!tline->next) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003016 free_tlist(origline);
H. Peter Anvin130736c2016-02-17 20:27:41 -08003017 nasm_error(ERR_NONFATAL, "`%%rotate' missing rotate count");
H. Peter Anvine2c80182005-01-15 22:15:51 +00003018 return DIRECTIVE_FOUND;
3019 }
3020 t = expand_smacro(tline->next);
3021 tline->next = NULL;
3022 free_tlist(origline);
H. Peter Anvin8b262472019-02-26 14:00:54 -08003023 pps.tptr = tline = t;
3024 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003025 tokval.t_type = TOKEN_INVALID;
3026 evalresult =
H. Peter Anvin8b262472019-02-26 14:00:54 -08003027 evaluate(ppscan, &pps, &tokval, NULL, pass, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003028 free_tlist(tline);
3029 if (!evalresult)
3030 return DIRECTIVE_FOUND;
3031 if (tokval.t_type)
H. Peter Anvin130736c2016-02-17 20:27:41 -08003032 nasm_error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003033 "trailing garbage after expression ignored");
3034 if (!is_simple(evalresult)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003035 nasm_error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
H. Peter Anvine2c80182005-01-15 22:15:51 +00003036 return DIRECTIVE_FOUND;
3037 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003038 mmac = istk->mstk;
3039 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
3040 mmac = mmac->next_active;
3041 if (!mmac) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003042 nasm_error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003043 } else if (mmac->nparam == 0) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003044 nasm_error(ERR_NONFATAL,
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003045 "`%%rotate' invoked within macro without parameters");
3046 } else {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003047 int rotate = mmac->rotate + reloc_value(evalresult);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003048
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003049 rotate %= (int)mmac->nparam;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003050 if (rotate < 0)
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003051 rotate += mmac->nparam;
3052
3053 mmac->rotate = rotate;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003054 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003055 return DIRECTIVE_FOUND;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003056
H. Peter Anvine2c80182005-01-15 22:15:51 +00003057 case PP_REP:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003058 nolist = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003059 do {
3060 tline = tline->next;
3061 } while (tok_type_(tline, TOK_WHITESPACE));
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003062
H. Peter Anvine2c80182005-01-15 22:15:51 +00003063 if (tok_type_(tline, TOK_ID) &&
3064 nasm_stricmp(tline->text, ".nolist") == 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003065 nolist = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003066 do {
3067 tline = tline->next;
3068 } while (tok_type_(tline, TOK_WHITESPACE));
3069 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003070
H. Peter Anvine2c80182005-01-15 22:15:51 +00003071 if (tline) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08003072 pps.tptr = expand_smacro(tline);
3073 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003074 tokval.t_type = TOKEN_INVALID;
3075 evalresult =
H. Peter Anvin8b262472019-02-26 14:00:54 -08003076 evaluate(ppscan, &pps, &tokval, NULL, pass, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003077 if (!evalresult) {
3078 free_tlist(origline);
3079 return DIRECTIVE_FOUND;
3080 }
3081 if (tokval.t_type)
H. Peter Anvin130736c2016-02-17 20:27:41 -08003082 nasm_error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003083 "trailing garbage after expression ignored");
3084 if (!is_simple(evalresult)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003085 nasm_error(ERR_NONFATAL, "non-constant value given to `%%rep'");
H. Peter Anvine2c80182005-01-15 22:15:51 +00003086 return DIRECTIVE_FOUND;
3087 }
Cyrill Gorcunove091d6e2010-08-09 13:58:22 +04003088 count = reloc_value(evalresult);
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07003089 if (count > nasm_limit[LIMIT_REP]) {
3090 nasm_error(ERR_NONFATAL,
H. Peter Anvin79561022018-06-15 17:51:39 -07003091 "`%%rep' count %"PRId64" exceeds limit (currently %"PRId64")",
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07003092 count, nasm_limit[LIMIT_REP]);
Cyrill Gorcunove091d6e2010-08-09 13:58:22 +04003093 count = 0;
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07003094 } else if (count < 0) {
H. Peter Anvin (Intel)77f53ba2018-12-12 14:38:50 -08003095 nasm_error(ERR_WARNING|ERR_PASS2|WARN_NEG_REP,
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07003096 "negative `%%rep' count: %"PRId64, count);
3097 count = 0;
3098 } else {
Cyrill Gorcunove091d6e2010-08-09 13:58:22 +04003099 count++;
H. Peter Anvin987dc9c2018-06-12 13:50:37 -07003100 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003101 } else {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003102 nasm_error(ERR_NONFATAL, "`%%rep' expects a repeat count");
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07003103 count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003104 }
3105 free_tlist(origline);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003106
3107 tmp_defining = defining;
3108 defining = nasm_malloc(sizeof(MMacro));
3109 defining->prev = NULL;
3110 defining->name = NULL; /* flags this macro as a %rep block */
3111 defining->casesense = false;
3112 defining->plus = false;
3113 defining->nolist = nolist;
3114 defining->in_progress = count;
3115 defining->max_depth = 0;
3116 defining->nparam_min = defining->nparam_max = 0;
3117 defining->defaults = NULL;
3118 defining->dlist = NULL;
3119 defining->expansion = NULL;
3120 defining->next_active = istk->mstk;
3121 defining->rep_nest = tmp_defining;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003122 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003123
H. Peter Anvine2c80182005-01-15 22:15:51 +00003124 case PP_ENDREP:
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003125 if (!defining || defining->name) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003126 nasm_error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
H. Peter Anvine2c80182005-01-15 22:15:51 +00003127 return DIRECTIVE_FOUND;
3128 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003129
H. Peter Anvine2c80182005-01-15 22:15:51 +00003130 /*
3131 * Now we have a "macro" defined - although it has no name
3132 * and we won't be entering it in the hash tables - we must
3133 * push a macro-end marker for it on to istk->expansion.
3134 * After that, it will take care of propagating itself (a
3135 * macro-end marker line for a macro which is really a %rep
3136 * block will cause the macro to be re-expanded, complete
3137 * with another macro-end marker to ensure the process
3138 * continues) until the whole expansion is forcibly removed
3139 * from istk->expansion by a %exitrep.
3140 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003141 l = nasm_malloc(sizeof(Line));
3142 l->next = istk->expansion;
3143 l->finishes = defining;
3144 l->first = NULL;
3145 istk->expansion = l;
3146
3147 istk->mstk = defining;
3148
H. Peter Anvin8ac25aa2016-02-18 01:16:18 -08003149 lfmt->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003150 tmp_defining = defining;
3151 defining = defining->rep_nest;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003152 free_tlist(origline);
3153 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003154
H. Peter Anvine2c80182005-01-15 22:15:51 +00003155 case PP_EXITREP:
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003156 /*
3157 * We must search along istk->expansion until we hit a
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003158 * macro-end marker for a macro with no name. Then we set
3159 * its `in_progress' flag to 0.
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003160 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003161 list_for_each(l, istk->expansion)
3162 if (l->finishes && !l->finishes->name)
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003163 break;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003164
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003165 if (l)
3166 l->finishes->in_progress = 1;
3167 else
H. Peter Anvin130736c2016-02-17 20:27:41 -08003168 nasm_error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
H. Peter Anvine2c80182005-01-15 22:15:51 +00003169 free_tlist(origline);
3170 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003171
H. Peter Anvine2c80182005-01-15 22:15:51 +00003172 case PP_IDEFINE:
H. Peter Anvin8b262472019-02-26 14:00:54 -08003173 case PP_IXDEFINE:
3174 casesense = false;
3175 /* fall through */
3176 case PP_DEFINE:
3177 case PP_XDEFINE:
3178 {
3179 SMacro *s;
3180 bool have_eval_params = false;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003181
H. Peter Anvine2c80182005-01-15 22:15:51 +00003182 tline = tline->next;
3183 skip_white_(tline);
3184 tline = expand_id(tline);
3185 if (!tline || (tline->type != TOK_ID &&
3186 (tline->type != TOK_PREPROC_ID ||
3187 tline->text[1] != '$'))) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003188 nasm_error(ERR_NONFATAL, "`%s' expects a macro identifier",
H. Peter Anvin8b262472019-02-26 14:00:54 -08003189 dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003190 free_tlist(origline);
3191 return DIRECTIVE_FOUND;
3192 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003193
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04003194 ctx = get_ctx(tline->text, &mname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003195 last = tline;
3196 param_start = tline = tline->next;
3197 nparam = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003198
H. Peter Anvine2c80182005-01-15 22:15:51 +00003199 if (tok_is_(tline, "(")) {
3200 /*
3201 * This macro has parameters.
3202 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003203
H. Peter Anvine2c80182005-01-15 22:15:51 +00003204 tline = tline->next;
3205 while (1) {
3206 skip_white_(tline);
3207 if (!tline) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003208 nasm_error(ERR_NONFATAL, "parameter identifier expected");
H. Peter Anvine2c80182005-01-15 22:15:51 +00003209 free_tlist(origline);
3210 return DIRECTIVE_FOUND;
3211 }
H. Peter Anvin8b262472019-02-26 14:00:54 -08003212 if (tok_is_(tline, "=")) {
3213 have_eval_params = true;
3214 tline = tline->next;
3215 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003216 if (tline->type != TOK_ID) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003217 nasm_error(ERR_NONFATAL,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003218 "`%s': parameter identifier expected",
3219 tline->text);
3220 free_tlist(origline);
3221 return DIRECTIVE_FOUND;
3222 }
H. Peter Anvin8b262472019-02-26 14:00:54 -08003223 tline->type = tok_smac_param(nparam++);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003224 tline = tline->next;
3225 skip_white_(tline);
3226 if (tok_is_(tline, ",")) {
3227 tline = tline->next;
H. Peter Anvinca348b62008-07-23 10:49:26 -04003228 } else {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003229 if (!tok_is_(tline, ")")) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003230 nasm_error(ERR_NONFATAL,
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003231 "`)' expected to terminate macro template");
3232 free_tlist(origline);
3233 return DIRECTIVE_FOUND;
3234 }
3235 break;
3236 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003237 }
3238 last = tline;
3239 tline = tline->next;
3240 }
3241 if (tok_type_(tline, TOK_WHITESPACE))
3242 last = tline, tline = tline->next;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003243 last->next = NULL;
H. Peter Anvin8b262472019-02-26 14:00:54 -08003244
3245 /* Expand the macro definition now for %xdefine and %ixdefine */
3246 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
3247 tline = expand_smacro(tline);
3248
3249 macro_start = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003250 t = tline;
3251 while (t) {
3252 if (t->type == TOK_ID) {
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04003253 list_for_each(tt, param_start)
H. Peter Anvin8b262472019-02-26 14:00:54 -08003254 if (is_smac_param(tt->type) && !strcmp(tt->text, t->text))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003255 t->type = tt->type;
3256 }
3257 tt = t->next;
3258 t->next = macro_start;
3259 macro_start = t;
3260 t = tt;
3261 }
3262 /*
3263 * Good. We now have a macro name, a parameter count, and a
3264 * token list (in reverse order) for an expansion. We ought
3265 * to be OK just to create an SMacro, store it, and let
3266 * free_tlist have the rest of the line (which we have
3267 * carefully re-terminated after chopping off the expansion
3268 * from the end).
3269 */
H. Peter Anvin8b262472019-02-26 14:00:54 -08003270 s = define_smacro(ctx, mname, casesense, nparam, macro_start);
3271
3272 if (have_eval_params) {
3273 /* Create evaluated parameters table */
3274 bool is_eval = false;
3275
3276 nasm_newn(s->eval_param, nparam);
3277 list_for_each(tt, param_start) {
3278 if (is_smac_param(tt->type))
3279 s->eval_param[smac_nparam(tt->type)] = is_eval;
3280 is_eval = tok_is_(tt, "=");
3281 }
3282 }
3283
3284
H. Peter Anvine2c80182005-01-15 22:15:51 +00003285 free_tlist(origline);
3286 return DIRECTIVE_FOUND;
H. Peter Anvin8b262472019-02-26 14:00:54 -08003287 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003288
H. Peter Anvine2c80182005-01-15 22:15:51 +00003289 case PP_UNDEF:
3290 tline = tline->next;
3291 skip_white_(tline);
3292 tline = expand_id(tline);
3293 if (!tline || (tline->type != TOK_ID &&
3294 (tline->type != TOK_PREPROC_ID ||
3295 tline->text[1] != '$'))) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003296 nasm_error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
H. Peter Anvine2c80182005-01-15 22:15:51 +00003297 free_tlist(origline);
3298 return DIRECTIVE_FOUND;
3299 }
3300 if (tline->next) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003301 nasm_error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003302 "trailing garbage after macro name ignored");
3303 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003304
H. Peter Anvine2c80182005-01-15 22:15:51 +00003305 /* Find the context that symbol belongs to */
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04003306 ctx = get_ctx(tline->text, &mname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003307 undef_smacro(ctx, mname);
3308 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003309 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003310
H. Peter Anvin9e200162008-06-04 17:23:14 -07003311 case PP_IDEFSTR:
H. Peter Anvin8b262472019-02-26 14:00:54 -08003312 casesense = false;
3313 /* fall through */
3314 case PP_DEFSTR:
H. Peter Anvin9e200162008-06-04 17:23:14 -07003315 tline = tline->next;
3316 skip_white_(tline);
3317 tline = expand_id(tline);
3318 if (!tline || (tline->type != TOK_ID &&
3319 (tline->type != TOK_PREPROC_ID ||
3320 tline->text[1] != '$'))) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003321 nasm_error(ERR_NONFATAL, "`%s' expects a macro identifier",
H. Peter Anvin8b262472019-02-26 14:00:54 -08003322 dname);
H. Peter Anvin9e200162008-06-04 17:23:14 -07003323 free_tlist(origline);
3324 return DIRECTIVE_FOUND;
3325 }
3326
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04003327 ctx = get_ctx(tline->text, &mname);
H. Peter Anvin9e200162008-06-04 17:23:14 -07003328 last = tline;
3329 tline = expand_smacro(tline->next);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003330 last->next = NULL;
H. Peter Anvin9e200162008-06-04 17:23:14 -07003331
3332 while (tok_type_(tline, TOK_WHITESPACE))
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003333 tline = delete_Token(tline);
H. Peter Anvin9e200162008-06-04 17:23:14 -07003334
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003335 p = detoken(tline, false);
H. Peter Anvin8b262472019-02-26 14:00:54 -08003336 macro_start = make_tok_qstr(p);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003337 nasm_free(p);
H. Peter Anvin9e200162008-06-04 17:23:14 -07003338
3339 /*
3340 * We now have a macro name, an implicit parameter count of
3341 * zero, and a string token to use as an expansion. Create
3342 * and store an SMacro.
3343 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003344 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvin9e200162008-06-04 17:23:14 -07003345 free_tlist(origline);
3346 return DIRECTIVE_FOUND;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003347
H. Peter Anvin2f55bda2009-07-14 15:04:04 -04003348 case PP_IDEFTOK:
H. Peter Anvin8b262472019-02-26 14:00:54 -08003349 casesense = false;
3350 /* fall through */
3351 case PP_DEFTOK:
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003352 tline = tline->next;
3353 skip_white_(tline);
3354 tline = expand_id(tline);
3355 if (!tline || (tline->type != TOK_ID &&
3356 (tline->type != TOK_PREPROC_ID ||
3357 tline->text[1] != '$'))) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003358 nasm_error(ERR_NONFATAL,
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003359 "`%s' expects a macro identifier as first parameter",
H. Peter Anvin8b262472019-02-26 14:00:54 -08003360 dname);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003361 free_tlist(origline);
3362 return DIRECTIVE_FOUND;
3363 }
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04003364 ctx = get_ctx(tline->text, &mname);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003365 last = tline;
3366 tline = expand_smacro(tline->next);
3367 last->next = NULL;
3368
3369 t = tline;
3370 while (tok_type_(t, TOK_WHITESPACE))
3371 t = t->next;
3372 /* t should now point to the string */
Cyrill Gorcunov6908e582010-09-06 19:36:15 +04003373 if (!tok_type_(t, TOK_STRING)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003374 nasm_error(ERR_NONFATAL,
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003375 "`%s` requires string as second parameter",
H. Peter Anvin8b262472019-02-26 14:00:54 -08003376 dname);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003377 free_tlist(tline);
3378 free_tlist(origline);
3379 return DIRECTIVE_FOUND;
3380 }
3381
Cyrill Gorcunov4d8dbd92014-06-28 10:15:18 +04003382 /*
3383 * Convert the string to a token stream. Note that smacros
3384 * are stored with the token stream reversed, so we have to
3385 * reverse the output of tokenize().
3386 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003387 nasm_unquote_cstr(t->text, i);
H. Peter Anvinb40992c2010-09-15 08:57:21 -07003388 macro_start = reverse_tokens(tokenize(t->text));
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003389
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003390 /*
3391 * We now have a macro name, an implicit parameter count of
3392 * zero, and a numeric token to use as an expansion. Create
3393 * and store an SMacro.
3394 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003395 define_smacro(ctx, mname, casesense, 0, macro_start);
Keith Kaniosb83fd0b2009-07-14 01:04:12 -05003396 free_tlist(tline);
3397 free_tlist(origline);
3398 return DIRECTIVE_FOUND;
H. Peter Anvin9e200162008-06-04 17:23:14 -07003399
H. Peter Anvin8b262472019-02-26 14:00:54 -08003400 case PP_IPATHSEARCH:
3401 casesense = false;
3402 /* fall through */
H. Peter Anvin418ca702008-05-30 10:42:30 -07003403 case PP_PATHSEARCH:
3404 {
H. Peter Anvinccad6f92016-10-04 00:34:35 -07003405 const char *found_path;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003406
H. Peter Anvin418ca702008-05-30 10:42:30 -07003407 tline = tline->next;
3408 skip_white_(tline);
3409 tline = expand_id(tline);
3410 if (!tline || (tline->type != TOK_ID &&
3411 (tline->type != TOK_PREPROC_ID ||
3412 tline->text[1] != '$'))) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003413 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08003414 "`%s' expects a macro identifier as first parameter", dname);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003415 free_tlist(origline);
3416 return DIRECTIVE_FOUND;
3417 }
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04003418 ctx = get_ctx(tline->text, &mname);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003419 last = tline;
3420 tline = expand_smacro(tline->next);
3421 last->next = NULL;
3422
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003423 t = tline;
H. Peter Anvin418ca702008-05-30 10:42:30 -07003424 while (tok_type_(t, TOK_WHITESPACE))
3425 t = t->next;
3426
3427 if (!t || (t->type != TOK_STRING &&
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003428 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08003429 nasm_error(ERR_NONFATAL, "`%s' expects a file name", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003430 free_tlist(tline);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003431 free_tlist(origline);
3432 return DIRECTIVE_FOUND; /* but we did _something_ */
3433 }
3434 if (t->next)
H. Peter Anvin130736c2016-02-17 20:27:41 -08003435 nasm_error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin8b262472019-02-26 14:00:54 -08003436 "trailing garbage after `%s' ignored", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003437 p = t->text;
H. Peter Anvin427cc912008-06-01 21:43:03 -07003438 if (t->type != TOK_INTERNAL_STRING)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003439 nasm_unquote(p, NULL);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003440
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07003441 inc_fopen(p, NULL, &found_path, INC_PROBE, NF_BINARY);
H. Peter Anvinccad6f92016-10-04 00:34:35 -07003442 if (!found_path)
3443 found_path = p;
H. Peter Anvin8b262472019-02-26 14:00:54 -08003444 macro_start = make_tok_qstr(found_path);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003445
3446 /*
3447 * We now have a macro name, an implicit parameter count of
3448 * zero, and a string token to use as an expansion. Create
3449 * and store an SMacro.
3450 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003451 define_smacro(ctx, mname, casesense, 0, macro_start);
3452 free_tlist(tline);
H. Peter Anvin418ca702008-05-30 10:42:30 -07003453 free_tlist(origline);
3454 return DIRECTIVE_FOUND;
3455 }
3456
H. Peter Anvin8b262472019-02-26 14:00:54 -08003457 case PP_ISTRLEN:
3458 casesense = false;
3459 /* fall through */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003460 case PP_STRLEN:
3461 tline = tline->next;
3462 skip_white_(tline);
3463 tline = expand_id(tline);
3464 if (!tline || (tline->type != TOK_ID &&
3465 (tline->type != TOK_PREPROC_ID ||
3466 tline->text[1] != '$'))) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003467 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08003468 "`%s' expects a macro identifier as first parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003469 free_tlist(origline);
3470 return DIRECTIVE_FOUND;
3471 }
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04003472 ctx = get_ctx(tline->text, &mname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003473 last = tline;
3474 tline = expand_smacro(tline->next);
3475 last->next = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003476
H. Peter Anvine2c80182005-01-15 22:15:51 +00003477 t = tline;
3478 while (tok_type_(t, TOK_WHITESPACE))
3479 t = t->next;
3480 /* t should now point to the string */
Cyrill Gorcunov4e1d5ab2010-07-23 18:51:51 +04003481 if (!tok_type_(t, TOK_STRING)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003482 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08003483 "`%s` requires string as second parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003484 free_tlist(tline);
3485 free_tlist(origline);
3486 return DIRECTIVE_FOUND;
3487 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003488
H. Peter Anvin8b262472019-02-26 14:00:54 -08003489 macro_start = make_tok_num(nasm_unquote(t->text, NULL));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003490
H. Peter Anvine2c80182005-01-15 22:15:51 +00003491 /*
3492 * We now have a macro name, an implicit parameter count of
3493 * zero, and a numeric token to use as an expansion. Create
3494 * and store an SMacro.
3495 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003496 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003497 free_tlist(tline);
3498 free_tlist(origline);
3499 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003500
H. Peter Anvin8b262472019-02-26 14:00:54 -08003501 case PP_ISTRCAT:
3502 casesense = false;
3503 /* fall through */
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003504 case PP_STRCAT:
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003505 tline = tline->next;
3506 skip_white_(tline);
3507 tline = expand_id(tline);
3508 if (!tline || (tline->type != TOK_ID &&
3509 (tline->type != TOK_PREPROC_ID ||
3510 tline->text[1] != '$'))) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003511 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08003512 "`%s' expects a macro identifier as first parameter", dname);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003513 free_tlist(origline);
3514 return DIRECTIVE_FOUND;
3515 }
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04003516 ctx = get_ctx(tline->text, &mname);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003517 last = tline;
3518 tline = expand_smacro(tline->next);
3519 last->next = NULL;
3520
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003521 len = 0;
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04003522 list_for_each(t, tline) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003523 switch (t->type) {
3524 case TOK_WHITESPACE:
3525 break;
3526 case TOK_STRING:
3527 len += t->a.len = nasm_unquote(t->text, NULL);
3528 break;
3529 case TOK_OTHER:
3530 if (!strcmp(t->text, ",")) /* permit comma separators */
3531 break;
3532 /* else fall through */
3533 default:
H. Peter Anvin130736c2016-02-17 20:27:41 -08003534 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08003535 "non-string passed to `%s': %s", dname, t->text);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003536 free_tlist(tline);
3537 free_tlist(origline);
3538 return DIRECTIVE_FOUND;
3539 }
3540 }
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003541
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003542 p = pp = nasm_malloc(len);
Cyrill Gorcunov3b4e86b2010-06-02 15:57:51 +04003543 list_for_each(t, tline) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003544 if (t->type == TOK_STRING) {
3545 memcpy(p, t->text, t->a.len);
3546 p += t->a.len;
3547 }
3548 }
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003549
3550 /*
3551 * We now have a macro name, an implicit parameter count of
3552 * zero, and a numeric token to use as an expansion. Create
3553 * and store an SMacro.
3554 */
H. Peter Anvin8b262472019-02-26 14:00:54 -08003555 macro_start = make_tok_qstr(pp);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003556 nasm_free(pp);
3557 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003558 free_tlist(tline);
3559 free_tlist(origline);
3560 return DIRECTIVE_FOUND;
3561
H. Peter Anvin8b262472019-02-26 14:00:54 -08003562 case PP_ISUBSTR:
3563 casesense = false;
3564 /* fall through */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003565 case PP_SUBSTR:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003566 {
Cyrill Gorcunovab122872010-09-07 10:42:02 +04003567 int64_t start, count;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003568 size_t len;
H. Peter Anvind2456592008-06-19 15:04:18 -07003569
H. Peter Anvine2c80182005-01-15 22:15:51 +00003570 tline = tline->next;
3571 skip_white_(tline);
3572 tline = expand_id(tline);
3573 if (!tline || (tline->type != TOK_ID &&
3574 (tline->type != TOK_PREPROC_ID ||
3575 tline->text[1] != '$'))) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003576 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08003577 "`%s' expects a macro identifier as first parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003578 free_tlist(origline);
3579 return DIRECTIVE_FOUND;
3580 }
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04003581 ctx = get_ctx(tline->text, &mname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003582 last = tline;
3583 tline = expand_smacro(tline->next);
3584 last->next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003585
Cyrill Gorcunov35519d62010-09-06 23:49:52 +04003586 if (tline) /* skip expanded id */
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003587 t = tline->next;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003588 while (tok_type_(t, TOK_WHITESPACE))
3589 t = t->next;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003590
H. Peter Anvine2c80182005-01-15 22:15:51 +00003591 /* t should now point to the string */
Cyrill Gorcunov35519d62010-09-06 23:49:52 +04003592 if (!tok_type_(t, TOK_STRING)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003593 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08003594 "`%s' requires string as second parameter", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003595 free_tlist(tline);
3596 free_tlist(origline);
3597 return DIRECTIVE_FOUND;
3598 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003599
H. Peter Anvin8b262472019-02-26 14:00:54 -08003600 pps.tptr = t->next;
3601 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003602 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin8b262472019-02-26 14:00:54 -08003603 evalresult = evaluate(ppscan, &pps, &tokval, NULL, pass, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003604 if (!evalresult) {
3605 free_tlist(tline);
3606 free_tlist(origline);
3607 return DIRECTIVE_FOUND;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003608 } else if (!is_simple(evalresult)) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08003609 nasm_error(ERR_NONFATAL, "non-constant value given to `%s'", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003610 free_tlist(tline);
3611 free_tlist(origline);
3612 return DIRECTIVE_FOUND;
3613 }
Cyrill Gorcunovab122872010-09-07 10:42:02 +04003614 start = evalresult->value - 1;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003615
H. Peter Anvin8b262472019-02-26 14:00:54 -08003616 while (tok_type_(pps.tptr, TOK_WHITESPACE))
3617 pps.tptr = pps.tptr->next;
3618 if (!pps.tptr) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003619 count = 1; /* Backwards compatibility: one character */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003620 } else {
3621 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin8b262472019-02-26 14:00:54 -08003622 evalresult = evaluate(ppscan, &pps, &tokval, NULL, pass, NULL);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003623 if (!evalresult) {
3624 free_tlist(tline);
3625 free_tlist(origline);
3626 return DIRECTIVE_FOUND;
3627 } else if (!is_simple(evalresult)) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08003628 nasm_error(ERR_NONFATAL, "non-constant value given to `%s'", dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003629 free_tlist(tline);
3630 free_tlist(origline);
3631 return DIRECTIVE_FOUND;
3632 }
Cyrill Gorcunovab122872010-09-07 10:42:02 +04003633 count = evalresult->value;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003634 }
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003635
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003636 len = nasm_unquote(t->text, NULL);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003637
Cyrill Gorcunovcff031e2010-09-07 20:31:11 +04003638 /* make start and count being in range */
3639 if (start < 0)
3640 start = 0;
Cyrill Gorcunovab122872010-09-07 10:42:02 +04003641 if (count < 0)
3642 count = len + count + 1 - start;
3643 if (start + count > (int64_t)len)
Cyrill Gorcunovcff031e2010-09-07 20:31:11 +04003644 count = len - start;
3645 if (!len || count < 0 || start >=(int64_t)len)
Cyrill Gorcunovab122872010-09-07 10:42:02 +04003646 start = -1, count = 0; /* empty string */
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003647
H. Peter Anvin8b262472019-02-26 14:00:54 -08003648 macro_start = new_Token(NULL, TOK_STRING, NULL, 0);
Cyrill Gorcunovab122872010-09-07 10:42:02 +04003649 macro_start->text = nasm_quote((start < 0) ? "" : t->text + start, count);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003650
H. Peter Anvine2c80182005-01-15 22:15:51 +00003651 /*
3652 * We now have a macro name, an implicit parameter count of
3653 * zero, and a numeric token to use as an expansion. Create
3654 * and store an SMacro.
3655 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003656 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003657 free_tlist(tline);
3658 free_tlist(origline);
3659 return DIRECTIVE_FOUND;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003660 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003661
H. Peter Anvine2c80182005-01-15 22:15:51 +00003662 case PP_IASSIGN:
H. Peter Anvin8b262472019-02-26 14:00:54 -08003663 casesense = false;
3664 /* fall through */
3665 case PP_ASSIGN:
H. Peter Anvine2c80182005-01-15 22:15:51 +00003666 tline = tline->next;
3667 skip_white_(tline);
3668 tline = expand_id(tline);
3669 if (!tline || (tline->type != TOK_ID &&
3670 (tline->type != TOK_PREPROC_ID ||
3671 tline->text[1] != '$'))) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003672 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08003673 "`%s' expects a macro identifier", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003674 free_tlist(origline);
3675 return DIRECTIVE_FOUND;
3676 }
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04003677 ctx = get_ctx(tline->text, &mname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003678 last = tline;
3679 tline = expand_smacro(tline->next);
3680 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003681
H. Peter Anvin8b262472019-02-26 14:00:54 -08003682 pps.tptr = tline;
3683 pps.ntokens = -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003684 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin8b262472019-02-26 14:00:54 -08003685 evalresult = evaluate(ppscan, &pps, &tokval, NULL, pass, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003686 free_tlist(tline);
3687 if (!evalresult) {
3688 free_tlist(origline);
3689 return DIRECTIVE_FOUND;
3690 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003691
H. Peter Anvine2c80182005-01-15 22:15:51 +00003692 if (tokval.t_type)
H. Peter Anvin130736c2016-02-17 20:27:41 -08003693 nasm_error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003694 "trailing garbage after expression ignored");
H. Peter Anvin734b1882002-04-30 21:01:08 +00003695
H. Peter Anvine2c80182005-01-15 22:15:51 +00003696 if (!is_simple(evalresult)) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08003697 nasm_error(ERR_NONFATAL,
H. Peter Anvin8b262472019-02-26 14:00:54 -08003698 "non-constant value given to `%s'", dname);
3699 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003700 return DIRECTIVE_FOUND;
H. Peter Anvin8b262472019-02-26 14:00:54 -08003701 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003702
H. Peter Anvin8b262472019-02-26 14:00:54 -08003703 macro_start = make_tok_num(reloc_value(evalresult));
H. Peter Anvin734b1882002-04-30 21:01:08 +00003704
H. Peter Anvine2c80182005-01-15 22:15:51 +00003705 /*
3706 * We now have a macro name, an implicit parameter count of
3707 * zero, and a numeric token to use as an expansion. Create
3708 * and store an SMacro.
3709 */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003710 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003711 free_tlist(origline);
3712 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003713
H. Peter Anvine2c80182005-01-15 22:15:51 +00003714 case PP_LINE:
3715 /*
3716 * Syntax is `%line nnn[+mmm] [filename]'
3717 */
H. Peter Anvin (Intel)800c1682018-12-14 12:22:11 -08003718 if (unlikely(pp_noline)) {
3719 free_tlist(origline);
3720 return DIRECTIVE_FOUND;
3721 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003722 tline = tline->next;
3723 skip_white_(tline);
3724 if (!tok_type_(tline, TOK_NUMBER)) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08003725 nasm_error(ERR_NONFATAL, "`%s' expects line number", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003726 free_tlist(origline);
3727 return DIRECTIVE_FOUND;
3728 }
H. Peter Anvin70055962007-10-11 00:05:31 -07003729 k = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003730 m = 1;
3731 tline = tline->next;
3732 if (tok_is_(tline, "+")) {
3733 tline = tline->next;
3734 if (!tok_type_(tline, TOK_NUMBER)) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08003735 nasm_error(ERR_NONFATAL, "`%s' expects line increment", dname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003736 free_tlist(origline);
3737 return DIRECTIVE_FOUND;
3738 }
H. Peter Anvin70055962007-10-11 00:05:31 -07003739 m = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003740 tline = tline->next;
3741 }
3742 skip_white_(tline);
3743 src_set_linnum(k);
3744 istk->lineinc = m;
3745 if (tline) {
H. Peter Anvin274cda82016-05-10 02:56:29 -07003746 char *fname = detoken(tline, false);
3747 src_set_fname(fname);
3748 nasm_free(fname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003749 }
3750 free_tlist(origline);
3751 return DIRECTIVE_FOUND;
Keith Kaniosb307a4f2010-11-06 17:41:51 -05003752
H. Peter Anvine2c80182005-01-15 22:15:51 +00003753 default:
H. Peter Anvin130736c2016-02-17 20:27:41 -08003754 nasm_error(ERR_FATAL,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003755 "preprocessor directive `%s' not yet implemented",
H. Peter Anvin8b262472019-02-26 14:00:54 -08003756 dname);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003757 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003758 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003759}
3760
3761/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00003762 * Ensure that a macro parameter contains a condition code and
3763 * nothing else. Return the condition code index if so, or -1
3764 * otherwise.
3765 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003766static int find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003767{
H. Peter Anvin76690a12002-04-30 20:52:49 +00003768 Token *tt;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003769
H. Peter Anvin25a99342007-09-22 17:45:45 -07003770 if (!t)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003771 return -1; /* Probably a %+ without a space */
H. Peter Anvin25a99342007-09-22 17:45:45 -07003772
H. Peter Anvineba20a72002-04-30 20:53:55 +00003773 skip_white_(t);
Cyrill Gorcunov7524cfd2017-10-22 19:01:16 +03003774 if (!t)
3775 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003776 if (t->type != TOK_ID)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003777 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003778 tt = t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003779 skip_white_(tt);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003780 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003781 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003782
Cyrill Gorcunov19456392012-05-02 00:18:56 +04003783 return bsii(t->text, (const char **)conditions, ARRAY_SIZE(conditions));
H. Peter Anvin76690a12002-04-30 20:52:49 +00003784}
3785
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003786/*
3787 * This routines walks over tokens strem and hadnles tokens
3788 * pasting, if @handle_explicit passed then explicit pasting
3789 * term is handled, otherwise -- implicit pastings only.
3790 */
Cyrill Gorcunov575d4282010-10-06 00:25:55 +04003791static bool paste_tokens(Token **head, const struct tokseq_match *m,
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003792 size_t mnum, bool handle_explicit)
H. Peter Anvind784a082009-04-20 14:01:18 -07003793{
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003794 Token *tok, *next, **prev_next, **prev_nonspace;
3795 bool pasted = false;
3796 char *buf, *p;
3797 size_t len, i;
H. Peter Anvind784a082009-04-20 14:01:18 -07003798
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003799 /*
3800 * The last token before pasting. We need it
3801 * to be able to connect new handled tokens.
3802 * In other words if there were a tokens stream
3803 *
3804 * A -> B -> C -> D
3805 *
3806 * and we've joined tokens B and C, the resulting
3807 * stream should be
3808 *
3809 * A -> BC -> D
3810 */
3811 tok = *head;
3812 prev_next = NULL;
3813
3814 if (!tok_type_(tok, TOK_WHITESPACE) && !tok_type_(tok, TOK_PASTE))
3815 prev_nonspace = head;
3816 else
3817 prev_nonspace = NULL;
3818
3819 while (tok && (next = tok->next)) {
3820
3821 switch (tok->type) {
H. Peter Anvind784a082009-04-20 14:01:18 -07003822 case TOK_WHITESPACE:
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003823 /* Zap redundant whitespaces */
3824 while (tok_type_(next, TOK_WHITESPACE))
3825 next = delete_Token(next);
3826 tok->next = next;
H. Peter Anvind784a082009-04-20 14:01:18 -07003827 break;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003828
3829 case TOK_PASTE:
3830 /* Explicit pasting */
3831 if (!handle_explicit)
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003832 break;
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003833 next = delete_Token(tok);
3834
3835 while (tok_type_(next, TOK_WHITESPACE))
3836 next = delete_Token(next);
3837
3838 if (!pasted)
3839 pasted = true;
3840
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003841 /* Left pasting token is start of line */
3842 if (!prev_nonspace)
H. Peter Anvin130736c2016-02-17 20:27:41 -08003843 nasm_error(ERR_FATAL, "No lvalue found on pasting");
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003844
Cyrill Gorcunov8b5c9fb2013-02-04 01:24:54 +04003845 /*
3846 * No ending token, this might happen in two
3847 * cases
3848 *
3849 * 1) There indeed no right token at all
3850 * 2) There is a bare "%define ID" statement,
3851 * and @ID does expand to whitespace.
3852 *
3853 * So technically we need to do a grammar analysis
3854 * in another stage of parsing, but for now lets don't
3855 * change the behaviour people used to. Simply allow
3856 * whitespace after paste token.
3857 */
3858 if (!next) {
3859 /*
3860 * Zap ending space tokens and that's all.
3861 */
3862 tok = (*prev_nonspace)->next;
3863 while (tok_type_(tok, TOK_WHITESPACE))
3864 tok = delete_Token(tok);
3865 tok = *prev_nonspace;
3866 tok->next = NULL;
3867 break;
3868 }
3869
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003870 tok = *prev_nonspace;
3871 while (tok_type_(tok, TOK_WHITESPACE))
3872 tok = delete_Token(tok);
3873 len = strlen(tok->text);
3874 len += strlen(next->text);
3875
3876 p = buf = nasm_malloc(len + 1);
3877 strcpy(p, tok->text);
3878 p = strchr(p, '\0');
3879 strcpy(p, next->text);
3880
3881 delete_Token(tok);
3882
3883 tok = tokenize(buf);
3884 nasm_free(buf);
3885
3886 *prev_nonspace = tok;
3887 while (tok && tok->next)
3888 tok = tok->next;
3889
3890 tok->next = delete_Token(next);
3891
3892 /* Restart from pasted tokens head */
3893 tok = *prev_nonspace;
3894 break;
3895
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003896 default:
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003897 /* implicit pasting */
Cyrill Gorcunov575d4282010-10-06 00:25:55 +04003898 for (i = 0; i < mnum; i++) {
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003899 if (!(PP_CONCAT_MATCH(tok, m[i].mask_head)))
3900 continue;
Cyrill Gorcunov8dcbbd72010-09-25 02:33:20 +04003901
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003902 len = 0;
3903 while (next && PP_CONCAT_MATCH(next, m[i].mask_tail)) {
3904 len += strlen(next->text);
3905 next = next->next;
Cyrill Gorcunov8dcbbd72010-09-25 02:33:20 +04003906 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003907
Cyrill Gorcunov6f8109e2017-10-22 21:26:36 +03003908 /* No match or no text to process */
3909 if (tok == next || len == 0)
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003910 break;
3911
3912 len += strlen(tok->text);
3913 p = buf = nasm_malloc(len + 1);
3914
Adam Majer1a069432017-07-25 11:12:35 +02003915 strcpy(p, tok->text);
3916 p = strchr(p, '\0');
3917 tok = delete_Token(tok);
3918
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003919 while (tok != next) {
Adam Majer1a069432017-07-25 11:12:35 +02003920 if (PP_CONCAT_MATCH(tok, m[i].mask_tail)) {
3921 strcpy(p, tok->text);
3922 p = strchr(p, '\0');
3923 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003924 tok = delete_Token(tok);
3925 }
3926
3927 tok = tokenize(buf);
3928 nasm_free(buf);
3929
3930 if (prev_next)
3931 *prev_next = tok;
3932 else
3933 *head = tok;
3934
3935 /*
3936 * Connect pasted into original stream,
3937 * ie A -> new-tokens -> B
3938 */
3939 while (tok && tok->next)
3940 tok = tok->next;
3941 tok->next = next;
3942
3943 if (!pasted)
3944 pasted = true;
3945
3946 /* Restart from pasted tokens head */
3947 tok = prev_next ? *prev_next : *head;
Cyrill Gorcunov575d4282010-10-06 00:25:55 +04003948 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003949
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03003950 break;
H. Peter Anvind784a082009-04-20 14:01:18 -07003951 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003952
3953 prev_next = &tok->next;
3954
3955 if (tok->next &&
3956 !tok_type_(tok->next, TOK_WHITESPACE) &&
3957 !tok_type_(tok->next, TOK_PASTE))
3958 prev_nonspace = prev_next;
3959
3960 tok = tok->next;
H. Peter Anvind784a082009-04-20 14:01:18 -07003961 }
Cyrill Gorcunov1cf9b312012-08-04 10:51:58 +04003962
3963 return pasted;
H. Peter Anvind784a082009-04-20 14:01:18 -07003964}
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003965
3966/*
3967 * expands to a list of tokens from %{x:y}
3968 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003969static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003970{
3971 Token *t = tline, **tt, *tm, *head;
3972 char *pos;
3973 int fst, lst, j, i;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03003974
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003975 pos = strchr(tline->text, ':');
3976 nasm_assert(pos);
3977
3978 lst = atoi(pos + 1);
3979 fst = atoi(tline->text + 1);
3980
3981 /*
3982 * only macros params are accounted so
3983 * if someone passes %0 -- we reject such
3984 * value(s)
3985 */
3986 if (lst == 0 || fst == 0)
3987 goto err;
3988
3989 /* the values should be sane */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003990 if ((fst > (int)mac->nparam || fst < (-(int)mac->nparam)) ||
3991 (lst > (int)mac->nparam || lst < (-(int)mac->nparam)))
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003992 goto err;
3993
H. Peter Anvin36206cd2012-03-03 16:14:51 -08003994 fst = fst < 0 ? fst + (int)mac->nparam + 1: fst;
3995 lst = lst < 0 ? lst + (int)mac->nparam + 1: lst;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04003996
3997 /* counted from zero */
3998 fst--, lst--;
3999
4000 /*
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004001 * It will be at least one token. Note we
4002 * need to scan params until separator, otherwise
4003 * only first token will be passed.
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004004 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004005 tm = mac->params[(fst + mac->rotate) % mac->nparam];
Cyrill Gorcunov67f2ca22018-10-13 19:41:01 +03004006 if (!tm)
4007 goto err;
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004008 head = new_Token(NULL, tm->type, tm->text, 0);
4009 tt = &head->next, tm = tm->next;
4010 while (tok_isnt_(tm, ",")) {
4011 t = new_Token(NULL, tm->type, tm->text, 0);
4012 *tt = t, tt = &t->next, tm = tm->next;
4013 }
4014
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004015 if (fst < lst) {
4016 for (i = fst + 1; i <= lst; i++) {
4017 t = new_Token(NULL, TOK_OTHER, ",", 0);
4018 *tt = t, tt = &t->next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004019 j = (i + mac->rotate) % mac->nparam;
4020 tm = mac->params[j];
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004021 while (tok_isnt_(tm, ",")) {
4022 t = new_Token(NULL, tm->type, tm->text, 0);
4023 *tt = t, tt = &t->next, tm = tm->next;
4024 }
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004025 }
4026 } else {
4027 for (i = fst - 1; i >= lst; i--) {
4028 t = new_Token(NULL, TOK_OTHER, ",", 0);
4029 *tt = t, tt = &t->next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004030 j = (i + mac->rotate) % mac->nparam;
4031 tm = mac->params[j];
Cyrill Gorcunove75331c2013-11-09 12:02:15 +04004032 while (tok_isnt_(tm, ",")) {
4033 t = new_Token(NULL, tm->type, tm->text, 0);
4034 *tt = t, tt = &t->next, tm = tm->next;
4035 }
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004036 }
4037 }
4038
4039 *last = tt;
4040 return head;
4041
4042err:
H. Peter Anvin130736c2016-02-17 20:27:41 -08004043 nasm_error(ERR_NONFATAL, "`%%{%s}': macro parameters out of range",
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004044 &tline->text[1]);
4045 return tline;
4046}
4047
H. Peter Anvin76690a12002-04-30 20:52:49 +00004048/*
4049 * Expand MMacro-local things: parameter references (%0, %n, %+n,
H. Peter Anvin67c63722008-10-26 23:49:00 -07004050 * %-n) and MMacro-local identifiers (%%foo) as well as
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004051 * macro indirection (%[...]) and range (%{..:..}).
H. Peter Anvin76690a12002-04-30 20:52:49 +00004052 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004053static Token *expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004054{
H. Peter Anvin734b1882002-04-30 21:01:08 +00004055 Token *t, *tt, **tail, *thead;
H. Peter Anvin6125b622009-04-08 14:02:25 -07004056 bool changed = false;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004057 char *pos;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004058
4059 tail = &thead;
4060 thead = NULL;
4061
H. Peter Anvine2c80182005-01-15 22:15:51 +00004062 while (tline) {
Cyrill Gorcunov661f7232018-10-28 20:39:34 +03004063 if (tline->type == TOK_PREPROC_ID && tline->text && tline->text[0] &&
Cyrill Gorcunovca611192010-06-04 09:22:12 +04004064 (((tline->text[1] == '+' || tline->text[1] == '-') && tline->text[2]) ||
4065 (tline->text[1] >= '0' && tline->text[1] <= '9') ||
4066 tline->text[1] == '%')) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004067 char *text = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004068 int type = 0, cc; /* type = 0 to placate optimisers */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004069 char tmpbuf[30];
H. Peter Anvin25a99342007-09-22 17:45:45 -07004070 unsigned int n;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004071 int i;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004072 MMacro *mac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004073
H. Peter Anvine2c80182005-01-15 22:15:51 +00004074 t = tline;
4075 tline = tline->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004076
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004077 mac = istk->mstk;
4078 while (mac && !mac->name) /* avoid mistaking %reps for macros */
4079 mac = mac->next_active;
4080 if (!mac) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08004081 nasm_error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004082 } else {
4083 pos = strchr(t->text, ':');
4084 if (!pos) {
4085 switch (t->text[1]) {
4086 /*
4087 * We have to make a substitution of one of the
4088 * forms %1, %-1, %+1, %%foo, %0.
4089 */
4090 case '0':
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004091 type = TOK_NUMBER;
4092 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
4093 text = nasm_strdup(tmpbuf);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004094 break;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004095 case '%':
H. Peter Anvine2c80182005-01-15 22:15:51 +00004096 type = TOK_ID;
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004097 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004098 mac->unique);
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004099 text = nasm_strcat(tmpbuf, t->text + 2);
4100 break;
4101 case '-':
4102 n = atoi(t->text + 2) - 1;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004103 if (n >= mac->nparam)
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004104 tt = NULL;
4105 else {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004106 if (mac->nparam > 1)
4107 n = (n + mac->rotate) % mac->nparam;
4108 tt = mac->params[n];
H. Peter Anvine2c80182005-01-15 22:15:51 +00004109 }
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004110 cc = find_cc(tt);
4111 if (cc == -1) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08004112 nasm_error(ERR_NONFATAL,
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004113 "macro parameter %d is not a condition code",
4114 n + 1);
4115 text = NULL;
4116 } else {
4117 type = TOK_ID;
4118 if (inverse_ccs[cc] == -1) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08004119 nasm_error(ERR_NONFATAL,
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004120 "condition code `%s' is not invertible",
4121 conditions[cc]);
4122 text = NULL;
4123 } else
4124 text = nasm_strdup(conditions[inverse_ccs[cc]]);
4125 }
4126 break;
4127 case '+':
4128 n = atoi(t->text + 2) - 1;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004129 if (n >= mac->nparam)
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004130 tt = NULL;
4131 else {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004132 if (mac->nparam > 1)
4133 n = (n + mac->rotate) % mac->nparam;
4134 tt = mac->params[n];
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004135 }
4136 cc = find_cc(tt);
4137 if (cc == -1) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08004138 nasm_error(ERR_NONFATAL,
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004139 "macro parameter %d is not a condition code",
4140 n + 1);
4141 text = NULL;
4142 } else {
4143 type = TOK_ID;
4144 text = nasm_strdup(conditions[cc]);
4145 }
4146 break;
4147 default:
4148 n = atoi(t->text + 1) - 1;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004149 if (n >= mac->nparam)
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004150 tt = NULL;
4151 else {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004152 if (mac->nparam > 1)
4153 n = (n + mac->rotate) % mac->nparam;
4154 tt = mac->params[n];
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004155 }
4156 if (tt) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004157 for (i = 0; i < mac->paramlen[n]; i++) {
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004158 *tail = new_Token(NULL, tt->type, tt->text, 0);
4159 tail = &(*tail)->next;
4160 tt = tt->next;
4161 }
4162 }
4163 text = NULL; /* we've done it here */
4164 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004165 }
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004166 } else {
4167 /*
4168 * seems we have a parameters range here
4169 */
4170 Token *head, **last;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004171 head = expand_mmac_params_range(mac, t, &last);
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004172 if (head != t) {
4173 *tail = head;
4174 *last = tline;
4175 tline = head;
4176 text = NULL;
4177 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004178 }
Cyrill Gorcunovc29404d2010-06-05 01:50:23 +04004179 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004180 if (!text) {
4181 delete_Token(t);
4182 } else {
4183 *tail = t;
4184 tail = &t->next;
4185 t->type = type;
4186 nasm_free(t->text);
4187 t->text = text;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004188 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004189 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004190 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004191 continue;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004192 } else if (tline->type == TOK_INDIRECT) {
4193 t = tline;
4194 tline = tline->next;
4195 tt = tokenize(t->text);
4196 tt = expand_mmac_params(tt);
4197 tt = expand_smacro(tt);
4198 *tail = tt;
4199 while (tt) {
4200 tt->a.mac = NULL; /* Necessary? */
4201 tail = &tt->next;
4202 tt = tt->next;
4203 }
4204 delete_Token(t);
4205 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004206 } else {
4207 t = *tail = tline;
4208 tline = tline->next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004209 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004210 tail = &t->next;
4211 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004212 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00004213 *tail = NULL;
H. Peter Anvin67c63722008-10-26 23:49:00 -07004214
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04004215 if (changed) {
4216 const struct tokseq_match t[] = {
4217 {
4218 PP_CONCAT_MASK(TOK_ID) |
4219 PP_CONCAT_MASK(TOK_FLOAT), /* head */
4220 PP_CONCAT_MASK(TOK_ID) |
4221 PP_CONCAT_MASK(TOK_NUMBER) |
4222 PP_CONCAT_MASK(TOK_FLOAT) |
4223 PP_CONCAT_MASK(TOK_OTHER) /* tail */
4224 },
4225 {
4226 PP_CONCAT_MASK(TOK_NUMBER), /* head */
4227 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
4228 }
4229 };
4230 paste_tokens(&thead, t, ARRAY_SIZE(t), false);
4231 }
H. Peter Anvin6125b622009-04-08 14:02:25 -07004232
H. Peter Anvin76690a12002-04-30 20:52:49 +00004233 return thead;
4234}
4235
4236/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004237 * Expand all single-line macro calls made in the given line.
4238 * Return the expanded version of the line. The original is deemed
4239 * to be destroyed in the process. (In reality we'll just move
4240 * Tokens from input to output a lot of the time, rather than
4241 * actually bothering to destroy and replicate.)
4242 */
H. Peter Anvincb1cf592007-11-19 12:26:50 -08004243
H. Peter Anvine2c80182005-01-15 22:15:51 +00004244static Token *expand_smacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004245{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004246 Token *t, *tt, *mstart, **tail, *thead;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004247 SMacro *head = NULL, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004248 Token **params;
4249 int *paramsize;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004250 Token *eparams;
4251 unsigned int nparam, sparam, i;
H. Peter Anvind784a082009-04-20 14:01:18 -07004252 int brackets;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004253 Token *org_tline = tline;
4254 Context *ctx;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08004255 const char *mname;
H. Peter Anvin79561022018-06-15 17:51:39 -07004256 int64_t deadman = nasm_limit[LIMIT_MACROS];
H. Peter Anvin8287daf2009-07-07 16:00:58 -07004257 bool expanded;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004258
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004259 /*
4260 * Trick: we should avoid changing the start token pointer since it can
4261 * be contained in "next" field of other token. Because of this
4262 * we allocate a copy of first token and work with it; at the end of
4263 * routine we copy it back
4264 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004265 if (org_tline) {
Cyrill Gorcunoved4a8052010-04-09 15:40:35 +04004266 tline = new_Token(org_tline->next, org_tline->type,
4267 org_tline->text, 0);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004268 tline->a.mac = org_tline->a.mac;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004269 nasm_free(org_tline->text);
4270 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004271 }
4272
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004273 expanded = true; /* Always expand %+ at least once */
H. Peter Anvin8287daf2009-07-07 16:00:58 -07004274
H. Peter Anvincb1cf592007-11-19 12:26:50 -08004275again:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004276 thead = NULL;
Cyrill Gorcunoved4a8052010-04-09 15:40:35 +04004277 tail = &thead;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004278
H. Peter Anvine2c80182005-01-15 22:15:51 +00004279 while (tline) { /* main token loop */
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004280 if (!--deadman) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08004281 nasm_error(ERR_NONFATAL, "interminable macro recursion");
Cyrill Gorcunovbd38c8f2009-11-21 11:11:23 +03004282 goto err;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004283 }
H. Peter Anvincb1cf592007-11-19 12:26:50 -08004284
H. Peter Anvine2c80182005-01-15 22:15:51 +00004285 if ((mname = tline->text)) {
4286 /* if this token is a local macro, look in local context */
Cyrill Gorcunovc56d9ad2010-02-11 15:12:19 +03004287 if (tline->type == TOK_ID) {
4288 head = (SMacro *)hash_findix(&smacros, mname);
4289 } else if (tline->type == TOK_PREPROC_ID) {
Cyrill Gorcunov1a42fb22012-03-11 11:38:47 +04004290 ctx = get_ctx(mname, &mname);
Cyrill Gorcunovc56d9ad2010-02-11 15:12:19 +03004291 head = ctx ? (SMacro *)hash_findix(&ctx->localmac, mname) : NULL;
4292 } else
4293 head = NULL;
H. Peter Anvin072771e2008-05-22 13:17:51 -07004294
H. Peter Anvine2c80182005-01-15 22:15:51 +00004295 /*
4296 * We've hit an identifier. As in is_mmacro below, we first
4297 * check whether the identifier is a single-line macro at
4298 * all, then think about checking for parameters if
4299 * necessary.
4300 */
H. Peter Anvin8b262472019-02-26 14:00:54 -08004301 list_for_each(m, head) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004302 if (!mstrcmp(m->name, mname, m->casesense))
4303 break;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004304 }
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004305 if (m) {
4306 mstart = tline;
4307 params = NULL;
4308 paramsize = NULL;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004309 eparams = NULL;
4310
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004311 if (m->nparam == 0) {
4312 /*
H. Peter Anvin8b262472019-02-26 14:00:54 -08004313 * Simple case: the macro is parameterless.
4314 * Nothing to parse; just drop the macro token itself.
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004315 */
H. Peter Anvin8b262472019-02-26 14:00:54 -08004316 tline = tline->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004317 } else {
4318 /*
4319 * Complicated case: at least one macro with this name
H. Peter Anvine2c80182005-01-15 22:15:51 +00004320 * exists and takes parameters. We must find the
4321 * parameters in the call, count them, find the SMacro
4322 * that corresponds to that form of the macro call, and
4323 * substitute for the parameters when we expand. What a
4324 * pain.
4325 */
4326 /*tline = tline->next;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004327 skip_white_(tline); */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004328 do {
4329 t = tline->next;
4330 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004331 t->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004332 t->text = NULL;
4333 t = tline->next = delete_Token(t);
4334 }
4335 tline = t;
4336 } while (tok_type_(tline, TOK_WHITESPACE));
4337 if (!tok_is_(tline, "(")) {
4338 /*
4339 * This macro wasn't called with parameters: ignore
4340 * the call. (Behaviour borrowed from gnu cpp.)
4341 */
4342 tline = mstart;
4343 m = NULL;
4344 } else {
4345 int paren = 0;
4346 int white = 0;
4347 brackets = 0;
4348 nparam = 0;
4349 sparam = PARAM_DELTA;
4350 params = nasm_malloc(sparam * sizeof(Token *));
4351 params[0] = tline->next;
4352 paramsize = nasm_malloc(sparam * sizeof(int));
4353 paramsize[0] = 0;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004354 while (true) { /* parameter loop */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004355 /*
4356 * For some unusual expansions
4357 * which concatenates function call
4358 */
4359 t = tline->next;
4360 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004361 t->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004362 t->text = NULL;
4363 t = tline->next = delete_Token(t);
4364 }
4365 tline = t;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00004366
H. Peter Anvine2c80182005-01-15 22:15:51 +00004367 if (!tline) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08004368 nasm_error(ERR_NONFATAL,
H. Peter Anvine2c80182005-01-15 22:15:51 +00004369 "macro call expects terminating `)'");
4370 break;
4371 }
4372 if (tline->type == TOK_WHITESPACE
4373 && brackets <= 0) {
4374 if (paramsize[nparam])
4375 white++;
4376 else
4377 params[nparam] = tline->next;
4378 continue; /* parameter loop */
4379 }
4380 if (tline->type == TOK_OTHER
4381 && tline->text[1] == 0) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004382 char ch = tline->text[0];
H. Peter Anvine2c80182005-01-15 22:15:51 +00004383 if (ch == ',' && !paren && brackets <= 0) {
4384 if (++nparam >= sparam) {
4385 sparam += PARAM_DELTA;
4386 params = nasm_realloc(params,
Cyrill Gorcunoved4a8052010-04-09 15:40:35 +04004387 sparam * sizeof(Token *));
4388 paramsize = nasm_realloc(paramsize,
4389 sparam * sizeof(int));
H. Peter Anvine2c80182005-01-15 22:15:51 +00004390 }
4391 params[nparam] = tline->next;
4392 paramsize[nparam] = 0;
4393 white = 0;
4394 continue; /* parameter loop */
4395 }
4396 if (ch == '{' &&
4397 (brackets > 0 || (brackets == 0 &&
4398 !paramsize[nparam])))
4399 {
4400 if (!(brackets++)) {
4401 params[nparam] = tline->next;
4402 continue; /* parameter loop */
4403 }
4404 }
4405 if (ch == '}' && brackets > 0)
4406 if (--brackets == 0) {
4407 brackets = -1;
4408 continue; /* parameter loop */
4409 }
4410 if (ch == '(' && !brackets)
4411 paren++;
4412 if (ch == ')' && brackets <= 0)
4413 if (--paren < 0)
4414 break;
4415 }
4416 if (brackets < 0) {
4417 brackets = 0;
H. Peter Anvin130736c2016-02-17 20:27:41 -08004418 nasm_error(ERR_NONFATAL, "braces do not "
H. Peter Anvine2c80182005-01-15 22:15:51 +00004419 "enclose all of macro parameter");
4420 }
4421 paramsize[nparam] += white + 1;
4422 white = 0;
4423 } /* parameter loop */
4424 nparam++;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004425
H. Peter Anvine2c80182005-01-15 22:15:51 +00004426 while (m && (m->nparam != nparam ||
H. Peter Anvin8b262472019-02-26 14:00:54 -08004427 mstrcmp(m->name, mname, m->casesense)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004428 m = m->next;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004429 if (!m) {
H. Peter Anvin (Intel)77f53ba2018-12-12 14:38:50 -08004430 nasm_error(ERR_WARNING|ERR_PASS1|WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00004431 "macro `%s' exists, "
4432 "but not taking %d parameters",
4433 mstart->text, nparam);
H. Peter Anvin8b262472019-02-26 14:00:54 -08004434 } else if (m->eval_param) {
4435 struct ppscan pps;
4436 struct tokenval tokval;
4437 expr *evalresult;
4438
4439 /* Evaluate parameters if applicable */
4440 for (i = 0; i < nparam; i++) {
4441 if (!m->eval_param[i])
4442 continue;
4443
4444 pps.tptr = params[i];
4445 pps.ntokens = paramsize[i];
4446 tokval.t_type = TOKEN_INVALID;
4447 evalresult = evaluate(ppscan, &pps, &tokval,
4448 NULL, pass, NULL);
4449 if (!evalresult)
4450 continue;
4451
4452 if (tokval.t_type) {
4453 nasm_error(ERR_NONFATAL,
4454 "invalid expression in parameter %d of macro `%s'", i, m->name);
4455 continue;
4456 }
4457
4458 if (!is_simple(evalresult)) {
4459 nasm_error(ERR_NONFATAL,
4460 "non-constant expression in parameter %d of macro `%s'", i, m->name);
4461 continue;
4462 }
4463 params[i] = make_tok_num(reloc_value(evalresult));
4464 params[i]->next = eparams;
4465 eparams = params[i];
4466 paramsize[i] = 1;
4467 }
4468 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004469 }
4470 }
4471 if (m && m->in_progress)
4472 m = NULL;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004473 if (!m) {
4474 /* in progress or didn't find '(' or wrong nparam */
H. Peter Anvin70653092007-10-19 14:42:29 -07004475 /*
H. Peter Anvine2c80182005-01-15 22:15:51 +00004476 * Design question: should we handle !tline, which
4477 * indicates missing ')' here, or expand those
4478 * macros anyway, which requires the (t) test a few
H. Peter Anvin70653092007-10-19 14:42:29 -07004479 * lines down?
H. Peter Anvine2c80182005-01-15 22:15:51 +00004480 */
H. Peter Anvin8b262472019-02-26 14:00:54 -08004481 free_tlist(eparams);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004482 nasm_free(params);
4483 nasm_free(paramsize);
4484 tline = mstart;
4485 } else {
4486 /*
4487 * Expand the macro: we are placed on the last token of the
4488 * call, so that we can easily split the call from the
4489 * following tokens. We also start by pushing an SMAC_END
4490 * token for the cycle removal.
4491 */
H. Peter Anvin8b262472019-02-26 14:00:54 -08004492 Token *expansion;
4493
H. Peter Anvine2c80182005-01-15 22:15:51 +00004494 t = tline;
4495 if (t) {
4496 tline = t->next;
4497 t->next = NULL;
4498 }
4499 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004500 tt->a.mac = m;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004501 m->in_progress = true;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004502 if (unlikely(m->magic))
4503 expansion = m->e.magic(m, params, paramsize);
4504 else
4505 expansion = m->e.expansion;
4506
H. Peter Anvine2c80182005-01-15 22:15:51 +00004507 tline = tt;
H. Peter Anvin8b262472019-02-26 14:00:54 -08004508 list_for_each(t, expansion) {
4509 if (is_smac_param(t->type)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004510 Token *pcopy = tline, **ptail = &pcopy;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004511 Token *ttt, *pt;
4512 int i;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004513
H. Peter Anvin8b262472019-02-26 14:00:54 -08004514 ttt = params[smac_nparam(t->type)];
4515 i = paramsize[smac_nparam(t->type)];
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004516 while (--i >= 0) {
H. Peter Anvin8b262472019-02-26 14:00:54 -08004517 nasm_assert(ttt);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004518 pt = *ptail = new_Token(tline, ttt->type,
4519 ttt->text, 0);
4520 ptail = &pt->next;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004521 ttt = ttt->next;
4522 }
4523 tline = pcopy;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004524 } else if (t->type == TOK_PREPROC_Q) {
4525 tt = new_Token(tline, TOK_ID, mname, 0);
4526 tline = tt;
4527 } else if (t->type == TOK_PREPROC_QQ) {
4528 tt = new_Token(tline, TOK_ID, m->name, 0);
4529 tline = tt;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004530 } else {
4531 tt = new_Token(tline, t->type, t->text, 0);
4532 tline = tt;
4533 }
4534 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004535
H. Peter Anvine2c80182005-01-15 22:15:51 +00004536 /*
4537 * Having done that, get rid of the macro call, and clean
4538 * up the parameters.
4539 */
4540 nasm_free(params);
4541 nasm_free(paramsize);
4542 free_tlist(mstart);
H. Peter Anvin8b262472019-02-26 14:00:54 -08004543 free_tlist(eparams);
4544 if (m->magic)
4545 free_tlist(expansion);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004546 expanded = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004547 continue; /* main token loop */
4548 }
4549 }
4550 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004551
H. Peter Anvine2c80182005-01-15 22:15:51 +00004552 if (tline->type == TOK_SMAC_END) {
Cyrill Gorcunov980dd652018-10-14 19:25:32 +03004553 /* On error path it might already be dropped */
4554 if (tline->a.mac)
4555 tline->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004556 tline = delete_Token(tline);
4557 } else {
4558 t = *tail = tline;
4559 tline = tline->next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07004560 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004561 t->next = NULL;
4562 tail = &t->next;
4563 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004564 }
4565
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004566 /*
4567 * Now scan the entire line and look for successive TOK_IDs that resulted
Keith Kaniosb7a89542007-04-12 02:40:54 +00004568 * after expansion (they can't be produced by tokenize()). The successive
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004569 * TOK_IDs should be concatenated.
4570 * Also we look for %+ tokens and concatenate the tokens before and after
4571 * them (without white spaces in between).
4572 */
Cyrill Gorcunov8dcbbd72010-09-25 02:33:20 +04004573 if (expanded) {
Cyrill Gorcunovc6a742c2011-06-27 01:23:09 +04004574 const struct tokseq_match t[] = {
4575 {
4576 PP_CONCAT_MASK(TOK_ID) |
4577 PP_CONCAT_MASK(TOK_PREPROC_ID), /* head */
4578 PP_CONCAT_MASK(TOK_ID) |
4579 PP_CONCAT_MASK(TOK_PREPROC_ID) |
4580 PP_CONCAT_MASK(TOK_NUMBER) /* tail */
4581 }
4582 };
4583 if (paste_tokens(&thead, t, ARRAY_SIZE(t), true)) {
Cyrill Gorcunov8dcbbd72010-09-25 02:33:20 +04004584 /*
4585 * If we concatenated something, *and* we had previously expanded
4586 * an actual macro, scan the lines again for macros...
4587 */
4588 tline = thead;
4589 expanded = false;
4590 goto again;
4591 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00004592 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004593
Cyrill Gorcunovbd38c8f2009-11-21 11:11:23 +03004594err:
H. Peter Anvine2c80182005-01-15 22:15:51 +00004595 if (org_tline) {
4596 if (thead) {
4597 *org_tline = *thead;
4598 /* since we just gave text to org_line, don't free it */
4599 thead->text = NULL;
4600 delete_Token(thead);
4601 } else {
4602 /* the expression expanded to empty line;
4603 we can't return NULL for some reasons
4604 we just set the line to a single WHITESPACE token. */
4605 memset(org_tline, 0, sizeof(*org_tline));
4606 org_tline->text = NULL;
4607 org_tline->type = TOK_WHITESPACE;
4608 }
4609 thead = org_tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004610 }
4611
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004612 return thead;
4613}
4614
4615/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004616 * Similar to expand_smacro but used exclusively with macro identifiers
4617 * right before they are fetched in. The reason is that there can be
4618 * identifiers consisting of several subparts. We consider that if there
4619 * are more than one element forming the name, user wants a expansion,
4620 * otherwise it will be left as-is. Example:
4621 *
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004622 * %define %$abc cde
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004623 *
4624 * the identifier %$abc will be left as-is so that the handler for %define
4625 * will suck it and define the corresponding value. Other case:
4626 *
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004627 * %define _%$abc cde
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004628 *
4629 * In this case user wants name to be expanded *before* %define starts
4630 * working, so we'll expand %$abc into something (if it has a value;
4631 * otherwise it will be left as-is) then concatenate all successive
4632 * PP_IDs into one.
4633 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004634static Token *expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004635{
4636 Token *cur, *oldnext = NULL;
4637
H. Peter Anvin734b1882002-04-30 21:01:08 +00004638 if (!tline || !tline->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004639 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004640
4641 cur = tline;
4642 while (cur->next &&
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004643 (cur->next->type == TOK_ID ||
4644 cur->next->type == TOK_PREPROC_ID
4645 || cur->next->type == TOK_NUMBER))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004646 cur = cur->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004647
4648 /* If identifier consists of just one token, don't expand */
4649 if (cur == tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004650 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004651
H. Peter Anvine2c80182005-01-15 22:15:51 +00004652 if (cur) {
4653 oldnext = cur->next; /* Detach the tail past identifier */
4654 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004655 }
4656
H. Peter Anvin734b1882002-04-30 21:01:08 +00004657 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004658
H. Peter Anvine2c80182005-01-15 22:15:51 +00004659 if (cur) {
4660 /* expand_smacro possibly changhed tline; re-scan for EOL */
4661 cur = tline;
4662 while (cur && cur->next)
4663 cur = cur->next;
4664 if (cur)
4665 cur->next = oldnext;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004666 }
4667
4668 return tline;
4669}
4670
4671/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004672 * Determine whether the given line constitutes a multi-line macro
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004673 * call, and return the MMacro structure called if so. Doesn't have
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004674 * to check for an initial label - that's taken care of in
4675 * expand_mmacro - but must check numbers of parameters. Guaranteed
4676 * to be called with tline->type == TOK_ID, so the putative macro
4677 * name is easy to find.
4678 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004679static MMacro *is_mmacro(Token * tline, Token *** params_array)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004680{
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004681 MMacro *head, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004682 Token **params;
4683 int nparam;
4684
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004685 head = (MMacro *) hash_findix(&mmacros, tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004686
4687 /*
4688 * Efficiency: first we see if any macro exists with the given
4689 * name. If not, we can return NULL immediately. _Then_ we
4690 * count the parameters, and then we look further along the
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004691 * list if necessary to find the proper MMacro.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004692 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004693 list_for_each(m, head)
4694 if (!mstrcmp(m->name, tline->text, m->casesense))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004695 break;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004696 if (!m)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004697 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004698
4699 /*
4700 * OK, we have a potential macro. Count and demarcate the
4701 * parameters.
4702 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00004703 count_mmac_params(tline->next, &nparam, &params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004704
4705 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004706 * So we know how many parameters we've got. Find the MMacro
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004707 * structure that handles this number.
4708 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004709 while (m) {
4710 if (m->nparam_min <= nparam
4711 && (m->plus || nparam <= m->nparam_max)) {
4712 /*
4713 * This one is right. Just check if cycle removal
4714 * prohibits us using it before we actually celebrate...
4715 */
4716 if (m->in_progress > m->max_depth) {
4717 if (m->max_depth > 0) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08004718 nasm_error(ERR_WARNING,
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004719 "reached maximum recursion depth of %i",
4720 m->max_depth);
4721 }
4722 nasm_free(params);
4723 return NULL;
4724 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004725 /*
4726 * It's right, and we can use it. Add its default
4727 * parameters to the end of our list if necessary.
4728 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004729 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004730 params =
4731 nasm_realloc(params,
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004732 ((m->nparam_min + m->ndefs +
H. Peter Anvine2c80182005-01-15 22:15:51 +00004733 1) * sizeof(*params)));
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004734 while (nparam < m->nparam_min + m->ndefs) {
4735 params[nparam] = m->defaults[nparam - m->nparam_min];
H. Peter Anvine2c80182005-01-15 22:15:51 +00004736 nparam++;
4737 }
4738 }
4739 /*
4740 * If we've gone over the maximum parameter count (and
4741 * we're in Plus mode), ignore parameters beyond
4742 * nparam_max.
4743 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004744 if (m->plus && nparam > m->nparam_max)
4745 nparam = m->nparam_max;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004746 /*
4747 * Then terminate the parameter list, and leave.
4748 */
4749 if (!params) { /* need this special case */
4750 params = nasm_malloc(sizeof(*params));
4751 nparam = 0;
4752 }
4753 params[nparam] = NULL;
4754 *params_array = params;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004755 return m;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004756 }
4757 /*
4758 * This one wasn't right: look for the next one with the
4759 * same name.
4760 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004761 list_for_each(m, m->next)
4762 if (!mstrcmp(m->name, tline->text, m->casesense))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004763 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004764 }
4765
4766 /*
4767 * After all that, we didn't find one with the right number of
4768 * parameters. Issue a warning, and fail to expand the macro.
4769 */
H. Peter Anvin (Intel)77f53ba2018-12-12 14:38:50 -08004770 nasm_error(ERR_WARNING|ERR_PASS1|WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00004771 "macro `%s' exists, but not taking %d parameters",
4772 tline->text, nparam);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004773 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004774 return NULL;
4775}
4776
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004777
4778/*
4779 * Save MMacro invocation specific fields in
4780 * preparation for a recursive macro expansion
4781 */
4782static void push_mmacro(MMacro *m)
4783{
4784 MMacroInvocation *i;
4785
4786 i = nasm_malloc(sizeof(MMacroInvocation));
4787 i->prev = m->prev;
4788 i->params = m->params;
4789 i->iline = m->iline;
4790 i->nparam = m->nparam;
4791 i->rotate = m->rotate;
4792 i->paramlen = m->paramlen;
4793 i->unique = m->unique;
4794 i->condcnt = m->condcnt;
4795 m->prev = i;
4796}
4797
4798
4799/*
4800 * Restore MMacro invocation specific fields that were
4801 * saved during a previous recursive macro expansion
4802 */
4803static void pop_mmacro(MMacro *m)
4804{
4805 MMacroInvocation *i;
4806
4807 if (m->prev) {
4808 i = m->prev;
4809 m->prev = i->prev;
4810 m->params = i->params;
4811 m->iline = i->iline;
4812 m->nparam = i->nparam;
4813 m->rotate = i->rotate;
4814 m->paramlen = i->paramlen;
4815 m->unique = i->unique;
4816 m->condcnt = i->condcnt;
4817 nasm_free(i);
4818 }
4819}
4820
4821
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004822/*
4823 * Expand the multi-line macro call made by the given line, if
4824 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004825 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004826 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004827static int expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004828{
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004829 Token *startline = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004830 Token *label = NULL;
4831 int dont_prepend = 0;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004832 Token **params, *t, *tt;
4833 MMacro *m;
4834 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004835 int i, nparam, *paramlen;
H. Peter Anvinc751e862008-06-09 10:18:45 -07004836 const char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004837
4838 t = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004839 skip_white_(t);
H. Peter Anvince2233b2008-05-25 21:57:00 -07004840 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00004841 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004842 return 0;
4843 m = is_mmacro(t, &params);
4844 if (m) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03004845 mname = t->text;
H. Peter Anvinc751e862008-06-09 10:18:45 -07004846 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004847 Token *last;
4848 /*
4849 * We have an id which isn't a macro call. We'll assume
4850 * it might be a label; we'll also check to see if a
4851 * colon follows it. Then, if there's another id after
4852 * that lot, we'll check it again for macro-hood.
4853 */
4854 label = last = t;
4855 t = t->next;
4856 if (tok_type_(t, TOK_WHITESPACE))
4857 last = t, t = t->next;
4858 if (tok_is_(t, ":")) {
4859 dont_prepend = 1;
4860 last = t, t = t->next;
4861 if (tok_type_(t, TOK_WHITESPACE))
4862 last = t, t = t->next;
4863 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004864 if (!tok_type_(t, TOK_ID) || !(m = is_mmacro(t, &params)))
4865 return 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004866 last->next = NULL;
Keith Kanios891775e2009-07-11 06:08:54 -05004867 mname = t->text;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004868 tline = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004869 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004870
4871 /*
4872 * Fix up the parameters: this involves stripping leading and
4873 * trailing whitespace, then stripping braces if they are
4874 * present.
4875 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004876 for (nparam = 0; params[nparam]; nparam++) ;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004877 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004878
H. Peter Anvine2c80182005-01-15 22:15:51 +00004879 for (i = 0; params[i]; i++) {
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08004880 int brace = 0;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004881 int comma = (!m->plus || i < nparam - 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004882
H. Peter Anvine2c80182005-01-15 22:15:51 +00004883 t = params[i];
4884 skip_white_(t);
4885 if (tok_is_(t, "{"))
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08004886 t = t->next, brace++, comma = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004887 params[i] = t;
4888 paramlen[i] = 0;
4889 while (t) {
4890 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
4891 break; /* ... because we have hit a comma */
4892 if (comma && t->type == TOK_WHITESPACE
4893 && tok_is_(t->next, ","))
4894 break; /* ... or a space then a comma */
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08004895 if (brace && t->type == TOK_OTHER) {
4896 if (t->text[0] == '{')
4897 brace++; /* ... or a nested opening brace */
4898 else if (t->text[0] == '}')
4899 if (!--brace)
4900 break; /* ... or a brace */
4901 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004902 t = t->next;
4903 paramlen[i]++;
4904 }
Jin Kyu Song5eac14b2013-11-27 20:52:16 -08004905 if (brace)
H. Peter Anvin130736c2016-02-17 20:27:41 -08004906 nasm_error(ERR_NONFATAL, "macro params should be enclosed in braces");
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004907 }
4908
4909 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004910 * OK, we have a MMacro structure together with a set of
4911 * parameters. We must now go through the expansion and push
4912 * copies of each Line on to istk->expansion. Substitution of
H. Peter Anvin76690a12002-04-30 20:52:49 +00004913 * parameter tokens and macro-local tokens doesn't get done
4914 * until the single-line macro substitution process; this is
4915 * because delaying them allows us to change the semantics
4916 * later through %rotate.
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004917 *
4918 * First, push an end marker on to istk->expansion, mark this
4919 * macro as in progress, and set up its invocation-specific
4920 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004921 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004922 ll = nasm_malloc(sizeof(Line));
4923 ll->next = istk->expansion;
4924 ll->finishes = m;
4925 ll->first = NULL;
4926 istk->expansion = ll;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004927
4928 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004929 * Save the previous MMacro expansion in the case of
4930 * macro recursion
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004931 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004932 if (m->max_depth && m->in_progress)
4933 push_mmacro(m);
4934
4935 m->in_progress ++;
4936 m->params = params;
4937 m->iline = tline;
4938 m->nparam = nparam;
4939 m->rotate = 0;
4940 m->paramlen = paramlen;
4941 m->unique = unique++;
4942 m->lineno = 0;
4943 m->condcnt = 0;
4944
4945 m->next_active = istk->mstk;
4946 istk->mstk = m;
4947
4948 list_for_each(l, m->expansion) {
4949 Token **tail;
4950
4951 ll = nasm_malloc(sizeof(Line));
4952 ll->finishes = NULL;
4953 ll->next = istk->expansion;
4954 istk->expansion = ll;
4955 tail = &ll->first;
4956
4957 list_for_each(t, l->first) {
4958 Token *x = t;
4959 switch (t->type) {
4960 case TOK_PREPROC_Q:
4961 tt = *tail = new_Token(NULL, TOK_ID, mname, 0);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004962 break;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004963 case TOK_PREPROC_QQ:
4964 tt = *tail = new_Token(NULL, TOK_ID, m->name, 0);
4965 break;
4966 case TOK_PREPROC_ID:
4967 if (t->text[1] == '0' && t->text[2] == '0') {
4968 dont_prepend = -1;
4969 x = label;
4970 if (!x)
4971 continue;
4972 }
4973 /* fall through */
4974 default:
4975 tt = *tail = new_Token(NULL, x->type, x->text, 0);
4976 break;
4977 }
4978 tail = &tt->next;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004979 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004980 *tail = NULL;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03004981 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004982
4983 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00004984 * If we had a label, push it on as the first line of
4985 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004986 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08004987 if (label) {
4988 if (dont_prepend < 0)
4989 free_tlist(startline);
4990 else {
4991 ll = nasm_malloc(sizeof(Line));
4992 ll->finishes = NULL;
4993 ll->next = istk->expansion;
4994 istk->expansion = ll;
4995 ll->first = startline;
4996 if (!dont_prepend) {
4997 while (label->next)
4998 label = label->next;
4999 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005000 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005001 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005002 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005003
H. Peter Anvin8ac25aa2016-02-18 01:16:18 -08005004 lfmt->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005005
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005006 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005007}
5008
H. Peter Anvin130736c2016-02-17 20:27:41 -08005009/*
5010 * This function adds macro names to error messages, and suppresses
5011 * them if necessary.
5012 */
5013static void pp_verror(int severity, const char *fmt, va_list arg)
Victor van den Elzen3b404c02008-09-18 13:51:36 +02005014{
H. Peter Anvin130736c2016-02-17 20:27:41 -08005015 char buff[BUFSIZ];
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005016 MMacro *mmac = NULL;
5017 int delta = 0;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02005018
H. Peter Anvin130736c2016-02-17 20:27:41 -08005019 /*
5020 * If we're in a dead branch of IF or something like it, ignore the error.
5021 * However, because %else etc are evaluated in the state context
5022 * of the previous branch, errors might get lost:
5023 * %if 0 ... %else trailing garbage ... %endif
5024 * So %else etc should set the ERR_PP_PRECOND flag.
5025 */
5026 if ((severity & ERR_MASK) < ERR_FATAL &&
5027 istk && istk->conds &&
5028 ((severity & ERR_PP_PRECOND) ?
5029 istk->conds->state == COND_NEVER :
H. Peter Anvineb6653f2016-04-05 13:03:10 -07005030 !emitting(istk->conds->state)))
H. Peter Anvin130736c2016-02-17 20:27:41 -08005031 return;
Victor van den Elzen3b404c02008-09-18 13:51:36 +02005032
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005033 /* get %macro name */
H. Peter Anvin130736c2016-02-17 20:27:41 -08005034 if (!(severity & ERR_NOFILE) && istk && istk->mstk) {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005035 mmac = istk->mstk;
5036 /* but %rep blocks should be skipped */
5037 while (mmac && !mmac->name)
5038 mmac = mmac->next_active, delta++;
Cyrill Gorcunov9900c6b2011-10-09 18:58:46 +04005039 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005040
H. Peter Anvin130736c2016-02-17 20:27:41 -08005041 if (mmac) {
5042 vsnprintf(buff, sizeof(buff), fmt, arg);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02005043
H. Peter Anvin130736c2016-02-17 20:27:41 -08005044 nasm_set_verror(real_verror);
5045 nasm_error(severity, "(%s:%d) %s",
5046 mmac->name, mmac->lineno - delta, buff);
5047 nasm_set_verror(pp_verror);
5048 } else {
5049 real_verror(severity, fmt, arg);
5050 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00005051}
5052
H. Peter Anvin8b262472019-02-26 14:00:54 -08005053static Token *stdmac_file(const SMacro *s, Token **params, int *paramsize)
5054{
5055 (void)s;
5056 (void)params;
5057 (void)paramsize;
5058
5059 return make_tok_qstr(src_get_fname());
5060}
5061
5062static Token *stdmac_line(const SMacro *s, Token **params, int *paramsize)
5063{
5064 (void)s;
5065 (void)params;
5066 (void)paramsize;
5067
5068 return make_tok_num(src_get_linnum());
5069}
5070
5071static Token *stdmac_bits(const SMacro *s, Token **params, int *paramsize)
5072{
5073 (void)s;
5074 (void)params;
5075 (void)paramsize;
5076
5077 return make_tok_num(globalbits);
5078}
5079
5080static Token *stdmac_ptr(const SMacro *s, Token **params, int *paramsize)
5081{
5082 const char *name;
5083
5084 (void)s;
5085 (void)params;
5086 (void)paramsize;
5087
5088 switch (globalbits) {
5089 case 16:
5090 name = "word";
5091 break;
5092 case 32:
5093 name = "dword";
5094 break;
5095 case 64:
5096 name = "qword";
5097 break;
5098 default:
5099 panic();
5100 }
5101 return new_Token(NULL, TOK_ID, name, 0);
5102}
5103
5104static Token *stdmac_pass(const SMacro *s, Token **params, int *paramsize)
5105{
5106 (void)s;
5107 (void)params;
5108 (void)paramsize;
5109
5110 return make_tok_num(pass);
5111}
5112
5113/* Add magic standard macros */
5114struct magic_macros {
5115 const char *name;
5116 int nparams;
5117 Token *(*func)(const SMacro *s, Token **params, int *paramsize);
5118};
5119static const struct magic_macros magic_macros[] =
5120{
5121 { "__FILE__", 0, stdmac_file },
5122 { "__LINE__", 0, stdmac_line },
5123 { "__BITS__", 0, stdmac_bits },
5124 { "__PTR__", 0, stdmac_ptr },
5125 { "__PASS__", 0, stdmac_pass },
5126 { NULL, 0, NULL }
5127};
5128
5129static void pp_add_magic_stdmac(void)
5130{
5131 const struct magic_macros *m;
5132 SMacro *s;
5133
5134 for (m = magic_macros; m->name; m++) {
5135 s = define_smacro(NULL, m->name, true, m->nparams, NULL);
5136 s->magic = true;
5137 s->e.magic = m->func;
5138 }
5139}
5140
H. Peter Anvin734b1882002-04-30 21:01:08 +00005141static void
H. Peter Anvin81b62b92017-12-20 13:33:49 -08005142pp_reset(const char *file, int apass, StrList **deplist)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005143{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005144 cstk = NULL;
H. Peter Anvin8b262472019-02-26 14:00:54 -08005145 nasm_new(istk);
H. Peter Anvin3e83cec2016-05-25 04:28:46 -07005146 istk->fp = nasm_open_read(file, NF_TEXT);
H. Peter Anvin274cda82016-05-10 02:56:29 -07005147 src_set(0, file);
H. Peter Anvineba20a72002-04-30 20:53:55 +00005148 istk->lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005149 if (!istk->fp)
H. Peter Anvin130736c2016-02-17 20:27:41 -08005150 nasm_fatal(ERR_NOFILE, "unable to open input file `%s'", file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005151 defining = NULL;
Charles Crayned4200be2008-07-12 16:42:33 -07005152 nested_mac_count = 0;
5153 nested_rep_count = 0;
H. Peter Anvin97a23472007-09-16 17:57:25 -07005154 init_macros();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005155 unique = 0;
H. Peter Anvinf7606612016-07-13 14:23:48 -07005156
H. Peter Anvin8b262472019-02-26 14:00:54 -08005157 pp_add_magic_stdmac();
5158
H. Peter Anvinf7606612016-07-13 14:23:48 -07005159 if (tasm_compatible_mode)
5160 pp_add_stdmac(nasm_stdmac_tasm);
5161
5162 pp_add_stdmac(nasm_stdmac_nasm);
5163 pp_add_stdmac(nasm_stdmac_version);
5164
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +03005165 if (extrastdmac)
5166 pp_add_stdmac(extrastdmac);
5167
H. Peter Anvinf7606612016-07-13 14:23:48 -07005168 stdmacpos = stdmacros[0];
5169 stdmacnext = &stdmacros[1];
5170
H. Peter Anvind2456592008-06-19 15:04:18 -07005171 do_predef = true;
H. Peter Anvin61f130f2008-09-25 15:45:06 -07005172
5173 /*
5174 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
5175 * The caller, however, will also pass in 3 for preprocess-only so
5176 * we can set __PASS__ accordingly.
5177 */
5178 pass = apass > 2 ? 2 : apass;
5179
H. Peter Anvin9924d1e2016-10-04 00:59:39 -07005180 dephead = deplist;
H. Peter Anvin436e3672016-10-04 01:12:28 -07005181 nasm_add_string_to_strlist(dephead, file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005182}
5183
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07005184static void pp_init(void)
5185{
5186 hash_init(&FileHash, HASH_MEDIUM);
5187}
5188
Keith Kaniosa6dfa782007-04-13 16:47:53 +00005189static char *pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005190{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00005191 char *line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005192 Token *tline;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005193
H. Peter Anvin130736c2016-02-17 20:27:41 -08005194 real_verror = nasm_set_verror(pp_verror);
H. Peter Anvin215186f2016-02-17 20:27:41 -08005195
H. Peter Anvine2c80182005-01-15 22:15:51 +00005196 while (1) {
5197 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005198 * Fetch a tokenized line, either from the macro-expansion
H. Peter Anvine2c80182005-01-15 22:15:51 +00005199 * buffer or from the input file.
5200 */
5201 tline = NULL;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005202 while (istk->expansion && istk->expansion->finishes) {
5203 Line *l = istk->expansion;
5204 if (!l->finishes->name && l->finishes->in_progress > 1) {
5205 Line *ll;
H. Peter Anvineba20a72002-04-30 20:53:55 +00005206
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005207 /*
5208 * This is a macro-end marker for a macro with no
5209 * name, which means it's not really a macro at all
5210 * but a %rep block, and the `in_progress' field is
5211 * more than 1, meaning that we still need to
5212 * repeat. (1 means the natural last repetition; 0
5213 * means termination by %exitrep.) We have
5214 * therefore expanded up to the %endrep, and must
5215 * push the whole block on to the expansion buffer
5216 * again. We don't bother to remove the macro-end
5217 * marker: we'd only have to generate another one
5218 * if we did.
5219 */
5220 l->finishes->in_progress--;
5221 list_for_each(l, l->finishes->expansion) {
5222 Token *t, *tt, **tail;
5223
5224 ll = nasm_malloc(sizeof(Line));
5225 ll->next = istk->expansion;
5226 ll->finishes = NULL;
5227 ll->first = NULL;
5228 tail = &ll->first;
5229
5230 list_for_each(t, l->first) {
5231 if (t->text || t->type == TOK_WHITESPACE) {
5232 tt = *tail = new_Token(NULL, t->type, t->text, 0);
5233 tail = &tt->next;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005234 }
5235 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005236
5237 istk->expansion = ll;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005238 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005239 } else {
5240 /*
5241 * Check whether a `%rep' was started and not ended
5242 * within this macro expansion. This can happen and
5243 * should be detected. It's a fatal error because
5244 * I'm too confused to work out how to recover
5245 * sensibly from it.
5246 */
5247 if (defining) {
5248 if (defining->name)
H. Peter Anvin130736c2016-02-17 20:27:41 -08005249 nasm_panic(0, "defining with name in expansion");
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005250 else if (istk->mstk->name)
H. Peter Anvin130736c2016-02-17 20:27:41 -08005251 nasm_fatal(0, "`%%rep' without `%%endrep' within"
5252 " expansion of macro `%s'",
5253 istk->mstk->name);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005254 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005255
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005256 /*
5257 * FIXME: investigate the relationship at this point between
5258 * istk->mstk and l->finishes
5259 */
5260 {
5261 MMacro *m = istk->mstk;
5262 istk->mstk = m->next_active;
5263 if (m->name) {
5264 /*
5265 * This was a real macro call, not a %rep, and
5266 * therefore the parameter information needs to
5267 * be freed.
5268 */
5269 if (m->prev) {
5270 pop_mmacro(m);
5271 l->finishes->in_progress --;
5272 } else {
5273 nasm_free(m->params);
5274 free_tlist(m->iline);
5275 nasm_free(m->paramlen);
5276 l->finishes->in_progress = 0;
5277 }
Adam Majer91e72402017-07-25 10:42:01 +02005278 }
5279
5280 /*
5281 * FIXME It is incorrect to always free_mmacro here.
5282 * It leads to usage-after-free.
5283 *
5284 * https://bugzilla.nasm.us/show_bug.cgi?id=3392414
5285 */
5286#if 0
5287 else
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005288 free_mmacro(m);
Adam Majer91e72402017-07-25 10:42:01 +02005289#endif
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005290 }
5291 istk->expansion = l->next;
5292 nasm_free(l);
H. Peter Anvin8ac25aa2016-02-18 01:16:18 -08005293 lfmt->downlevel(LIST_MACRO);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005294 }
5295 }
5296 while (1) { /* until we get a line we can use */
5297
5298 if (istk->expansion) { /* from a macro expansion */
5299 char *p;
5300 Line *l = istk->expansion;
5301 if (istk->mstk)
5302 istk->mstk->lineno++;
5303 tline = l->first;
5304 istk->expansion = l->next;
5305 nasm_free(l);
5306 p = detoken(tline, false);
H. Peter Anvin8ac25aa2016-02-18 01:16:18 -08005307 lfmt->line(LIST_MACRO, p);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005308 nasm_free(p);
5309 break;
5310 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00005311 line = read_line();
5312 if (line) { /* from the current input file */
5313 line = prepreproc(line);
Keith Kaniosb7a89542007-04-12 02:40:54 +00005314 tline = tokenize(line);
H. Peter Anvine2c80182005-01-15 22:15:51 +00005315 nasm_free(line);
5316 break;
5317 }
5318 /*
5319 * The current file has ended; work down the istk
5320 */
5321 {
5322 Include *i = istk;
5323 fclose(i->fp);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005324 if (i->conds) {
5325 /* nasm_error can't be conditionally suppressed */
H. Peter Anvin41087062016-03-03 14:27:34 -08005326 nasm_fatal(0,
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005327 "expected `%%endif' before end of file");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005328 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00005329 /* only set line and file name if there's a next node */
H. Peter Anvin274cda82016-05-10 02:56:29 -07005330 if (i->next)
5331 src_set(i->lineno, i->fname);
H. Peter Anvine2c80182005-01-15 22:15:51 +00005332 istk = i->next;
H. Peter Anvin8ac25aa2016-02-18 01:16:18 -08005333 lfmt->downlevel(LIST_INCLUDE);
H. Peter Anvine2c80182005-01-15 22:15:51 +00005334 nasm_free(i);
H. Peter Anvin130736c2016-02-17 20:27:41 -08005335 if (!istk) {
5336 line = NULL;
5337 goto done;
5338 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005339 if (istk->expansion && istk->expansion->finishes)
5340 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005341 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005342 }
5343
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005344 /*
5345 * We must expand MMacro parameters and MMacro-local labels
5346 * _before_ we plunge into directive processing, to cope
5347 * with things like `%define something %1' such as STRUC
5348 * uses. Unless we're _defining_ a MMacro, in which case
5349 * those tokens should be left alone to go into the
5350 * definition; and unless we're in a non-emitting
5351 * condition, in which case we don't want to meddle with
5352 * anything.
5353 */
5354 if (!defining && !(istk->conds && !emitting(istk->conds->state))
5355 && !(istk->mstk && !istk->mstk->in_progress)) {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005356 tline = expand_mmac_params(tline);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005357 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005358
H. Peter Anvine2c80182005-01-15 22:15:51 +00005359 /*
5360 * Check the line to see if it's a preprocessor directive.
5361 */
H. Peter Anvinbc7f4fe2016-10-04 14:57:17 -07005362 if (do_directive(tline, &line) == DIRECTIVE_FOUND) {
5363 if (line)
5364 break; /* Directive generated output */
5365 else
5366 continue;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005367 } else if (defining) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00005368 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005369 * We're defining a multi-line macro. We emit nothing
5370 * at all, and just
5371 * shove the tokenized line on to the macro definition.
H. Peter Anvine2c80182005-01-15 22:15:51 +00005372 */
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005373 Line *l = nasm_malloc(sizeof(Line));
5374 l->next = defining->expansion;
5375 l->first = tline;
5376 l->finishes = NULL;
5377 defining->expansion = l;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005378 continue;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005379 } else if (istk->conds && !emitting(istk->conds->state)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00005380 /*
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005381 * We're in a non-emitting branch of a condition block.
H. Peter Anvine2c80182005-01-15 22:15:51 +00005382 * Emit nothing at all, not even a blank line: when we
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005383 * emerge from the condition we'll give a line-number
H. Peter Anvine2c80182005-01-15 22:15:51 +00005384 * directive so we keep our place correctly.
5385 */
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005386 free_tlist(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00005387 continue;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005388 } else if (istk->mstk && !istk->mstk->in_progress) {
5389 /*
5390 * We're in a %rep block which has been terminated, so
5391 * we're walking through to the %endrep without
5392 * emitting anything. Emit nothing at all, not even a
5393 * blank line: when we emerge from the %rep block we'll
5394 * give a line-number directive so we keep our place
5395 * correctly.
5396 */
5397 free_tlist(tline);
5398 continue;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005399 } else {
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005400 tline = expand_smacro(tline);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005401 if (!expand_mmacro(tline)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00005402 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00005403 * De-tokenize the line again, and emit it.
H. Peter Anvine2c80182005-01-15 22:15:51 +00005404 */
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005405 line = detoken(tline, true);
5406 free_tlist(tline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00005407 break;
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005408 } else {
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005409 continue; /* expand_mmacro calls free_tlist */
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005410 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00005411 }
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005412 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005413
H. Peter Anvin130736c2016-02-17 20:27:41 -08005414done:
5415 nasm_set_verror(real_verror);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005416 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005417}
5418
H. Peter Anvine2c80182005-01-15 22:15:51 +00005419static void pp_cleanup(int pass)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005420{
H. Peter Anvin130736c2016-02-17 20:27:41 -08005421 real_verror = nasm_set_verror(pp_verror);
H. Peter Anvin215186f2016-02-17 20:27:41 -08005422
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005423 if (defining) {
5424 if (defining->name) {
H. Peter Anvin130736c2016-02-17 20:27:41 -08005425 nasm_error(ERR_NONFATAL,
5426 "end of file while still defining macro `%s'",
5427 defining->name);
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005428 } else {
H. Peter Anvin130736c2016-02-17 20:27:41 -08005429 nasm_error(ERR_NONFATAL, "end of file while still in %%rep");
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005430 }
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005431
5432 free_mmacro(defining);
Cyrill Gorcunova5aea572010-11-11 10:14:45 +03005433 defining = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005434 }
H. Peter Anvin130736c2016-02-17 20:27:41 -08005435
5436 nasm_set_verror(real_verror);
H. Peter Anvin215186f2016-02-17 20:27:41 -08005437
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005438 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005439 ctx_pop();
H. Peter Anvin97a23472007-09-16 17:57:25 -07005440 free_macros();
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005441 while (istk) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00005442 Include *i = istk;
5443 istk = istk->next;
5444 fclose(i->fp);
Cyrill Gorcunov8dcfd882011-03-03 09:18:56 +03005445 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005446 }
5447 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005448 ctx_pop();
H. Peter Anvin274cda82016-05-10 02:56:29 -07005449 src_set_fname(NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00005450 if (pass == 0) {
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03005451 IncPath *i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005452 free_llist(predef);
Cyrill Gorcunovdae24d72014-06-28 10:17:39 +04005453 predef = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00005454 delete_Blocks();
Cyrill Gorcunovdae24d72014-06-28 10:17:39 +04005455 freeTokens = NULL;
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03005456 while ((i = ipath)) {
5457 ipath = i->next;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005458 if (i->path)
5459 nasm_free(i->path);
Cyrill Gorcunovaccda192010-02-16 10:27:56 +03005460 nasm_free(i);
5461 }
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07005462 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005463}
5464
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04005465static void pp_include_path(char *path)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005466{
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005467 IncPath *i;
H. Peter Anvin37a321f2007-09-24 13:41:58 -07005468
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005469 i = nasm_malloc(sizeof(IncPath));
5470 i->path = path ? nasm_strdup(path) : NULL;
5471 i->next = NULL;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00005472
H. Peter Anvin89cee572009-07-15 09:16:54 -04005473 if (ipath) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00005474 IncPath *j = ipath;
H. Peter Anvin89cee572009-07-15 09:16:54 -04005475 while (j->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005476 j = j->next;
5477 j->next = i;
5478 } else {
5479 ipath = i;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00005480 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005481}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00005482
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04005483static void pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005484{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005485 Token *inc, *space, *name;
5486 Line *l;
5487
H. Peter Anvin734b1882002-04-30 21:01:08 +00005488 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
5489 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
5490 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005491
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005492 l = nasm_malloc(sizeof(Line));
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005493 l->next = predef;
5494 l->first = inc;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005495 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005496 predef = l;
5497}
5498
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04005499static void pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005500{
5501 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005502 Line *l;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00005503 char *equals;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005504
H. Peter Anvin130736c2016-02-17 20:27:41 -08005505 real_verror = nasm_set_verror(pp_verror);
H. Peter Anvin215186f2016-02-17 20:27:41 -08005506
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005507 equals = strchr(definition, '=');
H. Peter Anvin734b1882002-04-30 21:01:08 +00005508 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
5509 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005510 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005511 *equals = ' ';
Keith Kaniosb7a89542007-04-12 02:40:54 +00005512 space->next = tokenize(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005513 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00005514 *equals = '=';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005515
Cyrill Gorcunov6d42e9b2015-02-08 11:07:17 +03005516 if (space->next->type != TOK_PREPROC_ID &&
5517 space->next->type != TOK_ID)
H. Peter Anvin130736c2016-02-17 20:27:41 -08005518 nasm_error(ERR_WARNING, "pre-defining non ID `%s\'\n", definition);
Cyrill Gorcunov6d42e9b2015-02-08 11:07:17 +03005519
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005520 l = nasm_malloc(sizeof(Line));
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005521 l->next = predef;
5522 l->first = def;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005523 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005524 predef = l;
H. Peter Anvin130736c2016-02-17 20:27:41 -08005525
5526 nasm_set_verror(real_verror);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00005527}
5528
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04005529static void pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00005530{
5531 Token *def, *space;
5532 Line *l;
5533
H. Peter Anvin734b1882002-04-30 21:01:08 +00005534 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
5535 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Keith Kaniosb7a89542007-04-12 02:40:54 +00005536 space->next = tokenize(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00005537
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005538 l = nasm_malloc(sizeof(Line));
H. Peter Anvin620515a2002-04-30 20:57:38 +00005539 l->next = predef;
5540 l->first = def;
H. Peter Anvin36206cd2012-03-03 16:14:51 -08005541 l->finishes = NULL;
H. Peter Anvin620515a2002-04-30 20:57:38 +00005542 predef = l;
5543}
5544
H. Peter Anvin05990342018-06-11 13:32:42 -07005545/* Insert an early preprocessor command that doesn't need special handling */
5546static void pp_pre_command(const char *what, char *string)
5547{
5548 char *cmd;
5549 Token *def, *space;
5550 Line *l;
5551
5552 def = tokenize(string);
5553 if (what) {
5554 cmd = nasm_strcat(what[0] == '%' ? "" : "%", what);
5555 space = new_Token(def, TOK_WHITESPACE, NULL, 0);
5556 def = new_Token(space, TOK_PREPROC_ID, cmd, 0);
5557 }
5558
5559 l = nasm_malloc(sizeof(Line));
5560 l->next = predef;
5561 l->first = def;
5562 l->finishes = NULL;
5563 predef = l;
5564}
5565
H. Peter Anvinf7606612016-07-13 14:23:48 -07005566static void pp_add_stdmac(macros_t *macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005567{
H. Peter Anvinf7606612016-07-13 14:23:48 -07005568 macros_t **mp;
5569
5570 /* Find the end of the list and avoid duplicates */
5571 for (mp = stdmacros; *mp; mp++) {
5572 if (*mp == macros)
5573 return; /* Nothing to do */
5574 }
5575
5576 nasm_assert(mp < &stdmacros[ARRAY_SIZE(stdmacros)-1]);
5577
5578 *mp = macros;
H. Peter Anvin76690a12002-04-30 20:52:49 +00005579}
5580
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +03005581static void pp_extra_stdmac(macros_t *macros)
5582{
5583 extrastdmac = macros;
5584}
5585
H. Peter Anvin8b262472019-02-26 14:00:54 -08005586static Token *make_tok_num(int64_t val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00005587{
Cyrill Gorcunovce652742013-05-06 23:43:43 +04005588 char numbuf[32];
H. Peter Anvin8b262472019-02-26 14:00:54 -08005589 int len = snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
5590 return new_Token(NULL, TOK_NUMBER, numbuf, len);
5591}
5592
5593static Token *make_tok_qstr(const char *str)
5594{
5595 Token *t = new_Token(NULL, TOK_STRING, NULL, 0);
5596 t->text = nasm_quote_cstr(str);
5597 return t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00005598}
5599
H. Peter Anvin37368952016-05-09 14:10:32 -07005600static void pp_list_one_macro(MMacro *m, int severity)
5601{
5602 if (!m)
5603 return;
5604
5605 /* We need to print the next_active list in reverse order */
5606 pp_list_one_macro(m->next_active, severity);
5607
5608 if (m->name && !m->nolist) {
H. Peter Anvin274cda82016-05-10 02:56:29 -07005609 src_set(m->xline + m->lineno, m->fname);
H. Peter Anvine2f5edb2018-12-11 00:06:29 -08005610 nasm_error(severity, "... from macro `%s' defined", m->name);
H. Peter Anvin37368952016-05-09 14:10:32 -07005611 }
5612}
5613
H. Peter Anvin4def1a82016-05-09 13:59:44 -07005614static void pp_error_list_macros(int severity)
5615{
H. Peter Anvin4def1a82016-05-09 13:59:44 -07005616 int32_t saved_line;
5617 const char *saved_fname = NULL;
5618
H. Peter Anvine2f5edb2018-12-11 00:06:29 -08005619 severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE;
H. Peter Anvin274cda82016-05-10 02:56:29 -07005620 src_get(&saved_line, &saved_fname);
H. Peter Anvin4def1a82016-05-09 13:59:44 -07005621
Cyrill Gorcunov771d04e2016-05-10 23:27:03 +03005622 if (istk)
5623 pp_list_one_macro(istk->mstk, severity);
H. Peter Anvin4def1a82016-05-09 13:59:44 -07005624
H. Peter Anvin274cda82016-05-10 02:56:29 -07005625 src_set(saved_line, saved_fname);
H. Peter Anvin4def1a82016-05-09 13:59:44 -07005626}
5627
H. Peter Anvine7469712016-02-18 02:20:59 -08005628const struct preproc_ops nasmpp = {
H. Peter Anvin169ac7c2016-09-25 17:08:05 -07005629 pp_init,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005630 pp_reset,
5631 pp_getline,
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04005632 pp_cleanup,
Cyrill Gorcunov15ce78f2017-01-06 20:21:28 +03005633 pp_extra_stdmac,
Cyrill Gorcunov0b78bff2012-05-07 01:57:55 +04005634 pp_pre_define,
5635 pp_pre_undefine,
5636 pp_pre_include,
H. Peter Anvin05990342018-06-11 13:32:42 -07005637 pp_pre_command,
H. Peter Anvin4def1a82016-05-09 13:59:44 -07005638 pp_include_path,
5639 pp_error_list_macros,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00005640};