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

📄 nasm.c

📁 汇编编译器的最新版本的源码.买了自己动手写操作系统这本书的人一定要下
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifdef DEBUG
                    " with -DDEBUG"
#endif
                    ;
                puts(nasm_version_string);
                exit(0);        /* never need usage message here */
            }
            break;

        case 'e':              /* preprocess only */
	case 'E':
            operating_mode = op_preprocess;
            break;

        case 'a':              /* assemble only - don't preprocess */
            preproc = &no_pp;
            break;

	case 'W':
	    if (param[0] == 'n' && param[1] == 'o' && param[2] == '-') {
		do_warn = false;
		param += 3;
	    } else {
		do_warn = true;
	    }
	    goto set_warning;

        case 'w':
            if (param[0] != '+' && param[0] != '-') {
                report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
                             "invalid option to `-w'");
		break;
            }
	    do_warn = (param[0] == '+');
	    param++;
	    goto set_warning;
	set_warning:
	    for (i = 0; i <= ERR_WARN_MAX; i++)
		if (!nasm_stricmp(param, warnings[i].name))
		    break;
	    if (i <= ERR_WARN_MAX)
		warning_on[i] = do_warn;
	    else if (!nasm_stricmp(param, "all"))
		for (i = 1; i <= ERR_WARN_MAX; i++)
		    warning_on[i] = do_warn;
	    else if (!nasm_stricmp(param, "none"))
		for (i = 1; i <= ERR_WARN_MAX; i++)
		    warning_on[i] = !do_warn;
	    else
		report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
			     "invalid warning `%s'", param);
            break;

        case 'M':
	    switch (p[2]) {
	    case 0:
		operating_mode = op_depend;
		break;
	    case 'G':
		operating_mode = op_depend;
		depend_missing_ok = true;
		break;
	    case 'P':
		depend_emit_phony = true;
		break;
	    case 'D':
		depend_file = q;
		advance = true;
		break;
	    case 'T':
		depend_target = q;
		advance = true;
		break;
	    case 'Q':
		depend_target = quote_for_make(q);
		advance = true;
		break;
	    default:
		report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
			     "unknown dependency option `-M%c'", p[2]);
		break;
	    }
	    if (advance && (!q || !q[0])) {
		report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
			     "option `-M%c' requires a parameter", p[2]);
		break;
	    }
            break;

        case '-':
            {
                int s;

                if (p[2] == 0) {        /* -- => stop processing options */
                    stopoptions = 1;
                    break;
                }
                for (s = 0; textopts[s].label; s++) {
                    if (!nasm_stricmp(p + 2, textopts[s].label)) {
                        break;
                    }
                }

                switch (s) {

                case OPT_PREFIX:
                case OPT_POSTFIX:
                    {
                        if (!q) {
                            report_error(ERR_NONFATAL | ERR_NOFILE |
                                         ERR_USAGE,
                                         "option `--%s' requires an argument",
                                         p + 2);
                            break;
                        } else {
                            advance = 1, param = q;
                        }

                        if (s == OPT_PREFIX) {
                            strncpy(lprefix, param, PREFIX_MAX - 1);
                            lprefix[PREFIX_MAX - 1] = 0;
                            break;
                        }
                        if (s == OPT_POSTFIX) {
                            strncpy(lpostfix, param, POSTFIX_MAX - 1);
                            lpostfix[POSTFIX_MAX - 1] = 0;
                            break;
                        }
                        break;
                    }
                default:
                    {
                        report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
                                     "unrecognised option `--%s'", p + 2);
                        break;
                    }
                }
                break;
            }

        default:
            if (!ofmt->setinfo(GI_SWITCH, &p))
                report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
                             "unrecognised option `-%c'", p[1]);
            break;
        }
    } else {
        if (*inname) {
            report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
                         "more than one input file specified");
        } else {
            copy_filename(inname, p);
	}
    }

    return advance;
}

#define ARG_BUF_DELTA 128

static void process_respfile(FILE * rfile)
{
    char *buffer, *p, *q, *prevarg;
    int bufsize, prevargsize;

    bufsize = prevargsize = ARG_BUF_DELTA;
    buffer = nasm_malloc(ARG_BUF_DELTA);
    prevarg = nasm_malloc(ARG_BUF_DELTA);
    prevarg[0] = '\0';

    while (1) {                 /* Loop to handle all lines in file */
        p = buffer;
        while (1) {             /* Loop to handle long lines */
            q = fgets(p, bufsize - (p - buffer), rfile);
            if (!q)
                break;
            p += strlen(p);
            if (p > buffer && p[-1] == '\n')
                break;
            if (p - buffer > bufsize - 10) {
                int offset;
                offset = p - buffer;
                bufsize += ARG_BUF_DELTA;
                buffer = nasm_realloc(buffer, bufsize);
                p = buffer + offset;
            }
        }

        if (!q && p == buffer) {
            if (prevarg[0])
                process_arg(prevarg, NULL);
            nasm_free(buffer);
            nasm_free(prevarg);
            return;
        }

        /*
         * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
         * them are present at the end of the line.
         */
        *(p = &buffer[strcspn(buffer, "\r\n\032")]) = '\0';

        while (p > buffer && nasm_isspace(p[-1]))
            *--p = '\0';

        p = buffer;
        while (nasm_isspace(*p))
            p++;

        if (process_arg(prevarg, p))
            *p = '\0';

        if ((int) strlen(p) > prevargsize - 10) {
            prevargsize += ARG_BUF_DELTA;
            prevarg = nasm_realloc(prevarg, prevargsize);
        }
        strncpy(prevarg, p, prevargsize);
    }
}

/* Function to process args from a string of args, rather than the
 * argv array. Used by the environment variable and response file
 * processing.
 */
static void process_args(char *args)
{
    char *p, *q, *arg, *prevarg;
    char separator = ' ';

    p = args;
    if (*p && *p != '-')
        separator = *p++;
    arg = NULL;
    while (*p) {
        q = p;
        while (*p && *p != separator)
            p++;
        while (*p == separator)
            *p++ = '\0';
        prevarg = arg;
        arg = q;
        if (process_arg(prevarg, arg))
            arg = NULL;
    }
    if (arg)
        process_arg(arg, NULL);
}

static void process_response_file(const char *file)
{
    char str[2048];
    FILE *f = fopen(file, "r");
    if (!f) {
	perror(file);
	exit(-1);
    }
    while (fgets(str, sizeof str, f)) {
	process_args(str);
    }
    fclose(f);
}

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

    *inname = *outname = *listname = *errname = '\0';
    for (i = 0; i <= ERR_WARN_MAX; i++)
	warning_on_global[i] = warnings[i].enabled;

    /*
     * 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) {
	bool advance;
        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.
             */
	    process_response_file(argv[0]+1);
            argc--;
            argv++;
        }
        if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
	    p = get_param(argv[0], argc > 1 ? argv[1] : NULL, &advance);
            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
            advance = process_arg(argv[0], argc > 1 ? argv[1] : NULL);
        argv += advance, argc -= advance;
    }

    /* Look for basic command line typos.  This definitely doesn't
       catch all errors, but it might help cases of fumbled fingers. */
    if (!*inname)
        report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
                     "no input file specified");
    else if (!strcmp(inname, errname) ||
	     !strcmp(inname, outname) ||
	     !strcmp(inname, listname) ||
	     (depend_file && !strcmp(inname, depend_file)))
	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, StrList **depend_ptr)
{
    char *directive, *value, *p, *q, *special, *line, debugid[80];
    insn output_ins;
    int i, validid;
    bool rn_error;
    int32_t seg;
    int64_t offs;
    struct tokenval tokval;
    expr *e;
    int pass_max;

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

    pass_max = prev_offset_changed = (INT_MAX >> 1) + 2; /* Almost unlimited */
    for (passn = 1; pass0 <= 2; passn++) {
        int pass1, pass2;
        ldfunc def_label;

        pass1 = pass0 == 2 ? 2 : 1;	/* 1, 1, 1, ..., 1, 2 */
        pass2 = passn > 1  ? 2 : 1;     /* 1, 2, 2, ..., 2, 2 */
        /* pass0                           0, 0, 0, ..., 1, 2 */

        def_label = passn > 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 = 0;  /* set by redefine_label */
        location.segment = ofmt->section(NULL, pass2, &sb);
        globalbits = sb;
        if (passn > 1) {
            saa_rewind(forwrefs);
            forwref = saa_rstruct(forwrefs);
            raa_free(offsets);
            offsets = raa_init();
        }
        preproc->reset(fname, pass1, report_error, evaluate, &nasmlist,
		       pass1 == 2 ? depend_ptr : NULL);
        memcpy(warning_on, warning_on_global, (ERR_WARN_MAX+1) * sizeof(bool));

⌨️ 快捷键说明

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