⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 preproc.c

📁 nasm早期的源代码,比较简单是学习汇编和编译原理的好例子
💻 C
📖 第 1 页 / 共 5 页
字号:
    bool err;
    int nparam;
    bool nolist;
    bool casesense;
    int k, m;
    int offset;
    char *p, *mname;
    Include *inc;
    Context *ctx;
    Cond *cond;
    MMacro *mmac, **mmhead;
    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 */
    int64_t count;

    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 = pp_token_hash(tline->text);

    /*
     * 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;
    }

    switch (i) {
    case PP_INVALID:
        error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
              tline->text);
        return NO_DIRECTIVE_FOUND;      /* didn't get it */

    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 = tokenize(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 */
            snprintf(directive, sizeof(directive), "%%define %s (%s+%d)",
                     arg, StackPointer, offset);
            do_directive(tokenize(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 = tokenize(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 */
            snprintf(directive, sizeof(directive), "%%define %s (%s-%d)",
                     local, StackPointer, offset);
            do_directive(tokenize(directive));
            offset += size;

            /* Now define the assign to setup the enter_c macro correctly */
            snprintf(directive, sizeof(directive),
                     "%%assign %%$localsize %%$localsize+%d", size);
            do_directive(tokenize(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");
	free_macros();
	init_macros();
        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)
            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 */
            p[strlen(p) - 1] = '\0';    /* remove the trailing quote */
        } else
            p = tline->text;    /* internal_string is easier */
        expand_macros_in_string(&p);
        inc = nasm_malloc(sizeof(Include));
        inc->next = istk;
        inc->conds = NULL;
        inc->fp = inc_fopen(p);
	if (!inc->fp && pass == 0) {
	    /* -MG given but file not found */
	    nasm_free(inc);
	} else {
	    inc->fname = src_set_fname(p);
	    inc->lineno = src_set_linnum(0);
	    inc->lineinc = 1;
	    inc->expansion = NULL;
	    inc->mstk = NULL;
	    istk = inc;
	    list->uplevel(LIST_INCLUDE);
	}
	free_tlist(origline);
        return DIRECTIVE_FOUND;

    case PP_PUSH:
        tline = tline->next;
        skip_white_(tline);
        tline = expand_id(tline);
        if (!tok_type_(tline, TOK_ID)) {
            error(ERR_NONFATAL, "`%%push' expects a context identifier");
            free_tlist(origline);
            return DIRECTIVE_FOUND;     /* but we did _something_ */
        }
        if (tline->next)
            error(ERR_WARNING, "trailing garbage after `%%push' ignored");
        ctx = nasm_malloc(sizeof(Context));
        ctx->next = cstk;
        ctx->localmac = NULL;
        ctx->name = nasm_strdup(tline->text);
        ctx->number = unique++;
        cstk = ctx;
        free_tlist(origline);
        break;

    case PP_REPL:
        tline = tline->next;
        skip_white_(tline);
        tline = expand_id(tline);
        if (!tok_type_(tline, TOK_ID)) {
            error(ERR_NONFATAL, "`%%repl' expects a context identifier");
            free_tlist(origline);
            return DIRECTIVE_FOUND;     /* but we did _something_ */
        }
        if (tline->next)
            error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
        if (!cstk)
            error(ERR_NONFATAL, "`%%repl': context stack is empty");
        else {
            nasm_free(cstk->name);
            cstk->name = nasm_strdup(tline->text);
        }
        free_tlist(origline);
        break;

    case PP_POP:
        if (tline->next)
            error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
        if (!cstk)
            error(ERR_NONFATAL, "`%%pop': context stack is already empty");
        else
            ctx_pop();
        free_tlist(origline);
        break;

    case PP_ERROR:
        tline->next = expand_smacro(tline->next);
        tline = tline->next;
        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 */
            expand_macros_in_string(&p);
            error(ERR_NONFATAL, "%s", p);
            nasm_free(p);
        } else {
            p = detoken(tline, false);
            error(ERR_WARNING, "%s", p);
            nasm_free(p);
        }
        free_tlist(origline);
        break;

    CASE_PP_IF:
        if (istk->conds && !emitting(istk->conds->state))
            j = COND_NEVER;
        else {
            j = if_condition(tline->next, i);
            tline->next = NULL; /* it got freed */
            free_tlist(origline);
            j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
        }
        cond = nasm_malloc(sizeof(Cond));
        cond->next = istk->conds;
        cond->state = j;
        istk->conds = cond;
        return DIRECTIVE_FOUND;

    CASE_PP_ELIF:
        if (!istk->conds)
            error(ERR_FATAL, "`%s': no matching `%%if'", pp_directives[i]);
        if (emitting(istk->conds->state)
            || istk->conds->state == COND_NEVER)
            istk->conds->state = COND_NEVER;
        else {
            /*
             * IMPORTANT: In the case of %if, we will already have
             * called expand_mmac_params(); however, if we're
             * processing an %elif we must have been in a
             * non-emitting mode, which would have inhibited
             * the normal invocation of expand_mmac_params().  Therefore,
             * we have to do it explicitly here.
             */
            j = if_condition(expand_mmac_params(tline->next), i);
            tline->next = NULL; /* it got freed */
            free_tlist(origline);
            istk->conds->state =
                j < 0

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -