📄 nasm.c
字号:
#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 + -