blob: a19db0a091046583c78f778b746559689ba6864f [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 Anvind7ed89e2002-04-30 20:52:08 +000078 int casesense;
H. Peter Anvin25a99342007-09-22 17:45:45 -070079 unsigned int nparam;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000080 int in_progress;
81 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) {
1028 int 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 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001094static int mstrcmp(char *p, char *q, int 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 Anvinda10e7b2007-09-12 04:18:37 +00001343static int 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);
1346 int 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;
1595 int nparam, nolist;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -07001596 int k, m;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001597 int offset;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001598 char *p, *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001599 Include *inc;
1600 Context *ctx;
1601 Cond *cond;
1602 SMacro *smac, **smhead;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001603 MMacro *mmac, **mmhead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001604 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
1605 Line *l;
1606 struct tokenval tokval;
1607 expr *evalresult;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001608 MMacro *tmp_defining; /* Used when manipulating rep_nest */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001609
1610 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001611
H. Peter Anvineba20a72002-04-30 20:53:55 +00001612 skip_white_(tline);
1613 if (!tok_type_(tline, TOK_PREPROC_ID) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001614 (tline->text[1] == '%' || tline->text[1] == '$'
1615 || tline->text[1] == '!'))
1616 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001617
H. Peter Anvin4169a472007-09-12 01:29:43 +00001618 i = pp_token_hash(tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001619
1620 /*
1621 * If we're in a non-emitting branch of a condition construct,
H. Peter Anvin76690a12002-04-30 20:52:49 +00001622 * or walking to the end of an already terminated %rep block,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001623 * we should ignore all directives except for condition
1624 * directives.
1625 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001626 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001627 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
1628 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001629 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001630
1631 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001632 * If we're defining a macro or reading a %rep block, we should
1633 * ignore all directives except for %macro/%imacro (which
1634 * generate an error), %endm/%endmacro, and (only if we're in a
H. Peter Anvineba20a72002-04-30 20:53:55 +00001635 * %rep block) %endrep. If we're in a %rep block, another %rep
1636 * causes an error, so should be let through.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001637 */
1638 if (defining && i != PP_MACRO && i != PP_IMACRO &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001639 i != PP_ENDMACRO && i != PP_ENDM &&
1640 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
1641 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001642 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001643
H. Peter Anvin4169a472007-09-12 01:29:43 +00001644 switch (i) {
1645 case PP_INVALID:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001646 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
1647 tline->text);
1648 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001649
H. Peter Anvine2c80182005-01-15 22:15:51 +00001650 case PP_STACKSIZE:
1651 /* Directive to tell NASM what the default stack size is. The
1652 * default is for a 16-bit stack, and this can be overriden with
1653 * %stacksize large.
1654 * the following form:
1655 *
1656 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1657 */
1658 tline = tline->next;
1659 if (tline && tline->type == TOK_WHITESPACE)
1660 tline = tline->next;
1661 if (!tline || tline->type != TOK_ID) {
1662 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
1663 free_tlist(origline);
1664 return DIRECTIVE_FOUND;
1665 }
1666 if (nasm_stricmp(tline->text, "flat") == 0) {
1667 /* All subsequent ARG directives are for a 32-bit stack */
1668 StackSize = 4;
1669 StackPointer = "ebp";
1670 ArgOffset = 8;
1671 LocalOffset = 4;
1672 } else if (nasm_stricmp(tline->text, "large") == 0) {
1673 /* All subsequent ARG directives are for a 16-bit stack,
1674 * far function call.
1675 */
1676 StackSize = 2;
1677 StackPointer = "bp";
1678 ArgOffset = 4;
1679 LocalOffset = 2;
1680 } else if (nasm_stricmp(tline->text, "small") == 0) {
1681 /* All subsequent ARG directives are for a 16-bit stack,
1682 * far function call. We don't support near functions.
1683 */
1684 StackSize = 2;
1685 StackPointer = "bp";
1686 ArgOffset = 6;
1687 LocalOffset = 2;
1688 } else {
1689 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
1690 free_tlist(origline);
1691 return DIRECTIVE_FOUND;
1692 }
1693 free_tlist(origline);
1694 return DIRECTIVE_FOUND;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001695
H. Peter Anvine2c80182005-01-15 22:15:51 +00001696 case PP_ARG:
1697 /* TASM like ARG directive to define arguments to functions, in
1698 * the following form:
1699 *
1700 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1701 */
1702 offset = ArgOffset;
1703 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001704 char *arg, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00001705 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001706
H. Peter Anvine2c80182005-01-15 22:15:51 +00001707 /* Find the argument name */
1708 tline = tline->next;
1709 if (tline && tline->type == TOK_WHITESPACE)
1710 tline = tline->next;
1711 if (!tline || tline->type != TOK_ID) {
1712 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
1713 free_tlist(origline);
1714 return DIRECTIVE_FOUND;
1715 }
1716 arg = tline->text;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001717
H. Peter Anvine2c80182005-01-15 22:15:51 +00001718 /* Find the argument size type */
1719 tline = tline->next;
1720 if (!tline || tline->type != TOK_OTHER
1721 || tline->text[0] != ':') {
1722 error(ERR_NONFATAL,
1723 "Syntax error processing `%%arg' directive");
1724 free_tlist(origline);
1725 return DIRECTIVE_FOUND;
1726 }
1727 tline = tline->next;
1728 if (!tline || tline->type != TOK_ID) {
1729 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
1730 free_tlist(origline);
1731 return DIRECTIVE_FOUND;
1732 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001733
H. Peter Anvine2c80182005-01-15 22:15:51 +00001734 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001735 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001736 tt = expand_smacro(tt);
1737 if (nasm_stricmp(tt->text, "byte") == 0) {
1738 size = MAX(StackSize, 1);
1739 } else if (nasm_stricmp(tt->text, "word") == 0) {
1740 size = MAX(StackSize, 2);
1741 } else if (nasm_stricmp(tt->text, "dword") == 0) {
1742 size = MAX(StackSize, 4);
1743 } else if (nasm_stricmp(tt->text, "qword") == 0) {
1744 size = MAX(StackSize, 8);
1745 } else if (nasm_stricmp(tt->text, "tword") == 0) {
1746 size = MAX(StackSize, 10);
1747 } else {
1748 error(ERR_NONFATAL,
1749 "Invalid size type for `%%arg' missing directive");
1750 free_tlist(tt);
1751 free_tlist(origline);
1752 return DIRECTIVE_FOUND;
1753 }
1754 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001755
H. Peter Anvine2c80182005-01-15 22:15:51 +00001756 /* Now define the macro for the argument */
1757 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
1758 arg, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001759 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001760 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001761
H. Peter Anvine2c80182005-01-15 22:15:51 +00001762 /* Move to the next argument in the list */
1763 tline = tline->next;
1764 if (tline && tline->type == TOK_WHITESPACE)
1765 tline = tline->next;
1766 }
1767 while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
1768 free_tlist(origline);
1769 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001770
H. Peter Anvine2c80182005-01-15 22:15:51 +00001771 case PP_LOCAL:
1772 /* TASM like LOCAL directive to define local variables for a
1773 * function, in the following form:
1774 *
1775 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
1776 *
1777 * The '= LocalSize' at the end is ignored by NASM, but is
1778 * required by TASM to define the local parameter size (and used
1779 * by the TASM macro package).
1780 */
1781 offset = LocalOffset;
1782 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001783 char *local, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00001784 int size = StackSize;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001785
H. Peter Anvine2c80182005-01-15 22:15:51 +00001786 /* Find the argument name */
1787 tline = tline->next;
1788 if (tline && tline->type == TOK_WHITESPACE)
1789 tline = tline->next;
1790 if (!tline || tline->type != TOK_ID) {
1791 error(ERR_NONFATAL,
1792 "`%%local' missing argument parameter");
1793 free_tlist(origline);
1794 return DIRECTIVE_FOUND;
1795 }
1796 local = tline->text;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001797
H. Peter Anvine2c80182005-01-15 22:15:51 +00001798 /* Find the argument size type */
1799 tline = tline->next;
1800 if (!tline || tline->type != TOK_OTHER
1801 || tline->text[0] != ':') {
1802 error(ERR_NONFATAL,
1803 "Syntax error processing `%%local' directive");
1804 free_tlist(origline);
1805 return DIRECTIVE_FOUND;
1806 }
1807 tline = tline->next;
1808 if (!tline || tline->type != TOK_ID) {
1809 error(ERR_NONFATAL,
1810 "`%%local' missing size type parameter");
1811 free_tlist(origline);
1812 return DIRECTIVE_FOUND;
1813 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001814
H. Peter Anvine2c80182005-01-15 22:15:51 +00001815 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001816 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001817 tt = expand_smacro(tt);
1818 if (nasm_stricmp(tt->text, "byte") == 0) {
1819 size = MAX(StackSize, 1);
1820 } else if (nasm_stricmp(tt->text, "word") == 0) {
1821 size = MAX(StackSize, 2);
1822 } else if (nasm_stricmp(tt->text, "dword") == 0) {
1823 size = MAX(StackSize, 4);
1824 } else if (nasm_stricmp(tt->text, "qword") == 0) {
1825 size = MAX(StackSize, 8);
1826 } else if (nasm_stricmp(tt->text, "tword") == 0) {
1827 size = MAX(StackSize, 10);
1828 } else {
1829 error(ERR_NONFATAL,
1830 "Invalid size type for `%%local' missing directive");
1831 free_tlist(tt);
1832 free_tlist(origline);
1833 return DIRECTIVE_FOUND;
1834 }
1835 free_tlist(tt);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001836
H. Peter Anvine2c80182005-01-15 22:15:51 +00001837 /* Now define the macro for the argument */
1838 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
1839 local, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001840 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001841 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001842
H. Peter Anvine2c80182005-01-15 22:15:51 +00001843 /* Now define the assign to setup the enter_c macro correctly */
1844 snprintf(directive, sizeof(directive),
1845 "%%assign %%$localsize %%$localsize+%d", size);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001846 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001847
H. Peter Anvine2c80182005-01-15 22:15:51 +00001848 /* Move to the next argument in the list */
1849 tline = tline->next;
1850 if (tline && tline->type == TOK_WHITESPACE)
1851 tline = tline->next;
1852 }
1853 while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
1854 free_tlist(origline);
1855 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001856
H. Peter Anvine2c80182005-01-15 22:15:51 +00001857 case PP_CLEAR:
1858 if (tline->next)
1859 error(ERR_WARNING, "trailing garbage after `%%clear' ignored");
H. Peter Anvin97a23472007-09-16 17:57:25 -07001860 free_macros();
1861 init_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001862 free_tlist(origline);
1863 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001864
H. Peter Anvine2c80182005-01-15 22:15:51 +00001865 case PP_INCLUDE:
1866 tline = tline->next;
1867 skip_white_(tline);
1868 if (!tline || (tline->type != TOK_STRING &&
1869 tline->type != TOK_INTERNAL_STRING)) {
1870 error(ERR_NONFATAL, "`%%include' expects a file name");
1871 free_tlist(origline);
1872 return DIRECTIVE_FOUND; /* but we did _something_ */
1873 }
1874 if (tline->next)
1875 error(ERR_WARNING,
1876 "trailing garbage after `%%include' ignored");
1877 if (tline->type != TOK_INTERNAL_STRING) {
1878 p = tline->text + 1; /* point past the quote to the name */
1879 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
1880 } else
1881 p = tline->text; /* internal_string is easier */
1882 expand_macros_in_string(&p);
1883 inc = nasm_malloc(sizeof(Include));
1884 inc->next = istk;
1885 inc->conds = NULL;
1886 inc->fp = inc_fopen(p);
H. Peter Anvin37a321f2007-09-24 13:41:58 -07001887 if (!inc->fp && pass == 0) {
1888 /* -MG given but file not found */
1889 nasm_free(inc);
1890 } else {
1891 inc->fname = src_set_fname(p);
1892 inc->lineno = src_set_linnum(0);
1893 inc->lineinc = 1;
1894 inc->expansion = NULL;
1895 inc->mstk = NULL;
1896 istk = inc;
1897 list->uplevel(LIST_INCLUDE);
1898 }
1899 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001900 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001901
H. Peter Anvine2c80182005-01-15 22:15:51 +00001902 case PP_PUSH:
1903 tline = tline->next;
1904 skip_white_(tline);
1905 tline = expand_id(tline);
1906 if (!tok_type_(tline, TOK_ID)) {
1907 error(ERR_NONFATAL, "`%%push' expects a context identifier");
1908 free_tlist(origline);
1909 return DIRECTIVE_FOUND; /* but we did _something_ */
1910 }
1911 if (tline->next)
1912 error(ERR_WARNING, "trailing garbage after `%%push' ignored");
1913 ctx = nasm_malloc(sizeof(Context));
1914 ctx->next = cstk;
1915 ctx->localmac = NULL;
1916 ctx->name = nasm_strdup(tline->text);
1917 ctx->number = unique++;
1918 cstk = ctx;
1919 free_tlist(origline);
1920 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001921
H. Peter Anvine2c80182005-01-15 22:15:51 +00001922 case PP_REPL:
1923 tline = tline->next;
1924 skip_white_(tline);
1925 tline = expand_id(tline);
1926 if (!tok_type_(tline, TOK_ID)) {
1927 error(ERR_NONFATAL, "`%%repl' expects a context identifier");
1928 free_tlist(origline);
1929 return DIRECTIVE_FOUND; /* but we did _something_ */
1930 }
1931 if (tline->next)
1932 error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
1933 if (!cstk)
1934 error(ERR_NONFATAL, "`%%repl': context stack is empty");
1935 else {
1936 nasm_free(cstk->name);
1937 cstk->name = nasm_strdup(tline->text);
1938 }
1939 free_tlist(origline);
1940 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001941
H. Peter Anvine2c80182005-01-15 22:15:51 +00001942 case PP_POP:
1943 if (tline->next)
1944 error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
1945 if (!cstk)
1946 error(ERR_NONFATAL, "`%%pop': context stack is already empty");
1947 else
1948 ctx_pop();
1949 free_tlist(origline);
1950 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001951
H. Peter Anvine2c80182005-01-15 22:15:51 +00001952 case PP_ERROR:
1953 tline->next = expand_smacro(tline->next);
1954 tline = tline->next;
1955 skip_white_(tline);
1956 if (tok_type_(tline, TOK_STRING)) {
1957 p = tline->text + 1; /* point past the quote to the name */
1958 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
1959 expand_macros_in_string(&p);
1960 error(ERR_NONFATAL, "%s", p);
1961 nasm_free(p);
1962 } else {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001963 p = detoken(tline, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001964 error(ERR_WARNING, "%s", p);
1965 nasm_free(p);
1966 }
1967 free_tlist(origline);
1968 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001969
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001970 CASE_PP_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001971 if (istk->conds && !emitting(istk->conds->state))
1972 j = COND_NEVER;
1973 else {
1974 j = if_condition(tline->next, i);
1975 tline->next = NULL; /* it got freed */
1976 free_tlist(origline);
1977 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
1978 }
1979 cond = nasm_malloc(sizeof(Cond));
1980 cond->next = istk->conds;
1981 cond->state = j;
1982 istk->conds = cond;
1983 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001984
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001985 CASE_PP_ELIF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001986 if (!istk->conds)
H. Peter Anvin4169a472007-09-12 01:29:43 +00001987 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001988 if (emitting(istk->conds->state)
1989 || istk->conds->state == COND_NEVER)
1990 istk->conds->state = COND_NEVER;
1991 else {
1992 /*
1993 * IMPORTANT: In the case of %if, we will already have
1994 * called expand_mmac_params(); however, if we're
1995 * processing an %elif we must have been in a
1996 * non-emitting mode, which would have inhibited
1997 * the normal invocation of expand_mmac_params(). Therefore,
1998 * we have to do it explicitly here.
1999 */
2000 j = if_condition(expand_mmac_params(tline->next), i);
2001 tline->next = NULL; /* it got freed */
2002 free_tlist(origline);
2003 istk->conds->state =
2004 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2005 }
2006 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002007
H. Peter Anvine2c80182005-01-15 22:15:51 +00002008 case PP_ELSE:
2009 if (tline->next)
2010 error(ERR_WARNING, "trailing garbage after `%%else' ignored");
2011 if (!istk->conds)
2012 error(ERR_FATAL, "`%%else': no matching `%%if'");
2013 if (emitting(istk->conds->state)
2014 || istk->conds->state == COND_NEVER)
2015 istk->conds->state = COND_ELSE_FALSE;
2016 else
2017 istk->conds->state = COND_ELSE_TRUE;
2018 free_tlist(origline);
2019 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002020
H. Peter Anvine2c80182005-01-15 22:15:51 +00002021 case PP_ENDIF:
2022 if (tline->next)
2023 error(ERR_WARNING, "trailing garbage after `%%endif' ignored");
2024 if (!istk->conds)
2025 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2026 cond = istk->conds;
2027 istk->conds = cond->next;
2028 nasm_free(cond);
2029 free_tlist(origline);
2030 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002031
H. Peter Anvine2c80182005-01-15 22:15:51 +00002032 case PP_MACRO:
2033 case PP_IMACRO:
2034 if (defining)
2035 error(ERR_FATAL,
2036 "`%%%smacro': already defining a macro",
2037 (i == PP_IMACRO ? "i" : ""));
2038 tline = tline->next;
2039 skip_white_(tline);
2040 tline = expand_id(tline);
2041 if (!tok_type_(tline, TOK_ID)) {
2042 error(ERR_NONFATAL,
2043 "`%%%smacro' expects a macro name",
2044 (i == PP_IMACRO ? "i" : ""));
2045 return DIRECTIVE_FOUND;
2046 }
2047 defining = nasm_malloc(sizeof(MMacro));
2048 defining->name = nasm_strdup(tline->text);
2049 defining->casesense = (i == PP_MACRO);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002050 defining->plus = false;
2051 defining->nolist = false;
2052 defining->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002053 defining->rep_nest = NULL;
2054 tline = expand_smacro(tline->next);
2055 skip_white_(tline);
2056 if (!tok_type_(tline, TOK_NUMBER)) {
2057 error(ERR_NONFATAL,
2058 "`%%%smacro' expects a parameter count",
2059 (i == PP_IMACRO ? "i" : ""));
2060 defining->nparam_min = defining->nparam_max = 0;
2061 } else {
2062 defining->nparam_min = defining->nparam_max =
2063 readnum(tline->text, &j);
2064 if (j)
2065 error(ERR_NONFATAL,
2066 "unable to parse parameter count `%s'", tline->text);
2067 }
2068 if (tline && tok_is_(tline->next, "-")) {
2069 tline = tline->next->next;
2070 if (tok_is_(tline, "*"))
2071 defining->nparam_max = INT_MAX;
2072 else if (!tok_type_(tline, TOK_NUMBER))
2073 error(ERR_NONFATAL,
2074 "`%%%smacro' expects a parameter count after `-'",
2075 (i == PP_IMACRO ? "i" : ""));
2076 else {
2077 defining->nparam_max = readnum(tline->text, &j);
2078 if (j)
2079 error(ERR_NONFATAL,
2080 "unable to parse parameter count `%s'",
2081 tline->text);
2082 if (defining->nparam_min > defining->nparam_max)
2083 error(ERR_NONFATAL,
2084 "minimum parameter count exceeds maximum");
2085 }
2086 }
2087 if (tline && tok_is_(tline->next, "+")) {
2088 tline = tline->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002089 defining->plus = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002090 }
2091 if (tline && tok_type_(tline->next, TOK_ID) &&
2092 !nasm_stricmp(tline->next->text, ".nolist")) {
2093 tline = tline->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002094 defining->nolist = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002095 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07002096 mmac = (MMacro *) hash_findix(mmacros, defining->name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002097 while (mmac) {
2098 if (!strcmp(mmac->name, defining->name) &&
2099 (mmac->nparam_min <= defining->nparam_max
2100 || defining->plus)
2101 && (defining->nparam_min <= mmac->nparam_max
2102 || mmac->plus)) {
2103 error(ERR_WARNING,
2104 "redefining multi-line macro `%s'", defining->name);
2105 break;
2106 }
2107 mmac = mmac->next;
2108 }
2109 /*
2110 * Handle default parameters.
2111 */
2112 if (tline && tline->next) {
2113 defining->dlist = tline->next;
2114 tline->next = NULL;
2115 count_mmac_params(defining->dlist, &defining->ndefs,
2116 &defining->defaults);
2117 } else {
2118 defining->dlist = NULL;
2119 defining->defaults = NULL;
2120 }
2121 defining->expansion = NULL;
2122 free_tlist(origline);
2123 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002124
H. Peter Anvine2c80182005-01-15 22:15:51 +00002125 case PP_ENDM:
2126 case PP_ENDMACRO:
2127 if (!defining) {
2128 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2129 return DIRECTIVE_FOUND;
2130 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07002131 mmhead = (MMacro **) hash_findi_add(mmacros, defining->name);
2132 defining->next = *mmhead;
2133 *mmhead = defining;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002134 defining = NULL;
2135 free_tlist(origline);
2136 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002137
H. Peter Anvine2c80182005-01-15 22:15:51 +00002138 case PP_ROTATE:
2139 if (tline->next && tline->next->type == TOK_WHITESPACE)
2140 tline = tline->next;
2141 if (tline->next == NULL) {
2142 free_tlist(origline);
2143 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2144 return DIRECTIVE_FOUND;
2145 }
2146 t = expand_smacro(tline->next);
2147 tline->next = NULL;
2148 free_tlist(origline);
2149 tline = t;
2150 tptr = &t;
2151 tokval.t_type = TOKEN_INVALID;
2152 evalresult =
2153 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2154 free_tlist(tline);
2155 if (!evalresult)
2156 return DIRECTIVE_FOUND;
2157 if (tokval.t_type)
2158 error(ERR_WARNING,
2159 "trailing garbage after expression ignored");
2160 if (!is_simple(evalresult)) {
2161 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2162 return DIRECTIVE_FOUND;
2163 }
2164 mmac = istk->mstk;
2165 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2166 mmac = mmac->next_active;
2167 if (!mmac) {
2168 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2169 } else if (mmac->nparam == 0) {
2170 error(ERR_NONFATAL,
2171 "`%%rotate' invoked within macro without parameters");
2172 } else {
H. Peter Anvin25a99342007-09-22 17:45:45 -07002173 int rotate = mmac->rotate + reloc_value(evalresult);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002174
H. Peter Anvin25a99342007-09-22 17:45:45 -07002175 rotate %= (int)mmac->nparam;
2176 if (rotate < 0)
2177 rotate += mmac->nparam;
2178
2179 mmac->rotate = rotate;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002180 }
2181 return DIRECTIVE_FOUND;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002182
H. Peter Anvine2c80182005-01-15 22:15:51 +00002183 case PP_REP:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002184 nolist = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002185 do {
2186 tline = tline->next;
2187 } while (tok_type_(tline, TOK_WHITESPACE));
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002188
H. Peter Anvine2c80182005-01-15 22:15:51 +00002189 if (tok_type_(tline, TOK_ID) &&
2190 nasm_stricmp(tline->text, ".nolist") == 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002191 nolist = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002192 do {
2193 tline = tline->next;
2194 } while (tok_type_(tline, TOK_WHITESPACE));
2195 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002196
H. Peter Anvine2c80182005-01-15 22:15:51 +00002197 if (tline) {
2198 t = expand_smacro(tline);
2199 tptr = &t;
2200 tokval.t_type = TOKEN_INVALID;
2201 evalresult =
2202 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2203 if (!evalresult) {
2204 free_tlist(origline);
2205 return DIRECTIVE_FOUND;
2206 }
2207 if (tokval.t_type)
2208 error(ERR_WARNING,
2209 "trailing garbage after expression ignored");
2210 if (!is_simple(evalresult)) {
2211 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2212 return DIRECTIVE_FOUND;
2213 }
2214 i = (int)reloc_value(evalresult) + 1;
2215 } else {
2216 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
2217 i = 0;
2218 }
2219 free_tlist(origline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002220
H. Peter Anvine2c80182005-01-15 22:15:51 +00002221 tmp_defining = defining;
2222 defining = nasm_malloc(sizeof(MMacro));
2223 defining->name = NULL; /* flags this macro as a %rep block */
2224 defining->casesense = 0;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002225 defining->plus = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002226 defining->nolist = nolist;
2227 defining->in_progress = i;
2228 defining->nparam_min = defining->nparam_max = 0;
2229 defining->defaults = NULL;
2230 defining->dlist = NULL;
2231 defining->expansion = NULL;
2232 defining->next_active = istk->mstk;
2233 defining->rep_nest = tmp_defining;
2234 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002235
H. Peter Anvine2c80182005-01-15 22:15:51 +00002236 case PP_ENDREP:
2237 if (!defining || defining->name) {
2238 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2239 return DIRECTIVE_FOUND;
2240 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002241
H. Peter Anvine2c80182005-01-15 22:15:51 +00002242 /*
2243 * Now we have a "macro" defined - although it has no name
2244 * and we won't be entering it in the hash tables - we must
2245 * push a macro-end marker for it on to istk->expansion.
2246 * After that, it will take care of propagating itself (a
2247 * macro-end marker line for a macro which is really a %rep
2248 * block will cause the macro to be re-expanded, complete
2249 * with another macro-end marker to ensure the process
2250 * continues) until the whole expansion is forcibly removed
2251 * from istk->expansion by a %exitrep.
2252 */
2253 l = nasm_malloc(sizeof(Line));
2254 l->next = istk->expansion;
2255 l->finishes = defining;
2256 l->first = NULL;
2257 istk->expansion = l;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002258
H. Peter Anvine2c80182005-01-15 22:15:51 +00002259 istk->mstk = defining;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002260
H. Peter Anvine2c80182005-01-15 22:15:51 +00002261 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2262 tmp_defining = defining;
2263 defining = defining->rep_nest;
2264 free_tlist(origline);
2265 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002266
H. Peter Anvine2c80182005-01-15 22:15:51 +00002267 case PP_EXITREP:
2268 /*
2269 * We must search along istk->expansion until we hit a
2270 * macro-end marker for a macro with no name. Then we set
2271 * its `in_progress' flag to 0.
2272 */
2273 for (l = istk->expansion; l; l = l->next)
2274 if (l->finishes && !l->finishes->name)
2275 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002276
H. Peter Anvine2c80182005-01-15 22:15:51 +00002277 if (l)
2278 l->finishes->in_progress = 0;
2279 else
2280 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2281 free_tlist(origline);
2282 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002283
H. Peter Anvine2c80182005-01-15 22:15:51 +00002284 case PP_XDEFINE:
2285 case PP_IXDEFINE:
2286 case PP_DEFINE:
2287 case PP_IDEFINE:
2288 tline = tline->next;
2289 skip_white_(tline);
2290 tline = expand_id(tline);
2291 if (!tline || (tline->type != TOK_ID &&
2292 (tline->type != TOK_PREPROC_ID ||
2293 tline->text[1] != '$'))) {
2294 error(ERR_NONFATAL,
2295 "`%%%s%sdefine' expects a macro identifier",
2296 ((i == PP_IDEFINE || i == PP_IXDEFINE) ? "i" : ""),
2297 ((i == PP_XDEFINE || i == PP_IXDEFINE) ? "x" : ""));
2298 free_tlist(origline);
2299 return DIRECTIVE_FOUND;
2300 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002301
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002302 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002303
H. Peter Anvine2c80182005-01-15 22:15:51 +00002304 mname = tline->text;
2305 last = tline;
2306 param_start = tline = tline->next;
2307 nparam = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002308
H. Peter Anvine2c80182005-01-15 22:15:51 +00002309 /* Expand the macro definition now for %xdefine and %ixdefine */
2310 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2311 tline = expand_smacro(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002312
H. Peter Anvine2c80182005-01-15 22:15:51 +00002313 if (tok_is_(tline, "(")) {
2314 /*
2315 * This macro has parameters.
2316 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002317
H. Peter Anvine2c80182005-01-15 22:15:51 +00002318 tline = tline->next;
2319 while (1) {
2320 skip_white_(tline);
2321 if (!tline) {
2322 error(ERR_NONFATAL, "parameter identifier expected");
2323 free_tlist(origline);
2324 return DIRECTIVE_FOUND;
2325 }
2326 if (tline->type != TOK_ID) {
2327 error(ERR_NONFATAL,
2328 "`%s': parameter identifier expected",
2329 tline->text);
2330 free_tlist(origline);
2331 return DIRECTIVE_FOUND;
2332 }
2333 tline->type = TOK_SMAC_PARAM + nparam++;
2334 tline = tline->next;
2335 skip_white_(tline);
2336 if (tok_is_(tline, ",")) {
2337 tline = tline->next;
2338 continue;
2339 }
2340 if (!tok_is_(tline, ")")) {
2341 error(ERR_NONFATAL,
2342 "`)' expected to terminate macro template");
2343 free_tlist(origline);
2344 return DIRECTIVE_FOUND;
2345 }
2346 break;
2347 }
2348 last = tline;
2349 tline = tline->next;
2350 }
2351 if (tok_type_(tline, TOK_WHITESPACE))
2352 last = tline, tline = tline->next;
2353 macro_start = NULL;
2354 last->next = NULL;
2355 t = tline;
2356 while (t) {
2357 if (t->type == TOK_ID) {
2358 for (tt = param_start; tt; tt = tt->next)
2359 if (tt->type >= TOK_SMAC_PARAM &&
2360 !strcmp(tt->text, t->text))
2361 t->type = tt->type;
2362 }
2363 tt = t->next;
2364 t->next = macro_start;
2365 macro_start = t;
2366 t = tt;
2367 }
2368 /*
2369 * Good. We now have a macro name, a parameter count, and a
2370 * token list (in reverse order) for an expansion. We ought
2371 * to be OK just to create an SMacro, store it, and let
2372 * free_tlist have the rest of the line (which we have
2373 * carefully re-terminated after chopping off the expansion
2374 * from the end).
2375 */
2376 if (smacro_defined(ctx, mname, nparam, &smac, i == PP_DEFINE)) {
2377 if (!smac) {
2378 error(ERR_WARNING,
2379 "single-line macro `%s' defined both with and"
2380 " without parameters", mname);
2381 free_tlist(origline);
2382 free_tlist(macro_start);
2383 return DIRECTIVE_FOUND;
2384 } else {
2385 /*
2386 * We're redefining, so we have to take over an
2387 * existing SMacro structure. This means freeing
2388 * what was already in it.
2389 */
2390 nasm_free(smac->name);
2391 free_tlist(smac->expansion);
2392 }
2393 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002394 if (!ctx)
2395 smhead = (SMacro **) hash_findi_add(smacros, mname);
2396 else
2397 smhead = &ctx->localmac;
2398
H. Peter Anvine2c80182005-01-15 22:15:51 +00002399 smac = nasm_malloc(sizeof(SMacro));
2400 smac->next = *smhead;
2401 *smhead = smac;
2402 }
2403 smac->name = nasm_strdup(mname);
2404 smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE));
2405 smac->nparam = nparam;
2406 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002407 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002408 free_tlist(origline);
2409 return DIRECTIVE_FOUND;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002410
H. Peter Anvine2c80182005-01-15 22:15:51 +00002411 case PP_UNDEF:
2412 tline = tline->next;
2413 skip_white_(tline);
2414 tline = expand_id(tline);
2415 if (!tline || (tline->type != TOK_ID &&
2416 (tline->type != TOK_PREPROC_ID ||
2417 tline->text[1] != '$'))) {
2418 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2419 free_tlist(origline);
2420 return DIRECTIVE_FOUND;
2421 }
2422 if (tline->next) {
2423 error(ERR_WARNING,
2424 "trailing garbage after macro name ignored");
2425 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002426
H. Peter Anvine2c80182005-01-15 22:15:51 +00002427 /* Find the context that symbol belongs to */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002428 ctx = get_ctx(tline->text, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002429 if (!ctx)
H. Peter Anvin97a23472007-09-16 17:57:25 -07002430 smhead = (SMacro **) hash_findi(smacros, tline->text, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002431 else
2432 smhead = &ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002433
H. Peter Anvin97a23472007-09-16 17:57:25 -07002434 if (smhead) {
2435 SMacro *s, **sp;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002436
H. Peter Anvin97a23472007-09-16 17:57:25 -07002437 mname = tline->text;
2438 last = tline;
2439 last->next = NULL;
2440
2441 /*
2442 * We now have a macro name... go hunt for it.
2443 */
H. Peter Anvine373efd2007-09-24 21:33:17 -07002444 sp = smhead;
2445 while ((s = *sp) != NULL) {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002446 if (!mstrcmp(s->name, tline->text, s->casesense)) {
2447 *sp = s->next;
2448 nasm_free(s->name);
2449 free_tlist(s->expansion);
2450 nasm_free(s);
H. Peter Anvine373efd2007-09-24 21:33:17 -07002451 } else {
2452 sp = &s->next;
H. Peter Anvin97a23472007-09-16 17:57:25 -07002453 }
2454 }
2455 free_tlist(origline);
2456 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002457 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002458
H. Peter Anvine2c80182005-01-15 22:15:51 +00002459 case PP_STRLEN:
2460 tline = tline->next;
2461 skip_white_(tline);
2462 tline = expand_id(tline);
2463 if (!tline || (tline->type != TOK_ID &&
2464 (tline->type != TOK_PREPROC_ID ||
2465 tline->text[1] != '$'))) {
2466 error(ERR_NONFATAL,
2467 "`%%strlen' expects a macro identifier as first parameter");
2468 free_tlist(origline);
2469 return DIRECTIVE_FOUND;
2470 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002471 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002472
H. Peter Anvine2c80182005-01-15 22:15:51 +00002473 mname = tline->text;
2474 last = tline;
2475 tline = expand_smacro(tline->next);
2476 last->next = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002477
H. Peter Anvine2c80182005-01-15 22:15:51 +00002478 t = tline;
2479 while (tok_type_(t, TOK_WHITESPACE))
2480 t = t->next;
2481 /* t should now point to the string */
2482 if (t->type != TOK_STRING) {
2483 error(ERR_NONFATAL,
2484 "`%%strlen` requires string as second parameter");
2485 free_tlist(tline);
2486 free_tlist(origline);
2487 return DIRECTIVE_FOUND;
2488 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002489
H. Peter Anvine2c80182005-01-15 22:15:51 +00002490 macro_start = nasm_malloc(sizeof(*macro_start));
2491 macro_start->next = NULL;
2492 make_tok_num(macro_start, strlen(t->text) - 2);
2493 macro_start->mac = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002494
H. Peter Anvine2c80182005-01-15 22:15:51 +00002495 /*
2496 * We now have a macro name, an implicit parameter count of
2497 * zero, and a numeric token to use as an expansion. Create
2498 * and store an SMacro.
2499 */
2500 if (smacro_defined(ctx, mname, 0, &smac, i == PP_STRLEN)) {
2501 if (!smac)
2502 error(ERR_WARNING,
2503 "single-line macro `%s' defined both with and"
2504 " without parameters", mname);
2505 else {
2506 /*
2507 * We're redefining, so we have to take over an
2508 * existing SMacro structure. This means freeing
2509 * what was already in it.
2510 */
2511 nasm_free(smac->name);
2512 free_tlist(smac->expansion);
2513 }
2514 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002515 if (!ctx)
2516 smhead = (SMacro **) hash_findi_add(smacros, mname);
2517 else
2518 smhead = &ctx->localmac;
2519
H. Peter Anvine2c80182005-01-15 22:15:51 +00002520 smac = nasm_malloc(sizeof(SMacro));
2521 smac->next = *smhead;
2522 *smhead = smac;
2523 }
2524 smac->name = nasm_strdup(mname);
2525 smac->casesense = (i == PP_STRLEN);
2526 smac->nparam = 0;
2527 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002528 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002529 free_tlist(tline);
2530 free_tlist(origline);
2531 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002532
H. Peter Anvine2c80182005-01-15 22:15:51 +00002533 case PP_SUBSTR:
2534 tline = tline->next;
2535 skip_white_(tline);
2536 tline = expand_id(tline);
2537 if (!tline || (tline->type != TOK_ID &&
2538 (tline->type != TOK_PREPROC_ID ||
2539 tline->text[1] != '$'))) {
2540 error(ERR_NONFATAL,
2541 "`%%substr' expects a macro identifier as first parameter");
2542 free_tlist(origline);
2543 return DIRECTIVE_FOUND;
2544 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002545 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002546
H. Peter Anvine2c80182005-01-15 22:15:51 +00002547 mname = tline->text;
2548 last = tline;
2549 tline = expand_smacro(tline->next);
2550 last->next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002551
H. Peter Anvine2c80182005-01-15 22:15:51 +00002552 t = tline->next;
2553 while (tok_type_(t, TOK_WHITESPACE))
2554 t = t->next;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002555
H. Peter Anvine2c80182005-01-15 22:15:51 +00002556 /* t should now point to the string */
2557 if (t->type != TOK_STRING) {
2558 error(ERR_NONFATAL,
2559 "`%%substr` requires string as second parameter");
2560 free_tlist(tline);
2561 free_tlist(origline);
2562 return DIRECTIVE_FOUND;
2563 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002564
H. Peter Anvine2c80182005-01-15 22:15:51 +00002565 tt = t->next;
2566 tptr = &tt;
2567 tokval.t_type = TOKEN_INVALID;
2568 evalresult =
2569 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2570 if (!evalresult) {
2571 free_tlist(tline);
2572 free_tlist(origline);
2573 return DIRECTIVE_FOUND;
2574 }
2575 if (!is_simple(evalresult)) {
2576 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
2577 free_tlist(tline);
2578 free_tlist(origline);
2579 return DIRECTIVE_FOUND;
2580 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002581
H. Peter Anvine2c80182005-01-15 22:15:51 +00002582 macro_start = nasm_malloc(sizeof(*macro_start));
2583 macro_start->next = NULL;
2584 macro_start->text = nasm_strdup("'''");
2585 if (evalresult->value > 0
2586 && evalresult->value < strlen(t->text) - 1) {
2587 macro_start->text[1] = t->text[evalresult->value];
2588 } else {
2589 macro_start->text[2] = '\0';
2590 }
2591 macro_start->type = TOK_STRING;
2592 macro_start->mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002593
H. Peter Anvine2c80182005-01-15 22:15:51 +00002594 /*
2595 * We now have a macro name, an implicit parameter count of
2596 * zero, and a numeric token to use as an expansion. Create
2597 * and store an SMacro.
2598 */
2599 if (smacro_defined(ctx, mname, 0, &smac, i == PP_SUBSTR)) {
2600 if (!smac)
2601 error(ERR_WARNING,
2602 "single-line macro `%s' defined both with and"
2603 " without parameters", mname);
2604 else {
2605 /*
2606 * We're redefining, so we have to take over an
2607 * existing SMacro structure. This means freeing
2608 * what was already in it.
2609 */
2610 nasm_free(smac->name);
2611 free_tlist(smac->expansion);
2612 }
2613 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002614 if (!ctx)
2615 smhead = (SMacro **) hash_findi_add(smacros, tline->text);
2616 else
2617 smhead = &ctx->localmac;
2618
H. Peter Anvine2c80182005-01-15 22:15:51 +00002619 smac = nasm_malloc(sizeof(SMacro));
2620 smac->next = *smhead;
2621 *smhead = smac;
2622 }
2623 smac->name = nasm_strdup(mname);
2624 smac->casesense = (i == PP_SUBSTR);
2625 smac->nparam = 0;
2626 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002627 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002628 free_tlist(tline);
2629 free_tlist(origline);
2630 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002631
H. Peter Anvine2c80182005-01-15 22:15:51 +00002632 case PP_ASSIGN:
2633 case PP_IASSIGN:
2634 tline = tline->next;
2635 skip_white_(tline);
2636 tline = expand_id(tline);
2637 if (!tline || (tline->type != TOK_ID &&
2638 (tline->type != TOK_PREPROC_ID ||
2639 tline->text[1] != '$'))) {
2640 error(ERR_NONFATAL,
2641 "`%%%sassign' expects a macro identifier",
2642 (i == PP_IASSIGN ? "i" : ""));
2643 free_tlist(origline);
2644 return DIRECTIVE_FOUND;
2645 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002646 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002647
H. Peter Anvine2c80182005-01-15 22:15:51 +00002648 mname = tline->text;
2649 last = tline;
2650 tline = expand_smacro(tline->next);
2651 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002652
H. Peter Anvine2c80182005-01-15 22:15:51 +00002653 t = tline;
2654 tptr = &t;
2655 tokval.t_type = TOKEN_INVALID;
2656 evalresult =
2657 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2658 free_tlist(tline);
2659 if (!evalresult) {
2660 free_tlist(origline);
2661 return DIRECTIVE_FOUND;
2662 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002663
H. Peter Anvine2c80182005-01-15 22:15:51 +00002664 if (tokval.t_type)
2665 error(ERR_WARNING,
2666 "trailing garbage after expression ignored");
H. Peter Anvin734b1882002-04-30 21:01:08 +00002667
H. Peter Anvine2c80182005-01-15 22:15:51 +00002668 if (!is_simple(evalresult)) {
2669 error(ERR_NONFATAL,
2670 "non-constant value given to `%%%sassign'",
2671 (i == PP_IASSIGN ? "i" : ""));
2672 free_tlist(origline);
2673 return DIRECTIVE_FOUND;
2674 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002675
H. Peter Anvine2c80182005-01-15 22:15:51 +00002676 macro_start = nasm_malloc(sizeof(*macro_start));
2677 macro_start->next = NULL;
2678 make_tok_num(macro_start, reloc_value(evalresult));
2679 macro_start->mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002680
H. Peter Anvine2c80182005-01-15 22:15:51 +00002681 /*
2682 * We now have a macro name, an implicit parameter count of
2683 * zero, and a numeric token to use as an expansion. Create
2684 * and store an SMacro.
2685 */
2686 if (smacro_defined(ctx, mname, 0, &smac, i == PP_ASSIGN)) {
2687 if (!smac)
2688 error(ERR_WARNING,
2689 "single-line macro `%s' defined both with and"
2690 " without parameters", mname);
2691 else {
2692 /*
2693 * We're redefining, so we have to take over an
2694 * existing SMacro structure. This means freeing
2695 * what was already in it.
2696 */
2697 nasm_free(smac->name);
2698 free_tlist(smac->expansion);
2699 }
2700 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002701 if (!ctx)
2702 smhead = (SMacro **) hash_findi_add(smacros, mname);
2703 else
2704 smhead = &ctx->localmac;
2705
H. Peter Anvine2c80182005-01-15 22:15:51 +00002706 smac = nasm_malloc(sizeof(SMacro));
2707 smac->next = *smhead;
2708 *smhead = smac;
2709 }
2710 smac->name = nasm_strdup(mname);
2711 smac->casesense = (i == PP_ASSIGN);
2712 smac->nparam = 0;
2713 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002714 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002715 free_tlist(origline);
2716 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002717
H. Peter Anvine2c80182005-01-15 22:15:51 +00002718 case PP_LINE:
2719 /*
2720 * Syntax is `%line nnn[+mmm] [filename]'
2721 */
2722 tline = tline->next;
2723 skip_white_(tline);
2724 if (!tok_type_(tline, TOK_NUMBER)) {
2725 error(ERR_NONFATAL, "`%%line' expects line number");
2726 free_tlist(origline);
2727 return DIRECTIVE_FOUND;
2728 }
2729 k = readnum(tline->text, &j);
2730 m = 1;
2731 tline = tline->next;
2732 if (tok_is_(tline, "+")) {
2733 tline = tline->next;
2734 if (!tok_type_(tline, TOK_NUMBER)) {
2735 error(ERR_NONFATAL, "`%%line' expects line increment");
2736 free_tlist(origline);
2737 return DIRECTIVE_FOUND;
2738 }
2739 m = readnum(tline->text, &j);
2740 tline = tline->next;
2741 }
2742 skip_white_(tline);
2743 src_set_linnum(k);
2744 istk->lineinc = m;
2745 if (tline) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002746 nasm_free(src_set_fname(detoken(tline, false)));
H. Peter Anvine2c80182005-01-15 22:15:51 +00002747 }
2748 free_tlist(origline);
2749 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002750
H. Peter Anvine2c80182005-01-15 22:15:51 +00002751 default:
2752 error(ERR_FATAL,
2753 "preprocessor directive `%s' not yet implemented",
H. Peter Anvin4169a472007-09-12 01:29:43 +00002754 pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002755 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002756 }
Ed Beroset3ab3f412002-06-11 03:31:49 +00002757 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002758}
2759
2760/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002761 * Ensure that a macro parameter contains a condition code and
2762 * nothing else. Return the condition code index if so, or -1
2763 * otherwise.
2764 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002765static int find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002766{
H. Peter Anvin76690a12002-04-30 20:52:49 +00002767 Token *tt;
2768 int i, j, k, m;
2769
H. Peter Anvin25a99342007-09-22 17:45:45 -07002770 if (!t)
2771 return -1; /* Probably a %+ without a space */
2772
H. Peter Anvineba20a72002-04-30 20:53:55 +00002773 skip_white_(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002774 if (t->type != TOK_ID)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002775 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002776 tt = t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002777 skip_white_(tt);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002778 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002779 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002780
2781 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +00002782 j = elements(conditions);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002783 while (j - i > 1) {
2784 k = (j + i) / 2;
2785 m = nasm_stricmp(t->text, conditions[k]);
2786 if (m == 0) {
2787 i = k;
2788 j = -2;
2789 break;
2790 } else if (m < 0) {
2791 j = k;
2792 } else
2793 i = k;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002794 }
2795 if (j != -2)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002796 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002797 return i;
2798}
2799
2800/*
2801 * Expand MMacro-local things: parameter references (%0, %n, %+n,
2802 * %-n) and MMacro-local identifiers (%%foo).
2803 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002804static Token *expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002805{
H. Peter Anvin734b1882002-04-30 21:01:08 +00002806 Token *t, *tt, **tail, *thead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002807
2808 tail = &thead;
2809 thead = NULL;
2810
H. Peter Anvine2c80182005-01-15 22:15:51 +00002811 while (tline) {
2812 if (tline->type == TOK_PREPROC_ID &&
2813 (((tline->text[1] == '+' || tline->text[1] == '-')
2814 && tline->text[2]) || tline->text[1] == '%'
2815 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002816 char *text = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002817 int type = 0, cc; /* type = 0 to placate optimisers */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002818 char tmpbuf[30];
H. Peter Anvin25a99342007-09-22 17:45:45 -07002819 unsigned int n;
2820 int i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002821 MMacro *mac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002822
H. Peter Anvine2c80182005-01-15 22:15:51 +00002823 t = tline;
2824 tline = tline->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002825
H. Peter Anvine2c80182005-01-15 22:15:51 +00002826 mac = istk->mstk;
2827 while (mac && !mac->name) /* avoid mistaking %reps for macros */
2828 mac = mac->next_active;
2829 if (!mac)
2830 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
2831 else
2832 switch (t->text[1]) {
2833 /*
2834 * We have to make a substitution of one of the
2835 * forms %1, %-1, %+1, %%foo, %0.
2836 */
2837 case '0':
2838 type = TOK_NUMBER;
2839 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
2840 text = nasm_strdup(tmpbuf);
2841 break;
2842 case '%':
2843 type = TOK_ID;
Keith Kanios93f2e9a2007-04-14 00:10:59 +00002844 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu32".",
H. Peter Anvine2c80182005-01-15 22:15:51 +00002845 mac->unique);
2846 text = nasm_strcat(tmpbuf, t->text + 2);
2847 break;
2848 case '-':
2849 n = atoi(t->text + 2) - 1;
2850 if (n >= mac->nparam)
2851 tt = NULL;
2852 else {
2853 if (mac->nparam > 1)
2854 n = (n + mac->rotate) % mac->nparam;
2855 tt = mac->params[n];
2856 }
2857 cc = find_cc(tt);
2858 if (cc == -1) {
2859 error(ERR_NONFATAL,
2860 "macro parameter %d is not a condition code",
2861 n + 1);
2862 text = NULL;
2863 } else {
2864 type = TOK_ID;
2865 if (inverse_ccs[cc] == -1) {
2866 error(ERR_NONFATAL,
2867 "condition code `%s' is not invertible",
2868 conditions[cc]);
2869 text = NULL;
2870 } else
2871 text =
2872 nasm_strdup(conditions[inverse_ccs[cc]]);
2873 }
2874 break;
2875 case '+':
2876 n = atoi(t->text + 2) - 1;
2877 if (n >= mac->nparam)
2878 tt = NULL;
2879 else {
2880 if (mac->nparam > 1)
2881 n = (n + mac->rotate) % mac->nparam;
2882 tt = mac->params[n];
2883 }
2884 cc = find_cc(tt);
2885 if (cc == -1) {
2886 error(ERR_NONFATAL,
2887 "macro parameter %d is not a condition code",
2888 n + 1);
2889 text = NULL;
2890 } else {
2891 type = TOK_ID;
2892 text = nasm_strdup(conditions[cc]);
2893 }
2894 break;
2895 default:
2896 n = atoi(t->text + 1) - 1;
2897 if (n >= mac->nparam)
2898 tt = NULL;
2899 else {
2900 if (mac->nparam > 1)
2901 n = (n + mac->rotate) % mac->nparam;
2902 tt = mac->params[n];
2903 }
2904 if (tt) {
2905 for (i = 0; i < mac->paramlen[n]; i++) {
2906 *tail = new_Token(NULL, tt->type, tt->text, 0);
2907 tail = &(*tail)->next;
2908 tt = tt->next;
2909 }
2910 }
2911 text = NULL; /* we've done it here */
2912 break;
2913 }
2914 if (!text) {
2915 delete_Token(t);
2916 } else {
2917 *tail = t;
2918 tail = &t->next;
2919 t->type = type;
2920 nasm_free(t->text);
2921 t->text = text;
2922 t->mac = NULL;
2923 }
2924 continue;
2925 } else {
2926 t = *tail = tline;
2927 tline = tline->next;
2928 t->mac = NULL;
2929 tail = &t->next;
2930 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002931 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00002932 *tail = NULL;
2933 t = thead;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002934 for (; t && (tt = t->next) != NULL; t = t->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002935 switch (t->type) {
2936 case TOK_WHITESPACE:
2937 if (tt->type == TOK_WHITESPACE) {
2938 t->next = delete_Token(tt);
2939 }
2940 break;
2941 case TOK_ID:
2942 if (tt->type == TOK_ID || tt->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002943 char *tmp = nasm_strcat(t->text, tt->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002944 nasm_free(t->text);
2945 t->text = tmp;
2946 t->next = delete_Token(tt);
2947 }
2948 break;
2949 case TOK_NUMBER:
2950 if (tt->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002951 char *tmp = nasm_strcat(t->text, tt->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002952 nasm_free(t->text);
2953 t->text = tmp;
2954 t->next = delete_Token(tt);
2955 }
2956 break;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002957 default:
2958 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002959 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002960
H. Peter Anvin76690a12002-04-30 20:52:49 +00002961 return thead;
2962}
2963
2964/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002965 * Expand all single-line macro calls made in the given line.
2966 * Return the expanded version of the line. The original is deemed
2967 * to be destroyed in the process. (In reality we'll just move
2968 * Tokens from input to output a lot of the time, rather than
2969 * actually bothering to destroy and replicate.)
2970 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002971static Token *expand_smacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002972{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002973 Token *t, *tt, *mstart, **tail, *thead;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002974 SMacro *head = NULL, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002975 Token **params;
2976 int *paramsize;
H. Peter Anvin25a99342007-09-22 17:45:45 -07002977 unsigned int nparam, sparam;
2978 int brackets, rescan;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002979 Token *org_tline = tline;
2980 Context *ctx;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002981 char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002982
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002983 /*
2984 * Trick: we should avoid changing the start token pointer since it can
2985 * be contained in "next" field of other token. Because of this
2986 * we allocate a copy of first token and work with it; at the end of
2987 * routine we copy it back
2988 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002989 if (org_tline) {
2990 tline =
2991 new_Token(org_tline->next, org_tline->type, org_tline->text,
2992 0);
2993 tline->mac = org_tline->mac;
2994 nasm_free(org_tline->text);
2995 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002996 }
2997
H. Peter Anvin734b1882002-04-30 21:01:08 +00002998 again:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002999 tail = &thead;
3000 thead = NULL;
3001
H. Peter Anvine2c80182005-01-15 22:15:51 +00003002 while (tline) { /* main token loop */
3003 if ((mname = tline->text)) {
3004 /* if this token is a local macro, look in local context */
3005 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003006 ctx = get_ctx(mname, true);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003007 else
3008 ctx = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003009 if (!ctx) {
3010 head = (SMacro *) hash_findix(smacros, mname);
3011 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003012 head = ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003013 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003014 /*
3015 * We've hit an identifier. As in is_mmacro below, we first
3016 * check whether the identifier is a single-line macro at
3017 * all, then think about checking for parameters if
3018 * necessary.
3019 */
H. Peter Anvin97a23472007-09-16 17:57:25 -07003020 for (m = head; m; m = m->next)
3021 if (!mstrcmp(m->name, mname, m->casesense))
3022 break;
3023 if (m) {
3024 mstart = tline;
3025 params = NULL;
3026 paramsize = NULL;
3027 if (m->nparam == 0) {
3028 /*
3029 * Simple case: the macro is parameterless. Discard the
3030 * one token that the macro call took, and push the
3031 * expansion back on the to-do stack.
3032 */
3033 if (!m->expansion) {
3034 if (!strcmp("__FILE__", m->name)) {
3035 int32_t num = 0;
3036 src_get(&num, &(tline->text));
3037 nasm_quote(&(tline->text));
3038 tline->type = TOK_STRING;
3039 continue;
3040 }
3041 if (!strcmp("__LINE__", m->name)) {
3042 nasm_free(tline->text);
3043 make_tok_num(tline, src_get_linnum());
3044 continue;
3045 }
3046 if (!strcmp("__BITS__", m->name)) {
3047 nasm_free(tline->text);
3048 make_tok_num(tline, globalbits);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003049 continue;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003050 }
3051 tline = delete_Token(tline);
3052 continue;
3053 }
3054 } else {
3055 /*
3056 * Complicated case: at least one macro with this name
H. Peter Anvine2c80182005-01-15 22:15:51 +00003057 * exists and takes parameters. We must find the
3058 * parameters in the call, count them, find the SMacro
3059 * that corresponds to that form of the macro call, and
3060 * substitute for the parameters when we expand. What a
3061 * pain.
3062 */
3063 /*tline = tline->next;
3064 skip_white_(tline); */
3065 do {
3066 t = tline->next;
3067 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003068 t->mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003069 t->text = NULL;
3070 t = tline->next = delete_Token(t);
3071 }
3072 tline = t;
3073 } while (tok_type_(tline, TOK_WHITESPACE));
3074 if (!tok_is_(tline, "(")) {
3075 /*
3076 * This macro wasn't called with parameters: ignore
3077 * the call. (Behaviour borrowed from gnu cpp.)
3078 */
3079 tline = mstart;
3080 m = NULL;
3081 } else {
3082 int paren = 0;
3083 int white = 0;
3084 brackets = 0;
3085 nparam = 0;
3086 sparam = PARAM_DELTA;
3087 params = nasm_malloc(sparam * sizeof(Token *));
3088 params[0] = tline->next;
3089 paramsize = nasm_malloc(sparam * sizeof(int));
3090 paramsize[0] = 0;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003091 while (true) { /* parameter loop */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003092 /*
3093 * For some unusual expansions
3094 * which concatenates function call
3095 */
3096 t = tline->next;
3097 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003098 t->mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003099 t->text = NULL;
3100 t = tline->next = delete_Token(t);
3101 }
3102 tline = t;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003103
H. Peter Anvine2c80182005-01-15 22:15:51 +00003104 if (!tline) {
3105 error(ERR_NONFATAL,
3106 "macro call expects terminating `)'");
3107 break;
3108 }
3109 if (tline->type == TOK_WHITESPACE
3110 && brackets <= 0) {
3111 if (paramsize[nparam])
3112 white++;
3113 else
3114 params[nparam] = tline->next;
3115 continue; /* parameter loop */
3116 }
3117 if (tline->type == TOK_OTHER
3118 && tline->text[1] == 0) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003119 char ch = tline->text[0];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003120 if (ch == ',' && !paren && brackets <= 0) {
3121 if (++nparam >= sparam) {
3122 sparam += PARAM_DELTA;
3123 params = nasm_realloc(params,
3124 sparam *
3125 sizeof(Token
3126 *));
3127 paramsize =
3128 nasm_realloc(paramsize,
3129 sparam *
3130 sizeof(int));
3131 }
3132 params[nparam] = tline->next;
3133 paramsize[nparam] = 0;
3134 white = 0;
3135 continue; /* parameter loop */
3136 }
3137 if (ch == '{' &&
3138 (brackets > 0 || (brackets == 0 &&
3139 !paramsize[nparam])))
3140 {
3141 if (!(brackets++)) {
3142 params[nparam] = tline->next;
3143 continue; /* parameter loop */
3144 }
3145 }
3146 if (ch == '}' && brackets > 0)
3147 if (--brackets == 0) {
3148 brackets = -1;
3149 continue; /* parameter loop */
3150 }
3151 if (ch == '(' && !brackets)
3152 paren++;
3153 if (ch == ')' && brackets <= 0)
3154 if (--paren < 0)
3155 break;
3156 }
3157 if (brackets < 0) {
3158 brackets = 0;
3159 error(ERR_NONFATAL, "braces do not "
3160 "enclose all of macro parameter");
3161 }
3162 paramsize[nparam] += white + 1;
3163 white = 0;
3164 } /* parameter loop */
3165 nparam++;
3166 while (m && (m->nparam != nparam ||
3167 mstrcmp(m->name, mname,
3168 m->casesense)))
3169 m = m->next;
3170 if (!m)
3171 error(ERR_WARNING | ERR_WARN_MNP,
3172 "macro `%s' exists, "
3173 "but not taking %d parameters",
3174 mstart->text, nparam);
3175 }
3176 }
3177 if (m && m->in_progress)
3178 m = NULL;
3179 if (!m) { /* in progess or didn't find '(' or wrong nparam */
3180 /*
3181 * Design question: should we handle !tline, which
3182 * indicates missing ')' here, or expand those
3183 * macros anyway, which requires the (t) test a few
3184 * lines down?
3185 */
3186 nasm_free(params);
3187 nasm_free(paramsize);
3188 tline = mstart;
3189 } else {
3190 /*
3191 * Expand the macro: we are placed on the last token of the
3192 * call, so that we can easily split the call from the
3193 * following tokens. We also start by pushing an SMAC_END
3194 * token for the cycle removal.
3195 */
3196 t = tline;
3197 if (t) {
3198 tline = t->next;
3199 t->next = NULL;
3200 }
3201 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
3202 tt->mac = m;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003203 m->in_progress = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003204 tline = tt;
3205 for (t = m->expansion; t; t = t->next) {
3206 if (t->type >= TOK_SMAC_PARAM) {
3207 Token *pcopy = tline, **ptail = &pcopy;
3208 Token *ttt, *pt;
3209 int i;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003210
H. Peter Anvine2c80182005-01-15 22:15:51 +00003211 ttt = params[t->type - TOK_SMAC_PARAM];
3212 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3213 --i >= 0;) {
3214 pt = *ptail =
3215 new_Token(tline, ttt->type, ttt->text,
3216 0);
3217 ptail = &pt->next;
3218 ttt = ttt->next;
3219 }
3220 tline = pcopy;
3221 } else {
3222 tt = new_Token(tline, t->type, t->text, 0);
3223 tline = tt;
3224 }
3225 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003226
H. Peter Anvine2c80182005-01-15 22:15:51 +00003227 /*
3228 * Having done that, get rid of the macro call, and clean
3229 * up the parameters.
3230 */
3231 nasm_free(params);
3232 nasm_free(paramsize);
3233 free_tlist(mstart);
3234 continue; /* main token loop */
3235 }
3236 }
3237 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003238
H. Peter Anvine2c80182005-01-15 22:15:51 +00003239 if (tline->type == TOK_SMAC_END) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003240 tline->mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003241 tline = delete_Token(tline);
3242 } else {
3243 t = *tail = tline;
3244 tline = tline->next;
3245 t->mac = NULL;
3246 t->next = NULL;
3247 tail = &t->next;
3248 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003249 }
3250
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003251 /*
3252 * Now scan the entire line and look for successive TOK_IDs that resulted
Keith Kaniosb7a89542007-04-12 02:40:54 +00003253 * after expansion (they can't be produced by tokenize()). The successive
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003254 * TOK_IDs should be concatenated.
3255 * Also we look for %+ tokens and concatenate the tokens before and after
3256 * them (without white spaces in between).
3257 */
3258 t = thead;
3259 rescan = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003260 while (t) {
3261 while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
3262 t = t->next;
3263 if (!t || !t->next)
3264 break;
3265 if (t->next->type == TOK_ID ||
3266 t->next->type == TOK_PREPROC_ID ||
3267 t->next->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003268 char *p = nasm_strcat(t->text, t->next->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003269 nasm_free(t->text);
3270 t->next = delete_Token(t->next);
3271 t->text = p;
3272 rescan = 1;
3273 } else if (t->next->type == TOK_WHITESPACE && t->next->next &&
3274 t->next->next->type == TOK_PREPROC_ID &&
3275 strcmp(t->next->next->text, "%+") == 0) {
3276 /* free the next whitespace, the %+ token and next whitespace */
3277 int i;
3278 for (i = 1; i <= 3; i++) {
3279 if (!t->next
3280 || (i != 2 && t->next->type != TOK_WHITESPACE))
3281 break;
3282 t->next = delete_Token(t->next);
3283 } /* endfor */
3284 } else
3285 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003286 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003287 /* If we concatenaded something, re-scan the line for macros */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003288 if (rescan) {
3289 tline = thead;
3290 goto again;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003291 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003292
H. Peter Anvine2c80182005-01-15 22:15:51 +00003293 if (org_tline) {
3294 if (thead) {
3295 *org_tline = *thead;
3296 /* since we just gave text to org_line, don't free it */
3297 thead->text = NULL;
3298 delete_Token(thead);
3299 } else {
3300 /* the expression expanded to empty line;
3301 we can't return NULL for some reasons
3302 we just set the line to a single WHITESPACE token. */
3303 memset(org_tline, 0, sizeof(*org_tline));
3304 org_tline->text = NULL;
3305 org_tline->type = TOK_WHITESPACE;
3306 }
3307 thead = org_tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003308 }
3309
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003310 return thead;
3311}
3312
3313/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003314 * Similar to expand_smacro but used exclusively with macro identifiers
3315 * right before they are fetched in. The reason is that there can be
3316 * identifiers consisting of several subparts. We consider that if there
3317 * are more than one element forming the name, user wants a expansion,
3318 * otherwise it will be left as-is. Example:
3319 *
3320 * %define %$abc cde
3321 *
3322 * the identifier %$abc will be left as-is so that the handler for %define
3323 * will suck it and define the corresponding value. Other case:
3324 *
3325 * %define _%$abc cde
3326 *
3327 * In this case user wants name to be expanded *before* %define starts
3328 * working, so we'll expand %$abc into something (if it has a value;
3329 * otherwise it will be left as-is) then concatenate all successive
3330 * PP_IDs into one.
3331 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003332static Token *expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003333{
3334 Token *cur, *oldnext = NULL;
3335
H. Peter Anvin734b1882002-04-30 21:01:08 +00003336 if (!tline || !tline->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003337 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003338
3339 cur = tline;
3340 while (cur->next &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00003341 (cur->next->type == TOK_ID ||
3342 cur->next->type == TOK_PREPROC_ID
3343 || cur->next->type == TOK_NUMBER))
3344 cur = cur->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003345
3346 /* If identifier consists of just one token, don't expand */
3347 if (cur == tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003348 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003349
H. Peter Anvine2c80182005-01-15 22:15:51 +00003350 if (cur) {
3351 oldnext = cur->next; /* Detach the tail past identifier */
3352 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003353 }
3354
H. Peter Anvin734b1882002-04-30 21:01:08 +00003355 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003356
H. Peter Anvine2c80182005-01-15 22:15:51 +00003357 if (cur) {
3358 /* expand_smacro possibly changhed tline; re-scan for EOL */
3359 cur = tline;
3360 while (cur && cur->next)
3361 cur = cur->next;
3362 if (cur)
3363 cur->next = oldnext;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003364 }
3365
3366 return tline;
3367}
3368
3369/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003370 * Determine whether the given line constitutes a multi-line macro
3371 * call, and return the MMacro structure called if so. Doesn't have
3372 * to check for an initial label - that's taken care of in
3373 * expand_mmacro - but must check numbers of parameters. Guaranteed
3374 * to be called with tline->type == TOK_ID, so the putative macro
3375 * name is easy to find.
3376 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003377static MMacro *is_mmacro(Token * tline, Token *** params_array)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003378{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003379 MMacro *head, *m;
3380 Token **params;
3381 int nparam;
3382
H. Peter Anvin97a23472007-09-16 17:57:25 -07003383 head = (MMacro *) hash_findix(mmacros, tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003384
3385 /*
3386 * Efficiency: first we see if any macro exists with the given
3387 * name. If not, we can return NULL immediately. _Then_ we
3388 * count the parameters, and then we look further along the
3389 * list if necessary to find the proper MMacro.
3390 */
3391 for (m = head; m; m = m->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003392 if (!mstrcmp(m->name, tline->text, m->casesense))
3393 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003394 if (!m)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003395 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003396
3397 /*
3398 * OK, we have a potential macro. Count and demarcate the
3399 * parameters.
3400 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003401 count_mmac_params(tline->next, &nparam, &params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003402
3403 /*
3404 * So we know how many parameters we've got. Find the MMacro
3405 * structure that handles this number.
3406 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003407 while (m) {
3408 if (m->nparam_min <= nparam
3409 && (m->plus || nparam <= m->nparam_max)) {
3410 /*
3411 * This one is right. Just check if cycle removal
3412 * prohibits us using it before we actually celebrate...
3413 */
3414 if (m->in_progress) {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003415#if 0
H. Peter Anvine2c80182005-01-15 22:15:51 +00003416 error(ERR_NONFATAL,
3417 "self-reference in multi-line macro `%s'", m->name);
H. Peter Anvineba20a72002-04-30 20:53:55 +00003418#endif
H. Peter Anvine2c80182005-01-15 22:15:51 +00003419 nasm_free(params);
3420 return NULL;
3421 }
3422 /*
3423 * It's right, and we can use it. Add its default
3424 * parameters to the end of our list if necessary.
3425 */
3426 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
3427 params =
3428 nasm_realloc(params,
3429 ((m->nparam_min + m->ndefs +
3430 1) * sizeof(*params)));
3431 while (nparam < m->nparam_min + m->ndefs) {
3432 params[nparam] = m->defaults[nparam - m->nparam_min];
3433 nparam++;
3434 }
3435 }
3436 /*
3437 * If we've gone over the maximum parameter count (and
3438 * we're in Plus mode), ignore parameters beyond
3439 * nparam_max.
3440 */
3441 if (m->plus && nparam > m->nparam_max)
3442 nparam = m->nparam_max;
3443 /*
3444 * Then terminate the parameter list, and leave.
3445 */
3446 if (!params) { /* need this special case */
3447 params = nasm_malloc(sizeof(*params));
3448 nparam = 0;
3449 }
3450 params[nparam] = NULL;
3451 *params_array = params;
3452 return m;
3453 }
3454 /*
3455 * This one wasn't right: look for the next one with the
3456 * same name.
3457 */
3458 for (m = m->next; m; m = m->next)
3459 if (!mstrcmp(m->name, tline->text, m->casesense))
3460 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003461 }
3462
3463 /*
3464 * After all that, we didn't find one with the right number of
3465 * parameters. Issue a warning, and fail to expand the macro.
3466 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003467 error(ERR_WARNING | ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003468 "macro `%s' exists, but not taking %d parameters",
3469 tline->text, nparam);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003470 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003471 return NULL;
3472}
3473
3474/*
3475 * Expand the multi-line macro call made by the given line, if
3476 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvineba20a72002-04-30 20:53:55 +00003477 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003478 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003479static int expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003480{
3481 Token *startline = tline;
3482 Token *label = NULL;
3483 int dont_prepend = 0;
3484 Token **params, *t, *tt;
3485 MMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003486 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003487 int i, nparam, *paramlen;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003488
3489 t = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003490 skip_white_(t);
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00003491/* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
3492 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003493 return 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003494 m = is_mmacro(t, &params);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003495 if (!m) {
3496 Token *last;
3497 /*
3498 * We have an id which isn't a macro call. We'll assume
3499 * it might be a label; we'll also check to see if a
3500 * colon follows it. Then, if there's another id after
3501 * that lot, we'll check it again for macro-hood.
3502 */
3503 label = last = t;
3504 t = t->next;
3505 if (tok_type_(t, TOK_WHITESPACE))
3506 last = t, t = t->next;
3507 if (tok_is_(t, ":")) {
3508 dont_prepend = 1;
3509 last = t, t = t->next;
3510 if (tok_type_(t, TOK_WHITESPACE))
3511 last = t, t = t->next;
3512 }
3513 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
3514 return 0;
3515 last->next = NULL;
3516 tline = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003517 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003518
3519 /*
3520 * Fix up the parameters: this involves stripping leading and
3521 * trailing whitespace, then stripping braces if they are
3522 * present.
3523 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003524 for (nparam = 0; params[nparam]; nparam++) ;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003525 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003526
H. Peter Anvine2c80182005-01-15 22:15:51 +00003527 for (i = 0; params[i]; i++) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003528 int brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003529 int comma = (!m->plus || i < nparam - 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003530
H. Peter Anvine2c80182005-01-15 22:15:51 +00003531 t = params[i];
3532 skip_white_(t);
3533 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003534 t = t->next, brace = true, comma = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003535 params[i] = t;
3536 paramlen[i] = 0;
3537 while (t) {
3538 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
3539 break; /* ... because we have hit a comma */
3540 if (comma && t->type == TOK_WHITESPACE
3541 && tok_is_(t->next, ","))
3542 break; /* ... or a space then a comma */
3543 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
3544 break; /* ... or a brace */
3545 t = t->next;
3546 paramlen[i]++;
3547 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003548 }
3549
3550 /*
3551 * OK, we have a MMacro structure together with a set of
3552 * parameters. We must now go through the expansion and push
H. Peter Anvin76690a12002-04-30 20:52:49 +00003553 * copies of each Line on to istk->expansion. Substitution of
3554 * parameter tokens and macro-local tokens doesn't get done
3555 * until the single-line macro substitution process; this is
3556 * because delaying them allows us to change the semantics
3557 * later through %rotate.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003558 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00003559 * First, push an end marker on to istk->expansion, mark this
3560 * macro as in progress, and set up its invocation-specific
3561 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003562 */
3563 ll = nasm_malloc(sizeof(Line));
3564 ll->next = istk->expansion;
3565 ll->finishes = m;
3566 ll->first = NULL;
3567 istk->expansion = ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003568
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003569 m->in_progress = true;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003570 m->params = params;
3571 m->iline = tline;
3572 m->nparam = nparam;
3573 m->rotate = 0;
3574 m->paramlen = paramlen;
3575 m->unique = unique++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003576 m->lineno = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003577
3578 m->next_active = istk->mstk;
3579 istk->mstk = m;
3580
H. Peter Anvine2c80182005-01-15 22:15:51 +00003581 for (l = m->expansion; l; l = l->next) {
3582 Token **tail;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003583
H. Peter Anvine2c80182005-01-15 22:15:51 +00003584 ll = nasm_malloc(sizeof(Line));
3585 ll->finishes = NULL;
3586 ll->next = istk->expansion;
3587 istk->expansion = ll;
3588 tail = &ll->first;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003589
H. Peter Anvine2c80182005-01-15 22:15:51 +00003590 for (t = l->first; t; t = t->next) {
3591 Token *x = t;
3592 if (t->type == TOK_PREPROC_ID &&
3593 t->text[1] == '0' && t->text[2] == '0') {
3594 dont_prepend = -1;
3595 x = label;
3596 if (!x)
3597 continue;
3598 }
3599 tt = *tail = new_Token(NULL, x->type, x->text, 0);
3600 tail = &tt->next;
3601 }
3602 *tail = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003603 }
3604
3605 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00003606 * If we had a label, push it on as the first line of
3607 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003608 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003609 if (label) {
3610 if (dont_prepend < 0)
3611 free_tlist(startline);
3612 else {
3613 ll = nasm_malloc(sizeof(Line));
3614 ll->finishes = NULL;
3615 ll->next = istk->expansion;
3616 istk->expansion = ll;
3617 ll->first = startline;
3618 if (!dont_prepend) {
3619 while (label->next)
3620 label = label->next;
3621 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
3622 }
3623 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003624 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003625
H. Peter Anvin734b1882002-04-30 21:01:08 +00003626 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003627
H. Peter Anvineba20a72002-04-30 20:53:55 +00003628 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003629}
3630
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003631/*
3632 * Since preprocessor always operate only on the line that didn't
3633 * arrived yet, we should always use ERR_OFFBY1. Also since user
3634 * won't want to see same error twice (preprocessing is done once
3635 * per pass) we will want to show errors only during pass one.
3636 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003637static void error(int severity, const char *fmt, ...)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003638{
3639 va_list arg;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003640 char buff[1024];
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003641
3642 /* If we're in a dead branch of IF or something like it, ignore the error */
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00003643 if (istk && istk->conds && !emitting(istk->conds->state))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003644 return;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003645
H. Peter Anvin734b1882002-04-30 21:01:08 +00003646 va_start(arg, fmt);
Ed Beroset19f927a2004-12-15 17:07:03 +00003647 vsnprintf(buff, sizeof(buff), fmt, arg);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003648 va_end(arg);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003649
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00003650 if (istk && istk->mstk && istk->mstk->name)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003651 _error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
3652 istk->mstk->lineno, buff);
3653 else
3654 _error(severity | ERR_PASS1, "%s", buff);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003655}
3656
H. Peter Anvin734b1882002-04-30 21:01:08 +00003657static void
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003658pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003659 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003660{
H. Peter Anvin99941bf2002-05-14 17:44:03 +00003661 _error = errfunc;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003662 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003663 istk = nasm_malloc(sizeof(Include));
3664 istk->next = NULL;
3665 istk->conds = NULL;
3666 istk->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003667 istk->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003668 istk->fp = fopen(file, "r");
H. Peter Anvineba20a72002-04-30 20:53:55 +00003669 istk->fname = NULL;
3670 src_set_fname(nasm_strdup(file));
3671 src_set_linnum(0);
3672 istk->lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003673 if (!istk->fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003674 error(ERR_FATAL | ERR_NOFILE, "unable to open input file `%s'",
3675 file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003676 defining = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003677 init_macros();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003678 unique = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003679 if (tasm_compatible_mode) {
3680 stdmacpos = stdmac;
3681 } else {
3682 stdmacpos = &stdmac[TASM_MACRO_COUNT];
3683 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003684 any_extrastdmac = (extrastdmac != NULL);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003685 list = listgen;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003686 evaluate = eval;
3687 pass = apass;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003688}
3689
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003690static char *pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003691{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003692 char *line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003693 Token *tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003694
H. Peter Anvine2c80182005-01-15 22:15:51 +00003695 while (1) {
3696 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00003697 * Fetch a tokenized line, either from the macro-expansion
H. Peter Anvine2c80182005-01-15 22:15:51 +00003698 * buffer or from the input file.
3699 */
3700 tline = NULL;
3701 while (istk->expansion && istk->expansion->finishes) {
3702 Line *l = istk->expansion;
3703 if (!l->finishes->name && l->finishes->in_progress > 1) {
3704 Line *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003705
H. Peter Anvine2c80182005-01-15 22:15:51 +00003706 /*
3707 * This is a macro-end marker for a macro with no
3708 * name, which means it's not really a macro at all
3709 * but a %rep block, and the `in_progress' field is
3710 * more than 1, meaning that we still need to
3711 * repeat. (1 means the natural last repetition; 0
3712 * means termination by %exitrep.) We have
3713 * therefore expanded up to the %endrep, and must
3714 * push the whole block on to the expansion buffer
3715 * again. We don't bother to remove the macro-end
3716 * marker: we'd only have to generate another one
3717 * if we did.
3718 */
3719 l->finishes->in_progress--;
3720 for (l = l->finishes->expansion; l; l = l->next) {
3721 Token *t, *tt, **tail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003722
H. Peter Anvine2c80182005-01-15 22:15:51 +00003723 ll = nasm_malloc(sizeof(Line));
3724 ll->next = istk->expansion;
3725 ll->finishes = NULL;
3726 ll->first = NULL;
3727 tail = &ll->first;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003728
H. Peter Anvine2c80182005-01-15 22:15:51 +00003729 for (t = l->first; t; t = t->next) {
3730 if (t->text || t->type == TOK_WHITESPACE) {
3731 tt = *tail =
3732 new_Token(NULL, t->type, t->text, 0);
3733 tail = &tt->next;
3734 }
3735 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003736
H. Peter Anvine2c80182005-01-15 22:15:51 +00003737 istk->expansion = ll;
3738 }
3739 } else {
3740 /*
3741 * Check whether a `%rep' was started and not ended
3742 * within this macro expansion. This can happen and
3743 * should be detected. It's a fatal error because
3744 * I'm too confused to work out how to recover
3745 * sensibly from it.
3746 */
3747 if (defining) {
3748 if (defining->name)
3749 error(ERR_PANIC,
3750 "defining with name in expansion");
3751 else if (istk->mstk->name)
3752 error(ERR_FATAL,
3753 "`%%rep' without `%%endrep' within"
3754 " expansion of macro `%s'",
3755 istk->mstk->name);
3756 }
H. Peter Anvin87bc6192002-04-30 20:53:16 +00003757
H. Peter Anvine2c80182005-01-15 22:15:51 +00003758 /*
3759 * FIXME: investigate the relationship at this point between
3760 * istk->mstk and l->finishes
3761 */
3762 {
3763 MMacro *m = istk->mstk;
3764 istk->mstk = m->next_active;
3765 if (m->name) {
3766 /*
3767 * This was a real macro call, not a %rep, and
3768 * therefore the parameter information needs to
3769 * be freed.
3770 */
3771 nasm_free(m->params);
3772 free_tlist(m->iline);
3773 nasm_free(m->paramlen);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003774 l->finishes->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003775 } else
3776 free_mmacro(m);
3777 }
3778 istk->expansion = l->next;
3779 nasm_free(l);
3780 list->downlevel(LIST_MACRO);
3781 }
3782 }
3783 while (1) { /* until we get a line we can use */
H. Peter Anvineba20a72002-04-30 20:53:55 +00003784
H. Peter Anvine2c80182005-01-15 22:15:51 +00003785 if (istk->expansion) { /* from a macro expansion */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003786 char *p;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003787 Line *l = istk->expansion;
3788 if (istk->mstk)
3789 istk->mstk->lineno++;
3790 tline = l->first;
3791 istk->expansion = l->next;
3792 nasm_free(l);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003793 p = detoken(tline, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003794 list->line(LIST_MACRO, p);
3795 nasm_free(p);
3796 break;
3797 }
3798 line = read_line();
3799 if (line) { /* from the current input file */
3800 line = prepreproc(line);
Keith Kaniosb7a89542007-04-12 02:40:54 +00003801 tline = tokenize(line);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003802 nasm_free(line);
3803 break;
3804 }
3805 /*
3806 * The current file has ended; work down the istk
3807 */
3808 {
3809 Include *i = istk;
3810 fclose(i->fp);
3811 if (i->conds)
3812 error(ERR_FATAL,
3813 "expected `%%endif' before end of file");
3814 /* only set line and file name if there's a next node */
3815 if (i->next) {
3816 src_set_linnum(i->lineno);
3817 nasm_free(src_set_fname(i->fname));
3818 }
3819 istk = i->next;
3820 list->downlevel(LIST_INCLUDE);
3821 nasm_free(i);
3822 if (!istk)
3823 return NULL;
3824 }
3825 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003826
H. Peter Anvine2c80182005-01-15 22:15:51 +00003827 /*
3828 * We must expand MMacro parameters and MMacro-local labels
3829 * _before_ we plunge into directive processing, to cope
3830 * with things like `%define something %1' such as STRUC
3831 * uses. Unless we're _defining_ a MMacro, in which case
3832 * those tokens should be left alone to go into the
3833 * definition; and unless we're in a non-emitting
3834 * condition, in which case we don't want to meddle with
3835 * anything.
3836 */
3837 if (!defining && !(istk->conds && !emitting(istk->conds->state)))
3838 tline = expand_mmac_params(tline);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003839
H. Peter Anvine2c80182005-01-15 22:15:51 +00003840 /*
3841 * Check the line to see if it's a preprocessor directive.
3842 */
3843 if (do_directive(tline) == DIRECTIVE_FOUND) {
3844 continue;
3845 } else if (defining) {
3846 /*
3847 * We're defining a multi-line macro. We emit nothing
3848 * at all, and just
Keith Kaniosb7a89542007-04-12 02:40:54 +00003849 * shove the tokenized line on to the macro definition.
H. Peter Anvine2c80182005-01-15 22:15:51 +00003850 */
3851 Line *l = nasm_malloc(sizeof(Line));
3852 l->next = defining->expansion;
3853 l->first = tline;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003854 l->finishes = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003855 defining->expansion = l;
3856 continue;
3857 } else if (istk->conds && !emitting(istk->conds->state)) {
3858 /*
3859 * We're in a non-emitting branch of a condition block.
3860 * Emit nothing at all, not even a blank line: when we
3861 * emerge from the condition we'll give a line-number
3862 * directive so we keep our place correctly.
3863 */
3864 free_tlist(tline);
3865 continue;
3866 } else if (istk->mstk && !istk->mstk->in_progress) {
3867 /*
3868 * We're in a %rep block which has been terminated, so
3869 * we're walking through to the %endrep without
3870 * emitting anything. Emit nothing at all, not even a
3871 * blank line: when we emerge from the %rep block we'll
3872 * give a line-number directive so we keep our place
3873 * correctly.
3874 */
3875 free_tlist(tline);
3876 continue;
3877 } else {
3878 tline = expand_smacro(tline);
3879 if (!expand_mmacro(tline)) {
3880 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00003881 * De-tokenize the line again, and emit it.
H. Peter Anvine2c80182005-01-15 22:15:51 +00003882 */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003883 line = detoken(tline, true);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003884 free_tlist(tline);
3885 break;
3886 } else {
3887 continue; /* expand_mmacro calls free_tlist */
3888 }
3889 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003890 }
3891
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003892 return line;
3893}
3894
H. Peter Anvine2c80182005-01-15 22:15:51 +00003895static void pp_cleanup(int pass)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003896{
H. Peter Anvine2c80182005-01-15 22:15:51 +00003897 if (defining) {
3898 error(ERR_NONFATAL, "end of file while still defining macro `%s'",
3899 defining->name);
3900 free_mmacro(defining);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003901 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003902 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003903 ctx_pop();
H. Peter Anvin97a23472007-09-16 17:57:25 -07003904 free_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00003905 while (istk) {
3906 Include *i = istk;
3907 istk = istk->next;
3908 fclose(i->fp);
3909 nasm_free(i->fname);
3910 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003911 }
3912 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003913 ctx_pop();
3914 if (pass == 0) {
3915 free_llist(predef);
3916 delete_Blocks();
3917 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003918}
3919
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003920void pp_include_path(char *path)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003921{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003922 IncPath *i;
H. Peter Anvin37a321f2007-09-24 13:41:58 -07003923
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003924 i = nasm_malloc(sizeof(IncPath));
H. Peter Anvin37a321f2007-09-24 13:41:58 -07003925 i->path = path ? nasm_strdup(path) : NULL;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003926 i->next = NULL;
3927
H. Peter Anvine2c80182005-01-15 22:15:51 +00003928 if (ipath != NULL) {
3929 IncPath *j = ipath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003930 while (j->next != NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003931 j = j->next;
3932 j->next = i;
3933 } else {
3934 ipath = i;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003935 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003936}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003937
3938/*
3939 * added by alexfru:
3940 *
3941 * This function is used to "export" the include paths, e.g.
3942 * the paths specified in the '-I' command switch.
3943 * The need for such exporting is due to the 'incbin' directive,
3944 * which includes raw binary files (unlike '%include', which
3945 * includes text source files). It would be real nice to be
3946 * able to specify paths to search for incbin'ned files also.
3947 * So, this is a simple workaround.
3948 *
3949 * The function use is simple:
3950 *
3951 * The 1st call (with NULL argument) returns a pointer to the 1st path
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003952 * (char** type) or NULL if none include paths available.
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003953 *
3954 * All subsequent calls take as argument the value returned by this
3955 * function last. The return value is either the next path
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003956 * (char** type) or NULL if the end of the paths list is reached.
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003957 *
3958 * It is maybe not the best way to do things, but I didn't want
3959 * to export too much, just one or two functions and no types or
3960 * variables exported.
3961 *
3962 * Can't say I like the current situation with e.g. this path list either,
3963 * it seems to be never deallocated after creation...
3964 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003965char **pp_get_include_path_ptr(char **pPrevPath)
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003966{
3967/* This macro returns offset of a member of a structure */
3968#define GetMemberOffset(StructType,MemberName)\
3969 ((size_t)&((StructType*)0)->MemberName)
3970 IncPath *i;
3971
H. Peter Anvine2c80182005-01-15 22:15:51 +00003972 if (pPrevPath == NULL) {
3973 if (ipath != NULL)
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003974 return &ipath->path;
3975 else
3976 return NULL;
3977 }
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003978 i = (IncPath *) ((char *)pPrevPath - GetMemberOffset(IncPath, path));
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003979 i = i->next;
3980 if (i != NULL)
3981 return &i->path;
3982 else
3983 return NULL;
3984#undef GetMemberOffset
3985}
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003986
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003987void pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003988{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003989 Token *inc, *space, *name;
3990 Line *l;
3991
H. Peter Anvin734b1882002-04-30 21:01:08 +00003992 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
3993 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
3994 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003995
3996 l = nasm_malloc(sizeof(Line));
3997 l->next = predef;
3998 l->first = inc;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003999 l->finishes = false;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004000 predef = l;
4001}
4002
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004003void pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004004{
4005 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004006 Line *l;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004007 char *equals;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004008
4009 equals = strchr(definition, '=');
H. Peter Anvin734b1882002-04-30 21:01:08 +00004010 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4011 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004012 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004013 *equals = ' ';
Keith Kaniosb7a89542007-04-12 02:40:54 +00004014 space->next = tokenize(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004015 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004016 *equals = '=';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004017
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004018 l = nasm_malloc(sizeof(Line));
4019 l->next = predef;
4020 l->first = def;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004021 l->finishes = false;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004022 predef = l;
4023}
4024
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004025void pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00004026{
4027 Token *def, *space;
4028 Line *l;
4029
H. Peter Anvin734b1882002-04-30 21:01:08 +00004030 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4031 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Keith Kaniosb7a89542007-04-12 02:40:54 +00004032 space->next = tokenize(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00004033
4034 l = nasm_malloc(sizeof(Line));
4035 l->next = predef;
4036 l->first = def;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004037 l->finishes = false;
H. Peter Anvin620515a2002-04-30 20:57:38 +00004038 predef = l;
4039}
4040
Keith Kaniosb7a89542007-04-12 02:40:54 +00004041/*
4042 * Added by Keith Kanios:
4043 *
4044 * This function is used to assist with "runtime" preprocessor
4045 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4046 *
4047 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4048 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4049 */
4050
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004051void pp_runtime(char *definition)
Keith Kaniosb7a89542007-04-12 02:40:54 +00004052{
4053 Token *def;
4054
4055 def = tokenize(definition);
4056 if(do_directive(def) == NO_DIRECTIVE_FOUND)
4057 free_tlist(def);
4058
4059}
4060
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004061void pp_extra_stdmac(const char **macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004062{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004063 extrastdmac = macros;
4064}
4065
Keith Kaniosb7a89542007-04-12 02:40:54 +00004066static void make_tok_num(Token * tok, int32_t val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004067{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004068 char numbuf[20];
Keith Kanios93f2e9a2007-04-14 00:10:59 +00004069 snprintf(numbuf, sizeof(numbuf), "%"PRId32"", val);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004070 tok->text = nasm_strdup(numbuf);
4071 tok->type = TOK_NUMBER;
4072}
4073
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004074Preproc nasmpp = {
4075 pp_reset,
4076 pp_getline,
4077 pp_cleanup
4078};