📄 preproc.c
字号:
"`%s' expects a parameter count or nothing", directives[i]); } else { searching.nparam_min = searching.nparam_max = readnum(tline->text, &j); if (j) error(ERR_NONFATAL, "unable to parse parameter count `%s'", tline->text); } if (tline && tok_is_(tline->next, "-")) { tline = tline->next->next; if (tok_is_(tline, "*")) searching.nparam_max = INT_MAX; else if (!tok_type_(tline, TOK_NUMBER)) error(ERR_NONFATAL, "`%s' expects a parameter count after `-'", directives[i]); else { searching.nparam_max = readnum(tline->text, &j); if (j) error(ERR_NONFATAL, "unable to parse parameter count `%s'", tline->text); if (searching.nparam_min > searching.nparam_max) error(ERR_NONFATAL, "minimum parameter count exceeds maximum"); } } if (tline && tok_is_(tline->next, "+")) { tline = tline->next; searching.plus = TRUE; } mmac = mmacros[hash(searching.name)]; while (mmac) { if (!strcmp(mmac->name, searching.name) && (mmac->nparam_min <= searching.nparam_max || searching.plus) && (searching.nparam_min <= mmac->nparam_max || mmac->plus)) { found = TRUE; break; } mmac = mmac->next; } nasm_free(searching.name); free_tlist(origline); if (i == PP_IFNMACRO || i == PP_ELIFNMACRO) found = !found; return found; } case PP_IFID: case PP_ELIFID: case PP_IFNID: case PP_ELIFNID: case PP_IFNUM: case PP_ELIFNUM: case PP_IFNNUM: case PP_ELIFNNUM: case PP_IFSTR: case PP_ELIFSTR: case PP_IFNSTR: case PP_ELIFNSTR: tline = expand_smacro(tline); t = tline; while (tok_type_(t, TOK_WHITESPACE)) t = t->next; j = FALSE; /* placate optimiser */ if (t) switch (i) { case PP_IFID: case PP_ELIFID: case PP_IFNID: case PP_ELIFNID: j = (t->type == TOK_ID); break; case PP_IFNUM: case PP_ELIFNUM: case PP_IFNNUM: case PP_ELIFNNUM: j = (t->type == TOK_NUMBER); break; case PP_IFSTR: case PP_ELIFSTR: case PP_IFNSTR: case PP_ELIFNSTR: j = (t->type == TOK_STRING); break; } if (i == PP_IFNID || i == PP_ELIFNID || i == PP_IFNNUM || i == PP_ELIFNNUM || i == PP_IFNSTR || i == PP_ELIFNSTR) j = !j; free_tlist(tline); return j; case PP_IF: case PP_ELIF: t = tline = expand_smacro(tline); tptr = &t; tokval.t_type = TOKEN_INVALID; evalresult = evaluate(ppscan, tptr, &tokval, NULL, pass | CRITICAL, error, NULL); free_tlist(tline); if (!evalresult) return -1; if (tokval.t_type) error(ERR_WARNING, "trailing garbage after expression ignored"); if (!is_simple(evalresult)) { error(ERR_NONFATAL, "non-constant value given to `%s'", directives[i]); return -1; } return reloc_value(evalresult) != 0; default: error(ERR_FATAL, "preprocessor directive `%s' not yet implemented", directives[i]); free_tlist(origline); return -1; /* yeah, right */ }}/* * Expand macros in a string. Used in %error and %include directives. * First tokenise the string, apply "expand_smacro" and then de-tokenise back. * The returned variable should ALWAYS be freed after usage. */voidexpand_macros_in_string(char **p){ Token *line = tokenise(*p); line = expand_smacro(line); *p = detoken(line, FALSE);}/** * find and process preprocessor directive in passed line * Find out if a line contains a preprocessor directive, and deal * with it if so. * * If a directive _is_ found, it is the responsibility of this routine * (and not the caller) to free_tlist() the line. * * @param tline a pointer to the current tokeninzed line linked list * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND * */static intdo_directive(Token * tline){ int i, j, k, m, nparam, nolist; int offset; char *p, *mname; Include *inc; Context *ctx; Cond *cond; SMacro *smac, **smhead; MMacro *mmac; Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline; Line *l; struct tokenval tokval; expr *evalresult; MMacro *tmp_defining; /* Used when manipulating rep_nest */ origline = tline; skip_white_(tline); if (!tok_type_(tline, TOK_PREPROC_ID) || (tline->text[1] == '%' || tline->text[1] == '$' || tline->text[1] == '!')) return NO_DIRECTIVE_FOUND; i = -1; j = elements(directives); while (j - i > 1) { k = (j + i) / 2; m = nasm_stricmp(tline->text, directives[k]); if (m == 0) { if (tasm_compatible_mode) { i = k; j = -2; } else if (k != PP_ARG && k != PP_LOCAL && k != PP_STACKSIZE) { i = k; j = -2; } break; } else if (m < 0) { j = k; } else i = k; } /* * If we're in a non-emitting branch of a condition construct, * or walking to the end of an already terminated %rep block, * we should ignore all directives except for condition * directives. */ if (((istk->conds && !emitting(istk->conds->state)) || (istk->mstk && !istk->mstk->in_progress)) && !is_condition(i)) { return NO_DIRECTIVE_FOUND; } /* * 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. 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 && i != PP_REP))) { return NO_DIRECTIVE_FOUND; } if (j != -2) { error(ERR_NONFATAL, "unknown preprocessor directive `%s'", tline->text); return NO_DIRECTIVE_FOUND; /* didn't get it */ } switch (i) { case PP_STACKSIZE: /* Directive to tell NASM what the default stack size is. The * default is for a 16-bit stack, and this can be overriden with * %stacksize large. * the following form: * * ARG arg1:WORD, arg2:DWORD, arg4:QWORD */ tline = tline->next; if (tline && tline->type == TOK_WHITESPACE) tline = tline->next; if (!tline || tline->type != TOK_ID) { error(ERR_NONFATAL, "`%%stacksize' missing size parameter"); free_tlist(origline); return DIRECTIVE_FOUND; } if (nasm_stricmp(tline->text, "flat") == 0) { /* All subsequent ARG directives are for a 32-bit stack */ StackSize = 4; StackPointer = "ebp"; ArgOffset = 8; LocalOffset = 4; } else if (nasm_stricmp(tline->text, "large") == 0) { /* All subsequent ARG directives are for a 16-bit stack, * far function call. */ StackSize = 2; StackPointer = "bp"; ArgOffset = 4; LocalOffset = 2; } else if (nasm_stricmp(tline->text, "small") == 0) { /* All subsequent ARG directives are for a 16-bit stack, * far function call. We don't support near functions. */ StackSize = 2; StackPointer = "bp"; ArgOffset = 6; LocalOffset = 2; } else { error(ERR_NONFATAL, "`%%stacksize' invalid size type"); free_tlist(origline); return DIRECTIVE_FOUND; } free_tlist(origline); return DIRECTIVE_FOUND; case PP_ARG: /* TASM like ARG directive to define arguments to functions, in * the following form: * * ARG arg1:WORD, arg2:DWORD, arg4:QWORD */ offset = ArgOffset; do { char *arg, directive[256]; int size = StackSize; /* Find the argument name */ tline = tline->next; if (tline && tline->type == TOK_WHITESPACE) tline = tline->next; if (!tline || tline->type != TOK_ID) { error(ERR_NONFATAL, "`%%arg' missing argument parameter"); free_tlist(origline); return DIRECTIVE_FOUND; } arg = tline->text; /* Find the argument size type */ tline = tline->next; if (!tline || tline->type != TOK_OTHER || tline->text[0] != ':') { error(ERR_NONFATAL, "Syntax error processing `%%arg' directive"); free_tlist(origline); return DIRECTIVE_FOUND; } tline = tline->next; if (!tline || tline->type != TOK_ID) { error(ERR_NONFATAL, "`%%arg' missing size type parameter"); free_tlist(origline); return DIRECTIVE_FOUND; } /* Allow macro expansion of type parameter */ tt = tokenise(tline->text); tt = expand_smacro(tt); if (nasm_stricmp(tt->text, "byte") == 0) { size = MAX(StackSize, 1); } else if (nasm_stricmp(tt->text, "word") == 0) { size = MAX(StackSize, 2); } else if (nasm_stricmp(tt->text, "dword") == 0) { size = MAX(StackSize, 4); } else if (nasm_stricmp(tt->text, "qword") == 0) { size = MAX(StackSize, 8); } else if (nasm_stricmp(tt->text, "tword") == 0) { size = MAX(StackSize, 10); } else { error(ERR_NONFATAL, "Invalid size type for `%%arg' missing directive"); free_tlist(tt); free_tlist(origline); return DIRECTIVE_FOUND; } free_tlist(tt); /* Now define the macro for the argument */ sprintf(directive, "%%define %s (%s+%d)", arg, StackPointer, offset); do_directive(tokenise(directive)); offset += size; /* Move to the next argument in the list */ tline = tline->next; if (tline && tline->type == TOK_WHITESPACE) tline = tline->next; } while (tline && tline->type == TOK_OTHER && tline->text[0] == ','); free_tlist(origline); return DIRECTIVE_FOUND; case PP_LOCAL: /* TASM like LOCAL directive to define local variables for a * function, in the following form: * * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize * * The '= LocalSize' at the end is ignored by NASM, but is * required by TASM to define the local parameter size (and used * by the TASM macro package). */ offset = LocalOffset; do { char *local, directive[256]; int size = StackSize; /* Find the argument name */ tline = tline->next; if (tline && tline->type == TOK_WHITESPACE) tline = tline->next; if (!tline || tline->type != TOK_ID) { error(ERR_NONFATAL, "`%%local' missing argument parameter"); free_tlist(origline); return DIRECTIVE_FOUND; } local = tline->text; /* Find the argument size type */ tline = tline->next; if (!tline || tline->type != TOK_OTHER || tline->text[0] != ':') { error(ERR_NONFATAL, "Syntax error processing `%%local' directive"); free_tlist(origline); return DIRECTIVE_FOUND; } tline = tline->next; if (!tline || tline->type != TOK_ID) { error(ERR_NONFATAL, "`%%local' missing size type parameter"); free_tlist(origline); return DIRECTIVE_FOUND; } /* Allow macro expansion of type parameter */ tt = tokenise(tline->text); tt = expand_smacro(tt); if (nasm_stricmp(tt->text, "byte") == 0) { size = MAX(StackSize, 1); } else if (nasm_stricmp(tt->text, "word") == 0) { size = MAX(StackSize, 2); } else if (nasm_stricmp(tt->text, "dword") == 0) { size = MAX(StackSize, 4); } else if (nasm_stricmp(tt->text, "qword") == 0) { size = MAX(StackSize, 8); } else if (nasm_stricmp(tt->text, "tword") == 0) { size = MAX(StackSize, 10); } else { error(ERR_NONFATAL, "Invalid size type for `%%local' missing directive"); free_tlist(tt); free_tlist(origline); return DIRECTIVE_FOUND; } free_tlist(tt); /* Now define the macro for the argument */ sprintf(directive, "%%define %s (%s-%d)", local, StackPointer, offset); do_directive(tokenise(directive)); offset += size; /* Now define the assign to setup the enter_c macro correctly */ sprintf(directive, "%%assign %%$localsize %%$localsize+%d", size); do_directive(tokenise(directive)); /* Move to the next argument in the list */ tline = tline->next; if (tline && tline->type == TOK_WHITESPACE) tline = tline->next; } while (tline && tline->type == TOK_OTHER && tline->text[0] == ','); free_tlist(origline); return DIRECTIVE_FOUND; case PP_CLEAR: if (tline->next) error(ERR_WARNING, "trailing garbage after `%%clear' ignored"); for (j = 0; j < NHASH; j++) { while (mmacros[j]) { MMacro *m = mmacros[j]; mmacros[j] = m->next; free_mmacro(m); } while (smacros[j]) { SMacro *s = smacros[j]; smacros[j] = smacros[j]->next; nasm_free(s->name); free_tlist(s->expansion); nasm_free(s); } } free_tlist(origline); return DIRECTIVE_FOUND; case PP_INCLUDE: tline = tline->next; skip_white_(tline); if (!tline || (tline->type != TOK_STRING && tline->type != TOK_INTERNAL_STRING)) { error(ERR_NONFATAL, "`%%include' expects a file name"); free_tlist(origline); return DIRECTIVE_FOUND; /* but we did _something_ */ } if (tline->next)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -