blob: 0868e7521e75e2ca4dad2f5809098e8cf0aa6556 [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
Beroset095e6a22007-12-29 09:44:23 -05005 * redistributable under the license given in the file "LICENSE"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00006 * 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 Anvin8cad14b2008-06-01 17:23:51 -070051#include "quote.h"
H. Peter Anvinc2df2822007-10-24 15:29:28 -070052#include "stdscan.h"
53#include "tokens.h"
H. Peter Anvina4835d42008-05-20 14:21:29 -070054#include "tables.h"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000055
56typedef struct SMacro SMacro;
57typedef struct MMacro MMacro;
58typedef struct Context Context;
59typedef struct Token Token;
H. Peter Anvince616072002-04-30 21:02:23 +000060typedef struct Blocks Blocks;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000061typedef struct Line Line;
62typedef struct Include Include;
63typedef struct Cond Cond;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000064typedef struct IncPath IncPath;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000065
66/*
H. Peter Anvin97a23472007-09-16 17:57:25 -070067 * Note on the storage of both SMacro and MMacros: the hash table
68 * indexes them case-insensitively, and we then have to go through a
69 * linked list of potential case aliases (and, for MMacros, parameter
70 * ranges); this is to preserve the matching semantics of the earlier
71 * code. If the number of case aliases for a specific macro is a
72 * performance issue, you may want to reconsider your coding style.
73 */
74
75/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000076 * Store the definition of a single-line macro.
77 */
H. Peter Anvine2c80182005-01-15 22:15:51 +000078struct SMacro {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000079 SMacro *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +000080 char *name;
H. Peter Anvin70055962007-10-11 00:05:31 -070081 bool casesense;
H. Peter Anvin16ed4382007-10-11 10:06:19 -070082 bool in_progress;
H. Peter Anvin70055962007-10-11 00:05:31 -070083 unsigned int nparam;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000084 Token *expansion;
85};
86
87/*
H. Peter Anvin76690a12002-04-30 20:52:49 +000088 * Store the definition of a multi-line macro. This is also used to
89 * store the interiors of `%rep...%endrep' blocks, which are
90 * effectively self-re-invoking multi-line macros which simply
91 * don't have a name or bother to appear in the hash tables. %rep
92 * blocks are signified by having a NULL `name' field.
93 *
94 * In a MMacro describing a `%rep' block, the `in_progress' field
95 * isn't merely boolean, but gives the number of repeats left to
96 * run.
97 *
98 * The `next' field is used for storing MMacros in hash tables; the
99 * `next_active' field is for stacking them on istk entries.
100 *
101 * When a MMacro is being expanded, `params', `iline', `nparam',
102 * `paramlen', `rotate' and `unique' are local to the invocation.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000103 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000104struct MMacro {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000105 MMacro *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000106 char *name;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -0700107 int nparam_min, nparam_max;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700108 bool casesense;
109 bool plus; /* is the last parameter greedy? */
110 bool nolist; /* is this macro listing-inhibited? */
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700111 int64_t in_progress;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000112 Token *dlist; /* All defaults as one list */
113 Token **defaults; /* Parameter default pointers */
114 int ndefs; /* number of default parameters */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000115 Line *expansion;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000116
117 MMacro *next_active;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000118 MMacro *rep_nest; /* used for nesting %rep */
119 Token **params; /* actual parameters */
120 Token *iline; /* invocation line */
H. Peter Anvin25a99342007-09-22 17:45:45 -0700121 unsigned int nparam, rotate;
122 int *paramlen;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700123 uint64_t unique;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000124 int lineno; /* Current line number on expansion */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000125};
126
127/*
128 * The context stack is composed of a linked list of these.
129 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000130struct Context {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000131 Context *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000132 char *name;
H. Peter Anvin166c2472008-05-28 12:28:58 -0700133 struct hash_table localmac;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000134 uint32_t number;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000135};
136
137/*
138 * This is the internal form which we break input lines up into.
139 * Typically stored in linked lists.
140 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000141 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
142 * necessarily used as-is, but is intended to denote the number of
143 * the substituted parameter. So in the definition
144 *
145 * %define a(x,y) ( (x) & ~(y) )
H. Peter Anvin70653092007-10-19 14:42:29 -0700146 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000147 * the token representing `x' will have its type changed to
148 * TOK_SMAC_PARAM, but the one representing `y' will be
149 * TOK_SMAC_PARAM+1.
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000150 *
151 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
152 * which doesn't need quotes around it. Used in the pre-include
153 * mechanism as an alternative to trying to find a sensible type of
154 * quote to use on the filename we were passed.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000155 */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000156enum pp_token_type {
157 TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT, TOK_ID,
158 TOK_PREPROC_ID, TOK_STRING,
H. Peter Anvin6c81f0a2008-05-25 21:46:17 -0700159 TOK_NUMBER, TOK_FLOAT, TOK_SMAC_END, TOK_OTHER,
160 TOK_INTERNAL_STRING,
161 TOK_PREPROC_Q, TOK_PREPROC_QQ,
H. Peter Anvind784a082009-04-20 14:01:18 -0700162 TOK_PASTE, /* %+ */
H. Peter Anvin9bb46df2009-04-07 21:59:24 -0700163 TOK_INDIRECT, /* %[...] */
H. Peter Anvin5b76fa22008-05-26 11:14:38 -0700164 TOK_SMAC_PARAM, /* MUST BE LAST IN THE LIST!!! */
165 TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000166};
167
H. Peter Anvine2c80182005-01-15 22:15:51 +0000168struct Token {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000169 Token *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000170 char *text;
H. Peter Anvinf26e0972008-07-01 21:26:27 -0700171 union {
172 SMacro *mac; /* associated macro for TOK_SMAC_END */
173 size_t len; /* scratch length field */
174 } a; /* Auxiliary data */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000175 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000176};
177
178/*
179 * Multi-line macro definitions are stored as a linked list of
180 * these, which is essentially a container to allow several linked
181 * lists of Tokens.
H. Peter Anvin70653092007-10-19 14:42:29 -0700182 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000183 * Note that in this module, linked lists are treated as stacks
184 * wherever possible. For this reason, Lines are _pushed_ on to the
185 * `expansion' field in MMacro structures, so that the linked list,
186 * if walked, would give the macro lines in reverse order; this
187 * means that we can walk the list when expanding a macro, and thus
188 * push the lines on to the `expansion' field in _istk_ in reverse
189 * order (so that when popped back off they are in the right
190 * order). It may seem cockeyed, and it relies on my design having
191 * an even number of steps in, but it works...
192 *
193 * Some of these structures, rather than being actual lines, are
194 * markers delimiting the end of the expansion of a given macro.
H. Peter Anvin76690a12002-04-30 20:52:49 +0000195 * This is for use in the cycle-tracking and %rep-handling code.
196 * Such structures have `finishes' non-NULL, and `first' NULL. All
197 * others have `finishes' NULL, but `first' may still be NULL if
198 * the line is blank.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000199 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000200struct Line {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000201 Line *next;
202 MMacro *finishes;
203 Token *first;
204};
205
206/*
207 * To handle an arbitrary level of file inclusion, we maintain a
208 * stack (ie linked list) of these things.
209 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000210struct Include {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000211 Include *next;
212 FILE *fp;
213 Cond *conds;
214 Line *expansion;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000215 char *fname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000216 int lineno, lineinc;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000217 MMacro *mstk; /* stack of active macros/reps */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000218};
219
220/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000221 * Include search path. This is simply a list of strings which get
222 * prepended, in turn, to the name of an include file, in an
223 * attempt to find the file if it's not in the current directory.
224 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000225struct IncPath {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000226 IncPath *next;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000227 char *path;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000228};
229
230/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000231 * Conditional assembly: we maintain a separate stack of these for
232 * each level of file inclusion. (The only reason we keep the
233 * stacks separate is to ensure that a stray `%endif' in a file
234 * included from within the true branch of a `%if' won't terminate
235 * it and cause confusion: instead, rightly, it'll cause an error.)
236 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000237struct Cond {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000238 Cond *next;
239 int state;
240};
H. Peter Anvine2c80182005-01-15 22:15:51 +0000241enum {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000242 /*
243 * These states are for use just after %if or %elif: IF_TRUE
244 * means the condition has evaluated to truth so we are
245 * currently emitting, whereas IF_FALSE means we are not
246 * currently emitting but will start doing so if a %else comes
247 * up. In these states, all directives are admissible: %elif,
248 * %else and %endif. (And of course %if.)
249 */
250 COND_IF_TRUE, COND_IF_FALSE,
251 /*
252 * These states come up after a %else: ELSE_TRUE means we're
253 * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
254 * any %elif or %else will cause an error.
255 */
256 COND_ELSE_TRUE, COND_ELSE_FALSE,
257 /*
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200258 * These states mean that we're not emitting now, and also that
259 * nothing until %endif will be emitted at all. COND_DONE is
260 * used when we've had our moment of emission
261 * and have now started seeing %elifs. COND_NEVER is used when
262 * the condition construct in question is contained within a
263 * non-emitting branch of a larger condition construct,
264 * or if there is an error.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000265 */
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200266 COND_DONE, COND_NEVER
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000267};
268#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
269
H. Peter Anvin70653092007-10-19 14:42:29 -0700270/*
Ed Beroset3ab3f412002-06-11 03:31:49 +0000271 * These defines are used as the possible return values for do_directive
272 */
273#define NO_DIRECTIVE_FOUND 0
274#define DIRECTIVE_FOUND 1
275
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000276/*
277 * Condition codes. Note that we use c_ prefix not C_ because C_ is
278 * used in nasm.h for the "real" condition codes. At _this_ level,
279 * we treat CXZ and ECXZ as condition codes, albeit non-invertible
280 * ones, so we need a different enum...
281 */
H. Peter Anvin476d2862007-10-02 22:04:15 -0700282static const char * const conditions[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000283 "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
284 "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
H. Peter Anvince9be342007-09-12 00:22:29 +0000285 "np", "ns", "nz", "o", "p", "pe", "po", "rcxz", "s", "z"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000286};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700287enum pp_conds {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000288 c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
289 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 -0700290 c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_RCXZ, c_S, c_Z,
291 c_none = -1
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000292};
H. Peter Anvin476d2862007-10-02 22:04:15 -0700293static const enum pp_conds inverse_ccs[] = {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000294 c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
295 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 +0000296 c_Z, c_NO, c_NP, c_PO, c_PE, -1, c_NS, c_NZ
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000297};
298
H. Peter Anvin76690a12002-04-30 20:52:49 +0000299/*
300 * Directive names.
301 */
H. Peter Anvin65747262002-05-07 00:10:05 +0000302/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
H. Peter Anvin9bf0aa72007-09-12 02:12:07 +0000303static int is_condition(enum preproc_token arg)
H. Peter Anvin65747262002-05-07 00:10:05 +0000304{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000305 return PP_IS_COND(arg) || (arg == PP_ELSE) || (arg == PP_ENDIF);
H. Peter Anvin65747262002-05-07 00:10:05 +0000306}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000307
308/* For TASM compatibility we need to be able to recognise TASM compatible
309 * conditional compilation directives. Using the NASM pre-processor does
310 * not work, so we look for them specifically from the following list and
311 * then jam in the equivalent NASM directive into the input stream.
312 */
313
H. Peter Anvine2c80182005-01-15 22:15:51 +0000314enum {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000315 TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
316 TM_IFNDEF, TM_INCLUDE, TM_LOCAL
317};
318
H. Peter Anvin476d2862007-10-02 22:04:15 -0700319static const char * const tasm_directives[] = {
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000320 "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
321 "ifndef", "include", "local"
322};
323
324static int StackSize = 4;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000325static char *StackPointer = "ebp";
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000326static int ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -0800327static int LocalOffset = 0;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000328
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000329static Context *cstk;
330static Include *istk;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000331static IncPath *ipath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000332
H. Peter Anvine2c80182005-01-15 22:15:51 +0000333static efunc _error; /* Pointer to client-provided error reporting function */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000334static evalfunc evaluate;
335
H. Peter Anvine2c80182005-01-15 22:15:51 +0000336static int pass; /* HACK: pass 0 = generate dependencies only */
H. Peter Anvin9e1f5282008-05-29 21:38:00 -0700337static StrList **dephead, **deptail; /* Dependency list */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000338
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -0700339static uint64_t unique; /* unique identifier numbers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000340
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000341static Line *predef = NULL;
H. Peter Anvind2456592008-06-19 15:04:18 -0700342static bool do_predef;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000343
344static ListGen *list;
345
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000346/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000347 * The current set of multi-line macros we have defined.
348 */
H. Peter Anvin166c2472008-05-28 12:28:58 -0700349static struct hash_table mmacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000350
351/*
352 * The current set of single-line macros we have defined.
353 */
H. Peter Anvin166c2472008-05-28 12:28:58 -0700354static struct hash_table smacros;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000355
356/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000357 * The multi-line macro we are currently defining, or the %rep
358 * block we are currently reading, if any.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000359 */
360static MMacro *defining;
361
Charles Crayned4200be2008-07-12 16:42:33 -0700362static uint64_t nested_mac_count;
363static uint64_t nested_rep_count;
364
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000365/*
366 * The number of macro parameters to allocate space for at a time.
367 */
368#define PARAM_DELTA 16
369
370/*
H. Peter Anvina4835d42008-05-20 14:21:29 -0700371 * The standard macro set: defined in macros.c in the array nasm_stdmac.
372 * This gives our position in the macro set, when we're processing it.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000373 */
H. Peter Anvina70547f2008-07-19 21:44:26 -0700374static macros_t *stdmacpos;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000375
376/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000377 * The extra standard macros that come from the object format, if
378 * any.
379 */
H. Peter Anvina70547f2008-07-19 21:44:26 -0700380static macros_t *extrastdmac = NULL;
H. Peter Anvincfb71762008-06-20 15:20:16 -0700381static bool any_extrastdmac;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000382
383/*
H. Peter Anvin734b1882002-04-30 21:01:08 +0000384 * Tokens are allocated in blocks to improve speed
385 */
386#define TOKEN_BLOCKSIZE 4096
387static Token *freeTokens = NULL;
H. Peter Anvince616072002-04-30 21:02:23 +0000388struct Blocks {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000389 Blocks *next;
390 void *chunk;
H. Peter Anvince616072002-04-30 21:02:23 +0000391};
392
393static Blocks blocks = { NULL, NULL };
H. Peter Anvin734b1882002-04-30 21:01:08 +0000394
395/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000396 * Forward declarations.
397 */
H. Peter Anvin734b1882002-04-30 21:01:08 +0000398static Token *expand_mmac_params(Token * tline);
399static Token *expand_smacro(Token * tline);
400static Token *expand_id(Token * tline);
H. Peter Anvinf8ad5322009-02-21 17:55:08 -0800401static Context *get_ctx(const char *name, const char **namep,
402 bool all_contexts);
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700403static void make_tok_num(Token * tok, int64_t val);
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000404static void error(int severity, const char *fmt, ...);
Victor van den Elzen3b404c02008-09-18 13:51:36 +0200405static void error_precond(int severity, const char *fmt, ...);
H. Peter Anvince616072002-04-30 21:02:23 +0000406static void *new_Block(size_t size);
407static void delete_Blocks(void);
H. Peter Anvinc751e862008-06-09 10:18:45 -0700408static Token *new_Token(Token * next, enum pp_token_type type,
409 const char *text, int txtlen);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000410static Token *delete_Token(Token * t);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000411
412/*
413 * Macros for safe checking of token pointers, avoid *(NULL)
414 */
415#define tok_type_(x,t) ((x) && (x)->type == (t))
416#define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
417#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
418#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
H. Peter Anvin76690a12002-04-30 20:52:49 +0000419
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000420/* Handle TASM specific directives, which do not contain a % in
421 * front of them. We do it here because I could not find any other
422 * place to do it for the moment, and it is a hack (ideally it would
423 * be nice to be able to use the NASM pre-processor to do it).
424 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000425static char *check_tasm_directive(char *line)
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000426{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000427 int32_t i, j, k, m, len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000428 char *p = line, *oldline, oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000429
430 /* Skip whitespace */
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700431 while (nasm_isspace(*p) && *p != 0)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000432 p++;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000433
434 /* Binary search for the directive name */
435 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +0000436 j = elements(tasm_directives);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000437 len = 0;
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700438 while (!nasm_isspace(p[len]) && p[len] != 0)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000439 len++;
440 if (len) {
441 oldchar = p[len];
442 p[len] = 0;
443 while (j - i > 1) {
444 k = (j + i) / 2;
445 m = nasm_stricmp(p, tasm_directives[k]);
446 if (m == 0) {
447 /* We have found a directive, so jam a % in front of it
448 * so that NASM will then recognise it as one if it's own.
449 */
450 p[len] = oldchar;
451 len = strlen(p);
452 oldline = line;
453 line = nasm_malloc(len + 2);
454 line[0] = '%';
455 if (k == TM_IFDIFI) {
456 /* NASM does not recognise IFDIFI, so we convert it to
457 * %ifdef BOGUS. This is not used in NASM comaptible
458 * code, but does need to parse for the TASM macro
459 * package.
460 */
461 strcpy(line + 1, "ifdef BOGUS");
462 } else {
463 memcpy(line + 1, p, len + 1);
464 }
465 nasm_free(oldline);
466 return line;
467 } else if (m < 0) {
468 j = k;
469 } else
470 i = k;
471 }
472 p[len] = oldchar;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000473 }
474 return line;
475}
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000476
H. Peter Anvin76690a12002-04-30 20:52:49 +0000477/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000478 * The pre-preprocessing stage... This function translates line
479 * number indications as they emerge from GNU cpp (`# lineno "file"
480 * flags') into NASM preprocessor line number indications (`%line
481 * lineno file').
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000482 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000483static char *prepreproc(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000484{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000485 int lineno, fnlen;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000486 char *fname, *oldline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000487
H. Peter Anvine2c80182005-01-15 22:15:51 +0000488 if (line[0] == '#' && line[1] == ' ') {
489 oldline = line;
490 fname = oldline + 2;
491 lineno = atoi(fname);
492 fname += strspn(fname, "0123456789 ");
493 if (*fname == '"')
494 fname++;
495 fnlen = strcspn(fname, "\"");
496 line = nasm_malloc(20 + fnlen);
497 snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
498 nasm_free(oldline);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000499 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +0000500 if (tasm_compatible_mode)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000501 return check_tasm_directive(line);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000502 return line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000503}
504
505/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000506 * Free a linked list of tokens.
507 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000508static void free_tlist(Token * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000509{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000510 while (list) {
511 list = delete_Token(list);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000512 }
513}
514
515/*
516 * Free a linked list of lines.
517 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000518static void free_llist(Line * list)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000519{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000520 Line *l;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000521 while (list) {
522 l = list;
523 list = list->next;
524 free_tlist(l->first);
525 nasm_free(l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000526 }
527}
528
529/*
H. Peter Anvineba20a72002-04-30 20:53:55 +0000530 * Free an MMacro
531 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000532static void free_mmacro(MMacro * m)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000533{
H. Peter Anvin734b1882002-04-30 21:01:08 +0000534 nasm_free(m->name);
535 free_tlist(m->dlist);
536 nasm_free(m->defaults);
537 free_llist(m->expansion);
538 nasm_free(m);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000539}
540
541/*
H. Peter Anvin97a23472007-09-16 17:57:25 -0700542 * Free all currently defined macros, and free the hash tables
543 */
H. Peter Anvin072771e2008-05-22 13:17:51 -0700544static void free_smacro_table(struct hash_table *smt)
H. Peter Anvin97a23472007-09-16 17:57:25 -0700545{
H. Peter Anvin97a23472007-09-16 17:57:25 -0700546 SMacro *s;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700547 const char *key;
548 struct hash_tbl_node *it = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -0700549
H. Peter Anvin072771e2008-05-22 13:17:51 -0700550 while ((s = hash_iterate(smt, &it, &key)) != NULL) {
H. Peter Anvin97a23472007-09-16 17:57:25 -0700551 nasm_free((void *)key);
552 while (s) {
553 SMacro *ns = s->next;
554 nasm_free(s->name);
555 free_tlist(s->expansion);
556 nasm_free(s);
557 s = ns;
558 }
559 }
H. Peter Anvin072771e2008-05-22 13:17:51 -0700560 hash_free(smt);
561}
562
563static void free_mmacro_table(struct hash_table *mmt)
564{
565 MMacro *m;
566 const char *key;
567 struct hash_tbl_node *it = NULL;
H. Peter Anvin97a23472007-09-16 17:57:25 -0700568
569 it = NULL;
H. Peter Anvin072771e2008-05-22 13:17:51 -0700570 while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
H. Peter Anvin97a23472007-09-16 17:57:25 -0700571 nasm_free((void *)key);
572 while (m) {
573 MMacro *nm = m->next;
574 free_mmacro(m);
575 m = nm;
576 }
577 }
H. Peter Anvin072771e2008-05-22 13:17:51 -0700578 hash_free(mmt);
579}
580
581static void free_macros(void)
582{
H. Peter Anvin166c2472008-05-28 12:28:58 -0700583 free_smacro_table(&smacros);
584 free_mmacro_table(&mmacros);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700585}
586
587/*
588 * Initialize the hash tables
589 */
590static void init_macros(void)
591{
H. Peter Anvin166c2472008-05-28 12:28:58 -0700592 hash_init(&smacros, HASH_LARGE);
593 hash_init(&mmacros, HASH_LARGE);
H. Peter Anvin97a23472007-09-16 17:57:25 -0700594}
595
596/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000597 * Pop the context stack.
598 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000599static void ctx_pop(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000600{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000601 Context *c = cstk;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000602
603 cstk = cstk->next;
H. Peter Anvin166c2472008-05-28 12:28:58 -0700604 free_smacro_table(&c->localmac);
H. Peter Anvin734b1882002-04-30 21:01:08 +0000605 nasm_free(c->name);
606 nasm_free(c);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000607}
608
H. Peter Anvin072771e2008-05-22 13:17:51 -0700609/*
610 * Search for a key in the hash index; adding it if necessary
611 * (in which case we initialize the data pointer to NULL.)
612 */
613static void **
614hash_findi_add(struct hash_table *hash, const char *str)
615{
616 struct hash_insert hi;
617 void **r;
618 char *strx;
619
620 r = hash_findi(hash, str, &hi);
621 if (r)
622 return r;
623
624 strx = nasm_strdup(str); /* Use a more efficient allocator here? */
625 return hash_add(&hi, strx, NULL);
626}
627
628/*
629 * Like hash_findi, but returns the data element rather than a pointer
630 * to it. Used only when not adding a new element, hence no third
631 * argument.
632 */
633static void *
634hash_findix(struct hash_table *hash, const char *str)
635{
636 void **p;
637
638 p = hash_findi(hash, str, NULL);
639 return p ? *p : NULL;
640}
641
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000642#define BUF_DELTA 512
643/*
644 * Read a line from the top file in istk, handling multiple CR/LFs
645 * at the end of the line read, and handling spurious ^Zs. Will
646 * return lines from the standard macro set if this has not already
647 * been done.
648 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000649static char *read_line(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000650{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000651 char *buffer, *p, *q;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000652 int bufsize, continued_count;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000653
H. Peter Anvine2c80182005-01-15 22:15:51 +0000654 if (stdmacpos) {
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700655 unsigned char c;
H. Peter Anvin7e50d232008-06-25 14:54:14 -0700656 const unsigned char *p = stdmacpos;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700657 char *ret, *q;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700658 size_t len = 0;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700659 while ((c = *p++)) {
660 if (c >= 0x80)
661 len += pp_directives_len[c-0x80]+1;
662 else
663 len++;
664 }
665 ret = nasm_malloc(len+1);
H. Peter Anvincda81632008-06-21 15:15:40 -0700666 q = ret;
667 while ((c = *stdmacpos++)) {
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700668 if (c >= 0x80) {
669 memcpy(q, pp_directives[c-0x80], pp_directives_len[c-0x80]);
670 q += pp_directives_len[c-0x80];
671 *q++ = ' ';
672 } else {
673 *q++ = c;
674 }
675 }
H. Peter Anvincda81632008-06-21 15:15:40 -0700676 stdmacpos = p;
H. Peter Anvin72edbb82008-06-19 16:00:04 -0700677 *q = '\0';
678
H. Peter Anvind2456592008-06-19 15:04:18 -0700679 if (!*stdmacpos) {
680 /* This was the last of the standard macro chain... */
681 stdmacpos = NULL;
682 if (any_extrastdmac) {
683 stdmacpos = extrastdmac;
684 any_extrastdmac = false;
685 } else if (do_predef) {
686 Line *pd, *l;
687 Token *head, **tail, *t;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000688
H. Peter Anvind2456592008-06-19 15:04:18 -0700689 /*
690 * Nasty hack: here we push the contents of
691 * `predef' on to the top-level expansion stack,
692 * since this is the most convenient way to
693 * implement the pre-include and pre-define
694 * features.
695 */
696 for (pd = predef; pd; pd = pd->next) {
697 head = NULL;
698 tail = &head;
699 for (t = pd->first; t; t = t->next) {
700 *tail = new_Token(NULL, t->type, t->text, 0);
701 tail = &(*tail)->next;
702 }
703 l = nasm_malloc(sizeof(Line));
704 l->next = istk->expansion;
705 l->first = head;
H. Peter Anvin538002d2008-06-28 18:30:27 -0700706 l->finishes = NULL;
H. Peter Anvind2456592008-06-19 15:04:18 -0700707 istk->expansion = l;
708 }
709 do_predef = false;
710 }
711 }
712 return ret;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000713 }
714
715 bufsize = BUF_DELTA;
716 buffer = nasm_malloc(BUF_DELTA);
717 p = buffer;
H. Peter Anvin9f394642002-04-30 21:07:51 +0000718 continued_count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000719 while (1) {
720 q = fgets(p, bufsize - (p - buffer), istk->fp);
721 if (!q)
722 break;
723 p += strlen(p);
724 if (p > buffer && p[-1] == '\n') {
725 /* Convert backslash-CRLF line continuation sequences into
726 nothing at all (for DOS and Windows) */
727 if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
728 p -= 3;
729 *p = 0;
730 continued_count++;
731 }
732 /* Also convert backslash-LF line continuation sequences into
733 nothing at all (for Unix) */
734 else if (((p - 1) > buffer) && (p[-2] == '\\')) {
735 p -= 2;
736 *p = 0;
737 continued_count++;
738 } else {
739 break;
740 }
741 }
742 if (p - buffer > bufsize - 10) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000743 int32_t offset = p - buffer;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000744 bufsize += BUF_DELTA;
745 buffer = nasm_realloc(buffer, bufsize);
746 p = buffer + offset; /* prevent stale-pointer problems */
747 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000748 }
749
H. Peter Anvine2c80182005-01-15 22:15:51 +0000750 if (!q && p == buffer) {
751 nasm_free(buffer);
752 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000753 }
754
H. Peter Anvine2c80182005-01-15 22:15:51 +0000755 src_set_linnum(src_get_linnum() + istk->lineinc +
756 (continued_count * istk->lineinc));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000757
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000758 /*
759 * Play safe: remove CRs as well as LFs, if any of either are
760 * present at the end of the line.
761 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000762 while (--p >= buffer && (*p == '\n' || *p == '\r'))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000763 *p = '\0';
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000764
765 /*
766 * Handle spurious ^Z, which may be inserted into source files
767 * by some file transfer utilities.
768 */
769 buffer[strcspn(buffer, "\032")] = '\0';
770
H. Peter Anvin734b1882002-04-30 21:01:08 +0000771 list->line(LIST_READ, buffer);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000772
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000773 return buffer;
774}
775
776/*
Keith Kaniosb7a89542007-04-12 02:40:54 +0000777 * Tokenize a line of text. This is a very simple process since we
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000778 * don't need to parse the value out of e.g. numeric tokens: we
779 * simply split one string into many.
780 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000781static Token *tokenize(char *line)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000782{
H. Peter Anvinca544db2008-10-19 19:30:11 -0700783 char c, *p = line;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +0000784 enum pp_token_type type;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000785 Token *list = NULL;
786 Token *t, **tail = &list;
787
H. Peter Anvine2c80182005-01-15 22:15:51 +0000788 while (*line) {
789 p = line;
790 if (*p == '%') {
791 p++;
H. Peter Anvind784a082009-04-20 14:01:18 -0700792 if (*p == '+' && !nasm_isdigit(p[1])) {
793 p++;
794 type = TOK_PASTE;
795 } else if (nasm_isdigit(*p) ||
796 ((*p == '-' || *p == '+') && nasm_isdigit(p[1]))) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000797 do {
798 p++;
799 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700800 while (nasm_isdigit(*p));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000801 type = TOK_PREPROC_ID;
802 } else if (*p == '{') {
803 p++;
804 while (*p && *p != '}') {
805 p[-1] = *p;
806 p++;
807 }
808 p[-1] = '\0';
809 if (*p)
810 p++;
811 type = TOK_PREPROC_ID;
H. Peter Anvin992fe752008-10-19 15:45:05 -0700812 } else if (*p == '[') {
813 int lvl = 1;
814 line += 2; /* Skip the leading %[ */
815 p++;
H. Peter Anvinec033012008-10-19 22:12:06 -0700816 while (lvl && (c = *p++)) {
H. Peter Anvinca544db2008-10-19 19:30:11 -0700817 switch (c) {
818 case ']':
819 lvl--;
820 break;
821 case '%':
H. Peter Anvinca544db2008-10-19 19:30:11 -0700822 if (*p == '[')
823 lvl++;
824 break;
825 case '\'':
826 case '\"':
827 case '`':
H. Peter Anvinec033012008-10-19 22:12:06 -0700828 p = nasm_skip_string(p)+1;
H. Peter Anvinca544db2008-10-19 19:30:11 -0700829 break;
830 default:
831 break;
H. Peter Anvin992fe752008-10-19 15:45:05 -0700832 }
H. Peter Anvin992fe752008-10-19 15:45:05 -0700833 }
H. Peter Anvinec033012008-10-19 22:12:06 -0700834 p--;
H. Peter Anvin992fe752008-10-19 15:45:05 -0700835 if (*p)
836 *p++ = '\0';
H. Peter Anvine1265812008-10-19 22:14:30 -0700837 if (lvl)
838 error(ERR_NONFATAL, "unterminated %[ construct");
H. Peter Anvin992fe752008-10-19 15:45:05 -0700839 type = TOK_INDIRECT;
H. Peter Anvin6c81f0a2008-05-25 21:46:17 -0700840 } else if (*p == '?') {
841 type = TOK_PREPROC_Q; /* %? */
842 p++;
843 if (*p == '?') {
844 type = TOK_PREPROC_QQ; /* %?? */
845 p++;
846 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000847 } else if (isidchar(*p) ||
848 ((*p == '!' || *p == '%' || *p == '$') &&
849 isidchar(p[1]))) {
850 do {
851 p++;
852 }
853 while (isidchar(*p));
854 type = TOK_PREPROC_ID;
855 } else {
856 type = TOK_OTHER;
857 if (*p == '%')
858 p++;
859 }
860 } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
861 type = TOK_ID;
862 p++;
863 while (*p && isidchar(*p))
864 p++;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700865 } else if (*p == '\'' || *p == '"' || *p == '`') {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000866 /*
867 * A string token.
868 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000869 type = TOK_STRING;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -0700870 p = nasm_skip_string(p);
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000871
H. Peter Anvine2c80182005-01-15 22:15:51 +0000872 if (*p) {
873 p++;
874 } else {
H. Peter Anvin917a3492008-09-24 09:14:49 -0700875 error(ERR_WARNING|ERR_PASS1, "unterminated string");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000876 /* Handling unterminated strings by UNV */
877 /* type = -1; */
878 }
Victor van den Elzenfb5f2512009-04-17 16:17:59 +0200879 } else if (p[0] == '$' && p[1] == '$') {
H. Peter Anvin8e1f8112009-04-17 14:20:44 -0700880 type = TOK_OTHER; /* TOKEN_BASE */
Victor van den Elzenfb5f2512009-04-17 16:17:59 +0200881 p += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000882 } else if (isnumstart(*p)) {
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700883 bool is_hex = false;
884 bool is_float = false;
885 bool has_e = false;
886 char c, *r;
887
H. Peter Anvine2c80182005-01-15 22:15:51 +0000888 /*
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700889 * A numeric token.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000890 */
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700891
892 if (*p == '$') {
893 p++;
894 is_hex = true;
895 }
896
897 for (;;) {
898 c = *p++;
899
900 if (!is_hex && (c == 'e' || c == 'E')) {
901 has_e = true;
902 if (*p == '+' || *p == '-') {
903 /* e can only be followed by +/- if it is either a
904 prefixed hex number or a floating-point number */
905 p++;
906 is_float = true;
907 }
908 } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
909 is_hex = true;
910 } else if (c == 'P' || c == 'p') {
911 is_float = true;
912 if (*p == '+' || *p == '-')
913 p++;
914 } else if (isnumchar(c) || c == '_')
915 ; /* just advance */
916 else if (c == '.') {
917 /* we need to deal with consequences of the legacy
918 parser, like "1.nolist" being two tokens
919 (TOK_NUMBER, TOK_ID) here; at least give it
920 a shot for now. In the future, we probably need
921 a flex-based scanner with proper pattern matching
922 to do it as well as it can be done. Nothing in
923 the world is going to help the person who wants
924 0x123.p16 interpreted as two tokens, though. */
925 r = p;
926 while (*r == '_')
927 r++;
928
H. Peter Anvinf221b9e2008-06-21 11:03:51 -0700929 if (nasm_isdigit(*r) || (is_hex && nasm_isxdigit(*r)) ||
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700930 (!is_hex && (*r == 'e' || *r == 'E')) ||
931 (*r == 'p' || *r == 'P')) {
932 p = r;
933 is_float = true;
934 } else
935 break; /* Terminate the token */
936 } else
937 break;
938 }
939 p--; /* Point to first character beyond number */
940
H. Peter Anvin8e1f8112009-04-17 14:20:44 -0700941 if (p == line+1 && *line == '$') {
942 type = TOK_OTHER; /* TOKEN_HERE */
943 } else {
944 if (has_e && !is_hex) {
945 /* 1e13 is floating-point, but 1e13h is not */
946 is_float = true;
947 }
H. Peter Anvind784a082009-04-20 14:01:18 -0700948
H. Peter Anvin8e1f8112009-04-17 14:20:44 -0700949 type = is_float ? TOK_FLOAT : TOK_NUMBER;
H. Peter Anvinc2df2822007-10-24 15:29:28 -0700950 }
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700951 } else if (nasm_isspace(*p)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000952 type = TOK_WHITESPACE;
953 p++;
H. Peter Anvinbda7a6e2008-06-21 10:23:17 -0700954 while (*p && nasm_isspace(*p))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000955 p++;
956 /*
957 * Whitespace just before end-of-line is discarded by
958 * pretending it's a comment; whitespace just before a
959 * comment gets lumped into the comment.
960 */
961 if (!*p || *p == ';') {
962 type = TOK_COMMENT;
963 while (*p)
964 p++;
965 }
966 } else if (*p == ';') {
967 type = TOK_COMMENT;
968 while (*p)
969 p++;
970 } else {
971 /*
972 * Anything else is an operator of some kind. We check
973 * for all the double-character operators (>>, <<, //,
974 * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000975 * else is a single-character operator.
H. Peter Anvine2c80182005-01-15 22:15:51 +0000976 */
977 type = TOK_OTHER;
978 if ((p[0] == '>' && p[1] == '>') ||
979 (p[0] == '<' && p[1] == '<') ||
980 (p[0] == '/' && p[1] == '/') ||
981 (p[0] == '<' && p[1] == '=') ||
982 (p[0] == '>' && p[1] == '=') ||
983 (p[0] == '=' && p[1] == '=') ||
984 (p[0] == '!' && p[1] == '=') ||
985 (p[0] == '<' && p[1] == '>') ||
986 (p[0] == '&' && p[1] == '&') ||
987 (p[0] == '|' && p[1] == '|') ||
988 (p[0] == '^' && p[1] == '^')) {
989 p++;
990 }
991 p++;
992 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +0000993
H. Peter Anvine2c80182005-01-15 22:15:51 +0000994 /* Handling unterminated string by UNV */
995 /*if (type == -1)
996 {
997 *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
998 t->text[p-line] = *line;
999 tail = &t->next;
1000 }
1001 else */
1002 if (type != TOK_COMMENT) {
1003 *tail = t = new_Token(NULL, type, line, p - line);
1004 tail = &t->next;
1005 }
1006 line = p;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001007 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001008 return list;
1009}
1010
H. Peter Anvince616072002-04-30 21:02:23 +00001011/*
1012 * this function allocates a new managed block of memory and
H. Peter Anvin70653092007-10-19 14:42:29 -07001013 * returns a pointer to the block. The managed blocks are
H. Peter Anvince616072002-04-30 21:02:23 +00001014 * deleted only all at once by the delete_Blocks function.
1015 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001016static void *new_Block(size_t size)
H. Peter Anvince616072002-04-30 21:02:23 +00001017{
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001018 Blocks *b = &blocks;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001019
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001020 /* first, get to the end of the linked list */
1021 while (b->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001022 b = b->next;
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001023 /* now allocate the requested chunk */
1024 b->chunk = nasm_malloc(size);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001025
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001026 /* now allocate a new block for the next request */
1027 b->next = nasm_malloc(sizeof(Blocks));
1028 /* and initialize the contents of the new block */
1029 b->next->next = NULL;
1030 b->next->chunk = NULL;
1031 return b->chunk;
H. Peter Anvince616072002-04-30 21:02:23 +00001032}
1033
1034/*
1035 * this function deletes all managed blocks of memory
1036 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001037static void delete_Blocks(void)
H. Peter Anvince616072002-04-30 21:02:23 +00001038{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001039 Blocks *a, *b = &blocks;
H. Peter Anvince616072002-04-30 21:02:23 +00001040
H. Peter Anvin70653092007-10-19 14:42:29 -07001041 /*
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001042 * keep in mind that the first block, pointed to by blocks
H. Peter Anvin70653092007-10-19 14:42:29 -07001043 * is a static and not dynamically allocated, so we don't
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001044 * free it.
1045 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001046 while (b) {
1047 if (b->chunk)
1048 nasm_free(b->chunk);
1049 a = b;
1050 b = b->next;
1051 if (a != &blocks)
1052 nasm_free(a);
Nickolay Yurchenkof7956c42003-09-26 19:03:40 +00001053 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001054}
H. Peter Anvin734b1882002-04-30 21:01:08 +00001055
1056/*
H. Peter Anvin70653092007-10-19 14:42:29 -07001057 * this function creates a new Token and passes a pointer to it
H. Peter Anvin734b1882002-04-30 21:01:08 +00001058 * back to the caller. It sets the type and text elements, and
H. Peter Anvinf26e0972008-07-01 21:26:27 -07001059 * also the a.mac and next elements to NULL.
H. Peter Anvin734b1882002-04-30 21:01:08 +00001060 */
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001061static Token *new_Token(Token * next, enum pp_token_type type,
H. Peter Anvinc751e862008-06-09 10:18:45 -07001062 const char *text, int txtlen)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001063{
1064 Token *t;
1065 int i;
1066
H. Peter Anvine2c80182005-01-15 22:15:51 +00001067 if (freeTokens == NULL) {
1068 freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
1069 for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
1070 freeTokens[i].next = &freeTokens[i + 1];
1071 freeTokens[i].next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001072 }
1073 t = freeTokens;
1074 freeTokens = t->next;
1075 t->next = next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07001076 t->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001077 t->type = type;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001078 if (type == TOK_WHITESPACE || text == NULL) {
1079 t->text = NULL;
1080 } else {
1081 if (txtlen == 0)
1082 txtlen = strlen(text);
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001083 t->text = nasm_malloc(txtlen+1);
1084 memcpy(t->text, text, txtlen);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001085 t->text[txtlen] = '\0';
H. Peter Anvin734b1882002-04-30 21:01:08 +00001086 }
1087 return t;
1088}
1089
H. Peter Anvine2c80182005-01-15 22:15:51 +00001090static Token *delete_Token(Token * t)
H. Peter Anvin734b1882002-04-30 21:01:08 +00001091{
1092 Token *next = t->next;
1093 nasm_free(t->text);
H. Peter Anvin788e6c12002-04-30 21:02:01 +00001094 t->next = freeTokens;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001095 freeTokens = t;
1096 return next;
1097}
1098
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001099/*
1100 * Convert a line of tokens back into text.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001101 * If expand_locals is not zero, identifiers of the form "%$*xxx"
1102 * will be transformed into ..@ctxnum.xxx
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001103 */
H. Peter Anvin9e200162008-06-04 17:23:14 -07001104static char *detoken(Token * tlist, bool expand_locals)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001105{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001106 Token *t;
1107 int len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001108 char *line, *p;
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001109 const char *q;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001110
1111 len = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001112 for (t = tlist; t; t = t->next) {
1113 if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001114 char *p = getenv(t->text + 2);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001115 nasm_free(t->text);
1116 if (p)
1117 t->text = nasm_strdup(p);
1118 else
1119 t->text = NULL;
1120 }
1121 /* Expand local macros here and not during preprocessing */
1122 if (expand_locals &&
1123 t->type == TOK_PREPROC_ID && t->text &&
1124 t->text[0] == '%' && t->text[1] == '$') {
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001125 const char *q;
1126 char *p;
1127 Context *ctx = get_ctx(t->text, &q, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001128 if (ctx) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001129 char buffer[40];
Keith Kanios93f2e9a2007-04-14 00:10:59 +00001130 snprintf(buffer, sizeof(buffer), "..@%"PRIu32".", ctx->number);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001131 p = nasm_strcat(buffer, q);
1132 nasm_free(t->text);
1133 t->text = p;
1134 }
1135 }
1136 if (t->type == TOK_WHITESPACE) {
1137 len++;
1138 } else if (t->text) {
1139 len += strlen(t->text);
1140 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001141 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00001142 p = line = nasm_malloc(len + 1);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001143 for (t = tlist; t; t = t->next) {
1144 if (t->type == TOK_WHITESPACE) {
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001145 *p++ = ' ';
H. Peter Anvine2c80182005-01-15 22:15:51 +00001146 } else if (t->text) {
H. Peter Anvinb4daadc2008-01-21 16:31:57 -08001147 q = t->text;
1148 while (*q)
1149 *p++ = *q++;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001150 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001151 }
1152 *p = '\0';
1153 return line;
1154}
1155
1156/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001157 * A scanner, suitable for use by the expression evaluator, which
1158 * operates on a line of Tokens. Expects a pointer to a pointer to
1159 * the first token in the line to be passed in as its private_data
1160 * field.
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001161 *
1162 * FIX: This really needs to be unified with stdscan.
H. Peter Anvin76690a12002-04-30 20:52:49 +00001163 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001164static int ppscan(void *private_data, struct tokenval *tokval)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001165{
H. Peter Anvin76690a12002-04-30 20:52:49 +00001166 Token **tlineptr = private_data;
1167 Token *tline;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001168 char ourcopy[MAX_KEYWORD+1], *p, *r, *s;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001169
H. Peter Anvine2c80182005-01-15 22:15:51 +00001170 do {
1171 tline = *tlineptr;
1172 *tlineptr = tline ? tline->next : NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001173 }
1174 while (tline && (tline->type == TOK_WHITESPACE ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001175 tline->type == TOK_COMMENT));
H. Peter Anvin76690a12002-04-30 20:52:49 +00001176
1177 if (!tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001178 return tokval->t_type = TOKEN_EOS;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001179
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001180 tokval->t_charptr = tline->text;
1181
H. Peter Anvin76690a12002-04-30 20:52:49 +00001182 if (tline->text[0] == '$' && !tline->text[1])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001183 return tokval->t_type = TOKEN_HERE;
H. Peter Anvin7cf897e2002-05-30 21:30:33 +00001184 if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
H. Peter Anvine2c80182005-01-15 22:15:51 +00001185 return tokval->t_type = TOKEN_BASE;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001186
H. Peter Anvine2c80182005-01-15 22:15:51 +00001187 if (tline->type == TOK_ID) {
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001188 p = tokval->t_charptr = tline->text;
1189 if (p[0] == '$') {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001190 tokval->t_charptr++;
1191 return tokval->t_type = TOKEN_ID;
1192 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001193
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001194 for (r = p, s = ourcopy; *r; r++) {
Philipp Thomas76ec8e72008-05-21 08:53:21 -07001195 if (r >= p+MAX_KEYWORD)
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001196 return tokval->t_type = TOKEN_ID; /* Not a keyword */
H. Peter Anvinac8f8fc2008-06-11 15:49:41 -07001197 *s++ = nasm_tolower(*r);
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001198 }
1199 *s = '\0';
1200 /* right, so we have an identifier sitting in temp storage. now,
1201 * is it actually a register or instruction name, or what? */
1202 return nasm_token_hash(ourcopy, tokval);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001203 }
1204
H. Peter Anvine2c80182005-01-15 22:15:51 +00001205 if (tline->type == TOK_NUMBER) {
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001206 bool rn_error;
1207 tokval->t_integer = readnum(tline->text, &rn_error);
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001208 tokval->t_charptr = tline->text;
H. Peter Anvin11627042008-06-09 20:45:19 -07001209 if (rn_error)
1210 return tokval->t_type = TOKEN_ERRNUM;
1211 else
1212 return tokval->t_type = TOKEN_NUM;
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001213 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00001214
H. Peter Anvinc2df2822007-10-24 15:29:28 -07001215 if (tline->type == TOK_FLOAT) {
1216 return tokval->t_type = TOKEN_FLOAT;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001217 }
1218
H. Peter Anvine2c80182005-01-15 22:15:51 +00001219 if (tline->type == TOK_STRING) {
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07001220 char bq, *ep;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001221
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07001222 bq = tline->text[0];
H. Peter Anvin11627042008-06-09 20:45:19 -07001223 tokval->t_charptr = tline->text;
1224 tokval->t_inttwo = nasm_unquote(tline->text, &ep);
H. Peter Anvind2456592008-06-19 15:04:18 -07001225
H. Peter Anvin11627042008-06-09 20:45:19 -07001226 if (ep[0] != bq || ep[1] != '\0')
1227 return tokval->t_type = TOKEN_ERRSTR;
1228 else
1229 return tokval->t_type = TOKEN_STR;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001230 }
1231
H. Peter Anvine2c80182005-01-15 22:15:51 +00001232 if (tline->type == TOK_OTHER) {
1233 if (!strcmp(tline->text, "<<"))
1234 return tokval->t_type = TOKEN_SHL;
1235 if (!strcmp(tline->text, ">>"))
1236 return tokval->t_type = TOKEN_SHR;
1237 if (!strcmp(tline->text, "//"))
1238 return tokval->t_type = TOKEN_SDIV;
1239 if (!strcmp(tline->text, "%%"))
1240 return tokval->t_type = TOKEN_SMOD;
1241 if (!strcmp(tline->text, "=="))
1242 return tokval->t_type = TOKEN_EQ;
1243 if (!strcmp(tline->text, "<>"))
1244 return tokval->t_type = TOKEN_NE;
1245 if (!strcmp(tline->text, "!="))
1246 return tokval->t_type = TOKEN_NE;
1247 if (!strcmp(tline->text, "<="))
1248 return tokval->t_type = TOKEN_LE;
1249 if (!strcmp(tline->text, ">="))
1250 return tokval->t_type = TOKEN_GE;
1251 if (!strcmp(tline->text, "&&"))
1252 return tokval->t_type = TOKEN_DBL_AND;
1253 if (!strcmp(tline->text, "^^"))
1254 return tokval->t_type = TOKEN_DBL_XOR;
1255 if (!strcmp(tline->text, "||"))
1256 return tokval->t_type = TOKEN_DBL_OR;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001257 }
1258
1259 /*
1260 * We have no other options: just return the first character of
1261 * the token text.
1262 */
1263 return tokval->t_type = tline->text[0];
1264}
1265
1266/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001267 * Compare a string to the name of an existing macro; this is a
1268 * simple wrapper which calls either strcmp or nasm_stricmp
1269 * depending on the value of the `casesense' parameter.
1270 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001271static int mstrcmp(const char *p, const char *q, bool casesense)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001272{
H. Peter Anvin734b1882002-04-30 21:01:08 +00001273 return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001274}
1275
1276/*
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001277 * Compare a string to the name of an existing macro; this is a
1278 * simple wrapper which calls either strcmp or nasm_stricmp
1279 * depending on the value of the `casesense' parameter.
1280 */
1281static int mmemcmp(const char *p, const char *q, size_t l, bool casesense)
1282{
1283 return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l);
1284}
1285
1286/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001287 * Return the Context structure associated with a %$ token. Return
1288 * NULL, having _already_ reported an error condition, if the
1289 * context stack isn't deep enough for the supplied number of $
1290 * signs.
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001291 * If all_contexts == true, contexts that enclose current are
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001292 * also scanned for such smacro, until it is found; if not -
1293 * only the context that directly results from the number of $'s
1294 * in variable's name.
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001295 *
1296 * If "namep" is non-NULL, set it to the pointer to the macro name
1297 * tail, i.e. the part beyond %$...
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001298 */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001299static Context *get_ctx(const char *name, const char **namep,
1300 bool all_contexts)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001301{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001302 Context *ctx;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001303 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001304 int i;
1305
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001306 if (namep)
1307 *namep = name;
1308
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001309 if (!name || name[0] != '%' || name[1] != '$')
H. Peter Anvine2c80182005-01-15 22:15:51 +00001310 return NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001311
H. Peter Anvine2c80182005-01-15 22:15:51 +00001312 if (!cstk) {
1313 error(ERR_NONFATAL, "`%s': context stack is empty", name);
1314 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001315 }
1316
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001317 name += 2;
1318 ctx = cstk;
1319 i = 0;
1320 while (ctx && *name == '$') {
1321 name++;
1322 i++;
1323 ctx = ctx->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001324 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001325 if (!ctx) {
1326 error(ERR_NONFATAL, "`%s': context stack is only"
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001327 " %d level%s deep", name, i, (i == 1 ? "" : "s"));
H. Peter Anvine2c80182005-01-15 22:15:51 +00001328 return NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001329 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001330
1331 if (namep)
1332 *namep = name;
1333
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001334 if (!all_contexts)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001335 return ctx;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001336
H. Peter Anvine2c80182005-01-15 22:15:51 +00001337 do {
1338 /* Search for this smacro in found context */
H. Peter Anvin166c2472008-05-28 12:28:58 -07001339 m = hash_findix(&ctx->localmac, name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001340 while (m) {
1341 if (!mstrcmp(m->name, name, m->casesense))
1342 return ctx;
1343 m = m->next;
1344 }
1345 ctx = ctx->next;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001346 }
1347 while (ctx);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001348 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001349}
1350
1351/*
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001352 * Check to see if a file is already in a string list
1353 */
1354static bool in_list(const StrList *list, const char *str)
1355{
1356 while (list) {
1357 if (!strcmp(list->str, str))
1358 return true;
1359 list = list->next;
1360 }
1361 return false;
1362}
1363
1364/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001365 * Open an include file. This routine must always return a valid
1366 * file pointer if it returns - it's responsible for throwing an
1367 * ERR_FATAL and bombing out completely if not. It should also try
1368 * the include path one by one until it finds the file or reaches
1369 * the end of the path.
1370 */
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07001371static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
H. Peter Anvin418ca702008-05-30 10:42:30 -07001372 bool missing_ok)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001373{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001374 FILE *fp;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001375 char *prefix = "";
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001376 IncPath *ip = ipath;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001377 int len = strlen(file);
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001378 size_t prefix_len = 0;
1379 StrList *sl;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001380
H. Peter Anvine2c80182005-01-15 22:15:51 +00001381 while (1) {
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001382 sl = nasm_malloc(prefix_len+len+1+sizeof sl->next);
1383 memcpy(sl->str, prefix, prefix_len);
1384 memcpy(sl->str+prefix_len, file, len+1);
1385 fp = fopen(sl->str, "r");
H. Peter Anvin418ca702008-05-30 10:42:30 -07001386 if (fp && dhead && !in_list(*dhead, sl->str)) {
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001387 sl->next = NULL;
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07001388 **dtail = sl;
1389 *dtail = &sl->next;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001390 } else {
1391 nasm_free(sl);
1392 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001393 if (fp)
1394 return fp;
H. Peter Anvin418ca702008-05-30 10:42:30 -07001395 if (!ip) {
1396 if (!missing_ok)
1397 break;
1398 prefix = NULL;
1399 } else {
1400 prefix = ip->path;
1401 ip = ip->next;
1402 }
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001403 if (prefix) {
1404 prefix_len = strlen(prefix);
1405 } else {
1406 /* -MG given and file not found */
H. Peter Anvin418ca702008-05-30 10:42:30 -07001407 if (dhead && !in_list(*dhead, file)) {
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001408 sl = nasm_malloc(len+1+sizeof sl->next);
1409 sl->next = NULL;
1410 strcpy(sl->str, file);
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07001411 **dtail = sl;
1412 *dtail = &sl->next;
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07001413 }
H. Peter Anvin37a321f2007-09-24 13:41:58 -07001414 return NULL;
1415 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001416 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001417
H. Peter Anvin734b1882002-04-30 21:01:08 +00001418 error(ERR_FATAL, "unable to open include file `%s'", file);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001419 return NULL; /* never reached - placate compilers */
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001420}
1421
1422/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001423 * Determine if we should warn on defining a single-line macro of
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001424 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001425 * return true if _any_ single-line macro of that name is defined.
1426 * Otherwise, will return true if a single-line macro with either
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001427 * `nparam' or no parameters is defined.
1428 *
1429 * If a macro with precisely the right number of parameters is
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001430 * defined, or nparam is -1, the address of the definition structure
1431 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001432 * is NULL, no action will be taken regarding its contents, and no
1433 * error will occur.
1434 *
1435 * Note that this is also called with nparam zero to resolve
1436 * `ifdef'.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001437 *
1438 * If you already know which context macro belongs to, you can pass
1439 * the context pointer as first parameter; if you won't but name begins
1440 * with %$ the context will be automatically computed. If all_contexts
1441 * is true, macro will be searched in outer contexts as well.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001442 */
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001443static bool
H. Peter Anvinb2a5fda2008-06-19 21:42:42 -07001444smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001445 bool nocase)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001446{
H. Peter Anvin166c2472008-05-28 12:28:58 -07001447 struct hash_table *smtbl;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001448 SMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001449
H. Peter Anvin97a23472007-09-16 17:57:25 -07001450 if (ctx) {
H. Peter Anvin166c2472008-05-28 12:28:58 -07001451 smtbl = &ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001452 } else if (name[0] == '%' && name[1] == '$') {
1453 if (cstk)
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001454 ctx = get_ctx(name, &name, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001455 if (!ctx)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001456 return false; /* got to return _something_ */
H. Peter Anvin166c2472008-05-28 12:28:58 -07001457 smtbl = &ctx->localmac;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001458 } else {
H. Peter Anvin166c2472008-05-28 12:28:58 -07001459 smtbl = &smacros;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001460 }
H. Peter Anvin166c2472008-05-28 12:28:58 -07001461 m = (SMacro *) hash_findix(smtbl, name);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001462
H. Peter Anvine2c80182005-01-15 22:15:51 +00001463 while (m) {
1464 if (!mstrcmp(m->name, name, m->casesense && nocase) &&
Charles Crayne192d5b52007-10-18 19:02:42 -07001465 (nparam <= 0 || m->nparam == 0 || nparam == (int) m->nparam)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001466 if (defn) {
Charles Crayne192d5b52007-10-18 19:02:42 -07001467 if (nparam == (int) m->nparam || nparam == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001468 *defn = m;
1469 else
1470 *defn = NULL;
1471 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001472 return true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001473 }
1474 m = m->next;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001475 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001476
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001477 return false;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001478}
1479
1480/*
1481 * Count and mark off the parameters in a multi-line macro call.
1482 * This is called both from within the multi-line macro expansion
1483 * code, and also to mark off the default parameters when provided
1484 * in a %macro definition line.
1485 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001486static void count_mmac_params(Token * t, int *nparam, Token *** params)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001487{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001488 int paramsize, brace;
1489
1490 *nparam = paramsize = 0;
1491 *params = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001492 while (t) {
H. Peter Anvin91fb6f12008-09-01 10:56:33 -07001493 /* +1: we need space for the final NULL */
1494 if (*nparam+1 >= paramsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001495 paramsize += PARAM_DELTA;
1496 *params = nasm_realloc(*params, sizeof(**params) * paramsize);
1497 }
1498 skip_white_(t);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001499 brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001500 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001501 brace = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001502 (*params)[(*nparam)++] = t;
1503 while (tok_isnt_(t, brace ? "}" : ","))
1504 t = t->next;
1505 if (t) { /* got a comma/brace */
1506 t = t->next;
1507 if (brace) {
1508 /*
1509 * Now we've found the closing brace, look further
1510 * for the comma.
1511 */
1512 skip_white_(t);
1513 if (tok_isnt_(t, ",")) {
1514 error(ERR_NONFATAL,
1515 "braces do not enclose all of macro parameter");
1516 while (tok_isnt_(t, ","))
1517 t = t->next;
1518 }
1519 if (t)
1520 t = t->next; /* eat the comma */
1521 }
1522 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001523 }
1524}
1525
1526/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00001527 * Determine whether one of the various `if' conditions is true or
1528 * not.
1529 *
1530 * We must free the tline we get passed.
1531 */
H. Peter Anvin70055962007-10-11 00:05:31 -07001532static bool if_condition(Token * tline, enum preproc_token ct)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001533{
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001534 enum pp_conditional i = PP_COND(ct);
H. Peter Anvin70055962007-10-11 00:05:31 -07001535 bool j;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001536 Token *t, *tt, **tptr, *origline;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001537 struct tokenval tokval;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001538 expr *evalresult;
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001539 enum pp_token_type needtype;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001540
1541 origline = tline;
1542
H. Peter Anvine2c80182005-01-15 22:15:51 +00001543 switch (i) {
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001544 case PPC_IFCTX:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001545 j = false; /* have we matched yet? */
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001546 while (true) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001547 skip_white_(tline);
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001548 if (!tline)
1549 break;
1550 if (tline->type != TOK_ID) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001551 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001552 "`%s' expects context identifiers", pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001553 free_tlist(origline);
1554 return -1;
1555 }
Victor van den Elzen0e857f12008-07-23 13:21:29 +02001556 if (cstk && cstk->name && !nasm_stricmp(tline->text, cstk->name))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001557 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001558 tline = tline->next;
1559 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001560 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001561
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001562 case PPC_IFDEF:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001563 j = false; /* have we matched yet? */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001564 while (tline) {
1565 skip_white_(tline);
1566 if (!tline || (tline->type != TOK_ID &&
1567 (tline->type != TOK_PREPROC_ID ||
1568 tline->text[1] != '$'))) {
1569 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001570 "`%s' expects macro identifiers", pp_directives[ct]);
1571 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001572 }
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001573 if (smacro_defined(NULL, tline->text, 0, NULL, true))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001574 j = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001575 tline = tline->next;
1576 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001577 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00001578
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001579 case PPC_IFIDN:
1580 case PPC_IFIDNI:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001581 tline = expand_smacro(tline);
1582 t = tt = tline;
1583 while (tok_isnt_(tt, ","))
1584 tt = tt->next;
1585 if (!tt) {
1586 error(ERR_NONFATAL,
1587 "`%s' expects two comma-separated arguments",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001588 pp_directives[ct]);
1589 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001590 }
1591 tt = tt->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001592 j = true; /* assume equality unless proved not */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001593 while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt) {
1594 if (tt->type == TOK_OTHER && !strcmp(tt->text, ",")) {
1595 error(ERR_NONFATAL, "`%s': more than one comma on line",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001596 pp_directives[ct]);
1597 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001598 }
1599 if (t->type == TOK_WHITESPACE) {
1600 t = t->next;
1601 continue;
1602 }
1603 if (tt->type == TOK_WHITESPACE) {
1604 tt = tt->next;
1605 continue;
1606 }
1607 if (tt->type != t->type) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001608 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001609 break;
1610 }
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001611 /* When comparing strings, need to unquote them first */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001612 if (t->type == TOK_STRING) {
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07001613 size_t l1 = nasm_unquote(t->text, NULL);
1614 size_t l2 = nasm_unquote(tt->text, NULL);
H. Peter Anvind2456592008-06-19 15:04:18 -07001615
H. Peter Anvin6ecc1592008-06-01 21:34:49 -07001616 if (l1 != l2) {
1617 j = false;
1618 break;
1619 }
1620 if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) {
1621 j = false;
1622 break;
1623 }
1624 } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001625 j = false; /* found mismatching tokens */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001626 break;
1627 }
Nickolay Yurchenkof3b3ce22003-09-21 20:38:43 +00001628
H. Peter Anvine2c80182005-01-15 22:15:51 +00001629 t = t->next;
1630 tt = tt->next;
1631 }
1632 if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001633 j = false; /* trailing gunk on one end or other */
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001634 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001635
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001636 case PPC_IFMACRO:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001637 {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001638 bool found = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001639 MMacro searching, *mmac;
H. Peter Anvin65747262002-05-07 00:10:05 +00001640
H. Peter Anvine2c80182005-01-15 22:15:51 +00001641 skip_white_(tline);
1642 tline = expand_id(tline);
1643 if (!tok_type_(tline, TOK_ID)) {
1644 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001645 "`%s' expects a macro name", pp_directives[ct]);
1646 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001647 }
1648 searching.name = nasm_strdup(tline->text);
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001649 searching.casesense = true;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001650 searching.plus = false;
1651 searching.nolist = false;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07001652 searching.in_progress = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001653 searching.rep_nest = NULL;
1654 searching.nparam_min = 0;
1655 searching.nparam_max = INT_MAX;
1656 tline = expand_smacro(tline->next);
1657 skip_white_(tline);
1658 if (!tline) {
1659 } else if (!tok_type_(tline, TOK_NUMBER)) {
1660 error(ERR_NONFATAL,
1661 "`%s' expects a parameter count or nothing",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001662 pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001663 } else {
1664 searching.nparam_min = searching.nparam_max =
1665 readnum(tline->text, &j);
1666 if (j)
1667 error(ERR_NONFATAL,
1668 "unable to parse parameter count `%s'",
1669 tline->text);
1670 }
1671 if (tline && tok_is_(tline->next, "-")) {
1672 tline = tline->next->next;
1673 if (tok_is_(tline, "*"))
1674 searching.nparam_max = INT_MAX;
1675 else if (!tok_type_(tline, TOK_NUMBER))
1676 error(ERR_NONFATAL,
1677 "`%s' expects a parameter count after `-'",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001678 pp_directives[ct]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001679 else {
1680 searching.nparam_max = readnum(tline->text, &j);
1681 if (j)
1682 error(ERR_NONFATAL,
1683 "unable to parse parameter count `%s'",
1684 tline->text);
1685 if (searching.nparam_min > searching.nparam_max)
1686 error(ERR_NONFATAL,
1687 "minimum parameter count exceeds maximum");
1688 }
1689 }
1690 if (tline && tok_is_(tline->next, "+")) {
1691 tline = tline->next;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001692 searching.plus = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001693 }
H. Peter Anvin166c2472008-05-28 12:28:58 -07001694 mmac = (MMacro *) hash_findix(&mmacros, searching.name);
H. Peter Anvin97a23472007-09-16 17:57:25 -07001695 while (mmac) {
1696 if (!strcmp(mmac->name, searching.name) &&
1697 (mmac->nparam_min <= searching.nparam_max
1698 || searching.plus)
1699 && (searching.nparam_min <= mmac->nparam_max
1700 || mmac->plus)) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07001701 found = true;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001702 break;
1703 }
1704 mmac = mmac->next;
1705 }
Victor van den Elzenb916ede2008-07-23 15:14:22 +02001706 if(tline && tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07001707 error(ERR_WARNING|ERR_PASS1,
1708 "trailing garbage after %%ifmacro ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001709 nasm_free(searching.name);
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001710 j = found;
1711 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001712 }
H. Peter Anvin65747262002-05-07 00:10:05 +00001713
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001714 case PPC_IFID:
1715 needtype = TOK_ID;
1716 goto iftype;
1717 case PPC_IFNUM:
1718 needtype = TOK_NUMBER;
1719 goto iftype;
1720 case PPC_IFSTR:
1721 needtype = TOK_STRING;
1722 goto iftype;
1723
1724 iftype:
H. Peter Anvin134b9462008-02-16 17:01:40 -08001725 t = tline = expand_smacro(tline);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001726
H. Peter Anvin927c92b2008-02-16 13:44:52 -08001727 while (tok_type_(t, TOK_WHITESPACE) ||
1728 (needtype == TOK_NUMBER &&
1729 tok_type_(t, TOK_OTHER) &&
1730 (t->text[0] == '-' || t->text[0] == '+') &&
1731 !t->text[1]))
1732 t = t->next;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001733
H. Peter Anvincbf768d2008-02-16 16:41:25 -08001734 j = tok_type_(t, needtype);
1735 break;
1736
1737 case PPC_IFTOKEN:
1738 t = tline = expand_smacro(tline);
1739 while (tok_type_(t, TOK_WHITESPACE))
1740 t = t->next;
1741
1742 j = false;
1743 if (t) {
1744 t = t->next; /* Skip the actual token */
1745 while (tok_type_(t, TOK_WHITESPACE))
1746 t = t->next;
1747 j = !t; /* Should be nothing left */
1748 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001749 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001750
H. Peter Anvin134b9462008-02-16 17:01:40 -08001751 case PPC_IFEMPTY:
1752 t = tline = expand_smacro(tline);
1753 while (tok_type_(t, TOK_WHITESPACE))
1754 t = t->next;
1755
1756 j = !t; /* Should be empty */
1757 break;
1758
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001759 case PPC_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001760 t = tline = expand_smacro(tline);
1761 tptr = &t;
1762 tokval.t_type = TOKEN_INVALID;
1763 evalresult = evaluate(ppscan, tptr, &tokval,
1764 NULL, pass | CRITICAL, error, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001765 if (!evalresult)
1766 return -1;
1767 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07001768 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001769 "trailing garbage after expression ignored");
1770 if (!is_simple(evalresult)) {
1771 error(ERR_NONFATAL,
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001772 "non-constant value given to `%s'", pp_directives[ct]);
1773 goto fail;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001774 }
Chuck Crayne60ae75d2007-05-02 01:59:16 +00001775 j = reloc_value(evalresult) != 0;
H. Peter Anvin90e6e812008-07-16 14:38:24 -07001776 break;
H. Peter Anvin95e28822007-09-12 04:20:08 +00001777
H. Peter Anvine2c80182005-01-15 22:15:51 +00001778 default:
1779 error(ERR_FATAL,
1780 "preprocessor directive `%s' not yet implemented",
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001781 pp_directives[ct]);
1782 goto fail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001783 }
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001784
1785 free_tlist(origline);
1786 return j ^ PP_NEGATIVE(ct);
H. Peter Anvin70653092007-10-19 14:42:29 -07001787
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00001788fail:
1789 free_tlist(origline);
1790 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001791}
1792
1793/*
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001794 * Common code for defining an smacro
1795 */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001796static bool define_smacro(Context *ctx, const char *mname, bool casesense,
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001797 int nparam, Token *expansion)
1798{
1799 SMacro *smac, **smhead;
H. Peter Anvin166c2472008-05-28 12:28:58 -07001800 struct hash_table *smtbl;
H. Peter Anvin70653092007-10-19 14:42:29 -07001801
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001802 if (smacro_defined(ctx, mname, nparam, &smac, casesense)) {
1803 if (!smac) {
H. Peter Anvin917a3492008-09-24 09:14:49 -07001804 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001805 "single-line macro `%s' defined both with and"
1806 " without parameters", mname);
1807
1808 /* Some instances of the old code considered this a failure,
1809 some others didn't. What is the right thing to do here? */
1810 free_tlist(expansion);
1811 return false; /* Failure */
1812 } else {
1813 /*
1814 * We're redefining, so we have to take over an
1815 * existing SMacro structure. This means freeing
1816 * what was already in it.
1817 */
1818 nasm_free(smac->name);
1819 free_tlist(smac->expansion);
1820 }
1821 } else {
H. Peter Anvin166c2472008-05-28 12:28:58 -07001822 smtbl = ctx ? &ctx->localmac : &smacros;
1823 smhead = (SMacro **) hash_findi_add(smtbl, mname);
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001824 smac = nasm_malloc(sizeof(SMacro));
1825 smac->next = *smhead;
1826 *smhead = smac;
1827 }
1828 smac->name = nasm_strdup(mname);
1829 smac->casesense = casesense;
1830 smac->nparam = nparam;
1831 smac->expansion = expansion;
1832 smac->in_progress = false;
1833 return true; /* Success */
1834}
1835
1836/*
1837 * Undefine an smacro
1838 */
1839static void undef_smacro(Context *ctx, const char *mname)
1840{
1841 SMacro **smhead, *s, **sp;
H. Peter Anvin166c2472008-05-28 12:28:58 -07001842 struct hash_table *smtbl;
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001843
H. Peter Anvin166c2472008-05-28 12:28:58 -07001844 smtbl = ctx ? &ctx->localmac : &smacros;
1845 smhead = (SMacro **)hash_findi(smtbl, mname, NULL);
H. Peter Anvin70653092007-10-19 14:42:29 -07001846
H. Peter Anvin4db5a162007-10-11 13:42:09 -07001847 if (smhead) {
1848 /*
1849 * We now have a macro name... go hunt for it.
1850 */
1851 sp = smhead;
1852 while ((s = *sp) != NULL) {
1853 if (!mstrcmp(s->name, mname, s->casesense)) {
1854 *sp = s->next;
1855 nasm_free(s->name);
1856 free_tlist(s->expansion);
1857 nasm_free(s);
1858 } else {
1859 sp = &s->next;
1860 }
1861 }
1862 }
1863}
1864
H. Peter Anvin8781cb02007-11-08 20:01:11 -08001865/*
H. Peter Anvina26433d2008-07-16 14:40:01 -07001866 * Parse a mmacro specification.
1867 */
1868static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
1869{
1870 bool err;
1871
1872 tline = tline->next;
1873 skip_white_(tline);
1874 tline = expand_id(tline);
1875 if (!tok_type_(tline, TOK_ID)) {
1876 error(ERR_NONFATAL, "`%s' expects a macro name", directive);
1877 return false;
1878 }
Victor van den Elzenb916ede2008-07-23 15:14:22 +02001879
H. Peter Anvina26433d2008-07-16 14:40:01 -07001880 def->name = nasm_strdup(tline->text);
1881 def->plus = false;
1882 def->nolist = false;
1883 def->in_progress = 0;
1884 def->rep_nest = NULL;
Victor van den Elzenb916ede2008-07-23 15:14:22 +02001885 def->nparam_min = 0;
1886 def->nparam_max = 0;
1887
H. Peter Anvina26433d2008-07-16 14:40:01 -07001888 tline = expand_smacro(tline->next);
1889 skip_white_(tline);
1890 if (!tok_type_(tline, TOK_NUMBER)) {
1891 error(ERR_NONFATAL, "`%s' expects a parameter count", directive);
H. Peter Anvina26433d2008-07-16 14:40:01 -07001892 } else {
1893 def->nparam_min = def->nparam_max =
1894 readnum(tline->text, &err);
1895 if (err)
1896 error(ERR_NONFATAL,
1897 "unable to parse parameter count `%s'", tline->text);
1898 }
1899 if (tline && tok_is_(tline->next, "-")) {
1900 tline = tline->next->next;
1901 if (tok_is_(tline, "*")) {
1902 def->nparam_max = INT_MAX;
1903 } else if (!tok_type_(tline, TOK_NUMBER)) {
1904 error(ERR_NONFATAL,
1905 "`%s' expects a parameter count after `-'", directive);
1906 } else {
1907 def->nparam_max = readnum(tline->text, &err);
1908 if (err) {
1909 error(ERR_NONFATAL, "unable to parse parameter count `%s'",
1910 tline->text);
1911 }
1912 if (def->nparam_min > def->nparam_max) {
1913 error(ERR_NONFATAL, "minimum parameter count exceeds maximum");
1914 }
1915 }
1916 }
1917 if (tline && tok_is_(tline->next, "+")) {
1918 tline = tline->next;
1919 def->plus = true;
1920 }
1921 if (tline && tok_type_(tline->next, TOK_ID) &&
1922 !nasm_stricmp(tline->next->text, ".nolist")) {
1923 tline = tline->next;
1924 def->nolist = true;
1925 }
1926
1927 /*
1928 * Handle default parameters.
1929 */
1930 if (tline && tline->next) {
1931 def->dlist = tline->next;
1932 tline->next = NULL;
1933 count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
1934 } else {
1935 def->dlist = NULL;
1936 def->defaults = NULL;
1937 }
1938 def->expansion = NULL;
1939
Victor van den Elzen22343c22008-08-06 14:47:54 +02001940 if(def->defaults &&
1941 def->ndefs > def->nparam_max - def->nparam_min &&
1942 !def->plus)
H. Peter Anvin917a3492008-09-24 09:14:49 -07001943 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MDP,
1944 "too many default macro parameters");
Victor van den Elzenb916ede2008-07-23 15:14:22 +02001945
H. Peter Anvina26433d2008-07-16 14:40:01 -07001946 return true;
1947}
1948
1949
1950/*
H. Peter Anvin8781cb02007-11-08 20:01:11 -08001951 * Decode a size directive
1952 */
1953static int parse_size(const char *str) {
1954 static const char *size_names[] =
H. Peter Anvindfb91802008-05-20 11:43:53 -07001955 { "byte", "dword", "oword", "qword", "tword", "word", "yword" };
H. Peter Anvin8781cb02007-11-08 20:01:11 -08001956 static const int sizes[] =
H. Peter Anvindfb91802008-05-20 11:43:53 -07001957 { 0, 1, 4, 16, 8, 10, 2, 32 };
H. Peter Anvin8781cb02007-11-08 20:01:11 -08001958
1959 return sizes[bsii(str, size_names, elements(size_names))+1];
1960}
1961
Ed Beroset3ab3f412002-06-11 03:31:49 +00001962/**
1963 * find and process preprocessor directive in passed line
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001964 * Find out if a line contains a preprocessor directive, and deal
1965 * with it if so.
H. Peter Anvin70653092007-10-19 14:42:29 -07001966 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00001967 * If a directive _is_ found, it is the responsibility of this routine
1968 * (and not the caller) to free_tlist() the line.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001969 *
Ed Beroset3ab3f412002-06-11 03:31:49 +00001970 * @param tline a pointer to the current tokeninzed line linked list
1971 * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
H. Peter Anvin70653092007-10-19 14:42:29 -07001972 *
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001973 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001974static int do_directive(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001975{
H. Peter Anvin4169a472007-09-12 01:29:43 +00001976 enum preproc_token i;
1977 int j;
H. Peter Anvin70055962007-10-11 00:05:31 -07001978 bool err;
1979 int nparam;
1980 bool nolist;
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07001981 bool casesense;
H. Peter Anvin8cfdb9d2007-09-14 18:36:01 -07001982 int k, m;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00001983 int offset;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08001984 char *p, *pp;
1985 const char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001986 Include *inc;
1987 Context *ctx;
1988 Cond *cond;
H. Peter Anvin97a23472007-09-16 17:57:25 -07001989 MMacro *mmac, **mmhead;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001990 Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
1991 Line *l;
1992 struct tokenval tokval;
1993 expr *evalresult;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001994 MMacro *tmp_defining; /* Used when manipulating rep_nest */
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07001995 int64_t count;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07001996 size_t len;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07001997 int severity;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001998
1999 origline = tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002000
H. Peter Anvineba20a72002-04-30 20:53:55 +00002001 skip_white_(tline);
H. Peter Anvinf2936d72008-06-04 15:11:23 -07002002 if (!tline || !tok_type_(tline, TOK_PREPROC_ID) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00002003 (tline->text[1] == '%' || tline->text[1] == '$'
2004 || tline->text[1] == '!'))
2005 return NO_DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002006
H. Peter Anvin4169a472007-09-12 01:29:43 +00002007 i = pp_token_hash(tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002008
2009 /*
2010 * If we're in a non-emitting branch of a condition construct,
H. Peter Anvin76690a12002-04-30 20:52:49 +00002011 * or walking to the end of an already terminated %rep block,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002012 * we should ignore all directives except for condition
2013 * directives.
2014 */
H. Peter Anvin76690a12002-04-30 20:52:49 +00002015 if (((istk->conds && !emitting(istk->conds->state)) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00002016 (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) {
2017 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002018 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002019
2020 /*
H. Peter Anvin76690a12002-04-30 20:52:49 +00002021 * If we're defining a macro or reading a %rep block, we should
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02002022 * ignore all directives except for %macro/%imacro (which nest),
2023 * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
2024 * If we're in a %rep block, another %rep nests, so should be let through.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002025 */
2026 if (defining && i != PP_MACRO && i != PP_IMACRO &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00002027 i != PP_ENDMACRO && i != PP_ENDM &&
2028 (defining->name || (i != PP_ENDREP && i != PP_REP))) {
2029 return NO_DIRECTIVE_FOUND;
H. Peter Anvineba20a72002-04-30 20:53:55 +00002030 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002031
Charles Crayned4200be2008-07-12 16:42:33 -07002032 if (defining) {
2033 if (i == PP_MACRO || i == PP_IMACRO) {
2034 nested_mac_count++;
2035 return NO_DIRECTIVE_FOUND;
2036 } else if (nested_mac_count > 0) {
2037 if (i == PP_ENDMACRO) {
2038 nested_mac_count--;
2039 return NO_DIRECTIVE_FOUND;
2040 }
2041 }
2042 if (!defining->name) {
2043 if (i == PP_REP) {
2044 nested_rep_count++;
2045 return NO_DIRECTIVE_FOUND;
2046 } else if (nested_rep_count > 0) {
2047 if (i == PP_ENDREP) {
2048 nested_rep_count--;
2049 return NO_DIRECTIVE_FOUND;
2050 }
2051 }
2052 }
2053 }
2054
H. Peter Anvin4169a472007-09-12 01:29:43 +00002055 switch (i) {
2056 case PP_INVALID:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002057 error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
2058 tline->text);
2059 return NO_DIRECTIVE_FOUND; /* didn't get it */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00002060
H. Peter Anvine2c80182005-01-15 22:15:51 +00002061 case PP_STACKSIZE:
2062 /* Directive to tell NASM what the default stack size is. The
2063 * default is for a 16-bit stack, and this can be overriden with
2064 * %stacksize large.
2065 * the following form:
2066 *
2067 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2068 */
2069 tline = tline->next;
2070 if (tline && tline->type == TOK_WHITESPACE)
2071 tline = tline->next;
2072 if (!tline || tline->type != TOK_ID) {
2073 error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
2074 free_tlist(origline);
2075 return DIRECTIVE_FOUND;
2076 }
2077 if (nasm_stricmp(tline->text, "flat") == 0) {
2078 /* All subsequent ARG directives are for a 32-bit stack */
2079 StackSize = 4;
2080 StackPointer = "ebp";
2081 ArgOffset = 8;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002082 LocalOffset = 0;
Charles Crayne7eaf9192007-11-08 22:11:14 -08002083 } else if (nasm_stricmp(tline->text, "flat64") == 0) {
2084 /* All subsequent ARG directives are for a 64-bit stack */
2085 StackSize = 8;
2086 StackPointer = "rbp";
2087 ArgOffset = 8;
2088 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002089 } else if (nasm_stricmp(tline->text, "large") == 0) {
2090 /* All subsequent ARG directives are for a 16-bit stack,
2091 * far function call.
2092 */
2093 StackSize = 2;
2094 StackPointer = "bp";
2095 ArgOffset = 4;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002096 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002097 } else if (nasm_stricmp(tline->text, "small") == 0) {
2098 /* All subsequent ARG directives are for a 16-bit stack,
2099 * far function call. We don't support near functions.
2100 */
2101 StackSize = 2;
2102 StackPointer = "bp";
2103 ArgOffset = 6;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002104 LocalOffset = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002105 } else {
2106 error(ERR_NONFATAL, "`%%stacksize' invalid size type");
2107 free_tlist(origline);
2108 return DIRECTIVE_FOUND;
2109 }
2110 free_tlist(origline);
2111 return DIRECTIVE_FOUND;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002112
H. Peter Anvine2c80182005-01-15 22:15:51 +00002113 case PP_ARG:
2114 /* TASM like ARG directive to define arguments to functions, in
2115 * the following form:
2116 *
2117 * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
2118 */
2119 offset = ArgOffset;
2120 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002121 char *arg, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00002122 int size = StackSize;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002123
H. Peter Anvine2c80182005-01-15 22:15:51 +00002124 /* Find the argument name */
2125 tline = tline->next;
2126 if (tline && tline->type == TOK_WHITESPACE)
2127 tline = tline->next;
2128 if (!tline || tline->type != TOK_ID) {
2129 error(ERR_NONFATAL, "`%%arg' missing argument parameter");
2130 free_tlist(origline);
2131 return DIRECTIVE_FOUND;
2132 }
2133 arg = tline->text;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002134
H. Peter Anvine2c80182005-01-15 22:15:51 +00002135 /* Find the argument size type */
2136 tline = tline->next;
2137 if (!tline || tline->type != TOK_OTHER
2138 || tline->text[0] != ':') {
2139 error(ERR_NONFATAL,
2140 "Syntax error processing `%%arg' directive");
2141 free_tlist(origline);
2142 return DIRECTIVE_FOUND;
2143 }
2144 tline = tline->next;
2145 if (!tline || tline->type != TOK_ID) {
2146 error(ERR_NONFATAL, "`%%arg' missing size type parameter");
2147 free_tlist(origline);
2148 return DIRECTIVE_FOUND;
2149 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002150
H. Peter Anvine2c80182005-01-15 22:15:51 +00002151 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002152 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002153 tt = expand_smacro(tt);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002154 size = parse_size(tt->text);
2155 if (!size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002156 error(ERR_NONFATAL,
2157 "Invalid size type for `%%arg' missing directive");
2158 free_tlist(tt);
2159 free_tlist(origline);
2160 return DIRECTIVE_FOUND;
2161 }
2162 free_tlist(tt);
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002163
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002164 /* Round up to even stack slots */
2165 size = (size+StackSize-1) & ~(StackSize-1);
2166
H. Peter Anvine2c80182005-01-15 22:15:51 +00002167 /* Now define the macro for the argument */
2168 snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
2169 arg, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002170 do_directive(tokenize(directive));
H. Peter Anvine2c80182005-01-15 22:15:51 +00002171 offset += size;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002172
H. Peter Anvine2c80182005-01-15 22:15:51 +00002173 /* Move to the next argument in the list */
2174 tline = tline->next;
2175 if (tline && tline->type == TOK_WHITESPACE)
2176 tline = tline->next;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002177 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2178 ArgOffset = offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002179 free_tlist(origline);
2180 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002181
H. Peter Anvine2c80182005-01-15 22:15:51 +00002182 case PP_LOCAL:
2183 /* TASM like LOCAL directive to define local variables for a
2184 * function, in the following form:
2185 *
2186 * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
2187 *
2188 * The '= LocalSize' at the end is ignored by NASM, but is
2189 * required by TASM to define the local parameter size (and used
2190 * by the TASM macro package).
2191 */
2192 offset = LocalOffset;
2193 do {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00002194 char *local, directive[256];
H. Peter Anvine2c80182005-01-15 22:15:51 +00002195 int size = StackSize;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002196
H. Peter Anvine2c80182005-01-15 22:15:51 +00002197 /* Find the argument name */
2198 tline = tline->next;
2199 if (tline && tline->type == TOK_WHITESPACE)
2200 tline = tline->next;
2201 if (!tline || tline->type != TOK_ID) {
2202 error(ERR_NONFATAL,
2203 "`%%local' missing argument parameter");
2204 free_tlist(origline);
2205 return DIRECTIVE_FOUND;
2206 }
2207 local = tline->text;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002208
H. Peter Anvine2c80182005-01-15 22:15:51 +00002209 /* Find the argument size type */
2210 tline = tline->next;
2211 if (!tline || tline->type != TOK_OTHER
2212 || tline->text[0] != ':') {
2213 error(ERR_NONFATAL,
2214 "Syntax error processing `%%local' directive");
2215 free_tlist(origline);
2216 return DIRECTIVE_FOUND;
2217 }
2218 tline = tline->next;
2219 if (!tline || tline->type != TOK_ID) {
2220 error(ERR_NONFATAL,
2221 "`%%local' missing size type parameter");
2222 free_tlist(origline);
2223 return DIRECTIVE_FOUND;
2224 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002225
H. Peter Anvine2c80182005-01-15 22:15:51 +00002226 /* Allow macro expansion of type parameter */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002227 tt = tokenize(tline->text);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002228 tt = expand_smacro(tt);
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002229 size = parse_size(tt->text);
2230 if (!size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002231 error(ERR_NONFATAL,
2232 "Invalid size type for `%%local' missing directive");
2233 free_tlist(tt);
2234 free_tlist(origline);
2235 return DIRECTIVE_FOUND;
2236 }
2237 free_tlist(tt);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002238
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002239 /* Round up to even stack slots */
2240 size = (size+StackSize-1) & ~(StackSize-1);
2241
2242 offset += size; /* Negative offset, increment before */
2243
2244 /* Now define the macro for the argument */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002245 snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
2246 local, StackPointer, offset);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002247 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002248
H. Peter Anvine2c80182005-01-15 22:15:51 +00002249 /* Now define the assign to setup the enter_c macro correctly */
2250 snprintf(directive, sizeof(directive),
2251 "%%assign %%$localsize %%$localsize+%d", size);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002252 do_directive(tokenize(directive));
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002253
H. Peter Anvine2c80182005-01-15 22:15:51 +00002254 /* Move to the next argument in the list */
2255 tline = tline->next;
2256 if (tline && tline->type == TOK_WHITESPACE)
2257 tline = tline->next;
H. Peter Anvin8781cb02007-11-08 20:01:11 -08002258 } while (tline && tline->type == TOK_OTHER && tline->text[0] == ',');
2259 LocalOffset = offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002260 free_tlist(origline);
2261 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002262
H. Peter Anvine2c80182005-01-15 22:15:51 +00002263 case PP_CLEAR:
2264 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002265 error(ERR_WARNING|ERR_PASS1,
2266 "trailing garbage after `%%clear' ignored");
H. Peter Anvin97a23472007-09-16 17:57:25 -07002267 free_macros();
2268 init_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00002269 free_tlist(origline);
2270 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002271
H. Peter Anvin418ca702008-05-30 10:42:30 -07002272 case PP_DEPEND:
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002273 t = tline->next = expand_smacro(tline->next);
2274 skip_white_(t);
2275 if (!t || (t->type != TOK_STRING &&
2276 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvin418ca702008-05-30 10:42:30 -07002277 error(ERR_NONFATAL, "`%%depend' expects a file name");
2278 free_tlist(origline);
2279 return DIRECTIVE_FOUND; /* but we did _something_ */
2280 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002281 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002282 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin418ca702008-05-30 10:42:30 -07002283 "trailing garbage after `%%depend' ignored");
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002284 p = t->text;
2285 if (t->type != TOK_INTERNAL_STRING)
2286 nasm_unquote(p, NULL);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002287 if (dephead && !in_list(*dephead, p)) {
2288 StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next);
2289 sl->next = NULL;
2290 strcpy(sl->str, p);
2291 *deptail = sl;
2292 deptail = &sl->next;
2293 }
2294 free_tlist(origline);
2295 return DIRECTIVE_FOUND;
2296
2297 case PP_INCLUDE:
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002298 t = tline->next = expand_smacro(tline->next);
2299 skip_white_(t);
H. Peter Anvind2456592008-06-19 15:04:18 -07002300
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002301 if (!t || (t->type != TOK_STRING &&
2302 t->type != TOK_INTERNAL_STRING)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002303 error(ERR_NONFATAL, "`%%include' expects a file name");
2304 free_tlist(origline);
2305 return DIRECTIVE_FOUND; /* but we did _something_ */
2306 }
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002307 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002308 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002309 "trailing garbage after `%%include' ignored");
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002310 p = t->text;
2311 if (t->type != TOK_INTERNAL_STRING)
2312 nasm_unquote(p, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002313 inc = nasm_malloc(sizeof(Include));
2314 inc->next = istk;
2315 inc->conds = NULL;
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07002316 inc->fp = inc_fopen(p, dephead, &deptail, pass == 0);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002317 if (!inc->fp) {
H. Peter Anvin37a321f2007-09-24 13:41:58 -07002318 /* -MG given but file not found */
2319 nasm_free(inc);
2320 } else {
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002321 inc->fname = src_set_fname(nasm_strdup(p));
H. Peter Anvin37a321f2007-09-24 13:41:58 -07002322 inc->lineno = src_set_linnum(0);
2323 inc->lineinc = 1;
2324 inc->expansion = NULL;
2325 inc->mstk = NULL;
2326 istk = inc;
2327 list->uplevel(LIST_INCLUDE);
2328 }
2329 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002330 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002331
H. Peter Anvind2456592008-06-19 15:04:18 -07002332 case PP_USE:
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002333 {
H. Peter Anvina70547f2008-07-19 21:44:26 -07002334 static macros_t *use_pkg;
H. Peter Anvinb2a5fda2008-06-19 21:42:42 -07002335 const char *pkg_macro;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002336
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002337 tline = tline->next;
2338 skip_white_(tline);
2339 tline = expand_id(tline);
H. Peter Anvind2456592008-06-19 15:04:18 -07002340
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002341 if (!tline || (tline->type != TOK_STRING &&
2342 tline->type != TOK_INTERNAL_STRING &&
2343 tline->type != TOK_ID)) {
H. Peter Anvin926fc402008-06-19 16:26:12 -07002344 error(ERR_NONFATAL, "`%%use' expects a package name");
H. Peter Anvind2456592008-06-19 15:04:18 -07002345 free_tlist(origline);
2346 return DIRECTIVE_FOUND; /* but we did _something_ */
2347 }
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002348 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002349 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvind2456592008-06-19 15:04:18 -07002350 "trailing garbage after `%%use' ignored");
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002351 if (tline->type == TOK_STRING)
2352 nasm_unquote(tline->text, NULL);
2353 use_pkg = nasm_stdmac_find_package(tline->text);
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002354 if (!use_pkg)
H. Peter Anvin264b7b92008-10-24 16:38:17 -07002355 error(ERR_NONFATAL, "unknown `%%use' package: %s", tline->text);
H. Peter Anvinb2a5fda2008-06-19 21:42:42 -07002356 /* The first string will be <%define>__USE_*__ */
H. Peter Anvin7e50d232008-06-25 14:54:14 -07002357 pkg_macro = (char *)use_pkg + 1;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002358 if (!smacro_defined(NULL, pkg_macro, 0, NULL, true)) {
2359 /* Not already included, go ahead and include it */
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002360 stdmacpos = use_pkg;
2361 }
H. Peter Anvind2456592008-06-19 15:04:18 -07002362 free_tlist(origline);
2363 return DIRECTIVE_FOUND;
H. Peter Anvinf4ae5ad2008-06-19 18:39:24 -07002364 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002365 case PP_PUSH:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002366 case PP_REPL:
H. Peter Anvin42b56392008-10-24 16:24:21 -07002367 case PP_POP:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002368 tline = tline->next;
2369 skip_white_(tline);
2370 tline = expand_id(tline);
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002371 if (tline) {
2372 if (!tok_type_(tline, TOK_ID)) {
H. Peter Anvin42b56392008-10-24 16:24:21 -07002373 error(ERR_NONFATAL, "`%s' expects a context identifier",
2374 pp_directives[i]);
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002375 free_tlist(origline);
2376 return DIRECTIVE_FOUND; /* but we did _something_ */
2377 }
2378 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002379 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin42b56392008-10-24 16:24:21 -07002380 "trailing garbage after `%s' ignored",
2381 pp_directives[i]);
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002382 p = nasm_strdup(tline->text);
2383 } else {
H. Peter Anvin42b56392008-10-24 16:24:21 -07002384 p = NULL; /* Anonymous */
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07002385 }
H. Peter Anvin42b56392008-10-24 16:24:21 -07002386
2387 if (i == PP_PUSH) {
2388 ctx = nasm_malloc(sizeof(Context));
2389 ctx->next = cstk;
2390 hash_init(&ctx->localmac, HASH_SMALL);
2391 ctx->name = p;
2392 ctx->number = unique++;
2393 cstk = ctx;
2394 } else {
2395 /* %pop or %repl */
2396 if (!cstk) {
2397 error(ERR_NONFATAL, "`%s': context stack is empty",
2398 pp_directives[i]);
2399 } else if (i == PP_POP) {
2400 if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
2401 error(ERR_NONFATAL, "`%%pop' in wrong context: %s, "
2402 "expected %s",
2403 cstk->name ? cstk->name : "anonymous", p);
2404 else
2405 ctx_pop();
2406 } else {
2407 /* i == PP_REPL */
2408 nasm_free(cstk->name);
2409 cstk->name = p;
2410 p = NULL;
2411 }
2412 nasm_free(p);
2413 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002414 free_tlist(origline);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002415 return DIRECTIVE_FOUND;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002416 case PP_FATAL:
2417 severity = ERR_FATAL|ERR_NO_SEVERITY;
2418 goto issue_error;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002419 case PP_ERROR:
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002420 severity = ERR_NONFATAL|ERR_NO_SEVERITY;
2421 goto issue_error;
H. Peter Anvin7df04172008-06-10 18:27:38 -07002422 case PP_WARNING:
H. Peter Anvin2f160432008-09-30 16:39:17 -07002423 severity = ERR_WARNING|ERR_NO_SEVERITY|ERR_WARN_USER;
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002424 goto issue_error;
2425
2426 issue_error:
H. Peter Anvin7df04172008-06-10 18:27:38 -07002427 {
H. Peter Anvin8e3f75e2008-09-24 00:21:58 -07002428 /* Only error out if this is the final pass */
2429 if (pass != 2 && i != PP_FATAL)
2430 return DIRECTIVE_FOUND;
H. Peter Anvin7df04172008-06-10 18:27:38 -07002431
H. Peter Anvine2c80182005-01-15 22:15:51 +00002432 tline->next = expand_smacro(tline->next);
2433 tline = tline->next;
2434 skip_white_(tline);
H. Peter Anvin7df04172008-06-10 18:27:38 -07002435 t = tline ? tline->next : NULL;
2436 skip_white_(t);
2437 if (tok_type_(tline, TOK_STRING) && !t) {
2438 /* The line contains only a quoted string */
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07002439 p = tline->text;
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002440 nasm_unquote(p, NULL);
H. Peter Anvin7df04172008-06-10 18:27:38 -07002441 error(severity, "%s: %s", pp_directives[i], p);
2442 } else {
2443 /* Not a quoted string, or more than a quoted string */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002444 p = detoken(tline, false);
H. Peter Anvin7df04172008-06-10 18:27:38 -07002445 error(severity, "%s: %s", pp_directives[i], p);
2446 nasm_free(p);
H. Peter Anvind2456592008-06-19 15:04:18 -07002447 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002448 free_tlist(origline);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002449 return DIRECTIVE_FOUND;
H. Peter Anvin7df04172008-06-10 18:27:38 -07002450 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002451
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002452 CASE_PP_IF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002453 if (istk->conds && !emitting(istk->conds->state))
2454 j = COND_NEVER;
2455 else {
2456 j = if_condition(tline->next, i);
2457 tline->next = NULL; /* it got freed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002458 j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2459 }
2460 cond = nasm_malloc(sizeof(Cond));
2461 cond->next = istk->conds;
2462 cond->state = j;
2463 istk->conds = cond;
H. Peter Anvin7061ad72007-11-26 22:02:21 -08002464 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002465 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002466
H. Peter Anvinda10e7b2007-09-12 04:18:37 +00002467 CASE_PP_ELIF:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002468 if (!istk->conds)
H. Peter Anvin4169a472007-09-12 01:29:43 +00002469 error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002470 switch(istk->conds->state) {
2471 case COND_IF_TRUE:
2472 istk->conds->state = COND_DONE;
2473 break;
2474
2475 case COND_DONE:
2476 case COND_NEVER:
2477 break;
2478
2479 case COND_ELSE_TRUE:
2480 case COND_ELSE_FALSE:
H. Peter Anvin917a3492008-09-24 09:14:49 -07002481 error_precond(ERR_WARNING|ERR_PASS1,
2482 "`%%elif' after `%%else' ignored");
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002483 istk->conds->state = COND_NEVER;
2484 break;
2485
2486 case COND_IF_FALSE:
2487 /*
2488 * IMPORTANT: In the case of %if, we will already have
2489 * called expand_mmac_params(); however, if we're
2490 * processing an %elif we must have been in a
2491 * non-emitting mode, which would have inhibited
H. Peter Anvin67c63722008-10-26 23:49:00 -07002492 * the normal invocation of expand_mmac_params().
2493 * Therefore, we have to do it explicitly here.
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002494 */
H. Peter Anvin67c63722008-10-26 23:49:00 -07002495 j = if_condition(expand_mmac_params(tline->next), i);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002496 tline->next = NULL; /* it got freed */
2497 istk->conds->state =
2498 j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
2499 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002500 }
H. Peter Anvin7061ad72007-11-26 22:02:21 -08002501 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002502 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002503
H. Peter Anvine2c80182005-01-15 22:15:51 +00002504 case PP_ELSE:
2505 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002506 error_precond(ERR_WARNING|ERR_PASS1,
2507 "trailing garbage after `%%else' ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00002508 if (!istk->conds)
2509 error(ERR_FATAL, "`%%else': no matching `%%if'");
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002510 switch(istk->conds->state) {
2511 case COND_IF_TRUE:
2512 case COND_DONE:
2513 istk->conds->state = COND_ELSE_FALSE;
2514 break;
2515
2516 case COND_NEVER:
2517 break;
2518
2519 case COND_IF_FALSE:
2520 istk->conds->state = COND_ELSE_TRUE;
2521 break;
2522
2523 case COND_ELSE_TRUE:
2524 case COND_ELSE_FALSE:
H. Peter Anvin917a3492008-09-24 09:14:49 -07002525 error_precond(ERR_WARNING|ERR_PASS1,
2526 "`%%else' after `%%else' ignored.");
Victor van den Elzen3b404c02008-09-18 13:51:36 +02002527 istk->conds->state = COND_NEVER;
2528 break;
2529 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002530 free_tlist(origline);
2531 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002532
H. Peter Anvine2c80182005-01-15 22:15:51 +00002533 case PP_ENDIF:
2534 if (tline->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002535 error_precond(ERR_WARNING|ERR_PASS1,
2536 "trailing garbage after `%%endif' ignored");
H. Peter Anvine2c80182005-01-15 22:15:51 +00002537 if (!istk->conds)
2538 error(ERR_FATAL, "`%%endif': no matching `%%if'");
2539 cond = istk->conds;
2540 istk->conds = cond->next;
2541 nasm_free(cond);
2542 free_tlist(origline);
2543 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002544
H. Peter Anvine2c80182005-01-15 22:15:51 +00002545 case PP_MACRO:
2546 case PP_IMACRO:
H. Peter Anvina26433d2008-07-16 14:40:01 -07002547 if (defining) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002548 error(ERR_FATAL,
2549 "`%%%smacro': already defining a macro",
2550 (i == PP_IMACRO ? "i" : ""));
H. Peter Anvina26433d2008-07-16 14:40:01 -07002551 return DIRECTIVE_FOUND;
2552 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002553 defining = nasm_malloc(sizeof(MMacro));
H. Peter Anvina26433d2008-07-16 14:40:01 -07002554 defining->casesense = (i == PP_MACRO);
2555 if (!parse_mmacro_spec(tline, defining, pp_directives[i])) {
2556 nasm_free(defining);
2557 defining = NULL;
2558 return DIRECTIVE_FOUND;
2559 }
2560
H. Peter Anvin166c2472008-05-28 12:28:58 -07002561 mmac = (MMacro *) hash_findix(&mmacros, defining->name);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002562 while (mmac) {
2563 if (!strcmp(mmac->name, defining->name) &&
2564 (mmac->nparam_min <= defining->nparam_max
2565 || defining->plus)
2566 && (defining->nparam_min <= mmac->nparam_max
2567 || mmac->plus)) {
H. Peter Anvin917a3492008-09-24 09:14:49 -07002568 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002569 "redefining multi-line macro `%s'", defining->name);
H. Peter Anvina26433d2008-07-16 14:40:01 -07002570 return DIRECTIVE_FOUND;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002571 }
2572 mmac = mmac->next;
2573 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002574 free_tlist(origline);
2575 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002576
H. Peter Anvine2c80182005-01-15 22:15:51 +00002577 case PP_ENDM:
2578 case PP_ENDMACRO:
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02002579 if (! (defining && defining->name)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002580 error(ERR_NONFATAL, "`%s': not defining a macro", tline->text);
2581 return DIRECTIVE_FOUND;
2582 }
H. Peter Anvin166c2472008-05-28 12:28:58 -07002583 mmhead = (MMacro **) hash_findi_add(&mmacros, defining->name);
H. Peter Anvin97a23472007-09-16 17:57:25 -07002584 defining->next = *mmhead;
2585 *mmhead = defining;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002586 defining = NULL;
2587 free_tlist(origline);
2588 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002589
H. Peter Anvina26433d2008-07-16 14:40:01 -07002590 case PP_UNMACRO:
2591 case PP_UNIMACRO:
2592 {
2593 MMacro **mmac_p;
2594 MMacro spec;
2595
2596 spec.casesense = (i == PP_UNMACRO);
2597 if (!parse_mmacro_spec(tline, &spec, pp_directives[i])) {
2598 return DIRECTIVE_FOUND;
2599 }
2600 mmac_p = (MMacro **) hash_findi(&mmacros, spec.name, NULL);
2601 while (mmac_p && *mmac_p) {
2602 mmac = *mmac_p;
2603 if (mmac->casesense == spec.casesense &&
2604 !mstrcmp(mmac->name, spec.name, spec.casesense) &&
2605 mmac->nparam_min == spec.nparam_min &&
2606 mmac->nparam_max == spec.nparam_max &&
2607 mmac->plus == spec.plus) {
2608 *mmac_p = mmac->next;
2609 free_mmacro(mmac);
2610 } else {
2611 mmac_p = &mmac->next;
2612 }
2613 }
2614 free_tlist(origline);
2615 free_tlist(spec.dlist);
2616 return DIRECTIVE_FOUND;
2617 }
2618
H. Peter Anvine2c80182005-01-15 22:15:51 +00002619 case PP_ROTATE:
2620 if (tline->next && tline->next->type == TOK_WHITESPACE)
2621 tline = tline->next;
2622 if (tline->next == NULL) {
2623 free_tlist(origline);
2624 error(ERR_NONFATAL, "`%%rotate' missing rotate count");
2625 return DIRECTIVE_FOUND;
2626 }
2627 t = expand_smacro(tline->next);
2628 tline->next = NULL;
2629 free_tlist(origline);
2630 tline = t;
2631 tptr = &t;
2632 tokval.t_type = TOKEN_INVALID;
2633 evalresult =
2634 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2635 free_tlist(tline);
2636 if (!evalresult)
2637 return DIRECTIVE_FOUND;
2638 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002639 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002640 "trailing garbage after expression ignored");
2641 if (!is_simple(evalresult)) {
2642 error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
2643 return DIRECTIVE_FOUND;
2644 }
2645 mmac = istk->mstk;
2646 while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
2647 mmac = mmac->next_active;
2648 if (!mmac) {
2649 error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call");
2650 } else if (mmac->nparam == 0) {
2651 error(ERR_NONFATAL,
2652 "`%%rotate' invoked within macro without parameters");
2653 } else {
H. Peter Anvin25a99342007-09-22 17:45:45 -07002654 int rotate = mmac->rotate + reloc_value(evalresult);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002655
H. Peter Anvin25a99342007-09-22 17:45:45 -07002656 rotate %= (int)mmac->nparam;
2657 if (rotate < 0)
2658 rotate += mmac->nparam;
H. Peter Anvin70653092007-10-19 14:42:29 -07002659
H. Peter Anvin25a99342007-09-22 17:45:45 -07002660 mmac->rotate = rotate;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002661 }
2662 return DIRECTIVE_FOUND;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002663
H. Peter Anvine2c80182005-01-15 22:15:51 +00002664 case PP_REP:
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002665 nolist = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002666 do {
2667 tline = tline->next;
2668 } while (tok_type_(tline, TOK_WHITESPACE));
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002669
H. Peter Anvine2c80182005-01-15 22:15:51 +00002670 if (tok_type_(tline, TOK_ID) &&
2671 nasm_stricmp(tline->text, ".nolist") == 0) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002672 nolist = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002673 do {
2674 tline = tline->next;
2675 } while (tok_type_(tline, TOK_WHITESPACE));
2676 }
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00002677
H. Peter Anvine2c80182005-01-15 22:15:51 +00002678 if (tline) {
2679 t = expand_smacro(tline);
2680 tptr = &t;
2681 tokval.t_type = TOKEN_INVALID;
2682 evalresult =
2683 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
2684 if (!evalresult) {
2685 free_tlist(origline);
2686 return DIRECTIVE_FOUND;
2687 }
2688 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002689 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002690 "trailing garbage after expression ignored");
2691 if (!is_simple(evalresult)) {
2692 error(ERR_NONFATAL, "non-constant value given to `%%rep'");
2693 return DIRECTIVE_FOUND;
2694 }
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002695 count = reloc_value(evalresult) + 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002696 } else {
2697 error(ERR_NONFATAL, "`%%rep' expects a repeat count");
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002698 count = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002699 }
2700 free_tlist(origline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002701
H. Peter Anvine2c80182005-01-15 22:15:51 +00002702 tmp_defining = defining;
2703 defining = nasm_malloc(sizeof(MMacro));
2704 defining->name = NULL; /* flags this macro as a %rep block */
H. Peter Anvin70055962007-10-11 00:05:31 -07002705 defining->casesense = false;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002706 defining->plus = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002707 defining->nolist = nolist;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07002708 defining->in_progress = count;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002709 defining->nparam_min = defining->nparam_max = 0;
2710 defining->defaults = NULL;
2711 defining->dlist = NULL;
2712 defining->expansion = NULL;
2713 defining->next_active = istk->mstk;
2714 defining->rep_nest = tmp_defining;
2715 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002716
H. Peter Anvine2c80182005-01-15 22:15:51 +00002717 case PP_ENDREP:
2718 if (!defining || defining->name) {
2719 error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
2720 return DIRECTIVE_FOUND;
2721 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002722
H. Peter Anvine2c80182005-01-15 22:15:51 +00002723 /*
2724 * Now we have a "macro" defined - although it has no name
2725 * and we won't be entering it in the hash tables - we must
2726 * push a macro-end marker for it on to istk->expansion.
2727 * After that, it will take care of propagating itself (a
2728 * macro-end marker line for a macro which is really a %rep
2729 * block will cause the macro to be re-expanded, complete
2730 * with another macro-end marker to ensure the process
2731 * continues) until the whole expansion is forcibly removed
2732 * from istk->expansion by a %exitrep.
2733 */
2734 l = nasm_malloc(sizeof(Line));
2735 l->next = istk->expansion;
2736 l->finishes = defining;
2737 l->first = NULL;
2738 istk->expansion = l;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002739
H. Peter Anvine2c80182005-01-15 22:15:51 +00002740 istk->mstk = defining;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002741
H. Peter Anvine2c80182005-01-15 22:15:51 +00002742 list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
2743 tmp_defining = defining;
2744 defining = defining->rep_nest;
2745 free_tlist(origline);
2746 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002747
H. Peter Anvine2c80182005-01-15 22:15:51 +00002748 case PP_EXITREP:
2749 /*
2750 * We must search along istk->expansion until we hit a
2751 * macro-end marker for a macro with no name. Then we set
2752 * its `in_progress' flag to 0.
2753 */
2754 for (l = istk->expansion; l; l = l->next)
2755 if (l->finishes && !l->finishes->name)
H. Peter Anvinca348b62008-07-23 10:49:26 -04002756 break;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002757
H. Peter Anvine2c80182005-01-15 22:15:51 +00002758 if (l)
Charles Crayned4200be2008-07-12 16:42:33 -07002759 l->finishes->in_progress = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002760 else
2761 error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
2762 free_tlist(origline);
2763 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002764
H. Peter Anvine2c80182005-01-15 22:15:51 +00002765 case PP_XDEFINE:
2766 case PP_IXDEFINE:
2767 case PP_DEFINE:
2768 case PP_IDEFINE:
H. Peter Anvin95e7f952007-10-11 13:38:38 -07002769 casesense = (i == PP_DEFINE || i == PP_XDEFINE);
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002770
H. Peter Anvine2c80182005-01-15 22:15:51 +00002771 tline = tline->next;
2772 skip_white_(tline);
2773 tline = expand_id(tline);
2774 if (!tline || (tline->type != TOK_ID &&
2775 (tline->type != TOK_PREPROC_ID ||
2776 tline->text[1] != '$'))) {
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002777 error(ERR_NONFATAL, "`%s' expects a macro identifier",
2778 pp_directives[i]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002779 free_tlist(origline);
2780 return DIRECTIVE_FOUND;
2781 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00002782
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002783 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002784 last = tline;
2785 param_start = tline = tline->next;
2786 nparam = 0;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002787
H. Peter Anvine2c80182005-01-15 22:15:51 +00002788 /* Expand the macro definition now for %xdefine and %ixdefine */
2789 if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
2790 tline = expand_smacro(tline);
H. Peter Anvin734b1882002-04-30 21:01:08 +00002791
H. Peter Anvine2c80182005-01-15 22:15:51 +00002792 if (tok_is_(tline, "(")) {
2793 /*
2794 * This macro has parameters.
2795 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00002796
H. Peter Anvine2c80182005-01-15 22:15:51 +00002797 tline = tline->next;
2798 while (1) {
2799 skip_white_(tline);
2800 if (!tline) {
2801 error(ERR_NONFATAL, "parameter identifier expected");
2802 free_tlist(origline);
2803 return DIRECTIVE_FOUND;
2804 }
2805 if (tline->type != TOK_ID) {
2806 error(ERR_NONFATAL,
2807 "`%s': parameter identifier expected",
2808 tline->text);
2809 free_tlist(origline);
2810 return DIRECTIVE_FOUND;
2811 }
2812 tline->type = TOK_SMAC_PARAM + nparam++;
2813 tline = tline->next;
2814 skip_white_(tline);
2815 if (tok_is_(tline, ",")) {
2816 tline = tline->next;
H. Peter Anvinca348b62008-07-23 10:49:26 -04002817 } else {
2818 if (!tok_is_(tline, ")")) {
2819 error(ERR_NONFATAL,
2820 "`)' expected to terminate macro template");
2821 free_tlist(origline);
2822 return DIRECTIVE_FOUND;
2823 }
2824 break;
2825 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002826 }
2827 last = tline;
2828 tline = tline->next;
2829 }
2830 if (tok_type_(tline, TOK_WHITESPACE))
2831 last = tline, tline = tline->next;
2832 macro_start = NULL;
2833 last->next = NULL;
2834 t = tline;
2835 while (t) {
2836 if (t->type == TOK_ID) {
2837 for (tt = param_start; tt; tt = tt->next)
2838 if (tt->type >= TOK_SMAC_PARAM &&
2839 !strcmp(tt->text, t->text))
2840 t->type = tt->type;
2841 }
2842 tt = t->next;
2843 t->next = macro_start;
2844 macro_start = t;
2845 t = tt;
2846 }
2847 /*
2848 * Good. We now have a macro name, a parameter count, and a
2849 * token list (in reverse order) for an expansion. We ought
2850 * to be OK just to create an SMacro, store it, and let
2851 * free_tlist have the rest of the line (which we have
2852 * carefully re-terminated after chopping off the expansion
2853 * from the end).
2854 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002855 define_smacro(ctx, mname, casesense, nparam, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002856 free_tlist(origline);
2857 return DIRECTIVE_FOUND;
H. Peter Anvin76690a12002-04-30 20:52:49 +00002858
H. Peter Anvine2c80182005-01-15 22:15:51 +00002859 case PP_UNDEF:
2860 tline = tline->next;
2861 skip_white_(tline);
2862 tline = expand_id(tline);
2863 if (!tline || (tline->type != TOK_ID &&
2864 (tline->type != TOK_PREPROC_ID ||
2865 tline->text[1] != '$'))) {
2866 error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
2867 free_tlist(origline);
2868 return DIRECTIVE_FOUND;
2869 }
2870 if (tline->next) {
H. Peter Anvin917a3492008-09-24 09:14:49 -07002871 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00002872 "trailing garbage after macro name ignored");
2873 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00002874
H. Peter Anvine2c80182005-01-15 22:15:51 +00002875 /* Find the context that symbol belongs to */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002876 ctx = get_ctx(tline->text, &mname, false);
2877 undef_smacro(ctx, mname);
H. Peter Anvin4db5a162007-10-11 13:42:09 -07002878 free_tlist(origline);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002879 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00002880
H. Peter Anvin9e200162008-06-04 17:23:14 -07002881 case PP_DEFSTR:
2882 case PP_IDEFSTR:
2883 casesense = (i == PP_DEFSTR);
2884
2885 tline = tline->next;
2886 skip_white_(tline);
2887 tline = expand_id(tline);
2888 if (!tline || (tline->type != TOK_ID &&
2889 (tline->type != TOK_PREPROC_ID ||
2890 tline->text[1] != '$'))) {
2891 error(ERR_NONFATAL, "`%s' expects a macro identifier",
2892 pp_directives[i]);
2893 free_tlist(origline);
2894 return DIRECTIVE_FOUND;
2895 }
2896
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002897 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvin9e200162008-06-04 17:23:14 -07002898 last = tline;
2899 tline = expand_smacro(tline->next);
2900 last->next = NULL;
2901
2902 while (tok_type_(tline, TOK_WHITESPACE))
2903 tline = delete_Token(tline);
2904
2905 p = detoken(tline, false);
2906 macro_start = nasm_malloc(sizeof(*macro_start));
2907 macro_start->next = NULL;
2908 macro_start->text = nasm_quote(p, strlen(p));
2909 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07002910 macro_start->a.mac = NULL;
H. Peter Anvin9e200162008-06-04 17:23:14 -07002911 nasm_free(p);
2912
2913 /*
2914 * We now have a macro name, an implicit parameter count of
2915 * zero, and a string token to use as an expansion. Create
2916 * and store an SMacro.
2917 */
2918 define_smacro(ctx, mname, casesense, 0, macro_start);
2919 free_tlist(origline);
2920 return DIRECTIVE_FOUND;
2921
H. Peter Anvin418ca702008-05-30 10:42:30 -07002922 case PP_PATHSEARCH:
2923 {
2924 FILE *fp;
2925 StrList *xsl = NULL;
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07002926 StrList **xst = &xsl;
H. Peter Anvin418ca702008-05-30 10:42:30 -07002927
2928 casesense = true;
2929
2930 tline = tline->next;
2931 skip_white_(tline);
2932 tline = expand_id(tline);
2933 if (!tline || (tline->type != TOK_ID &&
2934 (tline->type != TOK_PREPROC_ID ||
2935 tline->text[1] != '$'))) {
2936 error(ERR_NONFATAL,
2937 "`%%pathsearch' expects a macro identifier as first parameter");
2938 free_tlist(origline);
2939 return DIRECTIVE_FOUND;
2940 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08002941 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002942 last = tline;
2943 tline = expand_smacro(tline->next);
2944 last->next = NULL;
2945
2946 t = tline;
2947 while (tok_type_(t, TOK_WHITESPACE))
2948 t = t->next;
2949
2950 if (!t || (t->type != TOK_STRING &&
2951 t->type != TOK_INTERNAL_STRING)) {
2952 error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
2953 free_tlist(tline);
2954 free_tlist(origline);
2955 return DIRECTIVE_FOUND; /* but we did _something_ */
2956 }
2957 if (t->next)
H. Peter Anvin917a3492008-09-24 09:14:49 -07002958 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvin418ca702008-05-30 10:42:30 -07002959 "trailing garbage after `%%pathsearch' ignored");
H. Peter Anvin427cc912008-06-01 21:43:03 -07002960 p = t->text;
2961 if (t->type != TOK_INTERNAL_STRING)
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07002962 nasm_unquote(p, NULL);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002963
H. Peter Anvin2b1c3b92008-06-06 10:38:46 -07002964 fp = inc_fopen(p, &xsl, &xst, true);
H. Peter Anvin418ca702008-05-30 10:42:30 -07002965 if (fp) {
2966 p = xsl->str;
2967 fclose(fp); /* Don't actually care about the file */
2968 }
2969 macro_start = nasm_malloc(sizeof(*macro_start));
2970 macro_start->next = NULL;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07002971 macro_start->text = nasm_quote(p, strlen(p));
H. Peter Anvin418ca702008-05-30 10:42:30 -07002972 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07002973 macro_start->a.mac = NULL;
H. Peter Anvin418ca702008-05-30 10:42:30 -07002974 if (xsl)
2975 nasm_free(xsl);
2976
2977 /*
2978 * We now have a macro name, an implicit parameter count of
2979 * zero, and a string token to use as an expansion. Create
2980 * and store an SMacro.
2981 */
2982 define_smacro(ctx, mname, casesense, 0, macro_start);
2983 free_tlist(tline);
2984 free_tlist(origline);
2985 return DIRECTIVE_FOUND;
2986 }
2987
H. Peter Anvine2c80182005-01-15 22:15:51 +00002988 case PP_STRLEN:
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07002989 casesense = true;
H. Peter Anvin70653092007-10-19 14:42:29 -07002990
H. Peter Anvine2c80182005-01-15 22:15:51 +00002991 tline = tline->next;
2992 skip_white_(tline);
2993 tline = expand_id(tline);
2994 if (!tline || (tline->type != TOK_ID &&
2995 (tline->type != TOK_PREPROC_ID ||
2996 tline->text[1] != '$'))) {
2997 error(ERR_NONFATAL,
2998 "`%%strlen' expects a macro identifier as first parameter");
2999 free_tlist(origline);
3000 return DIRECTIVE_FOUND;
3001 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003002 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003003 last = tline;
3004 tline = expand_smacro(tline->next);
3005 last->next = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003006
H. Peter Anvine2c80182005-01-15 22:15:51 +00003007 t = tline;
3008 while (tok_type_(t, TOK_WHITESPACE))
3009 t = t->next;
3010 /* t should now point to the string */
3011 if (t->type != TOK_STRING) {
3012 error(ERR_NONFATAL,
3013 "`%%strlen` requires string as second parameter");
3014 free_tlist(tline);
3015 free_tlist(origline);
3016 return DIRECTIVE_FOUND;
3017 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003018
H. Peter Anvine2c80182005-01-15 22:15:51 +00003019 macro_start = nasm_malloc(sizeof(*macro_start));
3020 macro_start->next = NULL;
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003021 make_tok_num(macro_start, nasm_unquote(t->text, NULL));
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003022 macro_start->a.mac = NULL;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003023
H. Peter Anvine2c80182005-01-15 22:15:51 +00003024 /*
3025 * We now have a macro name, an implicit parameter count of
3026 * zero, and a numeric token to use as an expansion. Create
3027 * and store an SMacro.
3028 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003029 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003030 free_tlist(tline);
3031 free_tlist(origline);
3032 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003033
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003034 case PP_STRCAT:
3035 casesense = true;
3036
3037 tline = tline->next;
3038 skip_white_(tline);
3039 tline = expand_id(tline);
3040 if (!tline || (tline->type != TOK_ID &&
3041 (tline->type != TOK_PREPROC_ID ||
3042 tline->text[1] != '$'))) {
3043 error(ERR_NONFATAL,
3044 "`%%strcat' expects a macro identifier as first parameter");
3045 free_tlist(origline);
3046 return DIRECTIVE_FOUND;
3047 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003048 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003049 last = tline;
3050 tline = expand_smacro(tline->next);
3051 last->next = NULL;
3052
3053 len = 0;
3054 for (t = tline; t; t = t->next) {
3055 switch (t->type) {
3056 case TOK_WHITESPACE:
3057 break;
3058 case TOK_STRING:
3059 len += t->a.len = nasm_unquote(t->text, NULL);
3060 break;
H. Peter Anvinaccf4332008-07-01 21:42:08 -07003061 case TOK_OTHER:
3062 if (!strcmp(t->text, ",")) /* permit comma separators */
3063 break;
3064 /* else fall through */
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003065 default:
3066 error(ERR_NONFATAL,
3067 "non-string passed to `%%strcat' (%d)", t->type);
3068 free_tlist(tline);
3069 free_tlist(origline);
3070 return DIRECTIVE_FOUND;
3071 }
3072 }
3073
3074 p = pp = nasm_malloc(len);
3075 t = tline;
3076 for (t = tline; t; t = t->next) {
3077 if (t->type == TOK_STRING) {
3078 memcpy(p, t->text, t->a.len);
3079 p += t->a.len;
3080 }
3081 }
3082
3083 /*
3084 * We now have a macro name, an implicit parameter count of
3085 * zero, and a numeric token to use as an expansion. Create
3086 * and store an SMacro.
3087 */
3088 macro_start = new_Token(NULL, TOK_STRING, NULL, 0);
3089 macro_start->text = nasm_quote(pp, len);
3090 nasm_free(pp);
3091 define_smacro(ctx, mname, casesense, 0, macro_start);
3092 free_tlist(tline);
3093 free_tlist(origline);
3094 return DIRECTIVE_FOUND;
3095
H. Peter Anvine2c80182005-01-15 22:15:51 +00003096 case PP_SUBSTR:
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003097 {
3098 int64_t a1, a2;
3099 size_t len;
H. Peter Anvind2456592008-06-19 15:04:18 -07003100
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003101 casesense = true;
3102
H. Peter Anvine2c80182005-01-15 22:15:51 +00003103 tline = tline->next;
3104 skip_white_(tline);
3105 tline = expand_id(tline);
3106 if (!tline || (tline->type != TOK_ID &&
3107 (tline->type != TOK_PREPROC_ID ||
3108 tline->text[1] != '$'))) {
3109 error(ERR_NONFATAL,
3110 "`%%substr' expects a macro identifier as first parameter");
3111 free_tlist(origline);
3112 return DIRECTIVE_FOUND;
3113 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003114 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003115 last = tline;
3116 tline = expand_smacro(tline->next);
3117 last->next = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003118
H. Peter Anvine2c80182005-01-15 22:15:51 +00003119 t = tline->next;
3120 while (tok_type_(t, TOK_WHITESPACE))
3121 t = t->next;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003122
H. Peter Anvine2c80182005-01-15 22:15:51 +00003123 /* t should now point to the string */
3124 if (t->type != TOK_STRING) {
3125 error(ERR_NONFATAL,
3126 "`%%substr` requires string as second parameter");
3127 free_tlist(tline);
3128 free_tlist(origline);
3129 return DIRECTIVE_FOUND;
3130 }
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003131
H. Peter Anvine2c80182005-01-15 22:15:51 +00003132 tt = t->next;
3133 tptr = &tt;
3134 tokval.t_type = TOKEN_INVALID;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003135 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3136 pass, error, NULL);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003137 if (!evalresult) {
3138 free_tlist(tline);
3139 free_tlist(origline);
3140 return DIRECTIVE_FOUND;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003141 } else if (!is_simple(evalresult)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00003142 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3143 free_tlist(tline);
3144 free_tlist(origline);
3145 return DIRECTIVE_FOUND;
3146 }
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003147 a1 = evalresult->value-1;
3148
3149 while (tok_type_(tt, TOK_WHITESPACE))
3150 tt = tt->next;
3151 if (!tt) {
3152 a2 = 1; /* Backwards compatibility: one character */
3153 } else {
3154 tokval.t_type = TOKEN_INVALID;
3155 evalresult = evaluate(ppscan, tptr, &tokval, NULL,
3156 pass, error, NULL);
3157 if (!evalresult) {
3158 free_tlist(tline);
3159 free_tlist(origline);
3160 return DIRECTIVE_FOUND;
3161 } else if (!is_simple(evalresult)) {
3162 error(ERR_NONFATAL, "non-constant value given to `%%substr`");
3163 free_tlist(tline);
3164 free_tlist(origline);
3165 return DIRECTIVE_FOUND;
3166 }
3167 a2 = evalresult->value;
3168 }
3169
H. Peter Anvin88c9e1f2008-06-04 11:26:59 -07003170 len = nasm_unquote(t->text, NULL);
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003171 if (a2 < 0)
3172 a2 = a2+1+len-a1;
3173 if (a1+a2 > (int64_t)len)
3174 a2 = len-a1;
H. Peter Anvin1cd0e2d2002-04-30 21:00:33 +00003175
H. Peter Anvine2c80182005-01-15 22:15:51 +00003176 macro_start = nasm_malloc(sizeof(*macro_start));
3177 macro_start->next = NULL;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003178 macro_start->text = nasm_quote((a1 < 0) ? "" : t->text+a1, a2);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003179 macro_start->type = TOK_STRING;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003180 macro_start->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003181
H. Peter Anvine2c80182005-01-15 22:15:51 +00003182 /*
3183 * We now have a macro name, an implicit parameter count of
3184 * zero, and a numeric token to use as an expansion. Create
3185 * and store an SMacro.
3186 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003187 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003188 free_tlist(tline);
3189 free_tlist(origline);
3190 return DIRECTIVE_FOUND;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003191 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003192
H. Peter Anvine2c80182005-01-15 22:15:51 +00003193 case PP_ASSIGN:
3194 case PP_IASSIGN:
H. Peter Anvin4bc9f1d2007-10-11 12:52:03 -07003195 casesense = (i == PP_ASSIGN);
3196
H. Peter Anvine2c80182005-01-15 22:15:51 +00003197 tline = tline->next;
3198 skip_white_(tline);
3199 tline = expand_id(tline);
3200 if (!tline || (tline->type != TOK_ID &&
3201 (tline->type != TOK_PREPROC_ID ||
3202 tline->text[1] != '$'))) {
3203 error(ERR_NONFATAL,
3204 "`%%%sassign' expects a macro identifier",
3205 (i == PP_IASSIGN ? "i" : ""));
3206 free_tlist(origline);
3207 return DIRECTIVE_FOUND;
3208 }
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003209 ctx = get_ctx(tline->text, &mname, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003210 last = tline;
3211 tline = expand_smacro(tline->next);
3212 last->next = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003213
H. Peter Anvine2c80182005-01-15 22:15:51 +00003214 t = tline;
3215 tptr = &t;
3216 tokval.t_type = TOKEN_INVALID;
3217 evalresult =
3218 evaluate(ppscan, tptr, &tokval, NULL, pass, error, NULL);
3219 free_tlist(tline);
3220 if (!evalresult) {
3221 free_tlist(origline);
3222 return DIRECTIVE_FOUND;
3223 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003224
H. Peter Anvine2c80182005-01-15 22:15:51 +00003225 if (tokval.t_type)
H. Peter Anvin917a3492008-09-24 09:14:49 -07003226 error(ERR_WARNING|ERR_PASS1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003227 "trailing garbage after expression ignored");
H. Peter Anvin734b1882002-04-30 21:01:08 +00003228
H. Peter Anvine2c80182005-01-15 22:15:51 +00003229 if (!is_simple(evalresult)) {
3230 error(ERR_NONFATAL,
3231 "non-constant value given to `%%%sassign'",
3232 (i == PP_IASSIGN ? "i" : ""));
3233 free_tlist(origline);
3234 return DIRECTIVE_FOUND;
3235 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003236
H. Peter Anvine2c80182005-01-15 22:15:51 +00003237 macro_start = nasm_malloc(sizeof(*macro_start));
3238 macro_start->next = NULL;
3239 make_tok_num(macro_start, reloc_value(evalresult));
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003240 macro_start->a.mac = NULL;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003241
H. Peter Anvine2c80182005-01-15 22:15:51 +00003242 /*
3243 * We now have a macro name, an implicit parameter count of
3244 * zero, and a numeric token to use as an expansion. Create
3245 * and store an SMacro.
3246 */
H. Peter Anvin4db5a162007-10-11 13:42:09 -07003247 define_smacro(ctx, mname, casesense, 0, macro_start);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003248 free_tlist(origline);
3249 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003250
H. Peter Anvine2c80182005-01-15 22:15:51 +00003251 case PP_LINE:
3252 /*
3253 * Syntax is `%line nnn[+mmm] [filename]'
3254 */
3255 tline = tline->next;
3256 skip_white_(tline);
3257 if (!tok_type_(tline, TOK_NUMBER)) {
3258 error(ERR_NONFATAL, "`%%line' expects line number");
3259 free_tlist(origline);
3260 return DIRECTIVE_FOUND;
3261 }
H. Peter Anvin70055962007-10-11 00:05:31 -07003262 k = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003263 m = 1;
3264 tline = tline->next;
3265 if (tok_is_(tline, "+")) {
3266 tline = tline->next;
3267 if (!tok_type_(tline, TOK_NUMBER)) {
3268 error(ERR_NONFATAL, "`%%line' expects line increment");
3269 free_tlist(origline);
3270 return DIRECTIVE_FOUND;
3271 }
H. Peter Anvin70055962007-10-11 00:05:31 -07003272 m = readnum(tline->text, &err);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003273 tline = tline->next;
3274 }
3275 skip_white_(tline);
3276 src_set_linnum(k);
3277 istk->lineinc = m;
3278 if (tline) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003279 nasm_free(src_set_fname(detoken(tline, false)));
H. Peter Anvine2c80182005-01-15 22:15:51 +00003280 }
3281 free_tlist(origline);
3282 return DIRECTIVE_FOUND;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003283
H. Peter Anvine2c80182005-01-15 22:15:51 +00003284 default:
3285 error(ERR_FATAL,
3286 "preprocessor directive `%s' not yet implemented",
H. Peter Anvin4169a472007-09-12 01:29:43 +00003287 pp_directives[i]);
H. Peter Anvina26433d2008-07-16 14:40:01 -07003288 return DIRECTIVE_FOUND;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003289 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003290}
3291
3292/*
H. Peter Anvin76690a12002-04-30 20:52:49 +00003293 * Ensure that a macro parameter contains a condition code and
3294 * nothing else. Return the condition code index if so, or -1
3295 * otherwise.
3296 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003297static int find_cc(Token * t)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003298{
H. Peter Anvin76690a12002-04-30 20:52:49 +00003299 Token *tt;
3300 int i, j, k, m;
3301
H. Peter Anvin25a99342007-09-22 17:45:45 -07003302 if (!t)
3303 return -1; /* Probably a %+ without a space */
3304
H. Peter Anvineba20a72002-04-30 20:53:55 +00003305 skip_white_(t);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003306 if (t->type != TOK_ID)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003307 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003308 tt = t->next;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003309 skip_white_(tt);
H. Peter Anvin76690a12002-04-30 20:52:49 +00003310 if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
H. Peter Anvine2c80182005-01-15 22:15:51 +00003311 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003312
3313 i = -1;
Ed Beroset3ab3f412002-06-11 03:31:49 +00003314 j = elements(conditions);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003315 while (j - i > 1) {
3316 k = (j + i) / 2;
3317 m = nasm_stricmp(t->text, conditions[k]);
3318 if (m == 0) {
3319 i = k;
3320 j = -2;
3321 break;
3322 } else if (m < 0) {
3323 j = k;
3324 } else
3325 i = k;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003326 }
3327 if (j != -2)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003328 return -1;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003329 return i;
3330}
3331
H. Peter Anvind784a082009-04-20 14:01:18 -07003332static bool paste_tokens(Token **head, bool handle_paste_tokens)
3333{
3334 Token **tail, *t, *tt;
3335 Token **paste_head;
3336 bool did_paste = false;
3337 char *tmp;
3338
3339 /* Now handle token pasting... */
3340 paste_head = NULL;
3341 tail = head;
3342 while ((t = *tail) && (tt = t->next)) {
3343 switch (t->type) {
3344 case TOK_WHITESPACE:
3345 if (tt->type == TOK_WHITESPACE) {
3346 /* Zap adjacent whitespace tokens */
3347 t->next = delete_Token(tt);
3348 } else {
3349 /* Do not advance paste_head here */
3350 tail = &t->next;
3351 }
3352 break;
3353 case TOK_ID:
3354 case TOK_PREPROC_ID:
3355 case TOK_NUMBER:
3356 case TOK_FLOAT:
3357 {
3358 size_t len = 0;
3359 char *tmp, *p;
3360
3361 while (tt && (tt->type == TOK_ID || tt->type == TOK_PREPROC_ID ||
3362 tt->type == TOK_NUMBER || tt->type == TOK_FLOAT ||
3363 tt->type == TOK_OTHER)) {
3364 len += strlen(tt->text);
3365 tt = tt->next;
3366 }
3367
3368 /* Now tt points to the first token after the potential
3369 paste area... */
3370 if (tt != t->next) {
3371 /* We have at least two tokens... */
3372 len += strlen(t->text);
3373 p = tmp = nasm_malloc(len+1);
3374
3375 while (t != tt) {
3376 strcpy(p, t->text);
3377 p = strchr(p, '\0');
3378 t = delete_Token(t);
3379 }
3380
3381 t = *tail = tokenize(tmp);
3382 nasm_free(tmp);
3383
3384 while (t->next) {
3385 tail = &t->next;
3386 t = t->next;
3387 }
3388 t->next = tt; /* Attach the remaining token chain */
3389
3390 did_paste = true;
3391 }
3392 paste_head = tail;
3393 tail = &t->next;
3394 break;
3395 }
3396 case TOK_PASTE: /* %+ */
3397 if (handle_paste_tokens) {
3398 /* Zap %+ and whitespace tokens to the right */
3399 while (t && (t->type == TOK_WHITESPACE ||
3400 t->type == TOK_PASTE))
3401 t = *tail = delete_Token(t);
3402 if (!paste_head || !t)
3403 break; /* Nothing to paste with */
3404 tail = paste_head;
3405 t = *tail;
3406 tt = t->next;
3407 while (tok_type_(tt, TOK_WHITESPACE))
3408 tt = t->next = delete_Token(tt);
3409
3410 if (tt) {
3411 tmp = nasm_strcat(t->text, tt->text);
3412 delete_Token(t);
3413 tt = delete_Token(tt);
3414 t = *tail = tokenize(tmp);
3415 nasm_free(tmp);
3416 while (t->next) {
3417 tail = &t->next;
3418 t = t->next;
3419 }
3420 t->next = tt; /* Attach the remaining token chain */
3421 did_paste = true;
3422 }
3423 paste_head = tail;
3424 tail = &t->next;
3425 break;
3426 }
3427 /* else fall through */
3428 default:
3429 tail = paste_head = &t->next;
3430 break;
3431 }
3432 }
3433 return did_paste;
3434}
H. Peter Anvin76690a12002-04-30 20:52:49 +00003435/*
3436 * Expand MMacro-local things: parameter references (%0, %n, %+n,
H. Peter Anvin67c63722008-10-26 23:49:00 -07003437 * %-n) and MMacro-local identifiers (%%foo) as well as
3438 * macro indirection (%[...]).
H. Peter Anvin76690a12002-04-30 20:52:49 +00003439 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003440static Token *expand_mmac_params(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003441{
H. Peter Anvin734b1882002-04-30 21:01:08 +00003442 Token *t, *tt, **tail, *thead;
H. Peter Anvin6125b622009-04-08 14:02:25 -07003443 bool changed = false;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003444
3445 tail = &thead;
3446 thead = NULL;
3447
H. Peter Anvine2c80182005-01-15 22:15:51 +00003448 while (tline) {
3449 if (tline->type == TOK_PREPROC_ID &&
3450 (((tline->text[1] == '+' || tline->text[1] == '-')
3451 && tline->text[2]) || tline->text[1] == '%'
3452 || (tline->text[1] >= '0' && tline->text[1] <= '9'))) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003453 char *text = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003454 int type = 0, cc; /* type = 0 to placate optimisers */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003455 char tmpbuf[30];
H. Peter Anvin25a99342007-09-22 17:45:45 -07003456 unsigned int n;
3457 int i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003458 MMacro *mac;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003459
H. Peter Anvine2c80182005-01-15 22:15:51 +00003460 t = tline;
3461 tline = tline->next;
H. Peter Anvin76690a12002-04-30 20:52:49 +00003462
H. Peter Anvine2c80182005-01-15 22:15:51 +00003463 mac = istk->mstk;
3464 while (mac && !mac->name) /* avoid mistaking %reps for macros */
3465 mac = mac->next_active;
3466 if (!mac)
3467 error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
3468 else
3469 switch (t->text[1]) {
3470 /*
3471 * We have to make a substitution of one of the
3472 * forms %1, %-1, %+1, %%foo, %0.
3473 */
3474 case '0':
3475 type = TOK_NUMBER;
3476 snprintf(tmpbuf, sizeof(tmpbuf), "%d", mac->nparam);
3477 text = nasm_strdup(tmpbuf);
3478 break;
3479 case '%':
3480 type = TOK_ID;
H. Peter Anvinf8ba53e2007-10-11 10:11:57 -07003481 snprintf(tmpbuf, sizeof(tmpbuf), "..@%"PRIu64".",
H. Peter Anvine2c80182005-01-15 22:15:51 +00003482 mac->unique);
3483 text = nasm_strcat(tmpbuf, t->text + 2);
3484 break;
3485 case '-':
3486 n = atoi(t->text + 2) - 1;
3487 if (n >= mac->nparam)
3488 tt = NULL;
3489 else {
3490 if (mac->nparam > 1)
3491 n = (n + mac->rotate) % mac->nparam;
3492 tt = mac->params[n];
3493 }
3494 cc = find_cc(tt);
3495 if (cc == -1) {
3496 error(ERR_NONFATAL,
3497 "macro parameter %d is not a condition code",
3498 n + 1);
3499 text = NULL;
3500 } else {
3501 type = TOK_ID;
3502 if (inverse_ccs[cc] == -1) {
3503 error(ERR_NONFATAL,
3504 "condition code `%s' is not invertible",
3505 conditions[cc]);
3506 text = NULL;
3507 } else
H. Peter Anvin67c63722008-10-26 23:49:00 -07003508 text = nasm_strdup(conditions[inverse_ccs[cc]]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003509 }
3510 break;
3511 case '+':
3512 n = atoi(t->text + 2) - 1;
3513 if (n >= mac->nparam)
3514 tt = NULL;
3515 else {
3516 if (mac->nparam > 1)
3517 n = (n + mac->rotate) % mac->nparam;
3518 tt = mac->params[n];
3519 }
3520 cc = find_cc(tt);
3521 if (cc == -1) {
3522 error(ERR_NONFATAL,
3523 "macro parameter %d is not a condition code",
3524 n + 1);
3525 text = NULL;
3526 } else {
3527 type = TOK_ID;
3528 text = nasm_strdup(conditions[cc]);
3529 }
3530 break;
3531 default:
3532 n = atoi(t->text + 1) - 1;
3533 if (n >= mac->nparam)
3534 tt = NULL;
3535 else {
3536 if (mac->nparam > 1)
3537 n = (n + mac->rotate) % mac->nparam;
3538 tt = mac->params[n];
3539 }
3540 if (tt) {
3541 for (i = 0; i < mac->paramlen[n]; i++) {
3542 *tail = new_Token(NULL, tt->type, tt->text, 0);
3543 tail = &(*tail)->next;
3544 tt = tt->next;
3545 }
3546 }
3547 text = NULL; /* we've done it here */
3548 break;
3549 }
3550 if (!text) {
3551 delete_Token(t);
3552 } else {
3553 *tail = t;
3554 tail = &t->next;
3555 t->type = type;
3556 nasm_free(t->text);
3557 t->text = text;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003558 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003559 }
H. Peter Anvin6125b622009-04-08 14:02:25 -07003560 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003561 continue;
H. Peter Anvin67c63722008-10-26 23:49:00 -07003562 } else if (tline->type == TOK_INDIRECT) {
3563 t = tline;
3564 tline = tline->next;
3565 tt = tokenize(t->text);
3566 tt = expand_mmac_params(tt);
3567 tt = expand_smacro(tt);
3568 *tail = tt;
3569 while (tt) {
3570 tt->a.mac = NULL; /* Necessary? */
3571 tail = &tt->next;
3572 tt = tt->next;
3573 }
3574 delete_Token(t);
H. Peter Anvin6125b622009-04-08 14:02:25 -07003575 changed = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003576 } else {
3577 t = *tail = tline;
3578 tline = tline->next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003579 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003580 tail = &t->next;
3581 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00003582 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00003583 *tail = NULL;
H. Peter Anvin67c63722008-10-26 23:49:00 -07003584
H. Peter Anvind784a082009-04-20 14:01:18 -07003585 if (changed)
3586 paste_tokens(&thead, false);
H. Peter Anvin6125b622009-04-08 14:02:25 -07003587
H. Peter Anvin76690a12002-04-30 20:52:49 +00003588 return thead;
3589}
3590
3591/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003592 * Expand all single-line macro calls made in the given line.
3593 * Return the expanded version of the line. The original is deemed
3594 * to be destroyed in the process. (In reality we'll just move
3595 * Tokens from input to output a lot of the time, rather than
3596 * actually bothering to destroy and replicate.)
3597 */
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003598#define DEADMAN_LIMIT (1 << 20)
3599
H. Peter Anvine2c80182005-01-15 22:15:51 +00003600static Token *expand_smacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003601{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003602 Token *t, *tt, *mstart, **tail, *thead;
H. Peter Anvin166c2472008-05-28 12:28:58 -07003603 struct hash_table *smtbl;
H. Peter Anvineba20a72002-04-30 20:53:55 +00003604 SMacro *head = NULL, *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003605 Token **params;
3606 int *paramsize;
H. Peter Anvin25a99342007-09-22 17:45:45 -07003607 unsigned int nparam, sparam;
H. Peter Anvind784a082009-04-20 14:01:18 -07003608 int brackets;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003609 Token *org_tline = tline;
3610 Context *ctx;
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003611 const char *mname;
H. Peter Anvin2a15e692007-11-19 13:14:59 -08003612 int deadman = DEADMAN_LIMIT;
H. Peter Anvind784a082009-04-20 14:01:18 -07003613 bool expanded;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003614
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003615 /*
3616 * Trick: we should avoid changing the start token pointer since it can
3617 * be contained in "next" field of other token. Because of this
3618 * we allocate a copy of first token and work with it; at the end of
3619 * routine we copy it back
3620 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003621 if (org_tline) {
3622 tline =
3623 new_Token(org_tline->next, org_tline->type, org_tline->text,
3624 0);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003625 tline->a.mac = org_tline->a.mac;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003626 nasm_free(org_tline->text);
3627 org_tline->text = NULL;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003628 }
3629
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003630again:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003631 tail = &thead;
3632 thead = NULL;
H. Peter Anvind784a082009-04-20 14:01:18 -07003633 expanded = false;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003634
H. Peter Anvine2c80182005-01-15 22:15:51 +00003635 while (tline) { /* main token loop */
H. Peter Anvin2a15e692007-11-19 13:14:59 -08003636 if (!--deadman) {
H. Peter Anvincb1cf592007-11-19 12:26:50 -08003637 error(ERR_NONFATAL, "interminable macro recursion");
3638 break;
3639 }
3640
H. Peter Anvine2c80182005-01-15 22:15:51 +00003641 if ((mname = tline->text)) {
3642 /* if this token is a local macro, look in local context */
H. Peter Anvinf8ad5322009-02-21 17:55:08 -08003643 if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
3644 ctx = get_ctx(mname, &mname, true);
3645 else
3646 ctx = NULL;
3647 smtbl = ctx ? &ctx->localmac : &smacros;
H. Peter Anvin166c2472008-05-28 12:28:58 -07003648 head = (SMacro *) hash_findix(smtbl, mname);
H. Peter Anvin072771e2008-05-22 13:17:51 -07003649
H. Peter Anvine2c80182005-01-15 22:15:51 +00003650 /*
3651 * We've hit an identifier. As in is_mmacro below, we first
3652 * check whether the identifier is a single-line macro at
3653 * all, then think about checking for parameters if
3654 * necessary.
3655 */
H. Peter Anvin97a23472007-09-16 17:57:25 -07003656 for (m = head; m; m = m->next)
3657 if (!mstrcmp(m->name, mname, m->casesense))
3658 break;
3659 if (m) {
3660 mstart = tline;
3661 params = NULL;
3662 paramsize = NULL;
3663 if (m->nparam == 0) {
3664 /*
3665 * Simple case: the macro is parameterless. Discard the
3666 * one token that the macro call took, and push the
3667 * expansion back on the to-do stack.
3668 */
3669 if (!m->expansion) {
3670 if (!strcmp("__FILE__", m->name)) {
3671 int32_t num = 0;
H. Peter Anvin932de6c2008-07-31 18:46:11 -07003672 char *file = NULL;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003673 src_get(&num, &file);
3674 tline->text = nasm_quote(file, strlen(file));
H. Peter Anvin97a23472007-09-16 17:57:25 -07003675 tline->type = TOK_STRING;
H. Peter Anvin8cad14b2008-06-01 17:23:51 -07003676 nasm_free(file);
H. Peter Anvin97a23472007-09-16 17:57:25 -07003677 continue;
3678 }
3679 if (!strcmp("__LINE__", m->name)) {
3680 nasm_free(tline->text);
3681 make_tok_num(tline, src_get_linnum());
3682 continue;
3683 }
3684 if (!strcmp("__BITS__", m->name)) {
3685 nasm_free(tline->text);
3686 make_tok_num(tline, globalbits);
H. Peter Anvine2c80182005-01-15 22:15:51 +00003687 continue;
H. Peter Anvin97a23472007-09-16 17:57:25 -07003688 }
3689 tline = delete_Token(tline);
3690 continue;
3691 }
3692 } else {
3693 /*
3694 * Complicated case: at least one macro with this name
H. Peter Anvine2c80182005-01-15 22:15:51 +00003695 * exists and takes parameters. We must find the
3696 * parameters in the call, count them, find the SMacro
3697 * that corresponds to that form of the macro call, and
3698 * substitute for the parameters when we expand. What a
3699 * pain.
3700 */
3701 /*tline = tline->next;
3702 skip_white_(tline); */
3703 do {
3704 t = tline->next;
3705 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003706 t->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003707 t->text = NULL;
3708 t = tline->next = delete_Token(t);
3709 }
3710 tline = t;
3711 } while (tok_type_(tline, TOK_WHITESPACE));
3712 if (!tok_is_(tline, "(")) {
3713 /*
3714 * This macro wasn't called with parameters: ignore
3715 * the call. (Behaviour borrowed from gnu cpp.)
3716 */
3717 tline = mstart;
3718 m = NULL;
3719 } else {
3720 int paren = 0;
3721 int white = 0;
3722 brackets = 0;
3723 nparam = 0;
3724 sparam = PARAM_DELTA;
3725 params = nasm_malloc(sparam * sizeof(Token *));
3726 params[0] = tline->next;
3727 paramsize = nasm_malloc(sparam * sizeof(int));
3728 paramsize[0] = 0;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003729 while (true) { /* parameter loop */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003730 /*
3731 * For some unusual expansions
3732 * which concatenates function call
3733 */
3734 t = tline->next;
3735 while (tok_type_(t, TOK_SMAC_END)) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003736 t->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003737 t->text = NULL;
3738 t = tline->next = delete_Token(t);
3739 }
3740 tline = t;
Nickolay Yurchenko9aea7152003-09-07 22:46:26 +00003741
H. Peter Anvine2c80182005-01-15 22:15:51 +00003742 if (!tline) {
3743 error(ERR_NONFATAL,
3744 "macro call expects terminating `)'");
3745 break;
3746 }
3747 if (tline->type == TOK_WHITESPACE
3748 && brackets <= 0) {
3749 if (paramsize[nparam])
3750 white++;
3751 else
3752 params[nparam] = tline->next;
3753 continue; /* parameter loop */
3754 }
3755 if (tline->type == TOK_OTHER
3756 && tline->text[1] == 0) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +00003757 char ch = tline->text[0];
H. Peter Anvine2c80182005-01-15 22:15:51 +00003758 if (ch == ',' && !paren && brackets <= 0) {
3759 if (++nparam >= sparam) {
3760 sparam += PARAM_DELTA;
3761 params = nasm_realloc(params,
3762 sparam *
3763 sizeof(Token
3764 *));
3765 paramsize =
3766 nasm_realloc(paramsize,
3767 sparam *
3768 sizeof(int));
3769 }
3770 params[nparam] = tline->next;
3771 paramsize[nparam] = 0;
3772 white = 0;
3773 continue; /* parameter loop */
3774 }
3775 if (ch == '{' &&
3776 (brackets > 0 || (brackets == 0 &&
3777 !paramsize[nparam])))
3778 {
3779 if (!(brackets++)) {
3780 params[nparam] = tline->next;
3781 continue; /* parameter loop */
3782 }
3783 }
3784 if (ch == '}' && brackets > 0)
3785 if (--brackets == 0) {
3786 brackets = -1;
3787 continue; /* parameter loop */
3788 }
3789 if (ch == '(' && !brackets)
3790 paren++;
3791 if (ch == ')' && brackets <= 0)
3792 if (--paren < 0)
3793 break;
3794 }
3795 if (brackets < 0) {
3796 brackets = 0;
3797 error(ERR_NONFATAL, "braces do not "
3798 "enclose all of macro parameter");
3799 }
3800 paramsize[nparam] += white + 1;
3801 white = 0;
3802 } /* parameter loop */
3803 nparam++;
3804 while (m && (m->nparam != nparam ||
3805 mstrcmp(m->name, mname,
3806 m->casesense)))
3807 m = m->next;
3808 if (!m)
H. Peter Anvin917a3492008-09-24 09:14:49 -07003809 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00003810 "macro `%s' exists, "
3811 "but not taking %d parameters",
3812 mstart->text, nparam);
3813 }
3814 }
3815 if (m && m->in_progress)
3816 m = NULL;
3817 if (!m) { /* in progess or didn't find '(' or wrong nparam */
H. Peter Anvin70653092007-10-19 14:42:29 -07003818 /*
H. Peter Anvine2c80182005-01-15 22:15:51 +00003819 * Design question: should we handle !tline, which
3820 * indicates missing ')' here, or expand those
3821 * macros anyway, which requires the (t) test a few
H. Peter Anvin70653092007-10-19 14:42:29 -07003822 * lines down?
H. Peter Anvine2c80182005-01-15 22:15:51 +00003823 */
3824 nasm_free(params);
3825 nasm_free(paramsize);
3826 tline = mstart;
3827 } else {
3828 /*
3829 * Expand the macro: we are placed on the last token of the
3830 * call, so that we can easily split the call from the
3831 * following tokens. We also start by pushing an SMAC_END
3832 * token for the cycle removal.
3833 */
3834 t = tline;
3835 if (t) {
3836 tline = t->next;
3837 t->next = NULL;
3838 }
3839 tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003840 tt->a.mac = m;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07003841 m->in_progress = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003842 tline = tt;
3843 for (t = m->expansion; t; t = t->next) {
3844 if (t->type >= TOK_SMAC_PARAM) {
3845 Token *pcopy = tline, **ptail = &pcopy;
3846 Token *ttt, *pt;
3847 int i;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003848
H. Peter Anvine2c80182005-01-15 22:15:51 +00003849 ttt = params[t->type - TOK_SMAC_PARAM];
3850 for (i = paramsize[t->type - TOK_SMAC_PARAM];
3851 --i >= 0;) {
3852 pt = *ptail =
3853 new_Token(tline, ttt->type, ttt->text,
3854 0);
3855 ptail = &pt->next;
3856 ttt = ttt->next;
3857 }
3858 tline = pcopy;
H. Peter Anvin6c81f0a2008-05-25 21:46:17 -07003859 } else if (t->type == TOK_PREPROC_Q) {
3860 tt = new_Token(tline, TOK_ID, mname, 0);
3861 tline = tt;
3862 } else if (t->type == TOK_PREPROC_QQ) {
3863 tt = new_Token(tline, TOK_ID, m->name, 0);
3864 tline = tt;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003865 } else {
3866 tt = new_Token(tline, t->type, t->text, 0);
3867 tline = tt;
3868 }
3869 }
H. Peter Anvin734b1882002-04-30 21:01:08 +00003870
H. Peter Anvine2c80182005-01-15 22:15:51 +00003871 /*
3872 * Having done that, get rid of the macro call, and clean
3873 * up the parameters.
3874 */
3875 nasm_free(params);
3876 nasm_free(paramsize);
3877 free_tlist(mstart);
H. Peter Anvind784a082009-04-20 14:01:18 -07003878 expanded = true;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003879 continue; /* main token loop */
3880 }
3881 }
3882 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003883
H. Peter Anvine2c80182005-01-15 22:15:51 +00003884 if (tline->type == TOK_SMAC_END) {
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003885 tline->a.mac->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003886 tline = delete_Token(tline);
3887 } else {
3888 t = *tail = tline;
3889 tline = tline->next;
H. Peter Anvinf26e0972008-07-01 21:26:27 -07003890 t->a.mac = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00003891 t->next = NULL;
3892 tail = &t->next;
3893 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003894 }
3895
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003896 /*
3897 * Now scan the entire line and look for successive TOK_IDs that resulted
Keith Kaniosb7a89542007-04-12 02:40:54 +00003898 * after expansion (they can't be produced by tokenize()). The successive
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003899 * TOK_IDs should be concatenated.
3900 * Also we look for %+ tokens and concatenate the tokens before and after
3901 * them (without white spaces in between).
3902 */
H. Peter Anvind784a082009-04-20 14:01:18 -07003903 if (expanded && paste_tokens(&thead, true)) {
3904 /* If we concatenated something, re-scan the line for macros */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003905 tline = thead;
3906 goto again;
H. Peter Anvin734b1882002-04-30 21:01:08 +00003907 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003908
H. Peter Anvine2c80182005-01-15 22:15:51 +00003909 if (org_tline) {
3910 if (thead) {
3911 *org_tline = *thead;
3912 /* since we just gave text to org_line, don't free it */
3913 thead->text = NULL;
3914 delete_Token(thead);
3915 } else {
3916 /* the expression expanded to empty line;
3917 we can't return NULL for some reasons
3918 we just set the line to a single WHITESPACE token. */
3919 memset(org_tline, 0, sizeof(*org_tline));
3920 org_tline->text = NULL;
3921 org_tline->type = TOK_WHITESPACE;
3922 }
3923 thead = org_tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003924 }
3925
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003926 return thead;
3927}
3928
3929/*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003930 * Similar to expand_smacro but used exclusively with macro identifiers
3931 * right before they are fetched in. The reason is that there can be
3932 * identifiers consisting of several subparts. We consider that if there
3933 * are more than one element forming the name, user wants a expansion,
3934 * otherwise it will be left as-is. Example:
3935 *
3936 * %define %$abc cde
3937 *
3938 * the identifier %$abc will be left as-is so that the handler for %define
3939 * will suck it and define the corresponding value. Other case:
3940 *
3941 * %define _%$abc cde
3942 *
3943 * In this case user wants name to be expanded *before* %define starts
3944 * working, so we'll expand %$abc into something (if it has a value;
3945 * otherwise it will be left as-is) then concatenate all successive
3946 * PP_IDs into one.
3947 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003948static Token *expand_id(Token * tline)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003949{
3950 Token *cur, *oldnext = NULL;
3951
H. Peter Anvin734b1882002-04-30 21:01:08 +00003952 if (!tline || !tline->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003953 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003954
3955 cur = tline;
3956 while (cur->next &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00003957 (cur->next->type == TOK_ID ||
3958 cur->next->type == TOK_PREPROC_ID
3959 || cur->next->type == TOK_NUMBER))
3960 cur = cur->next;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003961
3962 /* If identifier consists of just one token, don't expand */
3963 if (cur == tline)
H. Peter Anvine2c80182005-01-15 22:15:51 +00003964 return tline;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003965
H. Peter Anvine2c80182005-01-15 22:15:51 +00003966 if (cur) {
3967 oldnext = cur->next; /* Detach the tail past identifier */
3968 cur->next = NULL; /* so that expand_smacro stops here */
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003969 }
3970
H. Peter Anvin734b1882002-04-30 21:01:08 +00003971 tline = expand_smacro(tline);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003972
H. Peter Anvine2c80182005-01-15 22:15:51 +00003973 if (cur) {
3974 /* expand_smacro possibly changhed tline; re-scan for EOL */
3975 cur = tline;
3976 while (cur && cur->next)
3977 cur = cur->next;
3978 if (cur)
3979 cur->next = oldnext;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00003980 }
3981
3982 return tline;
3983}
3984
3985/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003986 * Determine whether the given line constitutes a multi-line macro
3987 * call, and return the MMacro structure called if so. Doesn't have
3988 * to check for an initial label - that's taken care of in
3989 * expand_mmacro - but must check numbers of parameters. Guaranteed
3990 * to be called with tline->type == TOK_ID, so the putative macro
3991 * name is easy to find.
3992 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00003993static MMacro *is_mmacro(Token * tline, Token *** params_array)
H. Peter Anvineba20a72002-04-30 20:53:55 +00003994{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00003995 MMacro *head, *m;
3996 Token **params;
3997 int nparam;
3998
H. Peter Anvin166c2472008-05-28 12:28:58 -07003999 head = (MMacro *) hash_findix(&mmacros, tline->text);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004000
4001 /*
4002 * Efficiency: first we see if any macro exists with the given
4003 * name. If not, we can return NULL immediately. _Then_ we
4004 * count the parameters, and then we look further along the
4005 * list if necessary to find the proper MMacro.
4006 */
4007 for (m = head; m; m = m->next)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004008 if (!mstrcmp(m->name, tline->text, m->casesense))
4009 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004010 if (!m)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004011 return NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004012
4013 /*
4014 * OK, we have a potential macro. Count and demarcate the
4015 * parameters.
4016 */
H. Peter Anvin734b1882002-04-30 21:01:08 +00004017 count_mmac_params(tline->next, &nparam, &params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004018
4019 /*
4020 * So we know how many parameters we've got. Find the MMacro
4021 * structure that handles this number.
4022 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004023 while (m) {
4024 if (m->nparam_min <= nparam
4025 && (m->plus || nparam <= m->nparam_max)) {
4026 /*
4027 * This one is right. Just check if cycle removal
4028 * prohibits us using it before we actually celebrate...
4029 */
4030 if (m->in_progress) {
H. Peter Anvineba20a72002-04-30 20:53:55 +00004031#if 0
H. Peter Anvine2c80182005-01-15 22:15:51 +00004032 error(ERR_NONFATAL,
4033 "self-reference in multi-line macro `%s'", m->name);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004034#endif
H. Peter Anvine2c80182005-01-15 22:15:51 +00004035 nasm_free(params);
4036 return NULL;
4037 }
4038 /*
4039 * It's right, and we can use it. Add its default
4040 * parameters to the end of our list if necessary.
4041 */
4042 if (m->defaults && nparam < m->nparam_min + m->ndefs) {
4043 params =
4044 nasm_realloc(params,
4045 ((m->nparam_min + m->ndefs +
4046 1) * sizeof(*params)));
4047 while (nparam < m->nparam_min + m->ndefs) {
4048 params[nparam] = m->defaults[nparam - m->nparam_min];
4049 nparam++;
4050 }
4051 }
4052 /*
4053 * If we've gone over the maximum parameter count (and
4054 * we're in Plus mode), ignore parameters beyond
4055 * nparam_max.
4056 */
4057 if (m->plus && nparam > m->nparam_max)
4058 nparam = m->nparam_max;
4059 /*
4060 * Then terminate the parameter list, and leave.
4061 */
4062 if (!params) { /* need this special case */
4063 params = nasm_malloc(sizeof(*params));
4064 nparam = 0;
4065 }
4066 params[nparam] = NULL;
4067 *params_array = params;
4068 return m;
4069 }
4070 /*
4071 * This one wasn't right: look for the next one with the
4072 * same name.
4073 */
4074 for (m = m->next; m; m = m->next)
4075 if (!mstrcmp(m->name, tline->text, m->casesense))
4076 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004077 }
4078
4079 /*
4080 * After all that, we didn't find one with the right number of
4081 * parameters. Issue a warning, and fail to expand the macro.
4082 */
H. Peter Anvin917a3492008-09-24 09:14:49 -07004083 error(ERR_WARNING|ERR_PASS1|ERR_WARN_MNP,
H. Peter Anvine2c80182005-01-15 22:15:51 +00004084 "macro `%s' exists, but not taking %d parameters",
4085 tline->text, nparam);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004086 nasm_free(params);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004087 return NULL;
4088}
4089
4090/*
4091 * Expand the multi-line macro call made by the given line, if
4092 * there is one to be expanded. If there is, push the expansion on
H. Peter Anvineba20a72002-04-30 20:53:55 +00004093 * istk->expansion and return 1. Otherwise return 0.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004094 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004095static int expand_mmacro(Token * tline)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004096{
4097 Token *startline = tline;
4098 Token *label = NULL;
4099 int dont_prepend = 0;
H. Peter Anvince2233b2008-05-25 21:57:00 -07004100 Token **params, *t, *mtok, *tt;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004101 MMacro *m;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004102 Line *l, *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004103 int i, nparam, *paramlen;
H. Peter Anvinc751e862008-06-09 10:18:45 -07004104 const char *mname;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004105
4106 t = tline;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004107 skip_white_(t);
H. Peter Anvince2233b2008-05-25 21:57:00 -07004108 /* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
H. Peter Anvindce1e2f2002-04-30 21:06:37 +00004109 if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004110 return 0;
H. Peter Anvince2233b2008-05-25 21:57:00 -07004111 mtok = t;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004112 m = is_mmacro(t, &params);
H. Peter Anvinc751e862008-06-09 10:18:45 -07004113 if (m) {
4114 mname = t->text;
4115 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004116 Token *last;
4117 /*
4118 * We have an id which isn't a macro call. We'll assume
4119 * it might be a label; we'll also check to see if a
4120 * colon follows it. Then, if there's another id after
4121 * that lot, we'll check it again for macro-hood.
4122 */
4123 label = last = t;
4124 t = t->next;
4125 if (tok_type_(t, TOK_WHITESPACE))
4126 last = t, t = t->next;
4127 if (tok_is_(t, ":")) {
4128 dont_prepend = 1;
4129 last = t, t = t->next;
4130 if (tok_type_(t, TOK_WHITESPACE))
4131 last = t, t = t->next;
4132 }
4133 if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
4134 return 0;
4135 last->next = NULL;
H. Peter Anvinc751e862008-06-09 10:18:45 -07004136 mname = t->text;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004137 tline = t;
H. Peter Anvineba20a72002-04-30 20:53:55 +00004138 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004139
4140 /*
4141 * Fix up the parameters: this involves stripping leading and
4142 * trailing whitespace, then stripping braces if they are
4143 * present.
4144 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004145 for (nparam = 0; params[nparam]; nparam++) ;
H. Peter Anvin734b1882002-04-30 21:01:08 +00004146 paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004147
H. Peter Anvine2c80182005-01-15 22:15:51 +00004148 for (i = 0; params[i]; i++) {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004149 int brace = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004150 int comma = (!m->plus || i < nparam - 1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004151
H. Peter Anvine2c80182005-01-15 22:15:51 +00004152 t = params[i];
4153 skip_white_(t);
4154 if (tok_is_(t, "{"))
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004155 t = t->next, brace = true, comma = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004156 params[i] = t;
4157 paramlen[i] = 0;
4158 while (t) {
4159 if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
4160 break; /* ... because we have hit a comma */
4161 if (comma && t->type == TOK_WHITESPACE
4162 && tok_is_(t->next, ","))
4163 break; /* ... or a space then a comma */
4164 if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
4165 break; /* ... or a brace */
4166 t = t->next;
4167 paramlen[i]++;
4168 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004169 }
4170
4171 /*
4172 * OK, we have a MMacro structure together with a set of
4173 * parameters. We must now go through the expansion and push
H. Peter Anvin76690a12002-04-30 20:52:49 +00004174 * copies of each Line on to istk->expansion. Substitution of
4175 * parameter tokens and macro-local tokens doesn't get done
4176 * until the single-line macro substitution process; this is
4177 * because delaying them allows us to change the semantics
4178 * later through %rotate.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004179 *
H. Peter Anvin76690a12002-04-30 20:52:49 +00004180 * First, push an end marker on to istk->expansion, mark this
4181 * macro as in progress, and set up its invocation-specific
4182 * variables.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004183 */
4184 ll = nasm_malloc(sizeof(Line));
4185 ll->next = istk->expansion;
4186 ll->finishes = m;
4187 ll->first = NULL;
4188 istk->expansion = ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004189
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004190 m->in_progress = true;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004191 m->params = params;
4192 m->iline = tline;
4193 m->nparam = nparam;
4194 m->rotate = 0;
4195 m->paramlen = paramlen;
4196 m->unique = unique++;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004197 m->lineno = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004198
4199 m->next_active = istk->mstk;
4200 istk->mstk = m;
4201
H. Peter Anvine2c80182005-01-15 22:15:51 +00004202 for (l = m->expansion; l; l = l->next) {
4203 Token **tail;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004204
H. Peter Anvine2c80182005-01-15 22:15:51 +00004205 ll = nasm_malloc(sizeof(Line));
4206 ll->finishes = NULL;
4207 ll->next = istk->expansion;
4208 istk->expansion = ll;
4209 tail = &ll->first;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004210
H. Peter Anvine2c80182005-01-15 22:15:51 +00004211 for (t = l->first; t; t = t->next) {
4212 Token *x = t;
H. Peter Anvince2233b2008-05-25 21:57:00 -07004213 switch (t->type) {
4214 case TOK_PREPROC_Q:
H. Peter Anvinc751e862008-06-09 10:18:45 -07004215 tt = *tail = new_Token(NULL, TOK_ID, mname, 0);
H. Peter Anvince2233b2008-05-25 21:57:00 -07004216 break;
4217 case TOK_PREPROC_QQ:
4218 tt = *tail = new_Token(NULL, TOK_ID, m->name, 0);
4219 break;
4220 case TOK_PREPROC_ID:
4221 if (t->text[1] == '0' && t->text[2] == '0') {
4222 dont_prepend = -1;
4223 x = label;
4224 if (!x)
4225 continue;
4226 }
4227 /* fall through */
4228 default:
4229 tt = *tail = new_Token(NULL, x->type, x->text, 0);
4230 break;
H. Peter Anvin166c2472008-05-28 12:28:58 -07004231 }
H. Peter Anvince2233b2008-05-25 21:57:00 -07004232 tail = &tt->next;
4233 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004234 *tail = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004235 }
4236
4237 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +00004238 * If we had a label, push it on as the first line of
4239 * the macro expansion.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004240 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00004241 if (label) {
4242 if (dont_prepend < 0)
4243 free_tlist(startline);
4244 else {
4245 ll = nasm_malloc(sizeof(Line));
4246 ll->finishes = NULL;
4247 ll->next = istk->expansion;
4248 istk->expansion = ll;
4249 ll->first = startline;
4250 if (!dont_prepend) {
4251 while (label->next)
4252 label = label->next;
4253 label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
4254 }
4255 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004256 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004257
H. Peter Anvin734b1882002-04-30 21:01:08 +00004258 list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004259
H. Peter Anvineba20a72002-04-30 20:53:55 +00004260 return 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004261}
4262
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004263/* The function that actually does the error reporting */
4264static void verror(int severity, const char *fmt, va_list arg)
4265{
4266 char buff[1024];
4267
4268 vsnprintf(buff, sizeof(buff), fmt, arg);
4269
4270 if (istk && istk->mstk && istk->mstk->name)
H. Peter Anvin917a3492008-09-24 09:14:49 -07004271 _error(severity, "(%s:%d) %s", istk->mstk->name,
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004272 istk->mstk->lineno, buff);
4273 else
H. Peter Anvin917a3492008-09-24 09:14:49 -07004274 _error(severity, "%s", buff);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004275}
4276
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004277/*
4278 * Since preprocessor always operate only on the line that didn't
H. Peter Anvin917a3492008-09-24 09:14:49 -07004279 * arrived yet, we should always use ERR_OFFBY1.
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004280 */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004281static void error(int severity, const char *fmt, ...)
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004282{
4283 va_list arg;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004284
4285 /* If we're in a dead branch of IF or something like it, ignore the error */
H. Peter Anvin77ba0c62002-05-14 03:18:53 +00004286 if (istk && istk->conds && !emitting(istk->conds->state))
H. Peter Anvine2c80182005-01-15 22:15:51 +00004287 return;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004288
H. Peter Anvin734b1882002-04-30 21:01:08 +00004289 va_start(arg, fmt);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004290 verror(severity, fmt, arg);
H. Peter Anvin734b1882002-04-30 21:01:08 +00004291 va_end(arg);
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004292}
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004293
Victor van den Elzen3b404c02008-09-18 13:51:36 +02004294/*
4295 * Because %else etc are evaluated in the state context
4296 * of the previous branch, errors might get lost with error():
4297 * %if 0 ... %else trailing garbage ... %endif
4298 * So %else etc should report errors with this function.
4299 */
4300static void error_precond(int severity, const char *fmt, ...)
4301{
4302 va_list arg;
4303
4304 /* Only ignore the error if it's really in a dead branch */
4305 if (istk && istk->conds && istk->conds->state == COND_NEVER)
4306 return;
4307
4308 va_start(arg, fmt);
4309 verror(severity, fmt, arg);
4310 va_end(arg);
H. Peter Anvinaf535c12002-04-30 20:59:21 +00004311}
4312
H. Peter Anvin734b1882002-04-30 21:01:08 +00004313static void
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004314pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07004315 ListGen * listgen, StrList **deplist)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004316{
H. Peter Anvin7383b402008-09-24 10:20:40 -07004317 Token *t;
4318
H. Peter Anvin99941bf2002-05-14 17:44:03 +00004319 _error = errfunc;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004320 cstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004321 istk = nasm_malloc(sizeof(Include));
4322 istk->next = NULL;
4323 istk->conds = NULL;
4324 istk->expansion = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004325 istk->mstk = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004326 istk->fp = fopen(file, "r");
H. Peter Anvineba20a72002-04-30 20:53:55 +00004327 istk->fname = NULL;
4328 src_set_fname(nasm_strdup(file));
4329 src_set_linnum(0);
4330 istk->lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004331 if (!istk->fp)
H. Peter Anvin917a3492008-09-24 09:14:49 -07004332 error(ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'",
H. Peter Anvine2c80182005-01-15 22:15:51 +00004333 file);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004334 defining = NULL;
Charles Crayned4200be2008-07-12 16:42:33 -07004335 nested_mac_count = 0;
4336 nested_rep_count = 0;
H. Peter Anvin97a23472007-09-16 17:57:25 -07004337 init_macros();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004338 unique = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004339 if (tasm_compatible_mode) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07004340 stdmacpos = nasm_stdmac;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004341 } else {
H. Peter Anvina4835d42008-05-20 14:21:29 -07004342 stdmacpos = nasm_stdmac_after_tasm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004343 }
H. Peter Anvind2456592008-06-19 15:04:18 -07004344 any_extrastdmac = extrastdmac && *extrastdmac;
4345 do_predef = true;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004346 list = listgen;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004347 evaluate = eval;
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004348
4349 /*
4350 * 0 for dependencies, 1 for preparatory passes, 2 for final pass.
4351 * The caller, however, will also pass in 3 for preprocess-only so
4352 * we can set __PASS__ accordingly.
4353 */
4354 pass = apass > 2 ? 2 : apass;
4355
H. Peter Anvin9e1f5282008-05-29 21:38:00 -07004356 dephead = deptail = deplist;
4357 if (deplist) {
4358 StrList *sl = nasm_malloc(strlen(file)+1+sizeof sl->next);
4359 sl->next = NULL;
4360 strcpy(sl->str, file);
4361 *deptail = sl;
4362 deptail = &sl->next;
4363 }
H. Peter Anvin7383b402008-09-24 10:20:40 -07004364
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004365 /*
4366 * Define the __PASS__ macro. This is defined here unlike
4367 * all the other builtins, because it is special -- it varies between
4368 * passes.
4369 */
H. Peter Anvin7383b402008-09-24 10:20:40 -07004370 t = nasm_malloc(sizeof(*t));
4371 t->next = NULL;
H. Peter Anvin61f130f2008-09-25 15:45:06 -07004372 make_tok_num(t, apass);
H. Peter Anvin7383b402008-09-24 10:20:40 -07004373 t->a.mac = NULL;
4374 define_smacro(NULL, "__PASS__", true, 0, t);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004375}
4376
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004377static char *pp_getline(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004378{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004379 char *line;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004380 Token *tline;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004381
H. Peter Anvine2c80182005-01-15 22:15:51 +00004382 while (1) {
4383 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00004384 * Fetch a tokenized line, either from the macro-expansion
H. Peter Anvine2c80182005-01-15 22:15:51 +00004385 * buffer or from the input file.
4386 */
4387 tline = NULL;
4388 while (istk->expansion && istk->expansion->finishes) {
4389 Line *l = istk->expansion;
4390 if (!l->finishes->name && l->finishes->in_progress > 1) {
4391 Line *ll;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004392
H. Peter Anvine2c80182005-01-15 22:15:51 +00004393 /*
4394 * This is a macro-end marker for a macro with no
4395 * name, which means it's not really a macro at all
4396 * but a %rep block, and the `in_progress' field is
4397 * more than 1, meaning that we still need to
4398 * repeat. (1 means the natural last repetition; 0
4399 * means termination by %exitrep.) We have
4400 * therefore expanded up to the %endrep, and must
4401 * push the whole block on to the expansion buffer
4402 * again. We don't bother to remove the macro-end
4403 * marker: we'd only have to generate another one
4404 * if we did.
4405 */
4406 l->finishes->in_progress--;
4407 for (l = l->finishes->expansion; l; l = l->next) {
4408 Token *t, *tt, **tail;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004409
H. Peter Anvine2c80182005-01-15 22:15:51 +00004410 ll = nasm_malloc(sizeof(Line));
4411 ll->next = istk->expansion;
4412 ll->finishes = NULL;
4413 ll->first = NULL;
4414 tail = &ll->first;
H. Peter Anvin76690a12002-04-30 20:52:49 +00004415
H. Peter Anvine2c80182005-01-15 22:15:51 +00004416 for (t = l->first; t; t = t->next) {
4417 if (t->text || t->type == TOK_WHITESPACE) {
4418 tt = *tail =
4419 new_Token(NULL, t->type, t->text, 0);
4420 tail = &tt->next;
4421 }
4422 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004423
H. Peter Anvine2c80182005-01-15 22:15:51 +00004424 istk->expansion = ll;
4425 }
4426 } else {
4427 /*
4428 * Check whether a `%rep' was started and not ended
4429 * within this macro expansion. This can happen and
4430 * should be detected. It's a fatal error because
4431 * I'm too confused to work out how to recover
4432 * sensibly from it.
4433 */
4434 if (defining) {
4435 if (defining->name)
4436 error(ERR_PANIC,
4437 "defining with name in expansion");
4438 else if (istk->mstk->name)
4439 error(ERR_FATAL,
4440 "`%%rep' without `%%endrep' within"
4441 " expansion of macro `%s'",
4442 istk->mstk->name);
4443 }
H. Peter Anvin87bc6192002-04-30 20:53:16 +00004444
H. Peter Anvine2c80182005-01-15 22:15:51 +00004445 /*
4446 * FIXME: investigate the relationship at this point between
4447 * istk->mstk and l->finishes
4448 */
4449 {
4450 MMacro *m = istk->mstk;
4451 istk->mstk = m->next_active;
4452 if (m->name) {
4453 /*
4454 * This was a real macro call, not a %rep, and
4455 * therefore the parameter information needs to
4456 * be freed.
4457 */
4458 nasm_free(m->params);
4459 free_tlist(m->iline);
4460 nasm_free(m->paramlen);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004461 l->finishes->in_progress = false;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004462 } else
4463 free_mmacro(m);
4464 }
4465 istk->expansion = l->next;
4466 nasm_free(l);
4467 list->downlevel(LIST_MACRO);
4468 }
4469 }
4470 while (1) { /* until we get a line we can use */
H. Peter Anvineba20a72002-04-30 20:53:55 +00004471
H. Peter Anvine2c80182005-01-15 22:15:51 +00004472 if (istk->expansion) { /* from a macro expansion */
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004473 char *p;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004474 Line *l = istk->expansion;
4475 if (istk->mstk)
4476 istk->mstk->lineno++;
4477 tline = l->first;
4478 istk->expansion = l->next;
4479 nasm_free(l);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004480 p = detoken(tline, false);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004481 list->line(LIST_MACRO, p);
4482 nasm_free(p);
4483 break;
4484 }
4485 line = read_line();
4486 if (line) { /* from the current input file */
4487 line = prepreproc(line);
Keith Kaniosb7a89542007-04-12 02:40:54 +00004488 tline = tokenize(line);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004489 nasm_free(line);
4490 break;
4491 }
4492 /*
4493 * The current file has ended; work down the istk
4494 */
4495 {
4496 Include *i = istk;
4497 fclose(i->fp);
4498 if (i->conds)
4499 error(ERR_FATAL,
4500 "expected `%%endif' before end of file");
4501 /* only set line and file name if there's a next node */
4502 if (i->next) {
4503 src_set_linnum(i->lineno);
4504 nasm_free(src_set_fname(i->fname));
H. Peter Anvin86877b22008-06-20 15:55:45 -07004505 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00004506 istk = i->next;
4507 list->downlevel(LIST_INCLUDE);
4508 nasm_free(i);
4509 if (!istk)
4510 return NULL;
Victor van den Elzen4c9d6222008-10-01 13:08:50 +02004511 if (istk->expansion && istk->expansion->finishes)
4512 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004513 }
4514 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004515
H. Peter Anvine2c80182005-01-15 22:15:51 +00004516 /*
4517 * We must expand MMacro parameters and MMacro-local labels
4518 * _before_ we plunge into directive processing, to cope
4519 * with things like `%define something %1' such as STRUC
4520 * uses. Unless we're _defining_ a MMacro, in which case
4521 * those tokens should be left alone to go into the
4522 * definition; and unless we're in a non-emitting
4523 * condition, in which case we don't want to meddle with
4524 * anything.
4525 */
Charles Crayned4200be2008-07-12 16:42:33 -07004526 if (!defining && !(istk->conds && !emitting(istk->conds->state))
H. Peter Anvin992fe752008-10-19 15:45:05 -07004527 && !(istk->mstk && !istk->mstk->in_progress)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00004528 tline = expand_mmac_params(tline);
H. Peter Anvin992fe752008-10-19 15:45:05 -07004529 }
H. Peter Anvin76690a12002-04-30 20:52:49 +00004530
H. Peter Anvine2c80182005-01-15 22:15:51 +00004531 /*
4532 * Check the line to see if it's a preprocessor directive.
4533 */
4534 if (do_directive(tline) == DIRECTIVE_FOUND) {
4535 continue;
4536 } else if (defining) {
4537 /*
4538 * We're defining a multi-line macro. We emit nothing
4539 * at all, and just
Keith Kaniosb7a89542007-04-12 02:40:54 +00004540 * shove the tokenized line on to the macro definition.
H. Peter Anvine2c80182005-01-15 22:15:51 +00004541 */
4542 Line *l = nasm_malloc(sizeof(Line));
4543 l->next = defining->expansion;
4544 l->first = tline;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004545 l->finishes = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004546 defining->expansion = l;
4547 continue;
4548 } else if (istk->conds && !emitting(istk->conds->state)) {
4549 /*
4550 * We're in a non-emitting branch of a condition block.
4551 * Emit nothing at all, not even a blank line: when we
4552 * emerge from the condition we'll give a line-number
4553 * directive so we keep our place correctly.
4554 */
4555 free_tlist(tline);
4556 continue;
4557 } else if (istk->mstk && !istk->mstk->in_progress) {
4558 /*
4559 * We're in a %rep block which has been terminated, so
4560 * we're walking through to the %endrep without
4561 * emitting anything. Emit nothing at all, not even a
4562 * blank line: when we emerge from the %rep block we'll
4563 * give a line-number directive so we keep our place
4564 * correctly.
4565 */
4566 free_tlist(tline);
4567 continue;
4568 } else {
4569 tline = expand_smacro(tline);
4570 if (!expand_mmacro(tline)) {
4571 /*
Keith Kaniosb7a89542007-04-12 02:40:54 +00004572 * De-tokenize the line again, and emit it.
H. Peter Anvine2c80182005-01-15 22:15:51 +00004573 */
H. Peter Anvin6867acc2007-10-10 14:58:45 -07004574 line = detoken(tline, true);
H. Peter Anvine2c80182005-01-15 22:15:51 +00004575 free_tlist(tline);
4576 break;
4577 } else {
4578 continue; /* expand_mmacro calls free_tlist */
4579 }
4580 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004581 }
4582
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004583 return line;
4584}
4585
H. Peter Anvine2c80182005-01-15 22:15:51 +00004586static void pp_cleanup(int pass)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004587{
H. Peter Anvine2c80182005-01-15 22:15:51 +00004588 if (defining) {
Victor van den Elzen8f1120f2008-07-16 13:41:37 +02004589 if(defining->name) {
4590 error(ERR_NONFATAL,
4591 "end of file while still defining macro `%s'",
4592 defining->name);
4593 } else {
4594 error(ERR_NONFATAL, "end of file while still in %%rep");
4595 }
4596
H. Peter Anvine2c80182005-01-15 22:15:51 +00004597 free_mmacro(defining);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004598 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004599 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004600 ctx_pop();
H. Peter Anvin97a23472007-09-16 17:57:25 -07004601 free_macros();
H. Peter Anvine2c80182005-01-15 22:15:51 +00004602 while (istk) {
4603 Include *i = istk;
4604 istk = istk->next;
4605 fclose(i->fp);
4606 nasm_free(i->fname);
4607 nasm_free(i);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004608 }
4609 while (cstk)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004610 ctx_pop();
H. Peter Anvin86877b22008-06-20 15:55:45 -07004611 nasm_free(src_set_fname(NULL));
H. Peter Anvine2c80182005-01-15 22:15:51 +00004612 if (pass == 0) {
H. Peter Anvin86877b22008-06-20 15:55:45 -07004613 IncPath *i;
H. Peter Anvine2c80182005-01-15 22:15:51 +00004614 free_llist(predef);
4615 delete_Blocks();
H. Peter Anvin86877b22008-06-20 15:55:45 -07004616 while ((i = ipath)) {
4617 ipath = i->next;
4618 if (i->path)
4619 nasm_free(i->path);
4620 nasm_free(i);
4621 }
H. Peter Anvin11dfa1a2008-07-02 18:11:04 -07004622 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004623}
4624
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004625void pp_include_path(char *path)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004626{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004627 IncPath *i;
H. Peter Anvin37a321f2007-09-24 13:41:58 -07004628
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004629 i = nasm_malloc(sizeof(IncPath));
H. Peter Anvin37a321f2007-09-24 13:41:58 -07004630 i->path = path ? nasm_strdup(path) : NULL;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004631 i->next = NULL;
4632
H. Peter Anvine2c80182005-01-15 22:15:51 +00004633 if (ipath != NULL) {
4634 IncPath *j = ipath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004635 while (j->next != NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004636 j = j->next;
4637 j->next = i;
4638 } else {
4639 ipath = i;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004640 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004641}
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +00004642
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004643void pp_pre_include(char *fname)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004644{
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004645 Token *inc, *space, *name;
4646 Line *l;
4647
H. Peter Anvin734b1882002-04-30 21:01:08 +00004648 name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
4649 space = new_Token(name, TOK_WHITESPACE, NULL, 0);
4650 inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004651
4652 l = nasm_malloc(sizeof(Line));
4653 l->next = predef;
4654 l->first = inc;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004655 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004656 predef = l;
4657}
4658
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004659void pp_pre_define(char *definition)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004660{
4661 Token *def, *space;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004662 Line *l;
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004663 char *equals;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004664
4665 equals = strchr(definition, '=');
H. Peter Anvin734b1882002-04-30 21:01:08 +00004666 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4667 def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004668 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004669 *equals = ' ';
Keith Kaniosb7a89542007-04-12 02:40:54 +00004670 space->next = tokenize(definition);
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004671 if (equals)
H. Peter Anvine2c80182005-01-15 22:15:51 +00004672 *equals = '=';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004673
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004674 l = nasm_malloc(sizeof(Line));
4675 l->next = predef;
4676 l->first = def;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004677 l->finishes = NULL;
H. Peter Anvin6768eb72002-04-30 20:52:26 +00004678 predef = l;
4679}
4680
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004681void pp_pre_undefine(char *definition)
H. Peter Anvin620515a2002-04-30 20:57:38 +00004682{
4683 Token *def, *space;
4684 Line *l;
4685
H. Peter Anvin734b1882002-04-30 21:01:08 +00004686 space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
4687 def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
Keith Kaniosb7a89542007-04-12 02:40:54 +00004688 space->next = tokenize(definition);
H. Peter Anvin620515a2002-04-30 20:57:38 +00004689
4690 l = nasm_malloc(sizeof(Line));
4691 l->next = predef;
4692 l->first = def;
H. Peter Anvin538002d2008-06-28 18:30:27 -07004693 l->finishes = NULL;
H. Peter Anvin620515a2002-04-30 20:57:38 +00004694 predef = l;
4695}
4696
Keith Kaniosb7a89542007-04-12 02:40:54 +00004697/*
4698 * Added by Keith Kanios:
4699 *
4700 * This function is used to assist with "runtime" preprocessor
4701 * directives. (e.g. pp_runtime("%define __BITS__ 64");)
4702 *
4703 * ERRORS ARE IGNORED HERE, SO MAKE COMPLETELY SURE THAT YOU
4704 * PASS A VALID STRING TO THIS FUNCTION!!!!!
4705 */
4706
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004707void pp_runtime(char *definition)
Keith Kaniosb7a89542007-04-12 02:40:54 +00004708{
4709 Token *def;
H. Peter Anvin70653092007-10-19 14:42:29 -07004710
Keith Kaniosb7a89542007-04-12 02:40:54 +00004711 def = tokenize(definition);
4712 if(do_directive(def) == NO_DIRECTIVE_FOUND)
4713 free_tlist(def);
H. Peter Anvin70653092007-10-19 14:42:29 -07004714
Keith Kaniosb7a89542007-04-12 02:40:54 +00004715}
4716
H. Peter Anvina70547f2008-07-19 21:44:26 -07004717void pp_extra_stdmac(macros_t *macros)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004718{
H. Peter Anvin76690a12002-04-30 20:52:49 +00004719 extrastdmac = macros;
4720}
4721
Keith Kaniosa5fc6462007-10-13 07:09:22 -07004722static void make_tok_num(Token * tok, int64_t val)
H. Peter Anvineba20a72002-04-30 20:53:55 +00004723{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00004724 char numbuf[20];
Keith Kaniosa5fc6462007-10-13 07:09:22 -07004725 snprintf(numbuf, sizeof(numbuf), "%"PRId64"", val);
H. Peter Anvineba20a72002-04-30 20:53:55 +00004726 tok->text = nasm_strdup(numbuf);
4727 tok->type = TOK_NUMBER;
4728}
4729
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00004730Preproc nasmpp = {
4731 pp_reset,
4732 pp_getline,
4733 pp_cleanup
4734};