blob: 888cd074e68b7cc621995ac8b124dfb4c1dcb030 [file] [log] [blame]
H. Peter Anvin65747262002-05-07 00:10:05 +00001/* -*- mode: c; c-file-style: "bsd" -*- */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002/* preproc.c macro preprocessor for the Netwide Assembler
3 *
4 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
5 * Julian Hall. All rights reserved. The software is
6 * redistributable under the licence given in the file "Licence"
7 * distributed in the NASM archive.
8 *
9 * initial version 18/iii/97 by Simon Tatham
10 */
11
H. Peter Anvin4836e332002-04-30 20:56:43 +000012/* Typical flow of text through preproc
13 *
Keith Kaniosb7a89542007-04-12 02:40:54 +000014 * pp_getline gets tokenized lines, either
H. Peter Anvin4836e332002-04-30 20:56:43 +000015 *
16 * from a macro expansion
17 *
18 * or
19 * {
20 * read_line gets raw text from stdmacpos, or predef, or current input file
Keith Kaniosb7a89542007-04-12 02:40:54 +000021 * tokenize converts to tokens
H. Peter Anvin4836e332002-04-30 20:56:43 +000022 * }
23 *
24 * expand_mmac_params is used to expand %1 etc., unless a macro is being
25 * defined or a false conditional is being processed
26 * (%0, %1, %+1, %-1, %%foo
27 *
28 * do_directive checks for directives
29 *
30 * expand_smacro is used to expand single line macros
31 *
32 * expand_mmacro is used to expand multi-line macros
33 *
34 * detoken is used to convert the line back to text
35 */
H. Peter Anvineba20a72002-04-30 20:53:55 +000036
H. Peter Anvinfe501952007-10-02 21:53:51 -070037#include "compiler.h"
38
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000039#include <stdio.h>
H. Peter Anvinaf535c12002-04-30 20:59:21 +000040#include <stdarg.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000041#include <stdlib.h>
42#include <stddef.h>
43#include <string.h>
44#include <ctype.h>
H. Peter Anvin76690a12002-04-30 20:52:49 +000045#include <limits.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000046#include <inttypes.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000047
48#include "nasm.h"
49#include "nasmlib.h"
H. Peter Anvin4169a472007-09-12 01:29:43 +000050#include "preproc.h"
H. Peter Anvin97a23472007-09-16 17:57:25 -070051#include "hashtbl.h"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000052
53typedef struct SMacro SMacro;
54typedef struct MMacro MMacro;
55typedef struct Context Context;
56typedef struct Token Token;
H. Peter Anvince616072002-04-30 21:02:23 +000057typedef struct Blocks Blocks;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000058typedef struct Line Line;
59typedef struct Include Include;
60typedef struct Cond Cond;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000061typedef struct IncPath IncPath;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000062
63/*
H. Peter Anvin97a23472007-09-16 17:57:25 -070064 * Note on the storage of both SMacro and MMacros: the hash table
65 * indexes them case-insensitively, and we then have to go through a
66 * linked list of potential case aliases (and, for MMacros, parameter
67 * ranges); this is to preserve the matching semantics of the earlier
68 * code. If the number of case aliases for a specific macro is a
69 * performance issue, you may want to reconsider your coding style.
70 */
71
72/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000073 * Store the definition of a single-line macro.
74 */
H. Peter Anvine2c80182005-01-15 22:15:51 +000075struct SMacro {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000076 SMacro *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +000077 char *name;
H. Peter Anvin70055962007-10-11 00:05:31 -070078 bool casesense;
H. Peter Anvin16ed4382007-10-11 10:06:19 -070079 bool in_progress;
H. Peter Anvin70055962007-10-11 00:05:31 -070080 unsigned int nparam;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000081 Token *expansion;
82};
83
84/*
H. Peter Anvin76690a12002-04-30 20:52:49 +000085 * Store the definition of a multi-line macro. This is also used to
86 * store the interiors of `%rep...%endrep' blocks, which are
87 * effectively self-re-invoking multi-line macros which simply
88 * don't have a name or bother to appear in the hash tables. %rep
89 * blocks are signified by having a NULL `name' field.
90 *
91 * In a MMacro describing a `%rep' block, the `in_progress' field
92 * isn't merely boolean, but gives the number of repeats left to
93 * run.
94 *
95 * The `next' field is used for storing MMacros in hash tables; the
96 * `next_active' field is for stacking them on istk entries.
97 *
98 * When a MMacro is being expanded, `params', `iline', `nparam',
99 * `paramlen', `rotate' and `unique' are local to the invocation.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000100 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000101struct MMacro {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000102 MMacro *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000103 char *name;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -0700104 int nparam_min, nparam_max;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700105 bool casesense;
106 bool plus; /* is the last parameter greedy? */
107 bool nolist; /* is this macro listing-inhibited? */
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700108 int64_t in_progress;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000109 Token *dlist; /* All defaults as one list */
110 Token **defaults; /* Parameter default pointers */
111 int ndefs; /* number of default parameters */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000112 Line *expansion;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000113
114 MMacro *next_active;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000115 MMacro *rep_nest; /* used for nesting %rep */
116 Token **params; /* actual parameters */
117 Token *iline; /* invocation line */
H. Peter Anvin25a99342007-09-22 17:45:45 -0700118 unsigned int nparam, rotate;
119 int *paramlen;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700120 uint64_t unique;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000121 int lineno; /* Current line number on expansion */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000122};
123
124/*
125 * The context stack is composed of a linked list of these.
126 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000127struct Context {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000128 Context *next;
129 SMacro *localmac;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000130 char *name;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000131 uint32_t number;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000132};
133
134/*
135 * This is the internal form which we break input lines up into.
136 * Typically stored in linked lists.
137 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000138 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
139 * necessarily used as-is, but is intended to denote the number of
140 * the substituted parameter. So in the definition
141 *
142 * %define a(x,y) ( (x) & ~(y) )
143 *
144 * the token representing `x' will have its type changed to
145 * TOK_SMAC_PARAM, but the one representing `y' will be
146 * TOK_SMAC_PARAM+1.
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000147 *
148 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
149 * which doesn't need quotes around it. Used in the pre-include
150 * mechanism as an alternative to trying to find a sensible type of
151 * quote to use on the filename we were passed.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000152 */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000153enum pp_token_type {
154 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID,
155 TOK_PREPROC_ID, TOK_STRING,
156 TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM,
157 TOK_INTERNAL_STRING
158};
159
H. Peter Anvine2c80182005-01-15 22:15:51 +0000160struct Token {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000161 Token *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000162 char *text;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000163 SMacro *mac; /* associated macro for TOK_SMAC_END */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000164 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000165};
166
167/*
168 * Multi-line macro definitions are stored as a linked list of
169 * these, which is essentially a container to allow several linked
170 * lists of Tokens.
171 *
172 * Note that in this module, linked lists are treated as stacks
173 * wherever possible. For this reason, Lines are _pushed_ on to the
174 * `expansion' field in MMacro structures, so that the linked list,
175 * if walked, would give the macro lines in reverse order; this
176 * means that we can walk the list when expanding a macro, and thus
177 * push the lines on to the `expansion' field in _istk_ in reverse
178 * order (so that when popped back off they are in the right
179 * order). It may seem cockeyed, and it relies on my design having
180 * an even number of steps in, but it works...
181 *
182 * Some of these structures, rather than being actual lines, are
183 * markers delimiting the end of the expansion of a given macro.
H. Peter Anvin76690a12002-04-30 20:52:49 +0000184 * This is for use in the cycle-tracking and %rep-handling code.
185 * Such structures have `finishes' non-NULL, and `first' NULL. All
186 * others have `finishes' NULL, but `first' may still be NULL if
187 * the line is blank.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000188 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000189struct Line {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000190 Line *next;
191 MMacro *finishes;
192 Token *first;
193};
194
195/*
196 * To handle an arbitrary level of file inclusion, we maintain a
197 * stack (ie linked list) of these things.
198 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000199struct Include {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000200 Include *next;
201 FILE *fp;
202 Cond *conds;
203 Line *expansion;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000204 char *fname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000205 int lineno, lineinc;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000206 MMacro *mstk; /* stack of active macros/reps */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000207};
208
209/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000210 * Include search path. This is simply a list of strings which get
211 * prepended, in turn, to the name of an include file, in an
212 * attempt to find the file if it's not in the current directory.
213 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000214struct IncPath {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000215 IncPath *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000216 char *path;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000217};
218
219/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000220 * Conditional assembly: we maintain a separate stack of these for
221 * each level of file inclusion. (The only reason we keep the
222 * stacks separate is to ensure that a stray `%endif' in a file
223 * included from within the true branch of a `%if' won't terminate
224 * it and cause confusion: instead, rightly, it'll cause an error.)
225 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000226struct Cond {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000227 Cond *next;
228 int state;
229};
H. Peter Anvine2c80182005-01-15 22:15:51 +0000230enum {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000231 /*
232 * These states are for use just after %if or %elif: IF_TRUE
233 * means the condition has evaluated to truth so we are
234 * currently emitting, whereas IF_FALSE means we are not
235 * currently emitting but will start doing so if a %else comes
236 * up. In these states, all directives are admissible: %elif,
237 * %else and %endif. (And of course %if.)
238 */
239 COND_IF_TRUE, COND_IF_FALSE,
240 /*
241 * These states come up after a %else: ELSE_TRUE means we're
242 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
243 * any %elif or %else will cause an error.
244 */
245 COND_ELSE_TRUE, COND_ELSE_FALSE,
246 /*
247 * This state means that we're not emitting now, and also that
248 * nothing until %endif will be emitted at all. It's for use in
249 * two circumstances: (i) when we've had our moment of emission
250 * and have now started seeing %elifs, and (ii) when the
251 * condition construct in question is contained within a
252 * non-emitting branch of a larger condition construct.
253 */
254 COND_NEVER
255};
256#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
257
Ed Beroset3ab3f412002-06-11 03:31:49 +0000258/*
259 * These defines are used as the possible return values for do_directive
260 */
261#define NO_DIRECTIVE_FOUND 0
262#define DIRECTIVE_FOUND 1
263
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000264/*
265 * Condition codes. Note that we use c_ prefix not C_ because C_ is
266 * used in nasm.h for the "real" condition codes. At _this_ level,
267 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
268 * ones, so we need a different enum...
269 */
H. Peter Anvin476d2862007-10-02 22:04:15 -0700270static const char * const conditions[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000271 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
272 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
H. Peter Anvince9be342007-09-12 00:22:29 +0000273 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000274};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700275enum pp_conds {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000276 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
277 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 -0700278 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
279 c_none = -1
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000280};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700281static const enum pp_conds inverse_ccs[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000282 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
283 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 +0000284 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000285};
286
H. Peter Anvin76690a12002-04-30 20:52:49 +0000287/*
288 * Directive names.
289 */
H. Peter Anvin65747262002-05-07 00:10:05 +0000290/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
H. Peter Anvin9bf0aa72007-09-12 02:12:07 +0000291static int is_condition(enum preproc_token arg)
H. Peter Anvin65747262002-05-07 00:10:05 +0000292{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000293 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
H. Peter Anvin65747262002-05-07 00:10:05 +0000294}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000295
296/* For TASM compatibility we need to be able to recognise TASM compatible
297 * conditional compilation directives. Using the NASM pre-processor does
298 * not work, so we look for them specifically from the following list and
299 * then jam in the equivalent NASM directive into the input stream.
300 */
301
302#ifndef MAX
303# define MAX(a,b) ( ((a) > (b)) ? (a) : (b))
304#endif
305
H. Peter Anvine2c80182005-01-15 22:15:51 +0000306enum {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000307 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
308 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
309};
310
H. Peter Anvin476d2862007-10-02 22:04:15 -0700311static const char * const tasm_directives[] = {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000312 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
313 "ifndef", "include", "local"
314};
315
316static int StackSize = 4;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000317static char *StackPointer = "ebp";
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000318static int ArgOffset = 8;
319static int LocalOffset = 4;
320
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000321static Context *cstk;
322static Include *istk;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000323static IncPath *ipath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000324
H. Peter Anvine2c80182005-01-15 22:15:51 +0000325static efunc _error; /* Pointer to client-provided error reporting function */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000326static evalfunc evaluate;
327
H. Peter Anvine2c80182005-01-15 22:15:51 +0000328static int pass; /* HACK: pass 0 = generate dependencies only */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000329
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700330static uint64_t unique; /* unique identifier numbers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000331
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000332static Line *predef = NULL;
333
334static ListGen *list;
335
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000336/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000337 * The current set of multi-line macros we have defined.
338 */
H. Peter Anvin97a23472007-09-16 17:57:25 -0700339static struct hash_table *mmacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000340
341/*
342 * The current set of single-line macros we have defined.
343 */
H. Peter Anvin97a23472007-09-16 17:57:25 -0700344static struct hash_table *smacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000345
346/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000347 * The multi-line macro we are currently defining, or the %rep
348 * block we are currently reading, if any.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000349 */
350static MMacro *defining;
351
352/*
353 * The number of macro parameters to allocate space for at a time.
354 */
355#define PARAM_DELTA 16
356
357/*
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000358 * The standard macro set: defined as `static char *stdmac[]'. Also
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000359 * gives our position in the macro set, when we're processing it.
360 */
361#include "macros.c"
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000362static const char **stdmacpos;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000363
364/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000365 * The extra standard macros that come from the object format, if
366 * any.
367 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000368static const char **extrastdmac = NULL;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700369bool any_extrastdmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000370
371/*
H. Peter Anvin734b1882002-04-30 21:01:08 +0000372 * Tokens are allocated in blocks to improve speed
373 */
374#define TOKEN_BLOCKSIZE 4096
375static Token *freeTokens = NULL;
H. Peter Anvince616072002-04-30 21:02:23 +0000376struct Blocks {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000377 Blocks *next;
378 void *chunk;
H. Peter Anvince616072002-04-30 21:02:23 +0000379};
380
381static Blocks blocks = { NULL, NULL };
H. Peter Anvin734b1882002-04-30 21:01:08 +0000382
383/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000384 * Forward declarations.
385 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000386static Token *expand_mmac_params(Token * tline);
387static Token *expand_smacro(Token * tline);
388static Token *expand_id(Token * tline);
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700389static Context *get_ctx(char *name, bool all_contexts);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000390static void make_tok_num(Token * tok, int32_t val);
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000391static void error(int severity, const char *fmt, ...);
H. Peter Anvince616072002-04-30 21:02:23 +0000392static void *new_Block(size_t size);
393static void delete_Blocks(void);
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000394static Token *new_Token(Token * next, enum pp_token_type type, char *text, int txtlen);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000395static Token *delete_Token(Token * t);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000396
397/*
398 * Macros for safe checking of token pointers, avoid *(NULL)
399 */
400#define tok_type_(x,t) ((x) && (x)->type == (t))
401#define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
402#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
403#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
H. Peter Anvin76690a12002-04-30 20:52:49 +0000404
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000405/* Handle TASM specific directives, which do not contain a % in
406 * front of them. We do it here because I could not find any other
407 * place to do it for the moment, and it is a hack (ideally it would
408 * be nice to be able to use the NASM pre-processor to do it).
409 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000410static char *check_tasm_directive(char *line)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000411{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000412 int32_t i, j, k, m, len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000413 char *p = line, *oldline, oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000414
415 /* Skip whitespace */
416 while (isspace(*p) && *p != 0)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000417 p++;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000418
419 /* Binary search for the directive name */
420 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +0000421 j = elements(tasm_directives);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000422 len = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000423 while (!isspace(p[len]) && p[len] != 0)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000424 len++;
425 if (len) {
426 oldchar = p[len];
427 p[len] = 0;
428 while (j - i > 1) {
429 k = (j + i) / 2;
430 m = nasm_stricmp(p, tasm_directives[k]);
431 if (m == 0) {
432 /* We have found a directive, so jam a % in front of it
433 * so that NASM will then recognise it as one if it's own.
434 */
435 p[len] = oldchar;
436 len = strlen(p);
437 oldline = line;
438 line = nasm_malloc(len + 2);
439 line[0] = '%';
440 if (k == TM_IFDIFI) {
441 /* NASM does not recognise IFDIFI, so we convert it to
442 * %ifdef BOGUS. This is not used in NASM comaptible
443 * code, but does need to parse for the TASM macro
444 * package.
445 */
446 strcpy(line + 1, "ifdef BOGUS");
447 } else {
448 memcpy(line + 1, p, len + 1);
449 }
450 nasm_free(oldline);
451 return line;
452 } else if (m < 0) {
453 j = k;
454 } else
455 i = k;
456 }
457 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000458 }
459 return line;
460}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000461
H. Peter Anvin76690a12002-04-30 20:52:49 +0000462/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000463 * The pre-preprocessing stage... This function translates line
464 * number indications as they emerge from GNU cpp (`# lineno "file"
465 * flags') into NASM preprocessor line number indications (`%line
466 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000467 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000468static char *prepreproc(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000469{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000470 int lineno, fnlen;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000471 char *fname, *oldline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000472
H. Peter Anvine2c80182005-01-15 22:15:51 +0000473 if (line[0] == '#' && line[1] == ' ') {
474 oldline = line;
475 fname = oldline + 2;
476 lineno = atoi(fname);
477 fname += strspn(fname, "0123456789 ");
478 if (*fname == '"')
479 fname++;
480 fnlen = strcspn(fname, "\"");
481 line = nasm_malloc(20 + fnlen);
482 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
483 nasm_free(oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000484 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000485 if (tasm_compatible_mode)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000486 return check_tasm_directive(line);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000487 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000488}
489
490/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000491 * Free a linked list of tokens.
492 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000493static void free_tlist(Token * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000494{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000495 while (list) {
496 list = delete_Token(list);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000497 }
498}
499
500/*
501 * Free a linked list of lines.
502 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000503static void free_llist(Line * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000504{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000505 Line *l;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000506 while (list) {
507 l = list;
508 list = list->next;
509 free_tlist(l->first);
510 nasm_free(l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000511 }
512}
513
514/*
H. Peter Anvineba20a72002-04-30 20:53:55 +0000515 * Free an MMacro
516 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000517static void free_mmacro(MMacro * m)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000518{
H. Peter Anvin734b1882002-04-30 21:01:08 +0000519 nasm_free(m->name);
520 free_tlist(m->dlist);
521 nasm_free(m->defaults);
522 free_llist(m->expansion);
523 nasm_free(m);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000524}
525
526/*
H. Peter Anvin97a23472007-09-16 17:57:25 -0700527 * Free all currently defined macros, and free the hash tables
528 */
529static void free_macros(void)
530{
531 struct hash_tbl_node *it;
532 const char *key;
533 SMacro *s;
534 MMacro *m;
535
536 it = NULL;
537 while ((s = hash_iterate(smacros, &it, &key)) != NULL) {
538 nasm_free((void *)key);
539 while (s) {
540 SMacro *ns = s->next;
541 nasm_free(s->name);
542 free_tlist(s->expansion);
543 nasm_free(s);
544 s = ns;
545 }
546 }
547 hash_free(smacros);
548
549 it = NULL;
550 while ((m = hash_iterate(mmacros, &it, &key)) != NULL) {
551 nasm_free((void *)key);
552 while (m) {
553 MMacro *nm = m->next;
554 free_mmacro(m);
555 m = nm;
556 }
557 }
558 hash_free(mmacros);
559}
560
561/*
562 * Initialize the hash tables
563 */
564static void init_macros(void)
565{
566 smacros = hash_init();
567 mmacros = hash_init();
568}
569
570/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000571 * Pop the context stack.
572 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000573static void ctx_pop(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000574{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000575 Context *c = cstk;
576 SMacro *smac, *s;
577
578 cstk = cstk->next;
579 smac = c->localmac;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000580 while (smac) {
581 s = smac;
582 smac = smac->next;
583 nasm_free(s->name);
584 free_tlist(s->expansion);
585 nasm_free(s);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000586 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000587 nasm_free(c->name);
588 nasm_free(c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000589}
590
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000591#define BUF_DELTA 512
592/*
593 * Read a line from the top file in istk, handling multiple CR/LFs
594 * at the end of the line read, and handling spurious ^Zs. Will
595 * return lines from the standard macro set if this has not already
596 * been done.
597 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000598static char *read_line(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000599{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000600 char *buffer, *p, *q;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000601 int bufsize, continued_count;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000602
H. Peter Anvine2c80182005-01-15 22:15:51 +0000603 if (stdmacpos) {
604 if (*stdmacpos) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000605 char *ret = nasm_strdup(*stdmacpos++);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000606 if (!*stdmacpos && any_extrastdmac) {
607 stdmacpos = extrastdmac;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700608 any_extrastdmac = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000609 return ret;
610 }
611 /*
612 * Nasty hack: here we push the contents of `predef' on
613 * to the top-level expansion stack, since this is the
614 * most convenient way to implement the pre-include and
615 * pre-define features.
616 */
617 if (!*stdmacpos) {
618 Line *pd, *l;
619 Token *head, **tail, *t;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000620
H. Peter Anvine2c80182005-01-15 22:15:51 +0000621 for (pd = predef; pd; pd = pd->next) {
622 head = NULL;
623 tail = &head;
624 for (t = pd->first; t; t = t->next) {
625 *tail = new_Token(NULL, t->type, t->text, 0);
626 tail = &(*tail)->next;
627 }
628 l = nasm_malloc(sizeof(Line));
629 l->next = istk->expansion;
630 l->first = head;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700631 l->finishes = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000632 istk->expansion = l;
633 }
634 }
635 return ret;
636 } else {
637 stdmacpos = NULL;
638 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000639 }
640
641 bufsize = BUF_DELTA;
642 buffer = nasm_malloc(BUF_DELTA);
643 p = buffer;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000644 continued_count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000645 while (1) {
646 q = fgets(p, bufsize - (p - buffer), istk->fp);
647 if (!q)
648 break;
649 p += strlen(p);
650 if (p > buffer && p[-1] == '\n') {
651 /* Convert backslash-CRLF line continuation sequences into
652 nothing at all (for DOS and Windows) */
653 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
654 p -= 3;
655 *p = 0;
656 continued_count++;
657 }
658 /* Also convert backslash-LF line continuation sequences into
659 nothing at all (for Unix) */
660 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
661 p -= 2;
662 *p = 0;
663 continued_count++;
664 } else {
665 break;
666 }
667 }
668 if (p - buffer > bufsize - 10) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000669 int32_t offset = p - buffer;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000670 bufsize += BUF_DELTA;
671 buffer = nasm_realloc(buffer, bufsize);
672 p = buffer + offset; /* prevent stale-pointer problems */
673 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000674 }
675
H. Peter Anvine2c80182005-01-15 22:15:51 +0000676 if (!q && p == buffer) {
677 nasm_free(buffer);
678 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000679 }
680
H. Peter Anvine2c80182005-01-15 22:15:51 +0000681 src_set_linnum(src_get_linnum() + istk->lineinc +
682 (continued_count * istk->lineinc));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000683
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000684 /*
685 * Play safe: remove CRs as well as LFs, if any of either are
686 * present at the end of the line.
687 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000688 while (--p >= buffer && (*p == '\n' || *p == '\r'))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000689 *p = '\0';
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000690
691 /*
692 * Handle spurious ^Z, which may be inserted into source files
693 * by some file transfer utilities.
694 */
695 buffer[strcspn(buffer, "\032")] = '\0';
696
H. Peter Anvin734b1882002-04-30 21:01:08 +0000697 list->line(LIST_READ, buffer);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000698
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000699 return buffer;
700}
701
702/*
Keith Kaniosb7a89542007-04-12 02:40:54 +0000703 * Tokenize a line of text. This is a very simple process since we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000704 * don't need to parse the value out of e.g. numeric tokens: we
705 * simply split one string into many.
706 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000707static Token *tokenize(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000708{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000709 char *p = line;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000710 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000711 Token *list = NULL;
712 Token *t, **tail = &list;
713
H. Peter Anvine2c80182005-01-15 22:15:51 +0000714 while (*line) {
715 p = line;
716 if (*p == '%') {
717 p++;
718 if (isdigit(*p) ||
719 ((*p == '-' || *p == '+') && isdigit(p[1])) ||
720 ((*p == '+') && (isspace(p[1]) || !p[1]))) {
721 do {
722 p++;
723 }
724 while (isdigit(*p));
725 type = TOK_PREPROC_ID;
726 } else if (*p == '{') {
727 p++;
728 while (*p && *p != '}') {
729 p[-1] = *p;
730 p++;
731 }
732 p[-1] = '\0';
733 if (*p)
734 p++;
735 type = TOK_PREPROC_ID;
736 } else if (isidchar(*p) ||
737 ((*p == '!' || *p == '%' || *p == '$') &&
738 isidchar(p[1]))) {
739 do {
740 p++;
741 }
742 while (isidchar(*p));
743 type = TOK_PREPROC_ID;
744 } else {
745 type = TOK_OTHER;
746 if (*p == '%')
747 p++;
748 }
749 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
750 type = TOK_ID;
751 p++;
752 while (*p && isidchar(*p))
753 p++;
754 } else if (*p == '\'' || *p == '"') {
755 /*
756 * A string token.
757 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000758 char c = *p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000759 p++;
760 type = TOK_STRING;
761 while (*p && *p != c)
762 p++;
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000763
H. Peter Anvine2c80182005-01-15 22:15:51 +0000764 if (*p) {
765 p++;
766 } else {
767 error(ERR_WARNING, "unterminated string");
768 /* Handling unterminated strings by UNV */
769 /* type = -1; */
770 }
771 } else if (isnumstart(*p)) {
772 /*
773 * A number token.
774 */
775 type = TOK_NUMBER;
776 p++;
777 while (*p && isnumchar(*p))
778 p++;
779 } else if (isspace(*p)) {
780 type = TOK_WHITESPACE;
781 p++;
782 while (*p && isspace(*p))
783 p++;
784 /*
785 * Whitespace just before end-of-line is discarded by
786 * pretending it's a comment; whitespace just before a
787 * comment gets lumped into the comment.
788 */
789 if (!*p || *p == ';') {
790 type = TOK_COMMENT;
791 while (*p)
792 p++;
793 }
794 } else if (*p == ';') {
795 type = TOK_COMMENT;
796 while (*p)
797 p++;
798 } else {
799 /*
800 * Anything else is an operator of some kind. We check
801 * for all the double-character operators (>>, <<, //,
802 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000803 * else is a single-character operator.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000804 */
805 type = TOK_OTHER;
806 if ((p[0] == '>' && p[1] == '>') ||
807 (p[0] == '<' && p[1] == '<') ||
808 (p[0] == '/' && p[1] == '/') ||
809 (p[0] == '<' && p[1] == '=') ||
810 (p[0] == '>' && p[1] == '=') ||
811 (p[0] == '=' && p[1] == '=') ||
812 (p[0] == '!' && p[1] == '=') ||
813 (p[0] == '<' && p[1] == '>') ||
814 (p[0] == '&' && p[1] == '&') ||
815 (p[0] == '|' && p[1] == '|') ||
816 (p[0] == '^' && p[1] == '^')) {
817 p++;
818 }
819 p++;
820 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000821
H. Peter Anvine2c80182005-01-15 22:15:51 +0000822 /* Handling unterminated string by UNV */
823 /*if (type == -1)
824 {
825 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
826 t->text[p-line] = *line;
827 tail = &t->next;
828 }
829 else */
830 if (type != TOK_COMMENT) {
831 *tail = t = new_Token(NULL, type, line, p - line);
832 tail = &t->next;
833 }
834 line = p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000835 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000836 return list;
837}
838
H. Peter Anvince616072002-04-30 21:02:23 +0000839/*
840 * this function allocates a new managed block of memory and
841 * returns a pointer to the block. The managed blocks are
842 * deleted only all at once by the delete_Blocks function.
843 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000844static void *new_Block(size_t size)
H. Peter Anvince616072002-04-30 21:02:23 +0000845{
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000846 Blocks *b = &blocks;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000847
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000848 /* first, get to the end of the linked list */
849 while (b->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000850 b = b->next;
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000851 /* now allocate the requested chunk */
852 b->chunk = nasm_malloc(size);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000853
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000854 /* now allocate a new block for the next request */
855 b->next = nasm_malloc(sizeof(Blocks));
856 /* and initialize the contents of the new block */
857 b->next->next = NULL;
858 b->next->chunk = NULL;
859 return b->chunk;
H. Peter Anvince616072002-04-30 21:02:23 +0000860}
861
862/*
863 * this function deletes all managed blocks of memory
864 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000865static void delete_Blocks(void)
H. Peter Anvince616072002-04-30 21:02:23 +0000866{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000867 Blocks *a, *b = &blocks;
H. Peter Anvince616072002-04-30 21:02:23 +0000868
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000869 /*
870 * keep in mind that the first block, pointed to by blocks
871 * is a static and not dynamically allocated, so we don't
872 * free it.
873 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000874 while (b) {
875 if (b->chunk)
876 nasm_free(b->chunk);
877 a = b;
878 b = b->next;
879 if (a != &blocks)
880 nasm_free(a);
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000881 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000882}
H. Peter Anvin734b1882002-04-30 21:01:08 +0000883
884/*
885 * this function creates a new Token and passes a pointer to it
886 * back to the caller. It sets the type and text elements, and
887 * also the mac and next elements to NULL.
888 */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000889static Token *new_Token(Token * next, enum pp_token_type type, char *text, int txtlen)
H. Peter Anvin734b1882002-04-30 21:01:08 +0000890{
891 Token *t;
892 int i;
893
H. Peter Anvine2c80182005-01-15 22:15:51 +0000894 if (freeTokens == NULL) {
895 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
896 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
897 freeTokens[i].next = &freeTokens[i + 1];
898 freeTokens[i].next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000899 }
900 t = freeTokens;
901 freeTokens = t->next;
902 t->next = next;
903 t->mac = NULL;
904 t->type = type;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000905 if (type == TOK_WHITESPACE || text == NULL) {
906 t->text = NULL;
907 } else {
908 if (txtlen == 0)
909 txtlen = strlen(text);
910 t->text = nasm_malloc(1 + txtlen);
911 strncpy(t->text, text, txtlen);
912 t->text[txtlen] = '\0';
H. Peter Anvin734b1882002-04-30 21:01:08 +0000913 }
914 return t;
915}
916
H. Peter Anvine2c80182005-01-15 22:15:51 +0000917static Token *delete_Token(Token * t)
H. Peter Anvin734b1882002-04-30 21:01:08 +0000918{
919 Token *next = t->next;
920 nasm_free(t->text);
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000921 t->next = freeTokens;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000922 freeTokens = t;
923 return next;
924}
925
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000926/*
927 * Convert a line of tokens back into text.
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000928 * If expand_locals is not zero, identifiers of the form "%$*xxx"
929 * will be transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000930 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000931static char *detoken(Token * tlist, int expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000932{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000933 Token *t;
934 int len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000935 char *line, *p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000936
937 len = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000938 for (t = tlist; t; t = t->next) {
939 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000940 char *p = getenv(t->text + 2);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000941 nasm_free(t->text);
942 if (p)
943 t->text = nasm_strdup(p);
944 else
945 t->text = NULL;
946 }
947 /* Expand local macros here and not during preprocessing */
948 if (expand_locals &&
949 t->type == TOK_PREPROC_ID && t->text &&
950 t->text[0] == '%' && t->text[1] == '$') {
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700951 Context *ctx = get_ctx(t->text, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000952 if (ctx) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000953 char buffer[40];
954 char *p, *q = t->text + 2;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000955
H. Peter Anvine2c80182005-01-15 22:15:51 +0000956 q += strspn(q, "$");
Keith Kanios93f2e9a2007-04-14 00:10:59 +0000957 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000958 p = nasm_strcat(buffer, q);
959 nasm_free(t->text);
960 t->text = p;
961 }
962 }
963 if (t->type == TOK_WHITESPACE) {
964 len++;
965 } else if (t->text) {
966 len += strlen(t->text);
967 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000968 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000969 p = line = nasm_malloc(len + 1);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000970 for (t = tlist; t; t = t->next) {
971 if (t->type == TOK_WHITESPACE) {
972 *p = ' ';
973 p++;
974 *p = '\0';
975 } else if (t->text) {
976 strcpy(p, t->text);
977 p += strlen(p);
978 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000979 }
980 *p = '\0';
981 return line;
982}
983
984/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000985 * A scanner, suitable for use by the expression evaluator, which
986 * operates on a line of Tokens. Expects a pointer to a pointer to
987 * the first token in the line to be passed in as its private_data
988 * field.
989 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000990static int ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000991{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000992 Token **tlineptr = private_data;
993 Token *tline;
994
H. Peter Anvine2c80182005-01-15 22:15:51 +0000995 do {
996 tline = *tlineptr;
997 *tlineptr = tline ? tline->next : NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000998 }
999 while (tline && (tline->type == TOK_WHITESPACE ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001000 tline->type == TOK_COMMENT));
H. Peter Anvin76690a12002-04-30 20:52:49 +00001001
1002 if (!tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001003 return tokval->t_type = TOKEN_EOS;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001004
1005 if (tline->text[0] == '$' && !tline->text[1])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001006 return tokval->t_type = TOKEN_HERE;
H. Peter Anvin7cf897e2002-05-30 21:30:33 +00001007 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001008 return tokval->t_type = TOKEN_BASE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001009
H. Peter Anvine2c80182005-01-15 22:15:51 +00001010 if (tline->type == TOK_ID) {
1011 tokval->t_charptr = tline->text;
1012 if (tline->text[0] == '$') {
1013 tokval->t_charptr++;
1014 return tokval->t_type = TOKEN_ID;
1015 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001016
H. Peter Anvine2c80182005-01-15 22:15:51 +00001017 /*
1018 * This is the only special case we actually need to worry
1019 * about in this restricted context.
1020 */
1021 if (!nasm_stricmp(tline->text, "seg"))
1022 return tokval->t_type = TOKEN_SEG;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001023
H. Peter Anvine2c80182005-01-15 22:15:51 +00001024 return tokval->t_type = TOKEN_ID;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001025 }
1026
H. Peter Anvine2c80182005-01-15 22:15:51 +00001027 if (tline->type == TOK_NUMBER) {
H. Peter Anvin70055962007-10-11 00:05:31 -07001028 bool rn_error;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001029
H. Peter Anvine2c80182005-01-15 22:15:51 +00001030 tokval->t_integer = readnum(tline->text, &rn_error);
1031 if (rn_error)
1032 return tokval->t_type = TOKEN_ERRNUM;
1033 tokval->t_charptr = NULL;
1034 return tokval->t_type = TOKEN_NUM;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001035 }
1036
H. Peter Anvine2c80182005-01-15 22:15:51 +00001037 if (tline->type == TOK_STRING) {
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07001038 bool rn_warn;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001039 char q, *r;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001040 int l;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001041
H. Peter Anvine2c80182005-01-15 22:15:51 +00001042 r = tline->text;
1043 q = *r++;
1044 l = strlen(r);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001045
H. Peter Anvine2c80182005-01-15 22:15:51 +00001046 if (l == 0 || r[l - 1] != q)
1047 return tokval->t_type = TOKEN_ERRNUM;
1048 tokval->t_integer = readstrnum(r, l - 1, &rn_warn);
1049 if (rn_warn)
1050 error(ERR_WARNING | ERR_PASS1, "character constant too long");
1051 tokval->t_charptr = NULL;
1052 return tokval->t_type = TOKEN_NUM;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001053 }
1054
H. Peter Anvine2c80182005-01-15 22:15:51 +00001055 if (tline->type == TOK_OTHER) {
1056 if (!strcmp(tline->text, "<<"))
1057 return tokval->t_type = TOKEN_SHL;
1058 if (!strcmp(tline->text, ">>"))
1059 return tokval->t_type = TOKEN_SHR;
1060 if (!strcmp(tline->text, "//"))
1061 return tokval->t_type = TOKEN_SDIV;
1062 if (!strcmp(tline->text, "%%"))
1063 return tokval->t_type = TOKEN_SMOD;
1064 if (!strcmp(tline->text, "=="))
1065 return tokval->t_type = TOKEN_EQ;
1066 if (!strcmp(tline->text, "<>"))
1067 return tokval->t_type = TOKEN_NE;
1068 if (!strcmp(tline->text, "!="))
1069 return tokval->t_type = TOKEN_NE;
1070 if (!strcmp(tline->text, "<="))
1071 return tokval->t_type = TOKEN_LE;
1072 if (!strcmp(tline->text, ">="))
1073 return tokval->t_type = TOKEN_GE;
1074 if (!strcmp(tline->text, "&&"))
1075 return tokval->t_type = TOKEN_DBL_AND;
1076 if (!strcmp(tline->text, "^^"))
1077 return tokval->t_type = TOKEN_DBL_XOR;
1078 if (!strcmp(tline->text, "||"))
1079 return tokval->t_type = TOKEN_DBL_OR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001080 }
1081
1082 /*
1083 * We have no other options: just return the first character of
1084 * the token text.
1085 */
1086 return tokval->t_type = tline->text[0];
1087}
1088
1089/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001090 * Compare a string to the name of an existing macro; this is a
1091 * simple wrapper which calls either strcmp or nasm_stricmp
1092 * depending on the value of the `casesense' parameter.
1093 */
H. Peter Anvin70055962007-10-11 00:05:31 -07001094static int mstrcmp(char *p, char *q, bool casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001095{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001096 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001097}
1098
1099/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001100 * Return the Context structure associated with a %$ token. Return
1101 * NULL, having _already_ reported an error condition, if the
1102 * context stack isn't deep enough for the supplied number of $
1103 * signs.
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001104 * If all_contexts == true, contexts that enclose current are
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001105 * also scanned for such smacro, until it is found; if not -
1106 * only the context that directly results from the number of $'s
1107 * in variable's name.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001108 */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001109static Context *get_ctx(char *name, bool all_contexts)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001110{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001111 Context *ctx;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001112 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001113 int i;
1114
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001115 if (!name || name[0] != '%' || name[1] != '$')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001116 return NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001117
H. Peter Anvine2c80182005-01-15 22:15:51 +00001118 if (!cstk) {
1119 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1120 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001121 }
1122
H. Peter Anvine2c80182005-01-15 22:15:51 +00001123 for (i = strspn(name + 2, "$"), ctx = cstk; (i > 0) && ctx; i--) {
1124 ctx = ctx->next;
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00001125/* i--; Lino - 02/25/02 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001126 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001127 if (!ctx) {
1128 error(ERR_NONFATAL, "`%s': context stack is only"
1129 " %d level%s deep", name, i - 1, (i == 2 ? "" : "s"));
1130 return NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001131 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001132 if (!all_contexts)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001133 return ctx;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001134
H. Peter Anvine2c80182005-01-15 22:15:51 +00001135 do {
1136 /* Search for this smacro in found context */
1137 m = ctx->localmac;
1138 while (m) {
1139 if (!mstrcmp(m->name, name, m->casesense))
1140 return ctx;
1141 m = m->next;
1142 }
1143 ctx = ctx->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001144 }
1145 while (ctx);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001146 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001147}
1148
1149/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001150 * Open an include file. This routine must always return a valid
1151 * file pointer if it returns - it's responsible for throwing an
1152 * ERR_FATAL and bombing out completely if not. It should also try
1153 * the include path one by one until it finds the file or reaches
1154 * the end of the path.
1155 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001156static FILE *inc_fopen(char *file)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001157{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001158 FILE *fp;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001159 char *prefix = "", *combine;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001160 IncPath *ip = ipath;
H. Peter Anvin620515a2002-04-30 20:57:38 +00001161 static int namelen = 0;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001162 int len = strlen(file);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001163
H. Peter Anvine2c80182005-01-15 22:15:51 +00001164 while (1) {
1165 combine = nasm_malloc(strlen(prefix) + len + 1);
1166 strcpy(combine, prefix);
1167 strcat(combine, file);
1168 fp = fopen(combine, "r");
1169 if (pass == 0 && fp) {
1170 namelen += strlen(combine) + 1;
1171 if (namelen > 62) {
1172 printf(" \\\n ");
1173 namelen = 2;
1174 }
1175 printf(" %s", combine);
1176 }
1177 nasm_free(combine);
1178 if (fp)
1179 return fp;
1180 if (!ip)
1181 break;
1182 prefix = ip->path;
1183 ip = ip->next;
H. Peter Anvin37a321f2007-09-24 13:41:58 -07001184
1185 if (!prefix) {
1186 /* -MG given and file not found */
1187 if (pass == 0) {
1188 namelen += strlen(file) + 1;
1189 if (namelen > 62) {
1190 printf(" \\\n ");
1191 namelen = 2;
1192 }
1193 printf(" %s", file);
1194 }
1195 return NULL;
1196 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001197 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001198
H. Peter Anvin734b1882002-04-30 21:01:08 +00001199 error(ERR_FATAL, "unable to open include file `%s'", file);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001200 return NULL; /* never reached - placate compilers */
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001201}
1202
1203/*
H. Peter Anvin97a23472007-09-16 17:57:25 -07001204 * Search for a key in the hash index; adding it if necessary
1205 * (in which case we initialize the data pointer to NULL.)
1206 */
1207static void **
1208hash_findi_add(struct hash_table *hash, const char *str)
1209{
1210 struct hash_insert hi;
1211 void **r;
1212 char *strx;
1213
1214 r = hash_findi(hash, str, &hi);
1215 if (r)
1216 return r;
1217
1218 strx = nasm_strdup(str); /* Use a more efficient allocator here? */
1219 return hash_add(&hi, strx, NULL);
1220}
1221
1222/*
1223 * Like hash_findi, but returns the data element rather than a pointer
1224 * to it. Used only when not adding a new element, hence no third
1225 * argument.
1226 */
1227static void *
1228hash_findix(struct hash_table *hash, const char *str)
1229{
1230 void **p;
1231
1232 p = hash_findi(hash, str, NULL);
1233 return p ? *p : NULL;
1234}
1235
1236/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001237 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001238 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001239 * return true if _any_ single-line macro of that name is defined.
1240 * Otherwise, will return true if a single-line macro with either
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001241 * `nparam' or no parameters is defined.
1242 *
1243 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001244 * defined, or nparam is -1, the address of the definition structure
1245 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001246 * is NULL, no action will be taken regarding its contents, and no
1247 * error will occur.
1248 *
1249 * Note that this is also called with nparam zero to resolve
1250 * `ifdef'.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001251 *
1252 * If you already know which context macro belongs to, you can pass
1253 * the context pointer as first parameter; if you won't but name begins
1254 * with %$ the context will be automatically computed. If all_contexts
1255 * is true, macro will be searched in outer contexts as well.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001256 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00001257static int
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001258smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001259 int nocase)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001260{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001261 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001262
H. Peter Anvin97a23472007-09-16 17:57:25 -07001263 if (ctx) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001264 m = ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001265 } else if (name[0] == '%' && name[1] == '$') {
1266 if (cstk)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001267 ctx = get_ctx(name, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001268 if (!ctx)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001269 return false; /* got to return _something_ */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001270 m = ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001271 } else {
1272 m = (SMacro *) hash_findix(smacros, name);
1273 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001274
H. Peter Anvine2c80182005-01-15 22:15:51 +00001275 while (m) {
1276 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
1277 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam)) {
1278 if (defn) {
1279 if (nparam == m->nparam || nparam == -1)
1280 *defn = m;
1281 else
1282 *defn = NULL;
1283 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001284 return true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001285 }
1286 m = m->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001287 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001288
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001289 return false;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001290}
1291
1292/*
1293 * Count and mark off the parameters in a multi-line macro call.
1294 * This is called both from within the multi-line macro expansion
1295 * code, and also to mark off the default parameters when provided
1296 * in a %macro definition line.
1297 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001298static void count_mmac_params(Token * t, int *nparam, Token *** params)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001299{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001300 int paramsize, brace;
1301
1302 *nparam = paramsize = 0;
1303 *params = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001304 while (t) {
1305 if (*nparam >= paramsize) {
1306 paramsize += PARAM_DELTA;
1307 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1308 }
1309 skip_white_(t);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001310 brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001311 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001312 brace = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001313 (*params)[(*nparam)++] = t;
1314 while (tok_isnt_(t, brace ? "}" : ","))
1315 t = t->next;
1316 if (t) { /* got a comma/brace */
1317 t = t->next;
1318 if (brace) {
1319 /*
1320 * Now we've found the closing brace, look further
1321 * for the comma.
1322 */
1323 skip_white_(t);
1324 if (tok_isnt_(t, ",")) {
1325 error(ERR_NONFATAL,
1326 "braces do not enclose all of macro parameter");
1327 while (tok_isnt_(t, ","))
1328 t = t->next;
1329 }
1330 if (t)
1331 t = t->next; /* eat the comma */
1332 }
1333 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001334 }
1335}
1336
1337/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001338 * Determine whether one of the various `if' conditions is true or
1339 * not.
1340 *
1341 * We must free the tline we get passed.
1342 */
H. Peter Anvin70055962007-10-11 00:05:31 -07001343static bool if_condition(Token * tline, enum preproc_token ct)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001344{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001345 enum pp_conditional i = PP_COND(ct);
H. Peter Anvin70055962007-10-11 00:05:31 -07001346 bool j;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001347 Token *t, *tt, **tptr, *origline;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001348 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001349 expr *evalresult;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001350 enum pp_token_type needtype;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001351
1352 origline = tline;
1353
H. Peter Anvine2c80182005-01-15 22:15:51 +00001354 switch (i) {
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001355 case PPC_IFCTX:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001356 j = false; /* have we matched yet? */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001357 while (cstk && tline) {
1358 skip_white_(tline);
1359 if (!tline || tline->type != TOK_ID) {
1360 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001361 "`%s' expects context identifiers", pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001362 free_tlist(origline);
1363 return -1;
1364 }
1365 if (!nasm_stricmp(tline->text, cstk->name))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001366 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001367 tline = tline->next;
1368 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001369 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001370
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001371 case PPC_IFDEF:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001372 j = false; /* have we matched yet? */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001373 while (tline) {
1374 skip_white_(tline);
1375 if (!tline || (tline->type != TOK_ID &&
1376 (tline->type != TOK_PREPROC_ID ||
1377 tline->text[1] != '$'))) {
1378 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001379 "`%s' expects macro identifiers", pp_directives[ct]);
1380 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001381 }
1382 if (smacro_defined(NULL, tline->text, 0, NULL, 1))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001383 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001384 tline = tline->next;
1385 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001386 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001387
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001388 case PPC_IFIDN:
1389 case PPC_IFIDNI:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001390 tline = expand_smacro(tline);
1391 t = tt = tline;
1392 while (tok_isnt_(tt, ","))
1393 tt = tt->next;
1394 if (!tt) {
1395 error(ERR_NONFATAL,
1396 "`%s' expects two comma-separated arguments",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001397 pp_directives[ct]);
1398 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001399 }
1400 tt = tt->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001401 j = true; /* assume equality unless proved not */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001402 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1403 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1404 error(ERR_NONFATAL, "`%s': more than one comma on line",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001405 pp_directives[ct]);
1406 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001407 }
1408 if (t->type == TOK_WHITESPACE) {
1409 t = t->next;
1410 continue;
1411 }
1412 if (tt->type == TOK_WHITESPACE) {
1413 tt = tt->next;
1414 continue;
1415 }
1416 if (tt->type != t->type) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001417 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001418 break;
1419 }
1420 /* Unify surrounding quotes for strings */
1421 if (t->type == TOK_STRING) {
1422 tt->text[0] = t->text[0];
1423 tt->text[strlen(tt->text) - 1] = t->text[0];
1424 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001425 if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001426 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001427 break;
1428 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001429
H. Peter Anvine2c80182005-01-15 22:15:51 +00001430 t = t->next;
1431 tt = tt->next;
1432 }
1433 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001434 j = false; /* trailing gunk on one end or other */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001435 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001436
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001437 case PPC_IFMACRO:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001438 {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001439 bool found = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001440 MMacro searching, *mmac;
H. Peter Anvin65747262002-05-07 00:10:05 +00001441
H. Peter Anvine2c80182005-01-15 22:15:51 +00001442 tline = tline->next;
1443 skip_white_(tline);
1444 tline = expand_id(tline);
1445 if (!tok_type_(tline, TOK_ID)) {
1446 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001447 "`%s' expects a macro name", pp_directives[ct]);
1448 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001449 }
1450 searching.name = nasm_strdup(tline->text);
1451 searching.casesense = (i == PP_MACRO);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001452 searching.plus = false;
1453 searching.nolist = false;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07001454 searching.in_progress = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001455 searching.rep_nest = NULL;
1456 searching.nparam_min = 0;
1457 searching.nparam_max = INT_MAX;
1458 tline = expand_smacro(tline->next);
1459 skip_white_(tline);
1460 if (!tline) {
1461 } else if (!tok_type_(tline, TOK_NUMBER)) {
1462 error(ERR_NONFATAL,
1463 "`%s' expects a parameter count or nothing",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001464 pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001465 } else {
1466 searching.nparam_min = searching.nparam_max =
1467 readnum(tline->text, &j);
1468 if (j)
1469 error(ERR_NONFATAL,
1470 "unable to parse parameter count `%s'",
1471 tline->text);
1472 }
1473 if (tline && tok_is_(tline->next, "-")) {
1474 tline = tline->next->next;
1475 if (tok_is_(tline, "*"))
1476 searching.nparam_max = INT_MAX;
1477 else if (!tok_type_(tline, TOK_NUMBER))
1478 error(ERR_NONFATAL,
1479 "`%s' expects a parameter count after `-'",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001480 pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001481 else {
1482 searching.nparam_max = readnum(tline->text, &j);
1483 if (j)
1484 error(ERR_NONFATAL,
1485 "unable to parse parameter count `%s'",
1486 tline->text);
1487 if (searching.nparam_min > searching.nparam_max)
1488 error(ERR_NONFATAL,
1489 "minimum parameter count exceeds maximum");
1490 }
1491 }
1492 if (tline && tok_is_(tline->next, "+")) {
1493 tline = tline->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001494 searching.plus = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001495 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07001496 mmac = (MMacro *) hash_findix(mmacros, searching.name);
1497 while (mmac) {
1498 if (!strcmp(mmac->name, searching.name) &&
1499 (mmac->nparam_min <= searching.nparam_max
1500 || searching.plus)
1501 && (searching.nparam_min <= mmac->nparam_max
1502 || mmac->plus)) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001503 found = true;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001504 break;
1505 }
1506 mmac = mmac->next;
1507 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001508 nasm_free(searching.name);
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001509 j = found;
1510 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001511 }
H. Peter Anvin65747262002-05-07 00:10:05 +00001512
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001513 case PPC_IFID:
1514 needtype = TOK_ID;
1515 goto iftype;
1516 case PPC_IFNUM:
1517 needtype = TOK_NUMBER;
1518 goto iftype;
1519 case PPC_IFSTR:
1520 needtype = TOK_STRING;
1521 goto iftype;
1522
1523 iftype:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001524 tline = expand_smacro(tline);
1525 t = tline;
1526 while (tok_type_(t, TOK_WHITESPACE))
1527 t = t->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001528 j = false; /* placate optimiser */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001529 if (t)
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001530 j = t->type == needtype;
1531 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001532
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001533 case PPC_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001534 t = tline = expand_smacro(tline);
1535 tptr = &t;
1536 tokval.t_type = TOKEN_INVALID;
1537 evalresult = evaluate(ppscan, tptr, &tokval,
1538 NULL, pass | CRITICAL, error, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001539 if (!evalresult)
1540 return -1;
1541 if (tokval.t_type)
1542 error(ERR_WARNING,
1543 "trailing garbage after expression ignored");
1544 if (!is_simple(evalresult)) {
1545 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001546 "non-constant value given to `%s'", pp_directives[ct]);
1547 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001548 }
Chuck Crayne60ae75d2007-05-02 01:59:16 +00001549 j = reloc_value(evalresult) != 0;
Chuck Crayne60ae75d2007-05-02 01:59:16 +00001550 return j;
H. Peter Anvin95e28822007-09-12 04:20:08 +00001551
H. Peter Anvine2c80182005-01-15 22:15:51 +00001552 default:
1553 error(ERR_FATAL,
1554 "preprocessor directive `%s' not yet implemented",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001555 pp_directives[ct]);
1556 goto fail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001557 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001558
1559 free_tlist(origline);
1560 return j ^ PP_NEGATIVE(ct);
1561
1562fail:
1563 free_tlist(origline);
1564 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001565}
1566
1567/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001568 * Expand macros in a string. Used in %error and %include directives.
Keith Kaniosb7a89542007-04-12 02:40:54 +00001569 * First tokenize the string, apply "expand_smacro" and then de-tokenize back.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001570 * The returned variable should ALWAYS be freed after usage.
1571 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001572void expand_macros_in_string(char **p)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001573{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001574 Token *line = tokenize(*p);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001575 line = expand_smacro(line);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001576 *p = detoken(line, false);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001577}
1578
Ed Beroset3ab3f412002-06-11 03:31:49 +00001579/**
1580 * find and process preprocessor directive in passed line
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001581 * Find out if a line contains a preprocessor directive, and deal
1582 * with it if so.
1583 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00001584 * If a directive _is_ found, it is the responsibility of this routine
1585 * (and not the caller) to free_tlist() the line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001586 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00001587 * @param tline a pointer to the current tokeninzed line linked list
1588 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001589 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001590 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001591static int do_directive(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001592{
H. Peter Anvin4169a472007-09-12 01:29:43 +00001593 enum preproc_token i;
1594 int j;
H. Peter Anvin70055962007-10-11 00:05:31 -07001595 bool err;
1596 int nparam;
1597 bool nolist;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -07001598 int k, m;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001599 int offset;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001600 char *p, *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001601 Include *inc;
1602 Context *ctx;
1603 Cond *cond;
1604 SMacro *smac, **smhead;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001605 MMacro *mmac, **mmhead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001606 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
1607 Line *l;
1608 struct tokenval tokval;
1609 expr *evalresult;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001610 MMacro *tmp_defining; /* Used when manipulating rep_nest */
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07001611 int64_t count;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001612
1613 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001614
H. Peter Anvineba20a72002-04-30 20:53:55 +00001615 skip_white_(tline);
1616 if (!tok_type_(tline, TOK_PREPROC_ID) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001617 (tline->text[1] == '%' || tline->text[1] == '$'
1618 || tline->text[1] == '!'))
1619 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001620
H. Peter Anvin4169a472007-09-12 01:29:43 +00001621 i = pp_token_hash(tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001622
1623 /*
1624 * If we're in a non-emitting branch of a condition construct,
H. Peter Anvin76690a12002-04-30 20:52:49 +00001625 * or walking to the end of an already terminated %rep block,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001626 * we should ignore all directives except for condition
1627 * directives.
1628 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001629 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001630 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
1631 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001632 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001633
1634 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001635 * If we're defining a macro or reading a %rep block, we should
1636 * ignore all directives except for %macro/%imacro (which
1637 * generate an error), %endm/%endmacro, and (only if we're in a
H. Peter Anvineba20a72002-04-30 20:53:55 +00001638 * %rep block) %endrep. If we're in a %rep block, another %rep
1639 * causes an error, so should be let through.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001640 */
1641 if (defining && i != PP_MACRO && i != PP_IMACRO &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001642 i != PP_ENDMACRO && i != PP_ENDM &&
1643 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
1644 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001645 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001646
H. Peter Anvin4169a472007-09-12 01:29:43 +00001647 switch (i) {
1648 case PP_INVALID:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001649 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
1650 tline->text);
1651 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001652
H. Peter Anvine2c80182005-01-15 22:15:51 +00001653 case PP_STACKSIZE:
1654 /* Directive to tell NASM what the default stack size is. The
1655 * default is for a 16-bit stack, and this can be overriden with
1656 * %stacksize large.
1657 * the following form:
1658 *
1659 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1660 */
1661 tline = tline->next;
1662 if (tline && tline->type == TOK_WHITESPACE)
1663 tline = tline->next;
1664 if (!tline || tline->type != TOK_ID) {
1665 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
1666 free_tlist(origline);
1667 return DIRECTIVE_FOUND;
1668 }
1669 if (nasm_stricmp(tline->text, "flat") == 0) {
1670 /* All subsequent ARG directives are for a 32-bit stack */
1671 StackSize = 4;
1672 StackPointer = "ebp";
1673 ArgOffset = 8;
1674 LocalOffset = 4;
1675 } else if (nasm_stricmp(tline->text, "large") == 0) {
1676 /* All subsequent ARG directives are for a 16-bit stack,
1677 * far function call.
1678 */
1679 StackSize = 2;
1680 StackPointer = "bp";
1681 ArgOffset = 4;
1682 LocalOffset = 2;
1683 } else if (nasm_stricmp(tline->text, "small") == 0) {
1684 /* All subsequent ARG directives are for a 16-bit stack,
1685 * far function call. We don't support near functions.
1686 */
1687 StackSize = 2;
1688 StackPointer = "bp";
1689 ArgOffset = 6;
1690 LocalOffset = 2;
1691 } else {
1692 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
1693 free_tlist(origline);
1694 return DIRECTIVE_FOUND;
1695 }
1696 free_tlist(origline);
1697 return DIRECTIVE_FOUND;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001698
H. Peter Anvine2c80182005-01-15 22:15:51 +00001699 case PP_ARG:
1700 /* TASM like ARG directive to define arguments to functions, in
1701 * the following form:
1702 *
1703 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1704 */
1705 offset = ArgOffset;
1706 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001707 char *arg, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00001708 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001709
H. Peter Anvine2c80182005-01-15 22:15:51 +00001710 /* Find the argument name */
1711 tline = tline->next;
1712 if (tline && tline->type == TOK_WHITESPACE)
1713 tline = tline->next;
1714 if (!tline || tline->type != TOK_ID) {
1715 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
1716 free_tlist(origline);
1717 return DIRECTIVE_FOUND;
1718 }
1719 arg = tline->text;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001720
H. Peter Anvine2c80182005-01-15 22:15:51 +00001721 /* Find the argument size type */
1722 tline = tline->next;
1723 if (!tline || tline->type != TOK_OTHER
1724 || tline->text[0] != ':') {
1725 error(ERR_NONFATAL,
1726 "Syntax error processing `%%arg' directive");
1727 free_tlist(origline);
1728 return DIRECTIVE_FOUND;
1729 }
1730 tline = tline->next;
1731 if (!tline || tline->type != TOK_ID) {
1732 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
1733 free_tlist(origline);
1734 return DIRECTIVE_FOUND;
1735 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001736
H. Peter Anvine2c80182005-01-15 22:15:51 +00001737 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001738 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001739 tt = expand_smacro(tt);
1740 if (nasm_stricmp(tt->text, "byte") == 0) {
1741 size = MAX(StackSize, 1);
1742 } else if (nasm_stricmp(tt->text, "word") == 0) {
1743 size = MAX(StackSize, 2);
1744 } else if (nasm_stricmp(tt->text, "dword") == 0) {
1745 size = MAX(StackSize, 4);
1746 } else if (nasm_stricmp(tt->text, "qword") == 0) {
1747 size = MAX(StackSize, 8);
1748 } else if (nasm_stricmp(tt->text, "tword") == 0) {
1749 size = MAX(StackSize, 10);
1750 } else {
1751 error(ERR_NONFATAL,
1752 "Invalid size type for `%%arg' missing directive");
1753 free_tlist(tt);
1754 free_tlist(origline);
1755 return DIRECTIVE_FOUND;
1756 }
1757 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001758
H. Peter Anvine2c80182005-01-15 22:15:51 +00001759 /* Now define the macro for the argument */
1760 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
1761 arg, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001762 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001763 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001764
H. Peter Anvine2c80182005-01-15 22:15:51 +00001765 /* Move to the next argument in the list */
1766 tline = tline->next;
1767 if (tline && tline->type == TOK_WHITESPACE)
1768 tline = tline->next;
1769 }
1770 while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
1771 free_tlist(origline);
1772 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001773
H. Peter Anvine2c80182005-01-15 22:15:51 +00001774 case PP_LOCAL:
1775 /* TASM like LOCAL directive to define local variables for a
1776 * function, in the following form:
1777 *
1778 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
1779 *
1780 * The '= LocalSize' at the end is ignored by NASM, but is
1781 * required by TASM to define the local parameter size (and used
1782 * by the TASM macro package).
1783 */
1784 offset = LocalOffset;
1785 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001786 char *local, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00001787 int size = StackSize;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001788
H. Peter Anvine2c80182005-01-15 22:15:51 +00001789 /* Find the argument name */
1790 tline = tline->next;
1791 if (tline && tline->type == TOK_WHITESPACE)
1792 tline = tline->next;
1793 if (!tline || tline->type != TOK_ID) {
1794 error(ERR_NONFATAL,
1795 "`%%local' missing argument parameter");
1796 free_tlist(origline);
1797 return DIRECTIVE_FOUND;
1798 }
1799 local = tline->text;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001800
H. Peter Anvine2c80182005-01-15 22:15:51 +00001801 /* Find the argument size type */
1802 tline = tline->next;
1803 if (!tline || tline->type != TOK_OTHER
1804 || tline->text[0] != ':') {
1805 error(ERR_NONFATAL,
1806 "Syntax error processing `%%local' directive");
1807 free_tlist(origline);
1808 return DIRECTIVE_FOUND;
1809 }
1810 tline = tline->next;
1811 if (!tline || tline->type != TOK_ID) {
1812 error(ERR_NONFATAL,
1813 "`%%local' missing size type parameter");
1814 free_tlist(origline);
1815 return DIRECTIVE_FOUND;
1816 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001817
H. Peter Anvine2c80182005-01-15 22:15:51 +00001818 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001819 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001820 tt = expand_smacro(tt);
1821 if (nasm_stricmp(tt->text, "byte") == 0) {
1822 size = MAX(StackSize, 1);
1823 } else if (nasm_stricmp(tt->text, "word") == 0) {
1824 size = MAX(StackSize, 2);
1825 } else if (nasm_stricmp(tt->text, "dword") == 0) {
1826 size = MAX(StackSize, 4);
1827 } else if (nasm_stricmp(tt->text, "qword") == 0) {
1828 size = MAX(StackSize, 8);
1829 } else if (nasm_stricmp(tt->text, "tword") == 0) {
1830 size = MAX(StackSize, 10);
1831 } else {
1832 error(ERR_NONFATAL,
1833 "Invalid size type for `%%local' missing directive");
1834 free_tlist(tt);
1835 free_tlist(origline);
1836 return DIRECTIVE_FOUND;
1837 }
1838 free_tlist(tt);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001839
H. Peter Anvine2c80182005-01-15 22:15:51 +00001840 /* Now define the macro for the argument */
1841 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
1842 local, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001843 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001844 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001845
H. Peter Anvine2c80182005-01-15 22:15:51 +00001846 /* Now define the assign to setup the enter_c macro correctly */
1847 snprintf(directive, sizeof(directive),
1848 "%%assign %%$localsize %%$localsize+%d", size);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001849 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001850
H. Peter Anvine2c80182005-01-15 22:15:51 +00001851 /* Move to the next argument in the list */
1852 tline = tline->next;
1853 if (tline && tline->type == TOK_WHITESPACE)
1854 tline = tline->next;
1855 }
1856 while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
1857 free_tlist(origline);
1858 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001859
H. Peter Anvine2c80182005-01-15 22:15:51 +00001860 case PP_CLEAR:
1861 if (tline->next)
1862 error(ERR_WARNING, "trailing garbage after `%%clear' ignored");
H. Peter Anvin97a23472007-09-16 17:57:25 -07001863 free_macros();
1864 init_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001865 free_tlist(origline);
1866 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001867
H. Peter Anvine2c80182005-01-15 22:15:51 +00001868 case PP_INCLUDE:
1869 tline = tline->next;
1870 skip_white_(tline);
1871 if (!tline || (tline->type != TOK_STRING &&
1872 tline->type != TOK_INTERNAL_STRING)) {
1873 error(ERR_NONFATAL, "`%%include' expects a file name");
1874 free_tlist(origline);
1875 return DIRECTIVE_FOUND; /* but we did _something_ */
1876 }
1877 if (tline->next)
1878 error(ERR_WARNING,
1879 "trailing garbage after `%%include' ignored");
1880 if (tline->type != TOK_INTERNAL_STRING) {
1881 p = tline->text + 1; /* point past the quote to the name */
1882 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
1883 } else
1884 p = tline->text; /* internal_string is easier */
1885 expand_macros_in_string(&p);
1886 inc = nasm_malloc(sizeof(Include));
1887 inc->next = istk;
1888 inc->conds = NULL;
1889 inc->fp = inc_fopen(p);
H. Peter Anvin37a321f2007-09-24 13:41:58 -07001890 if (!inc->fp && pass == 0) {
1891 /* -MG given but file not found */
1892 nasm_free(inc);
1893 } else {
1894 inc->fname = src_set_fname(p);
1895 inc->lineno = src_set_linnum(0);
1896 inc->lineinc = 1;
1897 inc->expansion = NULL;
1898 inc->mstk = NULL;
1899 istk = inc;
1900 list->uplevel(LIST_INCLUDE);
1901 }
1902 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001903 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001904
H. Peter Anvine2c80182005-01-15 22:15:51 +00001905 case PP_PUSH:
1906 tline = tline->next;
1907 skip_white_(tline);
1908 tline = expand_id(tline);
1909 if (!tok_type_(tline, TOK_ID)) {
1910 error(ERR_NONFATAL, "`%%push' expects a context identifier");
1911 free_tlist(origline);
1912 return DIRECTIVE_FOUND; /* but we did _something_ */
1913 }
1914 if (tline->next)
1915 error(ERR_WARNING, "trailing garbage after `%%push' ignored");
1916 ctx = nasm_malloc(sizeof(Context));
1917 ctx->next = cstk;
1918 ctx->localmac = NULL;
1919 ctx->name = nasm_strdup(tline->text);
1920 ctx->number = unique++;
1921 cstk = ctx;
1922 free_tlist(origline);
1923 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001924
H. Peter Anvine2c80182005-01-15 22:15:51 +00001925 case PP_REPL:
1926 tline = tline->next;
1927 skip_white_(tline);
1928 tline = expand_id(tline);
1929 if (!tok_type_(tline, TOK_ID)) {
1930 error(ERR_NONFATAL, "`%%repl' expects a context identifier");
1931 free_tlist(origline);
1932 return DIRECTIVE_FOUND; /* but we did _something_ */
1933 }
1934 if (tline->next)
1935 error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
1936 if (!cstk)
1937 error(ERR_NONFATAL, "`%%repl': context stack is empty");
1938 else {
1939 nasm_free(cstk->name);
1940 cstk->name = nasm_strdup(tline->text);
1941 }
1942 free_tlist(origline);
1943 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001944
H. Peter Anvine2c80182005-01-15 22:15:51 +00001945 case PP_POP:
1946 if (tline->next)
1947 error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
1948 if (!cstk)
1949 error(ERR_NONFATAL, "`%%pop': context stack is already empty");
1950 else
1951 ctx_pop();
1952 free_tlist(origline);
1953 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001954
H. Peter Anvine2c80182005-01-15 22:15:51 +00001955 case PP_ERROR:
1956 tline->next = expand_smacro(tline->next);
1957 tline = tline->next;
1958 skip_white_(tline);
1959 if (tok_type_(tline, TOK_STRING)) {
1960 p = tline->text + 1; /* point past the quote to the name */
1961 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
1962 expand_macros_in_string(&p);
1963 error(ERR_NONFATAL, "%s", p);
1964 nasm_free(p);
1965 } else {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001966 p = detoken(tline, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001967 error(ERR_WARNING, "%s", p);
1968 nasm_free(p);
1969 }
1970 free_tlist(origline);
1971 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001972
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001973 CASE_PP_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001974 if (istk->conds && !emitting(istk->conds->state))
1975 j = COND_NEVER;
1976 else {
1977 j = if_condition(tline->next, i);
1978 tline->next = NULL; /* it got freed */
1979 free_tlist(origline);
1980 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
1981 }
1982 cond = nasm_malloc(sizeof(Cond));
1983 cond->next = istk->conds;
1984 cond->state = j;
1985 istk->conds = cond;
1986 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001987
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001988 CASE_PP_ELIF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001989 if (!istk->conds)
H. Peter Anvin4169a472007-09-12 01:29:43 +00001990 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001991 if (emitting(istk->conds->state)
1992 || istk->conds->state == COND_NEVER)
1993 istk->conds->state = COND_NEVER;
1994 else {
1995 /*
1996 * IMPORTANT: In the case of %if, we will already have
1997 * called expand_mmac_params(); however, if we're
1998 * processing an %elif we must have been in a
1999 * non-emitting mode, which would have inhibited
2000 * the normal invocation of expand_mmac_params(). Therefore,
2001 * we have to do it explicitly here.
2002 */
2003 j = if_condition(expand_mmac_params(tline->next), i);
2004 tline->next = NULL; /* it got freed */
2005 free_tlist(origline);
2006 istk->conds->state =
2007 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2008 }
2009 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002010
H. Peter Anvine2c80182005-01-15 22:15:51 +00002011 case PP_ELSE:
2012 if (tline->next)
2013 error(ERR_WARNING, "trailing garbage after `%%else' ignored");
2014 if (!istk->conds)
2015 error(ERR_FATAL, "`%%else': no matching `%%if'");
2016 if (emitting(istk->conds->state)
2017 || istk->conds->state == COND_NEVER)
2018 istk->conds->state = COND_ELSE_FALSE;
2019 else
2020 istk->conds->state = COND_ELSE_TRUE;
2021 free_tlist(origline);
2022 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002023
H. Peter Anvine2c80182005-01-15 22:15:51 +00002024 case PP_ENDIF:
2025 if (tline->next)
2026 error(ERR_WARNING, "trailing garbage after `%%endif' ignored");
2027 if (!istk->conds)
2028 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2029 cond = istk->conds;
2030 istk->conds = cond->next;
2031 nasm_free(cond);
2032 free_tlist(origline);
2033 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002034
H. Peter Anvine2c80182005-01-15 22:15:51 +00002035 case PP_MACRO:
2036 case PP_IMACRO:
2037 if (defining)
2038 error(ERR_FATAL,
2039 "`%%%smacro': already defining a macro",
2040 (i == PP_IMACRO ? "i" : ""));
2041 tline = tline->next;
2042 skip_white_(tline);
2043 tline = expand_id(tline);
2044 if (!tok_type_(tline, TOK_ID)) {
2045 error(ERR_NONFATAL,
2046 "`%%%smacro' expects a macro name",
2047 (i == PP_IMACRO ? "i" : ""));
2048 return DIRECTIVE_FOUND;
2049 }
2050 defining = nasm_malloc(sizeof(MMacro));
2051 defining->name = nasm_strdup(tline->text);
2052 defining->casesense = (i == PP_MACRO);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002053 defining->plus = false;
2054 defining->nolist = false;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002055 defining->in_progress = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002056 defining->rep_nest = NULL;
2057 tline = expand_smacro(tline->next);
2058 skip_white_(tline);
2059 if (!tok_type_(tline, TOK_NUMBER)) {
2060 error(ERR_NONFATAL,
2061 "`%%%smacro' expects a parameter count",
2062 (i == PP_IMACRO ? "i" : ""));
2063 defining->nparam_min = defining->nparam_max = 0;
2064 } else {
2065 defining->nparam_min = defining->nparam_max =
H. Peter Anvin70055962007-10-11 00:05:31 -07002066 readnum(tline->text, &err);
2067 if (err)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002068 error(ERR_NONFATAL,
2069 "unable to parse parameter count `%s'", tline->text);
2070 }
2071 if (tline && tok_is_(tline->next, "-")) {
2072 tline = tline->next->next;
2073 if (tok_is_(tline, "*"))
2074 defining->nparam_max = INT_MAX;
2075 else if (!tok_type_(tline, TOK_NUMBER))
2076 error(ERR_NONFATAL,
2077 "`%%%smacro' expects a parameter count after `-'",
2078 (i == PP_IMACRO ? "i" : ""));
2079 else {
H. Peter Anvin70055962007-10-11 00:05:31 -07002080 defining->nparam_max = readnum(tline->text, &err);
2081 if (err)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002082 error(ERR_NONFATAL,
2083 "unable to parse parameter count `%s'",
2084 tline->text);
2085 if (defining->nparam_min > defining->nparam_max)
2086 error(ERR_NONFATAL,
2087 "minimum parameter count exceeds maximum");
2088 }
2089 }
2090 if (tline && tok_is_(tline->next, "+")) {
2091 tline = tline->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002092 defining->plus = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002093 }
2094 if (tline && tok_type_(tline->next, TOK_ID) &&
2095 !nasm_stricmp(tline->next->text, ".nolist")) {
2096 tline = tline->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002097 defining->nolist = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002098 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07002099 mmac = (MMacro *) hash_findix(mmacros, defining->name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002100 while (mmac) {
2101 if (!strcmp(mmac->name, defining->name) &&
2102 (mmac->nparam_min <= defining->nparam_max
2103 || defining->plus)
2104 && (defining->nparam_min <= mmac->nparam_max
2105 || mmac->plus)) {
2106 error(ERR_WARNING,
2107 "redefining multi-line macro `%s'", defining->name);
2108 break;
2109 }
2110 mmac = mmac->next;
2111 }
2112 /*
2113 * Handle default parameters.
2114 */
2115 if (tline && tline->next) {
2116 defining->dlist = tline->next;
2117 tline->next = NULL;
2118 count_mmac_params(defining->dlist, &defining->ndefs,
2119 &defining->defaults);
2120 } else {
2121 defining->dlist = NULL;
2122 defining->defaults = NULL;
2123 }
2124 defining->expansion = NULL;
2125 free_tlist(origline);
2126 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002127
H. Peter Anvine2c80182005-01-15 22:15:51 +00002128 case PP_ENDM:
2129 case PP_ENDMACRO:
2130 if (!defining) {
2131 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2132 return DIRECTIVE_FOUND;
2133 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07002134 mmhead = (MMacro **) hash_findi_add(mmacros, defining->name);
2135 defining->next = *mmhead;
2136 *mmhead = defining;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002137 defining = NULL;
2138 free_tlist(origline);
2139 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002140
H. Peter Anvine2c80182005-01-15 22:15:51 +00002141 case PP_ROTATE:
2142 if (tline->next && tline->next->type == TOK_WHITESPACE)
2143 tline = tline->next;
2144 if (tline->next == NULL) {
2145 free_tlist(origline);
2146 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2147 return DIRECTIVE_FOUND;
2148 }
2149 t = expand_smacro(tline->next);
2150 tline->next = NULL;
2151 free_tlist(origline);
2152 tline = t;
2153 tptr = &t;
2154 tokval.t_type = TOKEN_INVALID;
2155 evalresult =
2156 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2157 free_tlist(tline);
2158 if (!evalresult)
2159 return DIRECTIVE_FOUND;
2160 if (tokval.t_type)
2161 error(ERR_WARNING,
2162 "trailing garbage after expression ignored");
2163 if (!is_simple(evalresult)) {
2164 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2165 return DIRECTIVE_FOUND;
2166 }
2167 mmac = istk->mstk;
2168 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2169 mmac = mmac->next_active;
2170 if (!mmac) {
2171 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2172 } else if (mmac->nparam == 0) {
2173 error(ERR_NONFATAL,
2174 "`%%rotate' invoked within macro without parameters");
2175 } else {
H. Peter Anvin25a99342007-09-22 17:45:45 -07002176 int rotate = mmac->rotate + reloc_value(evalresult);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002177
H. Peter Anvin25a99342007-09-22 17:45:45 -07002178 rotate %= (int)mmac->nparam;
2179 if (rotate < 0)
2180 rotate += mmac->nparam;
2181
2182 mmac->rotate = rotate;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002183 }
2184 return DIRECTIVE_FOUND;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002185
H. Peter Anvine2c80182005-01-15 22:15:51 +00002186 case PP_REP:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002187 nolist = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002188 do {
2189 tline = tline->next;
2190 } while (tok_type_(tline, TOK_WHITESPACE));
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002191
H. Peter Anvine2c80182005-01-15 22:15:51 +00002192 if (tok_type_(tline, TOK_ID) &&
2193 nasm_stricmp(tline->text, ".nolist") == 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002194 nolist = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002195 do {
2196 tline = tline->next;
2197 } while (tok_type_(tline, TOK_WHITESPACE));
2198 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002199
H. Peter Anvine2c80182005-01-15 22:15:51 +00002200 if (tline) {
2201 t = expand_smacro(tline);
2202 tptr = &t;
2203 tokval.t_type = TOKEN_INVALID;
2204 evalresult =
2205 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2206 if (!evalresult) {
2207 free_tlist(origline);
2208 return DIRECTIVE_FOUND;
2209 }
2210 if (tokval.t_type)
2211 error(ERR_WARNING,
2212 "trailing garbage after expression ignored");
2213 if (!is_simple(evalresult)) {
2214 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2215 return DIRECTIVE_FOUND;
2216 }
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002217 count = reloc_value(evalresult) + 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002218 } else {
2219 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002220 count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002221 }
2222 free_tlist(origline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002223
H. Peter Anvine2c80182005-01-15 22:15:51 +00002224 tmp_defining = defining;
2225 defining = nasm_malloc(sizeof(MMacro));
2226 defining->name = NULL; /* flags this macro as a %rep block */
H. Peter Anvin70055962007-10-11 00:05:31 -07002227 defining->casesense = false;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002228 defining->plus = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002229 defining->nolist = nolist;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002230 defining->in_progress = count;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002231 defining->nparam_min = defining->nparam_max = 0;
2232 defining->defaults = NULL;
2233 defining->dlist = NULL;
2234 defining->expansion = NULL;
2235 defining->next_active = istk->mstk;
2236 defining->rep_nest = tmp_defining;
2237 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002238
H. Peter Anvine2c80182005-01-15 22:15:51 +00002239 case PP_ENDREP:
2240 if (!defining || defining->name) {
2241 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2242 return DIRECTIVE_FOUND;
2243 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002244
H. Peter Anvine2c80182005-01-15 22:15:51 +00002245 /*
2246 * Now we have a "macro" defined - although it has no name
2247 * and we won't be entering it in the hash tables - we must
2248 * push a macro-end marker for it on to istk->expansion.
2249 * After that, it will take care of propagating itself (a
2250 * macro-end marker line for a macro which is really a %rep
2251 * block will cause the macro to be re-expanded, complete
2252 * with another macro-end marker to ensure the process
2253 * continues) until the whole expansion is forcibly removed
2254 * from istk->expansion by a %exitrep.
2255 */
2256 l = nasm_malloc(sizeof(Line));
2257 l->next = istk->expansion;
2258 l->finishes = defining;
2259 l->first = NULL;
2260 istk->expansion = l;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002261
H. Peter Anvine2c80182005-01-15 22:15:51 +00002262 istk->mstk = defining;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002263
H. Peter Anvine2c80182005-01-15 22:15:51 +00002264 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2265 tmp_defining = defining;
2266 defining = defining->rep_nest;
2267 free_tlist(origline);
2268 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002269
H. Peter Anvine2c80182005-01-15 22:15:51 +00002270 case PP_EXITREP:
2271 /*
2272 * We must search along istk->expansion until we hit a
2273 * macro-end marker for a macro with no name. Then we set
2274 * its `in_progress' flag to 0.
2275 */
2276 for (l = istk->expansion; l; l = l->next)
2277 if (l->finishes && !l->finishes->name)
2278 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002279
H. Peter Anvine2c80182005-01-15 22:15:51 +00002280 if (l)
2281 l->finishes->in_progress = 0;
2282 else
2283 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2284 free_tlist(origline);
2285 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002286
H. Peter Anvine2c80182005-01-15 22:15:51 +00002287 case PP_XDEFINE:
2288 case PP_IXDEFINE:
2289 case PP_DEFINE:
2290 case PP_IDEFINE:
2291 tline = tline->next;
2292 skip_white_(tline);
2293 tline = expand_id(tline);
2294 if (!tline || (tline->type != TOK_ID &&
2295 (tline->type != TOK_PREPROC_ID ||
2296 tline->text[1] != '$'))) {
2297 error(ERR_NONFATAL,
2298 "`%%%s%sdefine' expects a macro identifier",
2299 ((i == PP_IDEFINE || i == PP_IXDEFINE) ? "i" : ""),
2300 ((i == PP_XDEFINE || i == PP_IXDEFINE) ? "x" : ""));
2301 free_tlist(origline);
2302 return DIRECTIVE_FOUND;
2303 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002304
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002305 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002306
H. Peter Anvine2c80182005-01-15 22:15:51 +00002307 mname = tline->text;
2308 last = tline;
2309 param_start = tline = tline->next;
2310 nparam = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002311
H. Peter Anvine2c80182005-01-15 22:15:51 +00002312 /* Expand the macro definition now for %xdefine and %ixdefine */
2313 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2314 tline = expand_smacro(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002315
H. Peter Anvine2c80182005-01-15 22:15:51 +00002316 if (tok_is_(tline, "(")) {
2317 /*
2318 * This macro has parameters.
2319 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002320
H. Peter Anvine2c80182005-01-15 22:15:51 +00002321 tline = tline->next;
2322 while (1) {
2323 skip_white_(tline);
2324 if (!tline) {
2325 error(ERR_NONFATAL, "parameter identifier expected");
2326 free_tlist(origline);
2327 return DIRECTIVE_FOUND;
2328 }
2329 if (tline->type != TOK_ID) {
2330 error(ERR_NONFATAL,
2331 "`%s': parameter identifier expected",
2332 tline->text);
2333 free_tlist(origline);
2334 return DIRECTIVE_FOUND;
2335 }
2336 tline->type = TOK_SMAC_PARAM + nparam++;
2337 tline = tline->next;
2338 skip_white_(tline);
2339 if (tok_is_(tline, ",")) {
2340 tline = tline->next;
2341 continue;
2342 }
2343 if (!tok_is_(tline, ")")) {
2344 error(ERR_NONFATAL,
2345 "`)' expected to terminate macro template");
2346 free_tlist(origline);
2347 return DIRECTIVE_FOUND;
2348 }
2349 break;
2350 }
2351 last = tline;
2352 tline = tline->next;
2353 }
2354 if (tok_type_(tline, TOK_WHITESPACE))
2355 last = tline, tline = tline->next;
2356 macro_start = NULL;
2357 last->next = NULL;
2358 t = tline;
2359 while (t) {
2360 if (t->type == TOK_ID) {
2361 for (tt = param_start; tt; tt = tt->next)
2362 if (tt->type >= TOK_SMAC_PARAM &&
2363 !strcmp(tt->text, t->text))
2364 t->type = tt->type;
2365 }
2366 tt = t->next;
2367 t->next = macro_start;
2368 macro_start = t;
2369 t = tt;
2370 }
2371 /*
2372 * Good. We now have a macro name, a parameter count, and a
2373 * token list (in reverse order) for an expansion. We ought
2374 * to be OK just to create an SMacro, store it, and let
2375 * free_tlist have the rest of the line (which we have
2376 * carefully re-terminated after chopping off the expansion
2377 * from the end).
2378 */
2379 if (smacro_defined(ctx, mname, nparam, &smac, i == PP_DEFINE)) {
2380 if (!smac) {
2381 error(ERR_WARNING,
2382 "single-line macro `%s' defined both with and"
2383 " without parameters", mname);
2384 free_tlist(origline);
2385 free_tlist(macro_start);
2386 return DIRECTIVE_FOUND;
2387 } else {
2388 /*
2389 * We're redefining, so we have to take over an
2390 * existing SMacro structure. This means freeing
2391 * what was already in it.
2392 */
2393 nasm_free(smac->name);
2394 free_tlist(smac->expansion);
2395 }
2396 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002397 if (!ctx)
2398 smhead = (SMacro **) hash_findi_add(smacros, mname);
2399 else
2400 smhead = &ctx->localmac;
2401
H. Peter Anvine2c80182005-01-15 22:15:51 +00002402 smac = nasm_malloc(sizeof(SMacro));
2403 smac->next = *smhead;
2404 *smhead = smac;
2405 }
2406 smac->name = nasm_strdup(mname);
2407 smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE));
2408 smac->nparam = nparam;
2409 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002410 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002411 free_tlist(origline);
2412 return DIRECTIVE_FOUND;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002413
H. Peter Anvine2c80182005-01-15 22:15:51 +00002414 case PP_UNDEF:
2415 tline = tline->next;
2416 skip_white_(tline);
2417 tline = expand_id(tline);
2418 if (!tline || (tline->type != TOK_ID &&
2419 (tline->type != TOK_PREPROC_ID ||
2420 tline->text[1] != '$'))) {
2421 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2422 free_tlist(origline);
2423 return DIRECTIVE_FOUND;
2424 }
2425 if (tline->next) {
2426 error(ERR_WARNING,
2427 "trailing garbage after macro name ignored");
2428 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002429
H. Peter Anvine2c80182005-01-15 22:15:51 +00002430 /* Find the context that symbol belongs to */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002431 ctx = get_ctx(tline->text, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002432 if (!ctx)
H. Peter Anvin97a23472007-09-16 17:57:25 -07002433 smhead = (SMacro **) hash_findi(smacros, tline->text, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002434 else
2435 smhead = &ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002436
H. Peter Anvin97a23472007-09-16 17:57:25 -07002437 if (smhead) {
2438 SMacro *s, **sp;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002439
H. Peter Anvin97a23472007-09-16 17:57:25 -07002440 mname = tline->text;
2441 last = tline;
2442 last->next = NULL;
2443
2444 /*
2445 * We now have a macro name... go hunt for it.
2446 */
H. Peter Anvine373efd2007-09-24 21:33:17 -07002447 sp = smhead;
2448 while ((s = *sp) != NULL) {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002449 if (!mstrcmp(s->name, tline->text, s->casesense)) {
2450 *sp = s->next;
2451 nasm_free(s->name);
2452 free_tlist(s->expansion);
2453 nasm_free(s);
H. Peter Anvine373efd2007-09-24 21:33:17 -07002454 } else {
2455 sp = &s->next;
H. Peter Anvin97a23472007-09-16 17:57:25 -07002456 }
2457 }
2458 free_tlist(origline);
2459 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002460 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002461
H. Peter Anvine2c80182005-01-15 22:15:51 +00002462 case PP_STRLEN:
2463 tline = tline->next;
2464 skip_white_(tline);
2465 tline = expand_id(tline);
2466 if (!tline || (tline->type != TOK_ID &&
2467 (tline->type != TOK_PREPROC_ID ||
2468 tline->text[1] != '$'))) {
2469 error(ERR_NONFATAL,
2470 "`%%strlen' expects a macro identifier as first parameter");
2471 free_tlist(origline);
2472 return DIRECTIVE_FOUND;
2473 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002474 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002475
H. Peter Anvine2c80182005-01-15 22:15:51 +00002476 mname = tline->text;
2477 last = tline;
2478 tline = expand_smacro(tline->next);
2479 last->next = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002480
H. Peter Anvine2c80182005-01-15 22:15:51 +00002481 t = tline;
2482 while (tok_type_(t, TOK_WHITESPACE))
2483 t = t->next;
2484 /* t should now point to the string */
2485 if (t->type != TOK_STRING) {
2486 error(ERR_NONFATAL,
2487 "`%%strlen` requires string as second parameter");
2488 free_tlist(tline);
2489 free_tlist(origline);
2490 return DIRECTIVE_FOUND;
2491 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002492
H. Peter Anvine2c80182005-01-15 22:15:51 +00002493 macro_start = nasm_malloc(sizeof(*macro_start));
2494 macro_start->next = NULL;
2495 make_tok_num(macro_start, strlen(t->text) - 2);
2496 macro_start->mac = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002497
H. Peter Anvine2c80182005-01-15 22:15:51 +00002498 /*
2499 * We now have a macro name, an implicit parameter count of
2500 * zero, and a numeric token to use as an expansion. Create
2501 * and store an SMacro.
2502 */
2503 if (smacro_defined(ctx, mname, 0, &smac, i == PP_STRLEN)) {
2504 if (!smac)
2505 error(ERR_WARNING,
2506 "single-line macro `%s' defined both with and"
2507 " without parameters", mname);
2508 else {
2509 /*
2510 * We're redefining, so we have to take over an
2511 * existing SMacro structure. This means freeing
2512 * what was already in it.
2513 */
2514 nasm_free(smac->name);
2515 free_tlist(smac->expansion);
2516 }
2517 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002518 if (!ctx)
2519 smhead = (SMacro **) hash_findi_add(smacros, mname);
2520 else
2521 smhead = &ctx->localmac;
2522
H. Peter Anvine2c80182005-01-15 22:15:51 +00002523 smac = nasm_malloc(sizeof(SMacro));
2524 smac->next = *smhead;
2525 *smhead = smac;
2526 }
2527 smac->name = nasm_strdup(mname);
2528 smac->casesense = (i == PP_STRLEN);
2529 smac->nparam = 0;
2530 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002531 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002532 free_tlist(tline);
2533 free_tlist(origline);
2534 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002535
H. Peter Anvine2c80182005-01-15 22:15:51 +00002536 case PP_SUBSTR:
2537 tline = tline->next;
2538 skip_white_(tline);
2539 tline = expand_id(tline);
2540 if (!tline || (tline->type != TOK_ID &&
2541 (tline->type != TOK_PREPROC_ID ||
2542 tline->text[1] != '$'))) {
2543 error(ERR_NONFATAL,
2544 "`%%substr' expects a macro identifier as first parameter");
2545 free_tlist(origline);
2546 return DIRECTIVE_FOUND;
2547 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002548 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002549
H. Peter Anvine2c80182005-01-15 22:15:51 +00002550 mname = tline->text;
2551 last = tline;
2552 tline = expand_smacro(tline->next);
2553 last->next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002554
H. Peter Anvine2c80182005-01-15 22:15:51 +00002555 t = tline->next;
2556 while (tok_type_(t, TOK_WHITESPACE))
2557 t = t->next;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002558
H. Peter Anvine2c80182005-01-15 22:15:51 +00002559 /* t should now point to the string */
2560 if (t->type != TOK_STRING) {
2561 error(ERR_NONFATAL,
2562 "`%%substr` requires string as second parameter");
2563 free_tlist(tline);
2564 free_tlist(origline);
2565 return DIRECTIVE_FOUND;
2566 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002567
H. Peter Anvine2c80182005-01-15 22:15:51 +00002568 tt = t->next;
2569 tptr = &tt;
2570 tokval.t_type = TOKEN_INVALID;
2571 evalresult =
2572 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2573 if (!evalresult) {
2574 free_tlist(tline);
2575 free_tlist(origline);
2576 return DIRECTIVE_FOUND;
2577 }
2578 if (!is_simple(evalresult)) {
2579 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
2580 free_tlist(tline);
2581 free_tlist(origline);
2582 return DIRECTIVE_FOUND;
2583 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002584
H. Peter Anvine2c80182005-01-15 22:15:51 +00002585 macro_start = nasm_malloc(sizeof(*macro_start));
2586 macro_start->next = NULL;
2587 macro_start->text = nasm_strdup("'''");
2588 if (evalresult->value > 0
2589 && evalresult->value < strlen(t->text) - 1) {
2590 macro_start->text[1] = t->text[evalresult->value];
2591 } else {
2592 macro_start->text[2] = '\0';
2593 }
2594 macro_start->type = TOK_STRING;
2595 macro_start->mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002596
H. Peter Anvine2c80182005-01-15 22:15:51 +00002597 /*
2598 * We now have a macro name, an implicit parameter count of
2599 * zero, and a numeric token to use as an expansion. Create
2600 * and store an SMacro.
2601 */
2602 if (smacro_defined(ctx, mname, 0, &smac, i == PP_SUBSTR)) {
2603 if (!smac)
2604 error(ERR_WARNING,
2605 "single-line macro `%s' defined both with and"
2606 " without parameters", mname);
2607 else {
2608 /*
2609 * We're redefining, so we have to take over an
2610 * existing SMacro structure. This means freeing
2611 * what was already in it.
2612 */
2613 nasm_free(smac->name);
2614 free_tlist(smac->expansion);
2615 }
2616 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002617 if (!ctx)
2618 smhead = (SMacro **) hash_findi_add(smacros, tline->text);
2619 else
2620 smhead = &ctx->localmac;
2621
H. Peter Anvine2c80182005-01-15 22:15:51 +00002622 smac = nasm_malloc(sizeof(SMacro));
2623 smac->next = *smhead;
2624 *smhead = smac;
2625 }
2626 smac->name = nasm_strdup(mname);
2627 smac->casesense = (i == PP_SUBSTR);
2628 smac->nparam = 0;
2629 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002630 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002631 free_tlist(tline);
2632 free_tlist(origline);
2633 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002634
H. Peter Anvine2c80182005-01-15 22:15:51 +00002635 case PP_ASSIGN:
2636 case PP_IASSIGN:
2637 tline = tline->next;
2638 skip_white_(tline);
2639 tline = expand_id(tline);
2640 if (!tline || (tline->type != TOK_ID &&
2641 (tline->type != TOK_PREPROC_ID ||
2642 tline->text[1] != '$'))) {
2643 error(ERR_NONFATAL,
2644 "`%%%sassign' expects a macro identifier",
2645 (i == PP_IASSIGN ? "i" : ""));
2646 free_tlist(origline);
2647 return DIRECTIVE_FOUND;
2648 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002649 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002650
H. Peter Anvine2c80182005-01-15 22:15:51 +00002651 mname = tline->text;
2652 last = tline;
2653 tline = expand_smacro(tline->next);
2654 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002655
H. Peter Anvine2c80182005-01-15 22:15:51 +00002656 t = tline;
2657 tptr = &t;
2658 tokval.t_type = TOKEN_INVALID;
2659 evalresult =
2660 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2661 free_tlist(tline);
2662 if (!evalresult) {
2663 free_tlist(origline);
2664 return DIRECTIVE_FOUND;
2665 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002666
H. Peter Anvine2c80182005-01-15 22:15:51 +00002667 if (tokval.t_type)
2668 error(ERR_WARNING,
2669 "trailing garbage after expression ignored");
H. Peter Anvin734b1882002-04-30 21:01:08 +00002670
H. Peter Anvine2c80182005-01-15 22:15:51 +00002671 if (!is_simple(evalresult)) {
2672 error(ERR_NONFATAL,
2673 "non-constant value given to `%%%sassign'",
2674 (i == PP_IASSIGN ? "i" : ""));
2675 free_tlist(origline);
2676 return DIRECTIVE_FOUND;
2677 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002678
H. Peter Anvine2c80182005-01-15 22:15:51 +00002679 macro_start = nasm_malloc(sizeof(*macro_start));
2680 macro_start->next = NULL;
2681 make_tok_num(macro_start, reloc_value(evalresult));
2682 macro_start->mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002683
H. Peter Anvine2c80182005-01-15 22:15:51 +00002684 /*
2685 * We now have a macro name, an implicit parameter count of
2686 * zero, and a numeric token to use as an expansion. Create
2687 * and store an SMacro.
2688 */
2689 if (smacro_defined(ctx, mname, 0, &smac, i == PP_ASSIGN)) {
2690 if (!smac)
2691 error(ERR_WARNING,
2692 "single-line macro `%s' defined both with and"
2693 " without parameters", mname);
2694 else {
2695 /*
2696 * We're redefining, so we have to take over an
2697 * existing SMacro structure. This means freeing
2698 * what was already in it.
2699 */
2700 nasm_free(smac->name);
2701 free_tlist(smac->expansion);
2702 }
2703 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002704 if (!ctx)
2705 smhead = (SMacro **) hash_findi_add(smacros, mname);
2706 else
2707 smhead = &ctx->localmac;
2708
H. Peter Anvine2c80182005-01-15 22:15:51 +00002709 smac = nasm_malloc(sizeof(SMacro));
2710 smac->next = *smhead;
2711 *smhead = smac;
2712 }
2713 smac->name = nasm_strdup(mname);
2714 smac->casesense = (i == PP_ASSIGN);
2715 smac->nparam = 0;
2716 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002717 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002718 free_tlist(origline);
2719 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002720
H. Peter Anvine2c80182005-01-15 22:15:51 +00002721 case PP_LINE:
2722 /*
2723 * Syntax is `%line nnn[+mmm] [filename]'
2724 */
2725 tline = tline->next;
2726 skip_white_(tline);
2727 if (!tok_type_(tline, TOK_NUMBER)) {
2728 error(ERR_NONFATAL, "`%%line' expects line number");
2729 free_tlist(origline);
2730 return DIRECTIVE_FOUND;
2731 }
H. Peter Anvin70055962007-10-11 00:05:31 -07002732 k = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002733 m = 1;
2734 tline = tline->next;
2735 if (tok_is_(tline, "+")) {
2736 tline = tline->next;
2737 if (!tok_type_(tline, TOK_NUMBER)) {
2738 error(ERR_NONFATAL, "`%%line' expects line increment");
2739 free_tlist(origline);
2740 return DIRECTIVE_FOUND;
2741 }
H. Peter Anvin70055962007-10-11 00:05:31 -07002742 m = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002743 tline = tline->next;
2744 }
2745 skip_white_(tline);
2746 src_set_linnum(k);
2747 istk->lineinc = m;
2748 if (tline) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002749 nasm_free(src_set_fname(detoken(tline, false)));
H. Peter Anvine2c80182005-01-15 22:15:51 +00002750 }
2751 free_tlist(origline);
2752 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002753
H. Peter Anvine2c80182005-01-15 22:15:51 +00002754 default:
2755 error(ERR_FATAL,
2756 "preprocessor directive `%s' not yet implemented",
H. Peter Anvin4169a472007-09-12 01:29:43 +00002757 pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002758 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002759 }
Ed Beroset3ab3f412002-06-11 03:31:49 +00002760 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002761}
2762
2763/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002764 * Ensure that a macro parameter contains a condition code and
2765 * nothing else. Return the condition code index if so, or -1
2766 * otherwise.
2767 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002768static int find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002769{
H. Peter Anvin76690a12002-04-30 20:52:49 +00002770 Token *tt;
2771 int i, j, k, m;
2772
H. Peter Anvin25a99342007-09-22 17:45:45 -07002773 if (!t)
2774 return -1; /* Probably a %+ without a space */
2775
H. Peter Anvineba20a72002-04-30 20:53:55 +00002776 skip_white_(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002777 if (t->type != TOK_ID)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002778 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002779 tt = t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002780 skip_white_(tt);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002781 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002782 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002783
2784 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +00002785 j = elements(conditions);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002786 while (j - i > 1) {
2787 k = (j + i) / 2;
2788 m = nasm_stricmp(t->text, conditions[k]);
2789 if (m == 0) {
2790 i = k;
2791 j = -2;
2792 break;
2793 } else if (m < 0) {
2794 j = k;
2795 } else
2796 i = k;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002797 }
2798 if (j != -2)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002799 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002800 return i;
2801}
2802
2803/*
2804 * Expand MMacro-local things: parameter references (%0, %n, %+n,
2805 * %-n) and MMacro-local identifiers (%%foo).
2806 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002807static Token *expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002808{
H. Peter Anvin734b1882002-04-30 21:01:08 +00002809 Token *t, *tt, **tail, *thead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002810
2811 tail = &thead;
2812 thead = NULL;
2813
H. Peter Anvine2c80182005-01-15 22:15:51 +00002814 while (tline) {
2815 if (tline->type == TOK_PREPROC_ID &&
2816 (((tline->text[1] == '+' || tline->text[1] == '-')
2817 && tline->text[2]) || tline->text[1] == '%'
2818 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002819 char *text = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002820 int type = 0, cc; /* type = 0 to placate optimisers */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002821 char tmpbuf[30];
H. Peter Anvin25a99342007-09-22 17:45:45 -07002822 unsigned int n;
2823 int i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002824 MMacro *mac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002825
H. Peter Anvine2c80182005-01-15 22:15:51 +00002826 t = tline;
2827 tline = tline->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002828
H. Peter Anvine2c80182005-01-15 22:15:51 +00002829 mac = istk->mstk;
2830 while (mac && !mac->name) /* avoid mistaking %reps for macros */
2831 mac = mac->next_active;
2832 if (!mac)
2833 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
2834 else
2835 switch (t->text[1]) {
2836 /*
2837 * We have to make a substitution of one of the
2838 * forms %1, %-1, %+1, %%foo, %0.
2839 */
2840 case '0':
2841 type = TOK_NUMBER;
2842 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
2843 text = nasm_strdup(tmpbuf);
2844 break;
2845 case '%':
2846 type = TOK_ID;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002847 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
H. Peter Anvine2c80182005-01-15 22:15:51 +00002848 mac->unique);
2849 text = nasm_strcat(tmpbuf, t->text + 2);
2850 break;
2851 case '-':
2852 n = atoi(t->text + 2) - 1;
2853 if (n >= mac->nparam)
2854 tt = NULL;
2855 else {
2856 if (mac->nparam > 1)
2857 n = (n + mac->rotate) % mac->nparam;
2858 tt = mac->params[n];
2859 }
2860 cc = find_cc(tt);
2861 if (cc == -1) {
2862 error(ERR_NONFATAL,
2863 "macro parameter %d is not a condition code",
2864 n + 1);
2865 text = NULL;
2866 } else {
2867 type = TOK_ID;
2868 if (inverse_ccs[cc] == -1) {
2869 error(ERR_NONFATAL,
2870 "condition code `%s' is not invertible",
2871 conditions[cc]);
2872 text = NULL;
2873 } else
2874 text =
2875 nasm_strdup(conditions[inverse_ccs[cc]]);
2876 }
2877 break;
2878 case '+':
2879 n = atoi(t->text + 2) - 1;
2880 if (n >= mac->nparam)
2881 tt = NULL;
2882 else {
2883 if (mac->nparam > 1)
2884 n = (n + mac->rotate) % mac->nparam;
2885 tt = mac->params[n];
2886 }
2887 cc = find_cc(tt);
2888 if (cc == -1) {
2889 error(ERR_NONFATAL,
2890 "macro parameter %d is not a condition code",
2891 n + 1);
2892 text = NULL;
2893 } else {
2894 type = TOK_ID;
2895 text = nasm_strdup(conditions[cc]);
2896 }
2897 break;
2898 default:
2899 n = atoi(t->text + 1) - 1;
2900 if (n >= mac->nparam)
2901 tt = NULL;
2902 else {
2903 if (mac->nparam > 1)
2904 n = (n + mac->rotate) % mac->nparam;
2905 tt = mac->params[n];
2906 }
2907 if (tt) {
2908 for (i = 0; i < mac->paramlen[n]; i++) {
2909 *tail = new_Token(NULL, tt->type, tt->text, 0);
2910 tail = &(*tail)->next;
2911 tt = tt->next;
2912 }
2913 }
2914 text = NULL; /* we've done it here */
2915 break;
2916 }
2917 if (!text) {
2918 delete_Token(t);
2919 } else {
2920 *tail = t;
2921 tail = &t->next;
2922 t->type = type;
2923 nasm_free(t->text);
2924 t->text = text;
2925 t->mac = NULL;
2926 }
2927 continue;
2928 } else {
2929 t = *tail = tline;
2930 tline = tline->next;
2931 t->mac = NULL;
2932 tail = &t->next;
2933 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002934 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00002935 *tail = NULL;
2936 t = thead;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002937 for (; t && (tt = t->next) != NULL; t = t->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002938 switch (t->type) {
2939 case TOK_WHITESPACE:
2940 if (tt->type == TOK_WHITESPACE) {
2941 t->next = delete_Token(tt);
2942 }
2943 break;
2944 case TOK_ID:
2945 if (tt->type == TOK_ID || tt->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002946 char *tmp = nasm_strcat(t->text, tt->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002947 nasm_free(t->text);
2948 t->text = tmp;
2949 t->next = delete_Token(tt);
2950 }
2951 break;
2952 case TOK_NUMBER:
2953 if (tt->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002954 char *tmp = nasm_strcat(t->text, tt->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002955 nasm_free(t->text);
2956 t->text = tmp;
2957 t->next = delete_Token(tt);
2958 }
2959 break;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002960 default:
2961 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002962 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002963
H. Peter Anvin76690a12002-04-30 20:52:49 +00002964 return thead;
2965}
2966
2967/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002968 * Expand all single-line macro calls made in the given line.
2969 * Return the expanded version of the line. The original is deemed
2970 * to be destroyed in the process. (In reality we'll just move
2971 * Tokens from input to output a lot of the time, rather than
2972 * actually bothering to destroy and replicate.)
2973 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002974static Token *expand_smacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002975{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002976 Token *t, *tt, *mstart, **tail, *thead;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002977 SMacro *head = NULL, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002978 Token **params;
2979 int *paramsize;
H. Peter Anvin25a99342007-09-22 17:45:45 -07002980 unsigned int nparam, sparam;
2981 int brackets, rescan;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002982 Token *org_tline = tline;
2983 Context *ctx;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002984 char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002985
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002986 /*
2987 * Trick: we should avoid changing the start token pointer since it can
2988 * be contained in "next" field of other token. Because of this
2989 * we allocate a copy of first token and work with it; at the end of
2990 * routine we copy it back
2991 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002992 if (org_tline) {
2993 tline =
2994 new_Token(org_tline->next, org_tline->type, org_tline->text,
2995 0);
2996 tline->mac = org_tline->mac;
2997 nasm_free(org_tline->text);
2998 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002999 }
3000
H. Peter Anvin734b1882002-04-30 21:01:08 +00003001 again:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003002 tail = &thead;
3003 thead = NULL;
3004
H. Peter Anvine2c80182005-01-15 22:15:51 +00003005 while (tline) { /* main token loop */
3006 if ((mname = tline->text)) {
3007 /* if this token is a local macro, look in local context */
3008 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003009 ctx = get_ctx(mname, true);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003010 else
3011 ctx = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003012 if (!ctx) {
3013 head = (SMacro *) hash_findix(smacros, mname);
3014 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003015 head = ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003016 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003017 /*
3018 * We've hit an identifier. As in is_mmacro below, we first
3019 * check whether the identifier is a single-line macro at
3020 * all, then think about checking for parameters if
3021 * necessary.
3022 */
H. Peter Anvin97a23472007-09-16 17:57:25 -07003023 for (m = head; m; m = m->next)
3024 if (!mstrcmp(m->name, mname, m->casesense))
3025 break;
3026 if (m) {
3027 mstart = tline;
3028 params = NULL;
3029 paramsize = NULL;
3030 if (m->nparam == 0) {
3031 /*
3032 * Simple case: the macro is parameterless. Discard the
3033 * one token that the macro call took, and push the
3034 * expansion back on the to-do stack.
3035 */
3036 if (!m->expansion) {
3037 if (!strcmp("__FILE__", m->name)) {
3038 int32_t num = 0;
3039 src_get(&num, &(tline->text));
3040 nasm_quote(&(tline->text));
3041 tline->type = TOK_STRING;
3042 continue;
3043 }
3044 if (!strcmp("__LINE__", m->name)) {
3045 nasm_free(tline->text);
3046 make_tok_num(tline, src_get_linnum());
3047 continue;
3048 }
3049 if (!strcmp("__BITS__", m->name)) {
3050 nasm_free(tline->text);
3051 make_tok_num(tline, globalbits);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003052 continue;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003053 }
3054 tline = delete_Token(tline);
3055 continue;
3056 }
3057 } else {
3058 /*
3059 * Complicated case: at least one macro with this name
H. Peter Anvine2c80182005-01-15 22:15:51 +00003060 * exists and takes parameters. We must find the
3061 * parameters in the call, count them, find the SMacro
3062 * that corresponds to that form of the macro call, and
3063 * substitute for the parameters when we expand. What a
3064 * pain.
3065 */
3066 /*tline = tline->next;
3067 skip_white_(tline); */
3068 do {
3069 t = tline->next;
3070 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003071 t->mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003072 t->text = NULL;
3073 t = tline->next = delete_Token(t);
3074 }
3075 tline = t;
3076 } while (tok_type_(tline, TOK_WHITESPACE));
3077 if (!tok_is_(tline, "(")) {
3078 /*
3079 * This macro wasn't called with parameters: ignore
3080 * the call. (Behaviour borrowed from gnu cpp.)
3081 */
3082 tline = mstart;
3083 m = NULL;
3084 } else {
3085 int paren = 0;
3086 int white = 0;
3087 brackets = 0;
3088 nparam = 0;
3089 sparam = PARAM_DELTA;
3090 params = nasm_malloc(sparam * sizeof(Token *));
3091 params[0] = tline->next;
3092 paramsize = nasm_malloc(sparam * sizeof(int));
3093 paramsize[0] = 0;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003094 while (true) { /* parameter loop */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003095 /*
3096 * For some unusual expansions
3097 * which concatenates function call
3098 */
3099 t = tline->next;
3100 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003101 t->mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003102 t->text = NULL;
3103 t = tline->next = delete_Token(t);
3104 }
3105 tline = t;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003106
H. Peter Anvine2c80182005-01-15 22:15:51 +00003107 if (!tline) {
3108 error(ERR_NONFATAL,
3109 "macro call expects terminating `)'");
3110 break;
3111 }
3112 if (tline->type == TOK_WHITESPACE
3113 && brackets <= 0) {
3114 if (paramsize[nparam])
3115 white++;
3116 else
3117 params[nparam] = tline->next;
3118 continue; /* parameter loop */
3119 }
3120 if (tline->type == TOK_OTHER
3121 && tline->text[1] == 0) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003122 char ch = tline->text[0];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003123 if (ch == ',' && !paren && brackets <= 0) {
3124 if (++nparam >= sparam) {
3125 sparam += PARAM_DELTA;
3126 params = nasm_realloc(params,
3127 sparam *
3128 sizeof(Token
3129 *));
3130 paramsize =
3131 nasm_realloc(paramsize,
3132 sparam *
3133 sizeof(int));
3134 }
3135 params[nparam] = tline->next;
3136 paramsize[nparam] = 0;
3137 white = 0;
3138 continue; /* parameter loop */
3139 }
3140 if (ch == '{' &&
3141 (brackets > 0 || (brackets == 0 &&
3142 !paramsize[nparam])))
3143 {
3144 if (!(brackets++)) {
3145 params[nparam] = tline->next;
3146 continue; /* parameter loop */
3147 }
3148 }
3149 if (ch == '}' && brackets > 0)
3150 if (--brackets == 0) {
3151 brackets = -1;
3152 continue; /* parameter loop */
3153 }
3154 if (ch == '(' && !brackets)
3155 paren++;
3156 if (ch == ')' && brackets <= 0)
3157 if (--paren < 0)
3158 break;
3159 }
3160 if (brackets < 0) {
3161 brackets = 0;
3162 error(ERR_NONFATAL, "braces do not "
3163 "enclose all of macro parameter");
3164 }
3165 paramsize[nparam] += white + 1;
3166 white = 0;
3167 } /* parameter loop */
3168 nparam++;
3169 while (m && (m->nparam != nparam ||
3170 mstrcmp(m->name, mname,
3171 m->casesense)))
3172 m = m->next;
3173 if (!m)
3174 error(ERR_WARNING | ERR_WARN_MNP,
3175 "macro `%s' exists, "
3176 "but not taking %d parameters",
3177 mstart->text, nparam);
3178 }
3179 }
3180 if (m && m->in_progress)
3181 m = NULL;
3182 if (!m) { /* in progess or didn't find '(' or wrong nparam */
3183 /*
3184 * Design question: should we handle !tline, which
3185 * indicates missing ')' here, or expand those
3186 * macros anyway, which requires the (t) test a few
3187 * lines down?
3188 */
3189 nasm_free(params);
3190 nasm_free(paramsize);
3191 tline = mstart;
3192 } else {
3193 /*
3194 * Expand the macro: we are placed on the last token of the
3195 * call, so that we can easily split the call from the
3196 * following tokens. We also start by pushing an SMAC_END
3197 * token for the cycle removal.
3198 */
3199 t = tline;
3200 if (t) {
3201 tline = t->next;
3202 t->next = NULL;
3203 }
3204 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
3205 tt->mac = m;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003206 m->in_progress = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003207 tline = tt;
3208 for (t = m->expansion; t; t = t->next) {
3209 if (t->type >= TOK_SMAC_PARAM) {
3210 Token *pcopy = tline, **ptail = &pcopy;
3211 Token *ttt, *pt;
3212 int i;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003213
H. Peter Anvine2c80182005-01-15 22:15:51 +00003214 ttt = params[t->type - TOK_SMAC_PARAM];
3215 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3216 --i >= 0;) {
3217 pt = *ptail =
3218 new_Token(tline, ttt->type, ttt->text,
3219 0);
3220 ptail = &pt->next;
3221 ttt = ttt->next;
3222 }
3223 tline = pcopy;
3224 } else {
3225 tt = new_Token(tline, t->type, t->text, 0);
3226 tline = tt;
3227 }
3228 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003229
H. Peter Anvine2c80182005-01-15 22:15:51 +00003230 /*
3231 * Having done that, get rid of the macro call, and clean
3232 * up the parameters.
3233 */
3234 nasm_free(params);
3235 nasm_free(paramsize);
3236 free_tlist(mstart);
3237 continue; /* main token loop */
3238 }
3239 }
3240 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003241
H. Peter Anvine2c80182005-01-15 22:15:51 +00003242 if (tline->type == TOK_SMAC_END) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003243 tline->mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003244 tline = delete_Token(tline);
3245 } else {
3246 t = *tail = tline;
3247 tline = tline->next;
3248 t->mac = NULL;
3249 t->next = NULL;
3250 tail = &t->next;
3251 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003252 }
3253
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003254 /*
3255 * Now scan the entire line and look for successive TOK_IDs that resulted
Keith Kaniosb7a89542007-04-12 02:40:54 +00003256 * after expansion (they can't be produced by tokenize()). The successive
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003257 * TOK_IDs should be concatenated.
3258 * Also we look for %+ tokens and concatenate the tokens before and after
3259 * them (without white spaces in between).
3260 */
3261 t = thead;
3262 rescan = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003263 while (t) {
3264 while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
3265 t = t->next;
3266 if (!t || !t->next)
3267 break;
3268 if (t->next->type == TOK_ID ||
3269 t->next->type == TOK_PREPROC_ID ||
3270 t->next->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003271 char *p = nasm_strcat(t->text, t->next->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003272 nasm_free(t->text);
3273 t->next = delete_Token(t->next);
3274 t->text = p;
3275 rescan = 1;
3276 } else if (t->next->type == TOK_WHITESPACE && t->next->next &&
3277 t->next->next->type == TOK_PREPROC_ID &&
3278 strcmp(t->next->next->text, "%+") == 0) {
3279 /* free the next whitespace, the %+ token and next whitespace */
3280 int i;
3281 for (i = 1; i <= 3; i++) {
3282 if (!t->next
3283 || (i != 2 && t->next->type != TOK_WHITESPACE))
3284 break;
3285 t->next = delete_Token(t->next);
3286 } /* endfor */
3287 } else
3288 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003289 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003290 /* If we concatenaded something, re-scan the line for macros */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003291 if (rescan) {
3292 tline = thead;
3293 goto again;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003294 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003295
H. Peter Anvine2c80182005-01-15 22:15:51 +00003296 if (org_tline) {
3297 if (thead) {
3298 *org_tline = *thead;
3299 /* since we just gave text to org_line, don't free it */
3300 thead->text = NULL;
3301 delete_Token(thead);
3302 } else {
3303 /* the expression expanded to empty line;
3304 we can't return NULL for some reasons
3305 we just set the line to a single WHITESPACE token. */
3306 memset(org_tline, 0, sizeof(*org_tline));
3307 org_tline->text = NULL;
3308 org_tline->type = TOK_WHITESPACE;
3309 }
3310 thead = org_tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003311 }
3312
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003313 return thead;
3314}
3315
3316/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003317 * Similar to expand_smacro but used exclusively with macro identifiers
3318 * right before they are fetched in. The reason is that there can be
3319 * identifiers consisting of several subparts. We consider that if there
3320 * are more than one element forming the name, user wants a expansion,
3321 * otherwise it will be left as-is. Example:
3322 *
3323 * %define %$abc cde
3324 *
3325 * the identifier %$abc will be left as-is so that the handler for %define
3326 * will suck it and define the corresponding value. Other case:
3327 *
3328 * %define _%$abc cde
3329 *
3330 * In this case user wants name to be expanded *before* %define starts
3331 * working, so we'll expand %$abc into something (if it has a value;
3332 * otherwise it will be left as-is) then concatenate all successive
3333 * PP_IDs into one.
3334 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003335static Token *expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003336{
3337 Token *cur, *oldnext = NULL;
3338
H. Peter Anvin734b1882002-04-30 21:01:08 +00003339 if (!tline || !tline->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003340 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003341
3342 cur = tline;
3343 while (cur->next &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00003344 (cur->next->type == TOK_ID ||
3345 cur->next->type == TOK_PREPROC_ID
3346 || cur->next->type == TOK_NUMBER))
3347 cur = cur->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003348
3349 /* If identifier consists of just one token, don't expand */
3350 if (cur == tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003351 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003352
H. Peter Anvine2c80182005-01-15 22:15:51 +00003353 if (cur) {
3354 oldnext = cur->next; /* Detach the tail past identifier */
3355 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003356 }
3357
H. Peter Anvin734b1882002-04-30 21:01:08 +00003358 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003359
H. Peter Anvine2c80182005-01-15 22:15:51 +00003360 if (cur) {
3361 /* expand_smacro possibly changhed tline; re-scan for EOL */
3362 cur = tline;
3363 while (cur && cur->next)
3364 cur = cur->next;
3365 if (cur)
3366 cur->next = oldnext;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003367 }
3368
3369 return tline;
3370}
3371
3372/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003373 * Determine whether the given line constitutes a multi-line macro
3374 * call, and return the MMacro structure called if so. Doesn't have
3375 * to check for an initial label - that's taken care of in
3376 * expand_mmacro - but must check numbers of parameters. Guaranteed
3377 * to be called with tline->type == TOK_ID, so the putative macro
3378 * name is easy to find.
3379 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003380static MMacro *is_mmacro(Token * tline, Token *** params_array)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003381{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003382 MMacro *head, *m;
3383 Token **params;
3384 int nparam;
3385
H. Peter Anvin97a23472007-09-16 17:57:25 -07003386 head = (MMacro *) hash_findix(mmacros, tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003387
3388 /*
3389 * Efficiency: first we see if any macro exists with the given
3390 * name. If not, we can return NULL immediately. _Then_ we
3391 * count the parameters, and then we look further along the
3392 * list if necessary to find the proper MMacro.
3393 */
3394 for (m = head; m; m = m->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003395 if (!mstrcmp(m->name, tline->text, m->casesense))
3396 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003397 if (!m)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003398 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003399
3400 /*
3401 * OK, we have a potential macro. Count and demarcate the
3402 * parameters.
3403 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003404 count_mmac_params(tline->next, &nparam, &params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003405
3406 /*
3407 * So we know how many parameters we've got. Find the MMacro
3408 * structure that handles this number.
3409 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003410 while (m) {
3411 if (m->nparam_min <= nparam
3412 && (m->plus || nparam <= m->nparam_max)) {
3413 /*
3414 * This one is right. Just check if cycle removal
3415 * prohibits us using it before we actually celebrate...
3416 */
3417 if (m->in_progress) {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003418#if 0
H. Peter Anvine2c80182005-01-15 22:15:51 +00003419 error(ERR_NONFATAL,
3420 "self-reference in multi-line macro `%s'", m->name);
H. Peter Anvineba20a72002-04-30 20:53:55 +00003421#endif
H. Peter Anvine2c80182005-01-15 22:15:51 +00003422 nasm_free(params);
3423 return NULL;
3424 }
3425 /*
3426 * It's right, and we can use it. Add its default
3427 * parameters to the end of our list if necessary.
3428 */
3429 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
3430 params =
3431 nasm_realloc(params,
3432 ((m->nparam_min + m->ndefs +
3433 1) * sizeof(*params)));
3434 while (nparam < m->nparam_min + m->ndefs) {
3435 params[nparam] = m->defaults[nparam - m->nparam_min];
3436 nparam++;
3437 }
3438 }
3439 /*
3440 * If we've gone over the maximum parameter count (and
3441 * we're in Plus mode), ignore parameters beyond
3442 * nparam_max.
3443 */
3444 if (m->plus && nparam > m->nparam_max)
3445 nparam = m->nparam_max;
3446 /*
3447 * Then terminate the parameter list, and leave.
3448 */
3449 if (!params) { /* need this special case */
3450 params = nasm_malloc(sizeof(*params));
3451 nparam = 0;
3452 }
3453 params[nparam] = NULL;
3454 *params_array = params;
3455 return m;
3456 }
3457 /*
3458 * This one wasn't right: look for the next one with the
3459 * same name.
3460 */
3461 for (m = m->next; m; m = m->next)
3462 if (!mstrcmp(m->name, tline->text, m->casesense))
3463 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003464 }
3465
3466 /*
3467 * After all that, we didn't find one with the right number of
3468 * parameters. Issue a warning, and fail to expand the macro.
3469 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003470 error(ERR_WARNING | ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003471 "macro `%s' exists, but not taking %d parameters",
3472 tline->text, nparam);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003473 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003474 return NULL;
3475}
3476
3477/*
3478 * Expand the multi-line macro call made by the given line, if
3479 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvineba20a72002-04-30 20:53:55 +00003480 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003481 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003482static int expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003483{
3484 Token *startline = tline;
3485 Token *label = NULL;
3486 int dont_prepend = 0;
3487 Token **params, *t, *tt;
3488 MMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003489 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003490 int i, nparam, *paramlen;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003491
3492 t = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003493 skip_white_(t);
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00003494/* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
3495 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003496 return 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003497 m = is_mmacro(t, &params);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003498 if (!m) {
3499 Token *last;
3500 /*
3501 * We have an id which isn't a macro call. We'll assume
3502 * it might be a label; we'll also check to see if a
3503 * colon follows it. Then, if there's another id after
3504 * that lot, we'll check it again for macro-hood.
3505 */
3506 label = last = t;
3507 t = t->next;
3508 if (tok_type_(t, TOK_WHITESPACE))
3509 last = t, t = t->next;
3510 if (tok_is_(t, ":")) {
3511 dont_prepend = 1;
3512 last = t, t = t->next;
3513 if (tok_type_(t, TOK_WHITESPACE))
3514 last = t, t = t->next;
3515 }
3516 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
3517 return 0;
3518 last->next = NULL;
3519 tline = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003520 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003521
3522 /*
3523 * Fix up the parameters: this involves stripping leading and
3524 * trailing whitespace, then stripping braces if they are
3525 * present.
3526 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003527 for (nparam = 0; params[nparam]; nparam++) ;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003528 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003529
H. Peter Anvine2c80182005-01-15 22:15:51 +00003530 for (i = 0; params[i]; i++) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003531 int brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003532 int comma = (!m->plus || i < nparam - 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003533
H. Peter Anvine2c80182005-01-15 22:15:51 +00003534 t = params[i];
3535 skip_white_(t);
3536 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003537 t = t->next, brace = true, comma = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003538 params[i] = t;
3539 paramlen[i] = 0;
3540 while (t) {
3541 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
3542 break; /* ... because we have hit a comma */
3543 if (comma && t->type == TOK_WHITESPACE
3544 && tok_is_(t->next, ","))
3545 break; /* ... or a space then a comma */
3546 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
3547 break; /* ... or a brace */
3548 t = t->next;
3549 paramlen[i]++;
3550 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003551 }
3552
3553 /*
3554 * OK, we have a MMacro structure together with a set of
3555 * parameters. We must now go through the expansion and push
H. Peter Anvin76690a12002-04-30 20:52:49 +00003556 * copies of each Line on to istk->expansion. Substitution of
3557 * parameter tokens and macro-local tokens doesn't get done
3558 * until the single-line macro substitution process; this is
3559 * because delaying them allows us to change the semantics
3560 * later through %rotate.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003561 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00003562 * First, push an end marker on to istk->expansion, mark this
3563 * macro as in progress, and set up its invocation-specific
3564 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003565 */
3566 ll = nasm_malloc(sizeof(Line));
3567 ll->next = istk->expansion;
3568 ll->finishes = m;
3569 ll->first = NULL;
3570 istk->expansion = ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003571
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003572 m->in_progress = true;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003573 m->params = params;
3574 m->iline = tline;
3575 m->nparam = nparam;
3576 m->rotate = 0;
3577 m->paramlen = paramlen;
3578 m->unique = unique++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003579 m->lineno = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003580
3581 m->next_active = istk->mstk;
3582 istk->mstk = m;
3583
H. Peter Anvine2c80182005-01-15 22:15:51 +00003584 for (l = m->expansion; l; l = l->next) {
3585 Token **tail;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003586
H. Peter Anvine2c80182005-01-15 22:15:51 +00003587 ll = nasm_malloc(sizeof(Line));
3588 ll->finishes = NULL;
3589 ll->next = istk->expansion;
3590 istk->expansion = ll;
3591 tail = &ll->first;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003592
H. Peter Anvine2c80182005-01-15 22:15:51 +00003593 for (t = l->first; t; t = t->next) {
3594 Token *x = t;
3595 if (t->type == TOK_PREPROC_ID &&
3596 t->text[1] == '0' && t->text[2] == '0') {
3597 dont_prepend = -1;
3598 x = label;
3599 if (!x)
3600 continue;
3601 }
3602 tt = *tail = new_Token(NULL, x->type, x->text, 0);
3603 tail = &tt->next;
3604 }
3605 *tail = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003606 }
3607
3608 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00003609 * If we had a label, push it on as the first line of
3610 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003611 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003612 if (label) {
3613 if (dont_prepend < 0)
3614 free_tlist(startline);
3615 else {
3616 ll = nasm_malloc(sizeof(Line));
3617 ll->finishes = NULL;
3618 ll->next = istk->expansion;
3619 istk->expansion = ll;
3620 ll->first = startline;
3621 if (!dont_prepend) {
3622 while (label->next)
3623 label = label->next;
3624 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
3625 }
3626 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003627 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003628
H. Peter Anvin734b1882002-04-30 21:01:08 +00003629 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003630
H. Peter Anvineba20a72002-04-30 20:53:55 +00003631 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003632}
3633
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003634/*
3635 * Since preprocessor always operate only on the line that didn't
3636 * arrived yet, we should always use ERR_OFFBY1. Also since user
3637 * won't want to see same error twice (preprocessing is done once
3638 * per pass) we will want to show errors only during pass one.
3639 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003640static void error(int severity, const char *fmt, ...)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003641{
3642 va_list arg;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003643 char buff[1024];
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003644
3645 /* If we're in a dead branch of IF or something like it, ignore the error */
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00003646 if (istk && istk->conds && !emitting(istk->conds->state))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003647 return;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003648
H. Peter Anvin734b1882002-04-30 21:01:08 +00003649 va_start(arg, fmt);
Ed Beroset19f927a2004-12-15 17:07:03 +00003650 vsnprintf(buff, sizeof(buff), fmt, arg);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003651 va_end(arg);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003652
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00003653 if (istk && istk->mstk && istk->mstk->name)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003654 _error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
3655 istk->mstk->lineno, buff);
3656 else
3657 _error(severity | ERR_PASS1, "%s", buff);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003658}
3659
H. Peter Anvin734b1882002-04-30 21:01:08 +00003660static void
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003661pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003662 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003663{
H. Peter Anvin99941bf2002-05-14 17:44:03 +00003664 _error = errfunc;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003665 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003666 istk = nasm_malloc(sizeof(Include));
3667 istk->next = NULL;
3668 istk->conds = NULL;
3669 istk->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003670 istk->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003671 istk->fp = fopen(file, "r");
H. Peter Anvineba20a72002-04-30 20:53:55 +00003672 istk->fname = NULL;
3673 src_set_fname(nasm_strdup(file));
3674 src_set_linnum(0);
3675 istk->lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003676 if (!istk->fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003677 error(ERR_FATAL | ERR_NOFILE, "unable to open input file `%s'",
3678 file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003679 defining = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003680 init_macros();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003681 unique = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003682 if (tasm_compatible_mode) {
3683 stdmacpos = stdmac;
3684 } else {
3685 stdmacpos = &stdmac[TASM_MACRO_COUNT];
3686 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003687 any_extrastdmac = (extrastdmac != NULL);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003688 list = listgen;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003689 evaluate = eval;
3690 pass = apass;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003691}
3692
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003693static char *pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003694{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003695 char *line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003696 Token *tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003697
H. Peter Anvine2c80182005-01-15 22:15:51 +00003698 while (1) {
3699 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00003700 * Fetch a tokenized line, either from the macro-expansion
H. Peter Anvine2c80182005-01-15 22:15:51 +00003701 * buffer or from the input file.
3702 */
3703 tline = NULL;
3704 while (istk->expansion && istk->expansion->finishes) {
3705 Line *l = istk->expansion;
3706 if (!l->finishes->name && l->finishes->in_progress > 1) {
3707 Line *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003708
H. Peter Anvine2c80182005-01-15 22:15:51 +00003709 /*
3710 * This is a macro-end marker for a macro with no
3711 * name, which means it's not really a macro at all
3712 * but a %rep block, and the `in_progress' field is
3713 * more than 1, meaning that we still need to
3714 * repeat. (1 means the natural last repetition; 0
3715 * means termination by %exitrep.) We have
3716 * therefore expanded up to the %endrep, and must
3717 * push the whole block on to the expansion buffer
3718 * again. We don't bother to remove the macro-end
3719 * marker: we'd only have to generate another one
3720 * if we did.
3721 */
3722 l->finishes->in_progress--;
3723 for (l = l->finishes->expansion; l; l = l->next) {
3724 Token *t, *tt, **tail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003725
H. Peter Anvine2c80182005-01-15 22:15:51 +00003726 ll = nasm_malloc(sizeof(Line));
3727 ll->next = istk->expansion;
3728 ll->finishes = NULL;
3729 ll->first = NULL;
3730 tail = &ll->first;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003731
H. Peter Anvine2c80182005-01-15 22:15:51 +00003732 for (t = l->first; t; t = t->next) {
3733 if (t->text || t->type == TOK_WHITESPACE) {
3734 tt = *tail =
3735 new_Token(NULL, t->type, t->text, 0);
3736 tail = &tt->next;
3737 }
3738 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003739
H. Peter Anvine2c80182005-01-15 22:15:51 +00003740 istk->expansion = ll;
3741 }
3742 } else {
3743 /*
3744 * Check whether a `%rep' was started and not ended
3745 * within this macro expansion. This can happen and
3746 * should be detected. It's a fatal error because
3747 * I'm too confused to work out how to recover
3748 * sensibly from it.
3749 */
3750 if (defining) {
3751 if (defining->name)
3752 error(ERR_PANIC,
3753 "defining with name in expansion");
3754 else if (istk->mstk->name)
3755 error(ERR_FATAL,
3756 "`%%rep' without `%%endrep' within"
3757 " expansion of macro `%s'",
3758 istk->mstk->name);
3759 }
H. Peter Anvin87bc6192002-04-30 20:53:16 +00003760
H. Peter Anvine2c80182005-01-15 22:15:51 +00003761 /*
3762 * FIXME: investigate the relationship at this point between
3763 * istk->mstk and l->finishes
3764 */
3765 {
3766 MMacro *m = istk->mstk;
3767 istk->mstk = m->next_active;
3768 if (m->name) {
3769 /*
3770 * This was a real macro call, not a %rep, and
3771 * therefore the parameter information needs to
3772 * be freed.
3773 */
3774 nasm_free(m->params);
3775 free_tlist(m->iline);
3776 nasm_free(m->paramlen);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003777 l->finishes->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003778 } else
3779 free_mmacro(m);
3780 }
3781 istk->expansion = l->next;
3782 nasm_free(l);
3783 list->downlevel(LIST_MACRO);
3784 }
3785 }
3786 while (1) { /* until we get a line we can use */
H. Peter Anvineba20a72002-04-30 20:53:55 +00003787
H. Peter Anvine2c80182005-01-15 22:15:51 +00003788 if (istk->expansion) { /* from a macro expansion */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003789 char *p;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003790 Line *l = istk->expansion;
3791 if (istk->mstk)
3792 istk->mstk->lineno++;
3793 tline = l->first;
3794 istk->expansion = l->next;
3795 nasm_free(l);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003796 p = detoken(tline, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003797 list->line(LIST_MACRO, p);
3798 nasm_free(p);
3799 break;
3800 }
3801 line = read_line();
3802 if (line) { /* from the current input file */
3803 line = prepreproc(line);
Keith Kaniosb7a89542007-04-12 02:40:54 +00003804 tline = tokenize(line);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003805 nasm_free(line);
3806 break;
3807 }
3808 /*
3809 * The current file has ended; work down the istk
3810 */
3811 {
3812 Include *i = istk;
3813 fclose(i->fp);
3814 if (i->conds)
3815 error(ERR_FATAL,
3816 "expected `%%endif' before end of file");
3817 /* only set line and file name if there's a next node */
3818 if (i->next) {
3819 src_set_linnum(i->lineno);
3820 nasm_free(src_set_fname(i->fname));
3821 }
3822 istk = i->next;
3823 list->downlevel(LIST_INCLUDE);
3824 nasm_free(i);
3825 if (!istk)
3826 return NULL;
3827 }
3828 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003829
H. Peter Anvine2c80182005-01-15 22:15:51 +00003830 /*
3831 * We must expand MMacro parameters and MMacro-local labels
3832 * _before_ we plunge into directive processing, to cope
3833 * with things like `%define something %1' such as STRUC
3834 * uses. Unless we're _defining_ a MMacro, in which case
3835 * those tokens should be left alone to go into the
3836 * definition; and unless we're in a non-emitting
3837 * condition, in which case we don't want to meddle with
3838 * anything.
3839 */
3840 if (!defining && !(istk->conds && !emitting(istk->conds->state)))
3841 tline = expand_mmac_params(tline);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003842
H. Peter Anvine2c80182005-01-15 22:15:51 +00003843 /*
3844 * Check the line to see if it's a preprocessor directive.
3845 */
3846 if (do_directive(tline) == DIRECTIVE_FOUND) {
3847 continue;
3848 } else if (defining) {
3849 /*
3850 * We're defining a multi-line macro. We emit nothing
3851 * at all, and just
Keith Kaniosb7a89542007-04-12 02:40:54 +00003852 * shove the tokenized line on to the macro definition.
H. Peter Anvine2c80182005-01-15 22:15:51 +00003853 */
3854 Line *l = nasm_malloc(sizeof(Line));
3855 l->next = defining->expansion;
3856 l->first = tline;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003857 l->finishes = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003858 defining->expansion = l;
3859 continue;
3860 } else if (istk->conds && !emitting(istk->conds->state)) {
3861 /*
3862 * We're in a non-emitting branch of a condition block.
3863 * Emit nothing at all, not even a blank line: when we
3864 * emerge from the condition we'll give a line-number
3865 * directive so we keep our place correctly.
3866 */
3867 free_tlist(tline);
3868 continue;
3869 } else if (istk->mstk && !istk->mstk->in_progress) {
3870 /*
3871 * We're in a %rep block which has been terminated, so
3872 * we're walking through to the %endrep without
3873 * emitting anything. Emit nothing at all, not even a
3874 * blank line: when we emerge from the %rep block we'll
3875 * give a line-number directive so we keep our place
3876 * correctly.
3877 */
3878 free_tlist(tline);
3879 continue;
3880 } else {
3881 tline = expand_smacro(tline);
3882 if (!expand_mmacro(tline)) {
3883 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00003884 * De-tokenize the line again, and emit it.
H. Peter Anvine2c80182005-01-15 22:15:51 +00003885 */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003886 line = detoken(tline, true);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003887 free_tlist(tline);
3888 break;
3889 } else {
3890 continue; /* expand_mmacro calls free_tlist */
3891 }
3892 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003893 }
3894
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003895 return line;
3896}
3897
H. Peter Anvine2c80182005-01-15 22:15:51 +00003898static void pp_cleanup(int pass)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003899{
H. Peter Anvine2c80182005-01-15 22:15:51 +00003900 if (defining) {
3901 error(ERR_NONFATAL, "end of file while still defining macro `%s'",
3902 defining->name);
3903 free_mmacro(defining);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003904 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003905 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003906 ctx_pop();
H. Peter Anvin97a23472007-09-16 17:57:25 -07003907 free_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00003908 while (istk) {
3909 Include *i = istk;
3910 istk = istk->next;
3911 fclose(i->fp);
3912 nasm_free(i->fname);
3913 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003914 }
3915 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003916 ctx_pop();
3917 if (pass == 0) {
3918 free_llist(predef);
3919 delete_Blocks();
3920 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003921}
3922
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003923void pp_include_path(char *path)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003924{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003925 IncPath *i;
H. Peter Anvin37a321f2007-09-24 13:41:58 -07003926
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003927 i = nasm_malloc(sizeof(IncPath));
H. Peter Anvin37a321f2007-09-24 13:41:58 -07003928 i->path = path ? nasm_strdup(path) : NULL;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003929 i->next = NULL;
3930
H. Peter Anvine2c80182005-01-15 22:15:51 +00003931 if (ipath != NULL) {
3932 IncPath *j = ipath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003933 while (j->next != NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003934 j = j->next;
3935 j->next = i;
3936 } else {
3937 ipath = i;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003938 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003939}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003940
3941/*
3942 * added by alexfru:
3943 *
3944 * This function is used to "export" the include paths, e.g.
3945 * the paths specified in the '-I' command switch.
3946 * The need for such exporting is due to the 'incbin' directive,
3947 * which includes raw binary files (unlike '%include', which
3948 * includes text source files). It would be real nice to be
3949 * able to specify paths to search for incbin'ned files also.
3950 * So, this is a simple workaround.
3951 *
3952 * The function use is simple:
3953 *
3954 * The 1st call (with NULL argument) returns a pointer to the 1st path
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003955 * (char** type) or NULL if none include paths available.
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003956 *
3957 * All subsequent calls take as argument the value returned by this
3958 * function last. The return value is either the next path
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003959 * (char** type) or NULL if the end of the paths list is reached.
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003960 *
3961 * It is maybe not the best way to do things, but I didn't want
3962 * to export too much, just one or two functions and no types or
3963 * variables exported.
3964 *
3965 * Can't say I like the current situation with e.g. this path list either,
3966 * it seems to be never deallocated after creation...
3967 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003968char **pp_get_include_path_ptr(char **pPrevPath)
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003969{
3970/* This macro returns offset of a member of a structure */
3971#define GetMemberOffset(StructType,MemberName)\
3972 ((size_t)&((StructType*)0)->MemberName)
3973 IncPath *i;
3974
H. Peter Anvine2c80182005-01-15 22:15:51 +00003975 if (pPrevPath == NULL) {
3976 if (ipath != NULL)
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003977 return &ipath->path;
3978 else
3979 return NULL;
3980 }
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003981 i = (IncPath *) ((char *)pPrevPath - GetMemberOffset(IncPath, path));
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003982 i = i->next;
3983 if (i != NULL)
3984 return &i->path;
3985 else
3986 return NULL;
3987#undef GetMemberOffset
3988}
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003989
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003990void pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003991{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003992 Token *inc, *space, *name;
3993 Line *l;
3994
H. Peter Anvin734b1882002-04-30 21:01:08 +00003995 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
3996 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
3997 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003998
3999 l = nasm_malloc(sizeof(Line));
4000 l->next = predef;
4001 l->first = inc;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004002 l->finishes = false;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004003 predef = l;
4004}
4005
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004006void pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004007{
4008 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004009 Line *l;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004010 char *equals;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004011
4012 equals = strchr(definition, '=');
H. Peter Anvin734b1882002-04-30 21:01:08 +00004013 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4014 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004015 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004016 *equals = ' ';
Keith Kaniosb7a89542007-04-12 02:40:54 +00004017 space->next = tokenize(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004018 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004019 *equals = '=';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004020
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004021 l = nasm_malloc(sizeof(Line));
4022 l->next = predef;
4023 l->first = def;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004024 l->finishes = false;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004025 predef = l;
4026}
4027
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004028void pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00004029{
4030 Token *def, *space;
4031 Line *l;
4032
H. Peter Anvin734b1882002-04-30 21:01:08 +00004033 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4034 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Keith Kaniosb7a89542007-04-12 02:40:54 +00004035 space->next = tokenize(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00004036
4037 l = nasm_malloc(sizeof(Line));
4038 l->next = predef;
4039 l->first = def;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004040 l->finishes = false;
H. Peter Anvin620515a2002-04-30 20:57:38 +00004041 predef = l;
4042}
4043
Keith Kaniosb7a89542007-04-12 02:40:54 +00004044/*
4045 * Added by Keith Kanios:
4046 *
4047 * This function is used to assist with "runtime" preprocessor
4048 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4049 *
4050 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4051 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4052 */
4053
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004054void pp_runtime(char *definition)
Keith Kaniosb7a89542007-04-12 02:40:54 +00004055{
4056 Token *def;
4057
4058 def = tokenize(definition);
4059 if(do_directive(def) == NO_DIRECTIVE_FOUND)
4060 free_tlist(def);
4061
4062}
4063
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004064void pp_extra_stdmac(const char **macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004065{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004066 extrastdmac = macros;
4067}
4068
Keith Kaniosb7a89542007-04-12 02:40:54 +00004069static void make_tok_num(Token * tok, int32_t val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004070{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004071 char numbuf[20];
Keith Kanios93f2e9a2007-04-14 00:10:59 +00004072 snprintf(numbuf, sizeof(numbuf), "%"PRId32"", val);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004073 tok->text = nasm_strdup(numbuf);
4074 tok->type = TOK_NUMBER;
4075}
4076
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004077Preproc nasmpp = {
4078 pp_reset,
4079 pp_getline,
4080 pp_cleanup
4081};