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

📄 preproc.c

📁 nasm的全套源代码,有些我做了些修改,以方便您更方便更容易调试成功,方便学习做编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
    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 */
            snprintf(directive, sizeof(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 */
            snprintf(directive, sizeof(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 */
            snprintf(directive, sizeof(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)
            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);
        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:
    case PP_IFCTX:
    case PP_IFDEF:
    case PP_IFID:
    case PP_IFIDN:
    case PP_IFIDNI:
    case PP_IFMACRO:
    case PP_IFNCTX:
    case PP_IFNDEF:
    case PP_IFNID:
    case PP_IFNIDN:
    case PP_IFNIDNI:
    case PP_IFNMACRO:
    case PP_IFNNUM:
    case PP_IFNSTR:
    case PP_IFNUM:
    case PP_IFSTR:
        if (istk->conds && !emitting(istk->conds->state))

⌨️ 快捷键说明

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