diff options
author | H. Peter Anvin <hpa@zytor.com> | 2002-04-30 20:53:55 +0000 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2002-04-30 20:53:55 +0000 |
commit | eba20a73f2b3396f617747e789e35a679eb09606 (patch) | |
tree | 2a1b5e2652e39022a1d6ff7a36a630041edad1b6 /preproc.c | |
parent | 87bc61964cf5d2cc2e322883d6f927a43fb53af3 (diff) | |
download | nasm-eba20a73f2b3396f617747e789e35a679eb09606.tar.gz nasm-eba20a73f2b3396f617747e789e35a679eb09606.tar.bz2 nasm-eba20a73f2b3396f617747e789e35a679eb09606.zip |
NASM 0.98p3
Diffstat (limited to 'preproc.c')
-rw-r--r-- | preproc.c | 1460 |
1 files changed, 760 insertions, 700 deletions
@@ -8,6 +8,11 @@ * initial version 18/iii/97 by Simon Tatham */ +#define br0 '{' +#define br1 "{" +#define br2 '}' +#define br3 "}" + #include <stdio.h> #include <stdlib.h> #include <stddef.h> @@ -64,12 +69,14 @@ struct MMacro { int plus; /* is the last parameter greedy? */ int nolist; /* is this macro listing-inhibited? */ int in_progress; - Token **defaults, *dlist; + Token *dlist; /* All defaults as one list */ + Token **defaults; /* Parameter default pointers */ int ndefs; /* number of default parameters */ Line *expansion; MMacro *next_active; - Token **params, *iline; + Token **params; /* actual parameters */ + Token *iline; /* invocation line */ int nparam, rotate, *paramlen; unsigned long unique; }; @@ -88,11 +95,6 @@ struct Context { * This is the internal form which we break input lines up into. * Typically stored in linked lists. * - * TOK_PS_OTHER is a token type used internally within - * expand_smacro(), to denote a token which has already been - * checked for being a potential macro, but may still be a context- - * local label. - * * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not * necessarily used as-is, but is intended to denote the number of * the substituted parameter. So in the definition @@ -116,7 +118,7 @@ struct Token { }; enum { TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING, - TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_PS_OTHER, TOK_SMAC_PARAM, + TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM, TOK_INTERNAL_STRING }; @@ -271,14 +273,14 @@ static int pass; static unsigned long unique; /* unique identifier numbers */ -static char *linesync, *outline; - static Line *predef = NULL; static ListGen *list; /* * The number of hash values we use for the macro lookup tables. + * FIXME: We should *really* be able to configure this at run time, + * or even have the hash table automatically expanding when necessary. */ #define NHASH 31 @@ -321,7 +323,15 @@ int any_extrastdmac; * Forward declarations. */ static Token *expand_smacro (Token *tline); -static void update_fileline (int which); +static void make_tok_num(Token *tok, long val); + +/* + * Macros for safe checking of token pointers, avoid *(NULL) + */ +#define tok_type_(x,t) ((x) && (x)->type == (t)) +#define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next +#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v))) +#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v)))) /* * The pre-preprocessing stage... This function translates line @@ -329,7 +339,8 @@ static void update_fileline (int which); * flags') into NASM preprocessor line number indications (`%line * lineno file'). */ -static char *prepreproc(char *line) { +static char *prepreproc(char *line) +{ int lineno, fnlen; char *fname, *oldline; @@ -354,7 +365,10 @@ static char *prepreproc(char *line) { * invariant under case changes. We implement this by applying a * perfectly normal hash function to the uppercase of the string. */ -static int hash(char *s) { +static int hash(char *s) +{ + unsigned int h = 0; + int i = 0; /* * Powers of three, mod 31. */ @@ -362,8 +376,7 @@ static int hash(char *s) { 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21 }; - int h = 0; - int i = 0; + while (*s) { h += multipliers[i] * (unsigned char) (toupper(*s)); @@ -378,7 +391,8 @@ static int hash(char *s) { /* * Free a linked list of tokens. */ -static void free_tlist (Token *list) { +static void free_tlist (Token *list) +{ Token *t; while (list) { t = list; @@ -391,7 +405,8 @@ static void free_tlist (Token *list) { /* * Free a linked list of lines. */ -static void free_llist (Line *list) { +static void free_llist (Line *list) +{ Line *l; while (list) { l = list; @@ -402,9 +417,22 @@ static void free_llist (Line *list) { } /* + * Free an MMacro + */ +static void free_mmacro (MMacro *m) +{ + nasm_free (m->name); + free_tlist (m->dlist); + nasm_free (m->defaults); + free_llist (m->expansion); + nasm_free (m); +} + +/* * Pop the context stack. */ -static void ctx_pop (void) { +static void ctx_pop (void) +{ Context *c = cstk; SMacro *smac, *s; @@ -421,19 +449,6 @@ static void ctx_pop (void) { nasm_free (c); } -/* - * Generate a line synchronisation comment, to ensure the assembler - * knows which source file the current output has really come from. - */ -static void line_sync (void) { - char text[30+FILENAME_MAX]; - sprintf(text, "%%line %d+%d %s", - (istk->expansion ? istk->lineno - istk->lineinc : istk->lineno), - (istk->expansion ? 0 : istk->lineinc), istk->fname); - nasm_free (linesync); - linesync = nasm_strdup(text); -} - #define BUF_DELTA 512 /* * Read a line from the top file in istk, handling multiple CR/LFs @@ -441,14 +456,16 @@ static void line_sync (void) { * return lines from the standard macro set if this has not already * been done. */ -static char *read_line (void) { +static char *read_line (void) +{ char *buffer, *p, *q; int bufsize; if (stdmacpos) { if (*stdmacpos) { char *ret = nasm_strdup(*stdmacpos++); - if (!*stdmacpos && any_extrastdmac) { + if (!*stdmacpos && any_extrastdmac) + { stdmacpos = extrastdmac; any_extrastdmac = FALSE; return ret; @@ -459,7 +476,8 @@ static char *read_line (void) { * most convenient way to implement the pre-include and * pre-define features. */ - if (!*stdmacpos) { + if (!*stdmacpos) + { Line *pd, *l; Token *head, **tail, *t, *tt; @@ -482,10 +500,9 @@ static char *read_line (void) { } } return ret; - } else { + } + else { stdmacpos = NULL; - line_sync(); - update_fileline(3); /* update __FILE__ and __LINE__ */ } } @@ -498,13 +515,13 @@ static char *read_line (void) { break; p += strlen(p); if (p > buffer && p[-1] == '\n') { - istk->lineno += istk->lineinc; - update_fileline(1); /* update __LINE__ only */ break; } if (p-buffer > bufsize-10) { + long offset = p-buffer; bufsize += BUF_DELTA; buffer = nasm_realloc(buffer, bufsize); + p = buffer+offset; /* prevent stale-pointer problems */ } } @@ -513,12 +530,14 @@ static char *read_line (void) { return NULL; } + src_set_linnum(src_get_linnum() + istk->lineinc); + /* * Play safe: remove CRs as well as LFs, if any of either are * present at the end of the line. */ - while (p > buffer && (p[-1] == '\n' || p[-1] == '\r')) - *--p = '\0'; + while (--p >= buffer && (*p == '\n' || *p == '\r')) + *p = '\0'; /* * Handle spurious ^Z, which may be inserted into source files @@ -536,7 +555,8 @@ static char *read_line (void) { * don't need to parse the value out of e.g. numeric tokens: we * simply split one string into many. */ -static Token *tokenise (char *line) { +static Token *tokenise (char *line) +{ char *p = line; int type; Token *list = NULL; @@ -544,31 +564,42 @@ static Token *tokenise (char *line) { while (*line) { p = line; - if (*p == '%' && - (p[1] == '{' || p[1] == '!' || (p[1] == '%' && isidchar(p[2])) || - p[1] == '$' || p[1] == '+' || p[1] == '-' || isidchar(p[1]))) { - type = TOK_PREPROC_ID; + if (*p == '%' && ( isdigit(p[1]) || + ((p[1] == '-' || p[1] == '+') && isdigit(p[2])))) + { p++; - if (*p == '{') { + do { + p++; + } while (isdigit(*p)); + type = TOK_PREPROC_ID; + } + else if (*p == '%' && p[1] == '{') { + p += 2; + while (*p && *p != '}') { + p[-1] = *p; p++; - while (*p && *p != '}') { - p[-1] = *p; - p++; - } - p[-1] = '\0'; - if (*p) p++; - } else { - if (*p == '!' || *p == '%' || *p == '$' || - *p == '+' || *p == '-') p++; - while (*p && isidchar(*p)) - p++; } - } else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) { + p[-1] = '\0'; + if (*p) p++; + type = TOK_PREPROC_ID; + } + else if (*p == '%' && (isidchar(p[1]) || + ((p[1] == '!' || p[1] == '%' || p[1] == '$') && + isidchar(p[2])))) + { + p++; + do { + p++; + } while (isidchar(*p)); + type = TOK_PREPROC_ID; + } + else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) { type = TOK_ID; p++; while (*p && isidchar(*p)) p++; - } else if (*p == '\'' || *p == '"') { + } + else if (*p == '\'' || *p == '"') { /* * A string token. */ @@ -578,7 +609,8 @@ static Token *tokenise (char *line) { while (*p && *p != c) p++; if (*p) p++; - } else if (isnumstart(*p)) { + } + else if (isnumstart(*p)) { /* * A number token. */ @@ -586,7 +618,8 @@ static Token *tokenise (char *line) { p++; while (*p && isnumchar(*p)) p++; - } else if (isspace(*p)) { + } + else if (isspace(*p)) { type = TOK_WHITESPACE; p++; while (*p && isspace(*p)) @@ -600,10 +633,12 @@ static Token *tokenise (char *line) { type = TOK_COMMENT; while (*p) p++; } - } else if (*p == ';') { + } + else if (*p == ';') { type = TOK_COMMENT; while (*p) p++; - } else { + } + else { /* * Anything else is an operator of some kind. We check * for all the double-character operators (>>, <<, //, @@ -623,7 +658,9 @@ static Token *tokenise (char *line) { (p[0] == '&' && p[1] == '&') || (p[0] == '|' && p[1] == '|') || (p[0] == '^' && p[1] == '^')) + { p++; + } p++; } if (type != TOK_COMMENT) { @@ -644,7 +681,8 @@ static Token *tokenise (char *line) { /* * Convert a line of tokens back into text. */ -static char *detoken (Token *tlist) { +char *detoken (Token *tlist) +{ Token *t; int len; char *line, *p; @@ -679,7 +717,8 @@ static char *detoken (Token *tlist) { * the first token in the line to be passed in as its private_data * field. */ -static int ppscan(void *private_data, struct tokenval *tokval) { +static int ppscan(void *private_data, struct tokenval *tokval) +{ Token **tlineptr = private_data; Token *tline; @@ -724,6 +763,25 @@ static int ppscan(void *private_data, struct tokenval *tokval) { return tokval->t_type = TOKEN_NUM; } + if (tline->type == TOK_STRING) { + int rn_warn; + char q, *r; + int l; + + r = tline->text; + q = *r++; + l = strlen(r); + + if (l == 0 || r[l-1] != q) + return tokval->t_type = TOKEN_ERRNUM; + tokval->t_integer = readstrnum(r, l-1, &rn_warn); + if (rn_warn) + error(ERR_WARNING|ERR_PASS1, + "character constant too long"); + tokval->t_charptr = NULL; + return tokval->t_type = TOKEN_NUM; + } + if (tline->type == TOK_OTHER) { if (!strcmp(tline->text, "<<")) return tokval->t_type = TOKEN_SHL; if (!strcmp(tline->text, ">>")) return tokval->t_type = TOKEN_SHR; @@ -752,12 +810,13 @@ static int ppscan(void *private_data, struct tokenval *tokval) { * context stack isn't deep enough for the supplied number of $ * signs. */ -static Context *get_ctx (char *name) { +static Context *get_ctx (char *name) +{ Context *ctx; int i; if (!cstk) { - error (ERR_NONFATAL|ERR_OFFBY1, "`%s': context stack is empty", name); + error (ERR_NONFATAL, "`%s': context stack is empty", name); return NULL; } @@ -767,7 +826,7 @@ static Context *get_ctx (char *name) { i++; ctx = ctx->next; if (!ctx) { - error (ERR_NONFATAL|ERR_OFFBY1, "`%s': context stack is only" + error (ERR_NONFATAL, "`%s': context stack is only" " %d level%s deep", name, i-1, (i==2 ? "" : "s")); return NULL; } @@ -780,7 +839,8 @@ static Context *get_ctx (char *name) { * simple wrapper which calls either strcmp or nasm_stricmp * depending on the value of the `casesense' parameter. */ -static int mstrcmp(char *p, char *q, int casesense) { +static int mstrcmp(char *p, char *q, int casesense) +{ return casesense ? strcmp(p,q) : nasm_stricmp(p,q); } @@ -791,26 +851,25 @@ static int mstrcmp(char *p, char *q, int casesense) { * the include path one by one until it finds the file or reaches * the end of the path. */ -static FILE *inc_fopen(char *file) { +static FILE *inc_fopen(char *file) +{ FILE *fp; char *prefix = "", *combine; IncPath *ip = ipath; - int len = strlen(file); - do { - combine = nasm_malloc(strlen(prefix)+len+1); - strcpy(combine, prefix); - strcat(combine, file); + while (1) { + combine = nasm_strcat(prefix,file); fp = fopen(combine, "r"); nasm_free (combine); if (fp) return fp; - prefix = ip ? ip->path : NULL; - if (ip) - ip = ip->next; - } while (prefix); + if (!ip) + break; + prefix = ip->path; + ip = ip->next; + } - error (ERR_FATAL|ERR_OFFBY1, + error (ERR_FATAL, "unable to open include file `%s'", file); return NULL; /* never reached - placate compilers */ } @@ -831,7 +890,8 @@ static FILE *inc_fopen(char *file) { * Note that this is also called with nparam zero to resolve * `ifdef'. */ -static int smacro_defined (char *name, int nparam, SMacro **defn) { +static int smacro_defined (char *name, int nparam, SMacro **defn, int nocase) +{ SMacro *m; Context *ctx; char *p; @@ -849,7 +909,7 @@ static int smacro_defined (char *name, int nparam, SMacro **defn) { } while (m) { - if (!mstrcmp(m->name, p, m->casesense) && + if (!mstrcmp(m->name, p, m->casesense & nocase) && (nparam == 0 || m->nparam == 0 || nparam == m->nparam)) { if (defn) { if (nparam == m->nparam) @@ -865,48 +925,13 @@ static int smacro_defined (char *name, int nparam, SMacro **defn) { } /* - * Update the __FILE__ and __LINE__ macros. Specifically, update - * __FILE__ if bit 1 of our argument is set, and update __LINE__ if - * bit 0 is set. - * - * If the macros don't exist, a `%clear' must have happened, in - * which case we should exit quite happily and carry on going. It's - * not an error condition. - */ -static void update_fileline(int which) { - SMacro *sm; - char num[20]; - - if ((which & 3) && smacro_defined ("__FILE__", 0, &sm) && sm) { - free_tlist(sm->expansion); - sm->expansion = nasm_malloc(sizeof(Token)); - sm->expansion->next = NULL; - sm->expansion->mac = NULL; - sm->expansion->type = TOK_STRING; - sm->expansion->text = nasm_malloc(3+strlen(istk->fname)); - /* FIXME: throw an error if both sorts of quote are present */ - /* Better still, invent a way for us to cope with that case */ - sprintf(sm->expansion->text, "\"%s\"", istk->fname); - } - - if ((which & 1) && smacro_defined ("__LINE__", 0, &sm) && sm) { - free_tlist(sm->expansion); - sm->expansion = nasm_malloc(sizeof(Token)); - sm->expansion->next = NULL; - sm->expansion->mac = NULL; - sm->expansion->type = TOK_NUMBER; - sprintf(num, "%d", istk->lineno - istk->lineinc); - sm->expansion->text = nasm_strdup(num); - } -} - -/* * Count and mark off the parameters in a multi-line macro call. * This is called both from within the multi-line macro expansion * code, and also to mark off the default parameters when provided * in a %macro definition line. */ -static void count_mmac_params (Token *t, int *nparam, Token ***params) { +static void count_mmac_params (Token *t, int *nparam, Token ***params) +{ int paramsize, brace; *nparam = paramsize = 0; @@ -916,14 +941,12 @@ static void count_mmac_params (Token *t, int *nparam, Token ***params) { paramsize += PARAM_DELTA; *params = nasm_realloc(*params, sizeof(**params) * paramsize); } - if (t && t->type == TOK_WHITESPACE) - t = t->next; + skip_white_(t); brace = FALSE; - if (t && t->type == TOK_OTHER && !strcmp(t->text, "{")) + if (tok_is_(t, "{")) brace = TRUE; (*params)[(*nparam)++] = t; - while (t && (t->type != TOK_OTHER || - strcmp(t->text, brace ? "}" : ","))) + while (tok_isnt_(t, brace ? "}" : ",")) t = t->next; if (t) { /* got a comma/brace */ t = t->next; @@ -932,21 +955,17 @@ static void count_mmac_params (Token *t, int *nparam, Token ***params) { * Now we've found the closing brace, look further * for the comma. */ - if (t && t->type == TOK_WHITESPACE) - t = t->next; - if (t && (t->type != TOK_OTHER || strcmp(t->text, ","))) { - error (ERR_NONFATAL|ERR_OFFBY1, + skip_white_(t); + if (tok_isnt_(t, ",")) { + error (ERR_NONFATAL, "braces do not enclose all of macro parameter"); - while (t && (t->type != TOK_OTHER || - strcmp(t->text, ","))) + while (tok_isnt_(t, ",")) t = t->next; } if (t) t = t->next; /* eat the comma */ } } - else /* got EOL */ - break; } } @@ -956,11 +975,12 @@ static void count_mmac_params (Token *t, int *nparam, Token ***params) { * * We must free the tline we get passed. */ -static int if_condition (Token *tline, int i) { - int j, casesense; - Token *t, *tt, **tptr, *origline; +static int if_condition (Token *tline, int i) +{ + int j, casesense; + Token * t, * tt, ** tptr, * origline; struct tokenval tokval; - expr *evalresult; + expr * evalresult; origline = tline; @@ -969,13 +989,12 @@ static int if_condition (Token *tline, int i) { case PP_IFNCTX: case PP_ELIFNCTX: j = FALSE; /* have we matched yet? */ if (!cstk) - error(ERR_FATAL|ERR_OFFBY1, + error(ERR_FATAL, "`%s': context stack is empty", directives[i]); else while (tline) { - if (tline->type == TOK_WHITESPACE) - tline = tline->next; + skip_white_(tline); if (!tline || tline->type != TOK_ID) { - error(ERR_NONFATAL|ERR_OFFBY1, + error(ERR_NONFATAL, "`%s' expects context identifiers", directives[i]); free_tlist (origline); return -1; @@ -993,18 +1012,17 @@ static int if_condition (Token *tline, int i) { case PP_IFNDEF: case PP_ELIFNDEF: j = FALSE; /* have we matched yet? */ while (tline) { - if (tline->type == TOK_WHITESPACE) - tline = tline->next; + skip_white_(tline); if (!tline || (tline->type != TOK_ID && (tline->type != TOK_PREPROC_ID || tline->text[1] != '$'))) { - error(ERR_NONFATAL|ERR_OFFBY1, + error(ERR_NONFATAL, "`%%if%sdef' expects macro identifiers", (i==PP_ELIFNDEF ? "n" : "")); free_tlist (origline); return -1; } - if (smacro_defined(tline->text, 0, NULL)) + if (smacro_defined(tline->text, 0, NULL, 1)) j = TRUE; tline = tline->next; } @@ -1017,7 +1035,7 @@ static int if_condition (Token *tline, int i) { case PP_IFIDNI: case PP_ELIFIDNI: case PP_IFNIDNI: case PP_ELIFNIDNI: tline = expand_smacro(tline); t = tt = tline; - while (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ","))) + while (tok_isnt_(tt, ",")) tt = tt->next; if (!tt) { error(ERR_NONFATAL, "`%s' expects two comma-separated arguments"); @@ -1054,7 +1072,8 @@ static int if_condition (Token *tline, int i) { } if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt) j = FALSE; /* trailing gunk on one end or other */ - if (i == PP_IFNIDN || i == PP_ELIFNIDN) + if (i == PP_IFNIDN || i == PP_ELIFNIDN || + i == PP_IFNIDNI || i == PP_ELIFNIDNI) j = !j; free_tlist (tline); return j; @@ -1064,10 +1083,10 @@ static int if_condition (Token *tline, int i) { case PP_IFSTR: case PP_ELIFSTR: case PP_IFNSTR: case PP_ELIFNSTR: tline = expand_smacro(tline); t = tline; - while (t && t->type == TOK_WHITESPACE) + while (tok_type_(t, TOK_WHITESPACE)) t = t->next; j = FALSE; /* placate optimiser */ - switch (i) { + if (t) switch (i) { case PP_IFID: case PP_ELIFID: case PP_IFNID: case PP_ELIFNID: j = (t->type == TOK_ID); break; @@ -1095,17 +1114,17 @@ static int if_condition (Token *tline, int i) { if (!evalresult) return -1; if (tokval.t_type) - error(ERR_WARNING|ERR_OFFBY1, + error(ERR_WARNING, "trailing garbage after expression ignored"); if (!is_simple(evalresult)) { - error(ERR_NONFATAL|ERR_OFFBY1, + error(ERR_NONFATAL, "non-constant value given to `%s'", directives[i]); return -1; } return reloc_value(evalresult) != 0; default: - error(ERR_FATAL|ERR_OFFBY1, + error(ERR_FATAL, "preprocessor directive `%s' not yet implemented", directives[i]); free_tlist (origline); @@ -1123,14 +1142,9 @@ static int if_condition (Token *tline, int i) { * Return values go like this: * * bit 0 is set if a directive was found (so the line gets freed) - * bit 1 is set if a blank line should be emitted - * bit 2 is set if a re-sync line number comment should be emitted - * - * (bits 1 and 2 are mutually exclusive in that the rest of the - * preprocessor doesn't guarantee to be able to handle the case in - * which both are set) */ -static int do_directive (Token *tline) { +static int do_directive (Token *tline) +{ int i, j, k, m, nparam, nolist; char *p, *mname; Include *inc; @@ -1145,9 +1159,8 @@ static int do_directive (Token *tline) { origline = tline; - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; - if (!tline || tline->type != TOK_PREPROC_ID || + skip_white_(tline); + if (!tok_type_(tline, TOK_PREPROC_ID) || (tline->text[1]=='%' || tline->text[1]=='$' || tline->text[1]=='!')) return 0; @@ -1190,21 +1203,26 @@ static int do_directive (Token *tline) { i != PP_IFNUM && i != PP_ELIFNUM && i != PP_IFSTR && i != PP_ELIFSTR && i != PP_ELSE && i != PP_ENDIF) + { return 0; + } /* * If we're defining a macro or reading a %rep block, we should * ignore all directives except for %macro/%imacro (which * generate an error), %endm/%endmacro, and (only if we're in a - * %rep block) %endrep. + * %rep block) %endrep. If we're in a %rep block, another %rep + * causes an error, so should be let through. */ if (defining && i != PP_MACRO && i != PP_IMACRO && i != PP_ENDMACRO && i != PP_ENDM && - (defining->name || i != PP_ENDREP)) + (defining->name || (i != PP_ENDREP && i != PP_REP))) + { return 0; + } if (j != -2) { - error(ERR_NONFATAL|ERR_OFFBY1, "unknown preprocessor directive `%s'", + error(ERR_NONFATAL, "unknown preprocessor directive `%s'", tline->text); return 0; /* didn't get it */ } @@ -1213,16 +1231,13 @@ static int do_directive (Token *tline) { case PP_CLEAR: if (tline->next) - error(ERR_WARNING|ERR_OFFBY1, + error(ERR_WARNING, "trailing garbage after `%%clear' ignored"); for (j=0; j<NHASH; j++) { while (mmacros[j]) { MMacro *m = mmacros[j]; - mmacros[j] = mmacros[j]->next; - nasm_free (m->name); - free_tlist (m->dlist); - free_llist (m->expansion); - nasm_free (m); + mmacros[j] = m->next; + free_mmacro(m); } while (smacros[j]) { SMacro *s = smacros[j]; @@ -1237,16 +1252,16 @@ static int do_directive (Token *tline) { case PP_INCLUDE: tline = tline->next; - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; + skip_white_(tline); if (!tline || (tline->type != TOK_STRING && - tline->type != TOK_INTERNAL_STRING)) { - error(ERR_NONFATAL|ERR_OFFBY1, "`%%include' expects a file name"); + tline->type != TOK_INTERNAL_STRING)) + { + error(ERR_NONFATAL, "`%%include' expects a file name"); free_tlist (origline); return 3; /* but we did _something_ */ } if (tline->next) - error(ERR_WARNING|ERR_OFFBY1, + error(ERR_WARNING, "trailing garbage after `%%include' ignored"); if (tline->type != TOK_INTERNAL_STRING) { p = tline->text+1; /* point past the quote to the name */ @@ -1257,28 +1272,27 @@ static int do_directive (Token *tline) { inc->next = istk; inc->conds = NULL; inc->fp = inc_fopen(p); - inc->fname = nasm_strdup(p); - inc->lineno = inc->lineinc = 1; + inc->fname = src_set_fname(nasm_strdup(p)); + inc->lineno = src_set_linnum(0); + inc->lineinc = 1; inc->expansion = NULL; inc->mstk = NULL; istk = inc; list->uplevel (LIST_INCLUDE); - update_fileline(3); /* update __FILE__ and __LINE__ */ free_tlist (origline); return 5; case PP_PUSH: tline = tline->next; - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; - if (!tline || tline->type != TOK_ID) { - error(ERR_NONFATAL|ERR_OFFBY1, + skip_white_(tline); + if (!tok_type_(tline, TOK_ID)) { + error(ERR_NONFATAL, "`%%push' expects a context identifier"); free_tlist (origline); return 3; /* but we did _something_ */ } if (tline->next) - error(ERR_WARNING|ERR_OFFBY1, + error(ERR_WARNING, "trailing garbage after `%%push' ignored"); ctx = nasm_malloc(sizeof(Context)); ctx->next = cstk; @@ -1291,19 +1305,18 @@ static int do_directive (Token *tline) { case PP_REPL: tline = tline->next; - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; - if (!tline || tline->type != TOK_ID) { - error(ERR_NONFATAL|ERR_OFFBY1, + skip_white_(tline); + if (!tok_type_(tline, TOK_ID)) { + error(ERR_NONFATAL, "`%%repl' expects a context identifier"); free_tlist (origline); return 3; /* but we did _something_ */ } if (tline->next) - error(ERR_WARNING|ERR_OFFBY1, + error(ERR_WARNING, "trailing garbage after `%%repl' ignored"); if (!cstk) - error(ERR_NONFATAL|ERR_OFFBY1, + error(ERR_NONFATAL, "`%%repl': context stack is empty"); else { nasm_free (cstk->name); @@ -1314,10 +1327,10 @@ static int do_directive (Token *tline) { case PP_POP: if (tline->next) - error(ERR_WARNING|ERR_OFFBY1, + error(ERR_WARNING, "trailing garbage after `%%pop' ignored"); if (!cstk) - error(ERR_NONFATAL|ERR_OFFBY1, + error(ERR_NONFATAL, "`%%pop': context stack is already empty"); else ctx_pop(); @@ -1325,21 +1338,18 @@ static int do_directive (Token *tline) { break; case PP_ERROR: + tline->next = expand_smacro (tline->next); tline = tline->next; - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; - if (!tline || tline->type != TOK_STRING) { - error(ERR_NONFATAL|ERR_OFFBY1, - "`%%error' expects an error string"); - free_tlist (origline); - return 3; /* but we did _something_ */ + skip_white_(tline); + if (tok_type_(tline, TOK_STRING)) { + p = tline->text+1; /* point past the quote to the name */ + p[strlen(p)-1] = '\0'; /* remove the trailing quote */ + error(ERR_NONFATAL, "user error: %s", p); + } else { + p = detoken(tline); + error(ERR_WARNING, "user error: %s", p); + nasm_free(p); } - if (tline->next) - error(ERR_WARNING|ERR_OFFBY1, - "trailing garbage after `%%error' ignored"); - p = tline->text+1; /* point past the quote to the name */ - p[strlen(p)-1] = '\0'; /* remove the trailing quote */ - error(ERR_NONFATAL|ERR_OFFBY1, "user error: %s", p); free_tlist (origline); break; @@ -1365,7 +1375,12 @@ static int do_directive (Token *tline) { tline->next = NULL; /* it got freed */ free_tlist (origline); if (j < 0) - return 3; + /* + * Bogus expression in %if, but we should pretend + * it was OK anyway, so that we don't get an error + * cascade on the subsequent %else / %endif. + */ + j = COND_NEVER; else j = j ? COND_IF_TRUE : COND_IF_FALSE; } @@ -1391,7 +1406,7 @@ static int do_directive (Token *tline) { case PP_ELIFNUM: case PP_ELIFSTR: if (!istk->conds) - error(ERR_FATAL|ERR_OFFBY1, "`%s': no matching `%%if'", + error(ERR_FATAL, "`%s': no matching `%%if'", directives[i]); if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER) istk->conds->state = COND_NEVER; @@ -1400,7 +1415,11 @@ static int do_directive (Token *tline) { tline->next = NULL; /* it got freed */ free_tlist (origline); if (j < 0) - return 3; + /* + * The expression was bogus, but let's make + * %endif not complain about missing %if + */ + j = COND_NEVER; else istk->conds->state = j ? COND_IF_TRUE : COND_IF_FALSE; } @@ -1408,10 +1427,10 @@ static int do_directive (Token *tline) { case PP_ELSE: if (tline->next) - error(ERR_WARNING|ERR_OFFBY1, + error(ERR_WARNING, "trailing garbage after `%%else' ignored"); if (!istk->conds) - error(ERR_FATAL|ERR_OFFBY1, + error(ERR_FATAL, "`%%else': no matching `%%if'"); if (emitting(istk->conds->state) || istk->conds->state == COND_NEVER) istk->conds->state = COND_ELSE_FALSE; @@ -1422,10 +1441,10 @@ static int do_directive (Token *tline) { case PP_ENDIF: if (tline->next) - error(ERR_WARNING|ERR_OFFBY1, + error(ERR_WARNING, "trailing garbage after `%%endif' ignored"); if (!istk->conds) - error(ERR_FATAL|ERR_OFFBY1, + error(ERR_FATAL, "`%%endif': no matching `%%if'"); cond = istk->conds; istk->conds = cond->next; @@ -1436,14 +1455,13 @@ static int do_directive (Token *tline) { case PP_MACRO: case PP_IMACRO: if (defining) - error (ERR_FATAL|ERR_OFFBY1, + error (ERR_FATAL, "`%%%smacro': already defining a macro", (i == PP_IMACRO ? "i" : "")); tline = tline->next; - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; - if (!tline || tline->type != TOK_ID) { - error (ERR_NONFATAL|ERR_OFFBY1, + skip_white_(tline); + if (!tok_type_(tline, TOK_ID)) { + error (ERR_NONFATAL, "`%%%smacro' expects a macro name", (i == PP_IMACRO ? "i" : "")); return 3; @@ -1455,10 +1473,9 @@ static int do_directive (Token *tline) { defining->nolist = FALSE; defining->in_progress = FALSE; tline = tline->next; - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; - if (!tline || tline->type != TOK_NUMBER) { - error (ERR_NONFATAL|ERR_OFFBY1, + skip_white_(tline); + if (!tok_type_(tline, TOK_NUMBER)) { + error (ERR_NONFATAL, "`%%%smacro' expects a parameter count", (i == PP_IMACRO ? "i" : "")); defining->nparam_min = defining->nparam_max = 0; @@ -1466,37 +1483,35 @@ static int do_directive (Token *tline) { defining->nparam_min = defining->nparam_max = readnum(tline->text, &j); if (j) - error (ERR_NONFATAL|ERR_OFFBY1, + error (ERR_NONFATAL, "unable to parse parameter count `%s'", tline->text); } - if (tline && tline->next && tline->next->type == TOK_OTHER && - !strcmp(tline->next->text, "-")) { + if (tline && tok_is_(tline->next, "-")) { tline = tline->next->next; - if (tline && tline->type == TOK_OTHER && - !strcmp(tline->text, "*")) + if (tok_is_(tline, "*")) defining->nparam_max = INT_MAX; - else if (!tline || tline->type != TOK_NUMBER) - error (ERR_NONFATAL|ERR_OFFBY1, + else if (!tok_type_(tline, TOK_NUMBER)) + error (ERR_NONFATAL, "`%%%smacro' expects a parameter count after `-'", (i == PP_IMACRO ? "i" : "")); else { defining->nparam_max = readnum(tline->text, &j); if (j) - error (ERR_NONFATAL|ERR_OFFBY1, + error (ERR_NONFATAL, "unable to parse parameter count `%s'", tline->text); if (defining->nparam_min > defining->nparam_max) - error (ERR_NONFATAL|ERR_OFFBY1, + error (ERR_NONFATAL, "minimum parameter count exceeds maximum"); } } - if (tline && tline->next && tline->next->type == TOK_OTHER && - !strcmp(tline->next->text, "+")) { + if (tline && tok_is_(tline->next, "+")) { tline = tline->next; defining->plus = TRUE; } - if (tline && tline->next && tline->next->type == TOK_ID && - !nasm_stricmp(tline->next->text, ".nolist")) { + if (tline && tok_type_(tline->next, TOK_ID) && + !nasm_stricmp(tline->next->text, ".nolist")) + { tline = tline->next; defining->nolist = TRUE; } @@ -1504,8 +1519,9 @@ static int do_directive (Token *tline) { while (mmac) { if (!strcmp(mmac->name, defining->name) && (mmac->nparam_min<=defining->nparam_max || defining->plus) && - (defining->nparam_min<=mmac->nparam_max || mmac->plus)) { - error (ERR_WARNING|ERR_OFFBY1, + (defining->nparam_min<=mmac->nparam_max || mmac->plus)) + { + error (ERR_WARNING, "redefining multi-line macro `%s'", defining->name); break; } @@ -1530,7 +1546,7 @@ static int do_directive (Token *tline) { case PP_ENDM: case PP_ENDMACRO: if (!defining) { - error (ERR_NONFATAL|ERR_OFFBY1, "`%s': not defining a macro", + error (ERR_NONFATAL, "`%s': not defining a macro", tline->text); return 3; } @@ -1555,10 +1571,10 @@ static int do_directive (Token *tline) { if (!evalresult) return 3; if (tokval.t_type) - error(ERR_WARNING|ERR_OFFBY1, + error(ERR_WARNING, "trailing garbage after expression ignored"); if (!is_simple(evalresult)) { - error(ERR_NONFATAL|ERR_OFFBY1, + error(ERR_NONFATAL, "non-constant value given to `%%rotate'"); return 3; } @@ -1566,7 +1582,7 @@ static int do_directive (Token *tline) { while (mmac && !mmac->name) /* avoid mistaking %reps for macros */ mmac = mmac->next_active; if (!mmac) - error(ERR_NONFATAL, "`%rotate' invoked outside a macro call"); + error(ERR_NONFATAL, "`%%rotate' invoked outside a macro call"); mmac->rotate = mmac->rotate + reloc_value(evalresult); if (mmac->rotate < 0) mmac->rotate = mmac->nparam - (-mmac->rotate) % mmac->nparam; @@ -1574,6 +1590,24 @@ static int do_directive (Token *tline) { return 1; case PP_REP: + if (defining) { + /* + * We don't allow nested %reps, because of a strange bug + * that was causing a panic. The cause of the bug appears to be + * that the nested %rep isn't taken into account when matching + * against the %endreps, so some mechanism to count the + * %reps in and the %endreps out may well work here. + * + * That's for experimentation with later, though. + * For informations sake, the panic produced by + * nesting %reps was: + * + * istk->mstk has no name but defining is set at end + * of expansion + */ + error(ERR_NONFATAL, "nested `%%rep' invocation not allowed"); + break; + } nolist = FALSE; tline = tline->next; if (tline->next && tline->next->type == TOK_WHITESPACE) @@ -1594,10 +1628,10 @@ static int do_directive (Token *tline) { if (!evalresult) return 3; if (tokval.t_type) - error(ERR_WARNING|ERR_OFFBY1, + error(ERR_WARNING, "trailing garbage after expression ignored"); if (!is_simple(evalresult)) { - error(ERR_NONFATAL|ERR_OFFBY1, + error(ERR_NONFATAL, "non-constant value given to `%%rep'"); return 3; } @@ -1608,13 +1642,15 @@ static int do_directive (Token *tline) { defining->nolist = nolist; defining->in_progress = reloc_value(evalresult) + 1; defining->nparam_min = defining->nparam_max = 0; + defining->defaults = NULL; + defining->dlist = NULL; defining->expansion = NULL; defining->next_active = istk->mstk; return 1; case PP_ENDREP: - if (!defining) { - error (ERR_NONFATAL|ERR_OFFBY1, + if (!defining || defining->name) { + error (ERR_NONFATAL, "`%%endrep': no matching `%%rep'"); return 3; } @@ -1641,7 +1677,7 @@ static int do_directive (Token *tline) { list->uplevel (defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO); defining = NULL; free_tlist (origline); - return 1; /* the expansion will line-sync */ + return 1; case PP_EXITREP: /* @@ -1653,22 +1689,21 @@ static int do_directive (Token *tline) { if (l->finishes && !l->finishes->name) break; - if (l->finishes && !l->finishes->name) + if (l) l->finishes->in_progress = 0; else error (ERR_NONFATAL, "`%%exitrep' not within `%%rep' block"); free_tlist (origline); - return 1; /* the end marker will line-sync */ + return 1; case PP_DEFINE: case PP_IDEFINE: tline = tline->next; - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; + skip_white_(tline); if (!tline || (tline->type != TOK_ID && (tline->type != TOK_PREPROC_ID || tline->text[1] != '$'))) { - error (ERR_NONFATAL|ERR_OFFBY1, + error (ERR_NONFATAL, "`%%%sdefine' expects a macro identifier", (i == PP_IDEFINE ? "i" : "")); free_tlist (origline); @@ -1691,23 +1726,22 @@ static int do_directive (Token *tline) { last = tline; param_start = tline = tline->next; nparam = 0; - if (tline && tline->type == TOK_OTHER && !strcmp(tline->text, "(")) { + if (tok_is_(tline, "(")) { /* * This macro has parameters. */ tline = tline->next; while (1) { - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; + skip_white_(tline); if (!tline) { - error (ERR_NONFATAL|ERR_OFFBY1, + error (ERR_NONFATAL, "parameter identifier expected"); free_tlist (origline); return 3; } if (tline->type != TOK_ID) { - error (ERR_NONFATAL|ERR_OFFBY1, + error (ERR_NONFATAL, "`%s': parameter identifier expected", tline->text); free_tlist (origline); @@ -1715,16 +1749,13 @@ static int do_directive (Token *tline) { } tline->type = TOK_SMAC_PARAM + nparam++; tline = tline->next; - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; - if (tline && tline->type == TOK_OTHER && - !strcmp(tline->text, ",")) { + skip_white_(tline); + if (tok_is_(tline, ",")) { tline = tline->next; continue; } - if (!tline || tline->type != TOK_OTHER || - strcmp(tline->text, ")")) { - error (ERR_NONFATAL|ERR_OFFBY1, + if (!tok_is_(tline, ")")) { + error (ERR_NONFATAL, "`)' expected to terminate macro template"); free_tlist (origline); return 3; @@ -1734,7 +1765,7 @@ static int do_directive (Token *tline) { last = tline; tline = tline->next; } - if (tline && tline->type == TOK_WHITESPACE) + if (tok_type_(tline, TOK_WHITESPACE)) last = tline, tline = tline->next; macro_start = NULL; last->next = NULL; @@ -1759,12 +1790,15 @@ static int do_directive (Token *tline) { * carefully re-terminated after chopping off the expansion * from the end). */ - if (smacro_defined (mname, nparam, &smac)) { - if (!smac) - error (ERR_WARNING|ERR_OFFBY1, + if (smacro_defined (mname, nparam, &smac, i==PP_DEFINE)) { + if (!smac) { + error (ERR_WARNING, "single-line macro `%s' defined both with and" " without parameters", mname); - else { + free_tlist (origline); + free_tlist (macro_start); + return 3; + } else { /* * We're redefining, so we have to take over an * existing SMacro structure. This means freeing @@ -1789,12 +1823,11 @@ static int do_directive (Token *tline) { case PP_ASSIGN: case PP_IASSIGN: tline = tline->next; - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; + skip_white_(tline); if (!tline || (tline->type != TOK_ID && (tline->type != TOK_PREPROC_ID || tline->text[1] != '$'))) { - error (ERR_NONFATAL|ERR_OFFBY1, + error (ERR_NONFATAL, "`%%%sassign' expects a macro identifier", (i == PP_IASSIGN ? "i" : "")); free_tlist (origline); @@ -1831,11 +1864,11 @@ static int do_directive (Token *tline) { } if (tokval.t_type) - error(ERR_WARNING|ERR_OFFBY1, + error(ERR_WARNING, "trailing garbage after expression ignored"); if (!is_simple(evalresult)) { - error(ERR_NONFATAL|ERR_OFFBY1, + error(ERR_NONFATAL, "non-constant value given to `%%%sassign'", (i == PP_IASSIGN ? "i" : "")); free_tlist (origline); @@ -1844,22 +1877,17 @@ static int do_directive (Token *tline) { macro_start = nasm_malloc(sizeof(*macro_start)); macro_start->next = NULL; - { - char numbuf[20]; - sprintf(numbuf, "%ld", reloc_value(evalresult)); - macro_start->text = nasm_strdup(numbuf); - } + make_tok_num(macro_start, reloc_value(evalresult)); macro_start->mac = NULL; - macro_start->type = TOK_NUMBER; /* * We now have a macro name, an implicit parameter count of * zero, and a numeric token to use as an expansion. Create * and store an SMacro. */ - if (smacro_defined (mname, 0, &smac)) { + if (smacro_defined (mname, 0, &smac, i==PP_ASSIGN)) { if (!smac) - error (ERR_WARNING|ERR_OFFBY1, + error (ERR_WARNING, "single-line macro `%s' defined both with and" " without parameters", mname); else { @@ -1871,7 +1899,8 @@ static int do_directive (Token *tline) { nasm_free (smac->name); free_tlist (smac->expansion); } - } else { + } + else { smac = nasm_malloc(sizeof(SMacro)); smac->next = *smhead; *smhead = smac; @@ -1889,20 +1918,19 @@ static int do_directive (Token *tline) { * Syntax is `%line nnn[+mmm] [filename]' */ tline = tline->next; - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; - if (!tline || tline->type != TOK_NUMBER) { - error (ERR_NONFATAL|ERR_OFFBY1, "`%%line' expects line number"); + skip_white_(tline); + if (!tok_type_(tline, TOK_NUMBER)) { + error (ERR_NONFATAL, "`%%line' expects line number"); free_tlist (origline); return 3; } k = readnum(tline->text, &j); m = 1; tline = tline->next; - if (tline && tline->type == TOK_OTHER && !strcmp(tline->text, "+")) { + if (tok_is_(tline, "+")) { tline = tline->next; - if (!tline || tline->type != TOK_NUMBER) { - error (ERR_NONFATAL|ERR_OFFBY1, + if (!tok_type_(tline, TOK_NUMBER)) { + error (ERR_NONFATAL, "`%%line' expects line increment"); free_tlist (origline); return 3; @@ -1910,21 +1938,17 @@ static int do_directive (Token *tline) { m = readnum(tline->text, &j); tline = tline->next; } - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; - istk->lineno = k; + skip_white_(tline); + src_set_linnum(k); istk->lineinc = m; - update_fileline(3); /* update __FILE__ and __LINE__ */ if (tline) { - char *s = detoken(tline); - nasm_free (istk->fname); - istk->fname = s; + nasm_free ( src_set_fname ( detoken(tline) ) ); } free_tlist (origline); return 5; default: - error(ERR_FATAL|ERR_OFFBY1, + error(ERR_FATAL, "preprocessor directive `%s' not yet implemented", directives[i]); break; @@ -1937,17 +1961,16 @@ static int do_directive (Token *tline) { * nothing else. Return the condition code index if so, or -1 * otherwise. */ -static int find_cc (Token *t) { +static int find_cc (Token *t) +{ Token *tt; int i, j, k, m; - if (t && t->type == TOK_WHITESPACE) - t = t->next; + skip_white_(t); if (t->type != TOK_ID) return -1; tt = t->next; - if (tt && tt->type == TOK_WHITESPACE) - tt = tt->next; + skip_white_(tt); if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ","))) return -1; @@ -1974,7 +1997,8 @@ static int find_cc (Token *t) { * Expand MMacro-local things: parameter references (%0, %n, %+n, * %-n) and MMacro-local identifiers (%%foo). */ -static Token *expand_mmac_params (Token *tline) { +static Token *expand_mmac_params (Token *tline) +{ Token *t, *tt, *ttt, **tail, *thead; tail = &thead; @@ -2012,9 +2036,7 @@ static Token *expand_mmac_params (Token *tline) { case '%': type = TOK_ID; sprintf(tmpbuf, "..@%lu.", mac->unique); - text = nasm_malloc(strlen(tmpbuf)+strlen(t->text+2)+1); - strcpy(text, tmpbuf); - strcat(text, t->text+2); + text = nasm_strcat(tmpbuf, t->text+2); break; case '-': n = atoi(t->text+2)-1; @@ -2027,14 +2049,14 @@ static Token *expand_mmac_params (Token *tline) { } cc = find_cc (tt); if (cc == -1) { - error (ERR_NONFATAL|ERR_OFFBY1, + error (ERR_NONFATAL, "macro parameter %d is not a condition code", n+1); text = NULL; } else { type = TOK_ID; if (inverse_ccs[cc] == -1) { - error (ERR_NONFATAL|ERR_OFFBY1, + error (ERR_NONFATAL, "condition code `%s' is not invertible", conditions[cc]); text = NULL; @@ -2053,7 +2075,7 @@ static Token *expand_mmac_params (Token *tline) { } cc = find_cc (tt); if (cc == -1) { - error (ERR_NONFATAL|ERR_OFFBY1, + error (ERR_NONFATAL, "macro parameter %d is not a condition code", n+1); text = NULL; @@ -2074,7 +2096,6 @@ static Token *expand_mmac_params (Token *tline) { if (tt) { for (i=0; i<mac->paramlen[n]; i++) { ttt = *tail = nasm_malloc(sizeof(Token)); - ttt->next = NULL; tail = &ttt->next; ttt->type = tt->type; ttt->text = nasm_strdup(tt->text); @@ -2086,10 +2107,10 @@ static Token *expand_mmac_params (Token *tline) { break; } nasm_free (t->text); - nasm_free (t); - if (text) { - t = *tail = nasm_malloc(sizeof(Token)); - t->next = NULL; + if (!text) { + nasm_free (t); + } else { + *tail = t; tail = &t->next; t->type = type; t->text = text; @@ -2100,10 +2121,42 @@ static Token *expand_mmac_params (Token *tline) { t = *tail = tline; tline = tline->next; t->mac = NULL; - t->next = NULL; tail = &t->next; } } + *tail = NULL; + t = thead; + for (; t && (tt=t->next)!=NULL ; t = t->next) + switch (t->type) { + case TOK_WHITESPACE: + if (tt->type == TOK_WHITESPACE) { + t->next = tt->next; + nasm_free(tt->text); + nasm_free(tt); + } + break; + case TOK_ID: + if (tt->type == TOK_ID || tt->type == TOK_NUMBER) { + char *tmp = nasm_strcat(t->text, tt->text); + nasm_free(t->text); + t->text = tmp; + t->next = tt->next; + nasm_free(tt->text); + nasm_free(tt); + } + break; + case TOK_NUMBER: + if (tt->type == TOK_NUMBER) { + char *tmp = nasm_strcat(t->text, tt->text); + nasm_free(t->text); + t->text = tmp; + t->next = tt->next; + nasm_free(tt->text); + nasm_free(tt); + } + break; + } + return thead; } @@ -2114,9 +2167,10 @@ static Token *expand_mmac_params (Token *tline) { * Tokens from input to output a lot of the time, rather than * actually bothering to destroy and replicate.) */ -static Token *expand_smacro (Token *tline) { +static Token *expand_smacro (Token *tline) +{ Token *t, *tt, *mstart, **tail, *thead; - SMacro *head, *m; + SMacro *head = NULL, *m; Token **params; int *paramsize; int nparam, sparam, brackets; @@ -2125,239 +2179,256 @@ static Token *expand_smacro (Token *tline) { tail = &thead; thead = NULL; - while (tline) { - while (tline && tline->type != TOK_ID && - (tline->type != TOK_PREPROC_ID || tline->text[1] != '$')) { - if (tline->type == TOK_SMAC_END) { - tline->mac->in_progress = FALSE; - t = tline; - tline = tline->next; - nasm_free (t); - } else { - t = *tail = tline; - tline = tline->next; - t->mac = NULL; - t->next = NULL; - tail = &t->next; - if (t->type == TOK_PS_OTHER) { - /* - * If we see a PS_OTHER, we must at the very - * least restore its correct token type. We - * should also check for a %$ token, since this - * is the point at which we expand context- - * local labels. - */ - t->type = TOK_ID; - if (t->text[0] == '%' && t->text[1] == '$') { - Context *c = get_ctx (t->text); - char *p, *q, buffer[40]; - - if (c) { - q = t->text+1; - q += strspn(q, "$"); - sprintf(buffer, "..@%lu.", c->number); - p = nasm_malloc (strlen(buffer)+strlen(q)+1); - strcpy (p, buffer); - strcat (p, q); - nasm_free (t->text); - t->text = p; - } - } - } - } - } - - if (!tline) - break; - /* - * We've hit an identifier. As in is_mmacro below, we first - * check whether the identifier is a single-line macro at - * all, then think about checking for parameters if - * necessary. - */ + while (tline) { /* main token loop */ + p = NULL; if (tline->type == TOK_ID) { head = smacros[hash(tline->text)]; p = tline->text; - } else { + } else if (tline->type == TOK_PREPROC_ID && tline->text[1] == '$') { Context *ctx = get_ctx (tline->text); if (ctx) { - p = tline->text+1; - p += strspn(p, "$"); head = ctx->localmac; - } else { - tline->type = TOK_OTHER; /* so it will get copied above */ - continue; + p = tline->text+2; + p += strspn(p, "$"); } } - for (m = head; m; m = m->next) - if (!mstrcmp(m->name, p, m->casesense)) - break; - if (!m || m->in_progress) { - /* - * Either we didn't find a macro, so this can't be a - * macro call, or we found a macro which was already in - * progress, in which case we don't _treat_ this as a - * macro call. Copy it through and ignore it. - */ - tline->type = TOK_PS_OTHER; /* so it will get copied above */ - continue; - } - mstart = tline; - if (m->nparam == 0) { - /* - * Simple case: the macro is parameterless. Discard the - * one token that the macro call took, and push the - * expansion back on the to-do stack. - */ - params = NULL; - paramsize = NULL; - } else { - /* - * Complicated case: at least one macro with this name - * exists and takes parameters. We must find the - * parameters in the call, count them, find the SMacro - * that corresponds to that form of the macro call, and - * substitute for the parameters when we expand. What a - * pain. - */ - nparam = sparam = 0; - params = NULL; - paramsize = NULL; - tline = tline->next; - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; - if (!tline || tline->type != TOK_OTHER || - strcmp(tline->text, "(")) { + if (p) { + /* + * We've hit an identifier. As in is_mmacro below, we first + * check whether the identifier is a single-line macro at + * all, then think about checking for parameters if + * necessary. + */ + for (m = head; m; m = m->next) + if (!mstrcmp(m->name, p, m->casesense)) + break; + if (m) { + mstart = tline; + params = NULL; + paramsize = NULL; + if (m->nparam == 0) { /* - * This macro wasn't called with parameters: ignore - * the call. (Behaviour borrowed from gnu cpp.) + * Simple case: the macro is parameterless. Discard the + * one token that the macro call took, and push the + * expansion back on the to-do stack. */ - tline = mstart; - tline->type = TOK_PS_OTHER; - continue; - } - tline = tline->next; - while (1) { - if (tline && tline->type == TOK_WHITESPACE) + if (!m->expansion) + { + if (!strcmp("__FILE__", m->name)) { + long num=0; + src_get(&num, &(tline->text)); + nasm_quote(&(tline->text)); + tline->type = TOK_STRING; + continue; + } + if (!strcmp("__LINE__", m->name)) { + nasm_free(tline->text); + make_tok_num(tline, src_get_linnum()); + continue; + } + t = tline; tline = tline->next; - if (!tline) { - error(ERR_NONFATAL|ERR_OFFBY1, - "macro call expects terminating `)'"); - break; + nasm_free (t->text); + nasm_free (t); + continue; } - if (nparam >= sparam) { - sparam += PARAM_DELTA; - params = nasm_realloc (params, sparam*sizeof(Token *)); - paramsize = nasm_realloc (paramsize, sparam*sizeof(int)); + } + else { + /* + * Complicated case: at least one macro with this name + * exists and takes parameters. We must find the + * parameters in the call, count them, find the SMacro + * that corresponds to that form of the macro call, and + * substitute for the parameters when we expand. What a + * pain. + */ + tline = tline->next; + skip_white_(tline); + if (!tok_is_(tline, "(")) { + /* + * This macro wasn't called with parameters: ignore + * the call. (Behaviour borrowed from gnu cpp.) + */ + tline = mstart; + m = NULL; + } + else { + int paren = 0; + int white = 0; + brackets = 0; + nparam = 0; + tline = tline->next; + sparam = PARAM_DELTA; + params = nasm_malloc (sparam*sizeof(Token *)); + params[0] = tline; + paramsize = nasm_malloc (sparam*sizeof(int)); + paramsize[0] = 0; + for (;;tline = tline->next) { /* parameter loop */ + if (!tline) { + error(ERR_NONFATAL, + "macro call expects terminating `)'"); + break; + } + if (tline->type == TOK_WHITESPACE && brackets<=0) { + if (paramsize[nparam]) + white++; + else + params[nparam] = tline->next; + continue; /* parameter loop */ + } + if (tline->type == TOK_OTHER && tline->text[1]==0) { + char ch = tline->text[0]; + if (ch == ',' && !paren && brackets<=0) { + if (++nparam >= sparam) { + sparam += PARAM_DELTA; + params = nasm_realloc (params, + sparam*sizeof(Token *)); + paramsize = nasm_realloc (paramsize, + sparam*sizeof(int)); + } + params[nparam] = tline->next; + paramsize[nparam] = 0; + white = 0; + continue; /* parameter loop */ + } + if (ch == br0 && + (brackets>0 || (brackets==0 && + !paramsize[nparam]))) + { + if (!(brackets++)) + { + params[nparam] = tline->next; + continue; /* parameter loop */ + } + } + if (ch == br2 && brackets>0) + if (--brackets == 0) { + brackets = -1; + continue; /* parameter loop */ + } + if (ch == '(' && !brackets) + paren++; + if (ch == ')' && brackets<=0) + if (--paren < 0) + break; + } + if (brackets<0) { + brackets = 0; + error (ERR_NONFATAL, "braces do not " + "enclose all of macro parameter"); + } + paramsize[nparam] += white+1; + white = 0; + } /* parameter loop */ + nparam++; + while (m && (m->nparam != nparam || + mstrcmp(m->name, p, m->casesense))) + m = m->next; + if (!m) + error (ERR_WARNING|ERR_WARN_MNP, + "macro `%s' exists, " + "but not taking %d parameters", + mstart->text, nparam); + } + } + if (m && m->in_progress) + m = NULL; + if (!m) /* in progess or didn't find '(' or wrong nparam */ + { + /* + * Design question: should we handle !tline, which + * indicates missing ')' here, or expand those + * macros anyway, which requires the (t) test a few + * lines down? + */ + nasm_free (params); + nasm_free (paramsize); + tline = mstart; + } + else { + /* + * Expand the macro: we are placed on the last token of the + * call, so that we can easily split the call from the + * following tokens. We also start by pushing an SMAC_END + * token for the cycle removal. + */ + t = tline; + if (t) { + tline = t->next; + t->next = NULL; } - params[nparam] = tline; - paramsize[nparam] = 0; - brackets = 0; - if (tline && tline->type == TOK_OTHER && - !strcmp(tline->text, "{")) { - params[nparam] = tline = tline->next; - while (tline && (brackets > 0 || - tline->type != TOK_OTHER || - strcmp(tline->text, "}"))) { - tline = tline->next; - paramsize[nparam]++; - } - tline = tline->next; - if (tline && tline->type == TOK_WHITESPACE) - tline = tline->next; - if (tline && (tline->type != TOK_OTHER || - (strcmp(tline->text, ")") && - strcmp(tline->text, ",")))) { - error (ERR_NONFATAL|ERR_OFFBY1, "braces do not " - "enclose all of macro parameter"); - } - if (tline && tline->type == TOK_OTHER && - !strcmp(tline->text, ",")) - tline = tline->next; - } else { - while (tline && (brackets > 0 || - tline->type != TOK_OTHER || - (strcmp(tline->text, ",") && - strcmp(tline->text, ")")))) { - if (tline->type == TOK_OTHER && !tline->text[1]) - brackets += (tline->text[0] == '(' ? 1 : - tline->text[0] == ')' ? -1 : 0); - tline = tline->next; - paramsize[nparam]++; + tt = nasm_malloc(sizeof(Token)); + tt->type = TOK_SMAC_END; + tt->text = NULL; + tt->mac = m; + m->in_progress = TRUE; + tt->next = tline; + tline = tt; + for (t = m->expansion; t; t = t->next) { + if (t->type >= TOK_SMAC_PARAM) { + Token *pcopy = tline, **ptail = &pcopy; + Token *ttt, *pt; + int i; + + ttt = params[t->type - TOK_SMAC_PARAM]; + for (i=paramsize[t->type-TOK_SMAC_PARAM]; --i>=0;) { + pt = *ptail = nasm_malloc(sizeof(Token)); + pt->next = tline; + ptail = &pt->next; + pt->text = nasm_strdup(ttt->text); + pt->type = ttt->type; + pt->mac = NULL; + ttt = ttt->next; + } + tline = pcopy; + } else { + tt = nasm_malloc(sizeof(Token)); + tt->type = t->type; + tt->text = nasm_strdup(t->text); + tt->mac = NULL; + tt->next = tline; + tline = tt; } } - nparam++; - if (tline && !strcmp(tline->text, ")")) - break; - if (tline && !strcmp(tline->text, ",")) - tline = tline->next; - } - while (m && m->nparam != nparam) { - while ( (m = m->next) ) - if (!strcmp(m->name, mstart->text)) - break; - } - if (!m) { - error (ERR_WARNING|ERR_OFFBY1|ERR_WARN_MNP, - "macro `%s' exists, but not taking %d parameters", - mstart->text, nparam); + + /* + * Having done that, get rid of the macro call, and clean + * up the parameters. + */ nasm_free (params); nasm_free (paramsize); - tline = mstart; - tline->type = TOK_PS_OTHER; - continue; + free_tlist (mstart); + continue; /* main token loop */ + } } } - /* - * Expand the macro: we are placed on the last token of the - * call, so that we can easily split the call from the - * following tokens. We also start by pushing an SMAC_END - * token for the cycle removal. - */ - t = tline; - tline = tline->next; - t->next = NULL; - tt = nasm_malloc(sizeof(Token)); - tt->type = TOK_SMAC_END; - tt->text = NULL; - tt->mac = m; - m->in_progress = TRUE; - tt->next = tline; - tline = tt; - for (t = m->expansion; t; t = t->next) { - if (t->type >= TOK_SMAC_PARAM) { - Token *pcopy = tline, **ptail = &pcopy; - Token *ttt, *pt; - int i; - - ttt = params[t->type - TOK_SMAC_PARAM]; - for (i=0; i<paramsize[t->type-TOK_SMAC_PARAM]; i++) { - pt = *ptail = nasm_malloc(sizeof(Token)); - pt->next = tline; - ptail = &pt->next; - pt->text = nasm_strdup(ttt->text); - pt->type = ttt->type; - pt->mac = NULL; - ttt = ttt->next; + + if (tline->type == TOK_SMAC_END) { + tline->mac->in_progress = FALSE; + t = tline; + tline = tline->next; + nasm_free (t); + } else { + t = *tail = tline; + tline = tline->next; + t->mac = NULL; + t->next = NULL; + tail = &t->next; + if (t->type == TOK_PREPROC_ID && t->text[1] == '$') { + Context *c = get_ctx (t->text); + char *p, *q, buffer[40]; + + t->type = TOK_ID; + if (c) { + q = t->text+1; + q += strspn(q, "$"); + sprintf(buffer, "..@%lu.", c->number); + p = nasm_strcat (buffer,q); + nasm_free (t->text); + t->text = p; } - tline = pcopy; - } else { - tt = nasm_malloc(sizeof(Token)); - tt->type = t->type; - tt->text = nasm_strdup(t->text); - tt->mac = NULL; - tt->next = tline; - tline = tt; } } - - /* - * Having done that, get rid of the macro call, and clean - * up the parameters. - */ - nasm_free (params); - nasm_free (paramsize); - free_tlist (mstart); } return thead; @@ -2371,7 +2442,8 @@ static Token *expand_smacro (Token *tline) { * to be called with tline->type == TOK_ID, so the putative macro * name is easy to find. */ -static MMacro *is_mmacro (Token *tline, Token ***params_array) { +static MMacro *is_mmacro (Token *tline, Token ***params_array) +{ MMacro *head, *m; Token **params; int nparam; @@ -2407,9 +2479,11 @@ static MMacro *is_mmacro (Token *tline, Token ***params_array) { * prohibits us using it before we actually celebrate... */ if (m->in_progress) { - error (ERR_NONFATAL|ERR_OFFBY1, +#if 0 + error (ERR_NONFATAL, "self-reference in multi-line macro `%s'", m->name); +#endif nasm_free (params); return NULL; } @@ -2456,7 +2530,7 @@ static MMacro *is_mmacro (Token *tline, Token ***params_array) { * After all that, we didn't find one with the right number of * parameters. Issue a warning, and fail to expand the macro. */ - error (ERR_WARNING|ERR_OFFBY1|ERR_WARN_MNP, + error (ERR_WARNING|ERR_WARN_MNP, "macro `%s' exists, but not taking %d parameters", tline->text, nparam); nasm_free (params); @@ -2466,62 +2540,54 @@ static MMacro *is_mmacro (Token *tline, Token ***params_array) { /* * Expand the multi-line macro call made by the given line, if * there is one to be expanded. If there is, push the expansion on - * istk->expansion and return 1 or 2, as according to whether a - * line sync is needed (2 if it is). Otherwise return 0. + * istk->expansion and return 1. Otherwise return 0. */ -static int expand_mmacro (Token *tline) { - Token *label = NULL, **params, *t, *tt, *last = NULL; - MMacro *m = NULL; +static int expand_mmacro (Token *tline) +{ + Token *startline = tline; + Token *label = NULL; + int dont_prepend = 0; + Token **params, *t, *tt; + MMacro *m; Line *l, *ll; int i, nparam, *paramlen; - int need_sync = FALSE; t = tline; - if (t && t->type == TOK_WHITESPACE) + skip_white_(t); + if (!tok_type_(t, TOK_ID)) + return 0; + m = is_mmacro (t, ¶ms); + if (!m) { + Token *last; + /* + * We have an id which isn't a macro call. We'll assume + * it might be a label; we'll also check to see if a + * colon follows it. Then, if there's another id after + * that lot, we'll check it again for macro-hood. + */ + label = last = t; t = t->next; - if (t && t->type == TOK_ID) { - m = is_mmacro (t, ¶ms); - if (!m) { - /* - * We have an id which isn't a macro call. We'll assume - * it might be a label; we'll also check to see if a - * colon follows it. Then, if there's another id after - * that lot, we'll check it again for macro-hood. - */ + if (tok_type_(t, TOK_WHITESPACE)) last = t, t = t->next; - if (t && t->type == TOK_WHITESPACE) - last = t, t = t->next; - if (t && t->type == TOK_OTHER && !strcmp(t->text, ":")) - last = t, t = t->next; - if (t && t->type == TOK_WHITESPACE) + if (tok_is_(t, ":")) { + dont_prepend = 1; + last = t, t = t->next; + if (tok_type_(t, TOK_WHITESPACE)) last = t, t = t->next; - if (t && t->type == TOK_ID) { - m = is_mmacro(t, ¶ms); - if (m) { - last->next = NULL; - label = tline; - tline = t; - } - } - } + } + if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, ¶ms)) == NULL) + return 0; + last->next = NULL; + tline = t; } - if (!m) - return 0; - - /* - * If we're not already inside another macro expansion, we'd - * better push a line synchronisation to ensure we stay put on - * line numbering. - */ - if (!istk->expansion) - need_sync = TRUE; /* * Fix up the parameters: this involves stripping leading and * trailing whitespace, then stripping braces if they are * present. */ - for (nparam = 0; params[nparam]; nparam++); + for (nparam = 0; params[nparam]; nparam++) + ; paramlen = nparam ? nasm_malloc(nparam*sizeof(*paramlen)) : NULL; for (i = 0; params[i]; i++) { @@ -2529,19 +2595,15 @@ static int expand_mmacro (Token *tline) { int comma = (!m->plus || i < nparam-1); t = params[i]; - if (t && t->type == TOK_WHITESPACE) - t = t->next; - if (t && t->type == TOK_OTHER && !strcmp(t->text, "{")) + skip_white_(t); + if (tok_is_(t, "{")) t = t->next, brace = TRUE, comma = FALSE; params[i] = t; paramlen[i] = 0; while (t) { - if (!t) /* end of param because EOL */ - break; if (comma && t->type == TOK_OTHER && !strcmp(t->text, ",")) break; /* ... because we have hit a comma */ - if (comma && t->type == TOK_WHITESPACE && - t->next->type == TOK_OTHER && !strcmp(t->next->text, ",")) + if (comma && t->type == TOK_WHITESPACE && tok_is_(t->next, ",")) break; /* ... or a space then a comma */ if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}")) break; /* ... or a brace */ @@ -2584,61 +2646,76 @@ static int expand_mmacro (Token *tline) { Token **tail; ll = nasm_malloc(sizeof(Line)); - ll->next = istk->expansion; ll->finishes = NULL; - ll->first = NULL; + ll->next = istk->expansion; + istk->expansion = ll; tail = &ll->first; for (t = l->first; t; t = t->next) { + Token *x = t; + if (t->type == TOK_PREPROC_ID && + t->text[1]=='0' && t->text[2]=='0') + { + dont_prepend = -1; + x = label; + if (!x) + continue; + } tt = *tail = nasm_malloc(sizeof(Token)); - tt->next = NULL; tail = &tt->next; - tt->type = t->type; - tt->text = nasm_strdup(t->text); + tt->type = x->type; + tt->text = nasm_strdup(x->text); tt->mac = NULL; } - - istk->expansion = ll; - + *tail = NULL; } /* - * If we had a label, push it on the front of the first line of - * the macro expansion. We must check that this doesn't give - * two consecutive TOK_WHITESPACE. + * If we had a label, push it on as the first line of + * the macro expansion. */ - if (label) { - if (last->type == TOK_WHITESPACE && - istk->expansion->first->type == TOK_WHITESPACE) { - Token *victim = istk->expansion->first; /* kill this whitespace */ - istk->expansion->first = victim->next; - nasm_free (victim->text); - nasm_free (victim); - } - last->next = istk->expansion->first; - istk->expansion->first = label; - } + if (label) + if (dont_prepend<0) + free_tlist(startline); + else { + ll = nasm_malloc(sizeof(Line)); + ll->finishes = NULL; + ll->next = istk->expansion; + istk->expansion = ll; + ll->first = startline; + if (!dont_prepend) { + while (label->next) + label = label->next; + label->next = tt = nasm_malloc(sizeof(Token)); + tt->next = NULL; + tt->mac = NULL; + tt->type = TOK_OTHER; + tt->text = nasm_strdup(":"); + } + } list->uplevel (m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO); - return need_sync ? 2 : 1; + return 1; } static void pp_reset (char *file, int apass, efunc errfunc, evalfunc eval, - ListGen *listgen) { + ListGen *listgen) +{ int h; error = errfunc; cstk = NULL; - linesync = outline = NULL; istk = nasm_malloc(sizeof(Include)); istk->next = NULL; istk->conds = NULL; istk->expansion = NULL; istk->mstk = NULL; istk->fp = fopen(file, "r"); - istk->fname = nasm_strdup(file); - istk->lineno = istk->lineinc = 1; + istk->fname = NULL; + src_set_fname(nasm_strdup(file)); + src_set_linnum(0); + istk->lineinc = 1; if (!istk->fp) error (ERR_FATAL|ERR_NOFILE, "unable to open input file `%s'", file); defining = NULL; @@ -2654,17 +2731,12 @@ static void pp_reset (char *file, int apass, efunc errfunc, evalfunc eval, pass = apass; } -static char *pp_getline (void) { +static char *pp_getline (void) +{ char *line; Token *tline; int ret; - if (outline) { - line = outline; - outline = NULL; - return line; - } - while (1) { /* * Fetch a tokenised line, either from the macro-expansion @@ -2712,7 +2784,6 @@ static char *pp_getline (void) { istk->expansion = ll; } - line_sync(); } else { /* * Check whether a `%rep' was started and not ended @@ -2733,62 +2804,68 @@ static char *pp_getline (void) { " expansion of macro `%s'", istk->mstk->name); } - if (istk->mstk->name) { - /* - * This was a real macro call, not a %rep, and - * therefore the parameter information needs to - * be freed. - */ - nasm_free(istk->mstk->params); - free_tlist(istk->mstk->iline); - nasm_free(istk->mstk->paramlen); + /* + * FIXME: investigate the relationship at this point between + * istk->mstk and l->finishes + */ + { + MMacro *m = istk->mstk; + istk->mstk = m->next_active; + if (m->name) { + /* + * This was a real macro call, not a %rep, and + * therefore the parameter information needs to + * be freed. + */ + nasm_free(m->params); + free_tlist(m->iline); + nasm_free(m->paramlen); + l->finishes->in_progress = FALSE; + } + else + free_mmacro(m); } - istk->mstk = istk->mstk->next_active; - l->finishes->in_progress = FALSE; istk->expansion = l->next; nasm_free (l); list->downlevel (LIST_MACRO); - if (!istk->expansion) - line_sync(); } } - if (istk->expansion) { - char *p; - Line *l = istk->expansion; - tline = l->first; - istk->expansion = l->next; - nasm_free (l); - p = detoken(tline); - list->line (LIST_MACRO, p); - nasm_free(p); - if (!istk->expansion) - line_sync(); - } else { + while (1) { /* until we get a line we can use */ + + if (istk->expansion) { /* from a macro expansion */ + char *p; + Line *l = istk->expansion; + tline = l->first; + istk->expansion = l->next; + nasm_free (l); + p = detoken(tline); + list->line (LIST_MACRO, p); + nasm_free(p); + break; + } line = read_line(); - while (!line) { - /* - * The current file has ended; work down the istk - * until we find a file we can read from. - */ - Include *i; - fclose(istk->fp); - if (istk->conds) + if (line) { /* from the current input file */ + line = prepreproc(line); + tline = tokenise(line); + nasm_free (line); + break; + } + /* + * The current file has ended; work down the istk + */ + { + Include *i = istk; + fclose(i->fp); + if (i->conds) error(ERR_FATAL, "expected `%%endif' before end of file"); - i = istk; - istk = istk->next; + istk = i->next; list->downlevel (LIST_INCLUDE); - nasm_free (i->fname); + src_set_linnum(i->lineno); + nasm_free ( src_set_fname(i->fname) ); nasm_free (i); if (!istk) return NULL; - else - line_sync(); - update_fileline(3); /* update __FILE__ and __LINE__ */ - line = read_line(); } - line = prepreproc(line); - tline = tokenise(line); - nasm_free (line); } /* @@ -2797,9 +2874,11 @@ static char *pp_getline (void) { * with things like `%define something %1' such as STRUC * uses. Unless we're _defining_ a MMacro, in which case * those tokens should be left alone to go into the - * definition. + * definition; and unless we're in a non-emitting + * condition, in which case we don't want to meddle with + * anything. */ - if (!defining) + if (!defining && !(istk->conds && !emitting(istk->conds->state))) tline = expand_mmac_params(tline); /* @@ -2807,20 +2886,11 @@ static char *pp_getline (void) { */ ret = do_directive(tline); if (ret & 1) { - if (ret & 4) - line_sync(); - if ((ret & 2) && !stdmacpos) {/* give a blank line to the output */ - outline = nasm_strdup(""); - break; - } - else continue; } else if (defining) { /* * We're defining a multi-line macro. We emit nothing - * at all, not even a blank line (when we finish - * defining the macro, we'll emit a line-number - * directive so that we keep sync properly), and just + * at all, and just * shove the tokenised line on to the macro definition. */ Line *l = nasm_malloc(sizeof(Line)); @@ -2858,54 +2928,32 @@ static char *pp_getline (void) { */ line = detoken(tline); free_tlist (tline); - outline = line; break; } else { - if (ret == 2) - line_sync(); continue; /* expand_mmacro calls free_tlist */ } } } - /* - * Once we're out of this loop, outline _must_ be non-NULL. The - * only question is whether linesync is NULL or not. - */ - if (linesync) { - line = linesync; - linesync = NULL; - } else { - line = outline; - outline = NULL; - } return line; } -static void pp_cleanup (void) { +static void pp_cleanup (void) +{ int h; if (defining) { error (ERR_NONFATAL, "end of file while still defining macro `%s'", defining->name); - nasm_free (defining->name); - free_tlist (defining->dlist); - free_llist (defining->expansion); - nasm_free (defining); + free_mmacro (defining); } - nasm_free (linesync); /* might just be necessary */ - nasm_free (outline); /* really shouldn't be necessary */ while (cstk) ctx_pop(); for (h=0; h<NHASH; h++) { while (mmacros[h]) { MMacro *m = mmacros[h]; mmacros[h] = mmacros[h]->next; - nasm_free (m->name); - free_tlist (m->dlist); - nasm_free (m->defaults); - free_llist (m->expansion); - nasm_free (m); + free_mmacro(m); } while (smacros[h]) { SMacro *s = smacros[h]; @@ -2926,7 +2974,8 @@ static void pp_cleanup (void) { ctx_pop(); } -void pp_include_path (char *path) { +void pp_include_path (char *path) +{ IncPath *i; i = nasm_malloc(sizeof(IncPath)); @@ -2936,7 +2985,8 @@ void pp_include_path (char *path) { ipath = i; } -void pp_pre_include (char *fname) { +void pp_pre_include (char *fname) +{ Token *inc, *space, *name; Line *l; @@ -2961,8 +3011,9 @@ void pp_pre_include (char *fname) { predef = l; } -void pp_pre_define (char *definition) { - Token *def, *space, *name; +void pp_pre_define (char *definition) +{ + Token *def, *space; Line *l; char *equals; @@ -2972,7 +3023,7 @@ void pp_pre_define (char *definition) { def->next = space = nasm_malloc(sizeof(Token)); if (equals) *equals = ' '; - space->next = name = tokenise(definition); + space->next = tokenise(definition); if (equals) *equals = '='; @@ -2990,10 +3041,19 @@ void pp_pre_define (char *definition) { predef = l; } -void pp_extra_stdmac (char **macros) { +void pp_extra_stdmac (char **macros) +{ extrastdmac = macros; } +static void make_tok_num(Token *tok, long val) +{ + char numbuf[20]; + sprintf(numbuf, "%ld", val); + tok->text = nasm_strdup(numbuf); + tok->type = TOK_NUMBER; +} + Preproc nasmpp = { pp_reset, pp_getline, |