blob: 1404db15a23382b21cdfd4bbf8413aadf3f77923 [file] [log] [blame]
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001/* The Netwide Assembler main program module
2 *
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
7 */
8
9#include <stdio.h>
10#include <stdarg.h>
11#include <stdlib.h>
12#include <string.h>
13#include <ctype.h>
14
15#include "nasm.h"
16#include "nasmlib.h"
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000017#include "preproc.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000018#include "parser.h"
H. Peter Anvin76690a12002-04-30 20:52:49 +000019#include "eval.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000020#include "assemble.h"
21#include "labels.h"
22#include "outform.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000023#include "listing.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000024
H. Peter Anvineba20a72002-04-30 20:53:55 +000025struct forwrefinfo { /* info held on forward refs. */
26 int lineno;
27 int operand;
28};
29
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000030static void report_error (int, char *, ...);
31static void parse_cmdline (int, char **);
32static void assemble_file (char *);
33static int getkw (char *buf, char **value);
34static void register_output_formats(void);
35static void usage(void);
36
H. Peter Anvineba20a72002-04-30 20:53:55 +000037static int using_debug_info;
38
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000039static char inname[FILENAME_MAX];
40static char outname[FILENAME_MAX];
H. Peter Anvin6768eb72002-04-30 20:52:26 +000041static char listname[FILENAME_MAX];
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000042static int globallineno; /* for forward-reference tracking */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000043static int pass;
44static struct ofmt *ofmt = NULL;
45
46static FILE *ofile = NULL;
47static int sb = 16; /* by default */
48
H. Peter Anvineba20a72002-04-30 20:53:55 +000049static loc_t location;
50int in_abs_seg; /* Flag we are in ABSOLUTE seg */
51static long abs_seg;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000052
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000053static struct RAA *offsets;
54static long abs_offset;
H. Peter Anvinea838272002-04-30 20:51:53 +000055
56static struct SAA *forwrefs; /* keep track of forward references */
H. Peter Anvineba20a72002-04-30 20:53:55 +000057static struct forwrefinfo *forwref;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000058
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000059static Preproc *preproc;
60static int preprocess_only;
61
62/* used by error function to report location */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000063
64/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +000065 * Which of the suppressible warnings are suppressed. Entry zero
66 * doesn't do anything. Initial defaults are given here.
67 */
68static char suppressed[1+ERR_WARN_MAX] = {
H. Peter Anvineba20a72002-04-30 20:53:55 +000069 0, TRUE, TRUE, FALSE
H. Peter Anvin6768eb72002-04-30 20:52:26 +000070};
71
72/*
73 * The option names for the suppressible warnings. As before, entry
74 * zero does nothing.
75 */
76static char *suppressed_names[1+ERR_WARN_MAX] = {
H. Peter Anvin76690a12002-04-30 20:52:49 +000077 NULL, "macro-params", "orphan-labels", "number-overflow"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000078};
79
80/*
81 * The explanations for the suppressible warnings. As before, entry
82 * zero does nothing.
83 */
84static char *suppressed_what[1+ERR_WARN_MAX] = {
85 NULL, "macro calls with wrong no. of params",
H. Peter Anvin76690a12002-04-30 20:52:49 +000086 "labels alone on lines without trailing `:'",
87 "numeric constants greater than 0xFFFFFFFF"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000088};
89
90/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000091 * This is a null preprocessor which just copies lines from input
92 * to output. It's used when someone explicitly requests that NASM
93 * not preprocess their source file.
94 */
95
H. Peter Anvin76690a12002-04-30 20:52:49 +000096static void no_pp_reset (char *, int, efunc, evalfunc, ListGen *);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000097static char *no_pp_getline (void);
98static void no_pp_cleanup (void);
99static Preproc no_pp = {
100 no_pp_reset,
101 no_pp_getline,
102 no_pp_cleanup
103};
104
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000105/*
106 * get/set current offset...
107 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000108#define get_curr_ofs (in_abs_seg?abs_offset:\
109 raa_read(offsets,location.segment))
110#define set_curr_ofs(x) (in_abs_seg?(void)(abs_offset=(x)):\
111 (void)(offsets=raa_write(offsets,location.segment,(x))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000112
113static int want_usage;
114static int terminate_after_phase;
115
H. Peter Anvineba20a72002-04-30 20:53:55 +0000116static void nasm_fputs(char *line, FILE *ofile)
117{
118 if (ofile) {
119 fputs(line, ofile);
120 fputc('\n', ofile);
121 } else
122 puts(line);
123}
124
125int main(int argc, char **argv)
126{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000127 want_usage = terminate_after_phase = FALSE;
128
129 nasm_set_malloc_error (report_error);
130 offsets = raa_init();
H. Peter Anvineba20a72002-04-30 20:53:55 +0000131 forwrefs = saa_init ((long)sizeof(struct forwrefinfo));
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000132
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000133 preproc = &nasmpp;
134 preprocess_only = FALSE;
135
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000136 seg_init();
137
138 register_output_formats();
139
140 parse_cmdline(argc, argv);
141
H. Peter Anvineba20a72002-04-30 20:53:55 +0000142 if (terminate_after_phase)
143 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000144 if (want_usage)
145 usage();
146 return 1;
147 }
148
H. Peter Anvin76690a12002-04-30 20:52:49 +0000149 if (ofmt->stdmac)
150 pp_extra_stdmac (ofmt->stdmac);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000151 parser_global_info (ofmt, &location);
152 eval_global_info (ofmt, lookup_label, &location);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000153
H. Peter Anvineba20a72002-04-30 20:53:55 +0000154 if (preprocess_only)
155 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000156 char *line;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000157 char *file_name = NULL;
158 long prior_linnum=0;
159 int lineinc=0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000160
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000161 if (*outname) {
162 ofile = fopen(outname, "w");
163 if (!ofile)
164 report_error (ERR_FATAL | ERR_NOFILE,
165 "unable to open output file `%s'", outname);
166 } else
167 ofile = NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000168
H. Peter Anvineba20a72002-04-30 20:53:55 +0000169 location.known = FALSE;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000170
171 preproc->reset (inname, 2, report_error, evaluate, &nasmlist);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000172 while ( (line = preproc->getline()) ) {
H. Peter Anvin76690a12002-04-30 20:52:49 +0000173 /*
H. Peter Anvineba20a72002-04-30 20:53:55 +0000174 * We generate %line directives if needed for later programs
H. Peter Anvin76690a12002-04-30 20:52:49 +0000175 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000176 long linnum = prior_linnum += lineinc;
177 int altline = src_get(&linnum, &file_name);
178 if (altline) {
179 if (altline==1 && lineinc==1)
180 nasm_fputs("", ofile);
181 else {
182 lineinc = (altline != -1 || lineinc!=1);
183 fprintf(ofile ? ofile : stdout, "%%line %ld+%d %s\n",
184 linnum, lineinc, file_name);
185 }
186 prior_linnum = linnum;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000187 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000188 nasm_fputs(line, ofile);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000189 nasm_free (line);
190 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000191 nasm_free(file_name);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000192 preproc->cleanup();
193 if (ofile)
194 fclose(ofile);
195 if (ofile && terminate_after_phase)
196 remove(outname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000197 }
198 else /* NOT preprocess only */
199 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000200 /*
201 * We must call ofmt->filename _anyway_, even if the user
202 * has specified their own output file, because some
203 * formats (eg OBJ and COFF) use ofmt->filename to find out
204 * the name of the input file and then put that inside the
205 * file.
206 */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000207 ofmt->filename (inname, outname, report_error);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000208
209 ofile = fopen(outname, "wb");
210 if (!ofile) {
211 report_error (ERR_FATAL | ERR_NOFILE,
212 "unable to open output file `%s'", outname);
213 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000214
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000215 /*
216 * We must call init_labels() before ofmt->init() since
217 * some object formats will want to define labels in their
218 * init routines. (eg OS/2 defines the FLAT group)
219 */
220 init_labels ();
H. Peter Anvineba20a72002-04-30 20:53:55 +0000221
H. Peter Anvin76690a12002-04-30 20:52:49 +0000222 ofmt->init (ofile, report_error, define_label, evaluate);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000223
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000224 assemble_file (inname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000225
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000226 if (!terminate_after_phase) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000227 ofmt->cleanup (using_debug_info);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000228 cleanup_labels ();
229 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000230 else {
231
232 /*
233 * We had an fclose on the output file here, but we
234 * actually do that in all the object file drivers as well,
235 * so we're leaving out the one here.
236 * fclose (ofile);
237 */
238
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000239 remove(outname);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000240 if (listname[0])
241 remove(listname);
242 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000243 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000244
245 if (want_usage)
246 usage();
H. Peter Anvineba20a72002-04-30 20:53:55 +0000247
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000248 raa_free (offsets);
249 saa_free (forwrefs);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000250 eval_cleanup ();
251 nasmlib_cleanup ();
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000252
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000253 if (terminate_after_phase)
254 return 1;
255 else
256 return 0;
257}
258
H. Peter Anvineba20a72002-04-30 20:53:55 +0000259
260/*
261 * Get a parameter for a command line option.
262 * First arg must be in the form of e.g. -f...
263 */
264static char *get_param (char *p, char *q, int *advance)
265{
266 *advance = 0;
267 if (p[2]) /* the parameter's in the option */
268 {
269 p += 2;
270 while (isspace(*p))
271 p++;
272 return p;
273 }
274 if (q && q[0])
275 {
276 *advance = 1;
277 return q;
278 }
279 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
280 "option `-%c' requires an argument",
281 p[1]);
282 return NULL;
283}
284
285int stopoptions = 0;
286static int process_arg (char *p, char *q)
287{
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000288 char *param;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000289 int i, advance = 0;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000290
291 if (!p || !p[0])
292 return 0;
293
H. Peter Anvineba20a72002-04-30 20:53:55 +0000294 if (p[0]=='-' && ! stopoptions)
295 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000296 switch (p[1]) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000297 case '-': /* -- => stop processing options */
298 stopoptions = 1;
299 break;
300 case 's': /* silently ignored for compatibility */
301 break;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000302 case 'o': /* these parameters take values */
303 case 'f':
304 case 'p':
305 case 'd':
306 case 'i':
307 case 'l':
H. Peter Anvineba20a72002-04-30 20:53:55 +0000308 case 'F':
309 if ( !(param = get_param (p, q, &advance)) )
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000310 break;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000311 if (p[1]=='o') { /* output file */
312 strcpy (outname, param);
313 } else if (p[1]=='f') { /* output format */
314 ofmt = ofmt_find(param);
315 if (!ofmt) {
316 report_error (ERR_FATAL | ERR_NOFILE | ERR_USAGE,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000317 "unrecognised output format `%s' - "
318 "use -hf for a list",
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000319 param);
320 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000321 else
322 ofmt->current_dfmt = ofmt->debug_formats[0];
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000323 } else if (p[1]=='p') { /* pre-include */
324 pp_pre_include (param);
325 } else if (p[1]=='d') { /* pre-define */
326 pp_pre_define (param);
327 } else if (p[1]=='i') { /* include search path */
328 pp_include_path (param);
329 } else if (p[1]=='l') { /* listing file */
330 strcpy (listname, param);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000331 } else if (p[1] == 'F') { /* specify debug format */
332 ofmt->current_dfmt = dfmt_find(ofmt, param);
333 if (!ofmt->current_dfmt) {
334 report_error (ERR_FATAL | ERR_NOFILE | ERR_USAGE,
335 "unrecognized debug format `%s' for"
336 " output format `%s'",
337 param, ofmt->shortname);
338 }
339 }
340 break;
341 case 'g':
342 using_debug_info = TRUE;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000343 break;
344 case 'h':
H. Peter Anvineba20a72002-04-30 20:53:55 +0000345 printf("usage: nasm [-@ response file] [-o outfile] [-f format] "
346 "[-l listfile]\n"
347 " [options...] [--] filename\n");
348 printf(" or nasm -r for version info\n\n");
349 printf(" -e preprocess only (writes output to "
350 "stdout by default)\n"
351 " -a don't preprocess\n\n");
352 printf(" -g enable debug info\n"
353 " -F format select a debugging format\n\n");
354 printf(" -i<path> adds a pathname to the include file path\n"
355 " -p<file> pre-includes a file\n"
356 " -d<macro>[=<value>] pre-defines a macro\n");
357 printf(" -w+foo enables warnings about foo; "
358 "-w-foo disables them\n where foo can be:\n");
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000359 for (i=1; i<=ERR_WARN_MAX; i++)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000360 printf(" %-16s%s (default %s)\n",
361 suppressed_names[i], suppressed_what[i],
362 suppressed[i] ? "off" : "on");
363 printf ("\nresponse files should contain command line parameters"
364 ", one per line.\n");
365 if (p[2] == 'f') {
366 printf("\nvalid output formats for -f are"
367 " (`*' denotes default):\n");
368 ofmt_list(ofmt, stdout);
369 }
370 else {
371 printf ("\nFor a list of valid output formats, use -hf.\n");
372 printf ("For a list of debug formats, use -f <form> -y.\n");
373 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000374 exit (0); /* never need usage message here */
375 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000376 case 'y':
377 printf("\nvalid debug formats for '%s' output format are"
378 " ('*' denotes default):\n",
379 ofmt->shortname);
380 dfmt_list(ofmt, stdout);
381 exit(0);
382 break;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000383 case 'r':
H. Peter Anvineba20a72002-04-30 20:53:55 +0000384 printf("NASM version %s\n", NASM_VER);
385#ifdef DEBUG
386 printf("Compiled with -DDEBUG on " __DATE__ "\n");
387#endif
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000388 exit (0); /* never need usage message here */
389 break;
390 case 'e': /* preprocess only */
391 preprocess_only = TRUE;
392 break;
393 case 'a': /* assemble only - don't preprocess */
394 preproc = &no_pp;
395 break;
396 case 'w':
397 if (p[2] != '+' && p[2] != '-') {
398 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
399 "invalid option to `-w'");
400 } else {
401 for (i=1; i<=ERR_WARN_MAX; i++)
402 if (!nasm_stricmp(p+3, suppressed_names[i]))
403 break;
404 if (i <= ERR_WARN_MAX)
405 suppressed[i] = (p[2] == '-');
406 else
407 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
408 "invalid option to `-w'");
409 }
410 break;
411 default:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000412 if (!ofmt->setinfo(GI_SWITCH,&p))
413 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000414 "unrecognised option `-%c'",
415 p[1]);
416 break;
417 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000418 }
419 else
420 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000421 if (*inname) {
422 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
423 "more than one input file specified");
424 } else
425 strcpy(inname, p);
426 }
427
428 return advance;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000429}
430
H. Peter Anvineba20a72002-04-30 20:53:55 +0000431#define ARG_BUF_DELTA 128
432
433static void process_respfile (FILE *rfile)
434{
435 char *buffer, *p, *q, *prevarg;
436 int bufsize, prevargsize;
437
438 bufsize = prevargsize = ARG_BUF_DELTA;
439 buffer = nasm_malloc(ARG_BUF_DELTA);
440 prevarg = nasm_malloc(ARG_BUF_DELTA);
441 prevarg[0] = '\0';
442
443 while (1) { /* Loop to handle all lines in file */
444
445 p = buffer;
446 while (1) { /* Loop to handle long lines */
447 q = fgets(p, bufsize-(p-buffer), rfile);
448 if (!q)
449 break;
450 p += strlen(p);
451 if (p > buffer && p[-1] == '\n')
452 break;
453 if (p-buffer > bufsize-10) {
454 int offset;
455 offset = p - buffer;
456 bufsize += ARG_BUF_DELTA;
457 buffer = nasm_realloc(buffer, bufsize);
458 p = buffer + offset;
459 }
460 }
461
462 if (!q && p == buffer) {
463 if (prevarg[0])
464 process_arg (prevarg, NULL);
465 nasm_free (buffer);
466 nasm_free (prevarg);
467 return;
468 }
469
470 /*
471 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
472 * them are present at the end of the line.
473 */
474 *(p = &buffer[strcspn(buffer, "\r\n\032")]) = '\0';
475
476 while (p > buffer && isspace(p[-1]))
477 *--p = '\0';
478
479 p = buffer;
480 while (isspace(*p))
481 p++;
482
483 if (process_arg (prevarg, p))
484 *p = '\0';
485
486 if (strlen(p) > prevargsize-10) {
487 prevargsize += ARG_BUF_DELTA;
488 prevarg = nasm_realloc(prevarg, prevargsize);
489 }
490 strcpy (prevarg, p);
491 }
492}
493
494static void parse_cmdline(int argc, char **argv)
495{
496 FILE *rfile;
497 char *envreal, *envcopy=NULL, *p, *q, *arg, *prevarg;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000498 char separator = ' ';
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000499
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000500 *inname = *outname = *listname = '\0';
501
502 /*
503 * First, process the NASM environment variable.
504 */
505 envreal = getenv("NASM");
506 arg = NULL;
507 if (envreal) {
508 envcopy = nasm_strdup(envreal);
509 p = envcopy;
510 if (*p && *p != '-')
511 separator = *p++;
512 while (*p) {
513 q = p;
514 while (*p && *p != separator) p++;
515 while (*p == separator) *p++ = '\0';
516 prevarg = arg;
517 arg = q;
518 if (process_arg (prevarg, arg))
519 arg = NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000520 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000521 if (arg)
522 process_arg (arg, NULL);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000523 nasm_free (envcopy);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000524 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000525
526 /*
527 * Now process the actual command line.
528 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000529 while (--argc)
530 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000531 int i;
532 argv++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000533 if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
534 if ((p = get_param (argv[0], argc > 1 ? argv[1] : NULL, &i)))
535 if ((rfile = fopen(p, "r"))) {
536 process_respfile (rfile);
537 fclose(rfile);
538 } else
539 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
540 "unable to open response file `%s'", p);
541 } else
542 i = process_arg (argv[0], argc > 1 ? argv[1] : NULL);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000543 argv += i, argc -= i;
544 }
545
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000546 if (!*inname)
547 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
548 "no input file specified");
549}
550
H. Peter Anvineba20a72002-04-30 20:53:55 +0000551static void assemble_file (char *fname)
552{
553 char * value, * p, * q, * special, * line, debugid[80];
554 insn output_ins;
555 int i, rn_error, validid;
556 long seg, offs;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000557 struct tokenval tokval;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000558 expr * e;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000559
H. Peter Anvineba20a72002-04-30 20:53:55 +0000560 /*
561 * pass one
562 */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000563 pass = 1;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000564 in_abs_seg = FALSE;
565 location.segment = ofmt->section(NULL, pass, &sb);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000566 preproc->reset(fname, 1, report_error, evaluate, &nasmlist);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000567 globallineno = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000568 location.known = TRUE;
569 location.offset = offs = get_curr_ofs;
570
571 while ( (line = preproc->getline()) )
572 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000573 globallineno++;
574
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000575 /* here we parse our directives; this is not handled by the 'real'
576 * parser. */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000577 if ( (i = getkw (line, &value)) )
578 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000579 switch (i) {
580 case 1: /* [SEGMENT n] */
581 seg = ofmt->section (value, pass, &sb);
582 if (seg == NO_SEG) {
583 report_error (ERR_NONFATAL,
584 "segment name `%s' not recognised",
585 value);
586 } else {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000587 in_abs_seg = FALSE;
588 location.segment = seg;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000589 }
590 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000591 case 2: /* [EXTERN label:special] */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000592 if (*value == '$')
593 value++; /* skip initial $ if present */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000594 q = value;
595 validid = TRUE;
596 if (!isidstart(*q))
597 validid = FALSE;
598 while (*q && *q != ':') {
599 if (!isidchar(*q))
600 validid = FALSE;
601 q++;
602 }
603 if (!validid) {
604 report_error (ERR_NONFATAL,
605 "identifier expected after EXTERN");
606 break;
607 }
608 if (*q == ':') {
609 *q++ = '\0';
610 special = q;
611 } else
612 special = NULL;
613 if (!is_extern(value)) { /* allow re-EXTERN to be ignored */
614 declare_as_global (value, special, report_error);
615 define_label (value, seg_alloc(), 0L, NULL, FALSE, TRUE,
616 ofmt, report_error);
617 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000618 break;
619 case 3: /* [BITS bits] */
620 switch (atoi(value)) {
621 case 16:
622 case 32:
623 sb = atoi(value);
624 break;
625 default:
626 report_error(ERR_NONFATAL,
627 "`%s' is not a valid argument to [BITS]",
628 value);
629 break;
630 }
631 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000632 case 4: /* [GLOBAL symbol:special] */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000633 if (*value == '$')
634 value++; /* skip initial $ if present */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000635 q = value;
636 validid = TRUE;
637 if (!isidstart(*q))
638 validid = FALSE;
639 while (*q && *q != ':') {
640 if (!isidchar(*q))
641 validid = FALSE;
642 q++;
643 }
644 if (!validid) {
645 report_error (ERR_NONFATAL,
646 "identifier expected after GLOBAL");
647 break;
648 }
649 if (*q == ':') {
650 *q++ = '\0';
651 special = q;
652 } else
653 special = NULL;
654 declare_as_global (value, special, report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000655 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000656 case 5: /* [COMMON symbol size:special] */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000657 p = value;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000658 validid = TRUE;
659 if (!isidstart(*p))
660 validid = FALSE;
661 while (*p && !isspace(*p)) {
662 if (!isidchar(*p))
663 validid = FALSE;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000664 p++;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000665 }
666 if (!validid) {
667 report_error (ERR_NONFATAL,
668 "identifier expected after COMMON");
669 break;
670 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000671 if (*p) {
672 long size;
673
674 while (*p && isspace(*p))
675 *p++ = '\0';
H. Peter Anvin76690a12002-04-30 20:52:49 +0000676 q = p;
677 while (*q && *q != ':')
678 q++;
679 if (*q == ':') {
680 *q++ = '\0';
681 special = q;
682 } else
683 special = NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000684 size = readnum (p, &rn_error);
685 if (rn_error)
686 report_error (ERR_NONFATAL, "invalid size specified"
687 " in COMMON declaration");
688 else
689 define_common (value, seg_alloc(), size,
H. Peter Anvin76690a12002-04-30 20:52:49 +0000690 special, ofmt, report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000691 } else
692 report_error (ERR_NONFATAL, "no size specified in"
693 " COMMON declaration");
694 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000695 case 6: /* [ABSOLUTE address] */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000696 stdscan_reset();
697 stdscan_bufptr = value;
698 tokval.t_type = TOKEN_INVALID;
699 e = evaluate(stdscan, NULL, &tokval, NULL, 1, report_error,
700 NULL);
701 if (e) {
702 if (!is_reloc(e))
703 report_error (ERR_NONFATAL, "cannot use non-"
704 "relocatable expression as ABSOLUTE"
705 " address");
706 else {
707 abs_seg = reloc_seg(e);
708 abs_offset = reloc_value(e);
709 }
710 } else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000711 abs_offset = 0x100;/* don't go near zero in case of / */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000712 in_abs_seg = TRUE;
713 location.segment = abs_seg;
714 break;
715 case 7:
716 p = value;
717 validid = TRUE;
718 if (!isidstart(*p))
719 validid = FALSE;
720 while (*p && !isspace(*p)) {
721 if (!isidchar(*p))
722 validid = FALSE;
723 p++;
724 }
725 if (!validid) {
726 report_error (ERR_NONFATAL,
727 "identifier expected after DEBUG");
728 break;
729 }
730 while (*p && isspace(*p)) p++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000731 break;
732 default:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000733 if (!ofmt->directive (line+1, value, 1))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000734 report_error (ERR_NONFATAL, "unrecognised directive [%s]",
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000735 line+1);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000736 break;
737 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000738 }
739 else /* it isn't a directive */
740 {
H. Peter Anvin76690a12002-04-30 20:52:49 +0000741 parse_line (1, line, &output_ins,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000742 report_error, evaluate, define_label);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000743
H. Peter Anvineba20a72002-04-30 20:53:55 +0000744 if (output_ins.forw_ref)
745 {
746 for(i = 0; i < output_ins.operands; i++)
747 {
748 if (output_ins.oprs[i].opflags & OPFLAG_FORWARD)
749 {
750 struct forwrefinfo *fwinf =
751 (struct forwrefinfo *)saa_wstruct(forwrefs);
752 fwinf->lineno = globallineno;
753 fwinf->operand = i;
754 }
755 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000756 }
757
H. Peter Anvineba20a72002-04-30 20:53:55 +0000758 if (output_ins.opcode == I_EQU)
759 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000760 /*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000761 * Special `..' EQUs get processed in pass two,
762 * except `..@' macro-processor EQUs which are done
763 * in the normal place.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000764 */
765 if (!output_ins.label)
766 report_error (ERR_NONFATAL,
767 "EQU not preceded by label");
H. Peter Anvineba20a72002-04-30 20:53:55 +0000768
769 /*
770 * EQU cannot be used to declare a label relative to
771 * an external symbol.
772 */
773 else if ((output_ins.oprs[0].opflags & OPFLAG_EXTERN)
774 || (output_ins.operands > 1
775 && (output_ins.oprs[1].opflags & OPFLAG_EXTERN)))
776 {
777 report_error (ERR_NONFATAL,
778 "EQU used relative to external symbol");
779 }
780
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000781 else if (output_ins.label[0] != '.' ||
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000782 output_ins.label[1] != '.' ||
H. Peter Anvineba20a72002-04-30 20:53:55 +0000783 output_ins.label[2] == '@')
784 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000785 if (output_ins.operands == 1 &&
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000786 (output_ins.oprs[0].type & IMMEDIATE) &&
H. Peter Anvineba20a72002-04-30 20:53:55 +0000787 output_ins.oprs[0].wrt == NO_SEG)
788 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000789 define_label (output_ins.label,
790 output_ins.oprs[0].segment,
791 output_ins.oprs[0].offset,
H. Peter Anvin76690a12002-04-30 20:52:49 +0000792 NULL, FALSE, FALSE, ofmt, report_error);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000793 }
794 else if (output_ins.operands == 2 &&
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000795 (output_ins.oprs[0].type & IMMEDIATE) &&
796 (output_ins.oprs[0].type & COLON) &&
797 output_ins.oprs[0].segment == NO_SEG &&
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000798 output_ins.oprs[0].wrt == NO_SEG &&
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000799 (output_ins.oprs[1].type & IMMEDIATE) &&
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000800 output_ins.oprs[1].segment == NO_SEG &&
H. Peter Anvineba20a72002-04-30 20:53:55 +0000801 output_ins.oprs[1].wrt == NO_SEG)
802 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000803 define_label (output_ins.label,
804 output_ins.oprs[0].offset | SEG_ABS,
805 output_ins.oprs[1].offset,
H. Peter Anvin76690a12002-04-30 20:52:49 +0000806 NULL, FALSE, FALSE, ofmt, report_error);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000807 }
808 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000809 report_error(ERR_NONFATAL, "bad syntax for EQU");
810 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000811 }
812 else /* instruction isn't an EQU */
813 {
814 long l = insn_size (location.segment, offs, sb,
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000815 &output_ins, report_error);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000816 if (using_debug_info && output_ins.opcode != -1) {
817 /* this is done here so we can do debug type info */
818 long typeinfo = TYS_ELEMENTS(output_ins.operands);
819 switch (output_ins.opcode) {
820 case I_RESB:
821 typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_BYTE;
822 break;
823 case I_RESW:
824 typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_WORD;
825 break;
826 case I_RESD:
827 typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_DWORD;
828 break;
829 case I_RESQ:
830 typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_QWORD;
831 break;
832 case I_REST:
833 typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_TBYTE;
834 break;
835 case I_DB:
836 typeinfo |= TY_BYTE;
837 break;
838 case I_DW:
839 typeinfo |= TY_WORD;
840 break;
841 case I_DD:
842 if (output_ins.eops_float)
843 typeinfo |= TY_FLOAT;
844 else
845 typeinfo |= TY_DWORD;
846 break;
847 case I_DQ:
848 typeinfo |= TY_QWORD;
849 break;
850 case I_DT:
851 typeinfo |= TY_TBYTE;
852 break;
853 default:
854 typeinfo = TY_LABEL;
855 }
856 ofmt->current_dfmt->debug_typevalue(typeinfo);
857 }
858 if (l != -1) {
859 offs += l;
860 set_curr_ofs (offs);
861 }
862 /*
863 * else l == -1 => invalid instruction, which will be
864 * flagged as an error on pass 2
865 */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000866 }
867 cleanup_insn (&output_ins);
868 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000869 nasm_free (line);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000870 location.offset = offs = get_curr_ofs;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000871 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000872
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000873 preproc->cleanup();
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000874
875 if (terminate_after_phase) {
876 fclose(ofile);
877 remove(outname);
878 if (want_usage)
879 usage();
880 exit (1);
881 }
882
H. Peter Anvineba20a72002-04-30 20:53:55 +0000883 /*
884 * pass two
885 */
886
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000887 pass = 2;
H. Peter Anvinea838272002-04-30 20:51:53 +0000888 saa_rewind (forwrefs);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000889 if (*listname)
890 nasmlist.init(listname, report_error);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000891 forwref = saa_rstruct (forwrefs);
892 in_abs_seg = FALSE;
893 location.segment = ofmt->section(NULL, pass, &sb);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000894 raa_free (offsets);
895 offsets = raa_init();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000896 preproc->reset(fname, 2, report_error, evaluate, &nasmlist);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000897 globallineno = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000898 location.offset = offs = get_curr_ofs;
899
900 while ( (line = preproc->getline()) )
901 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000902 globallineno++;
903
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000904 /* here we parse our directives; this is not handled by
905 * the 'real' parser. */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000906 if ( (i = getkw (line, &value)) ) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000907 switch (i) {
908 case 1: /* [SEGMENT n] */
909 seg = ofmt->section (value, pass, &sb);
910 if (seg == NO_SEG) {
911 report_error (ERR_PANIC,
912 "invalid segment name on pass two");
913 } else
H. Peter Anvineba20a72002-04-30 20:53:55 +0000914 in_abs_seg = FALSE;
915 location.segment = seg;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000916 break;
917 case 2: /* [EXTERN label] */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000918 q = value;
919 while (*q && *q != ':')
920 q++;
921 if (*q == ':') {
922 *q++ = '\0';
923 ofmt->symdef(value, 0L, 0L, 3, q);
924 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000925 break;
926 case 3: /* [BITS bits] */
927 switch (atoi(value)) {
928 case 16:
929 case 32:
930 sb = atoi(value);
931 break;
932 default:
933 report_error(ERR_PANIC,
934 "invalid [BITS] value on pass two",
935 value);
936 break;
937 }
938 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000939 case 4: /* [GLOBAL symbol] */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000940 q = value;
941 while (*q && *q != ':')
942 q++;
943 if (*q == ':') {
944 *q++ = '\0';
945 ofmt->symdef(value, 0L, 0L, 3, q);
946 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000947 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000948 case 5: /* [COMMON symbol size] */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000949 q = value;
950 while (*q && *q != ':') {
951 if (isspace(*q))
952 *q = '\0';
953 q++;
954 }
955 if (*q == ':') {
956 *q++ = '\0';
957 ofmt->symdef(value, 0L, 0L, 3, q);
958 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000959 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000960 case 6: /* [ABSOLUTE addr] */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000961 stdscan_reset();
962 stdscan_bufptr = value;
963 tokval.t_type = TOKEN_INVALID;
964 e = evaluate(stdscan, NULL, &tokval, NULL, 2, report_error,
965 NULL);
966 if (e) {
967 if (!is_reloc(e))
968 report_error (ERR_PANIC, "non-reloc ABSOLUTE address"
969 " in pass two");
970 else {
971 abs_seg = reloc_seg(e);
972 abs_offset = reloc_value(e);
973 }
974 } else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000975 report_error (ERR_PANIC, "invalid ABSOLUTE address "
976 "in pass two");
H. Peter Anvineba20a72002-04-30 20:53:55 +0000977 in_abs_seg = TRUE;
978 location.segment = abs_seg;
979 break;
980 case 7:
981 p = value;
982 q = debugid;
983 validid = TRUE;
984 if (!isidstart(*p))
985 validid = FALSE;
986 while (*p && !isspace(*p)) {
987 if (!isidchar(*p))
988 validid = FALSE;
989 *q++ = *p++;
990 }
991 *q++ = 0;
992 if (!validid) {
993 report_error (ERR_PANIC,
994 "identifier expected after DEBUG in pass 2");
995 break;
996 }
997 while (*p && isspace(*p))
998 p++;
999 ofmt->current_dfmt->debug_directive (debugid, p);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001000 break;
1001 default:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001002 if (!ofmt->directive (line+1, value, 2))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001003 report_error (ERR_PANIC, "invalid directive on pass two");
1004 break;
1005 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001006 }
1007 else /* not a directive */
1008 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001009 parse_line (2, line, &output_ins,
H. Peter Anvineba20a72002-04-30 20:53:55 +00001010 report_error, evaluate, redefine_label);
1011 if (forwref != NULL && globallineno == forwref->lineno) {
H. Peter Anvinea838272002-04-30 20:51:53 +00001012 output_ins.forw_ref = TRUE;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001013 do {
1014 output_ins.oprs[forwref->operand].opflags|= OPFLAG_FORWARD;
1015 forwref = saa_rstruct (forwrefs);
1016 } while (forwref != NULL && forwref->lineno == globallineno);
H. Peter Anvinea838272002-04-30 20:51:53 +00001017 } else
1018 output_ins.forw_ref = FALSE;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001019
1020 /*
1021 * Hack to prevent phase error in the code
1022 * rol ax,x
1023 * x equ 1
H. Peter Anvineba20a72002-04-30 20:53:55 +00001024 *
1025 * If the second operand is a forward reference,
1026 * the UNITY property of the number 1 in that
1027 * operand is cancelled. Otherwise the above
1028 * sequence will cause a phase error.
1029 *
1030 * This hack means that the above code will
1031 * generate 286+ code.
1032 *
1033 * The forward reference will mean that the
1034 * operand will not have the UNITY property on
1035 * the first pass, so the pass behaviours will
1036 * be consistent.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001037 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00001038
1039 if (output_ins.forw_ref &&
1040 output_ins.operands >= 2 &&
1041 (output_ins.oprs[1].opflags & OPFLAG_FORWARD))
1042 {
1043 output_ins.oprs[1].type &= ~ONENESS;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001044 }
1045
H. Peter Anvineba20a72002-04-30 20:53:55 +00001046 if (output_ins.opcode == I_EQU)
1047 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001048 /*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001049 * Special `..' EQUs get processed here, except
1050 * `..@' macro processor EQUs which are done above.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001051 */
1052 if (output_ins.label[0] == '.' &&
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001053 output_ins.label[1] == '.' &&
H. Peter Anvineba20a72002-04-30 20:53:55 +00001054 output_ins.label[2] != '@')
1055 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001056 if (output_ins.operands == 1 &&
1057 (output_ins.oprs[0].type & IMMEDIATE)) {
1058 define_label (output_ins.label,
1059 output_ins.oprs[0].segment,
1060 output_ins.oprs[0].offset,
H. Peter Anvin76690a12002-04-30 20:52:49 +00001061 NULL, FALSE, FALSE, ofmt, report_error);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001062 }
1063 else if (output_ins.operands == 2 &&
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001064 (output_ins.oprs[0].type & IMMEDIATE) &&
1065 (output_ins.oprs[0].type & COLON) &&
1066 output_ins.oprs[0].segment == NO_SEG &&
1067 (output_ins.oprs[1].type & IMMEDIATE) &&
H. Peter Anvineba20a72002-04-30 20:53:55 +00001068 output_ins.oprs[1].segment == NO_SEG)
1069 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001070 define_label (output_ins.label,
1071 output_ins.oprs[0].offset | SEG_ABS,
1072 output_ins.oprs[1].offset,
H. Peter Anvin76690a12002-04-30 20:52:49 +00001073 NULL, FALSE, FALSE, ofmt, report_error);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001074 }
1075 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001076 report_error(ERR_NONFATAL, "bad syntax for EQU");
1077 }
1078 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001079 offs += assemble (location.segment, offs, sb,
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001080 &output_ins, ofmt, report_error, &nasmlist);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001081 cleanup_insn (&output_ins);
1082 set_curr_ofs (offs);
1083 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001084
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001085 nasm_free (line);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001086
H. Peter Anvineba20a72002-04-30 20:53:55 +00001087 location.offset = offs = get_curr_ofs;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001088 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001089
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001090 preproc->cleanup();
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001091 nasmlist.cleanup();
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001092}
1093
H. Peter Anvineba20a72002-04-30 20:53:55 +00001094static int getkw (char *buf, char **value)
1095{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001096 char *p, *q;
1097
1098 if (*buf!='[')
1099 return 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001100
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001101 p = buf;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001102
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001103 while (*p && *p != ']') p++;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001104
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001105 if (!*p)
1106 return 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001107
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001108 q = p++;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001109
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001110 while (*p && *p != ';') {
1111 if (!isspace(*p))
1112 return 0;
1113 p++;
1114 }
1115 q[1] = '\0';
1116
1117 p = buf+1;
1118 while (*buf && *buf!=' ' && *buf!=']' && *buf!='\t')
1119 buf++;
1120 if (*buf==']') {
1121 *buf = '\0';
1122 *value = buf;
1123 } else {
1124 *buf++ = '\0';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001125 while (isspace(*buf)) buf++; /* beppu - skip leading whitespace */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001126 *value = buf;
1127 while (*buf!=']') buf++;
1128 *buf++ = '\0';
1129 }
1130 for (q=p; *q; q++)
1131 *q = tolower(*q);
1132 if (!strcmp(p, "segment") || !strcmp(p, "section"))
1133 return 1;
1134 if (!strcmp(p, "extern"))
1135 return 2;
1136 if (!strcmp(p, "bits"))
1137 return 3;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001138 if (!strcmp(p, "global"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001139 return 4;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001140 if (!strcmp(p, "common"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001141 return 5;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001142 if (!strcmp(p, "absolute"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001143 return 6;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001144 if (!strcmp(p, "debug"))
1145 return 7;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001146 return -1;
1147}
1148
H. Peter Anvineba20a72002-04-30 20:53:55 +00001149static void report_error (int severity, char *fmt, ...)
1150{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001151 va_list ap;
1152
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001153 /*
1154 * See if it's a suppressed warning.
1155 */
1156 if ((severity & ERR_MASK) == ERR_WARNING &&
1157 (severity & ERR_WARN_MASK) != 0 &&
1158 suppressed[ (severity & ERR_WARN_MASK) >> ERR_WARN_SHR ])
1159 return; /* and bail out if so */
1160
H. Peter Anvin76690a12002-04-30 20:52:49 +00001161 /*
1162 * See if it's a pass-one only warning and we're not in pass one.
1163 */
1164 if ((severity & ERR_PASS1) && pass != 1)
1165 return;
1166
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001167 if (severity & ERR_NOFILE)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001168 fputs ("nasm: ", stdout);
1169 else {
1170 char * currentfile = NULL;
1171 long lineno = 0;
1172 src_get (&lineno, &currentfile);
1173 fprintf (stdout, "%s:%ld: ", currentfile, lineno);
1174 nasm_free (currentfile);
1175 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001176
1177 if ( (severity & ERR_MASK) == ERR_WARNING)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001178 fputs ("warning: ", stdout);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001179 else if ( (severity & ERR_MASK) == ERR_PANIC)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001180 fputs ("panic: ", stdout);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001181
1182 va_start (ap, fmt);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001183 vfprintf (stdout, fmt, ap);
1184 fputc ('\n', stdout);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001185
1186 if (severity & ERR_USAGE)
1187 want_usage = TRUE;
1188
1189 switch (severity & ERR_MASK) {
1190 case ERR_WARNING:
1191 /* no further action, by definition */
1192 break;
1193 case ERR_NONFATAL:
1194 terminate_after_phase = TRUE;
1195 break;
1196 case ERR_FATAL:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001197 if (ofile) {
1198 fclose(ofile);
1199 remove(outname);
1200 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001201 if (want_usage)
1202 usage();
1203 exit(1); /* instantly die */
1204 break; /* placate silly compilers */
1205 case ERR_PANIC:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001206 abort(); /* halt, catch fire, and dump core */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001207 break;
1208 }
1209}
1210
H. Peter Anvineba20a72002-04-30 20:53:55 +00001211static void usage(void)
1212{
1213 fputs("type `nasm -h' for help\n", stdout);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001214}
1215
H. Peter Anvineba20a72002-04-30 20:53:55 +00001216static void register_output_formats(void)
1217{
1218 ofmt = ofmt_register (report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001219}
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001220
1221#define BUF_DELTA 512
1222
1223static FILE *no_pp_fp;
1224static efunc no_pp_err;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001225static ListGen *no_pp_list;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001226static long no_pp_lineinc;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001227
H. Peter Anvin76690a12002-04-30 20:52:49 +00001228static void no_pp_reset (char *file, int pass, efunc error, evalfunc eval,
H. Peter Anvineba20a72002-04-30 20:53:55 +00001229 ListGen *listgen)
1230{
1231 src_set_fname(nasm_strdup(file));
1232 src_set_linnum(0);
1233 no_pp_lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001234 no_pp_err = error;
1235 no_pp_fp = fopen(file, "r");
1236 if (!no_pp_fp)
1237 no_pp_err (ERR_FATAL | ERR_NOFILE,
1238 "unable to open input file `%s'", file);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001239 no_pp_list = listgen;
1240 (void) pass; /* placate compilers */
1241 (void) eval; /* placate compilers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001242}
1243
H. Peter Anvineba20a72002-04-30 20:53:55 +00001244static char *no_pp_getline (void)
1245{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001246 char *buffer, *p, *q;
1247 int bufsize;
1248
1249 bufsize = BUF_DELTA;
1250 buffer = nasm_malloc(BUF_DELTA);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001251 src_set_linnum(src_get_linnum() + no_pp_lineinc);
1252
1253 while (1) { /* Loop to handle %line */
1254
1255 p = buffer;
1256 while (1) { /* Loop to handle long lines */
1257 q = fgets(p, bufsize-(p-buffer), no_pp_fp);
1258 if (!q)
1259 break;
1260 p += strlen(p);
1261 if (p > buffer && p[-1] == '\n')
1262 break;
1263 if (p-buffer > bufsize-10) {
1264 int offset;
1265 offset = p - buffer;
1266 bufsize += BUF_DELTA;
1267 buffer = nasm_realloc(buffer, bufsize);
1268 p = buffer + offset;
1269 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001270 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001271
1272 if (!q && p == buffer) {
1273 nasm_free (buffer);
1274 return NULL;
1275 }
1276
1277 /*
1278 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
1279 * them are present at the end of the line.
1280 */
1281 buffer[strcspn(buffer, "\r\n\032")] = '\0';
1282
1283 if (!strncmp(buffer, "%line", 5)) {
1284 long ln;
1285 int li;
1286 char *nm = nasm_malloc(strlen(buffer));
1287 if (sscanf(buffer+5, "%ld+%d %s", &ln, &li, nm) == 3) {
1288 nasm_free( src_set_fname(nm) );
1289 src_set_linnum(ln);
1290 no_pp_lineinc = li;
1291 continue;
1292 }
1293 nasm_free(nm);
1294 }
1295 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001296 }
1297
H. Peter Anvin76690a12002-04-30 20:52:49 +00001298 no_pp_list->line (LIST_READ, buffer);
1299
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001300 return buffer;
1301}
1302
H. Peter Anvineba20a72002-04-30 20:53:55 +00001303static void no_pp_cleanup (void)
1304{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001305 fclose(no_pp_fp);
1306}