blob: 1338cafc42d7a536ae7c027df2e8127cf2c9cbce [file] [log] [blame]
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001/* preproc.c macro preprocessor for the Netwide Assembler
2 *
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
7 *
8 * initial version 18/iii/97 by Simon Tatham
9 */
10
H. Peter Anvin4836e332002-04-30 20:56:43 +000011/* Typical flow of text through preproc
12 *
Keith Kaniosb7a89542007-04-12 02:40:54 +000013 * pp_getline gets tokenized lines, either
H. Peter Anvin4836e332002-04-30 20:56:43 +000014 *
15 * from a macro expansion
16 *
17 * or
18 * {
19 * read_line gets raw text from stdmacpos, or predef, or current input file
Keith Kaniosb7a89542007-04-12 02:40:54 +000020 * tokenize converts to tokens
H. Peter Anvin4836e332002-04-30 20:56:43 +000021 * }
22 *
23 * expand_mmac_params is used to expand %1 etc., unless a macro is being
24 * defined or a false conditional is being processed
25 * (%0, %1, %+1, %-1, %%foo
26 *
27 * do_directive checks for directives
28 *
29 * expand_smacro is used to expand single line macros
30 *
31 * expand_mmacro is used to expand multi-line macros
32 *
33 * detoken is used to convert the line back to text
34 */
H. Peter Anvineba20a72002-04-30 20:53:55 +000035
H. Peter Anvinfe501952007-10-02 21:53:51 -070036#include "compiler.h"
37
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000038#include <stdio.h>
H. Peter Anvinaf535c12002-04-30 20:59:21 +000039#include <stdarg.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000040#include <stdlib.h>
41#include <stddef.h>
42#include <string.h>
43#include <ctype.h>
H. Peter Anvin76690a12002-04-30 20:52:49 +000044#include <limits.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000045#include <inttypes.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000046
47#include "nasm.h"
48#include "nasmlib.h"
H. Peter Anvin4169a472007-09-12 01:29:43 +000049#include "preproc.h"
H. Peter Anvin97a23472007-09-16 17:57:25 -070050#include "hashtbl.h"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000051
52typedef struct SMacro SMacro;
53typedef struct MMacro MMacro;
54typedef struct Context Context;
55typedef struct Token Token;
H. Peter Anvince616072002-04-30 21:02:23 +000056typedef struct Blocks Blocks;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000057typedef struct Line Line;
58typedef struct Include Include;
59typedef struct Cond Cond;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000060typedef struct IncPath IncPath;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000061
62/*
H. Peter Anvin97a23472007-09-16 17:57:25 -070063 * Note on the storage of both SMacro and MMacros: the hash table
64 * indexes them case-insensitively, and we then have to go through a
65 * linked list of potential case aliases (and, for MMacros, parameter
66 * ranges); this is to preserve the matching semantics of the earlier
67 * code. If the number of case aliases for a specific macro is a
68 * performance issue, you may want to reconsider your coding style.
69 */
70
71/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000072 * Store the definition of a single-line macro.
73 */
H. Peter Anvine2c80182005-01-15 22:15:51 +000074struct SMacro {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000075 SMacro *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +000076 char *name;
H. Peter Anvin70055962007-10-11 00:05:31 -070077 bool casesense;
H. Peter Anvin16ed4382007-10-11 10:06:19 -070078 bool in_progress;
H. Peter Anvin70055962007-10-11 00:05:31 -070079 unsigned int nparam;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000080 Token *expansion;
81};
82
83/*
H. Peter Anvin76690a12002-04-30 20:52:49 +000084 * Store the definition of a multi-line macro. This is also used to
85 * store the interiors of `%rep...%endrep' blocks, which are
86 * effectively self-re-invoking multi-line macros which simply
87 * don't have a name or bother to appear in the hash tables. %rep
88 * blocks are signified by having a NULL `name' field.
89 *
90 * In a MMacro describing a `%rep' block, the `in_progress' field
91 * isn't merely boolean, but gives the number of repeats left to
92 * run.
93 *
94 * The `next' field is used for storing MMacros in hash tables; the
95 * `next_active' field is for stacking them on istk entries.
96 *
97 * When a MMacro is being expanded, `params', `iline', `nparam',
98 * `paramlen', `rotate' and `unique' are local to the invocation.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000099 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000100struct MMacro {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000101 MMacro *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000102 char *name;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -0700103 int nparam_min, nparam_max;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700104 bool casesense;
105 bool plus; /* is the last parameter greedy? */
106 bool nolist; /* is this macro listing-inhibited? */
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700107 int64_t in_progress;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000108 Token *dlist; /* All defaults as one list */
109 Token **defaults; /* Parameter default pointers */
110 int ndefs; /* number of default parameters */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000111 Line *expansion;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000112
113 MMacro *next_active;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000114 MMacro *rep_nest; /* used for nesting %rep */
115 Token **params; /* actual parameters */
116 Token *iline; /* invocation line */
H. Peter Anvin25a99342007-09-22 17:45:45 -0700117 unsigned int nparam, rotate;
118 int *paramlen;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700119 uint64_t unique;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000120 int lineno; /* Current line number on expansion */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000121};
122
123/*
124 * The context stack is composed of a linked list of these.
125 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000126struct Context {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000127 Context *next;
128 SMacro *localmac;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000129 char *name;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000130 uint32_t number;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000131};
132
133/*
134 * This is the internal form which we break input lines up into.
135 * Typically stored in linked lists.
136 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000137 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
138 * necessarily used as-is, but is intended to denote the number of
139 * the substituted parameter. So in the definition
140 *
141 * %define a(x,y) ( (x) & ~(y) )
142 *
143 * the token representing `x' will have its type changed to
144 * TOK_SMAC_PARAM, but the one representing `y' will be
145 * TOK_SMAC_PARAM+1.
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000146 *
147 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
148 * which doesn't need quotes around it. Used in the pre-include
149 * mechanism as an alternative to trying to find a sensible type of
150 * quote to use on the filename we were passed.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000151 */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000152enum pp_token_type {
153 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID,
154 TOK_PREPROC_ID, TOK_STRING,
155 TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM,
156 TOK_INTERNAL_STRING
157};
158
H. Peter Anvine2c80182005-01-15 22:15:51 +0000159struct Token {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000160 Token *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000161 char *text;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000162 SMacro *mac; /* associated macro for TOK_SMAC_END */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000163 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000164};
165
166/*
167 * Multi-line macro definitions are stored as a linked list of
168 * these, which is essentially a container to allow several linked
169 * lists of Tokens.
170 *
171 * Note that in this module, linked lists are treated as stacks
172 * wherever possible. For this reason, Lines are _pushed_ on to the
173 * `expansion' field in MMacro structures, so that the linked list,
174 * if walked, would give the macro lines in reverse order; this
175 * means that we can walk the list when expanding a macro, and thus
176 * push the lines on to the `expansion' field in _istk_ in reverse
177 * order (so that when popped back off they are in the right
178 * order). It may seem cockeyed, and it relies on my design having
179 * an even number of steps in, but it works...
180 *
181 * Some of these structures, rather than being actual lines, are
182 * markers delimiting the end of the expansion of a given macro.
H. Peter Anvin76690a12002-04-30 20:52:49 +0000183 * This is for use in the cycle-tracking and %rep-handling code.
184 * Such structures have `finishes' non-NULL, and `first' NULL. All
185 * others have `finishes' NULL, but `first' may still be NULL if
186 * the line is blank.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000187 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000188struct Line {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000189 Line *next;
190 MMacro *finishes;
191 Token *first;
192};
193
194/*
195 * To handle an arbitrary level of file inclusion, we maintain a
196 * stack (ie linked list) of these things.
197 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000198struct Include {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000199 Include *next;
200 FILE *fp;
201 Cond *conds;
202 Line *expansion;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000203 char *fname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000204 int lineno, lineinc;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000205 MMacro *mstk; /* stack of active macros/reps */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000206};
207
208/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000209 * Include search path. This is simply a list of strings which get
210 * prepended, in turn, to the name of an include file, in an
211 * attempt to find the file if it's not in the current directory.
212 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000213struct IncPath {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000214 IncPath *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000215 char *path;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000216};
217
218/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000219 * Conditional assembly: we maintain a separate stack of these for
220 * each level of file inclusion. (The only reason we keep the
221 * stacks separate is to ensure that a stray `%endif' in a file
222 * included from within the true branch of a `%if' won't terminate
223 * it and cause confusion: instead, rightly, it'll cause an error.)
224 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000225struct Cond {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000226 Cond *next;
227 int state;
228};
H. Peter Anvine2c80182005-01-15 22:15:51 +0000229enum {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000230 /*
231 * These states are for use just after %if or %elif: IF_TRUE
232 * means the condition has evaluated to truth so we are
233 * currently emitting, whereas IF_FALSE means we are not
234 * currently emitting but will start doing so if a %else comes
235 * up. In these states, all directives are admissible: %elif,
236 * %else and %endif. (And of course %if.)
237 */
238 COND_IF_TRUE, COND_IF_FALSE,
239 /*
240 * These states come up after a %else: ELSE_TRUE means we're
241 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
242 * any %elif or %else will cause an error.
243 */
244 COND_ELSE_TRUE, COND_ELSE_FALSE,
245 /*
246 * This state means that we're not emitting now, and also that
247 * nothing until %endif will be emitted at all. It's for use in
248 * two circumstances: (i) when we've had our moment of emission
249 * and have now started seeing %elifs, and (ii) when the
250 * condition construct in question is contained within a
251 * non-emitting branch of a larger condition construct.
252 */
253 COND_NEVER
254};
255#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
256
Ed Beroset3ab3f412002-06-11 03:31:49 +0000257/*
258 * These defines are used as the possible return values for do_directive
259 */
260#define NO_DIRECTIVE_FOUND 0
261#define DIRECTIVE_FOUND 1
262
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000263/*
264 * Condition codes. Note that we use c_ prefix not C_ because C_ is
265 * used in nasm.h for the "real" condition codes. At _this_ level,
266 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
267 * ones, so we need a different enum...
268 */
H. Peter Anvin476d2862007-10-02 22:04:15 -0700269static const char * const conditions[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000270 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
271 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
H. Peter Anvince9be342007-09-12 00:22:29 +0000272 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000273};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700274enum pp_conds {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000275 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
276 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 -0700277 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
278 c_none = -1
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000279};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700280static const enum pp_conds inverse_ccs[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000281 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
282 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 +0000283 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000284};
285
H. Peter Anvin76690a12002-04-30 20:52:49 +0000286/*
287 * Directive names.
288 */
H. Peter Anvin65747262002-05-07 00:10:05 +0000289/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
H. Peter Anvin9bf0aa72007-09-12 02:12:07 +0000290static int is_condition(enum preproc_token arg)
H. Peter Anvin65747262002-05-07 00:10:05 +0000291{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000292 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
H. Peter Anvin65747262002-05-07 00:10:05 +0000293}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000294
295/* For TASM compatibility we need to be able to recognise TASM compatible
296 * conditional compilation directives. Using the NASM pre-processor does
297 * not work, so we look for them specifically from the following list and
298 * then jam in the equivalent NASM directive into the input stream.
299 */
300
301#ifndef MAX
302# define MAX(a,b) ( ((a) > (b)) ? (a) : (b))
303#endif
304
H. Peter Anvine2c80182005-01-15 22:15:51 +0000305enum {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000306 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
307 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
308};
309
H. Peter Anvin476d2862007-10-02 22:04:15 -0700310static const char * const tasm_directives[] = {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000311 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
312 "ifndef", "include", "local"
313};
314
315static int StackSize = 4;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000316static char *StackPointer = "ebp";
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000317static int ArgOffset = 8;
318static int LocalOffset = 4;
319
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000320static Context *cstk;
321static Include *istk;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000322static IncPath *ipath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000323
H. Peter Anvine2c80182005-01-15 22:15:51 +0000324static efunc _error; /* Pointer to client-provided error reporting function */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000325static evalfunc evaluate;
326
H. Peter Anvine2c80182005-01-15 22:15:51 +0000327static int pass; /* HACK: pass 0 = generate dependencies only */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000328
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700329static uint64_t unique; /* unique identifier numbers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000330
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000331static Line *predef = NULL;
332
333static ListGen *list;
334
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000335/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000336 * The current set of multi-line macros we have defined.
337 */
H. Peter Anvin97a23472007-09-16 17:57:25 -0700338static struct hash_table *mmacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000339
340/*
341 * The current set of single-line macros we have defined.
342 */
H. Peter Anvin97a23472007-09-16 17:57:25 -0700343static struct hash_table *smacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000344
345/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000346 * The multi-line macro we are currently defining, or the %rep
347 * block we are currently reading, if any.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000348 */
349static MMacro *defining;
350
351/*
352 * The number of macro parameters to allocate space for at a time.
353 */
354#define PARAM_DELTA 16
355
356/*
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000357 * The standard macro set: defined as `static char *stdmac[]'. Also
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000358 * gives our position in the macro set, when we're processing it.
359 */
360#include "macros.c"
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000361static const char **stdmacpos;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000362
363/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000364 * The extra standard macros that come from the object format, if
365 * any.
366 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000367static const char **extrastdmac = NULL;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700368bool any_extrastdmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000369
370/*
H. Peter Anvin734b1882002-04-30 21:01:08 +0000371 * Tokens are allocated in blocks to improve speed
372 */
373#define TOKEN_BLOCKSIZE 4096
374static Token *freeTokens = NULL;
H. Peter Anvince616072002-04-30 21:02:23 +0000375struct Blocks {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000376 Blocks *next;
377 void *chunk;
H. Peter Anvince616072002-04-30 21:02:23 +0000378};
379
380static Blocks blocks = { NULL, NULL };
H. Peter Anvin734b1882002-04-30 21:01:08 +0000381
382/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000383 * Forward declarations.
384 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000385static Token *expand_mmac_params(Token * tline);
386static Token *expand_smacro(Token * tline);
387static Token *expand_id(Token * tline);
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700388static Context *get_ctx(char *name, bool all_contexts);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000389static void make_tok_num(Token * tok, int32_t val);
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000390static void error(int severity, const char *fmt, ...);
H. Peter Anvince616072002-04-30 21:02:23 +0000391static void *new_Block(size_t size);
392static void delete_Blocks(void);
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000393static Token *new_Token(Token * next, enum pp_token_type type, char *text, int txtlen);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000394static Token *delete_Token(Token * t);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000395
396/*
397 * Macros for safe checking of token pointers, avoid *(NULL)
398 */
399#define tok_type_(x,t) ((x) && (x)->type == (t))
400#define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
401#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
402#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
H. Peter Anvin76690a12002-04-30 20:52:49 +0000403
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000404/* Handle TASM specific directives, which do not contain a % in
405 * front of them. We do it here because I could not find any other
406 * place to do it for the moment, and it is a hack (ideally it would
407 * be nice to be able to use the NASM pre-processor to do it).
408 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000409static char *check_tasm_directive(char *line)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000410{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000411 int32_t i, j, k, m, len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000412 char *p = line, *oldline, oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000413
414 /* Skip whitespace */
415 while (isspace(*p) && *p != 0)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000416 p++;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000417
418 /* Binary search for the directive name */
419 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +0000420 j = elements(tasm_directives);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000421 len = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000422 while (!isspace(p[len]) && p[len] != 0)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000423 len++;
424 if (len) {
425 oldchar = p[len];
426 p[len] = 0;
427 while (j - i > 1) {
428 k = (j + i) / 2;
429 m = nasm_stricmp(p, tasm_directives[k]);
430 if (m == 0) {
431 /* We have found a directive, so jam a % in front of it
432 * so that NASM will then recognise it as one if it's own.
433 */
434 p[len] = oldchar;
435 len = strlen(p);
436 oldline = line;
437 line = nasm_malloc(len + 2);
438 line[0] = '%';
439 if (k == TM_IFDIFI) {
440 /* NASM does not recognise IFDIFI, so we convert it to
441 * %ifdef BOGUS. This is not used in NASM comaptible
442 * code, but does need to parse for the TASM macro
443 * package.
444 */
445 strcpy(line + 1, "ifdef BOGUS");
446 } else {
447 memcpy(line + 1, p, len + 1);
448 }
449 nasm_free(oldline);
450 return line;
451 } else if (m < 0) {
452 j = k;
453 } else
454 i = k;
455 }
456 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000457 }
458 return line;
459}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000460
H. Peter Anvin76690a12002-04-30 20:52:49 +0000461/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000462 * The pre-preprocessing stage... This function translates line
463 * number indications as they emerge from GNU cpp (`# lineno "file"
464 * flags') into NASM preprocessor line number indications (`%line
465 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000466 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000467static char *prepreproc(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000468{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000469 int lineno, fnlen;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000470 char *fname, *oldline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000471
H. Peter Anvine2c80182005-01-15 22:15:51 +0000472 if (line[0] == '#' && line[1] == ' ') {
473 oldline = line;
474 fname = oldline + 2;
475 lineno = atoi(fname);
476 fname += strspn(fname, "0123456789 ");
477 if (*fname == '"')
478 fname++;
479 fnlen = strcspn(fname, "\"");
480 line = nasm_malloc(20 + fnlen);
481 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
482 nasm_free(oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000483 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000484 if (tasm_compatible_mode)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000485 return check_tasm_directive(line);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000486 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000487}
488
489/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000490 * Free a linked list of tokens.
491 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000492static void free_tlist(Token * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000493{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000494 while (list) {
495 list = delete_Token(list);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000496 }
497}
498
499/*
500 * Free a linked list of lines.
501 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000502static void free_llist(Line * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000503{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000504 Line *l;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000505 while (list) {
506 l = list;
507 list = list->next;
508 free_tlist(l->first);
509 nasm_free(l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000510 }
511}
512
513/*
H. Peter Anvineba20a72002-04-30 20:53:55 +0000514 * Free an MMacro
515 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000516static void free_mmacro(MMacro * m)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000517{
H. Peter Anvin734b1882002-04-30 21:01:08 +0000518 nasm_free(m->name);
519 free_tlist(m->dlist);
520 nasm_free(m->defaults);
521 free_llist(m->expansion);
522 nasm_free(m);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000523}
524
525/*
H. Peter Anvin97a23472007-09-16 17:57:25 -0700526 * Free all currently defined macros, and free the hash tables
527 */
528static void free_macros(void)
529{
530 struct hash_tbl_node *it;
531 const char *key;
532 SMacro *s;
533 MMacro *m;
534
535 it = NULL;
536 while ((s = hash_iterate(smacros, &it, &key)) != NULL) {
537 nasm_free((void *)key);
538 while (s) {
539 SMacro *ns = s->next;
540 nasm_free(s->name);
541 free_tlist(s->expansion);
542 nasm_free(s);
543 s = ns;
544 }
545 }
546 hash_free(smacros);
547
548 it = NULL;
549 while ((m = hash_iterate(mmacros, &it, &key)) != NULL) {
550 nasm_free((void *)key);
551 while (m) {
552 MMacro *nm = m->next;
553 free_mmacro(m);
554 m = nm;
555 }
556 }
557 hash_free(mmacros);
558}
559
560/*
561 * Initialize the hash tables
562 */
563static void init_macros(void)
564{
565 smacros = hash_init();
566 mmacros = hash_init();
567}
568
569/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000570 * Pop the context stack.
571 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000572static void ctx_pop(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000573{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000574 Context *c = cstk;
575 SMacro *smac, *s;
576
577 cstk = cstk->next;
578 smac = c->localmac;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000579 while (smac) {
580 s = smac;
581 smac = smac->next;
582 nasm_free(s->name);
583 free_tlist(s->expansion);
584 nasm_free(s);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000585 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000586 nasm_free(c->name);
587 nasm_free(c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000588}
589
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000590#define BUF_DELTA 512
591/*
592 * Read a line from the top file in istk, handling multiple CR/LFs
593 * at the end of the line read, and handling spurious ^Zs. Will
594 * return lines from the standard macro set if this has not already
595 * been done.
596 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000597static char *read_line(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000598{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000599 char *buffer, *p, *q;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000600 int bufsize, continued_count;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000601
H. Peter Anvine2c80182005-01-15 22:15:51 +0000602 if (stdmacpos) {
603 if (*stdmacpos) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000604 char *ret = nasm_strdup(*stdmacpos++);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000605 if (!*stdmacpos && any_extrastdmac) {
606 stdmacpos = extrastdmac;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700607 any_extrastdmac = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000608 return ret;
609 }
610 /*
611 * Nasty hack: here we push the contents of `predef' on
612 * to the top-level expansion stack, since this is the
613 * most convenient way to implement the pre-include and
614 * pre-define features.
615 */
616 if (!*stdmacpos) {
617 Line *pd, *l;
618 Token *head, **tail, *t;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000619
H. Peter Anvine2c80182005-01-15 22:15:51 +0000620 for (pd = predef; pd; pd = pd->next) {
621 head = NULL;
622 tail = &head;
623 for (t = pd->first; t; t = t->next) {
624 *tail = new_Token(NULL, t->type, t->text, 0);
625 tail = &(*tail)->next;
626 }
627 l = nasm_malloc(sizeof(Line));
628 l->next = istk->expansion;
629 l->first = head;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700630 l->finishes = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000631 istk->expansion = l;
632 }
633 }
634 return ret;
635 } else {
636 stdmacpos = NULL;
637 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000638 }
639
640 bufsize = BUF_DELTA;
641 buffer = nasm_malloc(BUF_DELTA);
642 p = buffer;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000643 continued_count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000644 while (1) {
645 q = fgets(p, bufsize - (p - buffer), istk->fp);
646 if (!q)
647 break;
648 p += strlen(p);
649 if (p > buffer && p[-1] == '\n') {
650 /* Convert backslash-CRLF line continuation sequences into
651 nothing at all (for DOS and Windows) */
652 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
653 p -= 3;
654 *p = 0;
655 continued_count++;
656 }
657 /* Also convert backslash-LF line continuation sequences into
658 nothing at all (for Unix) */
659 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
660 p -= 2;
661 *p = 0;
662 continued_count++;
663 } else {
664 break;
665 }
666 }
667 if (p - buffer > bufsize - 10) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000668 int32_t offset = p - buffer;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000669 bufsize += BUF_DELTA;
670 buffer = nasm_realloc(buffer, bufsize);
671 p = buffer + offset; /* prevent stale-pointer problems */
672 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000673 }
674
H. Peter Anvine2c80182005-01-15 22:15:51 +0000675 if (!q && p == buffer) {
676 nasm_free(buffer);
677 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000678 }
679
H. Peter Anvine2c80182005-01-15 22:15:51 +0000680 src_set_linnum(src_get_linnum() + istk->lineinc +
681 (continued_count * istk->lineinc));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000682
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000683 /*
684 * Play safe: remove CRs as well as LFs, if any of either are
685 * present at the end of the line.
686 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000687 while (--p >= buffer && (*p == '\n' || *p == '\r'))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000688 *p = '\0';
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000689
690 /*
691 * Handle spurious ^Z, which may be inserted into source files
692 * by some file transfer utilities.
693 */
694 buffer[strcspn(buffer, "\032")] = '\0';
695
H. Peter Anvin734b1882002-04-30 21:01:08 +0000696 list->line(LIST_READ, buffer);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000697
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000698 return buffer;
699}
700
701/*
Keith Kaniosb7a89542007-04-12 02:40:54 +0000702 * Tokenize a line of text. This is a very simple process since we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000703 * don't need to parse the value out of e.g. numeric tokens: we
704 * simply split one string into many.
705 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000706static Token *tokenize(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000707{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000708 char *p = line;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000709 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000710 Token *list = NULL;
711 Token *t, **tail = &list;
712
H. Peter Anvine2c80182005-01-15 22:15:51 +0000713 while (*line) {
714 p = line;
715 if (*p == '%') {
716 p++;
717 if (isdigit(*p) ||
718 ((*p == '-' || *p == '+') && isdigit(p[1])) ||
719 ((*p == '+') && (isspace(p[1]) || !p[1]))) {
720 do {
721 p++;
722 }
723 while (isdigit(*p));
724 type = TOK_PREPROC_ID;
725 } else if (*p == '{') {
726 p++;
727 while (*p && *p != '}') {
728 p[-1] = *p;
729 p++;
730 }
731 p[-1] = '\0';
732 if (*p)
733 p++;
734 type = TOK_PREPROC_ID;
735 } else if (isidchar(*p) ||
736 ((*p == '!' || *p == '%' || *p == '$') &&
737 isidchar(p[1]))) {
738 do {
739 p++;
740 }
741 while (isidchar(*p));
742 type = TOK_PREPROC_ID;
743 } else {
744 type = TOK_OTHER;
745 if (*p == '%')
746 p++;
747 }
748 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
749 type = TOK_ID;
750 p++;
751 while (*p && isidchar(*p))
752 p++;
753 } else if (*p == '\'' || *p == '"') {
754 /*
755 * A string token.
756 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000757 char c = *p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000758 p++;
759 type = TOK_STRING;
760 while (*p && *p != c)
761 p++;
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000762
H. Peter Anvine2c80182005-01-15 22:15:51 +0000763 if (*p) {
764 p++;
765 } else {
766 error(ERR_WARNING, "unterminated string");
767 /* Handling unterminated strings by UNV */
768 /* type = -1; */
769 }
770 } else if (isnumstart(*p)) {
771 /*
772 * A number token.
773 */
774 type = TOK_NUMBER;
775 p++;
776 while (*p && isnumchar(*p))
777 p++;
778 } else if (isspace(*p)) {
779 type = TOK_WHITESPACE;
780 p++;
781 while (*p && isspace(*p))
782 p++;
783 /*
784 * Whitespace just before end-of-line is discarded by
785 * pretending it's a comment; whitespace just before a
786 * comment gets lumped into the comment.
787 */
788 if (!*p || *p == ';') {
789 type = TOK_COMMENT;
790 while (*p)
791 p++;
792 }
793 } else if (*p == ';') {
794 type = TOK_COMMENT;
795 while (*p)
796 p++;
797 } else {
798 /*
799 * Anything else is an operator of some kind. We check
800 * for all the double-character operators (>>, <<, //,
801 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000802 * else is a single-character operator.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000803 */
804 type = TOK_OTHER;
805 if ((p[0] == '>' && p[1] == '>') ||
806 (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++;
817 }
818 p++;
819 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000820
H. Peter Anvine2c80182005-01-15 22:15:51 +0000821 /* Handling unterminated string by UNV */
822 /*if (type == -1)
823 {
824 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
825 t->text[p-line] = *line;
826 tail = &t->next;
827 }
828 else */
829 if (type != TOK_COMMENT) {
830 *tail = t = new_Token(NULL, type, line, p - line);
831 tail = &t->next;
832 }
833 line = p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000834 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000835 return list;
836}
837
H. Peter Anvince616072002-04-30 21:02:23 +0000838/*
839 * this function allocates a new managed block of memory and
840 * returns a pointer to the block. The managed blocks are
841 * deleted only all at once by the delete_Blocks function.
842 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000843static void *new_Block(size_t size)
H. Peter Anvince616072002-04-30 21:02:23 +0000844{
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000845 Blocks *b = &blocks;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000846
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000847 /* first, get to the end of the linked list */
848 while (b->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000849 b = b->next;
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000850 /* now allocate the requested chunk */
851 b->chunk = nasm_malloc(size);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000852
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000853 /* now allocate a new block for the next request */
854 b->next = nasm_malloc(sizeof(Blocks));
855 /* and initialize the contents of the new block */
856 b->next->next = NULL;
857 b->next->chunk = NULL;
858 return b->chunk;
H. Peter Anvince616072002-04-30 21:02:23 +0000859}
860
861/*
862 * this function deletes all managed blocks of memory
863 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000864static void delete_Blocks(void)
H. Peter Anvince616072002-04-30 21:02:23 +0000865{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000866 Blocks *a, *b = &blocks;
H. Peter Anvince616072002-04-30 21:02:23 +0000867
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000868 /*
869 * keep in mind that the first block, pointed to by blocks
870 * is a static and not dynamically allocated, so we don't
871 * free it.
872 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000873 while (b) {
874 if (b->chunk)
875 nasm_free(b->chunk);
876 a = b;
877 b = b->next;
878 if (a != &blocks)
879 nasm_free(a);
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +0000880 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000881}
H. Peter Anvin734b1882002-04-30 21:01:08 +0000882
883/*
884 * this function creates a new Token and passes a pointer to it
885 * back to the caller. It sets the type and text elements, and
886 * also the mac and next elements to NULL.
887 */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000888static Token *new_Token(Token * next, enum pp_token_type type, char *text, int txtlen)
H. Peter Anvin734b1882002-04-30 21:01:08 +0000889{
890 Token *t;
891 int i;
892
H. Peter Anvine2c80182005-01-15 22:15:51 +0000893 if (freeTokens == NULL) {
894 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
895 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
896 freeTokens[i].next = &freeTokens[i + 1];
897 freeTokens[i].next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000898 }
899 t = freeTokens;
900 freeTokens = t->next;
901 t->next = next;
902 t->mac = NULL;
903 t->type = type;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000904 if (type == TOK_WHITESPACE || text == NULL) {
905 t->text = NULL;
906 } else {
907 if (txtlen == 0)
908 txtlen = strlen(text);
909 t->text = nasm_malloc(1 + txtlen);
910 strncpy(t->text, text, txtlen);
911 t->text[txtlen] = '\0';
H. Peter Anvin734b1882002-04-30 21:01:08 +0000912 }
913 return t;
914}
915
H. Peter Anvine2c80182005-01-15 22:15:51 +0000916static Token *delete_Token(Token * t)
H. Peter Anvin734b1882002-04-30 21:01:08 +0000917{
918 Token *next = t->next;
919 nasm_free(t->text);
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000920 t->next = freeTokens;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000921 freeTokens = t;
922 return next;
923}
924
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000925/*
926 * Convert a line of tokens back into text.
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000927 * If expand_locals is not zero, identifiers of the form "%$*xxx"
928 * will be transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000929 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000930static char *detoken(Token * tlist, int expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000931{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000932 Token *t;
933 int len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000934 char *line, *p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000935
936 len = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000937 for (t = tlist; t; t = t->next) {
938 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000939 char *p = getenv(t->text + 2);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000940 nasm_free(t->text);
941 if (p)
942 t->text = nasm_strdup(p);
943 else
944 t->text = NULL;
945 }
946 /* Expand local macros here and not during preprocessing */
947 if (expand_locals &&
948 t->type == TOK_PREPROC_ID && t->text &&
949 t->text[0] == '%' && t->text[1] == '$') {
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700950 Context *ctx = get_ctx(t->text, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000951 if (ctx) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000952 char buffer[40];
953 char *p, *q = t->text + 2;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000954
H. Peter Anvine2c80182005-01-15 22:15:51 +0000955 q += strspn(q, "$");
Keith Kanios93f2e9a2007-04-14 00:10:59 +0000956 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000957 p = nasm_strcat(buffer, q);
958 nasm_free(t->text);
959 t->text = p;
960 }
961 }
962 if (t->type == TOK_WHITESPACE) {
963 len++;
964 } else if (t->text) {
965 len += strlen(t->text);
966 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000967 }
H. Peter Anvin734b1882002-04-30 21:01:08 +0000968 p = line = nasm_malloc(len + 1);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000969 for (t = tlist; t; t = t->next) {
970 if (t->type == TOK_WHITESPACE) {
971 *p = ' ';
972 p++;
973 *p = '\0';
974 } else if (t->text) {
975 strcpy(p, t->text);
976 p += strlen(p);
977 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000978 }
979 *p = '\0';
980 return line;
981}
982
983/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000984 * A scanner, suitable for use by the expression evaluator, which
985 * operates on a line of Tokens. Expects a pointer to a pointer to
986 * the first token in the line to be passed in as its private_data
987 * field.
988 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000989static int ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000990{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000991 Token **tlineptr = private_data;
992 Token *tline;
993
H. Peter Anvine2c80182005-01-15 22:15:51 +0000994 do {
995 tline = *tlineptr;
996 *tlineptr = tline ? tline->next : NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000997 }
998 while (tline && (tline->type == TOK_WHITESPACE ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000999 tline->type == TOK_COMMENT));
H. Peter Anvin76690a12002-04-30 20:52:49 +00001000
1001 if (!tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001002 return tokval->t_type = TOKEN_EOS;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001003
1004 if (tline->text[0] == '$' && !tline->text[1])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001005 return tokval->t_type = TOKEN_HERE;
H. Peter Anvin7cf897e2002-05-30 21:30:33 +00001006 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001007 return tokval->t_type = TOKEN_BASE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001008
H. Peter Anvine2c80182005-01-15 22:15:51 +00001009 if (tline->type == TOK_ID) {
1010 tokval->t_charptr = tline->text;
1011 if (tline->text[0] == '$') {
1012 tokval->t_charptr++;
1013 return tokval->t_type = TOKEN_ID;
1014 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001015
H. Peter Anvine2c80182005-01-15 22:15:51 +00001016 /*
1017 * This is the only special case we actually need to worry
1018 * about in this restricted context.
1019 */
1020 if (!nasm_stricmp(tline->text, "seg"))
1021 return tokval->t_type = TOKEN_SEG;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001022
H. Peter Anvine2c80182005-01-15 22:15:51 +00001023 return tokval->t_type = TOKEN_ID;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001024 }
1025
H. Peter Anvine2c80182005-01-15 22:15:51 +00001026 if (tline->type == TOK_NUMBER) {
H. Peter Anvin70055962007-10-11 00:05:31 -07001027 bool rn_error;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001028
H. Peter Anvine2c80182005-01-15 22:15:51 +00001029 tokval->t_integer = readnum(tline->text, &rn_error);
1030 if (rn_error)
1031 return tokval->t_type = TOKEN_ERRNUM;
1032 tokval->t_charptr = NULL;
1033 return tokval->t_type = TOKEN_NUM;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001034 }
1035
H. Peter Anvine2c80182005-01-15 22:15:51 +00001036 if (tline->type == TOK_STRING) {
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07001037 bool rn_warn;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001038 char q, *r;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001039 int l;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001040
H. Peter Anvine2c80182005-01-15 22:15:51 +00001041 r = tline->text;
1042 q = *r++;
1043 l = strlen(r);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001044
H. Peter Anvine2c80182005-01-15 22:15:51 +00001045 if (l == 0 || r[l - 1] != q)
1046 return tokval->t_type = TOKEN_ERRNUM;
1047 tokval->t_integer = readstrnum(r, l - 1, &rn_warn);
1048 if (rn_warn)
1049 error(ERR_WARNING | ERR_PASS1, "character constant too long");
1050 tokval->t_charptr = NULL;
1051 return tokval->t_type = TOKEN_NUM;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001052 }
1053
H. Peter Anvine2c80182005-01-15 22:15:51 +00001054 if (tline->type == TOK_OTHER) {
1055 if (!strcmp(tline->text, "<<"))
1056 return tokval->t_type = TOKEN_SHL;
1057 if (!strcmp(tline->text, ">>"))
1058 return tokval->t_type = TOKEN_SHR;
1059 if (!strcmp(tline->text, "//"))
1060 return tokval->t_type = TOKEN_SDIV;
1061 if (!strcmp(tline->text, "%%"))
1062 return tokval->t_type = TOKEN_SMOD;
1063 if (!strcmp(tline->text, "=="))
1064 return tokval->t_type = TOKEN_EQ;
1065 if (!strcmp(tline->text, "<>"))
1066 return tokval->t_type = TOKEN_NE;
1067 if (!strcmp(tline->text, "!="))
1068 return tokval->t_type = TOKEN_NE;
1069 if (!strcmp(tline->text, "<="))
1070 return tokval->t_type = TOKEN_LE;
1071 if (!strcmp(tline->text, ">="))
1072 return tokval->t_type = TOKEN_GE;
1073 if (!strcmp(tline->text, "&&"))
1074 return tokval->t_type = TOKEN_DBL_AND;
1075 if (!strcmp(tline->text, "^^"))
1076 return tokval->t_type = TOKEN_DBL_XOR;
1077 if (!strcmp(tline->text, "||"))
1078 return tokval->t_type = TOKEN_DBL_OR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001079 }
1080
1081 /*
1082 * We have no other options: just return the first character of
1083 * the token text.
1084 */
1085 return tokval->t_type = tline->text[0];
1086}
1087
1088/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001089 * Compare a string to the name of an existing macro; this is a
1090 * simple wrapper which calls either strcmp or nasm_stricmp
1091 * depending on the value of the `casesense' parameter.
1092 */
H. Peter Anvin70055962007-10-11 00:05:31 -07001093static int mstrcmp(char *p, char *q, bool casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001094{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001095 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001096}
1097
1098/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001099 * Return the Context structure associated with a %$ token. Return
1100 * NULL, having _already_ reported an error condition, if the
1101 * context stack isn't deep enough for the supplied number of $
1102 * signs.
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001103 * If all_contexts == true, contexts that enclose current are
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001104 * also scanned for such smacro, until it is found; if not -
1105 * only the context that directly results from the number of $'s
1106 * in variable's name.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001107 */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001108static Context *get_ctx(char *name, bool all_contexts)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001109{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001110 Context *ctx;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001111 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001112 int i;
1113
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001114 if (!name || name[0] != '%' || name[1] != '$')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001115 return NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001116
H. Peter Anvine2c80182005-01-15 22:15:51 +00001117 if (!cstk) {
1118 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1119 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001120 }
1121
H. Peter Anvine2c80182005-01-15 22:15:51 +00001122 for (i = strspn(name + 2, "$"), ctx = cstk; (i > 0) && ctx; i--) {
1123 ctx = ctx->next;
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00001124/* i--; Lino - 02/25/02 */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001125 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001126 if (!ctx) {
1127 error(ERR_NONFATAL, "`%s': context stack is only"
1128 " %d level%s deep", name, i - 1, (i == 2 ? "" : "s"));
1129 return NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001130 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001131 if (!all_contexts)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001132 return ctx;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001133
H. Peter Anvine2c80182005-01-15 22:15:51 +00001134 do {
1135 /* Search for this smacro in found context */
1136 m = ctx->localmac;
1137 while (m) {
1138 if (!mstrcmp(m->name, name, m->casesense))
1139 return ctx;
1140 m = m->next;
1141 }
1142 ctx = ctx->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001143 }
1144 while (ctx);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001145 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001146}
1147
1148/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001149 * Open an include file. This routine must always return a valid
1150 * file pointer if it returns - it's responsible for throwing an
1151 * ERR_FATAL and bombing out completely if not. It should also try
1152 * the include path one by one until it finds the file or reaches
1153 * the end of the path.
1154 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001155static FILE *inc_fopen(char *file)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001156{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001157 FILE *fp;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001158 char *prefix = "", *combine;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001159 IncPath *ip = ipath;
H. Peter Anvin620515a2002-04-30 20:57:38 +00001160 static int namelen = 0;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001161 int len = strlen(file);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001162
H. Peter Anvine2c80182005-01-15 22:15:51 +00001163 while (1) {
1164 combine = nasm_malloc(strlen(prefix) + len + 1);
1165 strcpy(combine, prefix);
1166 strcat(combine, file);
1167 fp = fopen(combine, "r");
1168 if (pass == 0 && fp) {
1169 namelen += strlen(combine) + 1;
1170 if (namelen > 62) {
1171 printf(" \\\n ");
1172 namelen = 2;
1173 }
1174 printf(" %s", combine);
1175 }
1176 nasm_free(combine);
1177 if (fp)
1178 return fp;
1179 if (!ip)
1180 break;
1181 prefix = ip->path;
1182 ip = ip->next;
H. Peter Anvin37a321f2007-09-24 13:41:58 -07001183
1184 if (!prefix) {
1185 /* -MG given and file not found */
1186 if (pass == 0) {
1187 namelen += strlen(file) + 1;
1188 if (namelen > 62) {
1189 printf(" \\\n ");
1190 namelen = 2;
1191 }
1192 printf(" %s", file);
1193 }
1194 return NULL;
1195 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001196 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001197
H. Peter Anvin734b1882002-04-30 21:01:08 +00001198 error(ERR_FATAL, "unable to open include file `%s'", file);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001199 return NULL; /* never reached - placate compilers */
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001200}
1201
1202/*
H. Peter Anvin97a23472007-09-16 17:57:25 -07001203 * Search for a key in the hash index; adding it if necessary
1204 * (in which case we initialize the data pointer to NULL.)
1205 */
1206static void **
1207hash_findi_add(struct hash_table *hash, const char *str)
1208{
1209 struct hash_insert hi;
1210 void **r;
1211 char *strx;
1212
1213 r = hash_findi(hash, str, &hi);
1214 if (r)
1215 return r;
1216
1217 strx = nasm_strdup(str); /* Use a more efficient allocator here? */
1218 return hash_add(&hi, strx, NULL);
1219}
1220
1221/*
1222 * Like hash_findi, but returns the data element rather than a pointer
1223 * to it. Used only when not adding a new element, hence no third
1224 * argument.
1225 */
1226static void *
1227hash_findix(struct hash_table *hash, const char *str)
1228{
1229 void **p;
1230
1231 p = hash_findi(hash, str, NULL);
1232 return p ? *p : NULL;
1233}
1234
1235/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001236 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001237 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001238 * return true if _any_ single-line macro of that name is defined.
1239 * Otherwise, will return true if a single-line macro with either
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001240 * `nparam' or no parameters is defined.
1241 *
1242 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001243 * defined, or nparam is -1, the address of the definition structure
1244 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001245 * is NULL, no action will be taken regarding its contents, and no
1246 * error will occur.
1247 *
1248 * Note that this is also called with nparam zero to resolve
1249 * `ifdef'.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001250 *
1251 * If you already know which context macro belongs to, you can pass
1252 * the context pointer as first parameter; if you won't but name begins
1253 * with %$ the context will be automatically computed. If all_contexts
1254 * is true, macro will be searched in outer contexts as well.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001255 */
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001256static bool
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001257smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001258 bool nocase)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001259{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001260 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001261
H. Peter Anvin97a23472007-09-16 17:57:25 -07001262 if (ctx) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001263 m = ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001264 } else if (name[0] == '%' && name[1] == '$') {
1265 if (cstk)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001266 ctx = get_ctx(name, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001267 if (!ctx)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001268 return false; /* got to return _something_ */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001269 m = ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001270 } else {
1271 m = (SMacro *) hash_findix(smacros, name);
1272 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001273
H. Peter Anvine2c80182005-01-15 22:15:51 +00001274 while (m) {
1275 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
1276 (nparam <= 0 || m->nparam == 0 || nparam == m->nparam)) {
1277 if (defn) {
1278 if (nparam == m->nparam || nparam == -1)
1279 *defn = m;
1280 else
1281 *defn = NULL;
1282 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001283 return true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001284 }
1285 m = m->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001286 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001287
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001288 return false;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001289}
1290
1291/*
1292 * Count and mark off the parameters in a multi-line macro call.
1293 * This is called both from within the multi-line macro expansion
1294 * code, and also to mark off the default parameters when provided
1295 * in a %macro definition line.
1296 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001297static void count_mmac_params(Token * t, int *nparam, Token *** params)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001298{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001299 int paramsize, brace;
1300
1301 *nparam = paramsize = 0;
1302 *params = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001303 while (t) {
1304 if (*nparam >= paramsize) {
1305 paramsize += PARAM_DELTA;
1306 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1307 }
1308 skip_white_(t);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001309 brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001310 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001311 brace = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001312 (*params)[(*nparam)++] = t;
1313 while (tok_isnt_(t, brace ? "}" : ","))
1314 t = t->next;
1315 if (t) { /* got a comma/brace */
1316 t = t->next;
1317 if (brace) {
1318 /*
1319 * Now we've found the closing brace, look further
1320 * for the comma.
1321 */
1322 skip_white_(t);
1323 if (tok_isnt_(t, ",")) {
1324 error(ERR_NONFATAL,
1325 "braces do not enclose all of macro parameter");
1326 while (tok_isnt_(t, ","))
1327 t = t->next;
1328 }
1329 if (t)
1330 t = t->next; /* eat the comma */
1331 }
1332 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001333 }
1334}
1335
1336/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001337 * Determine whether one of the various `if' conditions is true or
1338 * not.
1339 *
1340 * We must free the tline we get passed.
1341 */
H. Peter Anvin70055962007-10-11 00:05:31 -07001342static bool if_condition(Token * tline, enum preproc_token ct)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001343{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001344 enum pp_conditional i = PP_COND(ct);
H. Peter Anvin70055962007-10-11 00:05:31 -07001345 bool j;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001346 Token *t, *tt, **tptr, *origline;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001347 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001348 expr *evalresult;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001349 enum pp_token_type needtype;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001350
1351 origline = tline;
1352
H. Peter Anvine2c80182005-01-15 22:15:51 +00001353 switch (i) {
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001354 case PPC_IFCTX:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001355 j = false; /* have we matched yet? */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001356 while (cstk && tline) {
1357 skip_white_(tline);
1358 if (!tline || tline->type != TOK_ID) {
1359 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001360 "`%s' expects context identifiers", pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001361 free_tlist(origline);
1362 return -1;
1363 }
1364 if (!nasm_stricmp(tline->text, cstk->name))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001365 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001366 tline = tline->next;
1367 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001368 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001369
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001370 case PPC_IFDEF:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001371 j = false; /* have we matched yet? */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001372 while (tline) {
1373 skip_white_(tline);
1374 if (!tline || (tline->type != TOK_ID &&
1375 (tline->type != TOK_PREPROC_ID ||
1376 tline->text[1] != '$'))) {
1377 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001378 "`%s' expects macro identifiers", pp_directives[ct]);
1379 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001380 }
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001381 if (smacro_defined(NULL, tline->text, 0, NULL, true))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001382 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001383 tline = tline->next;
1384 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001385 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001386
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001387 case PPC_IFIDN:
1388 case PPC_IFIDNI:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001389 tline = expand_smacro(tline);
1390 t = tt = tline;
1391 while (tok_isnt_(tt, ","))
1392 tt = tt->next;
1393 if (!tt) {
1394 error(ERR_NONFATAL,
1395 "`%s' expects two comma-separated arguments",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001396 pp_directives[ct]);
1397 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001398 }
1399 tt = tt->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001400 j = true; /* assume equality unless proved not */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001401 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1402 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1403 error(ERR_NONFATAL, "`%s': more than one comma on line",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001404 pp_directives[ct]);
1405 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001406 }
1407 if (t->type == TOK_WHITESPACE) {
1408 t = t->next;
1409 continue;
1410 }
1411 if (tt->type == TOK_WHITESPACE) {
1412 tt = tt->next;
1413 continue;
1414 }
1415 if (tt->type != t->type) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001416 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001417 break;
1418 }
1419 /* Unify surrounding quotes for strings */
1420 if (t->type == TOK_STRING) {
1421 tt->text[0] = t->text[0];
1422 tt->text[strlen(tt->text) - 1] = t->text[0];
1423 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001424 if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001425 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001426 break;
1427 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001428
H. Peter Anvine2c80182005-01-15 22:15:51 +00001429 t = t->next;
1430 tt = tt->next;
1431 }
1432 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001433 j = false; /* trailing gunk on one end or other */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001434 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001435
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001436 case PPC_IFMACRO:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001437 {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001438 bool found = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001439 MMacro searching, *mmac;
H. Peter Anvin65747262002-05-07 00:10:05 +00001440
H. Peter Anvine2c80182005-01-15 22:15:51 +00001441 tline = tline->next;
1442 skip_white_(tline);
1443 tline = expand_id(tline);
1444 if (!tok_type_(tline, TOK_ID)) {
1445 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001446 "`%s' expects a macro name", pp_directives[ct]);
1447 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001448 }
1449 searching.name = nasm_strdup(tline->text);
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001450 searching.casesense = true;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001451 searching.plus = false;
1452 searching.nolist = false;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07001453 searching.in_progress = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001454 searching.rep_nest = NULL;
1455 searching.nparam_min = 0;
1456 searching.nparam_max = INT_MAX;
1457 tline = expand_smacro(tline->next);
1458 skip_white_(tline);
1459 if (!tline) {
1460 } else if (!tok_type_(tline, TOK_NUMBER)) {
1461 error(ERR_NONFATAL,
1462 "`%s' expects a parameter count or nothing",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001463 pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001464 } else {
1465 searching.nparam_min = searching.nparam_max =
1466 readnum(tline->text, &j);
1467 if (j)
1468 error(ERR_NONFATAL,
1469 "unable to parse parameter count `%s'",
1470 tline->text);
1471 }
1472 if (tline && tok_is_(tline->next, "-")) {
1473 tline = tline->next->next;
1474 if (tok_is_(tline, "*"))
1475 searching.nparam_max = INT_MAX;
1476 else if (!tok_type_(tline, TOK_NUMBER))
1477 error(ERR_NONFATAL,
1478 "`%s' expects a parameter count after `-'",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001479 pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001480 else {
1481 searching.nparam_max = readnum(tline->text, &j);
1482 if (j)
1483 error(ERR_NONFATAL,
1484 "unable to parse parameter count `%s'",
1485 tline->text);
1486 if (searching.nparam_min > searching.nparam_max)
1487 error(ERR_NONFATAL,
1488 "minimum parameter count exceeds maximum");
1489 }
1490 }
1491 if (tline && tok_is_(tline->next, "+")) {
1492 tline = tline->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001493 searching.plus = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001494 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07001495 mmac = (MMacro *) hash_findix(mmacros, searching.name);
1496 while (mmac) {
1497 if (!strcmp(mmac->name, searching.name) &&
1498 (mmac->nparam_min <= searching.nparam_max
1499 || searching.plus)
1500 && (searching.nparam_min <= mmac->nparam_max
1501 || mmac->plus)) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001502 found = true;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001503 break;
1504 }
1505 mmac = mmac->next;
1506 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001507 nasm_free(searching.name);
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001508 j = found;
1509 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001510 }
H. Peter Anvin65747262002-05-07 00:10:05 +00001511
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001512 case PPC_IFID:
1513 needtype = TOK_ID;
1514 goto iftype;
1515 case PPC_IFNUM:
1516 needtype = TOK_NUMBER;
1517 goto iftype;
1518 case PPC_IFSTR:
1519 needtype = TOK_STRING;
1520 goto iftype;
1521
1522 iftype:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001523 tline = expand_smacro(tline);
1524 t = tline;
1525 while (tok_type_(t, TOK_WHITESPACE))
1526 t = t->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001527 j = false; /* placate optimiser */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001528 if (t)
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001529 j = t->type == needtype;
1530 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001531
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001532 case PPC_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001533 t = tline = expand_smacro(tline);
1534 tptr = &t;
1535 tokval.t_type = TOKEN_INVALID;
1536 evalresult = evaluate(ppscan, tptr, &tokval,
1537 NULL, pass | CRITICAL, error, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001538 if (!evalresult)
1539 return -1;
1540 if (tokval.t_type)
1541 error(ERR_WARNING,
1542 "trailing garbage after expression ignored");
1543 if (!is_simple(evalresult)) {
1544 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001545 "non-constant value given to `%s'", pp_directives[ct]);
1546 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001547 }
Chuck Crayne60ae75d2007-05-02 01:59:16 +00001548 j = reloc_value(evalresult) != 0;
Chuck Crayne60ae75d2007-05-02 01:59:16 +00001549 return j;
H. Peter Anvin95e28822007-09-12 04:20:08 +00001550
H. Peter Anvine2c80182005-01-15 22:15:51 +00001551 default:
1552 error(ERR_FATAL,
1553 "preprocessor directive `%s' not yet implemented",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001554 pp_directives[ct]);
1555 goto fail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001556 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001557
1558 free_tlist(origline);
1559 return j ^ PP_NEGATIVE(ct);
1560
1561fail:
1562 free_tlist(origline);
1563 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001564}
1565
1566/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001567 * Expand macros in a string. Used in %error and %include directives.
Keith Kaniosb7a89542007-04-12 02:40:54 +00001568 * First tokenize the string, apply "expand_smacro" and then de-tokenize back.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001569 * The returned variable should ALWAYS be freed after usage.
1570 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001571void expand_macros_in_string(char **p)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001572{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001573 Token *line = tokenize(*p);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001574 line = expand_smacro(line);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001575 *p = detoken(line, false);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001576}
1577
Ed Beroset3ab3f412002-06-11 03:31:49 +00001578/**
1579 * find and process preprocessor directive in passed line
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001580 * Find out if a line contains a preprocessor directive, and deal
1581 * with it if so.
1582 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00001583 * If a directive _is_ found, it is the responsibility of this routine
1584 * (and not the caller) to free_tlist() the line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001585 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00001586 * @param tline a pointer to the current tokeninzed line linked list
1587 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001588 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001589 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001590static int do_directive(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001591{
H. Peter Anvin4169a472007-09-12 01:29:43 +00001592 enum preproc_token i;
1593 int j;
H. Peter Anvin70055962007-10-11 00:05:31 -07001594 bool err;
1595 int nparam;
1596 bool nolist;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001597 bool casesense;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -07001598 int k, m;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001599 int offset;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001600 char *p, *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001601 Include *inc;
1602 Context *ctx;
1603 Cond *cond;
1604 SMacro *smac, **smhead;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001605 MMacro *mmac, **mmhead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001606 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
1607 Line *l;
1608 struct tokenval tokval;
1609 expr *evalresult;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001610 MMacro *tmp_defining; /* Used when manipulating rep_nest */
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07001611 int64_t count;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001612
1613 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001614
H. Peter Anvineba20a72002-04-30 20:53:55 +00001615 skip_white_(tline);
1616 if (!tok_type_(tline, TOK_PREPROC_ID) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001617 (tline->text[1] == '%' || tline->text[1] == '$'
1618 || tline->text[1] == '!'))
1619 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001620
H. Peter Anvin4169a472007-09-12 01:29:43 +00001621 i = pp_token_hash(tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001622
1623 /*
1624 * If we're in a non-emitting branch of a condition construct,
H. Peter Anvin76690a12002-04-30 20:52:49 +00001625 * or walking to the end of an already terminated %rep block,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001626 * we should ignore all directives except for condition
1627 * directives.
1628 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001629 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001630 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
1631 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001632 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001633
1634 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001635 * If we're defining a macro or reading a %rep block, we should
1636 * ignore all directives except for %macro/%imacro (which
1637 * generate an error), %endm/%endmacro, and (only if we're in a
H. Peter Anvineba20a72002-04-30 20:53:55 +00001638 * %rep block) %endrep. If we're in a %rep block, another %rep
1639 * causes an error, so should be let through.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001640 */
1641 if (defining && i != PP_MACRO && i != PP_IMACRO &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001642 i != PP_ENDMACRO && i != PP_ENDM &&
1643 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
1644 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001645 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001646
H. Peter Anvin4169a472007-09-12 01:29:43 +00001647 switch (i) {
1648 case PP_INVALID:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001649 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
1650 tline->text);
1651 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001652
H. Peter Anvine2c80182005-01-15 22:15:51 +00001653 case PP_STACKSIZE:
1654 /* Directive to tell NASM what the default stack size is. The
1655 * default is for a 16-bit stack, and this can be overriden with
1656 * %stacksize large.
1657 * the following form:
1658 *
1659 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1660 */
1661 tline = tline->next;
1662 if (tline && tline->type == TOK_WHITESPACE)
1663 tline = tline->next;
1664 if (!tline || tline->type != TOK_ID) {
1665 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
1666 free_tlist(origline);
1667 return DIRECTIVE_FOUND;
1668 }
1669 if (nasm_stricmp(tline->text, "flat") == 0) {
1670 /* All subsequent ARG directives are for a 32-bit stack */
1671 StackSize = 4;
1672 StackPointer = "ebp";
1673 ArgOffset = 8;
1674 LocalOffset = 4;
1675 } else if (nasm_stricmp(tline->text, "large") == 0) {
1676 /* All subsequent ARG directives are for a 16-bit stack,
1677 * far function call.
1678 */
1679 StackSize = 2;
1680 StackPointer = "bp";
1681 ArgOffset = 4;
1682 LocalOffset = 2;
1683 } else if (nasm_stricmp(tline->text, "small") == 0) {
1684 /* All subsequent ARG directives are for a 16-bit stack,
1685 * far function call. We don't support near functions.
1686 */
1687 StackSize = 2;
1688 StackPointer = "bp";
1689 ArgOffset = 6;
1690 LocalOffset = 2;
1691 } else {
1692 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
1693 free_tlist(origline);
1694 return DIRECTIVE_FOUND;
1695 }
1696 free_tlist(origline);
1697 return DIRECTIVE_FOUND;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001698
H. Peter Anvine2c80182005-01-15 22:15:51 +00001699 case PP_ARG:
1700 /* TASM like ARG directive to define arguments to functions, in
1701 * the following form:
1702 *
1703 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
1704 */
1705 offset = ArgOffset;
1706 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001707 char *arg, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00001708 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001709
H. Peter Anvine2c80182005-01-15 22:15:51 +00001710 /* Find the argument name */
1711 tline = tline->next;
1712 if (tline && tline->type == TOK_WHITESPACE)
1713 tline = tline->next;
1714 if (!tline || tline->type != TOK_ID) {
1715 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
1716 free_tlist(origline);
1717 return DIRECTIVE_FOUND;
1718 }
1719 arg = tline->text;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001720
H. Peter Anvine2c80182005-01-15 22:15:51 +00001721 /* Find the argument size type */
1722 tline = tline->next;
1723 if (!tline || tline->type != TOK_OTHER
1724 || tline->text[0] != ':') {
1725 error(ERR_NONFATAL,
1726 "Syntax error processing `%%arg' directive");
1727 free_tlist(origline);
1728 return DIRECTIVE_FOUND;
1729 }
1730 tline = tline->next;
1731 if (!tline || tline->type != TOK_ID) {
1732 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
1733 free_tlist(origline);
1734 return DIRECTIVE_FOUND;
1735 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001736
H. Peter Anvine2c80182005-01-15 22:15:51 +00001737 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001738 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001739 tt = expand_smacro(tt);
1740 if (nasm_stricmp(tt->text, "byte") == 0) {
1741 size = MAX(StackSize, 1);
1742 } else if (nasm_stricmp(tt->text, "word") == 0) {
1743 size = MAX(StackSize, 2);
1744 } else if (nasm_stricmp(tt->text, "dword") == 0) {
1745 size = MAX(StackSize, 4);
1746 } else if (nasm_stricmp(tt->text, "qword") == 0) {
1747 size = MAX(StackSize, 8);
1748 } else if (nasm_stricmp(tt->text, "tword") == 0) {
1749 size = MAX(StackSize, 10);
1750 } else {
1751 error(ERR_NONFATAL,
1752 "Invalid size type for `%%arg' missing directive");
1753 free_tlist(tt);
1754 free_tlist(origline);
1755 return DIRECTIVE_FOUND;
1756 }
1757 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001758
H. Peter Anvine2c80182005-01-15 22:15:51 +00001759 /* Now define the macro for the argument */
1760 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
1761 arg, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001762 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001763 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001764
H. Peter Anvine2c80182005-01-15 22:15:51 +00001765 /* Move to the next argument in the list */
1766 tline = tline->next;
1767 if (tline && tline->type == TOK_WHITESPACE)
1768 tline = tline->next;
1769 }
1770 while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
1771 free_tlist(origline);
1772 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001773
H. Peter Anvine2c80182005-01-15 22:15:51 +00001774 case PP_LOCAL:
1775 /* TASM like LOCAL directive to define local variables for a
1776 * function, in the following form:
1777 *
1778 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
1779 *
1780 * The '= LocalSize' at the end is ignored by NASM, but is
1781 * required by TASM to define the local parameter size (and used
1782 * by the TASM macro package).
1783 */
1784 offset = LocalOffset;
1785 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001786 char *local, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00001787 int size = StackSize;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001788
H. Peter Anvine2c80182005-01-15 22:15:51 +00001789 /* Find the argument name */
1790 tline = tline->next;
1791 if (tline && tline->type == TOK_WHITESPACE)
1792 tline = tline->next;
1793 if (!tline || tline->type != TOK_ID) {
1794 error(ERR_NONFATAL,
1795 "`%%local' missing argument parameter");
1796 free_tlist(origline);
1797 return DIRECTIVE_FOUND;
1798 }
1799 local = tline->text;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001800
H. Peter Anvine2c80182005-01-15 22:15:51 +00001801 /* Find the argument size type */
1802 tline = tline->next;
1803 if (!tline || tline->type != TOK_OTHER
1804 || tline->text[0] != ':') {
1805 error(ERR_NONFATAL,
1806 "Syntax error processing `%%local' directive");
1807 free_tlist(origline);
1808 return DIRECTIVE_FOUND;
1809 }
1810 tline = tline->next;
1811 if (!tline || tline->type != TOK_ID) {
1812 error(ERR_NONFATAL,
1813 "`%%local' missing size type parameter");
1814 free_tlist(origline);
1815 return DIRECTIVE_FOUND;
1816 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001817
H. Peter Anvine2c80182005-01-15 22:15:51 +00001818 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001819 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001820 tt = expand_smacro(tt);
1821 if (nasm_stricmp(tt->text, "byte") == 0) {
1822 size = MAX(StackSize, 1);
1823 } else if (nasm_stricmp(tt->text, "word") == 0) {
1824 size = MAX(StackSize, 2);
1825 } else if (nasm_stricmp(tt->text, "dword") == 0) {
1826 size = MAX(StackSize, 4);
1827 } else if (nasm_stricmp(tt->text, "qword") == 0) {
1828 size = MAX(StackSize, 8);
1829 } else if (nasm_stricmp(tt->text, "tword") == 0) {
1830 size = MAX(StackSize, 10);
1831 } else {
1832 error(ERR_NONFATAL,
1833 "Invalid size type for `%%local' missing directive");
1834 free_tlist(tt);
1835 free_tlist(origline);
1836 return DIRECTIVE_FOUND;
1837 }
1838 free_tlist(tt);
H. Peter Anvin734b1882002-04-30 21:01:08 +00001839
H. Peter Anvine2c80182005-01-15 22:15:51 +00001840 /* Now define the macro for the argument */
1841 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
1842 local, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001843 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001844 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001845
H. Peter Anvine2c80182005-01-15 22:15:51 +00001846 /* Now define the assign to setup the enter_c macro correctly */
1847 snprintf(directive, sizeof(directive),
1848 "%%assign %%$localsize %%$localsize+%d", size);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001849 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001850
H. Peter Anvine2c80182005-01-15 22:15:51 +00001851 /* Move to the next argument in the list */
1852 tline = tline->next;
1853 if (tline && tline->type == TOK_WHITESPACE)
1854 tline = tline->next;
1855 }
1856 while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
1857 free_tlist(origline);
1858 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001859
H. Peter Anvine2c80182005-01-15 22:15:51 +00001860 case PP_CLEAR:
1861 if (tline->next)
1862 error(ERR_WARNING, "trailing garbage after `%%clear' ignored");
H. Peter Anvin97a23472007-09-16 17:57:25 -07001863 free_macros();
1864 init_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001865 free_tlist(origline);
1866 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001867
H. Peter Anvine2c80182005-01-15 22:15:51 +00001868 case PP_INCLUDE:
1869 tline = tline->next;
1870 skip_white_(tline);
1871 if (!tline || (tline->type != TOK_STRING &&
1872 tline->type != TOK_INTERNAL_STRING)) {
1873 error(ERR_NONFATAL, "`%%include' expects a file name");
1874 free_tlist(origline);
1875 return DIRECTIVE_FOUND; /* but we did _something_ */
1876 }
1877 if (tline->next)
1878 error(ERR_WARNING,
1879 "trailing garbage after `%%include' ignored");
1880 if (tline->type != TOK_INTERNAL_STRING) {
1881 p = tline->text + 1; /* point past the quote to the name */
1882 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
1883 } else
1884 p = tline->text; /* internal_string is easier */
1885 expand_macros_in_string(&p);
1886 inc = nasm_malloc(sizeof(Include));
1887 inc->next = istk;
1888 inc->conds = NULL;
1889 inc->fp = inc_fopen(p);
H. Peter Anvin37a321f2007-09-24 13:41:58 -07001890 if (!inc->fp && pass == 0) {
1891 /* -MG given but file not found */
1892 nasm_free(inc);
1893 } else {
1894 inc->fname = src_set_fname(p);
1895 inc->lineno = src_set_linnum(0);
1896 inc->lineinc = 1;
1897 inc->expansion = NULL;
1898 inc->mstk = NULL;
1899 istk = inc;
1900 list->uplevel(LIST_INCLUDE);
1901 }
1902 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001903 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001904
H. Peter Anvine2c80182005-01-15 22:15:51 +00001905 case PP_PUSH:
1906 tline = tline->next;
1907 skip_white_(tline);
1908 tline = expand_id(tline);
1909 if (!tok_type_(tline, TOK_ID)) {
1910 error(ERR_NONFATAL, "`%%push' expects a context identifier");
1911 free_tlist(origline);
1912 return DIRECTIVE_FOUND; /* but we did _something_ */
1913 }
1914 if (tline->next)
1915 error(ERR_WARNING, "trailing garbage after `%%push' ignored");
1916 ctx = nasm_malloc(sizeof(Context));
1917 ctx->next = cstk;
1918 ctx->localmac = NULL;
1919 ctx->name = nasm_strdup(tline->text);
1920 ctx->number = unique++;
1921 cstk = ctx;
1922 free_tlist(origline);
1923 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001924
H. Peter Anvine2c80182005-01-15 22:15:51 +00001925 case PP_REPL:
1926 tline = tline->next;
1927 skip_white_(tline);
1928 tline = expand_id(tline);
1929 if (!tok_type_(tline, TOK_ID)) {
1930 error(ERR_NONFATAL, "`%%repl' expects a context identifier");
1931 free_tlist(origline);
1932 return DIRECTIVE_FOUND; /* but we did _something_ */
1933 }
1934 if (tline->next)
1935 error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
1936 if (!cstk)
1937 error(ERR_NONFATAL, "`%%repl': context stack is empty");
1938 else {
1939 nasm_free(cstk->name);
1940 cstk->name = nasm_strdup(tline->text);
1941 }
1942 free_tlist(origline);
1943 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001944
H. Peter Anvine2c80182005-01-15 22:15:51 +00001945 case PP_POP:
1946 if (tline->next)
1947 error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
1948 if (!cstk)
1949 error(ERR_NONFATAL, "`%%pop': context stack is already empty");
1950 else
1951 ctx_pop();
1952 free_tlist(origline);
1953 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001954
H. Peter Anvine2c80182005-01-15 22:15:51 +00001955 case PP_ERROR:
1956 tline->next = expand_smacro(tline->next);
1957 tline = tline->next;
1958 skip_white_(tline);
1959 if (tok_type_(tline, TOK_STRING)) {
1960 p = tline->text + 1; /* point past the quote to the name */
1961 p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
1962 expand_macros_in_string(&p);
1963 error(ERR_NONFATAL, "%s", p);
1964 nasm_free(p);
1965 } else {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001966 p = detoken(tline, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001967 error(ERR_WARNING, "%s", p);
1968 nasm_free(p);
1969 }
1970 free_tlist(origline);
1971 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001972
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001973 CASE_PP_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001974 if (istk->conds && !emitting(istk->conds->state))
1975 j = COND_NEVER;
1976 else {
1977 j = if_condition(tline->next, i);
1978 tline->next = NULL; /* it got freed */
1979 free_tlist(origline);
1980 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
1981 }
1982 cond = nasm_malloc(sizeof(Cond));
1983 cond->next = istk->conds;
1984 cond->state = j;
1985 istk->conds = cond;
1986 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001987
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001988 CASE_PP_ELIF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001989 if (!istk->conds)
H. Peter Anvin4169a472007-09-12 01:29:43 +00001990 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001991 if (emitting(istk->conds->state)
1992 || istk->conds->state == COND_NEVER)
1993 istk->conds->state = COND_NEVER;
1994 else {
1995 /*
1996 * IMPORTANT: In the case of %if, we will already have
1997 * called expand_mmac_params(); however, if we're
1998 * processing an %elif we must have been in a
1999 * non-emitting mode, which would have inhibited
2000 * the normal invocation of expand_mmac_params(). Therefore,
2001 * we have to do it explicitly here.
2002 */
2003 j = if_condition(expand_mmac_params(tline->next), i);
2004 tline->next = NULL; /* it got freed */
2005 free_tlist(origline);
2006 istk->conds->state =
2007 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2008 }
2009 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002010
H. Peter Anvine2c80182005-01-15 22:15:51 +00002011 case PP_ELSE:
2012 if (tline->next)
2013 error(ERR_WARNING, "trailing garbage after `%%else' ignored");
2014 if (!istk->conds)
2015 error(ERR_FATAL, "`%%else': no matching `%%if'");
2016 if (emitting(istk->conds->state)
2017 || istk->conds->state == COND_NEVER)
2018 istk->conds->state = COND_ELSE_FALSE;
2019 else
2020 istk->conds->state = COND_ELSE_TRUE;
2021 free_tlist(origline);
2022 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002023
H. Peter Anvine2c80182005-01-15 22:15:51 +00002024 case PP_ENDIF:
2025 if (tline->next)
2026 error(ERR_WARNING, "trailing garbage after `%%endif' ignored");
2027 if (!istk->conds)
2028 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2029 cond = istk->conds;
2030 istk->conds = cond->next;
2031 nasm_free(cond);
2032 free_tlist(origline);
2033 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002034
H. Peter Anvine2c80182005-01-15 22:15:51 +00002035 case PP_MACRO:
2036 case PP_IMACRO:
2037 if (defining)
2038 error(ERR_FATAL,
2039 "`%%%smacro': already defining a macro",
2040 (i == PP_IMACRO ? "i" : ""));
2041 tline = tline->next;
2042 skip_white_(tline);
2043 tline = expand_id(tline);
2044 if (!tok_type_(tline, TOK_ID)) {
2045 error(ERR_NONFATAL,
2046 "`%%%smacro' expects a macro name",
2047 (i == PP_IMACRO ? "i" : ""));
2048 return DIRECTIVE_FOUND;
2049 }
2050 defining = nasm_malloc(sizeof(MMacro));
2051 defining->name = nasm_strdup(tline->text);
2052 defining->casesense = (i == PP_MACRO);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002053 defining->plus = false;
2054 defining->nolist = false;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002055 defining->in_progress = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002056 defining->rep_nest = NULL;
2057 tline = expand_smacro(tline->next);
2058 skip_white_(tline);
2059 if (!tok_type_(tline, TOK_NUMBER)) {
2060 error(ERR_NONFATAL,
2061 "`%%%smacro' expects a parameter count",
2062 (i == PP_IMACRO ? "i" : ""));
2063 defining->nparam_min = defining->nparam_max = 0;
2064 } else {
2065 defining->nparam_min = defining->nparam_max =
H. Peter Anvin70055962007-10-11 00:05:31 -07002066 readnum(tline->text, &err);
2067 if (err)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002068 error(ERR_NONFATAL,
2069 "unable to parse parameter count `%s'", tline->text);
2070 }
2071 if (tline && tok_is_(tline->next, "-")) {
2072 tline = tline->next->next;
2073 if (tok_is_(tline, "*"))
2074 defining->nparam_max = INT_MAX;
2075 else if (!tok_type_(tline, TOK_NUMBER))
2076 error(ERR_NONFATAL,
2077 "`%%%smacro' expects a parameter count after `-'",
2078 (i == PP_IMACRO ? "i" : ""));
2079 else {
H. Peter Anvin70055962007-10-11 00:05:31 -07002080 defining->nparam_max = readnum(tline->text, &err);
2081 if (err)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002082 error(ERR_NONFATAL,
2083 "unable to parse parameter count `%s'",
2084 tline->text);
2085 if (defining->nparam_min > defining->nparam_max)
2086 error(ERR_NONFATAL,
2087 "minimum parameter count exceeds maximum");
2088 }
2089 }
2090 if (tline && tok_is_(tline->next, "+")) {
2091 tline = tline->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002092 defining->plus = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002093 }
2094 if (tline && tok_type_(tline->next, TOK_ID) &&
2095 !nasm_stricmp(tline->next->text, ".nolist")) {
2096 tline = tline->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002097 defining->nolist = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002098 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07002099 mmac = (MMacro *) hash_findix(mmacros, defining->name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002100 while (mmac) {
2101 if (!strcmp(mmac->name, defining->name) &&
2102 (mmac->nparam_min <= defining->nparam_max
2103 || defining->plus)
2104 && (defining->nparam_min <= mmac->nparam_max
2105 || mmac->plus)) {
2106 error(ERR_WARNING,
2107 "redefining multi-line macro `%s'", defining->name);
2108 break;
2109 }
2110 mmac = mmac->next;
2111 }
2112 /*
2113 * Handle default parameters.
2114 */
2115 if (tline && tline->next) {
2116 defining->dlist = tline->next;
2117 tline->next = NULL;
2118 count_mmac_params(defining->dlist, &defining->ndefs,
2119 &defining->defaults);
2120 } else {
2121 defining->dlist = NULL;
2122 defining->defaults = NULL;
2123 }
2124 defining->expansion = NULL;
2125 free_tlist(origline);
2126 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002127
H. Peter Anvine2c80182005-01-15 22:15:51 +00002128 case PP_ENDM:
2129 case PP_ENDMACRO:
2130 if (!defining) {
2131 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2132 return DIRECTIVE_FOUND;
2133 }
H. Peter Anvin97a23472007-09-16 17:57:25 -07002134 mmhead = (MMacro **) hash_findi_add(mmacros, defining->name);
2135 defining->next = *mmhead;
2136 *mmhead = defining;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002137 defining = NULL;
2138 free_tlist(origline);
2139 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002140
H. Peter Anvine2c80182005-01-15 22:15:51 +00002141 case PP_ROTATE:
2142 if (tline->next && tline->next->type == TOK_WHITESPACE)
2143 tline = tline->next;
2144 if (tline->next == NULL) {
2145 free_tlist(origline);
2146 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2147 return DIRECTIVE_FOUND;
2148 }
2149 t = expand_smacro(tline->next);
2150 tline->next = NULL;
2151 free_tlist(origline);
2152 tline = t;
2153 tptr = &t;
2154 tokval.t_type = TOKEN_INVALID;
2155 evalresult =
2156 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2157 free_tlist(tline);
2158 if (!evalresult)
2159 return DIRECTIVE_FOUND;
2160 if (tokval.t_type)
2161 error(ERR_WARNING,
2162 "trailing garbage after expression ignored");
2163 if (!is_simple(evalresult)) {
2164 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2165 return DIRECTIVE_FOUND;
2166 }
2167 mmac = istk->mstk;
2168 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2169 mmac = mmac->next_active;
2170 if (!mmac) {
2171 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2172 } else if (mmac->nparam == 0) {
2173 error(ERR_NONFATAL,
2174 "`%%rotate' invoked within macro without parameters");
2175 } else {
H. Peter Anvin25a99342007-09-22 17:45:45 -07002176 int rotate = mmac->rotate + reloc_value(evalresult);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002177
H. Peter Anvin25a99342007-09-22 17:45:45 -07002178 rotate %= (int)mmac->nparam;
2179 if (rotate < 0)
2180 rotate += mmac->nparam;
2181
2182 mmac->rotate = rotate;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002183 }
2184 return DIRECTIVE_FOUND;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002185
H. Peter Anvine2c80182005-01-15 22:15:51 +00002186 case PP_REP:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002187 nolist = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002188 do {
2189 tline = tline->next;
2190 } while (tok_type_(tline, TOK_WHITESPACE));
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002191
H. Peter Anvine2c80182005-01-15 22:15:51 +00002192 if (tok_type_(tline, TOK_ID) &&
2193 nasm_stricmp(tline->text, ".nolist") == 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002194 nolist = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002195 do {
2196 tline = tline->next;
2197 } while (tok_type_(tline, TOK_WHITESPACE));
2198 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002199
H. Peter Anvine2c80182005-01-15 22:15:51 +00002200 if (tline) {
2201 t = expand_smacro(tline);
2202 tptr = &t;
2203 tokval.t_type = TOKEN_INVALID;
2204 evalresult =
2205 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2206 if (!evalresult) {
2207 free_tlist(origline);
2208 return DIRECTIVE_FOUND;
2209 }
2210 if (tokval.t_type)
2211 error(ERR_WARNING,
2212 "trailing garbage after expression ignored");
2213 if (!is_simple(evalresult)) {
2214 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2215 return DIRECTIVE_FOUND;
2216 }
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002217 count = reloc_value(evalresult) + 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002218 } else {
2219 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002220 count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002221 }
2222 free_tlist(origline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002223
H. Peter Anvine2c80182005-01-15 22:15:51 +00002224 tmp_defining = defining;
2225 defining = nasm_malloc(sizeof(MMacro));
2226 defining->name = NULL; /* flags this macro as a %rep block */
H. Peter Anvin70055962007-10-11 00:05:31 -07002227 defining->casesense = false;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002228 defining->plus = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002229 defining->nolist = nolist;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002230 defining->in_progress = count;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002231 defining->nparam_min = defining->nparam_max = 0;
2232 defining->defaults = NULL;
2233 defining->dlist = NULL;
2234 defining->expansion = NULL;
2235 defining->next_active = istk->mstk;
2236 defining->rep_nest = tmp_defining;
2237 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002238
H. Peter Anvine2c80182005-01-15 22:15:51 +00002239 case PP_ENDREP:
2240 if (!defining || defining->name) {
2241 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2242 return DIRECTIVE_FOUND;
2243 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002244
H. Peter Anvine2c80182005-01-15 22:15:51 +00002245 /*
2246 * Now we have a "macro" defined - although it has no name
2247 * and we won't be entering it in the hash tables - we must
2248 * push a macro-end marker for it on to istk->expansion.
2249 * After that, it will take care of propagating itself (a
2250 * macro-end marker line for a macro which is really a %rep
2251 * block will cause the macro to be re-expanded, complete
2252 * with another macro-end marker to ensure the process
2253 * continues) until the whole expansion is forcibly removed
2254 * from istk->expansion by a %exitrep.
2255 */
2256 l = nasm_malloc(sizeof(Line));
2257 l->next = istk->expansion;
2258 l->finishes = defining;
2259 l->first = NULL;
2260 istk->expansion = l;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002261
H. Peter Anvine2c80182005-01-15 22:15:51 +00002262 istk->mstk = defining;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002263
H. Peter Anvine2c80182005-01-15 22:15:51 +00002264 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2265 tmp_defining = defining;
2266 defining = defining->rep_nest;
2267 free_tlist(origline);
2268 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002269
H. Peter Anvine2c80182005-01-15 22:15:51 +00002270 case PP_EXITREP:
2271 /*
2272 * We must search along istk->expansion until we hit a
2273 * macro-end marker for a macro with no name. Then we set
2274 * its `in_progress' flag to 0.
2275 */
2276 for (l = istk->expansion; l; l = l->next)
2277 if (l->finishes && !l->finishes->name)
2278 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002279
H. Peter Anvine2c80182005-01-15 22:15:51 +00002280 if (l)
2281 l->finishes->in_progress = 0;
2282 else
2283 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2284 free_tlist(origline);
2285 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002286
H. Peter Anvine2c80182005-01-15 22:15:51 +00002287 case PP_XDEFINE:
2288 case PP_IXDEFINE:
2289 case PP_DEFINE:
2290 case PP_IDEFINE:
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002291 casesense = (i == PP_DEFINE || i == PP_IXDEFINE);
2292
H. Peter Anvine2c80182005-01-15 22:15:51 +00002293 tline = tline->next;
2294 skip_white_(tline);
2295 tline = expand_id(tline);
2296 if (!tline || (tline->type != TOK_ID &&
2297 (tline->type != TOK_PREPROC_ID ||
2298 tline->text[1] != '$'))) {
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002299 error(ERR_NONFATAL, "`%s' expects a macro identifier",
2300 pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002301 free_tlist(origline);
2302 return DIRECTIVE_FOUND;
2303 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002304
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002305 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002306
H. Peter Anvine2c80182005-01-15 22:15:51 +00002307 mname = tline->text;
2308 last = tline;
2309 param_start = tline = tline->next;
2310 nparam = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002311
H. Peter Anvine2c80182005-01-15 22:15:51 +00002312 /* Expand the macro definition now for %xdefine and %ixdefine */
2313 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2314 tline = expand_smacro(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002315
H. Peter Anvine2c80182005-01-15 22:15:51 +00002316 if (tok_is_(tline, "(")) {
2317 /*
2318 * This macro has parameters.
2319 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002320
H. Peter Anvine2c80182005-01-15 22:15:51 +00002321 tline = tline->next;
2322 while (1) {
2323 skip_white_(tline);
2324 if (!tline) {
2325 error(ERR_NONFATAL, "parameter identifier expected");
2326 free_tlist(origline);
2327 return DIRECTIVE_FOUND;
2328 }
2329 if (tline->type != TOK_ID) {
2330 error(ERR_NONFATAL,
2331 "`%s': parameter identifier expected",
2332 tline->text);
2333 free_tlist(origline);
2334 return DIRECTIVE_FOUND;
2335 }
2336 tline->type = TOK_SMAC_PARAM + nparam++;
2337 tline = tline->next;
2338 skip_white_(tline);
2339 if (tok_is_(tline, ",")) {
2340 tline = tline->next;
2341 continue;
2342 }
2343 if (!tok_is_(tline, ")")) {
2344 error(ERR_NONFATAL,
2345 "`)' expected to terminate macro template");
2346 free_tlist(origline);
2347 return DIRECTIVE_FOUND;
2348 }
2349 break;
2350 }
2351 last = tline;
2352 tline = tline->next;
2353 }
2354 if (tok_type_(tline, TOK_WHITESPACE))
2355 last = tline, tline = tline->next;
2356 macro_start = NULL;
2357 last->next = NULL;
2358 t = tline;
2359 while (t) {
2360 if (t->type == TOK_ID) {
2361 for (tt = param_start; tt; tt = tt->next)
2362 if (tt->type >= TOK_SMAC_PARAM &&
2363 !strcmp(tt->text, t->text))
2364 t->type = tt->type;
2365 }
2366 tt = t->next;
2367 t->next = macro_start;
2368 macro_start = t;
2369 t = tt;
2370 }
2371 /*
2372 * Good. We now have a macro name, a parameter count, and a
2373 * token list (in reverse order) for an expansion. We ought
2374 * to be OK just to create an SMacro, store it, and let
2375 * free_tlist have the rest of the line (which we have
2376 * carefully re-terminated after chopping off the expansion
2377 * from the end).
2378 */
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002379 if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002380 if (!smac) {
2381 error(ERR_WARNING,
2382 "single-line macro `%s' defined both with and"
2383 " without parameters", mname);
2384 free_tlist(origline);
2385 free_tlist(macro_start);
2386 return DIRECTIVE_FOUND;
2387 } else {
2388 /*
2389 * We're redefining, so we have to take over an
2390 * existing SMacro structure. This means freeing
2391 * what was already in it.
2392 */
2393 nasm_free(smac->name);
2394 free_tlist(smac->expansion);
2395 }
2396 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002397 if (!ctx)
2398 smhead = (SMacro **) hash_findi_add(smacros, mname);
2399 else
2400 smhead = &ctx->localmac;
2401
H. Peter Anvine2c80182005-01-15 22:15:51 +00002402 smac = nasm_malloc(sizeof(SMacro));
2403 smac->next = *smhead;
2404 *smhead = smac;
2405 }
2406 smac->name = nasm_strdup(mname);
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002407 smac->casesense = casesense;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002408 smac->nparam = nparam;
2409 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002410 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002411 free_tlist(origline);
2412 return DIRECTIVE_FOUND;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002413
H. Peter Anvine2c80182005-01-15 22:15:51 +00002414 case PP_UNDEF:
2415 tline = tline->next;
2416 skip_white_(tline);
2417 tline = expand_id(tline);
2418 if (!tline || (tline->type != TOK_ID &&
2419 (tline->type != TOK_PREPROC_ID ||
2420 tline->text[1] != '$'))) {
2421 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2422 free_tlist(origline);
2423 return DIRECTIVE_FOUND;
2424 }
2425 if (tline->next) {
2426 error(ERR_WARNING,
2427 "trailing garbage after macro name ignored");
2428 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002429
H. Peter Anvine2c80182005-01-15 22:15:51 +00002430 /* Find the context that symbol belongs to */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002431 ctx = get_ctx(tline->text, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002432 if (!ctx)
H. Peter Anvin97a23472007-09-16 17:57:25 -07002433 smhead = (SMacro **) hash_findi(smacros, tline->text, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002434 else
2435 smhead = &ctx->localmac;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002436
H. Peter Anvin97a23472007-09-16 17:57:25 -07002437 if (smhead) {
2438 SMacro *s, **sp;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002439
H. Peter Anvin97a23472007-09-16 17:57:25 -07002440 mname = tline->text;
2441 last = tline;
2442 last->next = NULL;
2443
2444 /*
2445 * We now have a macro name... go hunt for it.
2446 */
H. Peter Anvine373efd2007-09-24 21:33:17 -07002447 sp = smhead;
2448 while ((s = *sp) != NULL) {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002449 if (!mstrcmp(s->name, tline->text, s->casesense)) {
2450 *sp = s->next;
2451 nasm_free(s->name);
2452 free_tlist(s->expansion);
2453 nasm_free(s);
H. Peter Anvine373efd2007-09-24 21:33:17 -07002454 } else {
2455 sp = &s->next;
H. Peter Anvin97a23472007-09-16 17:57:25 -07002456 }
2457 }
2458 free_tlist(origline);
2459 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002460 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002461
H. Peter Anvine2c80182005-01-15 22:15:51 +00002462 case PP_STRLEN:
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002463 casesense = true;
2464
H. Peter Anvine2c80182005-01-15 22:15:51 +00002465 tline = tline->next;
2466 skip_white_(tline);
2467 tline = expand_id(tline);
2468 if (!tline || (tline->type != TOK_ID &&
2469 (tline->type != TOK_PREPROC_ID ||
2470 tline->text[1] != '$'))) {
2471 error(ERR_NONFATAL,
2472 "`%%strlen' expects a macro identifier as first parameter");
2473 free_tlist(origline);
2474 return DIRECTIVE_FOUND;
2475 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002476 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002477
H. Peter Anvine2c80182005-01-15 22:15:51 +00002478 mname = tline->text;
2479 last = tline;
2480 tline = expand_smacro(tline->next);
2481 last->next = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002482
H. Peter Anvine2c80182005-01-15 22:15:51 +00002483 t = tline;
2484 while (tok_type_(t, TOK_WHITESPACE))
2485 t = t->next;
2486 /* t should now point to the string */
2487 if (t->type != TOK_STRING) {
2488 error(ERR_NONFATAL,
2489 "`%%strlen` requires string as second parameter");
2490 free_tlist(tline);
2491 free_tlist(origline);
2492 return DIRECTIVE_FOUND;
2493 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002494
H. Peter Anvine2c80182005-01-15 22:15:51 +00002495 macro_start = nasm_malloc(sizeof(*macro_start));
2496 macro_start->next = NULL;
2497 make_tok_num(macro_start, strlen(t->text) - 2);
2498 macro_start->mac = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002499
H. Peter Anvine2c80182005-01-15 22:15:51 +00002500 /*
2501 * We now have a macro name, an implicit parameter count of
2502 * zero, and a numeric token to use as an expansion. Create
2503 * and store an SMacro.
2504 */
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002505 if (smacro_defined(ctx, mname, 0, &smac, casesense)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002506 if (!smac)
2507 error(ERR_WARNING,
2508 "single-line macro `%s' defined both with and"
2509 " without parameters", mname);
2510 else {
2511 /*
2512 * We're redefining, so we have to take over an
2513 * existing SMacro structure. This means freeing
2514 * what was already in it.
2515 */
2516 nasm_free(smac->name);
2517 free_tlist(smac->expansion);
2518 }
2519 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002520 if (!ctx)
2521 smhead = (SMacro **) hash_findi_add(smacros, mname);
2522 else
2523 smhead = &ctx->localmac;
2524
H. Peter Anvine2c80182005-01-15 22:15:51 +00002525 smac = nasm_malloc(sizeof(SMacro));
2526 smac->next = *smhead;
2527 *smhead = smac;
2528 }
2529 smac->name = nasm_strdup(mname);
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002530 smac->casesense = casesense;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002531 smac->nparam = 0;
2532 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002533 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002534 free_tlist(tline);
2535 free_tlist(origline);
2536 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002537
H. Peter Anvine2c80182005-01-15 22:15:51 +00002538 case PP_SUBSTR:
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002539 casesense = true;
2540
H. Peter Anvine2c80182005-01-15 22:15:51 +00002541 tline = tline->next;
2542 skip_white_(tline);
2543 tline = expand_id(tline);
2544 if (!tline || (tline->type != TOK_ID &&
2545 (tline->type != TOK_PREPROC_ID ||
2546 tline->text[1] != '$'))) {
2547 error(ERR_NONFATAL,
2548 "`%%substr' expects a macro identifier as first parameter");
2549 free_tlist(origline);
2550 return DIRECTIVE_FOUND;
2551 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002552 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002553
H. Peter Anvine2c80182005-01-15 22:15:51 +00002554 mname = tline->text;
2555 last = tline;
2556 tline = expand_smacro(tline->next);
2557 last->next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002558
H. Peter Anvine2c80182005-01-15 22:15:51 +00002559 t = tline->next;
2560 while (tok_type_(t, TOK_WHITESPACE))
2561 t = t->next;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002562
H. Peter Anvine2c80182005-01-15 22:15:51 +00002563 /* t should now point to the string */
2564 if (t->type != TOK_STRING) {
2565 error(ERR_NONFATAL,
2566 "`%%substr` requires string as second parameter");
2567 free_tlist(tline);
2568 free_tlist(origline);
2569 return DIRECTIVE_FOUND;
2570 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002571
H. Peter Anvine2c80182005-01-15 22:15:51 +00002572 tt = t->next;
2573 tptr = &tt;
2574 tokval.t_type = TOKEN_INVALID;
2575 evalresult =
2576 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2577 if (!evalresult) {
2578 free_tlist(tline);
2579 free_tlist(origline);
2580 return DIRECTIVE_FOUND;
2581 }
2582 if (!is_simple(evalresult)) {
2583 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
2584 free_tlist(tline);
2585 free_tlist(origline);
2586 return DIRECTIVE_FOUND;
2587 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002588
H. Peter Anvine2c80182005-01-15 22:15:51 +00002589 macro_start = nasm_malloc(sizeof(*macro_start));
2590 macro_start->next = NULL;
2591 macro_start->text = nasm_strdup("'''");
2592 if (evalresult->value > 0
2593 && evalresult->value < strlen(t->text) - 1) {
2594 macro_start->text[1] = t->text[evalresult->value];
2595 } else {
2596 macro_start->text[2] = '\0';
2597 }
2598 macro_start->type = TOK_STRING;
2599 macro_start->mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002600
H. Peter Anvine2c80182005-01-15 22:15:51 +00002601 /*
2602 * We now have a macro name, an implicit parameter count of
2603 * zero, and a numeric token to use as an expansion. Create
2604 * and store an SMacro.
2605 */
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002606 if (smacro_defined(ctx, mname, 0, &smac, casesense)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002607 if (!smac)
2608 error(ERR_WARNING,
2609 "single-line macro `%s' defined both with and"
2610 " without parameters", mname);
2611 else {
2612 /*
2613 * We're redefining, so we have to take over an
2614 * existing SMacro structure. This means freeing
2615 * what was already in it.
2616 */
2617 nasm_free(smac->name);
2618 free_tlist(smac->expansion);
2619 }
2620 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002621 if (!ctx)
2622 smhead = (SMacro **) hash_findi_add(smacros, tline->text);
2623 else
2624 smhead = &ctx->localmac;
2625
H. Peter Anvine2c80182005-01-15 22:15:51 +00002626 smac = nasm_malloc(sizeof(SMacro));
2627 smac->next = *smhead;
2628 *smhead = smac;
2629 }
2630 smac->name = nasm_strdup(mname);
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002631 smac->casesense = casesense;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002632 smac->nparam = 0;
2633 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002634 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002635 free_tlist(tline);
2636 free_tlist(origline);
2637 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002638
H. Peter Anvine2c80182005-01-15 22:15:51 +00002639 case PP_ASSIGN:
2640 case PP_IASSIGN:
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002641 casesense = (i == PP_ASSIGN);
2642
H. Peter Anvine2c80182005-01-15 22:15:51 +00002643 tline = tline->next;
2644 skip_white_(tline);
2645 tline = expand_id(tline);
2646 if (!tline || (tline->type != TOK_ID &&
2647 (tline->type != TOK_PREPROC_ID ||
2648 tline->text[1] != '$'))) {
2649 error(ERR_NONFATAL,
2650 "`%%%sassign' expects a macro identifier",
2651 (i == PP_IASSIGN ? "i" : ""));
2652 free_tlist(origline);
2653 return DIRECTIVE_FOUND;
2654 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002655 ctx = get_ctx(tline->text, false);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002656
H. Peter Anvine2c80182005-01-15 22:15:51 +00002657 mname = tline->text;
2658 last = tline;
2659 tline = expand_smacro(tline->next);
2660 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002661
H. Peter Anvine2c80182005-01-15 22:15:51 +00002662 t = tline;
2663 tptr = &t;
2664 tokval.t_type = TOKEN_INVALID;
2665 evalresult =
2666 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2667 free_tlist(tline);
2668 if (!evalresult) {
2669 free_tlist(origline);
2670 return DIRECTIVE_FOUND;
2671 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002672
H. Peter Anvine2c80182005-01-15 22:15:51 +00002673 if (tokval.t_type)
2674 error(ERR_WARNING,
2675 "trailing garbage after expression ignored");
H. Peter Anvin734b1882002-04-30 21:01:08 +00002676
H. Peter Anvine2c80182005-01-15 22:15:51 +00002677 if (!is_simple(evalresult)) {
2678 error(ERR_NONFATAL,
2679 "non-constant value given to `%%%sassign'",
2680 (i == PP_IASSIGN ? "i" : ""));
2681 free_tlist(origline);
2682 return DIRECTIVE_FOUND;
2683 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002684
H. Peter Anvine2c80182005-01-15 22:15:51 +00002685 macro_start = nasm_malloc(sizeof(*macro_start));
2686 macro_start->next = NULL;
2687 make_tok_num(macro_start, reloc_value(evalresult));
2688 macro_start->mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002689
H. Peter Anvine2c80182005-01-15 22:15:51 +00002690 /*
2691 * We now have a macro name, an implicit parameter count of
2692 * zero, and a numeric token to use as an expansion. Create
2693 * and store an SMacro.
2694 */
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002695 if (smacro_defined(ctx, mname, 0, &smac, casesense)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002696 if (!smac)
2697 error(ERR_WARNING,
2698 "single-line macro `%s' defined both with and"
2699 " without parameters", mname);
2700 else {
2701 /*
2702 * We're redefining, so we have to take over an
2703 * existing SMacro structure. This means freeing
2704 * what was already in it.
2705 */
2706 nasm_free(smac->name);
2707 free_tlist(smac->expansion);
2708 }
2709 } else {
H. Peter Anvin97a23472007-09-16 17:57:25 -07002710 if (!ctx)
2711 smhead = (SMacro **) hash_findi_add(smacros, mname);
2712 else
2713 smhead = &ctx->localmac;
2714
H. Peter Anvine2c80182005-01-15 22:15:51 +00002715 smac = nasm_malloc(sizeof(SMacro));
2716 smac->next = *smhead;
2717 *smhead = smac;
2718 }
2719 smac->name = nasm_strdup(mname);
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002720 smac->casesense = casesense;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002721 smac->nparam = 0;
2722 smac->expansion = macro_start;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002723 smac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002724 free_tlist(origline);
2725 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002726
H. Peter Anvine2c80182005-01-15 22:15:51 +00002727 case PP_LINE:
2728 /*
2729 * Syntax is `%line nnn[+mmm] [filename]'
2730 */
2731 tline = tline->next;
2732 skip_white_(tline);
2733 if (!tok_type_(tline, TOK_NUMBER)) {
2734 error(ERR_NONFATAL, "`%%line' expects line number");
2735 free_tlist(origline);
2736 return DIRECTIVE_FOUND;
2737 }
H. Peter Anvin70055962007-10-11 00:05:31 -07002738 k = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002739 m = 1;
2740 tline = tline->next;
2741 if (tok_is_(tline, "+")) {
2742 tline = tline->next;
2743 if (!tok_type_(tline, TOK_NUMBER)) {
2744 error(ERR_NONFATAL, "`%%line' expects line increment");
2745 free_tlist(origline);
2746 return DIRECTIVE_FOUND;
2747 }
H. Peter Anvin70055962007-10-11 00:05:31 -07002748 m = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002749 tline = tline->next;
2750 }
2751 skip_white_(tline);
2752 src_set_linnum(k);
2753 istk->lineinc = m;
2754 if (tline) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002755 nasm_free(src_set_fname(detoken(tline, false)));
H. Peter Anvine2c80182005-01-15 22:15:51 +00002756 }
2757 free_tlist(origline);
2758 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002759
H. Peter Anvine2c80182005-01-15 22:15:51 +00002760 default:
2761 error(ERR_FATAL,
2762 "preprocessor directive `%s' not yet implemented",
H. Peter Anvin4169a472007-09-12 01:29:43 +00002763 pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002764 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002765 }
Ed Beroset3ab3f412002-06-11 03:31:49 +00002766 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002767}
2768
2769/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002770 * Ensure that a macro parameter contains a condition code and
2771 * nothing else. Return the condition code index if so, or -1
2772 * otherwise.
2773 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002774static int find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002775{
H. Peter Anvin76690a12002-04-30 20:52:49 +00002776 Token *tt;
2777 int i, j, k, m;
2778
H. Peter Anvin25a99342007-09-22 17:45:45 -07002779 if (!t)
2780 return -1; /* Probably a %+ without a space */
2781
H. Peter Anvineba20a72002-04-30 20:53:55 +00002782 skip_white_(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002783 if (t->type != TOK_ID)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002784 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002785 tt = t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002786 skip_white_(tt);
H. Peter Anvin76690a12002-04-30 20:52:49 +00002787 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002788 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002789
2790 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +00002791 j = elements(conditions);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002792 while (j - i > 1) {
2793 k = (j + i) / 2;
2794 m = nasm_stricmp(t->text, conditions[k]);
2795 if (m == 0) {
2796 i = k;
2797 j = -2;
2798 break;
2799 } else if (m < 0) {
2800 j = k;
2801 } else
2802 i = k;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002803 }
2804 if (j != -2)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002805 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002806 return i;
2807}
2808
2809/*
2810 * Expand MMacro-local things: parameter references (%0, %n, %+n,
2811 * %-n) and MMacro-local identifiers (%%foo).
2812 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002813static Token *expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002814{
H. Peter Anvin734b1882002-04-30 21:01:08 +00002815 Token *t, *tt, **tail, *thead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002816
2817 tail = &thead;
2818 thead = NULL;
2819
H. Peter Anvine2c80182005-01-15 22:15:51 +00002820 while (tline) {
2821 if (tline->type == TOK_PREPROC_ID &&
2822 (((tline->text[1] == '+' || tline->text[1] == '-')
2823 && tline->text[2]) || tline->text[1] == '%'
2824 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002825 char *text = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002826 int type = 0, cc; /* type = 0 to placate optimisers */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002827 char tmpbuf[30];
H. Peter Anvin25a99342007-09-22 17:45:45 -07002828 unsigned int n;
2829 int i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002830 MMacro *mac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002831
H. Peter Anvine2c80182005-01-15 22:15:51 +00002832 t = tline;
2833 tline = tline->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002834
H. Peter Anvine2c80182005-01-15 22:15:51 +00002835 mac = istk->mstk;
2836 while (mac && !mac->name) /* avoid mistaking %reps for macros */
2837 mac = mac->next_active;
2838 if (!mac)
2839 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
2840 else
2841 switch (t->text[1]) {
2842 /*
2843 * We have to make a substitution of one of the
2844 * forms %1, %-1, %+1, %%foo, %0.
2845 */
2846 case '0':
2847 type = TOK_NUMBER;
2848 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
2849 text = nasm_strdup(tmpbuf);
2850 break;
2851 case '%':
2852 type = TOK_ID;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002853 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
H. Peter Anvine2c80182005-01-15 22:15:51 +00002854 mac->unique);
2855 text = nasm_strcat(tmpbuf, t->text + 2);
2856 break;
2857 case '-':
2858 n = atoi(t->text + 2) - 1;
2859 if (n >= mac->nparam)
2860 tt = NULL;
2861 else {
2862 if (mac->nparam > 1)
2863 n = (n + mac->rotate) % mac->nparam;
2864 tt = mac->params[n];
2865 }
2866 cc = find_cc(tt);
2867 if (cc == -1) {
2868 error(ERR_NONFATAL,
2869 "macro parameter %d is not a condition code",
2870 n + 1);
2871 text = NULL;
2872 } else {
2873 type = TOK_ID;
2874 if (inverse_ccs[cc] == -1) {
2875 error(ERR_NONFATAL,
2876 "condition code `%s' is not invertible",
2877 conditions[cc]);
2878 text = NULL;
2879 } else
2880 text =
2881 nasm_strdup(conditions[inverse_ccs[cc]]);
2882 }
2883 break;
2884 case '+':
2885 n = atoi(t->text + 2) - 1;
2886 if (n >= mac->nparam)
2887 tt = NULL;
2888 else {
2889 if (mac->nparam > 1)
2890 n = (n + mac->rotate) % mac->nparam;
2891 tt = mac->params[n];
2892 }
2893 cc = find_cc(tt);
2894 if (cc == -1) {
2895 error(ERR_NONFATAL,
2896 "macro parameter %d is not a condition code",
2897 n + 1);
2898 text = NULL;
2899 } else {
2900 type = TOK_ID;
2901 text = nasm_strdup(conditions[cc]);
2902 }
2903 break;
2904 default:
2905 n = atoi(t->text + 1) - 1;
2906 if (n >= mac->nparam)
2907 tt = NULL;
2908 else {
2909 if (mac->nparam > 1)
2910 n = (n + mac->rotate) % mac->nparam;
2911 tt = mac->params[n];
2912 }
2913 if (tt) {
2914 for (i = 0; i < mac->paramlen[n]; i++) {
2915 *tail = new_Token(NULL, tt->type, tt->text, 0);
2916 tail = &(*tail)->next;
2917 tt = tt->next;
2918 }
2919 }
2920 text = NULL; /* we've done it here */
2921 break;
2922 }
2923 if (!text) {
2924 delete_Token(t);
2925 } else {
2926 *tail = t;
2927 tail = &t->next;
2928 t->type = type;
2929 nasm_free(t->text);
2930 t->text = text;
2931 t->mac = NULL;
2932 }
2933 continue;
2934 } else {
2935 t = *tail = tline;
2936 tline = tline->next;
2937 t->mac = NULL;
2938 tail = &t->next;
2939 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00002940 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00002941 *tail = NULL;
2942 t = thead;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002943 for (; t && (tt = t->next) != NULL; t = t->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002944 switch (t->type) {
2945 case TOK_WHITESPACE:
2946 if (tt->type == TOK_WHITESPACE) {
2947 t->next = delete_Token(tt);
2948 }
2949 break;
2950 case TOK_ID:
2951 if (tt->type == TOK_ID || tt->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002952 char *tmp = nasm_strcat(t->text, tt->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002953 nasm_free(t->text);
2954 t->text = tmp;
2955 t->next = delete_Token(tt);
2956 }
2957 break;
2958 case TOK_NUMBER:
2959 if (tt->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002960 char *tmp = nasm_strcat(t->text, tt->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002961 nasm_free(t->text);
2962 t->text = tmp;
2963 t->next = delete_Token(tt);
2964 }
2965 break;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002966 default:
2967 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002968 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002969
H. Peter Anvin76690a12002-04-30 20:52:49 +00002970 return thead;
2971}
2972
2973/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002974 * Expand all single-line macro calls made in the given line.
2975 * Return the expanded version of the line. The original is deemed
2976 * to be destroyed in the process. (In reality we'll just move
2977 * Tokens from input to output a lot of the time, rather than
2978 * actually bothering to destroy and replicate.)
2979 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002980static Token *expand_smacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002981{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002982 Token *t, *tt, *mstart, **tail, *thead;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002983 SMacro *head = NULL, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002984 Token **params;
2985 int *paramsize;
H. Peter Anvin25a99342007-09-22 17:45:45 -07002986 unsigned int nparam, sparam;
2987 int brackets, rescan;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002988 Token *org_tline = tline;
2989 Context *ctx;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002990 char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002991
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002992 /*
2993 * Trick: we should avoid changing the start token pointer since it can
2994 * be contained in "next" field of other token. Because of this
2995 * we allocate a copy of first token and work with it; at the end of
2996 * routine we copy it back
2997 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002998 if (org_tline) {
2999 tline =
3000 new_Token(org_tline->next, org_tline->type, org_tline->text,
3001 0);
3002 tline->mac = org_tline->mac;
3003 nasm_free(org_tline->text);
3004 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003005 }
3006
H. Peter Anvin734b1882002-04-30 21:01:08 +00003007 again:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003008 tail = &thead;
3009 thead = NULL;
3010
H. Peter Anvine2c80182005-01-15 22:15:51 +00003011 while (tline) { /* main token loop */
3012 if ((mname = tline->text)) {
3013 /* if this token is a local macro, look in local context */
3014 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003015 ctx = get_ctx(mname, true);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003016 else
3017 ctx = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003018 if (!ctx) {
3019 head = (SMacro *) hash_findix(smacros, mname);
3020 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003021 head = ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003022 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00003023 /*
3024 * We've hit an identifier. As in is_mmacro below, we first
3025 * check whether the identifier is a single-line macro at
3026 * all, then think about checking for parameters if
3027 * necessary.
3028 */
H. Peter Anvin97a23472007-09-16 17:57:25 -07003029 for (m = head; m; m = m->next)
3030 if (!mstrcmp(m->name, mname, m->casesense))
3031 break;
3032 if (m) {
3033 mstart = tline;
3034 params = NULL;
3035 paramsize = NULL;
3036 if (m->nparam == 0) {
3037 /*
3038 * Simple case: the macro is parameterless. Discard the
3039 * one token that the macro call took, and push the
3040 * expansion back on the to-do stack.
3041 */
3042 if (!m->expansion) {
3043 if (!strcmp("__FILE__", m->name)) {
3044 int32_t num = 0;
3045 src_get(&num, &(tline->text));
3046 nasm_quote(&(tline->text));
3047 tline->type = TOK_STRING;
3048 continue;
3049 }
3050 if (!strcmp("__LINE__", m->name)) {
3051 nasm_free(tline->text);
3052 make_tok_num(tline, src_get_linnum());
3053 continue;
3054 }
3055 if (!strcmp("__BITS__", m->name)) {
3056 nasm_free(tline->text);
3057 make_tok_num(tline, globalbits);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003058 continue;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003059 }
3060 tline = delete_Token(tline);
3061 continue;
3062 }
3063 } else {
3064 /*
3065 * Complicated case: at least one macro with this name
H. Peter Anvine2c80182005-01-15 22:15:51 +00003066 * exists and takes parameters. We must find the
3067 * parameters in the call, count them, find the SMacro
3068 * that corresponds to that form of the macro call, and
3069 * substitute for the parameters when we expand. What a
3070 * pain.
3071 */
3072 /*tline = tline->next;
3073 skip_white_(tline); */
3074 do {
3075 t = tline->next;
3076 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003077 t->mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003078 t->text = NULL;
3079 t = tline->next = delete_Token(t);
3080 }
3081 tline = t;
3082 } while (tok_type_(tline, TOK_WHITESPACE));
3083 if (!tok_is_(tline, "(")) {
3084 /*
3085 * This macro wasn't called with parameters: ignore
3086 * the call. (Behaviour borrowed from gnu cpp.)
3087 */
3088 tline = mstart;
3089 m = NULL;
3090 } else {
3091 int paren = 0;
3092 int white = 0;
3093 brackets = 0;
3094 nparam = 0;
3095 sparam = PARAM_DELTA;
3096 params = nasm_malloc(sparam * sizeof(Token *));
3097 params[0] = tline->next;
3098 paramsize = nasm_malloc(sparam * sizeof(int));
3099 paramsize[0] = 0;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003100 while (true) { /* parameter loop */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003101 /*
3102 * For some unusual expansions
3103 * which concatenates function call
3104 */
3105 t = tline->next;
3106 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003107 t->mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003108 t->text = NULL;
3109 t = tline->next = delete_Token(t);
3110 }
3111 tline = t;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003112
H. Peter Anvine2c80182005-01-15 22:15:51 +00003113 if (!tline) {
3114 error(ERR_NONFATAL,
3115 "macro call expects terminating `)'");
3116 break;
3117 }
3118 if (tline->type == TOK_WHITESPACE
3119 && brackets <= 0) {
3120 if (paramsize[nparam])
3121 white++;
3122 else
3123 params[nparam] = tline->next;
3124 continue; /* parameter loop */
3125 }
3126 if (tline->type == TOK_OTHER
3127 && tline->text[1] == 0) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003128 char ch = tline->text[0];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003129 if (ch == ',' && !paren && brackets <= 0) {
3130 if (++nparam >= sparam) {
3131 sparam += PARAM_DELTA;
3132 params = nasm_realloc(params,
3133 sparam *
3134 sizeof(Token
3135 *));
3136 paramsize =
3137 nasm_realloc(paramsize,
3138 sparam *
3139 sizeof(int));
3140 }
3141 params[nparam] = tline->next;
3142 paramsize[nparam] = 0;
3143 white = 0;
3144 continue; /* parameter loop */
3145 }
3146 if (ch == '{' &&
3147 (brackets > 0 || (brackets == 0 &&
3148 !paramsize[nparam])))
3149 {
3150 if (!(brackets++)) {
3151 params[nparam] = tline->next;
3152 continue; /* parameter loop */
3153 }
3154 }
3155 if (ch == '}' && brackets > 0)
3156 if (--brackets == 0) {
3157 brackets = -1;
3158 continue; /* parameter loop */
3159 }
3160 if (ch == '(' && !brackets)
3161 paren++;
3162 if (ch == ')' && brackets <= 0)
3163 if (--paren < 0)
3164 break;
3165 }
3166 if (brackets < 0) {
3167 brackets = 0;
3168 error(ERR_NONFATAL, "braces do not "
3169 "enclose all of macro parameter");
3170 }
3171 paramsize[nparam] += white + 1;
3172 white = 0;
3173 } /* parameter loop */
3174 nparam++;
3175 while (m && (m->nparam != nparam ||
3176 mstrcmp(m->name, mname,
3177 m->casesense)))
3178 m = m->next;
3179 if (!m)
3180 error(ERR_WARNING | ERR_WARN_MNP,
3181 "macro `%s' exists, "
3182 "but not taking %d parameters",
3183 mstart->text, nparam);
3184 }
3185 }
3186 if (m && m->in_progress)
3187 m = NULL;
3188 if (!m) { /* in progess or didn't find '(' or wrong nparam */
3189 /*
3190 * Design question: should we handle !tline, which
3191 * indicates missing ')' here, or expand those
3192 * macros anyway, which requires the (t) test a few
3193 * lines down?
3194 */
3195 nasm_free(params);
3196 nasm_free(paramsize);
3197 tline = mstart;
3198 } else {
3199 /*
3200 * Expand the macro: we are placed on the last token of the
3201 * call, so that we can easily split the call from the
3202 * following tokens. We also start by pushing an SMAC_END
3203 * token for the cycle removal.
3204 */
3205 t = tline;
3206 if (t) {
3207 tline = t->next;
3208 t->next = NULL;
3209 }
3210 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
3211 tt->mac = m;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003212 m->in_progress = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003213 tline = tt;
3214 for (t = m->expansion; t; t = t->next) {
3215 if (t->type >= TOK_SMAC_PARAM) {
3216 Token *pcopy = tline, **ptail = &pcopy;
3217 Token *ttt, *pt;
3218 int i;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003219
H. Peter Anvine2c80182005-01-15 22:15:51 +00003220 ttt = params[t->type - TOK_SMAC_PARAM];
3221 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3222 --i >= 0;) {
3223 pt = *ptail =
3224 new_Token(tline, ttt->type, ttt->text,
3225 0);
3226 ptail = &pt->next;
3227 ttt = ttt->next;
3228 }
3229 tline = pcopy;
3230 } else {
3231 tt = new_Token(tline, t->type, t->text, 0);
3232 tline = tt;
3233 }
3234 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003235
H. Peter Anvine2c80182005-01-15 22:15:51 +00003236 /*
3237 * Having done that, get rid of the macro call, and clean
3238 * up the parameters.
3239 */
3240 nasm_free(params);
3241 nasm_free(paramsize);
3242 free_tlist(mstart);
3243 continue; /* main token loop */
3244 }
3245 }
3246 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003247
H. Peter Anvine2c80182005-01-15 22:15:51 +00003248 if (tline->type == TOK_SMAC_END) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003249 tline->mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003250 tline = delete_Token(tline);
3251 } else {
3252 t = *tail = tline;
3253 tline = tline->next;
3254 t->mac = NULL;
3255 t->next = NULL;
3256 tail = &t->next;
3257 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003258 }
3259
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003260 /*
3261 * Now scan the entire line and look for successive TOK_IDs that resulted
Keith Kaniosb7a89542007-04-12 02:40:54 +00003262 * after expansion (they can't be produced by tokenize()). The successive
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003263 * TOK_IDs should be concatenated.
3264 * Also we look for %+ tokens and concatenate the tokens before and after
3265 * them (without white spaces in between).
3266 */
3267 t = thead;
3268 rescan = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003269 while (t) {
3270 while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
3271 t = t->next;
3272 if (!t || !t->next)
3273 break;
3274 if (t->next->type == TOK_ID ||
3275 t->next->type == TOK_PREPROC_ID ||
3276 t->next->type == TOK_NUMBER) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003277 char *p = nasm_strcat(t->text, t->next->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003278 nasm_free(t->text);
3279 t->next = delete_Token(t->next);
3280 t->text = p;
3281 rescan = 1;
3282 } else if (t->next->type == TOK_WHITESPACE && t->next->next &&
3283 t->next->next->type == TOK_PREPROC_ID &&
3284 strcmp(t->next->next->text, "%+") == 0) {
3285 /* free the next whitespace, the %+ token and next whitespace */
3286 int i;
3287 for (i = 1; i <= 3; i++) {
3288 if (!t->next
3289 || (i != 2 && t->next->type != TOK_WHITESPACE))
3290 break;
3291 t->next = delete_Token(t->next);
3292 } /* endfor */
3293 } else
3294 t = t->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003295 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003296 /* If we concatenaded something, re-scan the line for macros */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003297 if (rescan) {
3298 tline = thead;
3299 goto again;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003300 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003301
H. Peter Anvine2c80182005-01-15 22:15:51 +00003302 if (org_tline) {
3303 if (thead) {
3304 *org_tline = *thead;
3305 /* since we just gave text to org_line, don't free it */
3306 thead->text = NULL;
3307 delete_Token(thead);
3308 } else {
3309 /* the expression expanded to empty line;
3310 we can't return NULL for some reasons
3311 we just set the line to a single WHITESPACE token. */
3312 memset(org_tline, 0, sizeof(*org_tline));
3313 org_tline->text = NULL;
3314 org_tline->type = TOK_WHITESPACE;
3315 }
3316 thead = org_tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003317 }
3318
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003319 return thead;
3320}
3321
3322/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003323 * Similar to expand_smacro but used exclusively with macro identifiers
3324 * right before they are fetched in. The reason is that there can be
3325 * identifiers consisting of several subparts. We consider that if there
3326 * are more than one element forming the name, user wants a expansion,
3327 * otherwise it will be left as-is. Example:
3328 *
3329 * %define %$abc cde
3330 *
3331 * the identifier %$abc will be left as-is so that the handler for %define
3332 * will suck it and define the corresponding value. Other case:
3333 *
3334 * %define _%$abc cde
3335 *
3336 * In this case user wants name to be expanded *before* %define starts
3337 * working, so we'll expand %$abc into something (if it has a value;
3338 * otherwise it will be left as-is) then concatenate all successive
3339 * PP_IDs into one.
3340 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003341static Token *expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003342{
3343 Token *cur, *oldnext = NULL;
3344
H. Peter Anvin734b1882002-04-30 21:01:08 +00003345 if (!tline || !tline->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003346 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003347
3348 cur = tline;
3349 while (cur->next &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00003350 (cur->next->type == TOK_ID ||
3351 cur->next->type == TOK_PREPROC_ID
3352 || cur->next->type == TOK_NUMBER))
3353 cur = cur->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003354
3355 /* If identifier consists of just one token, don't expand */
3356 if (cur == tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003357 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003358
H. Peter Anvine2c80182005-01-15 22:15:51 +00003359 if (cur) {
3360 oldnext = cur->next; /* Detach the tail past identifier */
3361 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003362 }
3363
H. Peter Anvin734b1882002-04-30 21:01:08 +00003364 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003365
H. Peter Anvine2c80182005-01-15 22:15:51 +00003366 if (cur) {
3367 /* expand_smacro possibly changhed tline; re-scan for EOL */
3368 cur = tline;
3369 while (cur && cur->next)
3370 cur = cur->next;
3371 if (cur)
3372 cur->next = oldnext;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003373 }
3374
3375 return tline;
3376}
3377
3378/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003379 * Determine whether the given line constitutes a multi-line macro
3380 * call, and return the MMacro structure called if so. Doesn't have
3381 * to check for an initial label - that's taken care of in
3382 * expand_mmacro - but must check numbers of parameters. Guaranteed
3383 * to be called with tline->type == TOK_ID, so the putative macro
3384 * name is easy to find.
3385 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003386static MMacro *is_mmacro(Token * tline, Token *** params_array)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003387{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003388 MMacro *head, *m;
3389 Token **params;
3390 int nparam;
3391
H. Peter Anvin97a23472007-09-16 17:57:25 -07003392 head = (MMacro *) hash_findix(mmacros, tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003393
3394 /*
3395 * Efficiency: first we see if any macro exists with the given
3396 * name. If not, we can return NULL immediately. _Then_ we
3397 * count the parameters, and then we look further along the
3398 * list if necessary to find the proper MMacro.
3399 */
3400 for (m = head; m; m = m->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003401 if (!mstrcmp(m->name, tline->text, m->casesense))
3402 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003403 if (!m)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003404 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003405
3406 /*
3407 * OK, we have a potential macro. Count and demarcate the
3408 * parameters.
3409 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003410 count_mmac_params(tline->next, &nparam, &params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003411
3412 /*
3413 * So we know how many parameters we've got. Find the MMacro
3414 * structure that handles this number.
3415 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003416 while (m) {
3417 if (m->nparam_min <= nparam
3418 && (m->plus || nparam <= m->nparam_max)) {
3419 /*
3420 * This one is right. Just check if cycle removal
3421 * prohibits us using it before we actually celebrate...
3422 */
3423 if (m->in_progress) {
H. Peter Anvineba20a72002-04-30 20:53:55 +00003424#if 0
H. Peter Anvine2c80182005-01-15 22:15:51 +00003425 error(ERR_NONFATAL,
3426 "self-reference in multi-line macro `%s'", m->name);
H. Peter Anvineba20a72002-04-30 20:53:55 +00003427#endif
H. Peter Anvine2c80182005-01-15 22:15:51 +00003428 nasm_free(params);
3429 return NULL;
3430 }
3431 /*
3432 * It's right, and we can use it. Add its default
3433 * parameters to the end of our list if necessary.
3434 */
3435 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
3436 params =
3437 nasm_realloc(params,
3438 ((m->nparam_min + m->ndefs +
3439 1) * sizeof(*params)));
3440 while (nparam < m->nparam_min + m->ndefs) {
3441 params[nparam] = m->defaults[nparam - m->nparam_min];
3442 nparam++;
3443 }
3444 }
3445 /*
3446 * If we've gone over the maximum parameter count (and
3447 * we're in Plus mode), ignore parameters beyond
3448 * nparam_max.
3449 */
3450 if (m->plus && nparam > m->nparam_max)
3451 nparam = m->nparam_max;
3452 /*
3453 * Then terminate the parameter list, and leave.
3454 */
3455 if (!params) { /* need this special case */
3456 params = nasm_malloc(sizeof(*params));
3457 nparam = 0;
3458 }
3459 params[nparam] = NULL;
3460 *params_array = params;
3461 return m;
3462 }
3463 /*
3464 * This one wasn't right: look for the next one with the
3465 * same name.
3466 */
3467 for (m = m->next; m; m = m->next)
3468 if (!mstrcmp(m->name, tline->text, m->casesense))
3469 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003470 }
3471
3472 /*
3473 * After all that, we didn't find one with the right number of
3474 * parameters. Issue a warning, and fail to expand the macro.
3475 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00003476 error(ERR_WARNING | ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003477 "macro `%s' exists, but not taking %d parameters",
3478 tline->text, nparam);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003479 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003480 return NULL;
3481}
3482
3483/*
3484 * Expand the multi-line macro call made by the given line, if
3485 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvineba20a72002-04-30 20:53:55 +00003486 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003487 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003488static int expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003489{
3490 Token *startline = tline;
3491 Token *label = NULL;
3492 int dont_prepend = 0;
3493 Token **params, *t, *tt;
3494 MMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003495 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003496 int i, nparam, *paramlen;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003497
3498 t = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003499 skip_white_(t);
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00003500/* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
3501 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003502 return 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003503 m = is_mmacro(t, &params);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003504 if (!m) {
3505 Token *last;
3506 /*
3507 * We have an id which isn't a macro call. We'll assume
3508 * it might be a label; we'll also check to see if a
3509 * colon follows it. Then, if there's another id after
3510 * that lot, we'll check it again for macro-hood.
3511 */
3512 label = last = t;
3513 t = t->next;
3514 if (tok_type_(t, TOK_WHITESPACE))
3515 last = t, t = t->next;
3516 if (tok_is_(t, ":")) {
3517 dont_prepend = 1;
3518 last = t, t = t->next;
3519 if (tok_type_(t, TOK_WHITESPACE))
3520 last = t, t = t->next;
3521 }
3522 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
3523 return 0;
3524 last->next = NULL;
3525 tline = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003526 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003527
3528 /*
3529 * Fix up the parameters: this involves stripping leading and
3530 * trailing whitespace, then stripping braces if they are
3531 * present.
3532 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003533 for (nparam = 0; params[nparam]; nparam++) ;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003534 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003535
H. Peter Anvine2c80182005-01-15 22:15:51 +00003536 for (i = 0; params[i]; i++) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003537 int brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003538 int comma = (!m->plus || i < nparam - 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003539
H. Peter Anvine2c80182005-01-15 22:15:51 +00003540 t = params[i];
3541 skip_white_(t);
3542 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003543 t = t->next, brace = true, comma = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003544 params[i] = t;
3545 paramlen[i] = 0;
3546 while (t) {
3547 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
3548 break; /* ... because we have hit a comma */
3549 if (comma && t->type == TOK_WHITESPACE
3550 && tok_is_(t->next, ","))
3551 break; /* ... or a space then a comma */
3552 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
3553 break; /* ... or a brace */
3554 t = t->next;
3555 paramlen[i]++;
3556 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003557 }
3558
3559 /*
3560 * OK, we have a MMacro structure together with a set of
3561 * parameters. We must now go through the expansion and push
H. Peter Anvin76690a12002-04-30 20:52:49 +00003562 * copies of each Line on to istk->expansion. Substitution of
3563 * parameter tokens and macro-local tokens doesn't get done
3564 * until the single-line macro substitution process; this is
3565 * because delaying them allows us to change the semantics
3566 * later through %rotate.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003567 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00003568 * First, push an end marker on to istk->expansion, mark this
3569 * macro as in progress, and set up its invocation-specific
3570 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003571 */
3572 ll = nasm_malloc(sizeof(Line));
3573 ll->next = istk->expansion;
3574 ll->finishes = m;
3575 ll->first = NULL;
3576 istk->expansion = ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003577
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003578 m->in_progress = true;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003579 m->params = params;
3580 m->iline = tline;
3581 m->nparam = nparam;
3582 m->rotate = 0;
3583 m->paramlen = paramlen;
3584 m->unique = unique++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003585 m->lineno = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003586
3587 m->next_active = istk->mstk;
3588 istk->mstk = m;
3589
H. Peter Anvine2c80182005-01-15 22:15:51 +00003590 for (l = m->expansion; l; l = l->next) {
3591 Token **tail;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003592
H. Peter Anvine2c80182005-01-15 22:15:51 +00003593 ll = nasm_malloc(sizeof(Line));
3594 ll->finishes = NULL;
3595 ll->next = istk->expansion;
3596 istk->expansion = ll;
3597 tail = &ll->first;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003598
H. Peter Anvine2c80182005-01-15 22:15:51 +00003599 for (t = l->first; t; t = t->next) {
3600 Token *x = t;
3601 if (t->type == TOK_PREPROC_ID &&
3602 t->text[1] == '0' && t->text[2] == '0') {
3603 dont_prepend = -1;
3604 x = label;
3605 if (!x)
3606 continue;
3607 }
3608 tt = *tail = new_Token(NULL, x->type, x->text, 0);
3609 tail = &tt->next;
3610 }
3611 *tail = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003612 }
3613
3614 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00003615 * If we had a label, push it on as the first line of
3616 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003617 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003618 if (label) {
3619 if (dont_prepend < 0)
3620 free_tlist(startline);
3621 else {
3622 ll = nasm_malloc(sizeof(Line));
3623 ll->finishes = NULL;
3624 ll->next = istk->expansion;
3625 istk->expansion = ll;
3626 ll->first = startline;
3627 if (!dont_prepend) {
3628 while (label->next)
3629 label = label->next;
3630 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
3631 }
3632 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003633 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003634
H. Peter Anvin734b1882002-04-30 21:01:08 +00003635 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003636
H. Peter Anvineba20a72002-04-30 20:53:55 +00003637 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003638}
3639
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003640/*
3641 * Since preprocessor always operate only on the line that didn't
3642 * arrived yet, we should always use ERR_OFFBY1. Also since user
3643 * won't want to see same error twice (preprocessing is done once
3644 * per pass) we will want to show errors only during pass one.
3645 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003646static void error(int severity, const char *fmt, ...)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003647{
3648 va_list arg;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003649 char buff[1024];
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003650
3651 /* If we're in a dead branch of IF or something like it, ignore the error */
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00003652 if (istk && istk->conds && !emitting(istk->conds->state))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003653 return;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003654
H. Peter Anvin734b1882002-04-30 21:01:08 +00003655 va_start(arg, fmt);
Ed Beroset19f927a2004-12-15 17:07:03 +00003656 vsnprintf(buff, sizeof(buff), fmt, arg);
H. Peter Anvin734b1882002-04-30 21:01:08 +00003657 va_end(arg);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003658
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00003659 if (istk && istk->mstk && istk->mstk->name)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003660 _error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
3661 istk->mstk->lineno, buff);
3662 else
3663 _error(severity | ERR_PASS1, "%s", buff);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003664}
3665
H. Peter Anvin734b1882002-04-30 21:01:08 +00003666static void
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003667pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003668 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003669{
H. Peter Anvin99941bf2002-05-14 17:44:03 +00003670 _error = errfunc;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003671 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003672 istk = nasm_malloc(sizeof(Include));
3673 istk->next = NULL;
3674 istk->conds = NULL;
3675 istk->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003676 istk->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003677 istk->fp = fopen(file, "r");
H. Peter Anvineba20a72002-04-30 20:53:55 +00003678 istk->fname = NULL;
3679 src_set_fname(nasm_strdup(file));
3680 src_set_linnum(0);
3681 istk->lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003682 if (!istk->fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003683 error(ERR_FATAL | ERR_NOFILE, "unable to open input file `%s'",
3684 file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003685 defining = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003686 init_macros();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003687 unique = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003688 if (tasm_compatible_mode) {
3689 stdmacpos = stdmac;
3690 } else {
3691 stdmacpos = &stdmac[TASM_MACRO_COUNT];
3692 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003693 any_extrastdmac = (extrastdmac != NULL);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003694 list = listgen;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003695 evaluate = eval;
3696 pass = apass;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003697}
3698
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003699static char *pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003700{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003701 char *line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003702 Token *tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003703
H. Peter Anvine2c80182005-01-15 22:15:51 +00003704 while (1) {
3705 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00003706 * Fetch a tokenized line, either from the macro-expansion
H. Peter Anvine2c80182005-01-15 22:15:51 +00003707 * buffer or from the input file.
3708 */
3709 tline = NULL;
3710 while (istk->expansion && istk->expansion->finishes) {
3711 Line *l = istk->expansion;
3712 if (!l->finishes->name && l->finishes->in_progress > 1) {
3713 Line *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003714
H. Peter Anvine2c80182005-01-15 22:15:51 +00003715 /*
3716 * This is a macro-end marker for a macro with no
3717 * name, which means it's not really a macro at all
3718 * but a %rep block, and the `in_progress' field is
3719 * more than 1, meaning that we still need to
3720 * repeat. (1 means the natural last repetition; 0
3721 * means termination by %exitrep.) We have
3722 * therefore expanded up to the %endrep, and must
3723 * push the whole block on to the expansion buffer
3724 * again. We don't bother to remove the macro-end
3725 * marker: we'd only have to generate another one
3726 * if we did.
3727 */
3728 l->finishes->in_progress--;
3729 for (l = l->finishes->expansion; l; l = l->next) {
3730 Token *t, *tt, **tail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003731
H. Peter Anvine2c80182005-01-15 22:15:51 +00003732 ll = nasm_malloc(sizeof(Line));
3733 ll->next = istk->expansion;
3734 ll->finishes = NULL;
3735 ll->first = NULL;
3736 tail = &ll->first;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003737
H. Peter Anvine2c80182005-01-15 22:15:51 +00003738 for (t = l->first; t; t = t->next) {
3739 if (t->text || t->type == TOK_WHITESPACE) {
3740 tt = *tail =
3741 new_Token(NULL, t->type, t->text, 0);
3742 tail = &tt->next;
3743 }
3744 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003745
H. Peter Anvine2c80182005-01-15 22:15:51 +00003746 istk->expansion = ll;
3747 }
3748 } else {
3749 /*
3750 * Check whether a `%rep' was started and not ended
3751 * within this macro expansion. This can happen and
3752 * should be detected. It's a fatal error because
3753 * I'm too confused to work out how to recover
3754 * sensibly from it.
3755 */
3756 if (defining) {
3757 if (defining->name)
3758 error(ERR_PANIC,
3759 "defining with name in expansion");
3760 else if (istk->mstk->name)
3761 error(ERR_FATAL,
3762 "`%%rep' without `%%endrep' within"
3763 " expansion of macro `%s'",
3764 istk->mstk->name);
3765 }
H. Peter Anvin87bc6192002-04-30 20:53:16 +00003766
H. Peter Anvine2c80182005-01-15 22:15:51 +00003767 /*
3768 * FIXME: investigate the relationship at this point between
3769 * istk->mstk and l->finishes
3770 */
3771 {
3772 MMacro *m = istk->mstk;
3773 istk->mstk = m->next_active;
3774 if (m->name) {
3775 /*
3776 * This was a real macro call, not a %rep, and
3777 * therefore the parameter information needs to
3778 * be freed.
3779 */
3780 nasm_free(m->params);
3781 free_tlist(m->iline);
3782 nasm_free(m->paramlen);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003783 l->finishes->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003784 } else
3785 free_mmacro(m);
3786 }
3787 istk->expansion = l->next;
3788 nasm_free(l);
3789 list->downlevel(LIST_MACRO);
3790 }
3791 }
3792 while (1) { /* until we get a line we can use */
H. Peter Anvineba20a72002-04-30 20:53:55 +00003793
H. Peter Anvine2c80182005-01-15 22:15:51 +00003794 if (istk->expansion) { /* from a macro expansion */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003795 char *p;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003796 Line *l = istk->expansion;
3797 if (istk->mstk)
3798 istk->mstk->lineno++;
3799 tline = l->first;
3800 istk->expansion = l->next;
3801 nasm_free(l);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003802 p = detoken(tline, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003803 list->line(LIST_MACRO, p);
3804 nasm_free(p);
3805 break;
3806 }
3807 line = read_line();
3808 if (line) { /* from the current input file */
3809 line = prepreproc(line);
Keith Kaniosb7a89542007-04-12 02:40:54 +00003810 tline = tokenize(line);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003811 nasm_free(line);
3812 break;
3813 }
3814 /*
3815 * The current file has ended; work down the istk
3816 */
3817 {
3818 Include *i = istk;
3819 fclose(i->fp);
3820 if (i->conds)
3821 error(ERR_FATAL,
3822 "expected `%%endif' before end of file");
3823 /* only set line and file name if there's a next node */
3824 if (i->next) {
3825 src_set_linnum(i->lineno);
3826 nasm_free(src_set_fname(i->fname));
3827 }
3828 istk = i->next;
3829 list->downlevel(LIST_INCLUDE);
3830 nasm_free(i);
3831 if (!istk)
3832 return NULL;
3833 }
3834 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003835
H. Peter Anvine2c80182005-01-15 22:15:51 +00003836 /*
3837 * We must expand MMacro parameters and MMacro-local labels
3838 * _before_ we plunge into directive processing, to cope
3839 * with things like `%define something %1' such as STRUC
3840 * uses. Unless we're _defining_ a MMacro, in which case
3841 * those tokens should be left alone to go into the
3842 * definition; and unless we're in a non-emitting
3843 * condition, in which case we don't want to meddle with
3844 * anything.
3845 */
3846 if (!defining && !(istk->conds && !emitting(istk->conds->state)))
3847 tline = expand_mmac_params(tline);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003848
H. Peter Anvine2c80182005-01-15 22:15:51 +00003849 /*
3850 * Check the line to see if it's a preprocessor directive.
3851 */
3852 if (do_directive(tline) == DIRECTIVE_FOUND) {
3853 continue;
3854 } else if (defining) {
3855 /*
3856 * We're defining a multi-line macro. We emit nothing
3857 * at all, and just
Keith Kaniosb7a89542007-04-12 02:40:54 +00003858 * shove the tokenized line on to the macro definition.
H. Peter Anvine2c80182005-01-15 22:15:51 +00003859 */
3860 Line *l = nasm_malloc(sizeof(Line));
3861 l->next = defining->expansion;
3862 l->first = tline;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003863 l->finishes = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003864 defining->expansion = l;
3865 continue;
3866 } else if (istk->conds && !emitting(istk->conds->state)) {
3867 /*
3868 * We're in a non-emitting branch of a condition block.
3869 * Emit nothing at all, not even a blank line: when we
3870 * emerge from the condition we'll give a line-number
3871 * directive so we keep our place correctly.
3872 */
3873 free_tlist(tline);
3874 continue;
3875 } else if (istk->mstk && !istk->mstk->in_progress) {
3876 /*
3877 * We're in a %rep block which has been terminated, so
3878 * we're walking through to the %endrep without
3879 * emitting anything. Emit nothing at all, not even a
3880 * blank line: when we emerge from the %rep block we'll
3881 * give a line-number directive so we keep our place
3882 * correctly.
3883 */
3884 free_tlist(tline);
3885 continue;
3886 } else {
3887 tline = expand_smacro(tline);
3888 if (!expand_mmacro(tline)) {
3889 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00003890 * De-tokenize the line again, and emit it.
H. Peter Anvine2c80182005-01-15 22:15:51 +00003891 */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003892 line = detoken(tline, true);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003893 free_tlist(tline);
3894 break;
3895 } else {
3896 continue; /* expand_mmacro calls free_tlist */
3897 }
3898 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003899 }
3900
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003901 return line;
3902}
3903
H. Peter Anvine2c80182005-01-15 22:15:51 +00003904static void pp_cleanup(int pass)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003905{
H. Peter Anvine2c80182005-01-15 22:15:51 +00003906 if (defining) {
3907 error(ERR_NONFATAL, "end of file while still defining macro `%s'",
3908 defining->name);
3909 free_mmacro(defining);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003910 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003911 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003912 ctx_pop();
H. Peter Anvin97a23472007-09-16 17:57:25 -07003913 free_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00003914 while (istk) {
3915 Include *i = istk;
3916 istk = istk->next;
3917 fclose(i->fp);
3918 nasm_free(i->fname);
3919 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003920 }
3921 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003922 ctx_pop();
3923 if (pass == 0) {
3924 free_llist(predef);
3925 delete_Blocks();
3926 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003927}
3928
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003929void pp_include_path(char *path)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003930{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003931 IncPath *i;
H. Peter Anvin37a321f2007-09-24 13:41:58 -07003932
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003933 i = nasm_malloc(sizeof(IncPath));
H. Peter Anvin37a321f2007-09-24 13:41:58 -07003934 i->path = path ? nasm_strdup(path) : NULL;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003935 i->next = NULL;
3936
H. Peter Anvine2c80182005-01-15 22:15:51 +00003937 if (ipath != NULL) {
3938 IncPath *j = ipath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003939 while (j->next != NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003940 j = j->next;
3941 j->next = i;
3942 } else {
3943 ipath = i;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003944 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003945}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003946
3947/*
3948 * added by alexfru:
3949 *
3950 * This function is used to "export" the include paths, e.g.
3951 * the paths specified in the '-I' command switch.
3952 * The need for such exporting is due to the 'incbin' directive,
3953 * which includes raw binary files (unlike '%include', which
3954 * includes text source files). It would be real nice to be
3955 * able to specify paths to search for incbin'ned files also.
3956 * So, this is a simple workaround.
3957 *
3958 * The function use is simple:
3959 *
3960 * The 1st call (with NULL argument) returns a pointer to the 1st path
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003961 * (char** type) or NULL if none include paths available.
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003962 *
3963 * All subsequent calls take as argument the value returned by this
3964 * function last. The return value is either the next path
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003965 * (char** type) or NULL if the end of the paths list is reached.
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003966 *
3967 * It is maybe not the best way to do things, but I didn't want
3968 * to export too much, just one or two functions and no types or
3969 * variables exported.
3970 *
3971 * Can't say I like the current situation with e.g. this path list either,
3972 * it seems to be never deallocated after creation...
3973 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003974char **pp_get_include_path_ptr(char **pPrevPath)
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003975{
3976/* This macro returns offset of a member of a structure */
3977#define GetMemberOffset(StructType,MemberName)\
3978 ((size_t)&((StructType*)0)->MemberName)
3979 IncPath *i;
3980
H. Peter Anvine2c80182005-01-15 22:15:51 +00003981 if (pPrevPath == NULL) {
3982 if (ipath != NULL)
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003983 return &ipath->path;
3984 else
3985 return NULL;
3986 }
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003987 i = (IncPath *) ((char *)pPrevPath - GetMemberOffset(IncPath, path));
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00003988 i = i->next;
3989 if (i != NULL)
3990 return &i->path;
3991 else
3992 return NULL;
3993#undef GetMemberOffset
3994}
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003995
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003996void pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003997{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00003998 Token *inc, *space, *name;
3999 Line *l;
4000
H. Peter Anvin734b1882002-04-30 21:01:08 +00004001 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
4002 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
4003 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004004
4005 l = nasm_malloc(sizeof(Line));
4006 l->next = predef;
4007 l->first = inc;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004008 l->finishes = false;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004009 predef = l;
4010}
4011
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004012void pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004013{
4014 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004015 Line *l;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004016 char *equals;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004017
4018 equals = strchr(definition, '=');
H. Peter Anvin734b1882002-04-30 21:01:08 +00004019 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4020 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004021 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004022 *equals = ' ';
Keith Kaniosb7a89542007-04-12 02:40:54 +00004023 space->next = tokenize(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004024 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004025 *equals = '=';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004026
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004027 l = nasm_malloc(sizeof(Line));
4028 l->next = predef;
4029 l->first = def;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004030 l->finishes = false;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004031 predef = l;
4032}
4033
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004034void pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00004035{
4036 Token *def, *space;
4037 Line *l;
4038
H. Peter Anvin734b1882002-04-30 21:01:08 +00004039 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4040 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Keith Kaniosb7a89542007-04-12 02:40:54 +00004041 space->next = tokenize(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00004042
4043 l = nasm_malloc(sizeof(Line));
4044 l->next = predef;
4045 l->first = def;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004046 l->finishes = false;
H. Peter Anvin620515a2002-04-30 20:57:38 +00004047 predef = l;
4048}
4049
Keith Kaniosb7a89542007-04-12 02:40:54 +00004050/*
4051 * Added by Keith Kanios:
4052 *
4053 * This function is used to assist with "runtime" preprocessor
4054 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4055 *
4056 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4057 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4058 */
4059
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004060void pp_runtime(char *definition)
Keith Kaniosb7a89542007-04-12 02:40:54 +00004061{
4062 Token *def;
4063
4064 def = tokenize(definition);
4065 if(do_directive(def) == NO_DIRECTIVE_FOUND)
4066 free_tlist(def);
4067
4068}
4069
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004070void pp_extra_stdmac(const char **macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004071{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004072 extrastdmac = macros;
4073}
4074
Keith Kaniosb7a89542007-04-12 02:40:54 +00004075static void make_tok_num(Token * tok, int32_t val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004076{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004077 char numbuf[20];
Keith Kanios93f2e9a2007-04-14 00:10:59 +00004078 snprintf(numbuf, sizeof(numbuf), "%"PRId32"", val);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004079 tok->text = nasm_strdup(numbuf);
4080 tok->type = TOK_NUMBER;
4081}
4082
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004083Preproc nasmpp = {
4084 pp_reset,
4085 pp_getline,
4086 pp_cleanup
4087};