📄 nasm.c
字号:
suppressed[i] = (p[2] == '-');
else
report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
"invalid option to `-w'");
}
break;
case 'M':
operating_mode = op_depend;
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
strcpy(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 && isspace(p[-1]))
*--p = '\0';
p = buffer;
while (isspace(*p))
p++;
if (process_arg (prevarg, p))
*p = '\0';
if (strlen(p) > prevargsize-10) {
prevargsize += ARG_BUF_DELTA;
prevarg = nasm_realloc(prevarg, prevargsize);
}
strcpy (prevarg, p);
}
}
static void parse_cmdline(int argc, char **argv)
{
FILE *rfile;
char *envreal, *envcopy=NULL, *p, *q, *arg, *prevarg;
char separator = ' ';
*inname = *outname = *listname = '\0';
/*
* First, process the NASM environment variable.
*/
envreal = getenv("NASM");
arg = NULL;
if (envreal) {
envcopy = nasm_strdup(envreal);
p = envcopy;
if (*p && *p != '-')
separator = *p++;
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);
nasm_free (envcopy);
}
/*
* Now process the actual command line.
*/
while (--argc)
{
int i;
argv++;
if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
if ((p = get_param (argv[0], argc > 1 ? argv[1] : NULL, &i)))
if ((rfile = fopen(p, "r"))) {
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");
}
static void assemble_file (char *fname)
{
char * value, * p, * q, * special, * line, debugid[80];
insn output_ins;
int i, rn_error, validid;
long seg, offs;
struct tokenval tokval;
expr * e;
/*
* pass one
*/
pass = 1;
in_abs_seg = FALSE;
location.segment = ofmt->section(NULL, pass, &sb);
preproc->reset(fname, 1, report_error, evaluate, &nasmlist);
globallineno = 0;
location.known = TRUE;
location.offset = offs = get_curr_ofs;
while ( (line = preproc->getline()) )
{
globallineno++;
/* here we parse our directives; this is not handled by the 'real'
* parser. */
if ( (i = getkw (line, &value)) )
{
switch (i) {
case 1: /* [SEGMENT n] */
seg = ofmt->section (value, pass, &sb);
if (seg == NO_SEG) {
report_error (ERR_NONFATAL,
"segment name `%s' not recognised",
value);
} else {
in_abs_seg = FALSE;
location.segment = seg;
}
break;
case 2: /* [EXTERN label:special] */
if (*value == '$')
value++; /* skip initial $ if present */
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 */
declare_as_global (value, special, report_error);
define_label (value, seg_alloc(), 0L, NULL, FALSE, TRUE,
ofmt, report_error);
}
break;
case 3: /* [BITS bits] */
switch (atoi(value)) {
case 16:
case 32:
sb = atoi(value);
break;
default:
report_error(ERR_NONFATAL,
"`%s' is not a valid argument to [BITS]",
value);
break;
}
break;
case 4: /* [GLOBAL symbol:special] */
if (*value == '$')
value++; /* skip initial $ if present */
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);
break;
case 5: /* [COMMON symbol size:special] */
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) {
long 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");
break;
case 6: /* [ABSOLUTE address] */
stdscan_reset();
stdscan_bufptr = value;
tokval.t_type = TOKEN_INVALID;
e = evaluate(stdscan, NULL, &tokval, NULL, 1, report_error,
NULL);
if (e) {
if (!is_reloc(e))
report_error (ERR_NONFATAL, "cannot use non-"
"relocatable expression as ABSOLUTE"
" address");
else {
abs_seg = reloc_seg(e);
abs_offset = reloc_value(e);
}
} else
abs_offset = 0x100;/* don't go near zero in case of / */
in_abs_seg = TRUE;
location.segment = abs_seg;
break;
case 7:
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 DEBUG");
break;
}
while (*p && isspace(*p)) p++;
break;
default:
if (!ofmt->directive (line+1, value, 1))
report_error (ERR_NONFATAL, "unrecognised directive [%s]",
line+1);
break;
}
}
else /* it isn't a directive */
{
parse_line (1, line, &output_ins,
report_error, evaluate, define_label);
if (output_ins.forw_ref)
{
for(i = 0; i < output_ins.operands; i++)
{
if (output_ins.oprs[i].opflags & OPFLAG_FORWARD)
{
struct forwrefinfo *fwinf =
(struct forwrefinfo *)saa_wstruct(forwrefs);
fwinf->lineno = globallineno;
fwinf->operand = i;
}
}
}
if (output_ins.opcode == I_EQU)
{
/*
* Special `..' EQUs get processed in pass two,
* except `..@' macro-processor EQUs which are done
* in the normal place.
*/
if (!output_ins.label)
report_error (ERR_NONFATAL,
"EQU not preceded by label");
else if (output_ins.label[0] != '.' ||
output_ins.label[1] != '.' ||
output_ins.label[2] == '@')
{
if (output_ins.operands == 1 &&
(output_ins.oprs[0].type & IMMEDIATE) &&
output_ins.oprs[0].wrt == NO_SEG)
{
int isext = output_ins.oprs[0].opflags & OPFLAG_EXTERN;
define_label (output_ins.label,
output_ins.oprs[0].segment,
output_ins.oprs[0].offset,
NULL, FALSE, isext, ofmt, report_error);
}
else if (output_ins.operands == 2 &&
(output_ins.oprs[0].type & IMMEDIATE) &&
(output_ins.oprs[0].type & COLON) &&
output_ins.oprs[0].segment == NO_SEG &&
output_ins.oprs[0].wrt == NO_SEG &&
(output_ins.oprs[1].type & IMMEDIATE) &&
output_ins.oprs[1].segment == NO_SEG &&
output_ins.oprs[1].wrt == NO_SEG)
{
define_label (output_ins.label,
output_ins.oprs[0].offset | SEG_ABS,
output_ins.oprs[1].offset,
NULL, FALSE, FALSE, ofmt, report_error);
}
else
report_error(ERR_NONFATAL, "bad syntax for EQU");
}
}
else /* instruction isn't an EQU */
{
long l = insn_size (location.segment, offs, sb,
&output_ins, report_error);
if (using_debug_info && output_ins.opcode != -1) {
/* this is done here so we can do debug type info */
long typeinfo = TYS_ELEMENTS(output_ins.operands);
switch (output_ins.opcode) {
case I_RESB:
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_BYTE;
break;
case I_RESW:
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_WORD;
break;
case I_RESD:
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_DWORD;
break;
case I_RESQ:
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_QWORD;
break;
case I_REST:
typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_TBYTE;
break;
case I_DB:
typeinfo |= TY_BYTE;
break;
case I_DW:
typeinfo |= TY_WORD;
break;
case I_DD:
if (output_ins.eops_float)
typeinfo |= TY_FLOAT;
else
typeinfo |= TY_DWORD;
break;
case I_DQ:
typeinfo |= TY_QWORD;
break;
case I_DT:
typeinfo |= TY_TBYTE;
break;
default:
typeinfo = TY_LABEL;
}
ofmt->current_dfmt->debug_typevalue(typeinfo);
}
if (l != -1) {
offs += l;
set_curr_ofs (offs);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -