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

📄 nasm.c

📁 nasm早期的源代码,比较简单是学习汇编和编译原理的好例子
💻 C
📖 第 1 页 / 共 5 页
字号:
            *p++ = '\0';
        prevarg = arg;
        arg = q;
        if (process_arg(prevarg, arg))
            arg = NULL;
    }
    if (arg)
        process_arg(arg, NULL);
}

static void parse_cmdline(int argc, char **argv)
{
    FILE *rfile;
    char *envreal, *envcopy = NULL, *p, *arg;

    *inname = *outname = *listname = *errname = '\0';

    /*
     * First, process the NASMENV environment variable.
     */
    envreal = getenv("NASMENV");
    arg = NULL;
    if (envreal) {
        envcopy = nasm_strdup(envreal);
        process_args(envcopy);
        nasm_free(envcopy);
    }

    /*
     * Now process the actual command line.
     */
    while (--argc) {
        int i;
        argv++;
        if (argv[0][0] == '@') {
            /* We have a response file, so process this as a set of
             * arguments like the environment variable. This allows us
             * to have multiple arguments on a single line, which is
             * different to the -@resp file processing below for regular
             * NASM.
             */
            char *str = malloc(2048);
            FILE *f = fopen(&argv[0][1], "r");
            if (!str) {
                printf("out of memory");
                exit(-1);
            }
            if (f) {
                while (fgets(str, 2048, f)) {
                    process_args(str);
                }
                fclose(f);
            }
            free(str);
            argc--;
            argv++;
        }
        if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
	    p = get_param(argv[0], argc > 1 ? argv[1] : NULL, &i);
            if (p) {
		rfile = fopen(p, "r");
                if (rfile) {
                    process_respfile(rfile);
                    fclose(rfile);
                } else
                    report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
                                 "unable to open response file `%s'", p);
            }
        } else
            i = process_arg(argv[0], argc > 1 ? argv[1] : NULL);
        argv += i, argc -= i;
    }

    if (!*inname)
        report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
                     "no input file specified");

    /* Look for basic command line typos.  This definitely doesn't
       catch all errors, but it might help cases of fumbled fingers. */
    if (!strcmp(inname, errname) || !strcmp(inname, outname) ||
	!strcmp(inname, listname))
	report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
		     "file `%s' is both input and output file",
		     inname);

    if (*errname) {  
	error_file = fopen(errname, "w");
	if (!error_file) {
	    error_file = stderr;        /* Revert to default! */
	    report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
			 "cannot open file `%s' for error messages",
			 errname);
	}
    }
}

/* List of directives */
enum directives {
    D_NONE, D_ABSOLUTE, D_BITS, D_COMMON, D_CPU, D_DEBUG, D_DEFAULT,
    D_EXTERN, D_FLOAT, D_GLOBAL, D_LIST, D_SECTION, D_SEGMENT, D_WARNING
};
static const char *directives[] = {
    "", "absolute", "bits", "common", "cpu", "debug", "default",
    "extern", "float", "global", "list", "section", "segment", "warning"
};
static enum directives getkw(char **directive, char **value);

static void assemble_file(char *fname)
{
    char *directive, *value, *p, *q, *special, *line, debugid[80];
    insn output_ins;
    int i, validid;
    bool rn_error;
    int32_t seg, offs;
    struct tokenval tokval;
    expr *e;
    int pass, pass_max;
    int pass_cnt = 0;           /* count actual passes */

    if (cmd_sb == 32 && cmd_cpu < IF_386)
        report_error(ERR_FATAL, "command line: "
                     "32-bit segment size requires a higher cpu");

    pass_max = (optimizing > 0 ? optimizing : 0) + 2;   /* passes 1, optimizing, then 2 */
    pass0 = !(optimizing > 0);  /* start at 1 if not optimizing */
    for (pass = 1; pass <= pass_max && pass0 <= 2; pass++) {
        int pass1, pass2;
        ldfunc def_label;

        pass1 = pass < pass_max ? 1 : 2;        /* seq is 1, 1, 1,..., 1, 2 */
        pass2 = pass > 1 ? 2 : 1;       /* seq is 1, 2, 2,..., 2, 2 */
        /*      pass0                            seq is 0, 0, 0,..., 1, 2 */

        def_label = pass > 1 ? redefine_label : define_label;

        globalbits = sb = cmd_sb;   /* set 'bits' to command line default */
        cpu = cmd_cpu;
        if (pass0 == 2) {
            if (*listname)
                nasmlist.init(listname, report_error);
        }
        in_abs_seg = false;
        global_offset_changed = false;  /* set by redefine_label */
        location.segment = ofmt->section(NULL, pass2, &sb);
        globalbits = sb;
        if (pass > 1) {
            saa_rewind(forwrefs);
            forwref = saa_rstruct(forwrefs);
            raa_free(offsets);
            offsets = raa_init();
        }
        preproc->reset(fname, pass1, report_error, evaluate, &nasmlist);
        globallineno = 0;
        if (pass == 1)
            location.known = true;
        location.offset = offs = GET_CURR_OFFS;

        while ((line = preproc->getline())) {
	    enum directives d;
            globallineno++;

            /* here we parse our directives; this is not handled by the 'real'
             * parser. */
            directive = line;
	    d = getkw(&directive, &value);
            if (d) {
		int err = 0;

                switch (d) {
                case D_SEGMENT:		/* [SEGMENT n] */
		case D_SECTION:
                    seg = ofmt->section(value, pass2, &sb);
                    if (seg == NO_SEG) {
                        report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
                                     "segment name `%s' not recognized",
                                     value);
                    } else {
                        in_abs_seg = false;
                        location.segment = seg;
                    }
                    break;
                case D_EXTERN:		/* [EXTERN label:special] */
                    if (*value == '$')
                        value++;        /* skip initial $ if present */
                    if (pass0 == 2) {
                        q = value;
                        while (*q && *q != ':')
                            q++;
                        if (*q == ':') {
                            *q++ = '\0';
                            ofmt->symdef(value, 0L, 0L, 3, q);
                        }
                    } else if (pass == 1) {     /* pass == 1 */
                        q = value;
                        validid = true;
                        if (!isidstart(*q))
                            validid = false;
                        while (*q && *q != ':') {
                            if (!isidchar(*q))
                                validid = false;
                            q++;
                        }
                        if (!validid) {
                            report_error(ERR_NONFATAL,
                                         "identifier expected after EXTERN");
                            break;
                        }
                        if (*q == ':') {
                            *q++ = '\0';
                            special = q;
                        } else
                            special = NULL;
                        if (!is_extern(value)) {        /* allow re-EXTERN to be ignored */
                            int temp = pass0;
                            pass0 = 1;  /* fake pass 1 in labels.c */
                            declare_as_global(value, special,
                                              report_error);
                            define_label(value, seg_alloc(), 0L, NULL,
                                         false, true, ofmt, report_error);
                            pass0 = temp;
                        }
                    }           /* else  pass0 == 1 */
                    break;
                case D_BITS:		/* [BITS bits] */
                    globalbits = sb = get_bits(value);
                    break;
                case D_GLOBAL:		/* [GLOBAL symbol:special] */
                    if (*value == '$')
                        value++;        /* skip initial $ if present */
                    if (pass0 == 2) {   /* pass 2 */
                        q = value;
                        while (*q && *q != ':')
                            q++;
                        if (*q == ':') {
                            *q++ = '\0';
                            ofmt->symdef(value, 0L, 0L, 3, q);
                        }
                    } else if (pass2 == 1) {    /* pass == 1 */
                        q = value;
                        validid = true;
                        if (!isidstart(*q))
                            validid = false;
                        while (*q && *q != ':') {
                            if (!isidchar(*q))
                                validid = false;
                            q++;
                        }
                        if (!validid) {
                            report_error(ERR_NONFATAL,
                                         "identifier expected after GLOBAL");
                            break;
                        }
                        if (*q == ':') {
                            *q++ = '\0';
                            special = q;
                        } else
                            special = NULL;
                        declare_as_global(value, special, report_error);
                    }           /* pass == 1 */
                    break;
                case D_COMMON:		/* [COMMON symbol size:special] */
                    if (*value == '$')
                        value++;        /* skip initial $ if present */
                    if (pass0 == 1) {
                        p = value;
                        validid = true;
                        if (!isidstart(*p))
                            validid = false;
                        while (*p && !isspace(*p)) {
                            if (!isidchar(*p))
                                validid = false;
                            p++;
                        }
                        if (!validid) {
                            report_error(ERR_NONFATAL,
                                         "identifier expected after COMMON");
                            break;
                        }
                        if (*p) {
                            int64_t size;

                            while (*p && isspace(*p))
                                *p++ = '\0';
                            q = p;
                            while (*q && *q != ':')
                                q++;
                            if (*q == ':') {
                                *q++ = '\0';
                                special = q;
                            } else
                                special = NULL;
                            size = readnum(p, &rn_error);
                            if (rn_error)
                                report_error(ERR_NONFATAL,
                                             "invalid size specified"
                                             " in COMMON declaration");
                            else
                                define_common(value, seg_alloc(), size,
                                              special, ofmt, report_error);
                        } else
                            report_error(ERR_NONFATAL,
                                         "no size specified in"
                                         " COMMON declaration");
                    } else if (pass0 == 2) {    /* pass == 2 */
                        q = value;
                        while (*q && *q != ':') {
                            if (isspace(*q))
                                *q = '\0';
                            q++;
                        }
                        if (*q == ':') {
                            *q++ = '\0';
                            ofmt->symdef(value, 0L, 0L, 3, q);
                        }
                    }
                    break;
                case D_ABSOLUTE:		/* [ABSOLUTE address] */
                    stdscan_reset();
                    stdscan_bufptr = value;
                    tokval.t_type = TOKEN_INVALID;
                    e = evaluate(stdscan, NULL, &tokval, NULL, pass2,
                                 report_error, NULL);
                    if (e) {
                        if (!is_reloc(e))
                            report_error(pass0 ==
                                         1 ? ERR_NONFATAL : ERR_PANIC,
                                         "cannot use non-relocatable expression as "
                                         "ABSOLUTE address");
                        else {
                            abs_seg = reloc_seg(e);
                            abs_offset = reloc_value(e);
                        }
                    } else if (pass == 1)
                        abs_offset = 0x100;     /* don't go near zero in case of / */
                    else
                        report_error(ERR_PANIC, "invalid ABSOLUTE address "
                                     "in pass two");
                    in_abs_seg = true;
                    location.segment = NO_SEG;
                    break;
                case D_DEBUG:		/* [DEBUG] */
                    p = value;
                    q = debugid;
                    validid = true;
                    if (!isidstart(*p))
                        validid = false;
                    while (*p && !isspace(*p)) {
                        if (!isidchar(*p))
                            validid = false;
                        *q++ = *p++;
                    }
                    *q++ = 0;
                    if (!validid) {
                        report_error(pass == 1 ? ERR_NONFATAL : ERR_PANIC,
                                     "identifier expected after DEBUG");
                        break;
                    }
                    while (*p && isspace(*p))
                        p++;
                    if (pass == pass_max)
                        ofmt->current_dfmt->debug_directive(debugid, p);
                    break;
                case D_WARNING:		/* [WARNING {+|-}warn-name] */

⌨️ 快捷键说明

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