145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* -*- mode: c; c-file-style: "bsd" -*- */
245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* preproc.c   macro preprocessor for the Netwide Assembler
345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Julian Hall. All rights reserved. The software is
645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * redistributable under the licence given in the file "Licence"
745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * distributed in the NASM archive.
845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * initial version 18/iii/97 by Simon Tatham
1045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
1145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
1245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Typical flow of text through preproc
1345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
1445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * pp_getline gets tokenised lines, either
1545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
1645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *   from a macro expansion
1745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
1845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * or
1945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *   {
2045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *   read_line  gets raw text from stdmacpos, or predef, or current input file
2145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *   tokenise   converts to tokens
2245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *   }
2345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
2445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * expand_mmac_params is used to expand %1 etc., unless a macro is being
2545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * defined or a false conditional is being processed
2645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * (%0, %1, %+1, %-1, %%foo
2745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
2845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * do_directive checks for directives
2945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * expand_smacro is used to expand single line macros
3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * expand_mmacro is used to expand multi-line macros
3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * detoken is used to convert the line back to text
3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <util.h>
3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <libyasm-stdint.h>
3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <libyasm/coretype.h>
3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <libyasm/intnum.h>
4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <libyasm/expr.h>
4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <libyasm/file.h>
4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <stdarg.h>
4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <ctype.h>
4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <limits.h>
4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "nasm.h"
4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "nasmlib.h"
4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "nasm-pp.h"
4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct SMacro SMacro;
5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct MMacro MMacro;
5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct Context Context;
5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct Token Token;
5445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct Blocks Blocks;
5545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct Line Line;
5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct Include Include;
5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct Cond Cond;
5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
6045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Store the definition of a single-line macro.
6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct SMacro
6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    SMacro *next;
6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *name;
66a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    int level;
6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int casesense;
6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int nparam;
6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int in_progress;
7045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *expansion;
7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Store the definition of a multi-line macro. This is also used to
7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * store the interiors of `%rep...%endrep' blocks, which are
7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * effectively self-re-invoking multi-line macros which simply
7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * don't have a name or bother to appear in the hash tables. %rep
7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * blocks are signified by having a NULL `name' field.
7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * In a MMacro describing a `%rep' block, the `in_progress' field
8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * isn't merely boolean, but gives the number of repeats left to
8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * run.
8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The `next' field is used for storing MMacros in hash tables; the
8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * `next_active' field is for stacking them on istk entries.
8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * When a MMacro is being expanded, `params', `iline', `nparam',
8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * `paramlen', `rotate' and `unique' are local to the invocation.
8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct MMacro
9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    MMacro *next;
9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *name;
9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int casesense;
9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    long nparam_min, nparam_max;
9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int plus;                   /* is the last parameter greedy? */
9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int nolist;                 /* is this macro listing-inhibited? */
9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int in_progress;
9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *dlist;               /* All defaults as one list */
10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token **defaults;           /* Parameter default pointers */
10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int ndefs;                  /* number of default parameters */
10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Line *expansion;
10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    MMacro *next_active;
10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    MMacro *rep_nest;           /* used for nesting %rep */
10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token **params;             /* actual parameters */
10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *iline;               /* invocation line */
10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    long nparam, rotate, *paramlen;
10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long unique;
11045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int lineno;                 /* Current line number on expansion */
11145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
11245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The context stack is composed of a linked list of these.
11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct Context
11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Context *next;
11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    SMacro *localmac;
12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *name;
12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long number;
12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
12345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * This is the internal form which we break input lines up into.
12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Typically stored in linked lists.
12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * necessarily used as-is, but is intended to denote the number of
13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * the substituted parameter. So in the definition
13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *     %define a(x,y) ( (x) & ~(y) )
13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * the token representing `x' will have its type changed to
13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * TOK_SMAC_PARAM, but the one representing `y' will be
13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * TOK_SMAC_PARAM+1.
13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * which doesn't need quotes around it. Used in the pre-include
14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * mechanism as an alternative to trying to find a sensible type of
14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * quote to use on the filename we were passed.
14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct Token
14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *next;
14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *text;
14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    SMacro *mac;                /* associated macro for TOK_SMAC_END */
14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int type;
14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgenum
15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
15345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM,
15445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TOK_INTERNAL_STRING
15545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
15645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
15845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Multi-line macro definitions are stored as a linked list of
15945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * these, which is essentially a container to allow several linked
16045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * lists of Tokens.
16145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
16245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Note that in this module, linked lists are treated as stacks
16345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * wherever possible. For this reason, Lines are _pushed_ on to the
16445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * `expansion' field in MMacro structures, so that the linked list,
16545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * if walked, would give the macro lines in reverse order; this
16645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * means that we can walk the list when expanding a macro, and thus
16745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * push the lines on to the `expansion' field in _istk_ in reverse
16845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * order (so that when popped back off they are in the right
16945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * order). It may seem cockeyed, and it relies on my design having
17045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * an even number of steps in, but it works...
17145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
17245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Some of these structures, rather than being actual lines, are
17345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * markers delimiting the end of the expansion of a given macro.
17445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * This is for use in the cycle-tracking and %rep-handling code.
17545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Such structures have `finishes' non-NULL, and `first' NULL. All
17645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * others have `finishes' NULL, but `first' may still be NULL if
17745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * the line is blank.
17845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
17945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct Line
18045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
18145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Line *next;
18245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    MMacro *finishes;
18345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *first;
18445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
18545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
18645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
18745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * To handle an arbitrary level of file inclusion, we maintain a
18845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * stack (ie linked list) of these things.
18945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
19045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct Include
19145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
19245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Include *next;
19345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    FILE *fp;
19445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Cond *conds;
19545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Line *expansion;
19645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *fname;
19745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int lineno, lineinc;
19845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    MMacro *mstk;               /* stack of active macros/reps */
19945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
20045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
20245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Conditional assembly: we maintain a separate stack of these for
20345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * each level of file inclusion. (The only reason we keep the
20445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * stacks separate is to ensure that a stray `%endif' in a file
20545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * included from within the true branch of a `%if' won't terminate
20645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * it and cause confusion: instead, rightly, it'll cause an error.)
20745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
20845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct Cond
20945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
21045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Cond *next;
21145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int state;
21245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
21345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgenum
21445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
21545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
21645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * These states are for use just after %if or %elif: IF_TRUE
21745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * means the condition has evaluated to truth so we are
21845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * currently emitting, whereas IF_FALSE means we are not
21945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * currently emitting but will start doing so if a %else comes
22045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * up. In these states, all directives are admissible: %elif,
22145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * %else and %endif. (And of course %if.)
22245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
22345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    COND_IF_TRUE, COND_IF_FALSE,
22445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
22545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * These states come up after a %else: ELSE_TRUE means we're
22645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
22745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * any %elif or %else will cause an error.
22845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
22945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    COND_ELSE_TRUE, COND_ELSE_FALSE,
23045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
23145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * This state means that we're not emitting now, and also that
23245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * nothing until %endif will be emitted at all. It's for use in
23345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * two circumstances: (i) when we've had our moment of emission
23445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * and have now started seeing %elifs, and (ii) when the
23545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * condition construct in question is contained within a
23645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * non-emitting branch of a larger condition construct.
23745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
23845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    COND_NEVER
23945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
24045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
24145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
24245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
24345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * These defines are used as the possible return values for do_directive
24445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
24545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define NO_DIRECTIVE_FOUND  0
24645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define DIRECTIVE_FOUND     1
24745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
24845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
24945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Condition codes. Note that we use c_ prefix not C_ because C_ is
25045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * used in nasm.h for the "real" condition codes. At _this_ level,
25145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * we treat CXZ and ECXZ as condition codes, albeit non-invertible
25245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ones, so we need a different enum...
25345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
25445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const char *conditions[] = {
25545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
25645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
25745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
25845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
25945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgenum
26045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
26145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
26245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
26345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
26445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
26545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int inverse_ccs[] = {
26645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
26745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    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,
26845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c_Z, c_NO, c_NP, c_PO, c_PE, c_NS, c_NZ
26945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
27045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
27145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
27245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Directive names.
27345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
27445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const char *directives[] = {
27545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%arg",
27645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
27745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%elifid", "%elifidn", "%elifidni", "%elifmacro", "%elifnctx", "%elifndef",
27845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%elifnid", "%elifnidn", "%elifnidni", "%elifnmacro", "%elifnnum", "%elifnstr",
27945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro",
280a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    "%endrep", "%endscope", "%error", "%exitrep", "%iassign", "%idefine", "%if",
28145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifmacro", "%ifnctx",
28245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnmacro", "%ifnnum",
28345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include",
28445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%ixdefine", "%line",
28545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%local",
28645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%macro", "%pop", "%push", "%rep", "%repl", "%rotate",
287a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    "%scope", "%stacksize",
28845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%strlen", "%substr", "%undef", "%xdefine"
28945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
29045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgenum
29145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
29245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    PP_ARG,
29345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
29445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFMACRO, PP_ELIFNCTX, PP_ELIFNDEF,
29545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNMACRO, PP_ELIFNNUM, PP_ELIFNSTR,
29645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO,
297a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    PP_ENDREP, PP_ENDSCOPE, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
29845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFMACRO, PP_IFNCTX,
29945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNMACRO, PP_IFNNUM,
30045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE,
30145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    PP_IXDEFINE, PP_LINE,
30245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    PP_LOCAL,
30345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE,
304a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    PP_SCOPE, PP_STACKSIZE,
30545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    PP_STRLEN, PP_SUBSTR, PP_UNDEF, PP_XDEFINE
30645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
30745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
30845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
30945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int is_condition(int arg)
31045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
31145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return ((arg >= PP_ELIF) && (arg <= PP_ENDIF)) ||
31245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ((arg >= PP_IF) && (arg <= PP_IFSTR));
31345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
31445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
31545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* For TASM compatibility we need to be able to recognise TASM compatible
31645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * conditional compilation directives. Using the NASM pre-processor does
31745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * not work, so we look for them specifically from the following list and
31845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * then jam in the equivalent NASM directive into the input stream.
31945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
32045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
32145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#ifndef MAX
32245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#       define MAX(a,b) ( ((a) > (b)) ? (a) : (b))
32345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#endif
32445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
32545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgenum
32645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
32745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
32845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TM_IFNDEF, TM_INCLUDE, TM_LOCAL,
32945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TM_REPT, TM_IRP, TM_MACRO,
33045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TM_STRUC, TM_SEGMENT
33145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
33245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
33345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const char *tasm_directives[] = {
33445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
33545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "ifndef", "include", "local"
33645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
33745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
33845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int StackSize = 4;
33945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const char *StackPointer = "ebp";
34045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int ArgOffset = 8;
34145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int LocalOffset = 4;
342a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.orgstatic int Level = 0;
34345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
34445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
34545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Context *cstk;
34645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Include *istk;
34745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
34845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic FILE *first_fp = NULL;
34945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
35045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic efunc _error;            /* Pointer to client-provided error reporting function */
35145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic evalfunc evaluate;
35245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
35345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int pass;                /* HACK: pass 0 = generate dependencies only */
35445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
35545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic unsigned long unique;    /* unique identifier numbers */
35645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
35745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Line *builtindef = NULL;
35845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Line *stddef = NULL;
35945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Line *predef = NULL;
36045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int first_line = 1;
36145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
36245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic ListGen *list;
36345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
36445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
36545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The number of hash values we use for the macro lookup tables.
36645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * FIXME: We should *really* be able to configure this at run time,
36745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * or even have the hash table automatically expanding when necessary.
36845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
36945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define NHASH 31
37045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
37145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
37245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The current set of multi-line macros we have defined.
37345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
37445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic MMacro *mmacros[NHASH];
37545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
37645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
37745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The current set of single-line macros we have defined.
37845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
37945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic SMacro *smacros[NHASH];
38045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
38145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
38245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The multi-line macro we are currently defining, or the %rep
38345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * block we are currently reading, if any.
38445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
38545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic MMacro *defining;
38645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
38745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
38845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The number of macro parameters to allocate space for at a time.
38945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
39045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define PARAM_DELTA 16
39145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
39245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
39345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Macros to make NASM ignore some TASM directives before the first include
39445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * directive.
39545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
39645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const char *tasm_compat_macros[] =
39745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
39845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine IDEAL",
39945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine JUMPS",
40045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine END",
40145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine P8086	CPU 8086",
40245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine P186	CPU 186",
40345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine P286	CPU 286",
40445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine P286N	CPU 286",
40545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine P286P	CPU 286 Priv",
40645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine P386	CPU 386",
40745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine P386N	CPU 386",
40845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine P386P	CPU 386 Priv",
40945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine P486	CPU 486",
41045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine P586	CPU 586",
41145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine .8086	CPU 8086",
41245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine .186	CPU 186",
41345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine .286	CPU 286",
41445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine .286C	CPU 286",
41545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine .286P	CPU 286",
41645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine .386	CPU 386",
41745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine .386C	CPU 386",
41845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine .386P	CPU 386",
41945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine .486	CPU 486",
42045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine .486C	CPU 486",
42145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine .486P	CPU 486",
42245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine .586	CPU 586",
42345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine .586C	CPU 586",
42445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine .586P	CPU 586",
42545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "",
42645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%imacro TITLE 1",
42745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%endm",
42845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%imacro NAME 1",
42945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%endm",
43045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "",
43145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%imacro EXTRN 1-*.nolist",
43245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%rep %0",
43345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "[extern %1]",
43445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%rotate 1",
43545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%endrep",
43645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%endmacro",
43745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "",
43845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%imacro PUBLIC 1-*.nolist",
43945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%rep %0",
44045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "[global %1]",
44145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%rotate 1",
44245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%endrep",
44345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%endmacro",
44445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "",
44545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "; this is not needed",
44645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "%idefine PTR",
44745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    NULL
44845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
44945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
45045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int nested_mac_count, nested_rep_count;
45145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
45245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
45345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Tokens are allocated in blocks to improve speed
45445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
45545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define TOKEN_BLOCKSIZE 4096
45645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Token *freeTokens = NULL;
45745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct Blocks {
45845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Blocks *next;
45945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        void *chunk;
46045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
46145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
46245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Blocks blocks = { NULL, NULL };
46345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
46445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
46545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Forward declarations.
46645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
46745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Token *expand_mmac_params(Token * tline);
46845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Token *expand_smacro(Token * tline);
46945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Token *expand_id(Token * tline);
47045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Context *get_ctx(char *name, int all_contexts);
47145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void make_tok_num(Token * tok, yasm_intnum *val);
47245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void error(int severity, const char *fmt, ...);
47345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void *new_Block(size_t size);
47445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void delete_Blocks(void);
47545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Token *new_Token(Token * next, int type, const char *text,
47645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        size_t txtlen);
47745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Token *delete_Token(Token * t);
47845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Token *tokenise(char *line);
47945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
48045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
48145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Macros for safe checking of token pointers, avoid *(NULL)
48245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
48345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define tok_type_(x,t) ((x) && (x)->type == (t))
48445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
48545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
48645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
48745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
48845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Handle TASM specific directives, which do not contain a % in
48945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * front of them. We do it here because I could not find any other
49045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * place to do it for the moment, and it is a hack (ideally it would
49145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * be nice to be able to use the NASM pre-processor to do it).
49245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
49345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
49445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct TMEndItem {
49545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int type;
49645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    void *data;
49745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct TMEndItem *next;
49845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} TMEndItem;
49945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
50045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic TMEndItem *EndmStack = NULL, *EndsStack = NULL;
50145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
50245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgchar **TMParameters;
50345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
50445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct TStrucField {
50545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *name;
50645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *type;
50745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct TStrucField *next;
50845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
50945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct TStruc {
51045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *name;
51145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct TStrucField *fields, *lastField;
51245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct TStruc *next;
51345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
51445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic struct TStruc *TStrucs = NULL;
51545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int inTstruc = 0;
51645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
51745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct TSegmentAssume {
51845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *segreg;
51945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *segment;
52045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
52145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct TSegmentAssume *TAssumes;
52245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
52345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgconst char *tasm_get_segment_register(const char *segment)
52445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
52545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct TSegmentAssume *assume;
52645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!TAssumes)
52745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;
52845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (assume = TAssumes; assume->segreg; assume++) {
52945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!strcmp(assume->segment, segment))
53045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
53145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
53245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return assume->segreg;
53345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
53445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
53545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic char *
53645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgcheck_tasm_directive(char *line)
53745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
53845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int i, j, k, m;
53945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t len, len2;
54045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *p, *oldline, oldchar, *q, oldchar2;
54145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    TMEndItem *end;
54245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
54345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    p = line;
54445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
54545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Skip whitespace */
546a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    while (isspace(*p) && *p != 0 && *p != ';')
54745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        p++;
54845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
54945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Ignore nasm directives */
55045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (*p == '%')
55145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return line;
55245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
55345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Binary search for the directive name */
55445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    len = 0;
555a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    while (!isspace(p[len]) && p[len] != 0 && p[len] != ';')
55645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        len++;
55745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!len)
55845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return line;
55945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
56045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    oldchar = p[len];
56145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    p[len] = 0;
56245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    i = -1;
56345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    j = elements(tasm_directives);
56445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (j - i > 1)
56545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
56645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        k = (j + i) / 2;
56745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        m = nasm_stricmp(p, tasm_directives[k]);
56845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (m == 0)
56945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
57045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* We have found a directive, so jam a % in front of it
57145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * so that NASM will then recognise it as one if it's own.
57245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
57345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p[len] = oldchar;
57445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            len = strlen(p);
57545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            oldline = line;
57645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (k == TM_IFDIFI)
57745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
57845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* NASM does not recognise IFDIFI, so we convert it to
57945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * %ifdef BOGUS. This is not used in NASM comaptible
58045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * code, but does need to parse for the TASM macro
58145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * package.
58245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 */
58345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                line = nasm_malloc(13);
58445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                strcpy(line, "%ifdef BOGUS");
58545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
58645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else if (k == TM_INCLUDE)
58745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
58845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* add double quotes around file name */
58945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p += 7 + 1;
59045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                while (isspace(*p) && *p)
59145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    p++;
59245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                len = strlen(p);
59345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                line = nasm_malloc(1 + 7 + 1 + 1 + len + 1 + 1);
59445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                sprintf(line, "%%include \"%s\"", p);
59545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
59645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
59745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
59845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                line = nasm_malloc(len + 2);
59945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                line[0] = '%';
60045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                memcpy(line + 1, p, len + 1);
60145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
60245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nasm_free(oldline);
60345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return line;
60445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
60545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (m < 0)
60645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
60745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            j = k;
60845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
60945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
61045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            i = k;
61145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
61245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
61345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Not a simple directive */
61445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
61545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!nasm_stricmp(p, "endm")) {
61645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* handle end of endm directive */
61745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        char **parameter;
61845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end = EndmStack;
61945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* undef parameters */
62045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!end) {
62145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error(ERR_FATAL, "ENDM: not in an endm context");
62245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return line;
62345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
62445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        EndmStack = EndmStack->next;
62545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(line);
62645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        switch (end->type) {
62745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case TM_MACRO:
62845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            len = 0;
62945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for (parameter = end->data; *parameter; parameter++)
63045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                len += 6 + 1 + strlen(*parameter) + 1;
63145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            len += 5 + 1;
63245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            line = nasm_malloc(len);
63345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p = line;
63445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for (parameter = end->data; *parameter; parameter++) {
63545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p += sprintf(p, "%%undef %s\n", *parameter);
63645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_free(*parameter);
63745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
63845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nasm_free(end->data);
63945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nasm_free(end);
64045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            sprintf(p, "%%endm");
64145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return line;
64245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case TM_REPT:
64345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nasm_free(end);
64445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return nasm_strdup("%endrep");
64545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case TM_IRP: {
64645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            char **data;
64745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            const char *irp_format =
64845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                "%%undef %s\n"
64945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                "%%rotate 1\n"
65045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                "%%endrep\n"
65145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                "%%endm\n"
65245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                "irp %s\n"
65345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                "%%undef irp";
65445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            data = end->data;
65545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            line = nasm_malloc(strlen(irp_format) - 4 + strlen(data[0])
65645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                   + strlen(data[1]));
65745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            sprintf(line, irp_format, data[0], data[1]);
65845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nasm_free(data[0]);
65945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nasm_free(data[1]);
66045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nasm_free(data);
66145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return line;
66245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
66345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        default:
66445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error(ERR_FATAL, "ENDM: bogus endm context type %d\n",end->type);
66545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return NULL;
66645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
66745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (!nasm_stricmp(p, "end")) {
66845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(line);
66945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return nasm_strdup("");
67045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (!nasm_stricmp(p, "rept")) {
67145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* handle repeat directive */
67245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end = nasm_malloc(sizeof(*end));
67345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end->type = TM_REPT;
67445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end->next = EndmStack;
67545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        EndmStack = end;
67645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        memcpy(p, "%rep", 4);
67745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        p[len] = oldchar;
67845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return line;
67945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (!nasm_stricmp(p, "locals")) {
68045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tasm_locals = 1;
68145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(line);
68245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return nasm_strdup("");
68345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
68445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
68545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!oldchar)
68645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return line;
68745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
68845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* handle two-words directives */
68945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    q = p + len + 1;
69045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Skip whitespaces */
69145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (isspace(*q) && *q)
69245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        q++;
69345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
69445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    len2 = 0;
69545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (!isspace(q[len2]) && q[len2]!=',' && q[len2] != 0)
69645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        len2++;
69745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    oldchar2 = q[len2];
69845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    q[len2] = '\0';
69945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
70045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!nasm_stricmp(p, "irp")) {
70145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* handle indefinite repeat directive */
70245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        const char *irp_format =
70345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            "%%imacro irp 0-*\n"
70445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            "%%rep %%0\n"
70545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            "%%define %s %%1\n";
70645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        char **data;
70745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
70845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data = malloc(2*sizeof(char*));
70945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        oldline = line;
71045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        line = nasm_malloc(strlen(irp_format) - 2 + len2 + 1);
71145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sprintf(line,irp_format,q);
71245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data[0] = nasm_strdup(q);
71345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
71445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!oldchar2)
71545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error(ERR_FATAL, "%s: expected <values>", q + len2);
71645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        p = strchr(q + len2 + 1, '<');
71745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!p)
71845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error(ERR_FATAL, "%s: expected <values>", q + len2);
71945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        p++;
72045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        q = strchr(p, '>');
72145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data[1] = nasm_strndup(p, q - p);
72245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
72345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end = nasm_malloc(sizeof(*end));
72445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end->type = TM_IRP;
72545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end->next = EndmStack;
72645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end->data = data;
72745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        EndmStack = end;
72845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
72945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(oldline);
73045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return line;
73145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (!nasm_stricmp(q, "macro")) {
73245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        char *name = p;
73345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* handle MACRO */
73445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* count parameters */
73545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        j = 1;
73645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        i = 0;
73745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        TMParameters = nasm_malloc(j*sizeof(*TMParameters));
73845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        len = 0;
73945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        p = q + len2 + 1;
74045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Skip whitespaces */
74145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (isspace(*p) && *p)
74245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p++;
74345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (*p) {
74445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Get parameter name */
74545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for (q = p; !isspace(*q) && *q != ',' && *q; q++);
74645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            len2 = q-p;
74745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (len2 == 0)
74845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_FATAL, "'%s': expected parameter name", p);
74945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            TMParameters[i] = nasm_malloc(len2 + 1);
75045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            memcpy(TMParameters[i], p, len2);
75145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            TMParameters[i][len2] = '\0';
75245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            len += len2;
75345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            i++;
75445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (i + 1 > j) {
75545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                j *= 2;
75645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                TMParameters = nasm_realloc(TMParameters,
75745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                               j*sizeof(*TMParameters));
75845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
75945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (i == 1000)
76045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_FATAL, "too many parameters for macro %s", name);
76145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p = q;
76245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (isspace(*p) && *p)
76345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p++;
76445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!*p)
76545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
76645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (*p != ',')
76745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_FATAL, "expected comma");
76845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p++;
76945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (isspace(*p) && *p)
77045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p++;
77145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
77245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        TMParameters[i] = NULL;
77345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        TMParameters = nasm_realloc(TMParameters,
77445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        (i+1)*sizeof(*TMParameters));
77545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        len += 1 + 6 + 1 + strlen(name) + 1 + 3; /* macro definition */
77645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        len += i * (1 + 9 + 1 + 1 + 1 + 3 + 2); /* macro parameter definition */
77745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        oldline = line;
77845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        p = line = nasm_malloc(len + 1);
77945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        p += sprintf(p, "%%imacro %s 0-*", name);
78045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(oldline);
78145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for (j = 0; TMParameters[j]; j++) {
78245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p += sprintf(p, "\n%%idefine %s %%{%-u}", TMParameters[j], j + 1);
78345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
78445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end = nasm_malloc(sizeof(*end));
78545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end->type = TM_MACRO;
78645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end->next = EndmStack;
78745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end->data = TMParameters;
78845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        EndmStack = end;
78945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return line;
79045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (!nasm_stricmp(q, "proc")) {
79145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* handle PROC */
79245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        oldline = line;
79345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        line = nasm_malloc(2 + len + 1);
79445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sprintf(line, "..%s",p);
79545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(oldline);
79645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return line;
79745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (!nasm_stricmp(q, "struc")) {
79845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* handle struc */
79945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        struct TStruc *struc;
80045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (inTstruc) {
80145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error(ERR_FATAL, "STRUC: already in a struc context");
80245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return line;
80345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
80445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        oldline = line;
80545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        line = nasm_malloc(5 + 1 + len + 1);
80645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sprintf(line, "struc %s", p);
80745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        struc = malloc(sizeof(*struc));
80845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        struc->name = nasm_strdup(p);
80945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        struc->fields = NULL;
81045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        struc->lastField = NULL;
81145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        struc->next = TStrucs;
81245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        TStrucs = struc;
81345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        inTstruc = 1;
81445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(oldline);
81545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end = nasm_malloc(sizeof(*end));
81645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end->type = TM_STRUC;
81745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end->next = EndsStack;
81845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        EndsStack = end;
81945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return line;
82045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (!nasm_stricmp(q, "segment")) {
82145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* handle SEGMENT */
82245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        oldline = line;
82345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        line = nasm_strdup(oldchar2?q+len2+1:"");
82445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (tasm_segment) {
82545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error(ERR_FATAL, "SEGMENT: already in a segment context");
82645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return line;
82745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
82845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tasm_segment = nasm_strdup(p);
82945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(oldline);
83045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end = nasm_malloc(sizeof(*end));
83145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end->type = TM_SEGMENT;
83245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end->next = EndsStack;
83345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        EndsStack = end;
83445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return line;
83545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (!nasm_stricmp(p, "ends") || !nasm_stricmp(q, "ends")) {
83645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* handle end of ends directive */
83745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        end = EndsStack;
83845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* undef parameters */
83945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!end) {
84045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error(ERR_FATAL, "ENDS: not in an ends context");
84145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return line;
84245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
84345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        EndsStack = EndsStack->next;
84445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(line);
84545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        switch (end->type) {
84645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case TM_STRUC:
84745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            inTstruc = 0;
84845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return nasm_strdup("endstruc");
84945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case TM_SEGMENT:
85045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* XXX: yes, we leak memory here, but that permits labels
85145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * to avoid strduping... */
85245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tasm_segment = NULL;
85345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return nasm_strdup("");
85445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        default:
85545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error(ERR_FATAL, "ENDS: bogus ends context type %d",end->type);
85645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return NULL;
85745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
85845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (!nasm_stricmp(p, "endp") || !nasm_stricmp(q, "endp")) {
85945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(line);
86045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return nasm_strdup("");
86145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (!nasm_stricmp(p, "assume")) {
86245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        struct TSegmentAssume *assume;
86345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* handle ASSUME */
86445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!TAssumes) {
86545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            TAssumes = nasm_malloc(sizeof(*TAssumes));
86645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            TAssumes[0].segreg = NULL;
86745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
86845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        i = 0;
86945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        q[len2] = oldchar2;
87045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Skip whitespaces */
87145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (isspace(*q) && *q)
87245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            q++;
873a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        while (*q && *q != ';') {
87445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p = q;
875a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            for (; *q && *q != ';' && *q != ':' && !isspace(*q); q++);
876a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            if (!*q || *q == ';')
87745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
87845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* segment register name */
87945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for (assume = TAssumes; assume->segreg; assume++)
88045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (strlen(assume->segreg) == (size_t)(q-p) &&
88145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    !yasm__strncasecmp(assume->segreg, p, q-p))
88245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
88345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!assume->segreg) {
88445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                i = assume - TAssumes + 1;
88545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                TAssumes = nasm_realloc(TAssumes, (i+1)*sizeof(*TAssumes));
88645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                assume = TAssumes + i - 1;
88745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                assume->segreg = nasm_strndup(p, q-p);
88845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                assume[1].segreg = NULL;
88945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
890a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            for (; *q && *q != ';' && *q != ':' && isspace(*q); q++);
89145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (*q != ':')
89245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_FATAL, "expected `:' instead of `%c'", *q);
89345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for (q++; *q && isspace(*q); q++);
89445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
89545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* segment name */
89645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p = q;
897a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            for (; *q && *q != ';' && *q != ',' && !isspace(*q); q++);
89845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            assume->segment = nasm_strndup(p, q-p);
89945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for (; *q && isspace(*q); q++);
900a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            if (*q && *q != ';' && *q != ',')
90145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_FATAL, "expected `,' instead of `%c'", *q);
90245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
903a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            if (*q && *q != ';')
904a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                q++;
905a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            for (; *q && isspace(*q); q++);
90645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
90745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        TAssumes[i].segreg = NULL;
90845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        TAssumes = nasm_realloc(TAssumes, (i+1)*sizeof(*TAssumes));
90945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(line);
91045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return nasm_strdup("");
91145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else if (inTstruc) {
91245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        struct TStrucField *field;
91345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* TODO: handle unnamed data */
91445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        field = nasm_malloc(sizeof(*field));
91545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        field->name = nasm_strdup(p);
91645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* TODO: type struc ! */
91745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        field->type = nasm_strdup(q);
91845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        field->next = NULL;
91945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!TStrucs->fields)
92045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                TStrucs->fields = field;
92145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (TStrucs->lastField)
92245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                TStrucs->lastField->next = field;
92345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        TStrucs->lastField = field;
92445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!oldchar2) {
92545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error(ERR_FATAL, "Expected struc field initializer after %s %s", p, q);
92645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return line;
92745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
92845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        oldline = line;
92945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        line = nasm_malloc(1 + len + 1 + len2 + 1 + strlen(q+len2+1) + 1);
93045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sprintf(line, ".%s %s %s", p, q, q+len2+1);
93145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(oldline);
93245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return line;
93345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
93445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
93545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        struct TStruc *struc;
93645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for (struc = TStrucs; struc; struc = struc->next) {
93745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!yasm__strcasecmp(q, struc->name)) {
93845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                char *r = q + len2 + 1, *s, *t, tasm_param[6];
93945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                struct TStrucField *field = struc->fields;
94045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                int size, n;
94145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!oldchar2) {
94245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_FATAL, "Expected struc field initializer after %s %s", p, q);
94345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return line;
94445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
94545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                r = strchr(r, '<');
94645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!r) {
94745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_FATAL, "Expected < for struc field initializer in %s %s %s", p, q, r);
94845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return line;
94945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
95045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t = strchr(r + 1, '>');
95145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!t) {
95245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_FATAL, "Expected > for struc field initializer in %s %s %s", p, q, r);
95345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return line;
95445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
95545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *t = 0;
95645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                oldline = line;
95745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                size = len + len2 + 128;
95845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                line = nasm_malloc(size);
95945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (defining)
96045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    for (n=0;TMParameters[n];n++)
96145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (!strcmp(TMParameters[n],p)) {
96245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            sprintf(tasm_param,"%%{%d}",n+1);
96345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            p = tasm_param;
96445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
96545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
96645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                n = sprintf(line, "%s: istruc %s\n", p, q);
96745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* use initialisers */
96845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                while ((s = strchr(r + 1, ','))) {
96945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (!field) {
97045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        error(ERR_FATAL, "Too many initializers in structure %s %s", p, q);
97145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        return oldline;
97245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
97345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    *s = 0;
97445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    m = strlen(p) + 1 + strlen(field->name)*2 + 8 +
97545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        strlen(field->type) + 1 + strlen(r+1) + 2;
97645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    size += m;
97745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    line = nasm_realloc(line, size);
97845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    sprintf(line + n, "%s.%s: at .%s, %s %s\n",
97945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            p, field->name, field->name, field->type, r + 1);
98045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    n += m-1;
98145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    r = s;
98245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    field = field->next;
98345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
98445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* complete with last initializer and '?' */
98545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                while(field) {
98645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    m = strlen(p) + 1 + strlen(field->name)*2 + 8 +
98745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        strlen(field->type) + 1 + (r ? strlen(r+1) : 1) + 2;
98845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    size += m;
98945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    line = nasm_realloc(line, size);
99045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    sprintf(line + n, "%s.%s: at .%s, %s %s\n", p, field->name,
99145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            field->name, field->type, r ? r + 1: "?");
99245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    n += m-1;
99345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    r = NULL;
99445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    field = field->next;
99545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
99645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                line = nasm_realloc(line, n + 5);
99745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                sprintf(line + n, "iend");
99845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_free(oldline);
99945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return line;
100045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
100145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
100245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
100345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
100445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    q[len2] = oldchar2;
100545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    p[len] = oldchar;
100645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
100745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return line;
100845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
100945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
101045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Token * tasm_join_tokens(Token *tline)
101145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
101245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *t, *prev, *next;
101345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (prev = NULL, t = tline; t; prev = t, t = next) {
101445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        next = t->next;
101545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (t->type == TOK_OTHER && !strcmp(t->text,"&")) {
101645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!prev)
101745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_FATAL, "no token before &");
101845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else if (!next)
101945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_FATAL, "no token after &");
102045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else if (prev->type != next->type)
102145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_FATAL, "can't handle different types of token around &");
102245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else if (!prev->text || !next->text)
102345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_FATAL, "can't handle empty token around &");
102445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else {
102545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                int lenp = strlen(prev->text);
102645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                int lenn = strlen(next->text);
102745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                prev->text = nasm_realloc(prev->text, lenp + lenn + 1);
102845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                strncpy(prev->text + lenp, next->text, lenn + 1);
102945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                (void) delete_Token(t);
103045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                prev->next = delete_Token(next);
103145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t = prev;
103245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                next = t->next;
103345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
103445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
103545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
103645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return tline;
103745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
103845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
103945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
104045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The pre-preprocessing stage... This function translates line
104145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * number indications as they emerge from GNU cpp (`# lineno "file"
104245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * flags') into NASM preprocessor line number indications (`%line
104345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * lineno file').
104445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
104545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic char *
104645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgprepreproc(char *line)
104745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
104845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int lineno;
104945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t fnlen;
105045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *fname, *oldline;
105145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *c, *d, *ret;
105245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Line *l, **lp;
105345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
105445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (line[0] == '#' && line[1] == ' ')
105545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
105645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        oldline = line;
105745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fname = oldline + 2;
105845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        lineno = atoi(fname);
105945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fname += strspn(fname, "0123456789 ");
106045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (*fname == '"')
106145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fname++;
106245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fnlen = strcspn(fname, "\"");
106345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        line = nasm_malloc(20 + fnlen);
106445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sprintf(line, "%%line %d %.*s", lineno, (int)fnlen, fname);
106545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(oldline);
106645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
106745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (tasm_compatible_mode)
106845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        line = check_tasm_directive(line);
106945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
107045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!(c = strchr(line, '\n')))
107145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return line;
107245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
107345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Turn multiline macros into several lines */
107445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *c = '\0';
107545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ret = nasm_strdup(line);
107645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
107745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lp = &istk->expansion;
107845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    do {
107945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        d = strchr(c+1, '\n');
108045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (d)
108145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *d = '\0';
108245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        l = malloc(sizeof(*l));
108345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        l -> first = tokenise(c+1);
108445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        l -> finishes = NULL;
108545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        l -> next = *lp;
108645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *lp = l;
108745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        c = d;
108845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        lp = &l -> next;
108945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } while (c);
109045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_free(line);
109145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return ret;
109245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
109345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
109445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
109545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The hash function for macro lookups. Note that due to some
109645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * macros having case-insensitive names, the hash function must be
109745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * invariant under case changes. We implement this by applying a
109845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * perfectly normal hash function to the uppercase of the string.
109945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
110045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
110145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orghash(char *s)
110245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
110345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int h = 0;
110445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int i = 0;
110545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
110645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Powers of three, mod 31.
110745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
110845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    static const int multipliers[] = {
110945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
111045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
111145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    };
111245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
111345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
111445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (*s)
111545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
111645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        h += multipliers[i] * (unsigned char) (toupper(*s));
111745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        s++;
111845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (++i >= elements(multipliers))
111945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            i = 0;
112045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
112145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    h %= NHASH;
112245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return h;
112345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
112445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
112545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
112645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Free a linked list of tokens.
112745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
112845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
112945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgfree_tlist(Token * list_)
113045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
113145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (list_)
113245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
113345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        list_ = delete_Token(list_);
113445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
113545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
113645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
113745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
113845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Free a linked list of lines.
113945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
114045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
114145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgfree_llist(Line * list_)
114245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
114345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Line *l;
114445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (list_)
114545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
114645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        l = list_;
114745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        list_ = list_->next;
114845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        free_tlist(l->first);
114945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(l);
115045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
115145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
115245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
115345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
115445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Free an MMacro
115545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
115645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
115745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgfree_mmacro(MMacro * m)
115845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
115945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_free(m->name);
116045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    free_tlist(m->dlist);
116145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_free(m->defaults);
116245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    free_llist(m->expansion);
116345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_free(m);
116445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
116545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
116645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
116745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Pop the context stack.
116845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
116945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
117045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgctx_pop(void)
117145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
117245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Context *c = cstk;
117345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    SMacro *smac, *s;
117445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
117545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    cstk = cstk->next;
117645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    smac = c->localmac;
117745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (smac)
117845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
117945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        s = smac;
118045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        smac = smac->next;
118145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(s->name);
118245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        free_tlist(s->expansion);
118345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(s);
118445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
118545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_free(c->name);
118645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_free(c);
118745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
118845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
118945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define BUF_DELTA 512
119045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
119145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Read a line from the top file in istk, handling multiple CR/LFs
119245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * at the end of the line read, and handling spurious ^Zs. Will
119345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * return lines from the standard macro set if this has not already
119445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * been done.
119545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
119645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic char *
119745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgread_line(void)
119845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
119945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *buffer, *p, *q;
120045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int bufsize, continued_count;
120145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
120245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bufsize = BUF_DELTA;
120345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    buffer = nasm_malloc(BUF_DELTA);
120445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    p = buffer;
120545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    continued_count = 0;
120645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (1)
120745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
120845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        q = fgets(p, bufsize - (int)(p - buffer), istk->fp);
120945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!q)
121045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
121145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        p += strlen(p);
121245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (p > buffer && p[-1] == '\n')
121345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
121445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org           /* Convert backslash-CRLF line continuation sequences into
121545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org              nothing at all (for DOS and Windows) */
121645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org           if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
121745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org               p -= 3;
121845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org               *p = 0;
121945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org               continued_count++;
122045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org           }
122145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org           /* Also convert backslash-LF line continuation sequences into
122245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org              nothing at all (for Unix) */
122345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org           else if (((p - 1) > buffer) && (p[-2] == '\\')) {
122445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org               p -= 2;
122545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org               *p = 0;
122645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org               continued_count++;
122745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org           }
122845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org           else {
122945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org               break;
123045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org           }
123145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
123245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (p - buffer > bufsize - 10)
123345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
123445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            long offset = (long)(p - buffer);
123545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bufsize += BUF_DELTA;
123645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            buffer = nasm_realloc(buffer, (size_t)bufsize);
123745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p = buffer + offset;        /* prevent stale-pointer problems */
123845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
123945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
124045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
124145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!q && p == buffer)
124245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
124345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(buffer);
124445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;
124545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
124645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
124745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_src_set_linnum(nasm_src_get_linnum() + istk->lineinc + (continued_count * istk->lineinc));
124845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
124945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
125045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Play safe: remove CRs as well as LFs, if any of either are
125145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * present at the end of the line.
125245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
125345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (--p >= buffer && (*p == '\n' || *p == '\r'))
125445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *p = '\0';
125545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
125645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
125745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Handle spurious ^Z, which may be inserted into source files
125845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * by some file transfer utilities.
125945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
126045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    buffer[strcspn(buffer, "\032")] = '\0';
126145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
126245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    list->line(LIST_READ, buffer);
126345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
126445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return buffer;
126545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
126645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
126745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
126845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Tokenise a line of text. This is a very simple process since we
126945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * don't need to parse the value out of e.g. numeric tokens: we
127045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * simply split one string into many.
127145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
127245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Token *
127345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtokenise(char *line)
127445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
127545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *p = line;
127645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int type;
127745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *list_ = NULL;
127845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *t, **tail = &list_;
127945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
128045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (*line)
128145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
128245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        p = line;
128345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (*p == '%')
128445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
128545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p++;
128645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if ( isdigit(*p) ||
128745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        ((*p == '-' || *p == '+') && isdigit(p[1])) ||
128845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        ((*p == '+') && (isspace(p[1]) || !p[1])))
128945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                {
129045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        do
129145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
129245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        p++;
129345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
129445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        while (isdigit(*p));
129545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        type = TOK_PREPROC_ID;
129645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
129745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if (*p == '{')
129845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
129945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        p++;
130045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        while (*p && *p != '}')
130145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
130245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        p[-1] = *p;
130345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        p++;
130445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
130545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        p[-1] = '\0';
130645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (*p)
130745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        p++;
130845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        type = TOK_PREPROC_ID;
130945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
131045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if (isidchar(*p) ||
131145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                ((*p == '!' || *p == '%' || *p == '$') &&
131245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        isidchar(p[1])))
131345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
131445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        do
131545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
131645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        p++;
131745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
131845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        while (isidchar(*p));
131945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        type = TOK_PREPROC_ID;
132045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
132145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
132245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
132345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        type = TOK_OTHER;
132445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (*p == '%')
132545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                p++;
132645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
132745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
132845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (isidstart(*p) || (*p == '$' && isidstart(p[1])))
132945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
133045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            type = TOK_ID;
133145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p++;
133245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (*p && isidchar(*p))
133345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p++;
133445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
133545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (*p == '\'' || *p == '"')
133645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
133745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
133845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * A string token.
133945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
134045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            char c = *p;
134145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p++;
134245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            type = TOK_STRING;
134345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (*p && *p != c)
134445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p++;
134545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
134645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (*p)
134745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
134845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p++;
134945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
135045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
135145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
135245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_WARNING, "unterminated string");
135345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                type = -1;
135445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
135545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
135645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (isnumstart(*p))
135745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
135845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
135945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * A number token.
136045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
136145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            type = TOK_NUMBER;
136245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p++;
136345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (*p && isnumchar(*p))
136445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p++;
136545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
136645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (isspace(*p))
136745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
136845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            type = TOK_WHITESPACE;
136945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p++;
137045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (*p && isspace(*p))
137145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p++;
137245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
137345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * Whitespace just before end-of-line is discarded by
137445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * pretending it's a comment; whitespace just before a
137545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * comment gets lumped into the comment.
137645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
137745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!*p || *p == ';')
137845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
137945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                type = TOK_COMMENT;
138045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                while (*p)
138145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    p++;
138245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
138345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
138445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (*p == ';')
138545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
138645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            type = TOK_COMMENT;
138745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (*p)
138845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p++;
138945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
139045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
139145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
139245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
139345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * Anything else is an operator of some kind. We check
139445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * for all the double-character operators (>>, <<, //,
139545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
139645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * else is a single-character operator.
139745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
139845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            type = TOK_OTHER;
139945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if ((p[0] == '>' && p[1] == '>') ||
140045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    (p[0] == '<' && p[1] == '<') ||
140145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    (p[0] == '/' && p[1] == '/') ||
140245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    (p[0] == '<' && p[1] == '=') ||
140345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    (p[0] == '>' && p[1] == '=') ||
140445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    (p[0] == '=' && p[1] == '=') ||
140545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    (p[0] == '!' && p[1] == '=') ||
140645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    (p[0] == '<' && p[1] == '>') ||
140745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    (p[0] == '&' && p[1] == '&') ||
140845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    (p[0] == '|' && p[1] == '|') ||
140945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    (p[0] == '^' && p[1] == '^'))
141045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
141145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p++;
141245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
141345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p++;
141445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
141545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
141645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Handle unterminated string */
141745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (type == -1)
141845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
141945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *tail = t = new_Token(NULL, TOK_STRING, line, (size_t)(p-line)+1);
142045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t->text[p-line] = *line;
142145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tail = &t->next;
142245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
142345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (type != TOK_COMMENT)
142445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
142545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *tail = t = new_Token(NULL, type, line, (size_t)(p - line));
142645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tail = &t->next;
142745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
142845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        line = p;
142945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
143045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return list_;
143145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
143245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
143345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
143445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * this function allocates a new managed block of memory and
143545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * returns a pointer to the block.  The managed blocks are
143645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * deleted only all at once by the delete_Blocks function.
143745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
143845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void *
143945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgnew_Block(size_t size)
144045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
144145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Blocks *b = &blocks;
144245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
144345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* first, get to the end of the linked list      */
144445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (b->next)
144545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                b = b->next;
144645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* now allocate the requested chunk */
144745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        b->chunk = nasm_malloc(size);
144845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
144945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* now allocate a new block for the next request */
145045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        b->next = nasm_malloc(sizeof(Blocks));
145145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* and initialize the contents of the new block */
145245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        b->next->next = NULL;
145345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        b->next->chunk = NULL;
145445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return b->chunk;
145545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
145645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
145745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
145845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * this function deletes all managed blocks of memory
145945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
146045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
146145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgdelete_Blocks(void)
146245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
146345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Blocks *a,*b = &blocks;
146445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
146545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*
146645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * keep in mind that the first block, pointed to by blocks
146745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * is a static and not dynamically allocated, so we don't
146845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * free it.
146945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         */
147045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (b)
147145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
147245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (b->chunk)
147345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        nasm_free(b->chunk);
147445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                a = b;
147545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                b = b->next;
147645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (a != &blocks)
147745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        nasm_free(a);
147845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
147945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
148045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
148145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
148245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *  this function creates a new Token and passes a pointer to it
148345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *  back to the caller.  It sets the type and text elements, and
148445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *  also the mac and next elements to NULL.
148545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
148645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Token *
148745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgnew_Token(Token * next, int type, const char *text, size_t txtlen)
148845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
148945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *t;
149045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int i;
149145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
149245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (freeTokens == NULL)
149345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
149445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        freeTokens = (Token *)new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
149545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
149645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            freeTokens[i].next = &freeTokens[i + 1];
149745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        freeTokens[i].next = NULL;
149845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
149945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    t = freeTokens;
150045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    freeTokens = t->next;
150145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    t->next = next;
150245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    t->mac = NULL;
150345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    t->type = type;
150445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (type == TOK_WHITESPACE || text == NULL)
150545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
150645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        t->text = NULL;
150745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
150845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
150945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
151045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (txtlen == 0)
151145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            txtlen = strlen(text);
151245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        t->text = nasm_malloc(1 + txtlen);
151345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        strncpy(t->text, text, txtlen);
151445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        t->text[txtlen] = '\0';
151545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
151645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return t;
151745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
151845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
151945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Token *
152045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgdelete_Token(Token * t)
152145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
152245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *next = t->next;
152345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_free(t->text);
152445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    t->next = freeTokens;
152545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    freeTokens = t;
152645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return next;
152745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
152845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
152945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
153045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Convert a line of tokens back into text.
153145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * If expand_locals is not zero, identifiers of the form "%$*xxx"
153245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * will be transformed into ..@ctxnum.xxx
153345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
153445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic char *
153545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgdetoken(Token * tlist, int expand_locals)
153645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
153745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *t;
153845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t len;
153945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *line, *p;
154045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
154145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    len = 0;
154245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (t = tlist; t; t = t->next)
154345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
154445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (t->type == TOK_PREPROC_ID && t->text[1] == '!')
154545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
154645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            char *p2 = getenv(t->text + 2);
154745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nasm_free(t->text);
154845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (p2)
154945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t->text = nasm_strdup(p2);
155045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
155145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t->text = NULL;
155245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
155345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Expand local macros here and not during preprocessing */
155445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (expand_locals &&
155545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t->type == TOK_PREPROC_ID && t->text &&
155645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t->text[0] == '%' && t->text[1] == '$')
155745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
155845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            Context *ctx = get_ctx(t->text, FALSE);
155945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (ctx)
156045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
156145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                char buffer[40];
156245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                char *p2, *q = t->text + 2;
156345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
156445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                q += strspn(q, "$");
156545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                sprintf(buffer, "..@%lu.", ctx->number);
156645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p2 = nasm_strcat(buffer, q);
156745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_free(t->text);
156845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t->text = p2;
156945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
157045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
157145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (t->type == TOK_WHITESPACE)
157245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
157345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            len++;
157445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
157545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (t->text)
157645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
157745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            len += strlen(t->text);
157845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
157945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
158045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    p = line = nasm_malloc(len + 1);
158145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (t = tlist; t; t = t->next)
158245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
158345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (t->type == TOK_WHITESPACE)
158445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
158545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *p = ' ';
158645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p++;
158745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *p = '\0';
158845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
158945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (t->text)
159045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
159145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            strcpy(p, t->text);
159245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p += strlen(p);
159345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
159445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
159545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *p = '\0';
159645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return line;
159745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
159845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
159945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
160045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * A scanner, suitable for use by the expression evaluator, which
160145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * operates on a line of Tokens. Expects a pointer to a pointer to
160245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * the first token in the line to be passed in as its private_data
160345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * field.
160445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
160545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
160645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgppscan(void *private_data, struct tokenval *tokval)
160745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
160845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token **tlineptr = private_data;
160945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *tline;
161045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
161145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    do
161245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
161345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tline = *tlineptr;
161445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *tlineptr = tline ? tline->next : NULL;
161545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
161645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (tline && (tline->type == TOK_WHITESPACE ||
161745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tline->type == TOK_COMMENT));
161845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
161945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!tline)
162045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return tokval->t_type = TOKEN_EOS;
162145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
162245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (tline->text[0] == '$' && !tline->text[1])
162345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return tokval->t_type = TOKEN_HERE;
162445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
162545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return tokval->t_type = TOKEN_BASE;
162645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
162745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (tline->type == TOK_ID)
162845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
162945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tokval->t_charptr = tline->text;
163045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (tline->text[0] == '$')
163145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
163245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tokval->t_charptr++;
163345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_ID;
163445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
163545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
163645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*
163745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * This is the only special case we actually need to worry
163845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * about in this restricted context.
163945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         */
164045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!nasm_stricmp(tline->text, "seg"))
164145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_SEG;
164245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
164345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return tokval->t_type = TOKEN_ID;
164445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
164545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
164645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (tline->type == TOK_NUMBER)
164745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
164845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        int rn_error;
164945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
165045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tokval->t_integer = nasm_readnum(tline->text, &rn_error);
165145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (rn_error)
165245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_ERRNUM;
165345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tokval->t_charptr = NULL;
165445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return tokval->t_type = TOKEN_NUM;
165545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
165645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
165745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (tline->type == TOK_STRING)
165845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
165945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        int rn_warn;
166045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        char q, *r;
166145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        size_t l;
166245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
166345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        r = tline->text;
166445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        q = *r++;
166545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        l = strlen(r);
166645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
166745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (l == 0 || r[l - 1] != q)
166845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_ERRNUM;
166945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tokval->t_integer = nasm_readstrnum(r, l - 1, &rn_warn);
167045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (rn_warn)
167145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error(ERR_WARNING | ERR_PASS1, "character constant too long");
167245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tokval->t_charptr = NULL;
167345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return tokval->t_type = TOKEN_NUM;
167445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
167545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
167645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (tline->type == TOK_OTHER)
167745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
167845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!strcmp(tline->text, "<<"))
167945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_SHL;
168045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!strcmp(tline->text, ">>"))
168145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_SHR;
168245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!strcmp(tline->text, "//"))
168345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_SDIV;
168445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!strcmp(tline->text, "%%"))
168545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_SMOD;
168645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!strcmp(tline->text, "=="))
168745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_EQ;
168845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!strcmp(tline->text, "<>"))
168945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_NE;
169045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!strcmp(tline->text, "!="))
169145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_NE;
169245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!strcmp(tline->text, "<="))
169345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_LE;
169445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!strcmp(tline->text, ">="))
169545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_GE;
169645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!strcmp(tline->text, "&&"))
169745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_DBL_AND;
169845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!strcmp(tline->text, "^^"))
169945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_DBL_XOR;
170045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!strcmp(tline->text, "||"))
170145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return tokval->t_type = TOKEN_DBL_OR;
170245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
170345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
170445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
170545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * We have no other options: just return the first character of
170645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * the token text.
170745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
170845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return tokval->t_type = tline->text[0];
170945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
171045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
171145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
171245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Compare a string to the name of an existing macro; this is a
171345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * simple wrapper which calls either strcmp or nasm_stricmp
171445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * depending on the value of the `casesense' parameter.
171545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
171645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
171745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgmstrcmp(char *p, char *q, int casesense)
171845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
171945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
172045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
172145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
172245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
172345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Return the Context structure associated with a %$ token. Return
172445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * NULL, having _already_ reported an error condition, if the
172545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * context stack isn't deep enough for the supplied number of $
172645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * signs.
172745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * If all_contexts == TRUE, contexts that enclose current are
172845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * also scanned for such smacro, until it is found; if not -
172945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * only the context that directly results from the number of $'s
173045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * in variable's name.
173145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
173245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Context *
173345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgget_ctx(char *name, int all_contexts)
173445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
173545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Context *ctx;
173645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    SMacro *m;
173745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t i;
173845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
173945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!name || name[0] != '%' || name[1] != '$')
174045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;
174145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
174245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!cstk)
174345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
174445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        error(ERR_NONFATAL, "`%s': context stack is empty", name);
174545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;
174645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
174745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
174845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (i = strspn(name + 2, "$"), ctx = cstk; (i > 0) && ctx; i--)
174945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
175045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ctx = ctx->next;
175145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*        i--;  Lino - 02/25/02 */
175245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
175345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!ctx)
175445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
175545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        error(ERR_NONFATAL, "`%s': context stack is only"
175645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                " %d level%s deep", name, i - 1, (i == 2 ? "" : "s"));
175745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;
175845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
175945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!all_contexts)
176045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return ctx;
176145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
176245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    do
176345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
176445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Search for this smacro in found context */
176545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        m = ctx->localmac;
176645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (m)
176745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
176845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!mstrcmp(m->name, name, m->casesense))
176945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return ctx;
177045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            m = m->next;
177145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
177245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ctx = ctx->next;
177345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
177445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (ctx);
177545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return NULL;
177645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
177745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
177845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
177945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Open an include file. This routine must always return a valid
178045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * file pointer if it returns - it's responsible for throwing an
178145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ERR_FATAL and bombing out completely if not. It should also try
178245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * the include path one by one until it finds the file or reaches
178345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * the end of the path.
178445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
178545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic FILE *
178645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orginc_fopen(char *file, char **newname)
178745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
178845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    FILE *fp;
178945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *combine = NULL, *c;
179045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *pb, *p1, *p2, *file2 = NULL;
179145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
179245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Try to expand all %ENVVAR% in filename.  Warn, and leave %string%
179345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * intact, if ENVVAR is not set in the environment.
179445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
179545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pb = file;
179645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    p1 = pb;
179745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (;;) {
179845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        char *env;
179945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (*p1 != '\0' && *p1 != '%')
180045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p1++;
180145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (*p1 == '\0')
180245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
180345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        p2 = p1+1;
180445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (*p2 != '\0' && *p2 != '%')
180545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p2++;
180645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (*p2 == '\0')
180745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
180845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* Okay, we have a %...%, with p1 pointing to the first %, and p2
180945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * pointing to the second %.
181045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         */
181145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *p2 = '\0';
181245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        env = getenv(p1+1);
181345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!env) {
181445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* warn, restore %, and continue looking */
181545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error(ERR_WARNING, "environment variable `%s' does not exist",
181645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                  p1+1);
181745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *p2 = '%';
181845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            p1 = p2+1;
181945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            continue;
182045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
182145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* need to expand */
182245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!file2) {
182345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            file2 = nasm_malloc(strlen(file)+strlen(env)+1);
182445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            file2[0] = '\0';
182545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        } else
182645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            file2 = nasm_realloc(file2, strlen(file2)+strlen(env)+1);
182745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *p1 = '\0';
182845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        strcat(file2, pb);
182945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        strcat(file2, env);
183045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        pb = p2+1;
183145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        p1 = pb;
183245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
183345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* add tail end; string is long enough that we don't need to realloc */
183445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (file2)
183545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        strcat(file2, pb);
183645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
183745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fp = yasm_fopen_include(file2 ? file2 : file, nasm_src_get_fname(), "r",
183845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            &combine);
183945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!fp && tasm_compatible_mode)
184045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
184145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        char *thefile = file2 ? file2 : file;
184245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* try a few case combinations */
184345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        do {
184445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for (c = thefile; *c; c++)
184545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *c = toupper(*c);
184645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fp = yasm_fopen_include(thefile, nasm_src_get_fname(), "r", &combine);
184745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (fp) break;
184845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *thefile = tolower(*thefile);
184945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fp = yasm_fopen_include(thefile, nasm_src_get_fname(), "r", &combine);
185045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (fp) break;
185145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for (c = thefile; *c; c++)
185245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *c = tolower(*c);
185345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fp = yasm_fopen_include(thefile, nasm_src_get_fname(), "r", &combine);
185445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (fp) break;
185545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *thefile = toupper(*thefile);
185645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fp = yasm_fopen_include(thefile, nasm_src_get_fname(), "r", &combine);
185745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (fp) break;
185845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        } while (0);
185945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
186045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!fp)
186145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        error(ERR_FATAL, "unable to open include file `%s'",
186245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org              file2 ? file2 : file);
186345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_preproc_add_dep(combine);
186445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
186545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (file2)
186645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(file2);
186745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
186845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *newname = combine;
186945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return fp;
187045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
187145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
187245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
187345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Determine if we should warn on defining a single-line macro of
187445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * name `name', with `nparam' parameters. If nparam is 0 or -1, will
187545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * return TRUE if _any_ single-line macro of that name is defined.
187645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Otherwise, will return TRUE if a single-line macro with either
187745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * `nparam' or no parameters is defined.
187845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
187945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * If a macro with precisely the right number of parameters is
188045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * defined, or nparam is -1, the address of the definition structure
188145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * will be returned in `defn'; otherwise NULL will be returned. If `defn'
188245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * is NULL, no action will be taken regarding its contents, and no
188345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * error will occur.
188445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
188545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Note that this is also called with nparam zero to resolve
188645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * `ifdef'.
188745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
188845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * If you already know which context macro belongs to, you can pass
188945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * the context pointer as first parameter; if you won't but name begins
189045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * with %$ the context will be automatically computed. If all_contexts
189145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * is true, macro will be searched in outer contexts as well.
189245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
189345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
189445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgsmacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
189545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        int nocase)
189645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
189745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    SMacro *m;
1898a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    int highest_level = -1;
189945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
190045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (ctx)
190145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        m = ctx->localmac;
190245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else if (name[0] == '%' && name[1] == '$')
190345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
190445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (cstk)
190545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ctx = get_ctx(name, FALSE);
190645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!ctx)
190745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return FALSE;       /* got to return _something_ */
190845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        m = ctx->localmac;
190945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
191045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
191145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        m = smacros[hash(name)];
191245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
191345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (m)
191445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
191545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!mstrcmp(m->name, name, m->casesense && nocase) &&
1916a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                (nparam <= 0 || m->nparam == 0 || nparam == m->nparam) && (highest_level < 0 || m->level > highest_level))
191745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
1918a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            highest_level = m->level;
191945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (defn)
192045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
192145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (nparam == m->nparam || nparam == -1)
192245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    *defn = m;
192345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
192445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    *defn = NULL;
192545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
192645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
192745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        m = m->next;
192845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
192945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
1930a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    return highest_level >= 0;
193145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
193245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
193345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
193445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Count and mark off the parameters in a multi-line macro call.
193545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * This is called both from within the multi-line macro expansion
193645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * code, and also to mark off the default parameters when provided
193745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * in a %macro definition line.
193845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
193945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
194045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgcount_mmac_params(Token * t, int *nparam, Token *** params)
194145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
194245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int paramsize, brace;
194345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
194445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *nparam = paramsize = 0;
194545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *params = NULL;
194645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (t)
194745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
194845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (*nparam+1 >= paramsize)
194945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
195045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            paramsize += PARAM_DELTA;
195145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *params = nasm_realloc(*params, sizeof(**params) * paramsize);
195245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
195345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        skip_white_(t);
195445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        brace = FALSE;
195545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (tok_is_(t, "{"))
195645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            brace = TRUE;
195745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        (*params)[(*nparam)++] = t;
195845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (tok_isnt_(t, brace ? "}" : ","))
195945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = t->next;
196045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (t)
196145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {                       /* got a comma/brace */
196245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = t->next;
196345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (brace)
196445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
196545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /*
196645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * Now we've found the closing brace, look further
196745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * for the comma.
196845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 */
196945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                skip_white_(t);
197045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tok_isnt_(t, ","))
197145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
197245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL,
197345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "braces do not enclose all of macro parameter");
197445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    while (tok_isnt_(t, ","))
197545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t = t->next;
197645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
197745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (t)
197845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    t = t->next;        /* eat the comma */
197945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
198045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
198145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
198245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
198345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
198445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
198545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Determine whether one of the various `if' conditions is true or
198645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * not.
198745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
198845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * We must free the tline we get passed.
198945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
199045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
199145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgif_condition(Token * tline, int i)
199245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
199345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int j, casesense;
199445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *t, *tt, **tptr, *origline;
199545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct tokenval tokval;
199645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_expr *evalresult;
199745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum *intn;
199845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
199945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    origline = tline;
200045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
200145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    switch (i)
200245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
200345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFCTX:
200445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFCTX:
200545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNCTX:
200645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNCTX:
200745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            j = FALSE;          /* have we matched yet? */
200845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (cstk && tline)
200945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
201045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                skip_white_(tline);
201145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!tline || tline->type != TOK_ID)
201245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
201345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL,
201445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "`%s' expects context identifiers",
201545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            directives[i]);
201645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(origline);
201745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return -1;
201845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
201945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!nasm_stricmp(tline->text, cstk->name))
202045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    j = TRUE;
202145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
202245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
202345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (i == PP_IFNCTX || i == PP_ELIFNCTX)
202445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                j = !j;
202545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
202645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return j;
202745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
202845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFDEF:
202945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFDEF:
203045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNDEF:
203145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNDEF:
203245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            j = FALSE;          /* have we matched yet? */
203345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (tline)
203445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
203545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                skip_white_(tline);
203645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!tline || (tline->type != TOK_ID &&
203745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                (tline->type != TOK_PREPROC_ID ||
203845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        tline->text[1] != '$')))
203945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
204045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL,
204145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          "`%s' expects macro identifiers",
204245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          directives[i]);
204345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(origline);
204445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return -1;
204545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
204645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (smacro_defined(NULL, tline->text, 0, NULL, 1))
204745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    j = TRUE;
204845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
204945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
205045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (i == PP_IFNDEF || i == PP_ELIFNDEF)
205145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                j = !j;
205245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
205345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return j;
205445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
205545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFIDN:
205645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFIDN:
205745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNIDN:
205845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNIDN:
205945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFIDNI:
206045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFIDNI:
206145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNIDNI:
206245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNIDNI:
206345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_smacro(tline);
206445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = tt = tline;
206545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (tok_isnt_(tt, ","))
206645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tt = tt->next;
206745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tt)
206845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
206945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
207045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "`%s' expects two comma-separated arguments",
207145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        directives[i]);
207245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(tline);
207345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return -1;
207445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
207545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tt = tt->next;
207645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||
207745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    i == PP_IFNIDN || i == PP_ELIFNIDN);
207845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            j = TRUE;           /* assume equality unless proved not */
207945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt)
208045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
208145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tt->type == TOK_OTHER && !strcmp(tt->text, ","))
208245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
208345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL, "`%s': more than one comma on line",
208445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            directives[i]);
208545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(tline);
208645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return -1;
208745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
208845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (t->type == TOK_WHITESPACE)
208945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
209045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    t = t->next;
209145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    continue;
209245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
209345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tt->type == TOK_WHITESPACE)
209445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
209545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tt = tt->next;
209645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    continue;
209745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
209845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tt->type != t->type)
209945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
210045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    j = FALSE;  /* found mismatching tokens */
210145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
210245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
210345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Unify surrounding quotes for strings */
210445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (t->type == TOK_STRING)
210545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
210645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tt->text[0] = t->text[0];
210745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tt->text[strlen(tt->text) - 1] = t->text[0];
210845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
210945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (mstrcmp(tt->text, t->text, casesense) != 0)
211045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
211145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    j = FALSE;  /* found mismatching tokens */
211245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
211345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
211445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
211545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t = t->next;
211645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tt = tt->next;
211745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
211845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
211945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                j = FALSE;      /* trailing gunk on one end or other */
212045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (i == PP_IFNIDN || i == PP_ELIFNIDN ||
212145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    i == PP_IFNIDNI || i == PP_ELIFNIDNI)
212245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                j = !j;
212345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(tline);
212445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return j;
212545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
212645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFMACRO:
212745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFMACRO:
212845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNMACRO:
212945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNMACRO:
213045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
213145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            int found = 0;
213245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            MMacro searching, *mmac;
213345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
213445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
213545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
213645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_id(tline);
213745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tok_type_(tline, TOK_ID))
213845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
213945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
214045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "`%s' expects a macro name",
214145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                      directives[i]);
214245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return -1;
214345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
214445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            searching.name = nasm_strdup(tline->text);
214545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            searching.casesense = (i == PP_MACRO);
214645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            searching.plus = FALSE;
214745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            searching.nolist = FALSE;
214845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            searching.in_progress = FALSE;
214945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            searching.rep_nest = NULL;
215045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            searching.nparam_min = 0;
215145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            searching.nparam_max = INT_MAX;
215245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_smacro(tline->next);
215345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
215445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tline)
215545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
215645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            } else if (!tok_type_(tline, TOK_NUMBER))
215745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
215845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
215945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                      "`%s' expects a parameter count or nothing",
216045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                      directives[i]);
216145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
216245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
216345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
216445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                intn = nasm_readnum(tline->text, &j);
216545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                searching.nparam_min = searching.nparam_max =
216645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_intnum_get_int(intn);
216745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_intnum_destroy(intn);
216845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (j)
216945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL,
217045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          "unable to parse parameter count `%s'",
217145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          tline->text);
217245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
217345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline && tok_is_(tline->next, "-"))
217445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
217545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next->next;
217645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tok_is_(tline, "*"))
217745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    searching.nparam_max = INT_MAX;
217845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if (!tok_type_(tline, TOK_NUMBER))
217945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL,
218045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          "`%s' expects a parameter count after `-'",
218145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          directives[i]);
218245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
218345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
218445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    intn = nasm_readnum(tline->text, &j);
218545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    searching.nparam_max = yasm_intnum_get_int(intn);
218645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_intnum_destroy(intn);
218745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (j)
218845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        error(ERR_NONFATAL,
218945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                "unable to parse parameter count `%s'",
219045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                tline->text);
219145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (searching.nparam_min > searching.nparam_max)
219245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        error(ERR_NONFATAL,
219345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                "minimum parameter count exceeds maximum");
219445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
219545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
219645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline && tok_is_(tline->next, "+"))
219745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
219845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
219945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                searching.plus = TRUE;
220045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
220145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mmac = mmacros[hash(searching.name)];
220245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (mmac)
220345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
220445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!strcmp(mmac->name, searching.name) &&
220545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        (mmac->nparam_min <= searching.nparam_max
220645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                || searching.plus)
220745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        && (searching.nparam_min <= mmac->nparam_max
220845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                || mmac->plus))
220945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
221045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    found = TRUE;
221145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
221245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
221345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mmac = mmac->next;
221445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
221545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nasm_free(searching.name);
221645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
221745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (i == PP_IFNMACRO || i == PP_ELIFNMACRO)
221845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                found = !found;
221945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return found;
222045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
222145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
222245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFID:
222345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFID:
222445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNID:
222545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNID:
222645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNUM:
222745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNUM:
222845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNNUM:
222945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNNUM:
223045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFSTR:
223145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFSTR:
223245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNSTR:
223345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNSTR:
223445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_smacro(tline);
223545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = tline;
223645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (tok_type_(t, TOK_WHITESPACE))
223745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t = t->next;
223845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            j = FALSE;          /* placate optimiser */
223945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (t)
224045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                switch (i)
224145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
224245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case PP_IFID:
224345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case PP_ELIFID:
224445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case PP_IFNID:
224545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case PP_ELIFNID:
224645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        j = (t->type == TOK_ID);
224745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
224845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case PP_IFNUM:
224945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case PP_ELIFNUM:
225045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case PP_IFNNUM:
225145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case PP_ELIFNNUM:
225245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        j = (t->type == TOK_NUMBER);
225345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
225445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case PP_IFSTR:
225545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case PP_ELIFSTR:
225645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case PP_IFNSTR:
225745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case PP_ELIFNSTR:
225845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        j = (t->type == TOK_STRING);
225945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
226045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
226145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (i == PP_IFNID || i == PP_ELIFNID ||
226245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    i == PP_IFNNUM || i == PP_ELIFNNUM ||
226345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    i == PP_IFNSTR || i == PP_ELIFNSTR)
226445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                j = !j;
226545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(tline);
226645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return j;
226745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
226845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IF:
226945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIF:
227045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = tline = expand_smacro(tline);
227145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tptr = &t;
227245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tokval.t_type = TOKEN_INVALID;
227345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            evalresult = evaluate(ppscan, tptr, &tokval, pass | CRITICAL,
227445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                  error);
227545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(tline);
227645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!evalresult)
227745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return -1;
227845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tokval.t_type)
227945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_WARNING,
228045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "trailing garbage after expression ignored");
228145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            intn = yasm_expr_get_intnum(&evalresult, 0);
228245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!intn)
228345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
228445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
228545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "non-constant value given to `%s'", directives[i]);
228645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_expr_destroy(evalresult);
228745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return -1;
228845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
228945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            j = !yasm_intnum_is_zero(intn);
229045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_expr_destroy(evalresult);
229145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return j;
229245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
229345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        default:
229445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error(ERR_FATAL,
229545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    "preprocessor directive `%s' not yet implemented",
229645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    directives[i]);
229745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
229845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return -1;          /* yeah, right */
229945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
230045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
230145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
230245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
230345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Expand macros in a string. Used in %error and %include directives.
230445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * First tokenise the string, apply "expand_smacro" and then de-tokenise back.
230545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The returned variable should ALWAYS be freed after usage.
230645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
230745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
230845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpand_macros_in_string(char **p)
230945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
231045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *line = tokenise(*p);
231145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    line = expand_smacro(line);
231245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *p = detoken(line, FALSE);
231345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
231445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
231545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/**
231645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * find and process preprocessor directive in passed line
231745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Find out if a line contains a preprocessor directive, and deal
231845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * with it if so.
231945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
232045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * If a directive _is_ found, it is the responsibility of this routine
232145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * (and not the caller) to free_tlist() the line.
232245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
232345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * @param tline a pointer to the current tokeninzed line linked list
232445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
232545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
232645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
232745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
232845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgdo_directive(Token * tline)
232945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
233045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int i, j, k, m, nparam, nolist;
233145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int offset;
233245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *p, *mname, *newname;
233345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Include *inc;
233445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Context *ctx;
233545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Cond *cond;
233645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    SMacro *smac, **smhead;
233745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    MMacro *mmac;
233845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
233945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Line *l;
234045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    struct tokenval tokval;
234145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_expr *evalresult;
234245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    MMacro *tmp_defining;       /* Used when manipulating rep_nest */
234345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum *intn;
234445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
234545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    origline = tline;
234645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
234745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    skip_white_(tline);
234845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!tok_type_(tline, TOK_PREPROC_ID) ||
234945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (tline->text[1] == '%' || tline->text[1] == '$'
235045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    || tline->text[1] == '!'))
235145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NO_DIRECTIVE_FOUND;
235245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
235345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    i = -1;
235445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    j = elements(directives);
235545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (j - i > 1)
235645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
235745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        k = (j + i) / 2;
235845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        m = nasm_stricmp(tline->text, directives[k]);
235945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (m == 0) {
236045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tasm_compatible_mode) {
236145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                i = k;
236245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                j = -2;
236345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                } else if (k != PP_ARG && k != PP_LOCAL && k != PP_STACKSIZE) {
236445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    i = k;
236545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                j = -2;
236645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
236745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
236845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
236945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (m < 0) {
237045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            j = k;
237145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
237245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
237345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            i = k;
237445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
237545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
237645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
237745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * If we're in a non-emitting branch of a condition construct,
237845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * or walking to the end of an already terminated %rep block,
237945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * we should ignore all directives except for condition
238045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * directives.
238145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
238245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (((istk->conds && !emitting(istk->conds->state)) ||
238345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         (istk->mstk && !istk->mstk->in_progress)) &&
238445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        !is_condition(i))
238545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
238645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NO_DIRECTIVE_FOUND;
238745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
238845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
238945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
239045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * If we're defining a macro or reading a %rep block, we should
239145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * ignore all directives except for %macro/%imacro (which
239245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * generate an error), %endm/%endmacro, and (only if we're in a
239345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * %rep block) %endrep. If we're in a %rep block, another %rep
239445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * causes an error, so should be let through.
239545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
239645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (defining && i != PP_MACRO && i != PP_IMACRO &&
239745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            i != PP_ENDMACRO && i != PP_ENDM &&
239845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (defining->name || (i != PP_ENDREP && i != PP_REP)))
239945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
240045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NO_DIRECTIVE_FOUND;
240145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
240245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
240345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (defining) {
240445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (i == PP_MACRO || i == PP_IMACRO) {
240545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nested_mac_count++;
240645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return NO_DIRECTIVE_FOUND;
240745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        } else if (nested_mac_count > 0) {
240845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (i == PP_ENDMACRO) {
240945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nested_mac_count--;
241045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return NO_DIRECTIVE_FOUND;
241145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
241245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
241345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!defining->name) {
241445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (i == PP_REP) {
241545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nested_rep_count++;
241645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return NO_DIRECTIVE_FOUND;
241745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            } else if (nested_rep_count > 0) {
241845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (i == PP_ENDREP) {
241945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nested_rep_count--;
242045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return NO_DIRECTIVE_FOUND;
242145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
242245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
242345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
242445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
242545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
242645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (j != -2)
242745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
242845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
242945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline->text);
243045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NO_DIRECTIVE_FOUND;              /* didn't get it */
243145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
243245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
243345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    switch (i)
243445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
243545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_STACKSIZE:
243645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Directive to tell NASM what the default stack size is. The
243745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * default is for a 16-bit stack, and this can be overriden with
243845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * %stacksize large.
243945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * the following form:
244045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             *
244145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             *      ARG arg1:WORD, arg2:DWORD, arg4:QWORD
244245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
244345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
244445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline && tline->type == TOK_WHITESPACE)
244545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
244645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tline || tline->type != TOK_ID)
244745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
244845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
244945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
245045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
245145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
245245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (nasm_stricmp(tline->text, "flat") == 0)
245345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
245445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* All subsequent ARG directives are for a 32-bit stack */
245545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                StackSize = 4;
245645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                StackPointer = "ebp";
245745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ArgOffset = 8;
245845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                LocalOffset = 4;
245945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
246045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else if (nasm_stricmp(tline->text, "large") == 0)
246145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
246245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* All subsequent ARG directives are for a 16-bit stack,
246345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * far function call.
246445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 */
246545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                StackSize = 2;
246645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                StackPointer = "bp";
246745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ArgOffset = 4;
246845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                LocalOffset = 2;
246945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
247045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else if (nasm_stricmp(tline->text, "small") == 0)
247145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
247245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* All subsequent ARG directives are for a 16-bit stack,
247345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                   * far function call. We don't support near functions.
247445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 */
247545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                StackSize = 2;
247645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                StackPointer = "bp";
247745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ArgOffset = 6;
247845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                LocalOffset = 2;
247945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
248045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
248145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
248245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "`%%stacksize' invalid size type");
248345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
248445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
248545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
248645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
248745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
248845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
248945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ARG:
249045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* TASM like ARG directive to define arguments to functions, in
249145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * the following form:
249245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             *
249345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             *      ARG arg1:WORD, arg2:DWORD, arg4:QWORD
249445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
249545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            offset = ArgOffset;
249645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            do
249745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
249845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                char *arg, directive[256];
249945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                int size = StackSize;
250045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
250145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Find the argument name */
250245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
250345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tline && tline->type == TOK_WHITESPACE)
250445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tline = tline->next;
250545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!tline || tline->type != TOK_ID)
250645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
250745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL, "`%%arg' missing argument parameter");
250845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(origline);
250945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return DIRECTIVE_FOUND;
251045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
251145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                arg = tline->text;
251245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
251345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Find the argument size type */
251445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
251545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!tline || tline->type != TOK_OTHER
251645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        || tline->text[0] != ':')
251745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
251845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL,
251945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "Syntax error processing `%%arg' directive");
252045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(origline);
252145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return DIRECTIVE_FOUND;
252245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
252345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
252445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!tline || tline->type != TOK_ID)
252545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
252645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL,
252745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "`%%arg' missing size type parameter");
252845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(origline);
252945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return DIRECTIVE_FOUND;
253045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
253145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
253245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Allow macro expansion of type parameter */
253345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tt = tokenise(tline->text);
253445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tt = expand_smacro(tt);
253545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (nasm_stricmp(tt->text, "byte") == 0)
253645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
253745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    size = MAX(StackSize, 1);
253845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
253945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if (nasm_stricmp(tt->text, "word") == 0)
254045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
254145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    size = MAX(StackSize, 2);
254245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
254345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if (nasm_stricmp(tt->text, "dword") == 0)
254445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
254545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    size = MAX(StackSize, 4);
254645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
254745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if (nasm_stricmp(tt->text, "qword") == 0)
254845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
254945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    size = MAX(StackSize, 8);
255045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
255145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if (nasm_stricmp(tt->text, "tword") == 0)
255245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
255345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    size = MAX(StackSize, 10);
255445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
255545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
255645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
255745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL,
255845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "Invalid size type for `%%arg' missing directive");
255945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(tt);
256045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(origline);
256145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return DIRECTIVE_FOUND;
256245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
256345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(tt);
256445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
256545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Now define the macro for the argument */
256645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                sprintf(directive, "%%define %s (%s+%d)", arg, StackPointer,
256745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        offset);
256845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                do_directive(tokenise(directive));
256945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                offset += size;
257045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
257145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Move to the next argument in the list */
257245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
257345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tline && tline->type == TOK_WHITESPACE)
257445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tline = tline->next;
257545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
257645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (tline && tline->type == TOK_OTHER
257745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    && tline->text[0] == ',');
257845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
257945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
258045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
258145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_LOCAL:
258245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* TASM like LOCAL directive to define local variables for a
258345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * function, in the following form:
258445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             *
258545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             *      LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
258645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             *
258745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * The '= LocalSize' at the end is ignored by NASM, but is
258845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * required by TASM to define the local parameter size (and used
258945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * by the TASM macro package).
259045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
259145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            offset = LocalOffset;
259245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            do
259345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
259445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                char *local, directive[256];
259545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                int size = StackSize;
259645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
259745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Find the argument name */
259845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
259945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tline && tline->type == TOK_WHITESPACE)
260045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tline = tline->next;
260145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!tline || tline->type != TOK_ID)
260245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
260345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL,
260445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "`%%local' missing argument parameter");
260545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(origline);
260645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return DIRECTIVE_FOUND;
260745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
260845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                local = tline->text;
260945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
261045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Find the argument size type */
261145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
261245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!tline || tline->type != TOK_OTHER
261345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        || tline->text[0] != ':')
261445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
261545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL,
261645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "Syntax error processing `%%local' directive");
261745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(origline);
261845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return DIRECTIVE_FOUND;
261945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
262045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
262145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!tline || tline->type != TOK_ID)
262245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
262345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL,
262445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "`%%local' missing size type parameter");
262545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(origline);
262645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return DIRECTIVE_FOUND;
262745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
262845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
262945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Allow macro expansion of type parameter */
263045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tt = tokenise(tline->text);
263145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tt = expand_smacro(tt);
263245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (nasm_stricmp(tt->text, "byte") == 0)
263345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
263445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    size = MAX(StackSize, 1);
263545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
263645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if (nasm_stricmp(tt->text, "word") == 0)
263745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
263845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    size = MAX(StackSize, 2);
263945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
264045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if (nasm_stricmp(tt->text, "dword") == 0)
264145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
264245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    size = MAX(StackSize, 4);
264345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
264445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if (nasm_stricmp(tt->text, "qword") == 0)
264545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
264645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    size = MAX(StackSize, 8);
264745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
264845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if (nasm_stricmp(tt->text, "tword") == 0)
264945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
265045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    size = MAX(StackSize, 10);
265145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
265245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
265345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
265445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL,
265545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "Invalid size type for `%%local' missing directive");
265645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(tt);
265745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(origline);
265845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return DIRECTIVE_FOUND;
265945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
266045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(tt);
266145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
266245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Now define the macro for the argument */
266345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                sprintf(directive, "%%define %s (%s-%d)", local, StackPointer,
266445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        offset);
266545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                do_directive(tokenise(directive));
266645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                offset += size;
266745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
266845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Now define the assign to setup the enter_c macro correctly */
266945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                sprintf(directive, "%%assign %%$localsize %%$localsize+%d",
267045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        size);
267145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                do_directive(tokenise(directive));
267245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
267345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Move to the next argument in the list */
267445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
267545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tline && tline->type == TOK_WHITESPACE)
267645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tline = tline->next;
267745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
267845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (tline && tline->type == TOK_OTHER
267945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    && tline->text[0] == ',');
268045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
268145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
268245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
268345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_CLEAR:
268445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline->next)
268545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_WARNING,
268645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "trailing garbage after `%%clear' ignored");
268745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for (j = 0; j < NHASH; j++)
268845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
268945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                while (mmacros[j])
269045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
269145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    MMacro *m2 = mmacros[j];
269245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    mmacros[j] = m2->next;
269345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_mmacro(m2);
269445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
269545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                while (smacros[j])
269645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
269745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    SMacro *s = smacros[j];
269845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    smacros[j] = smacros[j]->next;
269945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(s->name);
270045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(s->expansion);
270145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(s);
270245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
270345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
270445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
270545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
270645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
270745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_INCLUDE:
270845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
270945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
271045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tline || (tline->type != TOK_STRING &&
271145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            tline->type != TOK_INTERNAL_STRING))
271245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
271345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "`%%include' expects a file name");
271445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
271545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND; /* but we did _something_ */
271645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
271745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline->next)
271845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_WARNING,
271945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "trailing garbage after `%%include' ignored");
272045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline->type != TOK_INTERNAL_STRING)
272145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
272245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p = tline->text + 1;    /* point past the quote to the name */
272345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p[strlen(p) - 1] = '\0';        /* remove the trailing quote */
272445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
272545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
272645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p = tline->text;        /* internal_string is easier */
272745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            expand_macros_in_string(&p);
272845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            inc = nasm_malloc(sizeof(Include));
272945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            inc->next = istk;
273045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            inc->conds = NULL;
273145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            inc->fp = inc_fopen(p, &newname);
273245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            inc->fname = nasm_src_set_fname(newname);
273345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            inc->lineno = nasm_src_set_linnum(0);
273445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            inc->lineinc = 1;
273545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            inc->expansion = NULL;
273645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            inc->mstk = NULL;
273745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            istk = inc;
273845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            list->uplevel(LIST_INCLUDE);
273945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
274045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
274145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
274245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_PUSH:
274345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
274445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
274545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_id(tline);
274645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tok_type_(tline, TOK_ID))
274745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
274845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "`%%push' expects a context identifier");
274945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
275045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND; /* but we did _something_ */
275145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
275245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline->next)
275345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_WARNING, "trailing garbage after `%%push' ignored");
275445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ctx = nasm_malloc(sizeof(Context));
275545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ctx->next = cstk;
275645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ctx->localmac = NULL;
275745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ctx->name = nasm_strdup(tline->text);
275845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ctx->number = unique++;
275945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            cstk = ctx;
276045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
276145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
276245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
276345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_REPL:
276445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
276545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
276645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_id(tline);
276745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tok_type_(tline, TOK_ID))
276845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
276945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "`%%repl' expects a context identifier");
277045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
277145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND; /* but we did _something_ */
277245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
277345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline->next)
277445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
277545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!cstk)
277645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "`%%repl': context stack is empty");
277745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
277845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
277945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_free(cstk->name);
278045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                cstk->name = nasm_strdup(tline->text);
278145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
278245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
278345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
278445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
278545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_POP:
278645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline->next)
278745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
278845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!cstk)
278945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
279045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "`%%pop': context stack is already empty");
279145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
279245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ctx_pop();
279345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
279445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
279545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
2796a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        case PP_SCOPE:
2797a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            if (tline->next)
2798a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                error(ERR_WARNING, "trailing garbage after `%%scope' ignored");
2799a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            Level++;
2800a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            free_tlist(origline);
2801a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            break;
2802a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org
2803a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        case PP_ENDSCOPE:
2804a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            if (tline->next)
2805a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                error(ERR_WARNING, "trailing garbage after `%%endscope' ignored");
2806a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            if (!Level)
2807a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                error(ERR_NONFATAL,
2808a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        "`%%endscope': already popped all levels");
2809a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            else
2810a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            {
2811a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                for (k = 0; k < NHASH; k++)
2812a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                {
2813a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    SMacro **smlast = &smacros[k];
2814a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    smac = smacros[k];
2815a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    while (smac)
2816a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    {
2817a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        if (smac->level < Level)
2818a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        {
2819a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            smlast = &smac->next;
2820a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            smac = smac->next;
2821a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        }
2822a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        else
2823a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        {
2824a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            *smlast = smac->next;
2825a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            nasm_free(smac->name);
2826a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            free_tlist(smac->expansion);
2827a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            nasm_free(smac);
2828a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            smac = *smlast;
2829a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        }
2830a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    }
2831a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                }
2832a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                for (ctx = cstk; ctx; ctx = ctx->next)
2833a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                {
2834a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    SMacro **smlast = &ctx->localmac;
2835a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    smac = ctx->localmac;
2836a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    while (smac)
2837a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    {
2838a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        if (smac->level < Level)
2839a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        {
2840a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            smlast = &smac->next;
2841a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            smac = smac->next;
2842a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        }
2843a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        else
2844a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        {
2845a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            *smlast = smac->next;
2846a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            nasm_free(smac->name);
2847a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            free_tlist(smac->expansion);
2848a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            nasm_free(smac);
2849a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            smac = *smlast;
2850a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        }
2851a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    }
2852a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                }
2853a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                Level--;
2854a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            }
2855a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            free_tlist(origline);
2856a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            break;
2857a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org
285845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ERROR:
285945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline->next = expand_smacro(tline->next);
286045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
286145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
286245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tok_type_(tline, TOK_STRING))
286345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
286445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p = tline->text + 1;    /* point past the quote to the name */
286545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p[strlen(p) - 1] = '\0';        /* remove the trailing quote */
286645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                expand_macros_in_string(&p);
286745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "%s", p);
286845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_free(p);
286945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
287045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
287145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
287245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p = detoken(tline, FALSE);
287345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_WARNING, "%s", p);
287445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_free(p);
287545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
287645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
287745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
287845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
287945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IF:
288045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFCTX:
288145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFDEF:
288245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFID:
288345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFIDN:
288445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFIDNI:
288545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFMACRO:
288645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNCTX:
288745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNDEF:
288845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNID:
288945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNIDN:
289045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNIDNI:
289145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNMACRO:
289245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNNUM:
289345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNSTR:
289445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFNUM:
289545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IFSTR:
289645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (istk->conds && !emitting(istk->conds->state))
289745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                j = COND_NEVER;
289845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
289945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
290045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                j = if_condition(tline->next, i);
290145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline->next = NULL;     /* it got freed */
290245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
290345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
290445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
290545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            cond = nasm_malloc(sizeof(Cond));
290645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            cond->next = istk->conds;
290745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            cond->state = j;
290845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            istk->conds = cond;
290945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
291045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
291145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIF:
291245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFCTX:
291345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFDEF:
291445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFID:
291545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFIDN:
291645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFIDNI:
291745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFMACRO:
291845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNCTX:
291945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNDEF:
292045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNID:
292145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNIDN:
292245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNIDNI:
292345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNMACRO:
292445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNNUM:
292545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNSTR:
292645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFNUM:
292745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELIFSTR:
292845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!istk->conds)
292945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_FATAL, "`%s': no matching `%%if'", directives[i]);
293045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (emitting(istk->conds->state)
293145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    || istk->conds->state == COND_NEVER)
293245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                istk->conds->state = COND_NEVER;
293345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
293445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
293545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /*
293645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * IMPORTANT: In the case of %if, we will already have
293745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * called expand_mmac_params(); however, if we're
293845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * processing an %elif we must have been in a
293945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * non-emitting mode, which would have inhibited
294045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * the normal invocation of expand_mmac_params().  Therefore,
294145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * we have to do it explicitly here.
294245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 */
294345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                j = if_condition(expand_mmac_params(tline->next), i);
294445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline->next = NULL; /* it got freed */
294545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                istk->conds->state =
294645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
294745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
294845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
294945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
295045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
295145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ELSE:
295245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline->next)
295345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_WARNING, "trailing garbage after `%%else' ignored");
295445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!istk->conds)
295545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_FATAL, "`%%else': no matching `%%if'");
295645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (emitting(istk->conds->state)
295745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    || istk->conds->state == COND_NEVER)
295845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                istk->conds->state = COND_ELSE_FALSE;
295945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
296045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                istk->conds->state = COND_ELSE_TRUE;
296145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
296245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
296345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
296445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ENDIF:
296545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline->next)
296645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_WARNING,
296745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "trailing garbage after `%%endif' ignored");
296845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!istk->conds)
296945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_FATAL, "`%%endif': no matching `%%if'");
297045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            cond = istk->conds;
297145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            istk->conds = cond->next;
297245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nasm_free(cond);
297345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
297445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
297545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
297645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_MACRO:
297745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IMACRO:
297845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (defining)
297945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_FATAL,
298045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "`%%%smacro': already defining a macro",
298145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        (i == PP_IMACRO ? "i" : ""));
298245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
298345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
298445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_id(tline);
298545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tok_type_(tline, TOK_ID))
298645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
298745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
298845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "`%%%smacro' expects a macro name",
298945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        (i == PP_IMACRO ? "i" : ""));
299045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
299145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
299245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining = nasm_malloc(sizeof(MMacro));
299345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->name = nasm_strdup(tline->text);
299445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->casesense = (i == PP_MACRO);
299545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->plus = FALSE;
299645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->nolist = FALSE;
299745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->in_progress = FALSE;
299845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->rep_nest = NULL;
299945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_smacro(tline->next);
300045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
300145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tok_type_(tline, TOK_NUMBER))
300245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
300345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
300445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "`%%%smacro' expects a parameter count",
300545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        (i == PP_IMACRO ? "i" : ""));
300645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                defining->nparam_min = defining->nparam_max = 0;
300745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
300845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
300945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
301045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                intn = nasm_readnum(tline->text, &j);
301145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                defining->nparam_min = defining->nparam_max =
301245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_intnum_get_int(intn);
301345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_intnum_destroy(intn);
301445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (j)
301545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL,
301645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "unable to parse parameter count `%s'",
301745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            tline->text);
301845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
301945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline && tok_is_(tline->next, "-"))
302045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
302145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next->next;
302245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tok_is_(tline, "*"))
302345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    defining->nparam_max = INT_MAX;
302445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if (!tok_type_(tline, TOK_NUMBER))
302545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL,
302645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "`%%%smacro' expects a parameter count after `-'",
302745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            (i == PP_IMACRO ? "i" : ""));
302845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
302945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
303045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    intn = nasm_readnum(tline->text, &j);
303145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    defining->nparam_max = yasm_intnum_get_int(intn);
303245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_intnum_destroy(intn);
303345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (j)
303445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        error(ERR_NONFATAL,
303545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                "unable to parse parameter count `%s'",
303645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                tline->text);
303745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (defining->nparam_min > defining->nparam_max)
303845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        error(ERR_NONFATAL,
303945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                "minimum parameter count exceeds maximum");
304045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
304145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
304245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline && tok_is_(tline->next, "+"))
304345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
304445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
304545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                defining->plus = TRUE;
304645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
304745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline && tok_type_(tline->next, TOK_ID) &&
304845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    !nasm_stricmp(tline->next->text, ".nolist"))
304945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
305045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
305145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                defining->nolist = TRUE;
305245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
305345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mmac = mmacros[hash(defining->name)];
305445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (mmac)
305545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
305645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!strcmp(mmac->name, defining->name) &&
305745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        (mmac->nparam_min <= defining->nparam_max
305845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                || defining->plus)
305945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        && (defining->nparam_min <= mmac->nparam_max
306045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                || mmac->plus))
306145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
306245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_WARNING,
306345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "redefining multi-line macro `%s'",
306445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            defining->name);
306545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
306645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
306745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mmac = mmac->next;
306845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
306945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
307045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * Handle default parameters.
307145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
307245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline && tline->next)
307345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
307445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                defining->dlist = tline->next;
307545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline->next = NULL;
307645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                count_mmac_params(defining->dlist, &defining->ndefs,
307745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        &defining->defaults);
307845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
307945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
308045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
308145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                defining->dlist = NULL;
308245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                defining->defaults = NULL;
308345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
308445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->expansion = NULL;
308545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
308645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
308745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
308845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ENDM:
308945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ENDMACRO:
309045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!defining)
309145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
309245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "`%s': not defining a macro",
309345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        tline->text);
309445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
309545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
309645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            k = hash(defining->name);
309745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->next = mmacros[k];
309845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mmacros[k] = defining;
309945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining = NULL;
310045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
310145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
310245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
310345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ROTATE:
310445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline->next && tline->next->type == TOK_WHITESPACE)
310545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
310645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline->next == NULL)
310745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
310845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
310945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "`%%rotate' missing rotate count");
311045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
311145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
311245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = expand_smacro(tline->next);
311345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline->next = NULL;
311445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
311545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = t;
311645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tptr = &t;
311745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tokval.t_type = TOKEN_INVALID;
311845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
311945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(tline);
312045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!evalresult)
312145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
312245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tokval.t_type)
312345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_WARNING,
312445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "trailing garbage after expression ignored");
312545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            intn = yasm_expr_get_intnum(&evalresult, 0);
312645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!intn)
312745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
312845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
312945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_expr_destroy(evalresult);
313045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
313145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
313245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mmac = istk->mstk;
313345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
313445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mmac = mmac->next_active;
313545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!mmac)
313645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
313745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
313845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "`%%rotate' invoked outside a macro call");
313945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
314045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else if (mmac->nparam == 0)
314145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
314245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
314345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "`%%rotate' invoked within macro without parameters");
314445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
314545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
314645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
314745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mmac->rotate = mmac->rotate + yasm_intnum_get_int(intn);
314845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
314945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (mmac->rotate < 0)
315045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    mmac->rotate =
315145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        mmac->nparam - (-mmac->rotate) % mmac->nparam;
315245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mmac->rotate %= mmac->nparam;
315345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
315445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_expr_destroy(evalresult);
315545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
315645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
315745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_REP:
315845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nolist = FALSE;
315945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            do {
316045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
316145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            } while (tok_type_(tline, TOK_WHITESPACE));
316245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
316345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tok_type_(tline, TOK_ID) &&
316445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_stricmp(tline->text, ".nolist") == 0)
316545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
316645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nolist = TRUE;
316745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                do {
316845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tline = tline->next;
316945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                } while (tok_type_(tline, TOK_WHITESPACE));
317045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
317145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
317245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline)
317345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
317445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t = expand_smacro(tline);
317545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tptr = &t;
317645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tokval.t_type = TOKEN_INVALID;
317745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
317845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!evalresult)
317945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
318045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(origline);
318145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return DIRECTIVE_FOUND;
318245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
318345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tokval.t_type)
318445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_WARNING,
318545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          "trailing garbage after expression ignored");
318645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                intn = yasm_expr_get_intnum(&evalresult, 0);
318745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!intn)
318845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
318945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL, "non-constant value given to `%%rep'");
319045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_expr_destroy(evalresult);
319145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return DIRECTIVE_FOUND;
319245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
319345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                i = (int)yasm_intnum_get_int(intn) + 1;
319445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_expr_destroy(evalresult);
319545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
319645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
319745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
319845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "`%%rep' expects a repeat count");
319945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                i = 0;
320045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
320145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
320245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
320345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tmp_defining = defining;
320445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining = nasm_malloc(sizeof(MMacro));
320545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->name = NULL;      /* flags this macro as a %rep block */
320645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->casesense = 0;
320745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->plus = FALSE;
320845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->nolist = nolist;
320945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->in_progress = i;
321045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->nparam_min = defining->nparam_max = 0;
321145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->defaults = NULL;
321245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->dlist = NULL;
321345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->expansion = NULL;
321445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->next_active = istk->mstk;
321545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->rep_nest = tmp_defining;
321645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
321745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
321845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ENDREP:
321945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!defining || defining->name)
322045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
322145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
322245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
322345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
322445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
322545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
322645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * Now we have a "macro" defined - although it has no name
322745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * and we won't be entering it in the hash tables - we must
322845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * push a macro-end marker for it on to istk->expansion.
322945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * After that, it will take care of propagating itself (a
323045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * macro-end marker line for a macro which is really a %rep
323145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * block will cause the macro to be re-expanded, complete
323245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * with another macro-end marker to ensure the process
323345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * continues) until the whole expansion is forcibly removed
323445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * from istk->expansion by a %exitrep.
323545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
323645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            l = nasm_malloc(sizeof(Line));
323745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            l->next = istk->expansion;
323845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            l->finishes = defining;
323945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            l->first = NULL;
324045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            istk->expansion = l;
324145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
324245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            istk->mstk = defining;
324345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
324445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
324545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tmp_defining = defining;
324645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining = defining->rep_nest;
324745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
324845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
324945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
325045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_EXITREP:
325145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
325245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * We must search along istk->expansion until we hit a
325345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * macro-end marker for a macro with no name. Then we set
325445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * its `in_progress' flag to 0.
325545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
325645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for (l = istk->expansion; l; l = l->next)
325745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (l->finishes && !l->finishes->name)
325845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
325945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
326045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (l)
326145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                l->finishes->in_progress = 0;
326245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
326345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
326445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
326545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
326645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
326745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_XDEFINE:
326845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IXDEFINE:
326945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_DEFINE:
327045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IDEFINE:
327145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
327245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
327345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_id(tline);
327445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tline || (tline->type != TOK_ID &&
327545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            (tline->type != TOK_PREPROC_ID ||
327645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    tline->text[1] != '$')))
327745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
327845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
327945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "`%%%s%sdefine' expects a macro identifier",
328045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        ((i == PP_IDEFINE || i == PP_IXDEFINE) ? "i" : ""),
328145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        ((i == PP_XDEFINE || i == PP_IXDEFINE) ? "x" : ""));
328245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
328345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
328445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
328545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
328645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ctx = get_ctx(tline->text, FALSE);
328745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!ctx)
328845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smhead = &smacros[hash(tline->text)];
328945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
329045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smhead = &ctx->localmac;
329145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mname = tline->text;
329245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            last = tline;
329345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            param_start = tline = tline->next;
329445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nparam = 0;
329545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
329645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Expand the macro definition now for %xdefine and %ixdefine */
329745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
329845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = expand_smacro(tline);
329945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
330045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tok_is_(tline, "("))
330145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
330245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /*
330345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * This macro has parameters.
330445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 */
330545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
330645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
330745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                while (1)
330845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
330945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    skip_white_(tline);
331045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (!tline)
331145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
331245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        error(ERR_NONFATAL, "parameter identifier expected");
331345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        free_tlist(origline);
331445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        return DIRECTIVE_FOUND;
331545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
331645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (tline->type != TOK_ID)
331745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
331845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        error(ERR_NONFATAL,
331945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                "`%s': parameter identifier expected",
332045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                tline->text);
332145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        free_tlist(origline);
332245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        return DIRECTIVE_FOUND;
332345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
332445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tline->type = TOK_SMAC_PARAM + nparam++;
332545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tline = tline->next;
332645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    skip_white_(tline);
332745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (tok_is_(tline, ","))
332845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
332945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        tline = tline->next;
333045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        continue;
333145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
333245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (!tok_is_(tline, ")"))
333345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
333445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        error(ERR_NONFATAL,
333545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                "`)' expected to terminate macro template");
333645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        free_tlist(origline);
333745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        return DIRECTIVE_FOUND;
333845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
333945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
334045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
334145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                last = tline;
334245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
334345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
334445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tok_type_(tline, TOK_WHITESPACE))
334545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                last = tline, tline = tline->next;
334645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            macro_start = NULL;
334745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            last->next = NULL;
334845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = tline;
334945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (t)
335045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
335145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (t->type == TOK_ID)
335245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
335345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    for (tt = param_start; tt; tt = tt->next)
335445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (tt->type >= TOK_SMAC_PARAM &&
335545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                !strcmp(tt->text, t->text))
335645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            t->type = tt->type;
335745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
335845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tt = t->next;
335945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t->next = macro_start;
336045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                macro_start = t;
336145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t = tt;
336245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
336345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
336445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * Good. We now have a macro name, a parameter count, and a
336545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * token list (in reverse order) for an expansion. We ought
336645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * to be OK just to create an SMacro, store it, and let
336745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * free_tlist have the rest of the line (which we have
336845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * carefully re-terminated after chopping off the expansion
336945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * from the end).
337045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
337145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (smacro_defined(ctx, mname, nparam, &smac, i == PP_DEFINE))
337245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
337345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!smac)
337445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
337545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_WARNING,
337645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "single-line macro `%s' defined both with and"
337745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            " without parameters", mname);
337845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(origline);
337945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(macro_start);
338045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return DIRECTIVE_FOUND;
338145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
3382a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                else if (smac->level == Level)
338345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
338445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /*
3385a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                     * We're redefining in the same level, so we have to
3386a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                     * take over an existing SMacro structure. This means
3387a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                     * freeing what was already in it.
338845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     */
338945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(smac->name);
339045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(smac->expansion);
339145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
3392a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                else
3393a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                {
3394a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    smac = nasm_malloc(sizeof(SMacro));
3395a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    smac->next = *smhead;
3396a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    *smhead = smac;
3397a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                }
339845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
339945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
340045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
340145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smac = nasm_malloc(sizeof(SMacro));
340245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smac->next = *smhead;
340345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *smhead = smac;
340445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
340545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->name = nasm_strdup(mname);
340645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE));
340745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->nparam = nparam;
3408a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            smac->level = Level;
340945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->expansion = macro_start;
341045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->in_progress = FALSE;
341145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
341245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
341345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
341445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_UNDEF:
341545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
341645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
341745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_id(tline);
341845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tline || (tline->type != TOK_ID &&
341945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            (tline->type != TOK_PREPROC_ID ||
342045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    tline->text[1] != '$')))
342145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
342245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
342345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
342445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
342545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
342645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline->next)
342745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
342845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_WARNING,
342945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "trailing garbage after macro name ignored");
343045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
343145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
343245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Find the context that symbol belongs to */
343345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ctx = get_ctx(tline->text, FALSE);
343445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!ctx)
343545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smhead = &smacros[hash(tline->text)];
343645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
343745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smhead = &ctx->localmac;
343845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
343945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mname = tline->text;
344045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
344145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
344245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * We now have a macro name... go hunt for it.
344345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
344445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (smacro_defined(ctx, mname, -1, &smac, 1))
344545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
344645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Defined, so we need to find its predecessor and nuke it */
344745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                SMacro **s;
344845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                for (s = smhead; *s && *s != smac; s = &(*s)->next);
344945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (*s)
345045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
345145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    *s = smac->next;
345245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(smac->name);
345345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(smac->expansion);
345445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(smac);
345545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
345645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
345745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
345845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
345945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
346045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_STRLEN:
346145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
346245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
346345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_id(tline);
346445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tline || (tline->type != TOK_ID &&
346545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            (tline->type != TOK_PREPROC_ID ||
346645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    tline->text[1] != '$')))
346745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
346845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
346945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "`%%strlen' expects a macro identifier as first parameter");
347045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
347145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
347245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
347345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ctx = get_ctx(tline->text, FALSE);
347445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!ctx)
347545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smhead = &smacros[hash(tline->text)];
347645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
347745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smhead = &ctx->localmac;
347845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mname = tline->text;
347945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            last = tline;
348045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_smacro(tline->next);
348145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            last->next = NULL;
348245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
348345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = tline;
348445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (tok_type_(t, TOK_WHITESPACE))
348545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t = t->next;
348645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* t should now point to the string */
348745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (t->type != TOK_STRING)
348845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
348945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
349045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "`%%strlen` requires string as second parameter");
349145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(tline);
349245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
349345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
349445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
349545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
349645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            macro_start = nasm_malloc(sizeof(*macro_start));
349745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            macro_start->next = NULL;
349845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            make_tok_num(macro_start,
349945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_intnum_create_uint((unsigned long)(strlen(t->text) - 2)));
350045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            macro_start->mac = NULL;
350145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
350245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
350345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * We now have a macro name, an implicit parameter count of
350445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * zero, and a numeric token to use as an expansion. Create
350545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * and store an SMacro.
350645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
350745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (smacro_defined(ctx, mname, 0, &smac, i == PP_STRLEN))
350845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
350945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!smac)
351045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_WARNING,
351145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "single-line macro `%s' defined both with and"
351245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            " without parameters", mname);
351345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
351445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
351545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /*
351645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * We're redefining, so we have to take over an
351745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * existing SMacro structure. This means freeing
351845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * what was already in it.
351945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     */
352045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(smac->name);
352145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(smac->expansion);
352245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
352345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
352445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
352545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
352645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smac = nasm_malloc(sizeof(SMacro));
352745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smac->next = *smhead;
352845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *smhead = smac;
352945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
353045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->name = nasm_strdup(mname);
353145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->casesense = (i == PP_STRLEN);
353245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->nparam = 0;
3533a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            smac->level = 0;
353445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->expansion = macro_start;
353545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->in_progress = FALSE;
353645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(tline);
353745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
353845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
353945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
354045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_SUBSTR:
354145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
354245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
354345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_id(tline);
354445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tline || (tline->type != TOK_ID &&
354545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            (tline->type != TOK_PREPROC_ID ||
354645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    tline->text[1] != '$')))
354745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
354845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
354945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "`%%substr' expects a macro identifier as first parameter");
355045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
355145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
355245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
355345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ctx = get_ctx(tline->text, FALSE);
355445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!ctx)
355545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smhead = &smacros[hash(tline->text)];
355645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
355745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smhead = &ctx->localmac;
355845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mname = tline->text;
355945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            last = tline;
356045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_smacro(tline->next);
356145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            last->next = NULL;
356245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
356345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = tline->next;
356445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (tok_type_(t, TOK_WHITESPACE))
356545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t = t->next;
356645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
356745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* t should now point to the string */
356845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (t->type != TOK_STRING)
356945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
357045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
357145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "`%%substr` requires string as second parameter");
357245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(tline);
357345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
357445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
357545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
357645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
357745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tt = t->next;
357845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tptr = &tt;
357945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tokval.t_type = TOKEN_INVALID;
358045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
358145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!evalresult)
358245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
358345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(tline);
358445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
358545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
358645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
358745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            intn = yasm_expr_get_intnum(&evalresult, 0);
358845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!intn)
358945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
359045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "non-constant value given to `%%substr`");
359145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(tline);
359245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
359345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_expr_destroy(evalresult);
359445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
359545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
359645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
359745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            macro_start = nasm_malloc(sizeof(*macro_start));
359845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            macro_start->next = NULL;
359945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            macro_start->text = nasm_strdup("'''");
360045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (yasm_intnum_sign(intn) == 1
360145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    && yasm_intnum_get_uint(intn) < strlen(t->text) - 1)
360245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
360345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                macro_start->text[1] = t->text[yasm_intnum_get_uint(intn)];
360445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
360545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
360645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
360745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                macro_start->text[2] = '\0';
360845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
360945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_expr_destroy(evalresult);
361045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            macro_start->type = TOK_STRING;
361145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            macro_start->mac = NULL;
361245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
361345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
361445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * We now have a macro name, an implicit parameter count of
361545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * zero, and a numeric token to use as an expansion. Create
361645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * and store an SMacro.
361745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
361845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (smacro_defined(ctx, mname, 0, &smac, i == PP_SUBSTR))
361945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
362045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!smac)
362145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_WARNING,
362245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "single-line macro `%s' defined both with and"
362345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            " without parameters", mname);
362445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
362545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
362645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /*
362745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * We're redefining, so we have to take over an
362845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * existing SMacro structure. This means freeing
362945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * what was already in it.
363045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     */
363145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(smac->name);
363245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(smac->expansion);
363345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
363445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
363545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
363645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
363745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smac = nasm_malloc(sizeof(SMacro));
363845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smac->next = *smhead;
363945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *smhead = smac;
364045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
364145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->name = nasm_strdup(mname);
364245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->casesense = (i == PP_SUBSTR);
364345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->nparam = 0;
3644a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            smac->level = 0;
364545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->expansion = macro_start;
364645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->in_progress = FALSE;
364745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(tline);
364845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
364945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
365045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
365145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
365245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_ASSIGN:
365345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_IASSIGN:
365445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
365545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
365645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_id(tline);
365745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tline || (tline->type != TOK_ID &&
365845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            (tline->type != TOK_PREPROC_ID ||
365945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    tline->text[1] != '$')))
366045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
366145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
366245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "`%%%sassign' expects a macro identifier",
366345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        (i == PP_IASSIGN ? "i" : ""));
366445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
366545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
366645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
366745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ctx = get_ctx(tline->text, FALSE);
366845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!ctx)
366945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smhead = &smacros[hash(tline->text)];
367045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
367145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smhead = &ctx->localmac;
367245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mname = tline->text;
367345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            last = tline;
367445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_smacro(tline->next);
367545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            last->next = NULL;
367645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
367745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = tline;
367845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tptr = &t;
367945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tokval.t_type = TOKEN_INVALID;
368045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
368145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(tline);
368245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!evalresult)
368345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
368445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
368545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
368645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
368745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
368845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tokval.t_type)
368945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_WARNING,
369045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "trailing garbage after expression ignored");
369145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
369245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            intn = yasm_expr_get_intnum(&evalresult, 0);
369345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!intn)
369445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
369545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
369645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "non-constant value given to `%%%sassign'",
369745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        (i == PP_IASSIGN ? "i" : ""));
369845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
369945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_expr_destroy(evalresult);
370045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
370145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
370245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
370345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            macro_start = nasm_malloc(sizeof(*macro_start));
370445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            macro_start->next = NULL;
370545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            make_tok_num(macro_start, yasm_intnum_copy(intn));
370645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_expr_destroy(evalresult);
370745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            macro_start->mac = NULL;
370845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
370945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
371045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * We now have a macro name, an implicit parameter count of
371145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * zero, and a numeric token to use as an expansion. Create
371245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * and store an SMacro.
371345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
371445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (smacro_defined(ctx, mname, 0, &smac, i == PP_ASSIGN))
371545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
371645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!smac)
371745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_WARNING,
371845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            "single-line macro `%s' defined both with and"
371945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            " without parameters", mname);
372045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
372145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
372245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /*
372345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * We're redefining, so we have to take over an
372445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * existing SMacro structure. This means freeing
372545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * what was already in it.
372645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     */
372745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(smac->name);
372845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(smac->expansion);
372945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
373045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
373145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
373245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
373345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smac = nasm_malloc(sizeof(SMacro));
373445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                smac->next = *smhead;
373545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *smhead = smac;
373645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
373745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->name = nasm_strdup(mname);
373845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->casesense = (i == PP_ASSIGN);
373945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->nparam = 0;
3740a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            smac->level = 0;
374145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->expansion = macro_start;
374245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smac->in_progress = FALSE;
374345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
374445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
374545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
374645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case PP_LINE:
374745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
374845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * Syntax is `%line nnn[+mmm] [filename]'
374945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
375045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
375145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
375245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!tok_type_(tline, TOK_NUMBER))
375345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
375445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "`%%line' expects line number");
375545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(origline);
375645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return DIRECTIVE_FOUND;
375745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
375845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            intn = nasm_readnum(tline->text, &j);
375945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            k = yasm_intnum_get_int(intn);
376045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum_destroy(intn);
376145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            m = 1;
376245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
376345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tok_is_(tline, "+"))
376445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
376545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
376645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!tok_type_(tline, TOK_NUMBER))
376745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
376845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_NONFATAL, "`%%line' expects line increment");
376945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(origline);
377045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return DIRECTIVE_FOUND;
377145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
377245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                intn = nasm_readnum(tline->text, &j);
377345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                m = yasm_intnum_get_int(intn);
377445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_intnum_destroy(intn);
377545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tline->next;
377645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
377745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            skip_white_(tline);
377845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nasm_src_set_linnum(k);
377945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            istk->lineinc = m;
378045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline)
378145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
378245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_free(nasm_src_set_fname(detoken(tline, FALSE)));
378345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
378445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(origline);
378545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return DIRECTIVE_FOUND;
378645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
378745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        default:
378845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error(ERR_FATAL,
378945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    "preprocessor directive `%s' not yet implemented",
379045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    directives[i]);
379145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
379245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
379345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return DIRECTIVE_FOUND;
379445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
379545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
379645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
379745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Ensure that a macro parameter contains a condition code and
379845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * nothing else. Return the condition code index if so, or -1
379945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * otherwise.
380045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
380145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
380245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgfind_cc(Token * t)
380345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
380445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *tt;
380545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int i, j, k, m;
380645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
380745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    skip_white_(t);
380845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (t->type != TOK_ID)
380945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return -1;
381045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    tt = t->next;
381145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    skip_white_(tt);
381245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
381345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return -1;
381445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
381545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    i = -1;
381645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    j = elements(conditions);
381745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (j - i > 1)
381845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
381945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        k = (j + i) / 2;
382045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        m = nasm_stricmp(t->text, conditions[k]);
382145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (m == 0)
382245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
382345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            i = k;
382445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            j = -2;
382545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
382645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
382745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (m < 0)
382845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
382945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            j = k;
383045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
383145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
383245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            i = k;
383345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
383445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (j != -2)
383545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return -1;
383645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return i;
383745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
383845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
383945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
384045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Expand MMacro-local things: parameter references (%0, %n, %+n,
384145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * %-n) and MMacro-local identifiers (%%foo).
384245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
384345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Token *
384445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpand_mmac_params(Token * tline)
384545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
384645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *t, *tt, **tail, *thead;
384745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
384845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    tail = &thead;
384945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    thead = NULL;
385045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
385145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (tline)
385245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
385345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (tline->type == TOK_PREPROC_ID &&
385445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                (((tline->text[1] == '+' || tline->text[1] == '-')
385545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                && tline->text[2]) || tline->text[1] == '%'
385645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        || (tline->text[1] >= '0' && tline->text[1] <= '9')))
385745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
385845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            char *text = NULL;
385945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            int type = 0, cc;   /* type = 0 to placate optimisers */
386045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            char tmpbuf[30];
3861a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            char *second_text = NULL;
386245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            int n, i;
386345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            MMacro *mac;
386445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
386545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = tline;
386645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
386745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3868a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            second_text = strchr(t->text, ':');
3869a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org
387045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mac = istk->mstk;
387145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (mac && !mac->name)   /* avoid mistaking %reps for macros */
387245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mac = mac->next_active;
387345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!mac)
387445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
387545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
3876a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            {
3877a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                if (second_text)
387845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
3879a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    int end = atoi(second_text+1)-1;
3880a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    int is_fst = 1;
3881a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    int k;
3882a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    n = atoi(t->text + 1)-1;
3883a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    if (end < 0)
3884a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        end += mac->nparam;
3885a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org
3886a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    for (k = n; k <= end; k++)
3887a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    {
3888a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        if (k >= mac->nparam)
388945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            tt = NULL;
389045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        else
389145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
389245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            if (mac->nparam > 1)
3893a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                k = (k + mac->rotate) % mac->nparam;
3894a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            tt = mac->params[k];
389545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
3896a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        if (tt)
389745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
3898a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            if (!is_fst && mac->paramlen[k])
389945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            {
3900a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                *tail = new_Token(NULL, TOK_OTHER, ",", 0);
3901a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                tail = &(*tail)->next;
390245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            }
3903a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            if (mac->paramlen[k])
3904a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                is_fst = 0;
3905a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            for (i = 0; i < mac->paramlen[k]; i++)
390645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            {
390745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                *tail =
390845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        new_Token(NULL, tt->type, tt->text,
390945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        0);
391045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                tail = &(*tail)->next;
391145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                tt = tt->next;
391245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            }
391345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
391445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        text = NULL;    /* we've done it here */
3915a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    }
391645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
3917a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                else
3918a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                {
3919a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    switch (t->text[1])
3920a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    {
3921a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            /*
3922a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                             * We have to make a substitution of one of the
3923a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                             * forms %1, %-1, %+1, %%foo, %0.
3924a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                             */
3925a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        case '0':
3926a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            type = TOK_NUMBER;
3927a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            sprintf(tmpbuf, "%ld", mac->nparam);
3928a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            text = nasm_strdup(tmpbuf);
3929a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            break;
3930a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        case '%':
3931a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            type = TOK_ID;
3932a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            sprintf(tmpbuf, "..@%lu.", mac->unique);
3933a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            text = nasm_strcat(tmpbuf, t->text + 2);
3934a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            break;
3935a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        case '-':
3936a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            n = atoi(t->text + 2) - 1;
3937a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            if (n >= mac->nparam)
3938a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                tt = NULL;
3939a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            else
3940a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            {
3941a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                if (mac->nparam > 1)
3942a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                    n = (n + mac->rotate) % mac->nparam;
3943a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                tt = mac->params[n];
3944a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            }
3945a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            cc = find_cc(tt);
3946a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            if (cc == -1)
3947a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            {
3948a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                error(ERR_NONFATAL,
3949a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                        "macro parameter %d is not a condition code",
3950a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                        n + 1);
3951a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                text = NULL;
3952a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            }
3953a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            else
3954a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            {
3955a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                type = TOK_ID;
3956a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                if (inverse_ccs[cc] == -1)
3957a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                {
3958a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                    error(ERR_NONFATAL,
3959a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                            "condition code `%s' is not invertible",
3960a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                            conditions[cc]);
3961a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                    text = NULL;
3962a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                }
3963a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                else
3964a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                    text =
3965a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                            nasm_strdup(conditions[inverse_ccs
3966a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                                     [cc]]);
3967a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            }
3968a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            break;
3969a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        case '+':
3970a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            n = atoi(t->text + 2) - 1;
3971a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            if (n >= mac->nparam)
3972a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                tt = NULL;
3973a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            else
3974a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            {
3975a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                if (mac->nparam > 1)
3976a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                    n = (n + mac->rotate) % mac->nparam;
3977a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                tt = mac->params[n];
3978a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            }
3979a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            cc = find_cc(tt);
3980a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            if (cc == -1)
3981a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            {
3982a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                error(ERR_NONFATAL,
3983a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                        "macro parameter %d is not a condition code",
3984a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                        n + 1);
3985a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                text = NULL;
3986a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            }
3987a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            else
3988a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            {
3989a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                type = TOK_ID;
3990a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                text = nasm_strdup(conditions[cc]);
3991a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            }
3992a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            break;
3993a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                        default:
3994a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            n = atoi(t->text + 1) - 1;
3995a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            if (n >= mac->nparam)
3996a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                tt = NULL;
3997a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            else
3998a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            {
3999a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                if (mac->nparam > 1)
4000a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                    n = (n + mac->rotate) % mac->nparam;
4001a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                tt = mac->params[n];
4002a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            }
4003a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            if (tt)
4004a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            {
4005a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                for (i = 0; i < mac->paramlen[n]; i++)
4006a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                {
4007a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                    *tail =
4008a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                            new_Token(NULL, tt->type, tt->text,
4009a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                            0);
4010a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                    tail = &(*tail)->next;
4011a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                    tt = tt->next;
4012a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                                }
4013a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            }
4014a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            text = NULL;    /* we've done it here */
4015a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                            break;
4016a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                    }
4017a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                }
4018a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org            }
4019a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org
402045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!text)
402145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
402245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                delete_Token(t);
402345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
402445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
402545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
402645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *tail = t;
402745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tail = &t->next;
402845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t->type = type;
402945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_free(t->text);
403045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t->text = text;
403145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t->mac = NULL;
403245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
403345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            continue;
403445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
403545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
403645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
403745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = *tail = tline;
403845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
403945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t->mac = NULL;
404045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tail = &t->next;
404145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
404245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
404345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *tail = NULL;
404445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    t = thead;
404545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (; t && (tt = t->next) != NULL; t = t->next)
404645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        switch (t->type)
404745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
404845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case TOK_WHITESPACE:
404945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tt->type == TOK_WHITESPACE)
405045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
405145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    t->next = delete_Token(tt);
405245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
405345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
405445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case TOK_ID:
405545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tt->type == TOK_ID || tt->type == TOK_NUMBER)
405645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
405745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    char *tmp = nasm_strcat(t->text, tt->text);
405845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(t->text);
405945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    t->text = tmp;
406045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    t->next = delete_Token(tt);
406145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
406245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
406345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case TOK_NUMBER:
406445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tt->type == TOK_NUMBER)
406545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
406645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    char *tmp = nasm_strcat(t->text, tt->text);
406745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(t->text);
406845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    t->text = tmp;
406945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    t->next = delete_Token(tt);
407045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
407145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
407245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
407345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
407445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return thead;
407545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
407645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
407745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
407845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Expand all single-line macro calls made in the given line.
407945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Return the expanded version of the line. The original is deemed
408045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * to be destroyed in the process. (In reality we'll just move
408145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Tokens from input to output a lot of the time, rather than
408245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * actually bothering to destroy and replicate.)
408345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
408445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Token *
408545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpand_smacro(Token * tline)
408645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
408745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *t, *tt, *mstart, **tail, *thead;
408845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    SMacro *head = NULL, *m;
408945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token **params;
409045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int *paramsize;
409145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int nparam, sparam, brackets, rescan;
409245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *org_tline = tline;
409345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Context *ctx;
409445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *mname;
409545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
409645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
409745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Trick: we should avoid changing the start token pointer since it can
409845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * be contained in "next" field of other token. Because of this
409945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * we allocate a copy of first token and work with it; at the end of
410045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * routine we copy it back
410145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
410245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (org_tline)
410345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
410445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tline =
410545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                new_Token(org_tline->next, org_tline->type, org_tline->text,
410645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                0);
410745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tline->mac = org_tline->mac;
410845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(org_tline->text);
410945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        org_tline->text = NULL;
411045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
411145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
411245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  again:
411345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    tail = &thead;
411445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    thead = NULL;
411545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
411645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (tline)
411745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {                           /* main token loop */
411845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((mname = tline->text))
411945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
412045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* if this token is a local macro, look in local context */
412145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
412245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ctx = get_ctx(mname, TRUE);
412345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
412445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ctx = NULL;
412545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!ctx)
412645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                head = smacros[hash(mname)];
412745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
412845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                head = ctx->localmac;
412945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
413045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * We've hit an identifier. As in is_mmacro below, we first
413145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * check whether the identifier is a single-line macro at
413245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * all, then think about checking for parameters if
413345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * necessary.
413445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
413545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for (m = head; m; m = m->next)
413645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!mstrcmp(m->name, mname, m->casesense))
413745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
413845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (m)
413945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
414045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mstart = tline;
414145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                params = NULL;
414245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                paramsize = NULL;
414345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (m->nparam == 0)
414445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
414545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /*
414645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * Simple case: the macro is parameterless. Discard the
414745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * one token that the macro call took, and push the
414845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * expansion back on the to-do stack.
414945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     */
415045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (!m->expansion)
415145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
415245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (!strcmp("__FILE__", m->name))
415345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
415445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            long num = 0;
415545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            nasm_src_get(&num, &(tline->text));
415645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            nasm_quote(&(tline->text));
415745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            tline->type = TOK_STRING;
415845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            continue;
415945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
416045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (!strcmp("__LINE__", m->name))
416145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
416245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            nasm_free(tline->text);
416345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            make_tok_num(tline, yasm_intnum_create_int(nasm_src_get_linnum()));
416445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            continue;
416545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
416645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        tline = delete_Token(tline);
416745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        continue;
416845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
416945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
417045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
417145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
417245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /*
417345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * Complicated case: at least one macro with this name
417445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * exists and takes parameters. We must find the
417545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * parameters in the call, count them, find the SMacro
417645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * that corresponds to that form of the macro call, and
417745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * substitute for the parameters when we expand. What a
417845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * pain.
417945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     */
418045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /*tline = tline->next;
418145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    skip_white_(tline);*/
418245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    do {
418345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t = tline->next;
418445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        while (tok_type_(t, TOK_SMAC_END))
418545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
418645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            t->mac->in_progress = FALSE;
418745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            t->text = NULL;
418845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            t = tline->next = delete_Token(t);
418945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
419045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        tline = t;
419145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    } while (tok_type_(tline, TOK_WHITESPACE));
419245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (!tok_is_(tline, "("))
419345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
419445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        /*
419545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         * This macro wasn't called with parameters: ignore
419645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         * the call. (Behaviour borrowed from gnu cpp.)
419745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         */
419845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        tline = mstart;
419945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        m = NULL;
420045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
420145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    else
420245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
420345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        int paren = 0;
420445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        int white = 0;
420545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        brackets = 0;
420645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        nparam = 0;
420745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        sparam = PARAM_DELTA;
420845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        params = nasm_malloc(sparam * sizeof(Token *));
420945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        params[0] = tline->next;
421045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        paramsize = nasm_malloc(sparam * sizeof(int));
421145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        paramsize[0] = 0;
421245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        while (TRUE)
421345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {       /* parameter loop */
421445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            /*
421545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                             * For some unusual expansions
421645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                             * which concatenates function call
421745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                             */
421845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            t = tline->next;
421945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            while (tok_type_(t, TOK_SMAC_END))
422045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            {
422145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                t->mac->in_progress = FALSE;
422245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                t->text = NULL;
422345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                t = tline->next = delete_Token(t);
422445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            }
422545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            tline = t;
422645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
422745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            if (!tline)
422845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            {
422945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                error(ERR_NONFATAL,
423045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        "macro call expects terminating `)'");
423145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                break;
423245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            }
423345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            if (tline->type == TOK_WHITESPACE
423445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    && brackets <= 0)
423545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            {
423645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                if (paramsize[nparam])
423745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    white++;
423845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                else
423945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    params[nparam] = tline->next;
424045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                continue;       /* parameter loop */
424145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            }
424245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            if (tline->type == TOK_OTHER
424345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    && tline->text[1] == 0)
424445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            {
424545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                char ch = tline->text[0];
424645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                if (ch == ',' && !paren && brackets <= 0)
424745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                {
424845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    if (++nparam >= sparam)
424945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    {
425045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        sparam += PARAM_DELTA;
425145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        params = nasm_realloc(params,
425245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                                sparam * sizeof(Token *));
425345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        paramsize = nasm_realloc(paramsize,
425445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                                sparam * sizeof(int));
425545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    }
425645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    params[nparam] = tline->next;
425745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    paramsize[nparam] = 0;
425845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    white = 0;
425945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    continue;   /* parameter loop */
426045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                }
426145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                if (ch == '{' &&
426245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        (brackets > 0 || (brackets == 0 &&
426345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                                        !paramsize[nparam])))
426445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                {
426545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    if (!(brackets++))
426645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    {
426745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        params[nparam] = tline->next;
426845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        continue;       /* parameter loop */
426945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    }
427045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                }
427145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                if (ch == '}' && brackets > 0)
427245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    if (--brackets == 0)
427345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    {
427445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        brackets = -1;
427545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        continue;       /* parameter loop */
427645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    }
427745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                if (ch == '(' && !brackets)
427845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    paren++;
427945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                if (ch == ')' && brackets <= 0)
428045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    if (--paren < 0)
428145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        break;
428245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            }
428345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            if (brackets < 0)
428445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            {
428545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                brackets = 0;
428645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                error(ERR_NONFATAL, "braces do not "
428745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        "enclose all of macro parameter");
428845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            }
428945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            paramsize[nparam] += white + 1;
429045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            white = 0;
429145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }       /* parameter loop */
429245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        nparam++;
429345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        while (m && (m->nparam != nparam ||
429445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        mstrcmp(m->name, mname,
429545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                                m->casesense)))
429645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            m = m->next;
429745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (!m)
429845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            error(ERR_WARNING | ERR_WARN_MNP,
429945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    "macro `%s' exists, "
430045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    "but not taking %d parameters",
430145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    mstart->text, nparam);
430245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
430345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
430445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (m && m->in_progress)
430545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    m = NULL;
430645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!m)         /* in progess or didn't find '(' or wrong nparam */
430745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
430845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /*
430945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * Design question: should we handle !tline, which
431045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * indicates missing ')' here, or expand those
431145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * macros anyway, which requires the (t) test a few
431245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * lines down?
431345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     */
431445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(params);
431545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(paramsize);
431645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tline = mstart;
431745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
431845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
431945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
432045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /*
432145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * Expand the macro: we are placed on the last token of the
432245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * call, so that we can easily split the call from the
432345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * following tokens. We also start by pushing an SMAC_END
432445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * token for the cycle removal.
432545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     */
432645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    t = tline;
432745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (t)
432845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
432945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        tline = t->next;
433045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t->next = NULL;
433145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
433245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
433345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tt->mac = m;
433445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    m->in_progress = TRUE;
433545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tline = tt;
433645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    for (t = m->expansion; t; t = t->next)
433745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
433845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (t->type >= TOK_SMAC_PARAM)
433945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
434045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            Token *pcopy = tline, **ptail = &pcopy;
434145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            Token *ttt, *pt;
434245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            int i;
434345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
434445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            ttt = params[t->type - TOK_SMAC_PARAM];
434545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            for (i = paramsize[t->type - TOK_SMAC_PARAM];
434645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    --i >= 0;)
434745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            {
434845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                pt = *ptail =
434945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        new_Token(tline, ttt->type, ttt->text,
435045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                        0);
435145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                ptail = &pt->next;
435245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                ttt = ttt->next;
435345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            }
435445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            tline = pcopy;
435545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
435645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        else
435745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
435845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            tt = new_Token(tline, t->type, t->text, 0);
435945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            tline = tt;
436045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
436145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
436245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
436345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /*
436445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * Having done that, get rid of the macro call, and clean
436545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     * up the parameters.
436645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     */
436745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(params);
436845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(paramsize);
436945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    free_tlist(mstart);
437045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    continue;   /* main token loop */
437145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
437245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
437345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
437445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
437545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (tline->type == TOK_SMAC_END)
437645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
437745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline->mac->in_progress = FALSE;
437845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = delete_Token(tline);
437945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
438045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
438145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
438245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = *tail = tline;
438345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = tline->next;
438445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t->mac = NULL;
438545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t->next = NULL;
438645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tail = &t->next;
438745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
438845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
438945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
439045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
439145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Now scan the entire line and look for successive TOK_IDs that resulted
439245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * after expansion (they can't be produced by tokenise()). The successive
439345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * TOK_IDs should be concatenated.
439445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Also we look for %+ tokens and concatenate the tokens before and after
439545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * them (without white spaces in between).
439645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
439745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    t = thead;
439845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    rescan = 0;
439945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (t)
440045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
440145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
440245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = t->next;
440345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!t || !t->next)
440445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
440545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (t->next->type == TOK_ID ||
440645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t->next->type == TOK_PREPROC_ID ||
440745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t->next->type == TOK_NUMBER)
440845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
440945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            char *p = nasm_strcat(t->text, t->next->text);
441045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nasm_free(t->text);
441145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t->next = delete_Token(t->next);
441245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t->text = p;
441345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            rescan = 1;
441445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
441545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (t->next->type == TOK_WHITESPACE && t->next->next &&
441645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t->next->next->type == TOK_PREPROC_ID &&
441745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                strcmp(t->next->next->text, "%+") == 0)
441845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
441945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* free the next whitespace, the %+ token and next whitespace */
442045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            int i;
442145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for (i = 1; i <= 3; i++)
442245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
442345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!t->next || (i != 2 && t->next->type != TOK_WHITESPACE))
442445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
442545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t->next = delete_Token(t->next);
442645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }                   /* endfor */
442745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
442845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
442945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = t->next;
443045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
443145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* If we concatenaded something, re-scan the line for macros */
443245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (rescan)
443345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
443445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tline = thead;
443545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        goto again;
443645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
443745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
443845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (org_tline)
443945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
444045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (thead)
444145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
444245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *org_tline = *thead;
444345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* since we just gave text to org_line, don't free it */
444445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            thead->text = NULL;
444545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            delete_Token(thead);
444645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
444745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
444845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
444945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* the expression expanded to empty line;
445045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org               we can't return NULL for some reasons
445145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org               we just set the line to a single WHITESPACE token. */
445245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            memset(org_tline, 0, sizeof(*org_tline));
445345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            org_tline->text = NULL;
445445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            org_tline->type = TOK_WHITESPACE;
445545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
445645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        thead = org_tline;
445745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
445845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
445945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return thead;
446045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
446145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
446245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
446345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Similar to expand_smacro but used exclusively with macro identifiers
446445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * right before they are fetched in. The reason is that there can be
446545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * identifiers consisting of several subparts. We consider that if there
446645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * are more than one element forming the name, user wants a expansion,
446745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * otherwise it will be left as-is. Example:
446845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
446945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *      %define %$abc cde
447045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
447145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * the identifier %$abc will be left as-is so that the handler for %define
447245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * will suck it and define the corresponding value. Other case:
447345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
447445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *      %define _%$abc cde
447545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
447645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * In this case user wants name to be expanded *before* %define starts
447745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * working, so we'll expand %$abc into something (if it has a value;
447845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * otherwise it will be left as-is) then concatenate all successive
447945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * PP_IDs into one.
448045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
448145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic Token *
448245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpand_id(Token * tline)
448345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
448445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *cur, *oldnext = NULL;
448545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
448645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!tline || !tline->next)
448745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return tline;
448845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
448945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    cur = tline;
449045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (cur->next &&
449145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (cur->next->type == TOK_ID ||
449245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        cur->next->type == TOK_PREPROC_ID || cur->next->type == TOK_NUMBER))
449345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        cur = cur->next;
449445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
449545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* If identifier consists of just one token, don't expand */
449645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (cur == tline)
449745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return tline;
449845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
449945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (cur)
450045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
450145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        oldnext = cur->next;    /* Detach the tail past identifier */
450245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        cur->next = NULL;       /* so that expand_smacro stops here */
450345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
450445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
450545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    tline = expand_smacro(tline);
450645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
450745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (cur)
450845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
450945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* expand_smacro possibly changhed tline; re-scan for EOL */
451045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        cur = tline;
451145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (cur && cur->next)
451245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            cur = cur->next;
451345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (cur)
451445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            cur->next = oldnext;
451545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
451645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
451745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return tline;
451845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
451945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
452045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
452145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Determine whether the given line constitutes a multi-line macro
452245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * call, and return the MMacro structure called if so. Doesn't have
452345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * to check for an initial label - that's taken care of in
452445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * expand_mmacro - but must check numbers of parameters. Guaranteed
452545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * to be called with tline->type == TOK_ID, so the putative macro
452645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * name is easy to find.
452745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
452845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic MMacro *
452945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgis_mmacro(Token * tline, Token *** params_array)
453045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
453145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    MMacro *head, *m;
453245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token **params;
453345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int nparam;
453445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
453545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    head = mmacros[hash(tline->text)];
453645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
453745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
453845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Efficiency: first we see if any macro exists with the given
453945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * name. If not, we can return NULL immediately. _Then_ we
454045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * count the parameters, and then we look further along the
454145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * list if necessary to find the proper MMacro.
454245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
454345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (m = head; m; m = m->next)
454445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!mstrcmp(m->name, tline->text, m->casesense))
454545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
454645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!m)
454745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;
454845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
454945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
455045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * OK, we have a potential macro. Count and demarcate the
455145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * parameters.
455245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
455345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    count_mmac_params(tline->next, &nparam, &params);
455445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
455545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
455645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * So we know how many parameters we've got. Find the MMacro
455745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * structure that handles this number.
455845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
455945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (m)
456045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
456145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max))
456245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
456345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
456445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * This one is right. Just check if cycle removal
456545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * prohibits us using it before we actually celebrate...
456645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
456745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (m->in_progress)
456845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
456945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#if 0
457045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error(ERR_NONFATAL,
457145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        "self-reference in multi-line macro `%s'", m->name);
457245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#endif
457345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_free(params);
457445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                return NULL;
457545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
457645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
457745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * It's right, and we can use it. Add its default
457845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * parameters to the end of our list if necessary.
457945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
458045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (m->defaults && nparam < m->nparam_min + m->ndefs)
458145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
458245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                params =
458345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        nasm_realloc(params,
458445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        ((m->nparam_min + m->ndefs + 1) * sizeof(*params)));
458545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                while (nparam < m->nparam_min + m->ndefs)
458645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
458745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    params[nparam] = m->defaults[nparam - m->nparam_min];
458845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nparam++;
458945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
459045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
459145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
459245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * If we've gone over the maximum parameter count (and
459345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * we're in Plus mode), ignore parameters beyond
459445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * nparam_max.
459545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
459645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (m->plus && nparam > m->nparam_max)
459745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nparam = m->nparam_max;
459845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
459945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * Then terminate the parameter list, and leave.
460045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
460145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!params)
460245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {                   /* need this special case */
460345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                params = nasm_malloc(sizeof(*params));
460445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nparam = 0;
460545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
460645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            params[nparam] = NULL;
460745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *params_array = params;
460845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return m;
460945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
461045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*
461145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * This one wasn't right: look for the next one with the
461245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * same name.
461345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         */
461445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for (m = m->next; m; m = m->next)
461545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!mstrcmp(m->name, tline->text, m->casesense))
461645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
461745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
461845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
461945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
462045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * After all that, we didn't find one with the right number of
462145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * parameters. Issue a warning, and fail to expand the macro.
462245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
462345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    error(ERR_WARNING | ERR_WARN_MNP,
462445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            "macro `%s' exists, but not taking %d parameters",
462545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline->text, nparam);
462645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_free(params);
462745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return NULL;
462845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
462945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
463045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
463145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Expand the multi-line macro call made by the given line, if
463245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * there is one to be expanded. If there is, push the expansion on
463345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * istk->expansion and return 1. Otherwise return 0.
463445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
463545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
463645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpand_mmacro(Token * tline)
463745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
463845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *startline = tline;
463945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *label = NULL;
464045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int dont_prepend = 0;
464145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token **params, *t, *tt;
464245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    MMacro *m;
464345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Line *l, *ll;
464445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int i, nparam;
464545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    long *paramlen;
464645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
464745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    t = tline;
464845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    skip_white_(t);
464945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    if (!tok_type_(t, TOK_ID))  Lino 02/25/02 */
465045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
465145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 0;
465245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    m = is_mmacro(t, &params);
465345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (!m)
465445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
465545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Token *last;
465645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*
465745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * We have an id which isn't a macro call. We'll assume
465845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * it might be a label; we'll also check to see if a
465945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * colon follows it. Then, if there's another id after
466045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * that lot, we'll check it again for macro-hood.
466145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         */
466245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        label = last = t;
466345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        t = t->next;
466445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (tok_type_(t, TOK_WHITESPACE))
466545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            last = t, t = t->next;
466645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (tok_is_(t, ":"))
466745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
466845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            dont_prepend = 1;
466945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            last = t, t = t->next;
467045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (tok_type_(t, TOK_WHITESPACE))
467145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                last = t, t = t->next;
467245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
467345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
467445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 0;
467545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        last->next = NULL;
467645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tline = t;
467745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
467845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
467945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
468045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * Fix up the parameters: this involves stripping leading and
468145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * trailing whitespace, then stripping braces if they are
468245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * present.
468345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
468445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (nparam = 0; params[nparam]; nparam++)
468545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ;
468645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
468745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
468845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (i = 0; params[i]; i++)
468945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
469045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        int brace = FALSE;
469145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        int comma = (!m->plus || i < nparam - 1);
469245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
469345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        t = params[i];
469445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        skip_white_(t);
469545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (tok_is_(t, "{"))
469645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = t->next, brace = TRUE, comma = FALSE;
469745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        params[i] = t;
469845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        paramlen[i] = 0;
469945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (t)
470045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
470145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
470245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;          /* ... because we have hit a comma */
470345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (comma && t->type == TOK_WHITESPACE && tok_is_(t->next, ","))
470445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;          /* ... or a space then a comma */
470545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
470645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;          /* ... or a brace */
470745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t = t->next;
470845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            paramlen[i]++;
470945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
471045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
471145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
471245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
471345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * OK, we have a MMacro structure together with a set of
471445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * parameters. We must now go through the expansion and push
471545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * copies of each Line on to istk->expansion. Substitution of
471645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * parameter tokens and macro-local tokens doesn't get done
471745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * until the single-line macro substitution process; this is
471845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * because delaying them allows us to change the semantics
471945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * later through %rotate.
472045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     *
472145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * First, push an end marker on to istk->expansion, mark this
472245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * macro as in progress, and set up its invocation-specific
472345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * variables.
472445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
472545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ll = nasm_malloc(sizeof(Line));
472645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ll->next = istk->expansion;
472745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ll->finishes = m;
472845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ll->first = NULL;
472945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    istk->expansion = ll;
473045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
473145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    m->in_progress = TRUE;
473245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    m->params = params;
473345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    m->iline = tline;
473445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    m->nparam = nparam;
473545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    m->rotate = 0;
473645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    m->paramlen = paramlen;
473745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    m->unique = unique++;
473845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    m->lineno = 0;
473945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
474045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    m->next_active = istk->mstk;
474145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    istk->mstk = m;
474245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
474345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (l = m->expansion; l; l = l->next)
474445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
474545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Token **tail;
474645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
474745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ll = nasm_malloc(sizeof(Line));
474845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ll->finishes = NULL;
474945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ll->next = istk->expansion;
475045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        istk->expansion = ll;
475145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tail = &ll->first;
475245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
475345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for (t = l->first; t; t = t->next)
475445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
475545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            Token *x = t;
475645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (t->type == TOK_PREPROC_ID &&
475745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    t->text[1] == '0' && t->text[2] == '0')
475845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
475945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                dont_prepend = -1;
476045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                x = label;
476145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!x)
476245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    continue;
476345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
476445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tt = *tail = new_Token(NULL, x->type, x->text, 0);
476545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tail = &tt->next;
476645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
476745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *tail = NULL;
476845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
476945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
477045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
477145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * If we had a label, push it on as the first line of
477245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * the macro expansion.
477345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
477445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (label)
477545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
477645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (dont_prepend < 0)
477745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(startline);
477845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
477945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
478045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ll = nasm_malloc(sizeof(Line));
478145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ll->finishes = NULL;
478245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ll->next = istk->expansion;
478345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            istk->expansion = ll;
478445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ll->first = startline;
478545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!dont_prepend)
478645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
478745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                while (label->next)
478845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    label = label->next;
478945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
479045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
479145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
479245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
479345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
479445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
479545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
479645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 1;
479745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
479845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
479945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
4800a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org * Since preprocessor always operates only on the line that didn't
4801a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org * arrive yet, we should always use ERR_OFFBY1. Also since user
480245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * won't want to see same error twice (preprocessing is done once
480345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * per pass) we will want to show errors only during pass one.
480445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
480545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
480645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgerror(int severity, const char *fmt, ...)
480745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
480845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    va_list arg;
480945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char buff[1024];
481045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
481145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* If we're in a dead branch of IF or something like it, ignore the error */
481245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (istk && istk->conds && !emitting(istk->conds->state))
481345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
481445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
481545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    va_start(arg, fmt);
4816a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org#ifdef HAVE_VSNPRINTF
4817a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    vsnprintf(buff, sizeof(buff), fmt, arg);
4818a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org#else
481945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    vsprintf(buff, fmt, arg);
4820a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org#endif
482145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    va_end(arg);
482245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
482345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (istk && istk->mstk && istk->mstk->name)
482445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        _error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
482545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                istk->mstk->lineno, buff);
482645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
482745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        _error(severity | ERR_PASS1, "%s", buff);
482845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
482945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
483045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
483145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgpp_reset(FILE *f, const char *file, int apass, efunc errfunc, evalfunc eval,
483245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ListGen * listgen)
483345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
483445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int h;
483545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
483645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    first_fp = f;
483745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    _error = errfunc;
483845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    cstk = NULL;
483945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    istk = nasm_malloc(sizeof(Include));
484045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    istk->next = NULL;
484145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    istk->conds = NULL;
484245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    istk->expansion = NULL;
484345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    istk->mstk = NULL;
484445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    istk->fp = f;
484545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    istk->fname = NULL;
484645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_free(nasm_src_set_fname(nasm_strdup(file)));
484745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nasm_src_set_linnum(0);
484845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    istk->lineinc = 1;
484945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    defining = NULL;
485045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nested_mac_count = 0;
485145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    nested_rep_count = 0;
485245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (h = 0; h < NHASH; h++)
485345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
485445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        mmacros[h] = NULL;
485545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        smacros[h] = NULL;
485645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
485745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unique = 0;
485845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (tasm_compatible_mode) {
485945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        pp_extra_stdmac(tasm_compat_macros);
486045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
486145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    list = listgen;
486245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    evaluate = eval;
486345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass = apass;
486445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    first_line = 1;
486545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
486645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
486745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
486845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Nasty hack: here we push the contents of `predef' on
486945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * to the top-level expansion stack, since this is the
487045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * most convenient way to implement the pre-include and
487145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * pre-define features.
487245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
487345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
487445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgpoke_predef(Line *predef_lines)
487545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
487645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Line *pd, *l;
487745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *head, **tail, *t;
487845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
487945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (pd = predef_lines; pd; pd = pd->next)
488045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
488145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        head = NULL;
488245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tail = &head;
488345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for (t = pd->first; t; t = t->next)
488445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
488545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *tail = new_Token(NULL, t->type, t->text, 0);
488645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tail = &(*tail)->next;
488745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
488845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        l = nasm_malloc(sizeof(Line));
488945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        l->next = istk->expansion;
489045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        l->first = head;
489145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        l->finishes = FALSE;
489245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        istk->expansion = l;
489345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
489445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
489545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
489645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic char *
489745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgpp_getline(void)
489845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
489945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *line;
490045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *tline;
490145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
490245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (1)
490345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
490445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*
490545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * Fetch a tokenised line, either from the macro-expansion
490645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * buffer or from the input file.
490745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         */
490845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tline = NULL;
490945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
491045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (first_line)
491145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
491245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Reverse order */
491345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            poke_predef(predef);
491445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            poke_predef(stddef);
491545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            poke_predef(builtindef);
491645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            first_line = 0;
491745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
491845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
491945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!istk)
492045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return NULL;
492145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (istk->expansion && istk->expansion->finishes)
492245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
492345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            Line *l = istk->expansion;
492445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!l->finishes->name && l->finishes->in_progress > 1)
492545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
492645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                Line *ll;
492745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
492845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /*
492945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * This is a macro-end marker for a macro with no
493045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * name, which means it's not really a macro at all
493145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * but a %rep block, and the `in_progress' field is
493245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * more than 1, meaning that we still need to
493345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * repeat. (1 means the natural last repetition; 0
493445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * means termination by %exitrep.) We have
493545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * therefore expanded up to the %endrep, and must
493645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * push the whole block on to the expansion buffer
493745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * again. We don't bother to remove the macro-end
493845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * marker: we'd only have to generate another one
493945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * if we did.
494045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 */
494145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                l->finishes->in_progress--;
494245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                for (l = l->finishes->expansion; l; l = l->next)
494345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
494445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    Token *t, *tt, **tail;
494545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
494645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    ll = nasm_malloc(sizeof(Line));
494745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    ll->next = istk->expansion;
494845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    ll->finishes = NULL;
494945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    ll->first = NULL;
495045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tail = &ll->first;
495145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
495245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    for (t = l->first; t; t = t->next)
495345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
495445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (t->text || t->type == TOK_WHITESPACE)
495545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
495645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            tt = *tail = new_Token(NULL, t->type, t->text, 0);
495745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            tail = &tt->next;
495845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
495945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
496045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
496145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    istk->expansion = ll;
496245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
496345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
496445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
496545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
496645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /*
496745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * Check whether a `%rep' was started and not ended
496845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * within this macro expansion. This can happen and
496945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * should be detected. It's a fatal error because
497045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * I'm too confused to work out how to recover
497145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * sensibly from it.
497245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 */
497345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (defining)
497445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
497545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (defining->name)
497645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        error(ERR_PANIC, "defining with name in expansion");
497745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    else if (istk->mstk->name)
497845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        error(ERR_FATAL, "`%%rep' without `%%endrep' within"
497945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                " expansion of macro `%s'", istk->mstk->name);
498045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
498145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
498245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /*
498345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * FIXME:  investigate the relationship at this point between
498445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * istk->mstk and l->finishes
498545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 */
498645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
498745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    MMacro *m = istk->mstk;
498845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    istk->mstk = m->next_active;
498945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (m->name)
499045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
499145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        /*
499245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         * This was a real macro call, not a %rep, and
499345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         * therefore the parameter information needs to
499445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         * be freed.
499545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         */
499645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        nasm_free(m->params);
499745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        free_tlist(m->iline);
499845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        nasm_free(m->paramlen);
499945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        l->finishes->in_progress = FALSE;
500045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
500145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    else
500245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        free_mmacro(m);
500345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
500445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                istk->expansion = l->next;
500545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_free(l);
500645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                list->downlevel(LIST_MACRO);
500745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
500845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
500945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (1)
501045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {                       /* until we get a line we can use */
501145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
501245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (istk->expansion)
501345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {                   /* from a macro expansion */
501445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                char *p;
501545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                Line *l = istk->expansion;
501645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (istk->mstk)
501745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    istk->mstk->lineno++;
501845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = l->first;
501945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                istk->expansion = l->next;
502045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_free(l);
502145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                p = detoken(tline, FALSE);
502245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                list->line(LIST_MACRO, p);
502345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_free(p);
502445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
502545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
502645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            line = read_line();
502745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (line)
502845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {                   /* from the current input file */
502945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                line = prepreproc(line);
503045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tline = tokenise(line);
503145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_free(line);
503245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
503345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
503445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
503545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * The current file has ended; work down the istk
503645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
503745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
503845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                Include *i = istk;
503945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (i->fp != first_fp)
504045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    fclose(i->fp);
504145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (i->conds)
504245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error(ERR_FATAL, "expected `%%endif' before end of file");
504345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* only set line and file name if there's a next node */
504445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (i->next)
504545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
504645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_src_set_linnum(i->lineno);
504745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    nasm_free(nasm_src_set_fname(nasm_strdup(i->fname)));
504845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
504945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                istk = i->next;
505045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                list->downlevel(LIST_INCLUDE);
505145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                nasm_free(i);
505245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!istk)
505345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return NULL;
505445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (istk->expansion && istk->expansion->finishes)
505545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
505645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
505745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
505845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
505945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*
506045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * We must expand MMacro parameters and MMacro-local labels
506145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * _before_ we plunge into directive processing, to cope
506245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * with things like `%define something %1' such as STRUC
506345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * uses. Unless we're _defining_ a MMacro, in which case
506445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * those tokens should be left alone to go into the
506545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * definition; and unless we're in a non-emitting
506645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * condition, in which case we don't want to meddle with
506745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * anything.
506845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         */
506945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!defining && !(istk->conds && !emitting(istk->conds->state)))
507045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_mmac_params(tline);
507145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
507245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /*
507345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         * Check the line to see if it's a preprocessor directive.
507445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         */
507545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (do_directive(tline) == DIRECTIVE_FOUND)
507645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
507745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            continue;
507845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
507945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (defining)
508045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
508145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
508245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * We're defining a multi-line macro. We emit nothing
508345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * at all, and just
508445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * shove the tokenised line on to the macro definition.
508545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
508645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            Line *l = nasm_malloc(sizeof(Line));
508745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            l->next = defining->expansion;
508845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            l->first = tline;
508945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            l->finishes = FALSE;
509045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            defining->expansion = l;
509145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            continue;
509245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
509345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (istk->conds && !emitting(istk->conds->state))
509445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
509545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
509645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * We're in a non-emitting branch of a condition block.
509745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * Emit nothing at all, not even a blank line: when we
509845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * emerge from the condition we'll give a line-number
509945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * directive so we keep our place correctly.
510045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
510145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(tline);
510245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            continue;
510345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
510445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (istk->mstk && !istk->mstk->in_progress)
510545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
510645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*
510745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * We're in a %rep block which has been terminated, so
510845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * we're walking through to the %endrep without
510945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * emitting anything. Emit nothing at all, not even a
511045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * blank line: when we emerge from the %rep block we'll
511145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * give a line-number directive so we keep our place
511245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             * correctly.
511345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org             */
511445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(tline);
511545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            continue;
511645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
511745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
511845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
511945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tline = expand_smacro(tline);
512045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (!expand_mmacro(tline))
512145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
512245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /*
512345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * De-tokenise the line again, and emit it.
512445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 */
512545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (tasm_compatible_mode)
512645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    tline = tasm_join_tokens(tline);
512745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
512845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                line = detoken(tline, TRUE);
512945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_tlist(tline);
513045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
513145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
513245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
513345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
513445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                continue;       /* expand_mmacro calls free_tlist */
513545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
513645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
513745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
513845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
513945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return line;
514045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
514145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
514245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
514345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgpp_cleanup(int pass_)
514445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
514545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int h;
514645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
514745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (pass_ == 1)
514845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
514945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (defining)
515045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
515145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error(ERR_NONFATAL, "end of file while still defining macro `%s'",
515245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    defining->name);
515345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_mmacro(defining);
515445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
515545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return;
515645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
515745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (cstk)
515845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ctx_pop();
515945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (h = 0; h < NHASH; h++)
516045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
516145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (mmacros[h])
516245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
516345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            MMacro *m = mmacros[h];
516445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mmacros[h] = mmacros[h]->next;
516545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_mmacro(m);
516645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
516745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (smacros[h])
516845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
516945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            SMacro *s = smacros[h];
517045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            smacros[h] = smacros[h]->next;
517145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nasm_free(s->name);
517245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            free_tlist(s->expansion);
517345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            nasm_free(s);
517445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
517545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
517645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (istk)
517745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
517845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Include *i = istk;
517945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        istk = istk->next;
518045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (i->fp != first_fp)
518145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fclose(i->fp);
518245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(i->fname);
518345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(i);
518445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
518545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (cstk)
518645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ctx_pop();
518745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (pass_ == 0)
518845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
518945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_llist(builtindef);
519045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_llist(stddef);
519145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                free_llist(predef);
5192a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                builtindef = NULL;
5193a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                stddef = NULL;
5194a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                predef = NULL;
5195a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                freeTokens = NULL;
519645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                delete_Blocks();
5197a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                blocks.next = NULL;
5198a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org                blocks.chunk = NULL;
519945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
520045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
520145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
520245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
520345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgpp_pre_include(const char *fname)
520445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
520545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *inc, *space, *name;
520645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Line *l;
520745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
520845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
520945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    space = new_Token(name, TOK_WHITESPACE, NULL, 0);
521045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
521145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
521245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l = nasm_malloc(sizeof(Line));
521345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l->next = predef;
521445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l->first = inc;
521545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l->finishes = FALSE;
521645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    predef = l;
521745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
521845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
521945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
522045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgpp_pre_define(char *definition)
522145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
522245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *def, *space;
522345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Line *l;
522445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *equals;
522545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
522645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    equals = strchr(definition, '=');
522745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
522845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
522945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (equals)
523045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *equals = ' ';
523145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    space->next = tokenise(definition);
523245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (equals)
523345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *equals = '=';
523445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
523545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l = nasm_malloc(sizeof(Line));
523645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l->next = predef;
523745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l->first = def;
523845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l->finishes = FALSE;
523945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    predef = l;
524045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
524145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
524245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
524345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgpp_pre_undefine(char *definition)
524445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
524545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *def, *space;
524645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Line *l;
524745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
524845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
524945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
525045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    space->next = tokenise(definition);
525145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
525245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l = nasm_malloc(sizeof(Line));
525345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l->next = predef;
525445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l->first = def;
525545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l->finishes = FALSE;
525645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    predef = l;
525745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
525845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
525945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
526045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgpp_builtin_define(char *definition)
526145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
526245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Token *def, *space;
526345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Line *l;
526445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    char *equals;
526545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
526645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    equals = strchr(definition, '=');
526745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
526845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
526945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (equals)
527045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *equals = ' ';
527145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    space->next = tokenise(definition);
527245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (equals)
527345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *equals = '=';
527445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
527545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l = nasm_malloc(sizeof(Line));
527645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l->next = builtindef;
527745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l->first = def;
527845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    l->finishes = FALSE;
527945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    builtindef = l;
528045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
528145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
528245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
528345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgpp_extra_stdmac(const char **macros)
528445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
528545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const char **lp;
528645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
528745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (lp=macros; *lp; lp++)
528845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
528945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        char *macro;
529045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Token *t;
529145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Line *l;
529245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
529345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        macro = nasm_strdup(*lp);
529445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        t = tokenise(macro);
529545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        nasm_free(macro);
529645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
529745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        l = nasm_malloc(sizeof(Line));
529845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        l->next = stddef;
529945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        l->first = t;
530045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        l->finishes = FALSE;
530145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        stddef = l;
530245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
530345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
530445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
530545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
530645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgmake_tok_num(Token * tok, yasm_intnum *val)
530745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
530845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    tok->text = yasm_intnum_get_str(val);
530945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    tok->type = TOK_NUMBER;
5310d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org    yasm_intnum_destroy(val);
531145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
531245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
531345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgPreproc nasmpp = {
531445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pp_reset,
531545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pp_getline,
531645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pp_cleanup
531745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
5318