blob: 0c059ee341b77fc762980a618ce5fee3851b260e [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 Anvind7ed89e2002-04-30 20:52:08 +000079 int 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 Anvin54901e12007-10-11 00:03:26 -0700108 int 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;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000120 uint32_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
Keith Kaniosb7a89542007-04-12 02:40:54 +0000330static uint32_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) {
1038 int 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;
1454 searching.in_progress = false;
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 Anvin76690a12002-04-30 20:52:49 +00001611
1612 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001613
H. Peter Anvineba20a72002-04-30 20:53:55 +00001614 skip_white_(tline);
1615 if (!tok_type_(tline, TOK_PREPROC_ID) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001616 (tline->text[1] == '%' || tline->text[1] == '$'
1617 || tline->text[1] == '!'))
1618 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001619
H. Peter Anvin4169a472007-09-12 01:29:43 +00001620 i = pp_token_hash(tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001621
1622 /*
1623 * If we're in a non-emitting branch of a condition construct,
H. Peter Anvin76690a12002-04-30 20:52:49 +00001624 * or walking to the end of an already terminated %rep block,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001625 * we should ignore all directives except for condition
1626 * directives.
1627 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001628 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001629 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
1630 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001631 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001632
1633 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001634 * If we're defining a macro or reading a %rep block, we should
1635 * ignore all directives except for %macro/%imacro (which
1636 * generate an error), %endm/%endmacro, and (only if we're in a
H. Peter Anvineba20a72002-04-30 20:53:55 +00001637 * %rep block) %endrep. If we're in a %rep block, another %rep
1638 * causes an error, so should be let through.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001639 */
1640 if (defining && i != PP_MACRO && i != PP_IMACRO &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001641 i != PP_ENDMACRO && i != PP_ENDM &&
1642 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
1643 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001644 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001645
H. Peter Anvin4169a472007-09-12 01:29:43 +00001646 switch (i) {
1647 case PP_INVALID:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001648 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
1649 tline->text);
1650 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001651
H. Peter Anvine2c80182005-01-15 22:15:51 +00001652 case PP_STACKSIZE:
1653 /* Directive to tell NASM what the default stack size is. The
1654 * default is for a 16-bit stack, and this can be overriden with
1655 * %stacksize large.
1656 * the following form:
1657 *
1658 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1659 */
1660 tline = tline->next;
1661 if (tline && tline->type == TOK_WHITESPACE)
1662 tline = tline->next;
1663 if (!tline || tline->type != TOK_ID) {
1664 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
1665 free_tlist(origline);
1666 return DIRECTIVE_FOUND;
1667 }
1668 if (nasm_stricmp(tline->text, "flat") == 0) {
1669 /* All subsequent ARG directives are for a 32-bit stack */
1670 StackSize = 4;
1671 StackPointer = "ebp";
1672 ArgOffset = 8;
1673 LocalOffset = 4;
1674 } else if (nasm_stricmp(tline->text, "large") == 0) {
1675 /* All subsequent ARG directives are for a 16-bit stack,
1676 * far function call.
1677 */
1678 StackSize = 2;
1679 StackPointer = "bp";
1680 ArgOffset = 4;
1681 LocalOffset = 2;
1682 } else if (nasm_stricmp(tline->text, "small") == 0) {
1683 /* All subsequent ARG directives are for a 16-bit stack,
1684 * far function call. We don't support near functions.
1685 */
1686 StackSize = 2;
1687 StackPointer = "bp";
1688 ArgOffset = 6;
1689 LocalOffset = 2;
1690 } else {
1691 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
1692 free_tlist(origline);
1693 return DIRECTIVE_FOUND;
1694 }
1695 free_tlist(origline);
1696 return DIRECTIVE_FOUND;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001697
H. Peter Anvine2c80182005-01-15 22:15:51 +00001698 case PP_ARG:
1699 /* TASM like ARG directive to define arguments to functions, in
1700 * the following form:
1701 *
1702 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1703 */
1704 offset = ArgOffset;
1705 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001706 char *arg, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00001707 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001708
H. Peter Anvine2c80182005-01-15 22:15:51 +00001709 /* Find the argument name */
1710 tline = tline->next;
1711 if (tline && tline->type == TOK_WHITESPACE)
1712 tline = tline->next;
1713 if (!tline || tline->type != TOK_ID) {
1714 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
1715 free_tlist(origline);
1716 return DIRECTIVE_FOUND;
1717 }
1718 arg = tline->text;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001719
H. Peter Anvine2c80182005-01-15 22:15:51 +00001720 /* Find the argument size type */
1721 tline = tline->next;
1722 if (!tline || tline->type != TOK_OTHER
1723 || tline->text[0] != ':') {
1724 error(ERR_NONFATAL,
1725 "Syntax error processing `%%arg' directive");
1726 free_tlist(origline);
1727 return DIRECTIVE_FOUND;
1728 }
1729 tline = tline->next;
1730 if (!tline || tline->type != TOK_ID) {
1731 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
1732 free_tlist(origline);
1733 return DIRECTIVE_FOUND;
1734 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001735
H. Peter Anvine2c80182005-01-15 22:15:51 +00001736 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001737 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001738 tt = expand_smacro(tt);
1739 if (nasm_stricmp(tt->text, "byte") == 0) {
1740 size = MAX(StackSize, 1);
1741 } else if (nasm_stricmp(tt->text, "word") == 0) {
1742 size = MAX(StackSize, 2);
1743 } else if (nasm_stricmp(tt->text, "dword") == 0) {
1744 size = MAX(StackSize, 4);
1745 } else if (nasm_stricmp(tt->text, "qword") == 0) {
1746 size = MAX(StackSize, 8);
1747 } else if (nasm_stricmp(tt->text, "tword") == 0) {
1748 size = MAX(StackSize, 10);
1749 } else {
1750 error(ERR_NONFATAL,
1751 "Invalid size type for `%%arg' missing directive");
1752 free_tlist(tt);
1753 free_tlist(origline);
1754 return DIRECTIVE_FOUND;
1755 }
1756 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001757
H. Peter Anvine2c80182005-01-15 22:15:51 +00001758 /* Now define the macro for the argument */
1759 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
1760 arg, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001761 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001762 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001763
H. Peter Anvine2c80182005-01-15 22:15:51 +00001764 /* Move to the next argument in the list */
1765 tline = tline->next;
1766 if (tline && tline->type == TOK_WHITESPACE)
1767 tline = tline->next;
1768 }
1769 while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
1770 free_tlist(origline);
1771 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001772
H. Peter Anvine2c80182005-01-15 22:15:51 +00001773 case PP_LOCAL:
1774 /* TASM like LOCAL directive to define local variables for a
1775 * function, in the following form:
1776 *
1777 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
1778 *
1779 * The '= LocalSize' at the end is ignored by NASM, but is
1780 * required by TASM to define the local parameter size (and used
1781 * by the TASM macro package).
1782 */
1783 offset = LocalOffset;
1784 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001785 char *local, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00001786 int size = StackSize;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001787
H. Peter Anvine2c80182005-01-15 22:15:51 +00001788 /* Find the argument name */
1789 tline = tline->next;
1790 if (tline && tline->type == TOK_WHITESPACE)
1791 tline = tline->next;
1792 if (!tline || tline->type != TOK_ID) {
1793 error(ERR_NONFATAL,
1794 "`%%local' missing argument parameter");
1795 free_tlist(origline);
1796 return DIRECTIVE_FOUND;
1797 }
1798 local = tline->text;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001799
H. Peter Anvine2c80182005-01-15 22:15:51 +00001800 /* Find the argument size type */
1801 tline = tline->next;
1802 if (!tline || tline->type != TOK_OTHER
1803 || tline->text[0] != ':') {
1804 error(ERR_NONFATAL,
1805 "Syntax error processing `%%local' directive");
1806 free_tlist(origline);
1807 return DIRECTIVE_FOUND;
1808 }
1809 tline = tline->next;
1810 if (!tline || tline->type != TOK_ID) {
1811 error(ERR_NONFATAL,
1812 "`%%local' missing size type parameter");
1813 free_tlist(origline);
1814 return DIRECTIVE_FOUND;
1815 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001816
H. Peter Anvine2c80182005-01-15 22:15:51 +00001817 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001818 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001819 tt = expand_smacro(tt);
1820 if (nasm_stricmp(tt->text, "byte") == 0) {
1821 size = MAX(StackSize, 1);
1822 } else if (nasm_stricmp(tt->text, "word") == 0) {
1823 size = MAX(StackSize, 2);
1824 } else if (nasm_stricmp(tt->text, "dword") == 0) {
1825 size = MAX(StackSize, 4);
1826 } else if (nasm_stricmp(tt->text, "qword") == 0) {
1827 size = MAX(StackSize, 8);
1828 } else if (nasm_stricmp(tt->text, "tword") == 0) {
1829 size = MAX(StackSize, 10);
1830 } else {
1831 error(ERR_NONFATAL,
1832 "Invalid size type for `%%local' missing directive");
1833 free_tlist(tt);
1834 free_tlist(origline);
1835 return DIRECTIVE_FOUND;
1836 }
1837 free_tlist(tt);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001838
H. Peter Anvine2c80182005-01-15 22:15:51 +00001839 /* Now define the macro for the argument */
1840 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
1841 local, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001842 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001843 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001844
H. Peter Anvine2c80182005-01-15 22:15:51 +00001845 /* Now define the assign to setup the enter_c macro correctly */
1846 snprintf(directive, sizeof(directive),
1847 "%%assign %%$localsize %%$localsize+%d", size);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001848 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001849
H. Peter Anvine2c80182005-01-15 22:15:51 +00001850 /* Move to the next argument in the list */
1851 tline = tline->next;
1852 if (tline && tline->type == TOK_WHITESPACE)
1853 tline = tline->next;
1854 }
1855 while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
1856 free_tlist(origline);
1857 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001858
H. Peter Anvine2c80182005-01-15 22:15:51 +00001859 case PP_CLEAR:
1860 if (tline->next)
1861 error(ERR_WARNING, "trailing garbage after `%%clear' ignored");
H. Peter Anvin97a23472007-09-16 17:57:25 -07001862 free_macros();
1863 init_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001864 free_tlist(origline);
1865 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001866
H. Peter Anvine2c80182005-01-15 22:15:51 +00001867 case PP_INCLUDE:
1868 tline = tline->next;
1869 skip_white_(tline);
1870 if (!tline || (tline->type != TOK_STRING &&
1871 tline->type != TOK_INTERNAL_STRING)) {
1872 error(ERR_NONFATAL, "`%%include' expects a file name");
1873 free_tlist(origline);
1874 return DIRECTIVE_FOUND; /* but we did _something_ */
1875 }
1876 if (tline->next)
1877 error(ERR_WARNING,
1878 "trailing garbage after `%%include' ignored");
1879 if (tline->type != TOK_INTERNAL_STRING) {
1880 p = tline->text + 1; /* point past the quote to the name */
1881 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
1882 } else
1883 p = tline->text; /* internal_string is easier */
1884 expand_macros_in_string(&p);
1885 inc = nasm_malloc(sizeof(Include));
1886 inc->next = istk;
1887 inc->conds = NULL;
1888 inc->fp = inc_fopen(p);
H. Peter Anvin37a321f2007-09-24 13:41:58 -07001889 if (!inc->fp && pass == 0) {
1890 /* -MG given but file not found */
1891 nasm_free(inc);
1892 } else {
1893 inc->fname = src_set_fname(p);
1894 inc->lineno = src_set_linnum(0);
1895 inc->lineinc = 1;
1896 inc->expansion = NULL;
1897 inc->mstk = NULL;
1898 istk = inc;
1899 list->uplevel(LIST_INCLUDE);
1900 }
1901 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001902 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001903
H. Peter Anvine2c80182005-01-15 22:15:51 +00001904 case PP_PUSH:
1905 tline = tline->next;
1906 skip_white_(tline);
1907 tline = expand_id(tline);
1908 if (!tok_type_(tline, TOK_ID)) {
1909 error(ERR_NONFATAL, "`%%push' expects a context identifier");
1910 free_tlist(origline);
1911 return DIRECTIVE_FOUND; /* but we did _something_ */
1912 }
1913 if (tline->next)
1914 error(ERR_WARNING, "trailing garbage after `%%push' ignored");
1915 ctx = nasm_malloc(sizeof(Context));
1916 ctx->next = cstk;
1917 ctx->localmac = NULL;
1918 ctx->name = nasm_strdup(tline->text);
1919 ctx->number = unique++;
1920 cstk = ctx;
1921 free_tlist(origline);
1922 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001923
H. Peter Anvine2c80182005-01-15 22:15:51 +00001924 case PP_REPL:
1925 tline = tline->next;
1926 skip_white_(tline);
1927 tline = expand_id(tline);
1928 if (!tok_type_(tline, TOK_ID)) {
1929 error(ERR_NONFATAL, "`%%repl' expects a context identifier");
1930 free_tlist(origline);
1931 return DIRECTIVE_FOUND; /* but we did _something_ */
1932 }
1933 if (tline->next)
1934 error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
1935 if (!cstk)
1936 error(ERR_NONFATAL, "`%%repl': context stack is empty");
1937 else {
1938 nasm_free(cstk->name);
1939 cstk->name = nasm_strdup(tline->text);
1940 }
1941 free_tlist(origline);
1942 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001943
H. Peter Anvine2c80182005-01-15 22:15:51 +00001944 case PP_POP:
1945 if (tline->next)
1946 error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
1947 if (!cstk)
1948 error(ERR_NONFATAL, "`%%pop': context stack is already empty");
1949 else
1950 ctx_pop();
1951 free_tlist(origline);
1952 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001953
H. Peter Anvine2c80182005-01-15 22:15:51 +00001954 case PP_ERROR:
1955 tline->next = expand_smacro(tline->next);
1956 tline = tline->next;
1957 skip_white_(tline);
1958 if (tok_type_(tline, TOK_STRING)) {
1959 p = tline->text + 1; /* point past the quote to the name */
1960 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
1961 expand_macros_in_string(&p);
1962 error(ERR_NONFATAL, "%s", p);
1963 nasm_free(p);
1964 } else {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001965 p = detoken(tline, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001966 error(ERR_WARNING, "%s", p);
1967 nasm_free(p);
1968 }
1969 free_tlist(origline);
1970 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001971
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001972 CASE_PP_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001973 if (istk->conds && !emitting(istk->conds->state))
1974 j = COND_NEVER;
1975 else {
1976 j = if_condition(tline->next, i);
1977 tline->next = NULL; /* it got freed */
1978 free_tlist(origline);
1979 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
1980 }
1981 cond = nasm_malloc(sizeof(Cond));
1982 cond->next = istk->conds;
1983 cond->state = j;
1984 istk->conds = cond;
1985 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001986
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001987 CASE_PP_ELIF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001988 if (!istk->conds)
H. Peter Anvin4169a472007-09-12 01:29:43 +00001989 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001990 if (emitting(istk->conds->state)
1991 || istk->conds->state == COND_NEVER)
1992 istk->conds->state = COND_NEVER;
1993 else {
1994 /*
1995 * IMPORTANT: In the case of %if, we will already have
1996 * called expand_mmac_params(); however, if we're
1997 * processing an %elif we must have been in a
1998 * non-emitting mode, which would have inhibited
1999 * the normal invocation of expand_mmac_params(). Therefore,
2000 * we have to do it explicitly here.
2001 */
2002 j = if_condition(expand_mmac_params(tline->next), i);
2003 tline->next = NULL; /* it got freed */
2004 free_tlist(origline);
2005 istk->conds->state =
2006 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2007 }
2008 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002009
H. Peter Anvine2c80182005-01-15 22:15:51 +00002010 case PP_ELSE:
2011 if (tline->next)
2012 error(ERR_WARNING, "trailing garbage after `%%else' ignored");
2013 if (!istk->conds)
2014 error(ERR_FATAL, "`%%else': no matching `%%if'");
2015 if (emitting(istk->conds->state)
2016 || istk->conds->state == COND_NEVER)
2017 istk->conds->state = COND_ELSE_FALSE;
2018 else
2019 istk->conds->state = COND_ELSE_TRUE;
2020 free_tlist(origline);
2021 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002022
H. Peter Anvine2c80182005-01-15 22:15:51 +00002023 case PP_ENDIF:
2024 if (tline->next)
2025 error(ERR_WARNING, "trailing garbage after `%%endif' ignored");
2026 if (!istk->conds)
2027 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2028 cond = istk->conds;
2029 istk->conds = cond->next;
2030 nasm_free(cond);
2031 free_tlist(origline);
2032 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002033
H. Peter Anvine2c80182005-01-15 22:15:51 +00002034 case PP_MACRO:
2035 case PP_IMACRO:
2036 if (defining)
2037 error(ERR_FATAL,
2038 "`%%%smacro': already defining a macro",
2039 (i == PP_IMACRO ? "i" : ""));
2040 tline = tline->next;
2041 skip_white_(tline);
2042 tline = expand_id(tline);
2043 if (!tok_type_(tline, TOK_ID)) {
2044 error(ERR_NONFATAL,
2045 "`%%%smacro' expects a macro name",
2046 (i == PP_IMACRO ? "i" : ""));
2047 return DIRECTIVE_FOUND;
2048 }
2049 defining = nasm_malloc(sizeof(MMacro));
2050 defining->name = nasm_strdup(tline->text);
2051 defining->casesense = (i == PP_MACRO);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002052 defining->plus = false;
2053 defining->nolist = false;
2054 defining->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002055 defining->rep_nest = NULL;
2056 tline = expand_smacro(tline->next);
2057 skip_white_(tline);
2058 if (!tok_type_(tline, TOK_NUMBER)) {
2059 error(ERR_NONFATAL,
2060 "`%%%smacro' expects a parameter count",
2061 (i == PP_IMACRO ? "i" : ""));
2062 defining->nparam_min = defining->nparam_max = 0;
2063 } else {
2064 defining->nparam_min = defining->nparam_max =
H. Peter Anvin70055962007-10-11 00:05:31 -07002065 readnum(tline->text, &err);
2066 if (err)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002067 error(ERR_NONFATAL,
2068 "unable to parse parameter count `%s'", tline->text);
2069 }
2070 if (tline && tok_is_(tline->next, "-")) {
2071 tline = tline->next->next;
2072 if (tok_is_(tline, "*"))
2073 defining->nparam_max = INT_MAX;
2074 else if (!tok_type_(tline, TOK_NUMBER))
2075 error(ERR_NONFATAL,
2076 "`%%%smacro' expects a parameter count after `-'",
2077 (i == PP_IMACRO ? "i" : ""));
2078 else {
H. Peter Anvin70055962007-10-11 00:05:31 -07002079 defining->nparam_max = readnum(tline->text, &err);
2080 if (err)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002081 error(ERR_NONFATAL,
2082 "unable to parse parameter count `%s'",
2083 tline->text);
2084 if (defining->nparam_min > defining->nparam_max)
2085 error(ERR_NONFATAL,
2086 "minimum parameter count exceeds maximum");
2087 }
2088 }
2089 if (tline && tok_is_(tline->next, "+")) {
2090 tline = tline->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002091 defining->plus = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002092 }
2093 if (tline && tok_type_(tline->next, TOK_ID) &&
2094 !nasm_stricmp(tline->next->text, ".nolist")) {
2095 tline = tline->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002096 defining->nolist = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002097 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07002098 mmac = (MMacro *) hash_findix(mmacros, defining->name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002099 while (mmac) {
2100 if (!strcmp(mmac->name, defining->name) &&
2101 (mmac->nparam_min <= defining->nparam_max
2102 || defining->plus)
2103 && (defining->nparam_min <= mmac->nparam_max
2104 || mmac->plus)) {
2105 error(ERR_WARNING,
2106 "redefining multi-line macro `%s'", defining->name);
2107 break;
2108 }
2109 mmac = mmac->next;
2110 }
2111 /*
2112 * Handle default parameters.
2113 */
2114 if (tline && tline->next) {
2115 defining->dlist = tline->next;
2116 tline->next = NULL;
2117 count_mmac_params(defining->dlist, &defining->ndefs,
2118 &defining->defaults);
2119 } else {
2120 defining->dlist = NULL;
2121 defining->defaults = NULL;
2122 }
2123 defining->expansion = NULL;
2124 free_tlist(origline);
2125 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002126
H. Peter Anvine2c80182005-01-15 22:15:51 +00002127 case PP_ENDM:
2128 case PP_ENDMACRO:
2129 if (!defining) {
2130 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2131 return DIRECTIVE_FOUND;
2132 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07002133 mmhead = (MMacro **) hash_findi_add(mmacros, defining->name);
2134 defining->next = *mmhead;
2135 *mmhead = defining;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002136 defining = NULL;
2137 free_tlist(origline);
2138 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002139
H. Peter Anvine2c80182005-01-15 22:15:51 +00002140 case PP_ROTATE:
2141 if (tline->next && tline->next->type == TOK_WHITESPACE)
2142 tline = tline->next;
2143 if (tline->next == NULL) {
2144 free_tlist(origline);
2145 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2146 return DIRECTIVE_FOUND;
2147 }
2148 t = expand_smacro(tline->next);
2149 tline->next = NULL;
2150 free_tlist(origline);
2151 tline = t;
2152 tptr = &t;
2153 tokval.t_type = TOKEN_INVALID;
2154 evalresult =
2155 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2156 free_tlist(tline);
2157 if (!evalresult)
2158 return DIRECTIVE_FOUND;
2159 if (tokval.t_type)
2160 error(ERR_WARNING,
2161 "trailing garbage after expression ignored");
2162 if (!is_simple(evalresult)) {
2163 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2164 return DIRECTIVE_FOUND;
2165 }
2166 mmac = istk->mstk;
2167 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2168 mmac = mmac->next_active;
2169 if (!mmac) {
2170 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2171 } else if (mmac->nparam == 0) {
2172 error(ERR_NONFATAL,
2173 "`%%rotate' invoked within macro without parameters");
2174 } else {
H. Peter Anvin25a99342007-09-22 17:45:45 -07002175 int rotate = mmac->rotate + reloc_value(evalresult);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002176
H. Peter Anvin25a99342007-09-22 17:45:45 -07002177 rotate %= (int)mmac->nparam;
2178 if (rotate < 0)
2179 rotate += mmac->nparam;
2180
2181 mmac->rotate = rotate;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002182 }
2183 return DIRECTIVE_FOUND;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002184
H. Peter Anvine2c80182005-01-15 22:15:51 +00002185 case PP_REP:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002186 nolist = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002187 do {
2188 tline = tline->next;
2189 } while (tok_type_(tline, TOK_WHITESPACE));
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002190
H. Peter Anvine2c80182005-01-15 22:15:51 +00002191 if (tok_type_(tline, TOK_ID) &&
2192 nasm_stricmp(tline->text, ".nolist") == 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002193 nolist = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002194 do {
2195 tline = tline->next;
2196 } while (tok_type_(tline, TOK_WHITESPACE));
2197 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002198
H. Peter Anvine2c80182005-01-15 22:15:51 +00002199 if (tline) {
2200 t = expand_smacro(tline);
2201 tptr = &t;
2202 tokval.t_type = TOKEN_INVALID;
2203 evalresult =
2204 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2205 if (!evalresult) {
2206 free_tlist(origline);
2207 return DIRECTIVE_FOUND;
2208 }
2209 if (tokval.t_type)
2210 error(ERR_WARNING,
2211 "trailing garbage after expression ignored");
2212 if (!is_simple(evalresult)) {
2213 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2214 return DIRECTIVE_FOUND;
2215 }
2216 i = (int)reloc_value(evalresult) + 1;
2217 } else {
2218 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
2219 i = 0;
2220 }
2221 free_tlist(origline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002222
H. Peter Anvine2c80182005-01-15 22:15:51 +00002223 tmp_defining = defining;
2224 defining = nasm_malloc(sizeof(MMacro));
2225 defining->name = NULL; /* flags this macro as a %rep block */
H. Peter Anvin70055962007-10-11 00:05:31 -07002226 defining->casesense = false;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002227 defining->plus = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002228 defining->nolist = nolist;
2229 defining->in_progress = i;
2230 defining->nparam_min = defining->nparam_max = 0;
2231 defining->defaults = NULL;
2232 defining->dlist = NULL;
2233 defining->expansion = NULL;
2234 defining->next_active = istk->mstk;
2235 defining->rep_nest = tmp_defining;
2236 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002237
H. Peter Anvine2c80182005-01-15 22:15:51 +00002238 case PP_ENDREP:
2239 if (!defining || defining->name) {
2240 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2241 return DIRECTIVE_FOUND;
2242 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002243
H. Peter Anvine2c80182005-01-15 22:15:51 +00002244 /*
2245 * Now we have a "macro" defined - although it has no name
2246 * and we won't be entering it in the hash tables - we must
2247 * push a macro-end marker for it on to istk->expansion.
2248 * After that, it will take care of propagating itself (a
2249 * macro-end marker line for a macro which is really a %rep
2250 * block will cause the macro to be re-expanded, complete
2251 * with another macro-end marker to ensure the process
2252 * continues) until the whole expansion is forcibly removed
2253 * from istk->expansion by a %exitrep.
2254 */
2255 l = nasm_malloc(sizeof(Line));
2256 l->next = istk->expansion;
2257 l->finishes = defining;
2258 l->first = NULL;
2259 istk->expansion = l;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002260
H. Peter Anvine2c80182005-01-15 22:15:51 +00002261 istk->mstk = defining;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002262
H. Peter Anvine2c80182005-01-15 22:15:51 +00002263 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2264 tmp_defining = defining;
2265 defining = defining->rep_nest;
2266 free_tlist(origline);
2267 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002268
H. Peter Anvine2c80182005-01-15 22:15:51 +00002269 case PP_EXITREP:
2270 /*
2271 * We must search along istk->expansion until we hit a
2272 * macro-end marker for a macro with no name. Then we set
2273 * its `in_progress' flag to 0.
2274 */
2275 for (l = istk->expansion; l; l = l->next)
2276 if (l->finishes && !l->finishes->name)
2277 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002278
H. Peter Anvine2c80182005-01-15 22:15:51 +00002279 if (l)
2280 l->finishes->in_progress = 0;
2281 else
2282 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2283 free_tlist(origline);
2284 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002285
H. Peter Anvine2c80182005-01-15 22:15:51 +00002286 case PP_XDEFINE:
2287 case PP_IXDEFINE:
2288 case PP_DEFINE:
2289 case PP_IDEFINE:
2290 tline = tline->next;
2291 skip_white_(tline);
2292 tline = expand_id(tline);
2293 if (!tline || (tline->type != TOK_ID &&
2294 (tline->type != TOK_PREPROC_ID ||
2295 tline->text[1] != '$'))) {
2296 error(ERR_NONFATAL,
2297 "`%%%s%sdefine' expects a macro identifier",
2298 ((i == PP_IDEFINE || i == PP_IXDEFINE) ? "i" : ""),
2299 ((i == PP_XDEFINE || i == PP_IXDEFINE) ? "x" : ""));
2300 free_tlist(origline);
2301 return DIRECTIVE_FOUND;
2302 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002303
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002304 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002305
H. Peter Anvine2c80182005-01-15 22:15:51 +00002306 mname = tline->text;
2307 last = tline;
2308 param_start = tline = tline->next;
2309 nparam = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002310
H. Peter Anvine2c80182005-01-15 22:15:51 +00002311 /* Expand the macro definition now for %xdefine and %ixdefine */
2312 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2313 tline = expand_smacro(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002314
H. Peter Anvine2c80182005-01-15 22:15:51 +00002315 if (tok_is_(tline, "(")) {
2316 /*
2317 * This macro has parameters.
2318 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002319
H. Peter Anvine2c80182005-01-15 22:15:51 +00002320 tline = tline->next;
2321 while (1) {
2322 skip_white_(tline);
2323 if (!tline) {
2324 error(ERR_NONFATAL, "parameter identifier expected");
2325 free_tlist(origline);
2326 return DIRECTIVE_FOUND;
2327 }
2328 if (tline->type != TOK_ID) {
2329 error(ERR_NONFATAL,
2330 "`%s': parameter identifier expected",
2331 tline->text);
2332 free_tlist(origline);
2333 return DIRECTIVE_FOUND;
2334 }
2335 tline->type = TOK_SMAC_PARAM + nparam++;
2336 tline = tline->next;
2337 skip_white_(tline);
2338 if (tok_is_(tline, ",")) {
2339 tline = tline->next;
2340 continue;
2341 }
2342 if (!tok_is_(tline, ")")) {
2343 error(ERR_NONFATAL,
2344 "`)' expected to terminate macro template");
2345 free_tlist(origline);
2346 return DIRECTIVE_FOUND;
2347 }
2348 break;
2349 }
2350 last = tline;
2351 tline = tline->next;
2352 }
2353 if (tok_type_(tline, TOK_WHITESPACE))
2354 last = tline, tline = tline->next;
2355 macro_start = NULL;
2356 last->next = NULL;
2357 t = tline;
2358 while (t) {
2359 if (t->type == TOK_ID) {
2360 for (tt = param_start; tt; tt = tt->next)
2361 if (tt->type >= TOK_SMAC_PARAM &&
2362 !strcmp(tt->text, t->text))
2363 t->type = tt->type;
2364 }
2365 tt = t->next;
2366 t->next = macro_start;
2367 macro_start = t;
2368 t = tt;
2369 }
2370 /*
2371 * Good. We now have a macro name, a parameter count, and a
2372 * token list (in reverse order) for an expansion. We ought
2373 * to be OK just to create an SMacro, store it, and let
2374 * free_tlist have the rest of the line (which we have
2375 * carefully re-terminated after chopping off the expansion
2376 * from the end).
2377 */
2378 if (smacro_defined(ctx, mname, nparam, &smac, i == PP_DEFINE)) {
2379 if (!smac) {
2380 error(ERR_WARNING,
2381 "single-line macro `%s' defined both with and"
2382 " without parameters", mname);
2383 free_tlist(origline);
2384 free_tlist(macro_start);
2385 return DIRECTIVE_FOUND;
2386 } else {
2387 /*
2388 * We're redefining, so we have to take over an
2389 * existing SMacro structure. This means freeing
2390 * what was already in it.
2391 */
2392 nasm_free(smac->name);
2393 free_tlist(smac->expansion);
2394 }
2395 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002396 if (!ctx)
2397 smhead = (SMacro **) hash_findi_add(smacros, mname);
2398 else
2399 smhead = &ctx->localmac;
2400
H. Peter Anvine2c80182005-01-15 22:15:51 +00002401 smac = nasm_malloc(sizeof(SMacro));
2402 smac->next = *smhead;
2403 *smhead = smac;
2404 }
2405 smac->name = nasm_strdup(mname);
2406 smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE));
2407 smac->nparam = nparam;
2408 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002409 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002410 free_tlist(origline);
2411 return DIRECTIVE_FOUND;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002412
H. Peter Anvine2c80182005-01-15 22:15:51 +00002413 case PP_UNDEF:
2414 tline = tline->next;
2415 skip_white_(tline);
2416 tline = expand_id(tline);
2417 if (!tline || (tline->type != TOK_ID &&
2418 (tline->type != TOK_PREPROC_ID ||
2419 tline->text[1] != '$'))) {
2420 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2421 free_tlist(origline);
2422 return DIRECTIVE_FOUND;
2423 }
2424 if (tline->next) {
2425 error(ERR_WARNING,
2426 "trailing garbage after macro name ignored");
2427 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002428
H. Peter Anvine2c80182005-01-15 22:15:51 +00002429 /* Find the context that symbol belongs to */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002430 ctx = get_ctx(tline->text, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002431 if (!ctx)
H. Peter Anvin97a23472007-09-16 17:57:25 -07002432 smhead = (SMacro **) hash_findi(smacros, tline->text, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002433 else
2434 smhead = &ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002435
H. Peter Anvin97a23472007-09-16 17:57:25 -07002436 if (smhead) {
2437 SMacro *s, **sp;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002438
H. Peter Anvin97a23472007-09-16 17:57:25 -07002439 mname = tline->text;
2440 last = tline;
2441 last->next = NULL;
2442
2443 /*
2444 * We now have a macro name... go hunt for it.
2445 */
H. Peter Anvine373efd2007-09-24 21:33:17 -07002446 sp = smhead;
2447 while ((s = *sp) != NULL) {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002448 if (!mstrcmp(s->name, tline->text, s->casesense)) {
2449 *sp = s->next;
2450 nasm_free(s->name);
2451 free_tlist(s->expansion);
2452 nasm_free(s);
H. Peter Anvine373efd2007-09-24 21:33:17 -07002453 } else {
2454 sp = &s->next;
H. Peter Anvin97a23472007-09-16 17:57:25 -07002455 }
2456 }
2457 free_tlist(origline);
2458 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002459 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002460
H. Peter Anvine2c80182005-01-15 22:15:51 +00002461 case PP_STRLEN:
2462 tline = tline->next;
2463 skip_white_(tline);
2464 tline = expand_id(tline);
2465 if (!tline || (tline->type != TOK_ID &&
2466 (tline->type != TOK_PREPROC_ID ||
2467 tline->text[1] != '$'))) {
2468 error(ERR_NONFATAL,
2469 "`%%strlen' expects a macro identifier as first parameter");
2470 free_tlist(origline);
2471 return DIRECTIVE_FOUND;
2472 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002473 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002474
H. Peter Anvine2c80182005-01-15 22:15:51 +00002475 mname = tline->text;
2476 last = tline;
2477 tline = expand_smacro(tline->next);
2478 last->next = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002479
H. Peter Anvine2c80182005-01-15 22:15:51 +00002480 t = tline;
2481 while (tok_type_(t, TOK_WHITESPACE))
2482 t = t->next;
2483 /* t should now point to the string */
2484 if (t->type != TOK_STRING) {
2485 error(ERR_NONFATAL,
2486 "`%%strlen` requires string as second parameter");
2487 free_tlist(tline);
2488 free_tlist(origline);
2489 return DIRECTIVE_FOUND;
2490 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002491
H. Peter Anvine2c80182005-01-15 22:15:51 +00002492 macro_start = nasm_malloc(sizeof(*macro_start));
2493 macro_start->next = NULL;
2494 make_tok_num(macro_start, strlen(t->text) - 2);
2495 macro_start->mac = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002496
H. Peter Anvine2c80182005-01-15 22:15:51 +00002497 /*
2498 * We now have a macro name, an implicit parameter count of
2499 * zero, and a numeric token to use as an expansion. Create
2500 * and store an SMacro.
2501 */
2502 if (smacro_defined(ctx, mname, 0, &smac, i == PP_STRLEN)) {
2503 if (!smac)
2504 error(ERR_WARNING,
2505 "single-line macro `%s' defined both with and"
2506 " without parameters", mname);
2507 else {
2508 /*
2509 * We're redefining, so we have to take over an
2510 * existing SMacro structure. This means freeing
2511 * what was already in it.
2512 */
2513 nasm_free(smac->name);
2514 free_tlist(smac->expansion);
2515 }
2516 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002517 if (!ctx)
2518 smhead = (SMacro **) hash_findi_add(smacros, mname);
2519 else
2520 smhead = &ctx->localmac;
2521
H. Peter Anvine2c80182005-01-15 22:15:51 +00002522 smac = nasm_malloc(sizeof(SMacro));
2523 smac->next = *smhead;
2524 *smhead = smac;
2525 }
2526 smac->name = nasm_strdup(mname);
2527 smac->casesense = (i == PP_STRLEN);
2528 smac->nparam = 0;
2529 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002530 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002531 free_tlist(tline);
2532 free_tlist(origline);
2533 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002534
H. Peter Anvine2c80182005-01-15 22:15:51 +00002535 case PP_SUBSTR:
2536 tline = tline->next;
2537 skip_white_(tline);
2538 tline = expand_id(tline);
2539 if (!tline || (tline->type != TOK_ID &&
2540 (tline->type != TOK_PREPROC_ID ||
2541 tline->text[1] != '$'))) {
2542 error(ERR_NONFATAL,
2543 "`%%substr' expects a macro identifier as first parameter");
2544 free_tlist(origline);
2545 return DIRECTIVE_FOUND;
2546 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002547 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002548
H. Peter Anvine2c80182005-01-15 22:15:51 +00002549 mname = tline->text;
2550 last = tline;
2551 tline = expand_smacro(tline->next);
2552 last->next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002553
H. Peter Anvine2c80182005-01-15 22:15:51 +00002554 t = tline->next;
2555 while (tok_type_(t, TOK_WHITESPACE))
2556 t = t->next;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002557
H. Peter Anvine2c80182005-01-15 22:15:51 +00002558 /* t should now point to the string */
2559 if (t->type != TOK_STRING) {
2560 error(ERR_NONFATAL,
2561 "`%%substr` requires string as second parameter");
2562 free_tlist(tline);
2563 free_tlist(origline);
2564 return DIRECTIVE_FOUND;
2565 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002566
H. Peter Anvine2c80182005-01-15 22:15:51 +00002567 tt = t->next;
2568 tptr = &tt;
2569 tokval.t_type = TOKEN_INVALID;
2570 evalresult =
2571 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2572 if (!evalresult) {
2573 free_tlist(tline);
2574 free_tlist(origline);
2575 return DIRECTIVE_FOUND;
2576 }
2577 if (!is_simple(evalresult)) {
2578 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
2579 free_tlist(tline);
2580 free_tlist(origline);
2581 return DIRECTIVE_FOUND;
2582 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002583
H. Peter Anvine2c80182005-01-15 22:15:51 +00002584 macro_start = nasm_malloc(sizeof(*macro_start));
2585 macro_start->next = NULL;
2586 macro_start->text = nasm_strdup("'''");
2587 if (evalresult->value > 0
2588 && evalresult->value < strlen(t->text) - 1) {
2589 macro_start->text[1] = t->text[evalresult->value];
2590 } else {
2591 macro_start->text[2] = '\0';
2592 }
2593 macro_start->type = TOK_STRING;
2594 macro_start->mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002595
H. Peter Anvine2c80182005-01-15 22:15:51 +00002596 /*
2597 * We now have a macro name, an implicit parameter count of
2598 * zero, and a numeric token to use as an expansion. Create
2599 * and store an SMacro.
2600 */
2601 if (smacro_defined(ctx, mname, 0, &smac, i == PP_SUBSTR)) {
2602 if (!smac)
2603 error(ERR_WARNING,
2604 "single-line macro `%s' defined both with and"
2605 " without parameters", mname);
2606 else {
2607 /*
2608 * We're redefining, so we have to take over an
2609 * existing SMacro structure. This means freeing
2610 * what was already in it.
2611 */
2612 nasm_free(smac->name);
2613 free_tlist(smac->expansion);
2614 }
2615 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002616 if (!ctx)
2617 smhead = (SMacro **) hash_findi_add(smacros, tline->text);
2618 else
2619 smhead = &ctx->localmac;
2620
H. Peter Anvine2c80182005-01-15 22:15:51 +00002621 smac = nasm_malloc(sizeof(SMacro));
2622 smac->next = *smhead;
2623 *smhead = smac;
2624 }
2625 smac->name = nasm_strdup(mname);
2626 smac->casesense = (i == PP_SUBSTR);
2627 smac->nparam = 0;
2628 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002629 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002630 free_tlist(tline);
2631 free_tlist(origline);
2632 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002633
H. Peter Anvine2c80182005-01-15 22:15:51 +00002634 case PP_ASSIGN:
2635 case PP_IASSIGN:
2636 tline = tline->next;
2637 skip_white_(tline);
2638 tline = expand_id(tline);
2639 if (!tline || (tline->type != TOK_ID &&
2640 (tline->type != TOK_PREPROC_ID ||
2641 tline->text[1] != '$'))) {
2642 error(ERR_NONFATAL,
2643 "`%%%sassign' expects a macro identifier",
2644 (i == PP_IASSIGN ? "i" : ""));
2645 free_tlist(origline);
2646 return DIRECTIVE_FOUND;
2647 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002648 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002649
H. Peter Anvine2c80182005-01-15 22:15:51 +00002650 mname = tline->text;
2651 last = tline;
2652 tline = expand_smacro(tline->next);
2653 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002654
H. Peter Anvine2c80182005-01-15 22:15:51 +00002655 t = tline;
2656 tptr = &t;
2657 tokval.t_type = TOKEN_INVALID;
2658 evalresult =
2659 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2660 free_tlist(tline);
2661 if (!evalresult) {
2662 free_tlist(origline);
2663 return DIRECTIVE_FOUND;
2664 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002665
H. Peter Anvine2c80182005-01-15 22:15:51 +00002666 if (tokval.t_type)
2667 error(ERR_WARNING,
2668 "trailing garbage after expression ignored");
H. Peter Anvin734b1882002-04-30 21:01:08 +00002669
H. Peter Anvine2c80182005-01-15 22:15:51 +00002670 if (!is_simple(evalresult)) {
2671 error(ERR_NONFATAL,
2672 "non-constant value given to `%%%sassign'",
2673 (i == PP_IASSIGN ? "i" : ""));
2674 free_tlist(origline);
2675 return DIRECTIVE_FOUND;
2676 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002677
H. Peter Anvine2c80182005-01-15 22:15:51 +00002678 macro_start = nasm_malloc(sizeof(*macro_start));
2679 macro_start->next = NULL;
2680 make_tok_num(macro_start, reloc_value(evalresult));
2681 macro_start->mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002682
H. Peter Anvine2c80182005-01-15 22:15:51 +00002683 /*
2684 * We now have a macro name, an implicit parameter count of
2685 * zero, and a numeric token to use as an expansion. Create
2686 * and store an SMacro.
2687 */
2688 if (smacro_defined(ctx, mname, 0, &smac, i == PP_ASSIGN)) {
2689 if (!smac)
2690 error(ERR_WARNING,
2691 "single-line macro `%s' defined both with and"
2692 " without parameters", mname);
2693 else {
2694 /*
2695 * We're redefining, so we have to take over an
2696 * existing SMacro structure. This means freeing
2697 * what was already in it.
2698 */
2699 nasm_free(smac->name);
2700 free_tlist(smac->expansion);
2701 }
2702 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002703 if (!ctx)
2704 smhead = (SMacro **) hash_findi_add(smacros, mname);
2705 else
2706 smhead = &ctx->localmac;
2707
H. Peter Anvine2c80182005-01-15 22:15:51 +00002708 smac = nasm_malloc(sizeof(SMacro));
2709 smac->next = *smhead;
2710 *smhead = smac;
2711 }
2712 smac->name = nasm_strdup(mname);
2713 smac->casesense = (i == PP_ASSIGN);
2714 smac->nparam = 0;
2715 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002716 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002717 free_tlist(origline);
2718 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002719
H. Peter Anvine2c80182005-01-15 22:15:51 +00002720 case PP_LINE:
2721 /*
2722 * Syntax is `%line nnn[+mmm] [filename]'
2723 */
2724 tline = tline->next;
2725 skip_white_(tline);
2726 if (!tok_type_(tline, TOK_NUMBER)) {
2727 error(ERR_NONFATAL, "`%%line' expects line number");
2728 free_tlist(origline);
2729 return DIRECTIVE_FOUND;
2730 }
H. Peter Anvin70055962007-10-11 00:05:31 -07002731 k = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002732 m = 1;
2733 tline = tline->next;
2734 if (tok_is_(tline, "+")) {
2735 tline = tline->next;
2736 if (!tok_type_(tline, TOK_NUMBER)) {
2737 error(ERR_NONFATAL, "`%%line' expects line increment");
2738 free_tlist(origline);
2739 return DIRECTIVE_FOUND;
2740 }
H. Peter Anvin70055962007-10-11 00:05:31 -07002741 m = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002742 tline = tline->next;
2743 }
2744 skip_white_(tline);
2745 src_set_linnum(k);
2746 istk->lineinc = m;
2747 if (tline) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002748 nasm_free(src_set_fname(detoken(tline, false)));
H. Peter Anvine2c80182005-01-15 22:15:51 +00002749 }
2750 free_tlist(origline);
2751 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002752
H. Peter Anvine2c80182005-01-15 22:15:51 +00002753 default:
2754 error(ERR_FATAL,
2755 "preprocessor directive `%s' not yet implemented",
H. Peter Anvin4169a472007-09-12 01:29:43 +00002756 pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002757 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002758 }
Ed Beroset3ab3f412002-06-11 03:31:49 +00002759 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002760}
2761
2762/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002763 * Ensure that a macro parameter contains a condition code and
2764 * nothing else. Return the condition code index if so, or -1
2765 * otherwise.
2766 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002767static int find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002768{
H. Peter Anvin76690a12002-04-30 20:52:49 +00002769 Token *tt;
2770 int i, j, k, m;
2771
H. Peter Anvin25a99342007-09-22 17:45:45 -07002772 if (!t)
2773 return -1; /* Probably a %+ without a space */
2774
H. Peter Anvineba20a72002-04-30 20:53:55 +00002775 skip_white_(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002776 if (t->type != TOK_ID)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002777 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002778 tt = t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002779 skip_white_(tt);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002780 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002781 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002782
2783 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +00002784 j = elements(conditions);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002785 while (j - i > 1) {
2786 k = (j + i) / 2;
2787 m = nasm_stricmp(t->text, conditions[k]);
2788 if (m == 0) {
2789 i = k;
2790 j = -2;
2791 break;
2792 } else if (m < 0) {
2793 j = k;
2794 } else
2795 i = k;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002796 }
2797 if (j != -2)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002798 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002799 return i;
2800}
2801
2802/*
2803 * Expand MMacro-local things: parameter references (%0, %n, %+n,
2804 * %-n) and MMacro-local identifiers (%%foo).
2805 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002806static Token *expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002807{
H. Peter Anvin734b1882002-04-30 21:01:08 +00002808 Token *t, *tt, **tail, *thead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002809
2810 tail = &thead;
2811 thead = NULL;
2812
H. Peter Anvine2c80182005-01-15 22:15:51 +00002813 while (tline) {
2814 if (tline->type == TOK_PREPROC_ID &&
2815 (((tline->text[1] == '+' || tline->text[1] == '-')
2816 && tline->text[2]) || tline->text[1] == '%'
2817 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002818 char *text = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002819 int type = 0, cc; /* type = 0 to placate optimisers */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002820 char tmpbuf[30];
H. Peter Anvin25a99342007-09-22 17:45:45 -07002821 unsigned int n;
2822 int i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002823 MMacro *mac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002824
H. Peter Anvine2c80182005-01-15 22:15:51 +00002825 t = tline;
2826 tline = tline->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002827
H. Peter Anvine2c80182005-01-15 22:15:51 +00002828 mac = istk->mstk;
2829 while (mac && !mac->name) /* avoid mistaking %reps for macros */
2830 mac = mac->next_active;
2831 if (!mac)
2832 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
2833 else
2834 switch (t->text[1]) {
2835 /*
2836 * We have to make a substitution of one of the
2837 * forms %1, %-1, %+1, %%foo, %0.
2838 */
2839 case '0':
2840 type = TOK_NUMBER;
2841 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
2842 text = nasm_strdup(tmpbuf);
2843 break;
2844 case '%':
2845 type = TOK_ID;
Keith Kanios93f2e9a2007-04-14 00:10:59 +00002846 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu32".",
H. Peter Anvine2c80182005-01-15 22:15:51 +00002847 mac->unique);
2848 text = nasm_strcat(tmpbuf, t->text + 2);
2849 break;
2850 case '-':
2851 n = atoi(t->text + 2) - 1;
2852 if (n >= mac->nparam)
2853 tt = NULL;
2854 else {
2855 if (mac->nparam > 1)
2856 n = (n + mac->rotate) % mac->nparam;
2857 tt = mac->params[n];
2858 }
2859 cc = find_cc(tt);
2860 if (cc == -1) {
2861 error(ERR_NONFATAL,
2862 "macro parameter %d is not a condition code",
2863 n + 1);
2864 text = NULL;
2865 } else {
2866 type = TOK_ID;
2867 if (inverse_ccs[cc] == -1) {
2868 error(ERR_NONFATAL,
2869 "condition code `%s' is not invertible",
2870 conditions[cc]);
2871 text = NULL;
2872 } else
2873 text =
2874 nasm_strdup(conditions[inverse_ccs[cc]]);
2875 }
2876 break;
2877 case '+':
2878 n = atoi(t->text + 2) - 1;
2879 if (n >= mac->nparam)
2880 tt = NULL;
2881 else {
2882 if (mac->nparam > 1)
2883 n = (n + mac->rotate) % mac->nparam;
2884 tt = mac->params[n];
2885 }
2886 cc = find_cc(tt);
2887 if (cc == -1) {
2888 error(ERR_NONFATAL,
2889 "macro parameter %d is not a condition code",
2890 n + 1);
2891 text = NULL;
2892 } else {
2893 type = TOK_ID;
2894 text = nasm_strdup(conditions[cc]);
2895 }
2896 break;
2897 default:
2898 n = atoi(t->text + 1) - 1;
2899 if (n >= mac->nparam)
2900 tt = NULL;
2901 else {
2902 if (mac->nparam > 1)
2903 n = (n + mac->rotate) % mac->nparam;
2904 tt = mac->params[n];
2905 }
2906 if (tt) {
2907 for (i = 0; i < mac->paramlen[n]; i++) {
2908 *tail = new_Token(NULL, tt->type, tt->text, 0);
2909 tail = &(*tail)->next;
2910 tt = tt->next;
2911 }
2912 }
2913 text = NULL; /* we've done it here */
2914 break;
2915 }
2916 if (!text) {
2917 delete_Token(t);
2918 } else {
2919 *tail = t;
2920 tail = &t->next;
2921 t->type = type;
2922 nasm_free(t->text);
2923 t->text = text;
2924 t->mac = NULL;
2925 }
2926 continue;
2927 } else {
2928 t = *tail = tline;
2929 tline = tline->next;
2930 t->mac = NULL;
2931 tail = &t->next;
2932 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002933 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00002934 *tail = NULL;
2935 t = thead;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002936 for (; t && (tt = t->next) != NULL; t = t->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002937 switch (t->type) {
2938 case TOK_WHITESPACE:
2939 if (tt->type == TOK_WHITESPACE) {
2940 t->next = delete_Token(tt);
2941 }
2942 break;
2943 case TOK_ID:
2944 if (tt->type == TOK_ID || tt->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002945 char *tmp = nasm_strcat(t->text, tt->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002946 nasm_free(t->text);
2947 t->text = tmp;
2948 t->next = delete_Token(tt);
2949 }
2950 break;
2951 case TOK_NUMBER:
2952 if (tt->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002953 char *tmp = nasm_strcat(t->text, tt->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002954 nasm_free(t->text);
2955 t->text = tmp;
2956 t->next = delete_Token(tt);
2957 }
2958 break;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002959 default:
2960 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002961 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002962
H. Peter Anvin76690a12002-04-30 20:52:49 +00002963 return thead;
2964}
2965
2966/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002967 * Expand all single-line macro calls made in the given line.
2968 * Return the expanded version of the line. The original is deemed
2969 * to be destroyed in the process. (In reality we'll just move
2970 * Tokens from input to output a lot of the time, rather than
2971 * actually bothering to destroy and replicate.)
2972 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002973static Token *expand_smacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002974{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002975 Token *t, *tt, *mstart, **tail, *thead;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002976 SMacro *head = NULL, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002977 Token **params;
2978 int *paramsize;
H. Peter Anvin25a99342007-09-22 17:45:45 -07002979 unsigned int nparam, sparam;
2980 int brackets, rescan;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002981 Token *org_tline = tline;
2982 Context *ctx;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002983 char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002984
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002985 /*
2986 * Trick: we should avoid changing the start token pointer since it can
2987 * be contained in "next" field of other token. Because of this
2988 * we allocate a copy of first token and work with it; at the end of
2989 * routine we copy it back
2990 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002991 if (org_tline) {
2992 tline =
2993 new_Token(org_tline->next, org_tline->type, org_tline->text,
2994 0);
2995 tline->mac = org_tline->mac;
2996 nasm_free(org_tline->text);
2997 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002998 }
2999
H. Peter Anvin734b1882002-04-30 21:01:08 +00003000 again:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003001 tail = &thead;
3002 thead = NULL;
3003
H. Peter Anvine2c80182005-01-15 22:15:51 +00003004 while (tline) { /* main token loop */
3005 if ((mname = tline->text)) {
3006 /* if this token is a local macro, look in local context */
3007 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003008 ctx = get_ctx(mname, true);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003009 else
3010 ctx = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003011 if (!ctx) {
3012 head = (SMacro *) hash_findix(smacros, mname);
3013 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003014 head = ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003015 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003016 /*
3017 * We've hit an identifier. As in is_mmacro below, we first
3018 * check whether the identifier is a single-line macro at
3019 * all, then think about checking for parameters if
3020 * necessary.
3021 */
H. Peter Anvin97a23472007-09-16 17:57:25 -07003022 for (m = head; m; m = m->next)
3023 if (!mstrcmp(m->name, mname, m->casesense))
3024 break;
3025 if (m) {
3026 mstart = tline;
3027 params = NULL;
3028 paramsize = NULL;
3029 if (m->nparam == 0) {
3030 /*
3031 * Simple case: the macro is parameterless. Discard the
3032 * one token that the macro call took, and push the
3033 * expansion back on the to-do stack.
3034 */
3035 if (!m->expansion) {
3036 if (!strcmp("__FILE__", m->name)) {
3037 int32_t num = 0;
3038 src_get(&num, &(tline->text));
3039 nasm_quote(&(tline->text));
3040 tline->type = TOK_STRING;
3041 continue;
3042 }
3043 if (!strcmp("__LINE__", m->name)) {
3044 nasm_free(tline->text);
3045 make_tok_num(tline, src_get_linnum());
3046 continue;
3047 }
3048 if (!strcmp("__BITS__", m->name)) {
3049 nasm_free(tline->text);
3050 make_tok_num(tline, globalbits);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003051 continue;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003052 }
3053 tline = delete_Token(tline);
3054 continue;
3055 }
3056 } else {
3057 /*
3058 * Complicated case: at least one macro with this name
H. Peter Anvine2c80182005-01-15 22:15:51 +00003059 * exists and takes parameters. We must find the
3060 * parameters in the call, count them, find the SMacro
3061 * that corresponds to that form of the macro call, and
3062 * substitute for the parameters when we expand. What a
3063 * pain.
3064 */
3065 /*tline = tline->next;
3066 skip_white_(tline); */
3067 do {
3068 t = tline->next;
3069 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003070 t->mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003071 t->text = NULL;
3072 t = tline->next = delete_Token(t);
3073 }
3074 tline = t;
3075 } while (tok_type_(tline, TOK_WHITESPACE));
3076 if (!tok_is_(tline, "(")) {
3077 /*
3078 * This macro wasn't called with parameters: ignore
3079 * the call. (Behaviour borrowed from gnu cpp.)
3080 */
3081 tline = mstart;
3082 m = NULL;
3083 } else {
3084 int paren = 0;
3085 int white = 0;
3086 brackets = 0;
3087 nparam = 0;
3088 sparam = PARAM_DELTA;
3089 params = nasm_malloc(sparam * sizeof(Token *));
3090 params[0] = tline->next;
3091 paramsize = nasm_malloc(sparam * sizeof(int));
3092 paramsize[0] = 0;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003093 while (true) { /* parameter loop */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003094 /*
3095 * For some unusual expansions
3096 * which concatenates function call
3097 */
3098 t = tline->next;
3099 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003100 t->mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003101 t->text = NULL;
3102 t = tline->next = delete_Token(t);
3103 }
3104 tline = t;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003105
H. Peter Anvine2c80182005-01-15 22:15:51 +00003106 if (!tline) {
3107 error(ERR_NONFATAL,
3108 "macro call expects terminating `)'");
3109 break;
3110 }
3111 if (tline->type == TOK_WHITESPACE
3112 && brackets <= 0) {
3113 if (paramsize[nparam])
3114 white++;
3115 else
3116 params[nparam] = tline->next;
3117 continue; /* parameter loop */
3118 }
3119 if (tline->type == TOK_OTHER
3120 && tline->text[1] == 0) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003121 char ch = tline->text[0];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003122 if (ch == ',' && !paren && brackets <= 0) {
3123 if (++nparam >= sparam) {
3124 sparam += PARAM_DELTA;
3125 params = nasm_realloc(params,
3126 sparam *
3127 sizeof(Token
3128 *));
3129 paramsize =
3130 nasm_realloc(paramsize,
3131 sparam *
3132 sizeof(int));
3133 }
3134 params[nparam] = tline->next;
3135 paramsize[nparam] = 0;
3136 white = 0;
3137 continue; /* parameter loop */
3138 }
3139 if (ch == '{' &&
3140 (brackets > 0 || (brackets == 0 &&
3141 !paramsize[nparam])))
3142 {
3143 if (!(brackets++)) {
3144 params[nparam] = tline->next;
3145 continue; /* parameter loop */
3146 }
3147 }
3148 if (ch == '}' && brackets > 0)
3149 if (--brackets == 0) {
3150 brackets = -1;
3151 continue; /* parameter loop */
3152 }
3153 if (ch == '(' && !brackets)
3154 paren++;
3155 if (ch == ')' && brackets <= 0)
3156 if (--paren < 0)
3157 break;
3158 }
3159 if (brackets < 0) {
3160 brackets = 0;
3161 error(ERR_NONFATAL, "braces do not "
3162 "enclose all of macro parameter");
3163 }
3164 paramsize[nparam] += white + 1;
3165 white = 0;
3166 } /* parameter loop */
3167 nparam++;
3168 while (m && (m->nparam != nparam ||
3169 mstrcmp(m->name, mname,
3170 m->casesense)))
3171 m = m->next;
3172 if (!m)
3173 error(ERR_WARNING | ERR_WARN_MNP,
3174 "macro `%s' exists, "
3175 "but not taking %d parameters",
3176 mstart->text, nparam);
3177 }
3178 }
3179 if (m && m->in_progress)
3180 m = NULL;
3181 if (!m) { /* in progess or didn't find '(' or wrong nparam */
3182 /*
3183 * Design question: should we handle !tline, which
3184 * indicates missing ')' here, or expand those
3185 * macros anyway, which requires the (t) test a few
3186 * lines down?
3187 */
3188 nasm_free(params);
3189 nasm_free(paramsize);
3190 tline = mstart;
3191 } else {
3192 /*
3193 * Expand the macro: we are placed on the last token of the
3194 * call, so that we can easily split the call from the
3195 * following tokens. We also start by pushing an SMAC_END
3196 * token for the cycle removal.
3197 */
3198 t = tline;
3199 if (t) {
3200 tline = t->next;
3201 t->next = NULL;
3202 }
3203 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
3204 tt->mac = m;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003205 m->in_progress = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003206 tline = tt;
3207 for (t = m->expansion; t; t = t->next) {
3208 if (t->type >= TOK_SMAC_PARAM) {
3209 Token *pcopy = tline, **ptail = &pcopy;
3210 Token *ttt, *pt;
3211 int i;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003212
H. Peter Anvine2c80182005-01-15 22:15:51 +00003213 ttt = params[t->type - TOK_SMAC_PARAM];
3214 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3215 --i >= 0;) {
3216 pt = *ptail =
3217 new_Token(tline, ttt->type, ttt->text,
3218 0);
3219 ptail = &pt->next;
3220 ttt = ttt->next;
3221 }
3222 tline = pcopy;
3223 } else {
3224 tt = new_Token(tline, t->type, t->text, 0);
3225 tline = tt;
3226 }
3227 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003228
H. Peter Anvine2c80182005-01-15 22:15:51 +00003229 /*
3230 * Having done that, get rid of the macro call, and clean
3231 * up the parameters.
3232 */
3233 nasm_free(params);
3234 nasm_free(paramsize);
3235 free_tlist(mstart);
3236 continue; /* main token loop */
3237 }
3238 }
3239 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003240
H. Peter Anvine2c80182005-01-15 22:15:51 +00003241 if (tline->type == TOK_SMAC_END) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003242 tline->mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003243 tline = delete_Token(tline);
3244 } else {
3245 t = *tail = tline;
3246 tline = tline->next;
3247 t->mac = NULL;
3248 t->next = NULL;
3249 tail = &t->next;
3250 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003251 }
3252
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003253 /*
3254 * Now scan the entire line and look for successive TOK_IDs that resulted
Keith Kaniosb7a89542007-04-12 02:40:54 +00003255 * after expansion (they can't be produced by tokenize()). The successive
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003256 * TOK_IDs should be concatenated.
3257 * Also we look for %+ tokens and concatenate the tokens before and after
3258 * them (without white spaces in between).
3259 */
3260 t = thead;
3261 rescan = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003262 while (t) {
3263 while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
3264 t = t->next;
3265 if (!t || !t->next)
3266 break;
3267 if (t->next->type == TOK_ID ||
3268 t->next->type == TOK_PREPROC_ID ||
3269 t->next->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003270 char *p = nasm_strcat(t->text, t->next->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003271 nasm_free(t->text);
3272 t->next = delete_Token(t->next);
3273 t->text = p;
3274 rescan = 1;
3275 } else if (t->next->type == TOK_WHITESPACE && t->next->next &&
3276 t->next->next->type == TOK_PREPROC_ID &&
3277 strcmp(t->next->next->text, "%+") == 0) {
3278 /* free the next whitespace, the %+ token and next whitespace */
3279 int i;
3280 for (i = 1; i <= 3; i++) {
3281 if (!t->next
3282 || (i != 2 && t->next->type != TOK_WHITESPACE))
3283 break;
3284 t->next = delete_Token(t->next);
3285 } /* endfor */
3286 } else
3287 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003288 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003289 /* If we concatenaded something, re-scan the line for macros */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003290 if (rescan) {
3291 tline = thead;
3292 goto again;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003293 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003294
H. Peter Anvine2c80182005-01-15 22:15:51 +00003295 if (org_tline) {
3296 if (thead) {
3297 *org_tline = *thead;
3298 /* since we just gave text to org_line, don't free it */
3299 thead->text = NULL;
3300 delete_Token(thead);
3301 } else {
3302 /* the expression expanded to empty line;
3303 we can't return NULL for some reasons
3304 we just set the line to a single WHITESPACE token. */
3305 memset(org_tline, 0, sizeof(*org_tline));
3306 org_tline->text = NULL;
3307 org_tline->type = TOK_WHITESPACE;
3308 }
3309 thead = org_tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003310 }
3311
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003312 return thead;
3313}
3314
3315/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003316 * Similar to expand_smacro but used exclusively with macro identifiers
3317 * right before they are fetched in. The reason is that there can be
3318 * identifiers consisting of several subparts. We consider that if there
3319 * are more than one element forming the name, user wants a expansion,
3320 * otherwise it will be left as-is. Example:
3321 *
3322 * %define %$abc cde
3323 *
3324 * the identifier %$abc will be left as-is so that the handler for %define
3325 * will suck it and define the corresponding value. Other case:
3326 *
3327 * %define _%$abc cde
3328 *
3329 * In this case user wants name to be expanded *before* %define starts
3330 * working, so we'll expand %$abc into something (if it has a value;
3331 * otherwise it will be left as-is) then concatenate all successive
3332 * PP_IDs into one.
3333 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003334static Token *expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003335{
3336 Token *cur, *oldnext = NULL;
3337
H. Peter Anvin734b1882002-04-30 21:01:08 +00003338 if (!tline || !tline->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003339 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003340
3341 cur = tline;
3342 while (cur->next &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00003343 (cur->next->type == TOK_ID ||
3344 cur->next->type == TOK_PREPROC_ID
3345 || cur->next->type == TOK_NUMBER))
3346 cur = cur->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003347
3348 /* If identifier consists of just one token, don't expand */
3349 if (cur == tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003350 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003351
H. Peter Anvine2c80182005-01-15 22:15:51 +00003352 if (cur) {
3353 oldnext = cur->next; /* Detach the tail past identifier */
3354 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003355 }
3356
H. Peter Anvin734b1882002-04-30 21:01:08 +00003357 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003358
H. Peter Anvine2c80182005-01-15 22:15:51 +00003359 if (cur) {
3360 /* expand_smacro possibly changhed tline; re-scan for EOL */
3361 cur = tline;
3362 while (cur && cur->next)
3363 cur = cur->next;
3364 if (cur)
3365 cur->next = oldnext;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003366 }
3367
3368 return tline;
3369}
3370
3371/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003372 * Determine whether the given line constitutes a multi-line macro
3373 * call, and return the MMacro structure called if so. Doesn't have
3374 * to check for an initial label - that's taken care of in
3375 * expand_mmacro - but must check numbers of parameters. Guaranteed
3376 * to be called with tline->type == TOK_ID, so the putative macro
3377 * name is easy to find.
3378 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003379static MMacro *is_mmacro(Token * tline, Token *** params_array)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003380{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003381 MMacro *head, *m;
3382 Token **params;
3383 int nparam;
3384
H. Peter Anvin97a23472007-09-16 17:57:25 -07003385 head = (MMacro *) hash_findix(mmacros, tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003386
3387 /*
3388 * Efficiency: first we see if any macro exists with the given
3389 * name. If not, we can return NULL immediately. _Then_ we
3390 * count the parameters, and then we look further along the
3391 * list if necessary to find the proper MMacro.
3392 */
3393 for (m = head; m; m = m->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003394 if (!mstrcmp(m->name, tline->text, m->casesense))
3395 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003396 if (!m)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003397 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003398
3399 /*
3400 * OK, we have a potential macro. Count and demarcate the
3401 * parameters.
3402 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003403 count_mmac_params(tline->next, &nparam, &params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003404
3405 /*
3406 * So we know how many parameters we've got. Find the MMacro
3407 * structure that handles this number.
3408 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003409 while (m) {
3410 if (m->nparam_min <= nparam
3411 && (m->plus || nparam <= m->nparam_max)) {
3412 /*
3413 * This one is right. Just check if cycle removal
3414 * prohibits us using it before we actually celebrate...
3415 */
3416 if (m->in_progress) {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003417#if 0
H. Peter Anvine2c80182005-01-15 22:15:51 +00003418 error(ERR_NONFATAL,
3419 "self-reference in multi-line macro `%s'", m->name);
H. Peter Anvineba20a72002-04-30 20:53:55 +00003420#endif
H. Peter Anvine2c80182005-01-15 22:15:51 +00003421 nasm_free(params);
3422 return NULL;
3423 }
3424 /*
3425 * It's right, and we can use it. Add its default
3426 * parameters to the end of our list if necessary.
3427 */
3428 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
3429 params =
3430 nasm_realloc(params,
3431 ((m->nparam_min + m->ndefs +
3432 1) * sizeof(*params)));
3433 while (nparam < m->nparam_min + m->ndefs) {
3434 params[nparam] = m->defaults[nparam - m->nparam_min];
3435 nparam++;
3436 }
3437 }
3438 /*
3439 * If we've gone over the maximum parameter count (and
3440 * we're in Plus mode), ignore parameters beyond
3441 * nparam_max.
3442 */
3443 if (m->plus && nparam > m->nparam_max)
3444 nparam = m->nparam_max;
3445 /*
3446 * Then terminate the parameter list, and leave.
3447 */
3448 if (!params) { /* need this special case */
3449 params = nasm_malloc(sizeof(*params));
3450 nparam = 0;
3451 }
3452 params[nparam] = NULL;
3453 *params_array = params;
3454 return m;
3455 }
3456 /*
3457 * This one wasn't right: look for the next one with the
3458 * same name.
3459 */
3460 for (m = m->next; m; m = m->next)
3461 if (!mstrcmp(m->name, tline->text, m->casesense))
3462 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003463 }
3464
3465 /*
3466 * After all that, we didn't find one with the right number of
3467 * parameters. Issue a warning, and fail to expand the macro.
3468 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003469 error(ERR_WARNING | ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003470 "macro `%s' exists, but not taking %d parameters",
3471 tline->text, nparam);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003472 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003473 return NULL;
3474}
3475
3476/*
3477 * Expand the multi-line macro call made by the given line, if
3478 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvineba20a72002-04-30 20:53:55 +00003479 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003480 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003481static int expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003482{
3483 Token *startline = tline;
3484 Token *label = NULL;
3485 int dont_prepend = 0;
3486 Token **params, *t, *tt;
3487 MMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003488 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003489 int i, nparam, *paramlen;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003490
3491 t = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003492 skip_white_(t);
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00003493/* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
3494 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003495 return 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003496 m = is_mmacro(t, &params);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003497 if (!m) {
3498 Token *last;
3499 /*
3500 * We have an id which isn't a macro call. We'll assume
3501 * it might be a label; we'll also check to see if a
3502 * colon follows it. Then, if there's another id after
3503 * that lot, we'll check it again for macro-hood.
3504 */
3505 label = last = t;
3506 t = t->next;
3507 if (tok_type_(t, TOK_WHITESPACE))
3508 last = t, t = t->next;
3509 if (tok_is_(t, ":")) {
3510 dont_prepend = 1;
3511 last = t, t = t->next;
3512 if (tok_type_(t, TOK_WHITESPACE))
3513 last = t, t = t->next;
3514 }
3515 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
3516 return 0;
3517 last->next = NULL;
3518 tline = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003519 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003520
3521 /*
3522 * Fix up the parameters: this involves stripping leading and
3523 * trailing whitespace, then stripping braces if they are
3524 * present.
3525 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003526 for (nparam = 0; params[nparam]; nparam++) ;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003527 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003528
H. Peter Anvine2c80182005-01-15 22:15:51 +00003529 for (i = 0; params[i]; i++) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003530 int brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003531 int comma = (!m->plus || i < nparam - 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003532
H. Peter Anvine2c80182005-01-15 22:15:51 +00003533 t = params[i];
3534 skip_white_(t);
3535 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003536 t = t->next, brace = true, comma = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003537 params[i] = t;
3538 paramlen[i] = 0;
3539 while (t) {
3540 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
3541 break; /* ... because we have hit a comma */
3542 if (comma && t->type == TOK_WHITESPACE
3543 && tok_is_(t->next, ","))
3544 break; /* ... or a space then a comma */
3545 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
3546 break; /* ... or a brace */
3547 t = t->next;
3548 paramlen[i]++;
3549 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003550 }
3551
3552 /*
3553 * OK, we have a MMacro structure together with a set of
3554 * parameters. We must now go through the expansion and push
H. Peter Anvin76690a12002-04-30 20:52:49 +00003555 * copies of each Line on to istk->expansion. Substitution of
3556 * parameter tokens and macro-local tokens doesn't get done
3557 * until the single-line macro substitution process; this is
3558 * because delaying them allows us to change the semantics
3559 * later through %rotate.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003560 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00003561 * First, push an end marker on to istk->expansion, mark this
3562 * macro as in progress, and set up its invocation-specific
3563 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003564 */
3565 ll = nasm_malloc(sizeof(Line));
3566 ll->next = istk->expansion;
3567 ll->finishes = m;
3568 ll->first = NULL;
3569 istk->expansion = ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003570
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003571 m->in_progress = true;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003572 m->params = params;
3573 m->iline = tline;
3574 m->nparam = nparam;
3575 m->rotate = 0;
3576 m->paramlen = paramlen;
3577 m->unique = unique++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003578 m->lineno = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003579
3580 m->next_active = istk->mstk;
3581 istk->mstk = m;
3582
H. Peter Anvine2c80182005-01-15 22:15:51 +00003583 for (l = m->expansion; l; l = l->next) {
3584 Token **tail;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003585
H. Peter Anvine2c80182005-01-15 22:15:51 +00003586 ll = nasm_malloc(sizeof(Line));
3587 ll->finishes = NULL;
3588 ll->next = istk->expansion;
3589 istk->expansion = ll;
3590 tail = &ll->first;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003591
H. Peter Anvine2c80182005-01-15 22:15:51 +00003592 for (t = l->first; t; t = t->next) {
3593 Token *x = t;
3594 if (t->type == TOK_PREPROC_ID &&
3595 t->text[1] == '0' && t->text[2] == '0') {
3596 dont_prepend = -1;
3597 x = label;
3598 if (!x)
3599 continue;
3600 }
3601 tt = *tail = new_Token(NULL, x->type, x->text, 0);
3602 tail = &tt->next;
3603 }
3604 *tail = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003605 }
3606
3607 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00003608 * If we had a label, push it on as the first line of
3609 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003610 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003611 if (label) {
3612 if (dont_prepend < 0)
3613 free_tlist(startline);
3614 else {
3615 ll = nasm_malloc(sizeof(Line));
3616 ll->finishes = NULL;
3617 ll->next = istk->expansion;
3618 istk->expansion = ll;
3619 ll->first = startline;
3620 if (!dont_prepend) {
3621 while (label->next)
3622 label = label->next;
3623 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
3624 }
3625 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003626 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003627
H. Peter Anvin734b1882002-04-30 21:01:08 +00003628 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003629
H. Peter Anvineba20a72002-04-30 20:53:55 +00003630 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003631}
3632
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003633/*
3634 * Since preprocessor always operate only on the line that didn't
3635 * arrived yet, we should always use ERR_OFFBY1. Also since user
3636 * won't want to see same error twice (preprocessing is done once
3637 * per pass) we will want to show errors only during pass one.
3638 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003639static void error(int severity, const char *fmt, ...)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003640{
3641 va_list arg;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003642 char buff[1024];
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003643
3644 /* If we're in a dead branch of IF or something like it, ignore the error */
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00003645 if (istk && istk->conds && !emitting(istk->conds->state))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003646 return;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003647
H. Peter Anvin734b1882002-04-30 21:01:08 +00003648 va_start(arg, fmt);
Ed Beroset19f927a2004-12-15 17:07:03 +00003649 vsnprintf(buff, sizeof(buff), fmt, arg);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003650 va_end(arg);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003651
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00003652 if (istk && istk->mstk && istk->mstk->name)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003653 _error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
3654 istk->mstk->lineno, buff);
3655 else
3656 _error(severity | ERR_PASS1, "%s", buff);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003657}
3658
H. Peter Anvin734b1882002-04-30 21:01:08 +00003659static void
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003660pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003661 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003662{
H. Peter Anvin99941bf2002-05-14 17:44:03 +00003663 _error = errfunc;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003664 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003665 istk = nasm_malloc(sizeof(Include));
3666 istk->next = NULL;
3667 istk->conds = NULL;
3668 istk->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003669 istk->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003670 istk->fp = fopen(file, "r");
H. Peter Anvineba20a72002-04-30 20:53:55 +00003671 istk->fname = NULL;
3672 src_set_fname(nasm_strdup(file));
3673 src_set_linnum(0);
3674 istk->lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003675 if (!istk->fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003676 error(ERR_FATAL | ERR_NOFILE, "unable to open input file `%s'",
3677 file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003678 defining = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003679 init_macros();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003680 unique = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003681 if (tasm_compatible_mode) {
3682 stdmacpos = stdmac;
3683 } else {
3684 stdmacpos = &stdmac[TASM_MACRO_COUNT];
3685 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003686 any_extrastdmac = (extrastdmac != NULL);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003687 list = listgen;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003688 evaluate = eval;
3689 pass = apass;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003690}
3691
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003692static char *pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003693{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003694 char *line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003695 Token *tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003696
H. Peter Anvine2c80182005-01-15 22:15:51 +00003697 while (1) {
3698 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00003699 * Fetch a tokenized line, either from the macro-expansion
H. Peter Anvine2c80182005-01-15 22:15:51 +00003700 * buffer or from the input file.
3701 */
3702 tline = NULL;
3703 while (istk->expansion && istk->expansion->finishes) {
3704 Line *l = istk->expansion;
3705 if (!l->finishes->name && l->finishes->in_progress > 1) {
3706 Line *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003707
H. Peter Anvine2c80182005-01-15 22:15:51 +00003708 /*
3709 * This is a macro-end marker for a macro with no
3710 * name, which means it's not really a macro at all
3711 * but a %rep block, and the `in_progress' field is
3712 * more than 1, meaning that we still need to
3713 * repeat. (1 means the natural last repetition; 0
3714 * means termination by %exitrep.) We have
3715 * therefore expanded up to the %endrep, and must
3716 * push the whole block on to the expansion buffer
3717 * again. We don't bother to remove the macro-end
3718 * marker: we'd only have to generate another one
3719 * if we did.
3720 */
3721 l->finishes->in_progress--;
3722 for (l = l->finishes->expansion; l; l = l->next) {
3723 Token *t, *tt, **tail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003724
H. Peter Anvine2c80182005-01-15 22:15:51 +00003725 ll = nasm_malloc(sizeof(Line));
3726 ll->next = istk->expansion;
3727 ll->finishes = NULL;
3728 ll->first = NULL;
3729 tail = &ll->first;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003730
H. Peter Anvine2c80182005-01-15 22:15:51 +00003731 for (t = l->first; t; t = t->next) {
3732 if (t->text || t->type == TOK_WHITESPACE) {
3733 tt = *tail =
3734 new_Token(NULL, t->type, t->text, 0);
3735 tail = &tt->next;
3736 }
3737 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003738
H. Peter Anvine2c80182005-01-15 22:15:51 +00003739 istk->expansion = ll;
3740 }
3741 } else {
3742 /*
3743 * Check whether a `%rep' was started and not ended
3744 * within this macro expansion. This can happen and
3745 * should be detected. It's a fatal error because
3746 * I'm too confused to work out how to recover
3747 * sensibly from it.
3748 */
3749 if (defining) {
3750 if (defining->name)
3751 error(ERR_PANIC,
3752 "defining with name in expansion");
3753 else if (istk->mstk->name)
3754 error(ERR_FATAL,
3755 "`%%rep' without `%%endrep' within"
3756 " expansion of macro `%s'",
3757 istk->mstk->name);
3758 }
H. Peter Anvin87bc6192002-04-30 20:53:16 +00003759
H. Peter Anvine2c80182005-01-15 22:15:51 +00003760 /*
3761 * FIXME: investigate the relationship at this point between
3762 * istk->mstk and l->finishes
3763 */
3764 {
3765 MMacro *m = istk->mstk;
3766 istk->mstk = m->next_active;
3767 if (m->name) {
3768 /*
3769 * This was a real macro call, not a %rep, and
3770 * therefore the parameter information needs to
3771 * be freed.
3772 */
3773 nasm_free(m->params);
3774 free_tlist(m->iline);
3775 nasm_free(m->paramlen);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003776 l->finishes->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003777 } else
3778 free_mmacro(m);
3779 }
3780 istk->expansion = l->next;
3781 nasm_free(l);
3782 list->downlevel(LIST_MACRO);
3783 }
3784 }
3785 while (1) { /* until we get a line we can use */
H. Peter Anvineba20a72002-04-30 20:53:55 +00003786
H. Peter Anvine2c80182005-01-15 22:15:51 +00003787 if (istk->expansion) { /* from a macro expansion */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003788 char *p;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003789 Line *l = istk->expansion;
3790 if (istk->mstk)
3791 istk->mstk->lineno++;
3792 tline = l->first;
3793 istk->expansion = l->next;
3794 nasm_free(l);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003795 p = detoken(tline, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003796 list->line(LIST_MACRO, p);
3797 nasm_free(p);
3798 break;
3799 }
3800 line = read_line();
3801 if (line) { /* from the current input file */
3802 line = prepreproc(line);
Keith Kaniosb7a89542007-04-12 02:40:54 +00003803 tline = tokenize(line);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003804 nasm_free(line);
3805 break;
3806 }
3807 /*
3808 * The current file has ended; work down the istk
3809 */
3810 {
3811 Include *i = istk;
3812 fclose(i->fp);
3813 if (i->conds)
3814 error(ERR_FATAL,
3815 "expected `%%endif' before end of file");
3816 /* only set line and file name if there's a next node */
3817 if (i->next) {
3818 src_set_linnum(i->lineno);
3819 nasm_free(src_set_fname(i->fname));
3820 }
3821 istk = i->next;
3822 list->downlevel(LIST_INCLUDE);
3823 nasm_free(i);
3824 if (!istk)
3825 return NULL;
3826 }
3827 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003828
H. Peter Anvine2c80182005-01-15 22:15:51 +00003829 /*
3830 * We must expand MMacro parameters and MMacro-local labels
3831 * _before_ we plunge into directive processing, to cope
3832 * with things like `%define something %1' such as STRUC
3833 * uses. Unless we're _defining_ a MMacro, in which case
3834 * those tokens should be left alone to go into the
3835 * definition; and unless we're in a non-emitting
3836 * condition, in which case we don't want to meddle with
3837 * anything.
3838 */
3839 if (!defining && !(istk->conds && !emitting(istk->conds->state)))
3840 tline = expand_mmac_params(tline);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003841
H. Peter Anvine2c80182005-01-15 22:15:51 +00003842 /*
3843 * Check the line to see if it's a preprocessor directive.
3844 */
3845 if (do_directive(tline) == DIRECTIVE_FOUND) {
3846 continue;
3847 } else if (defining) {
3848 /*
3849 * We're defining a multi-line macro. We emit nothing
3850 * at all, and just
Keith Kaniosb7a89542007-04-12 02:40:54 +00003851 * shove the tokenized line on to the macro definition.
H. Peter Anvine2c80182005-01-15 22:15:51 +00003852 */
3853 Line *l = nasm_malloc(sizeof(Line));
3854 l->next = defining->expansion;
3855 l->first = tline;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003856 l->finishes = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003857 defining->expansion = l;
3858 continue;
3859 } else if (istk->conds && !emitting(istk->conds->state)) {
3860 /*
3861 * We're in a non-emitting branch of a condition block.
3862 * Emit nothing at all, not even a blank line: when we
3863 * emerge from the condition we'll give a line-number
3864 * directive so we keep our place correctly.
3865 */
3866 free_tlist(tline);
3867 continue;
3868 } else if (istk->mstk && !istk->mstk->in_progress) {
3869 /*
3870 * We're in a %rep block which has been terminated, so
3871 * we're walking through to the %endrep without
3872 * emitting anything. Emit nothing at all, not even a
3873 * blank line: when we emerge from the %rep block we'll
3874 * give a line-number directive so we keep our place
3875 * correctly.
3876 */
3877 free_tlist(tline);
3878 continue;
3879 } else {
3880 tline = expand_smacro(tline);
3881 if (!expand_mmacro(tline)) {
3882 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00003883 * De-tokenize the line again, and emit it.
H. Peter Anvine2c80182005-01-15 22:15:51 +00003884 */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003885 line = detoken(tline, true);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003886 free_tlist(tline);
3887 break;
3888 } else {
3889 continue; /* expand_mmacro calls free_tlist */
3890 }
3891 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003892 }
3893
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003894 return line;
3895}
3896
H. Peter Anvine2c80182005-01-15 22:15:51 +00003897static void pp_cleanup(int pass)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003898{
H. Peter Anvine2c80182005-01-15 22:15:51 +00003899 if (defining) {
3900 error(ERR_NONFATAL, "end of file while still defining macro `%s'",
3901 defining->name);
3902 free_mmacro(defining);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003903 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003904 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003905 ctx_pop();
H. Peter Anvin97a23472007-09-16 17:57:25 -07003906 free_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00003907 while (istk) {
3908 Include *i = istk;
3909 istk = istk->next;
3910 fclose(i->fp);
3911 nasm_free(i->fname);
3912 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003913 }
3914 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003915 ctx_pop();
3916 if (pass == 0) {
3917 free_llist(predef);
3918 delete_Blocks();
3919 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003920}
3921
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003922void pp_include_path(char *path)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003923{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003924 IncPath *i;
H. Peter Anvin37a321f2007-09-24 13:41:58 -07003925
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003926 i = nasm_malloc(sizeof(IncPath));
H. Peter Anvin37a321f2007-09-24 13:41:58 -07003927 i->path = path ? nasm_strdup(path) : NULL;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003928 i->next = NULL;
3929
H. Peter Anvine2c80182005-01-15 22:15:51 +00003930 if (ipath != NULL) {
3931 IncPath *j = ipath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003932 while (j->next != NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003933 j = j->next;
3934 j->next = i;
3935 } else {
3936 ipath = i;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003937 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003938}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003939
3940/*
3941 * added by alexfru:
3942 *
3943 * This function is used to "export" the include paths, e.g.
3944 * the paths specified in the '-I' command switch.
3945 * The need for such exporting is due to the 'incbin' directive,
3946 * which includes raw binary files (unlike '%include', which
3947 * includes text source files). It would be real nice to be
3948 * able to specify paths to search for incbin'ned files also.
3949 * So, this is a simple workaround.
3950 *
3951 * The function use is simple:
3952 *
3953 * The 1st call (with NULL argument) returns a pointer to the 1st path
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003954 * (char** type) or NULL if none include paths available.
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003955 *
3956 * All subsequent calls take as argument the value returned by this
3957 * function last. The return value is either the next path
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003958 * (char** type) or NULL if the end of the paths list is reached.
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003959 *
3960 * It is maybe not the best way to do things, but I didn't want
3961 * to export too much, just one or two functions and no types or
3962 * variables exported.
3963 *
3964 * Can't say I like the current situation with e.g. this path list either,
3965 * it seems to be never deallocated after creation...
3966 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003967char **pp_get_include_path_ptr(char **pPrevPath)
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003968{
3969/* This macro returns offset of a member of a structure */
3970#define GetMemberOffset(StructType,MemberName)\
3971 ((size_t)&((StructType*)0)->MemberName)
3972 IncPath *i;
3973
H. Peter Anvine2c80182005-01-15 22:15:51 +00003974 if (pPrevPath == NULL) {
3975 if (ipath != NULL)
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003976 return &ipath->path;
3977 else
3978 return NULL;
3979 }
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003980 i = (IncPath *) ((char *)pPrevPath - GetMemberOffset(IncPath, path));
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003981 i = i->next;
3982 if (i != NULL)
3983 return &i->path;
3984 else
3985 return NULL;
3986#undef GetMemberOffset
3987}
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003988
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003989void pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003990{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003991 Token *inc, *space, *name;
3992 Line *l;
3993
H. Peter Anvin734b1882002-04-30 21:01:08 +00003994 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
3995 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
3996 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003997
3998 l = nasm_malloc(sizeof(Line));
3999 l->next = predef;
4000 l->first = inc;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004001 l->finishes = false;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004002 predef = l;
4003}
4004
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004005void pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004006{
4007 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004008 Line *l;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004009 char *equals;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004010
4011 equals = strchr(definition, '=');
H. Peter Anvin734b1882002-04-30 21:01:08 +00004012 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4013 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004014 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004015 *equals = ' ';
Keith Kaniosb7a89542007-04-12 02:40:54 +00004016 space->next = tokenize(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004017 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004018 *equals = '=';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004019
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004020 l = nasm_malloc(sizeof(Line));
4021 l->next = predef;
4022 l->first = def;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004023 l->finishes = false;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004024 predef = l;
4025}
4026
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004027void pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00004028{
4029 Token *def, *space;
4030 Line *l;
4031
H. Peter Anvin734b1882002-04-30 21:01:08 +00004032 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4033 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Keith Kaniosb7a89542007-04-12 02:40:54 +00004034 space->next = tokenize(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00004035
4036 l = nasm_malloc(sizeof(Line));
4037 l->next = predef;
4038 l->first = def;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004039 l->finishes = false;
H. Peter Anvin620515a2002-04-30 20:57:38 +00004040 predef = l;
4041}
4042
Keith Kaniosb7a89542007-04-12 02:40:54 +00004043/*
4044 * Added by Keith Kanios:
4045 *
4046 * This function is used to assist with "runtime" preprocessor
4047 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4048 *
4049 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4050 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4051 */
4052
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004053void pp_runtime(char *definition)
Keith Kaniosb7a89542007-04-12 02:40:54 +00004054{
4055 Token *def;
4056
4057 def = tokenize(definition);
4058 if(do_directive(def) == NO_DIRECTIVE_FOUND)
4059 free_tlist(def);
4060
4061}
4062
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004063void pp_extra_stdmac(const char **macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004064{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004065 extrastdmac = macros;
4066}
4067
Keith Kaniosb7a89542007-04-12 02:40:54 +00004068static void make_tok_num(Token * tok, int32_t val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004069{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004070 char numbuf[20];
Keith Kanios93f2e9a2007-04-14 00:10:59 +00004071 snprintf(numbuf, sizeof(numbuf), "%"PRId32"", val);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004072 tok->text = nasm_strdup(numbuf);
4073 tok->type = TOK_NUMBER;
4074}
4075
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004076Preproc nasmpp = {
4077 pp_reset,
4078 pp_getline,
4079 pp_cleanup
4080};