📄 nasm.c
字号:
preproc->cleanup(0);
if (ofile)
fclose(ofile);
if (ofile && terminate_after_phase)
remove(outname);
}
break;
case op_normal:
{
/*
* We must call ofmt->filename _anyway_, even if the user
* has specified their own output file, because some
* formats (eg OBJ and COFF) use ofmt->filename to find out
* the name of the input file and then put that inside the
* file.
*/
ofmt->filename(inname, outname, report_error);
ofile = fopen(outname, "wb");
if (!ofile) {
report_error(ERR_FATAL | ERR_NOFILE,
"unable to open output file `%s'", outname);
}
/*
* We must call init_labels() before ofmt->init() since
* some object formats will want to define labels in their
* init routines. (eg OS/2 defines the FLAT group)
*/
init_labels();
ofmt->init(ofile, report_error, define_label, evaluate);
assemble_file(inname, depend_ptr);
if (!terminate_after_phase) {
ofmt->cleanup(using_debug_info);
cleanup_labels();
} else {
/*
* Despite earlier comments, we need this fclose.
* The object output drivers only fclose on cleanup,
* and we just skipped that.
*/
fclose (ofile);
remove(outname);
if (listname[0])
remove(listname);
}
}
break;
}
if (depend_list)
emit_dependencies(depend_list);
if (want_usage)
usage();
raa_free(offsets);
saa_free(forwrefs);
eval_cleanup();
stdscan_cleanup();
if (terminate_after_phase)
return 1;
else
return 0;
}
/*
* Get a parameter for a command line option.
* First arg must be in the form of e.g. -f...
*/
static char *get_param(char *p, char *q, bool *advance)
{
*advance = false;
if (p[2]) { /* the parameter's in the option */
p += 2;
while (nasm_isspace(*p))
p++;
return p;
}
if (q && q[0]) {
*advance = true;
return q;
}
report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
"option `-%c' requires an argument", p[1]);
return NULL;
}
/*
* Copy a filename
*/
static void copy_filename(char *dst, const char *src)
{
size_t len = strlen(src);
if (len >= (size_t)FILENAME_MAX) {
report_error(ERR_FATAL | ERR_NOFILE, "file name too long");
return;
}
strncpy(dst, src, FILENAME_MAX);
}
/*
* Convert a string to Make-safe form
*/
static char *quote_for_make(const char *str)
{
const char *p;
char *os, *q;
size_t n = 1; /* Terminating zero */
size_t nbs = 0;
if (!str)
return NULL;
for (p = str; *p; p++) {
switch (*p) {
case ' ':
case '\t':
/* Convert N backslashes + ws -> 2N+1 backslashes + ws */
n += nbs + 2;
nbs = 0;
break;
case '$':
case '#':
nbs = 0;
n += 2;
break;
case '\\':
nbs++;
n++;
break;
default:
nbs = 0;
n++;
break;
}
}
/* Convert N backslashes at the end of filename to 2N backslashes */
if (nbs)
n += nbs;
os = q = nasm_malloc(n);
nbs = 0;
for (p = str; *p; p++) {
switch (*p) {
case ' ':
case '\t':
while (nbs--)
*q++ = '\\';
*q++ = '\\';
*q++ = *p;
break;
case '$':
*q++ = *p;
*q++ = *p;
nbs = 0;
break;
case '#':
*q++ = '\\';
*q++ = *p;
nbs = 0;
break;
case '\\':
*q++ = *p;
nbs++;
break;
default:
*q++ = *p;
nbs = 0;
break;
}
}
while (nbs--)
*q++ = '\\';
*q = '\0';
return os;
}
struct textargs {
const char *label;
int value;
};
#define OPT_PREFIX 0
#define OPT_POSTFIX 1
struct textargs textopts[] = {
{"prefix", OPT_PREFIX},
{"postfix", OPT_POSTFIX},
{NULL, 0}
};
static bool stopoptions = false;
static bool process_arg(char *p, char *q)
{
char *param;
int i;
bool advance = false;
bool do_warn;
if (!p || !p[0])
return false;
if (p[0] == '-' && !stopoptions) {
if (strchr("oOfpPdDiIlFXuUZwW", p[1])) {
/* These parameters take values */
if (!(param = get_param(p, q, &advance)))
return advance;
}
switch (p[1]) {
case 's':
error_file = stdout;
break;
case 'o': /* output file */
copy_filename(outname, param);
break;
case 'f': /* output format */
ofmt = ofmt_find(param);
if (!ofmt) {
report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
"unrecognised output format `%s' - "
"use -hf for a list", param);
} else {
ofmt->current_dfmt = ofmt->debug_formats[0];
}
break;
case 'O': /* Optimization level */
{
int opt;
if (!*param) {
/* Naked -O == -Ox */
optimizing = INT_MAX >> 1; /* Almost unlimited */
} else {
while (*param) {
switch (*param) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
opt = strtoul(param, ¶m, 10);
/* -O0 -> optimizing == -1, 0.98 behaviour */
/* -O1 -> optimizing == 0, 0.98.09 behaviour */
if (opt < 2)
optimizing = opt - 1;
else
optimizing = opt;
break;
case 'v':
case '+':
param++;
opt_verbose_info = true;
break;
case 'x':
param++;
optimizing = INT_MAX >> 1; /* Almost unlimited */
break;
default:
report_error(ERR_FATAL,
"unknown optimization option -O%c\n",
*param);
break;
}
}
}
break;
}
case 'p': /* pre-include */
case 'P':
pp_pre_include(param);
break;
case 'd': /* pre-define */
case 'D':
pp_pre_define(param);
break;
case 'u': /* un-define */
case 'U':
pp_pre_undefine(param);
break;
case 'i': /* include search path */
case 'I':
pp_include_path(param);
break;
case 'l': /* listing file */
copy_filename(listname, param);
break;
case 'Z': /* error messages file */
strcpy(errname, param);
break;
case 'F': /* specify debug format */
ofmt->current_dfmt = dfmt_find(ofmt, param);
if (!ofmt->current_dfmt) {
report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
"unrecognized debug format `%s' for"
" output format `%s'",
param, ofmt->shortname);
}
using_debug_info = true;
break;
case 'X': /* specify error reporting format */
if (nasm_stricmp("vc", param) == 0)
report_error = report_error_vc;
else if (nasm_stricmp("gnu", param) == 0)
report_error = report_error_gnu;
else
report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
"unrecognized error reporting format `%s'",
param);
break;
case 'g':
using_debug_info = true;
break;
case 'h':
printf
("usage: nasm [-@ response file] [-o outfile] [-f format] "
"[-l listfile]\n"
" [options...] [--] filename\n"
" or nasm -v for version info\n\n"
" -t assemble in SciTech TASM compatible mode\n"
" -g generate debug information in selected format.\n");
printf
(" -E (or -e) preprocess only (writes output to stdout by default)\n"
" -a don't preprocess (assemble only)\n"
" -M generate Makefile dependencies on stdout\n"
" -MG d:o, missing files assumed generated\n\n"
" -Z<file> redirect error messages to file\n"
" -s redirect error messages to stdout\n\n"
" -F format select a debugging format\n\n"
" -I<path> adds a pathname to the include file path\n");
printf
(" -O<digit> optimize branch offsets (-O0 disables, default)\n"
" -P<file> pre-includes a file\n"
" -D<macro>[=<value>] pre-defines a macro\n"
" -U<macro> undefines a macro\n"
" -X<format> specifies error reporting format (gnu or vc)\n"
" -w+foo enables warning foo (equiv. -Wfoo)\n"
" -w-foo disable warning foo (equiv. -Wno-foo)\n"
"Warnings:\n");
for (i = 0; i <= ERR_WARN_MAX; i++)
printf(" %-23s %s (default %s)\n",
warnings[i].name, warnings[i].help,
warnings[i].enabled ? "on" : "off");
printf
("\nresponse files should contain command line parameters"
", one per line.\n");
if (p[2] == 'f') {
printf("\nvalid output formats for -f are"
" (`*' denotes default):\n");
ofmt_list(ofmt, stdout);
} else {
printf("\nFor a list of valid output formats, use -hf.\n");
printf("For a list of debug formats, use -f <form> -y.\n");
}
exit(0); /* never need usage message here */
break;
case 'y':
printf("\nvalid debug formats for '%s' output format are"
" ('*' denotes default):\n", ofmt->shortname);
dfmt_list(ofmt, stdout);
exit(0);
break;
case 't':
tasm_compatible_mode = true;
break;
case 'v':
{
const char *nasm_version_string =
"NASM version " NASM_VER " compiled on " __DATE__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -