blob: 3c5327a41652b72a466995ec8ffb184a0649b1ea [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
H. Peter Anvinef7468f2002-04-30 20:57:59 +000046static FILE *error_file; /* Where to write error messages */
H. Peter Anvin620515a2002-04-30 20:57:38 +000047
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000048static FILE *ofile = NULL;
49static int sb = 16; /* by default */
50
H. Peter Anvineba20a72002-04-30 20:53:55 +000051static loc_t location;
52int in_abs_seg; /* Flag we are in ABSOLUTE seg */
53static long abs_seg;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000054
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000055static struct RAA *offsets;
56static long abs_offset;
H. Peter Anvinea838272002-04-30 20:51:53 +000057
58static struct SAA *forwrefs; /* keep track of forward references */
H. Peter Anvineba20a72002-04-30 20:53:55 +000059static struct forwrefinfo *forwref;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000060
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000061static Preproc *preproc;
H. Peter Anvin620515a2002-04-30 20:57:38 +000062enum op_type {
63 op_normal, /* Preprocess and assemble */
64 op_preprocess, /* Preprocess only */
65 op_depend /* Generate dependencies */
66};
67static enum op_type operating_mode;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000068
69/* used by error function to report location */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000070
71/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +000072 * Which of the suppressible warnings are suppressed. Entry zero
73 * doesn't do anything. Initial defaults are given here.
74 */
75static char suppressed[1+ERR_WARN_MAX] = {
H. Peter Anvineba20a72002-04-30 20:53:55 +000076 0, TRUE, TRUE, FALSE
H. Peter Anvin6768eb72002-04-30 20:52:26 +000077};
78
79/*
80 * The option names for the suppressible warnings. As before, entry
81 * zero does nothing.
82 */
83static char *suppressed_names[1+ERR_WARN_MAX] = {
H. Peter Anvin76690a12002-04-30 20:52:49 +000084 NULL, "macro-params", "orphan-labels", "number-overflow"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000085};
86
87/*
88 * The explanations for the suppressible warnings. As before, entry
89 * zero does nothing.
90 */
91static char *suppressed_what[1+ERR_WARN_MAX] = {
92 NULL, "macro calls with wrong no. of params",
H. Peter Anvin76690a12002-04-30 20:52:49 +000093 "labels alone on lines without trailing `:'",
94 "numeric constants greater than 0xFFFFFFFF"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000095};
96
97/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000098 * This is a null preprocessor which just copies lines from input
99 * to output. It's used when someone explicitly requests that NASM
100 * not preprocess their source file.
101 */
102
H. Peter Anvin76690a12002-04-30 20:52:49 +0000103static void no_pp_reset (char *, int, efunc, evalfunc, ListGen *);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000104static char *no_pp_getline (void);
105static void no_pp_cleanup (void);
106static Preproc no_pp = {
107 no_pp_reset,
108 no_pp_getline,
109 no_pp_cleanup
110};
111
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000112/*
113 * get/set current offset...
114 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000115#define get_curr_ofs (in_abs_seg?abs_offset:\
116 raa_read(offsets,location.segment))
117#define set_curr_ofs(x) (in_abs_seg?(void)(abs_offset=(x)):\
118 (void)(offsets=raa_write(offsets,location.segment,(x))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000119
120static int want_usage;
121static int terminate_after_phase;
122
H. Peter Anvineba20a72002-04-30 20:53:55 +0000123static void nasm_fputs(char *line, FILE *ofile)
124{
125 if (ofile) {
126 fputs(line, ofile);
127 fputc('\n', ofile);
128 } else
129 puts(line);
130}
131
132int main(int argc, char **argv)
133{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000134 want_usage = terminate_after_phase = FALSE;
135
136 nasm_set_malloc_error (report_error);
137 offsets = raa_init();
H. Peter Anvineba20a72002-04-30 20:53:55 +0000138 forwrefs = saa_init ((long)sizeof(struct forwrefinfo));
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000139
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000140 preproc = &nasmpp;
H. Peter Anvin620515a2002-04-30 20:57:38 +0000141 operating_mode = op_normal;
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000142
143 error_file = stderr;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000144
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000145 seg_init();
146
147 register_output_formats();
148
149 parse_cmdline(argc, argv);
150
H. Peter Anvineba20a72002-04-30 20:53:55 +0000151 if (terminate_after_phase)
152 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000153 if (want_usage)
154 usage();
155 return 1;
156 }
157
H. Peter Anvin76690a12002-04-30 20:52:49 +0000158 if (ofmt->stdmac)
159 pp_extra_stdmac (ofmt->stdmac);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000160 parser_global_info (ofmt, &location);
161 eval_global_info (ofmt, lookup_label, &location);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000162
H. Peter Anvin620515a2002-04-30 20:57:38 +0000163 switch ( operating_mode ) {
164 case op_depend:
165 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000166 char *line;
H. Peter Anvin620515a2002-04-30 20:57:38 +0000167 preproc->reset (inname, 0, report_error, evaluate, &nasmlist);
168 if (outname[0] == '\0')
169 ofmt->filename (inname, outname, report_error);
170 ofile = NULL;
171 printf("%s: %s", outname, inname);
172 while ( (line = preproc->getline()) )
173 nasm_free (line);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000174 preproc->cleanup();
H. Peter Anvin620515a2002-04-30 20:57:38 +0000175 putc('\n', stdout);
176 }
177 break;
178
179 case op_preprocess:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000180 {
H. Peter Anvin620515a2002-04-30 20:57:38 +0000181 char *line;
182 char *file_name = NULL;
183 long prior_linnum=0;
184 int lineinc=0;
185
186 if (*outname) {
187 ofile = fopen(outname, "w");
188 if (!ofile)
189 report_error (ERR_FATAL | ERR_NOFILE,
190 "unable to open output file `%s'", outname);
191 } else
192 ofile = NULL;
193
194 location.known = FALSE;
195
196 preproc->reset (inname, 2, report_error, evaluate, &nasmlist);
197 while ( (line = preproc->getline()) ) {
198 /*
199 * We generate %line directives if needed for later programs
200 */
201 long linnum = prior_linnum += lineinc;
202 int altline = src_get(&linnum, &file_name);
203 if (altline) {
204 if (altline==1 && lineinc==1)
205 nasm_fputs("", ofile);
206 else {
207 lineinc = (altline != -1 || lineinc!=1);
208 fprintf(ofile ? ofile : stdout, "%%line %ld+%d %s\n",
209 linnum, lineinc, file_name);
210 }
211 prior_linnum = linnum;
212 }
213 nasm_fputs(line, ofile);
214 nasm_free (line);
215 }
216 nasm_free(file_name);
217 preproc->cleanup();
218 if (ofile)
219 fclose(ofile);
220 if (ofile && terminate_after_phase)
221 remove(outname);
222 }
223 break;
224
225 case op_normal:
226 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000227 /*
228 * We must call ofmt->filename _anyway_, even if the user
229 * has specified their own output file, because some
230 * formats (eg OBJ and COFF) use ofmt->filename to find out
231 * the name of the input file and then put that inside the
232 * file.
233 */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000234 ofmt->filename (inname, outname, report_error);
H. Peter Anvin620515a2002-04-30 20:57:38 +0000235
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000236 ofile = fopen(outname, "wb");
237 if (!ofile) {
H. Peter Anvin620515a2002-04-30 20:57:38 +0000238 report_error (ERR_FATAL | ERR_NOFILE,
239 "unable to open output file `%s'", outname);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000240 }
H. Peter Anvin620515a2002-04-30 20:57:38 +0000241
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000242 /*
243 * We must call init_labels() before ofmt->init() since
244 * some object formats will want to define labels in their
245 * init routines. (eg OS/2 defines the FLAT group)
246 */
247 init_labels ();
H. Peter Anvin620515a2002-04-30 20:57:38 +0000248
H. Peter Anvin76690a12002-04-30 20:52:49 +0000249 ofmt->init (ofile, report_error, define_label, evaluate);
H. Peter Anvin620515a2002-04-30 20:57:38 +0000250
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000251 assemble_file (inname);
H. Peter Anvin620515a2002-04-30 20:57:38 +0000252
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000253 if (!terminate_after_phase) {
H. Peter Anvin620515a2002-04-30 20:57:38 +0000254 ofmt->cleanup (using_debug_info);
255 cleanup_labels ();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000256 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000257 else {
H. Peter Anvin620515a2002-04-30 20:57:38 +0000258
259 /*
260 * We had an fclose on the output file here, but we
261 * actually do that in all the object file drivers as well,
262 * so we're leaving out the one here.
263 * fclose (ofile);
264 */
265
266 remove(outname);
267 if (listname[0])
268 remove(listname);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000269 }
H. Peter Anvin620515a2002-04-30 20:57:38 +0000270 }
271 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000272 }
H. Peter Anvin620515a2002-04-30 20:57:38 +0000273
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000274 if (want_usage)
H. Peter Anvin620515a2002-04-30 20:57:38 +0000275 usage();
276
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000277 raa_free (offsets);
278 saa_free (forwrefs);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000279 eval_cleanup ();
280 nasmlib_cleanup ();
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000281
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000282 if (terminate_after_phase)
283 return 1;
284 else
285 return 0;
286}
287
H. Peter Anvineba20a72002-04-30 20:53:55 +0000288
289/*
290 * Get a parameter for a command line option.
291 * First arg must be in the form of e.g. -f...
292 */
293static char *get_param (char *p, char *q, int *advance)
294{
295 *advance = 0;
296 if (p[2]) /* the parameter's in the option */
297 {
298 p += 2;
299 while (isspace(*p))
300 p++;
301 return p;
302 }
303 if (q && q[0])
304 {
305 *advance = 1;
306 return q;
307 }
308 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
309 "option `-%c' requires an argument",
310 p[1]);
311 return NULL;
312}
313
314int stopoptions = 0;
315static int process_arg (char *p, char *q)
316{
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000317 char *param;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000318 int i, advance = 0;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000319
320 if (!p || !p[0])
321 return 0;
322
H. Peter Anvineba20a72002-04-30 20:53:55 +0000323 if (p[0]=='-' && ! stopoptions)
324 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000325 switch (p[1]) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000326 case '-': /* -- => stop processing options */
327 stopoptions = 1;
328 break;
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000329 case 's':
330 error_file = stdout;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000331 break;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000332 case 'o': /* these parameters take values */
333 case 'f':
334 case 'p':
335 case 'd':
H. Peter Anvin620515a2002-04-30 20:57:38 +0000336 case 'D':
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000337 case 'i':
338 case 'l':
H. Peter Anvin620515a2002-04-30 20:57:38 +0000339 case 'E':
H. Peter Anvineba20a72002-04-30 20:53:55 +0000340 case 'F':
341 if ( !(param = get_param (p, q, &advance)) )
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000342 break;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000343 if (p[1]=='o') { /* output file */
344 strcpy (outname, param);
345 } else if (p[1]=='f') { /* output format */
346 ofmt = ofmt_find(param);
347 if (!ofmt) {
348 report_error (ERR_FATAL | ERR_NOFILE | ERR_USAGE,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000349 "unrecognised output format `%s' - "
350 "use -hf for a list",
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000351 param);
352 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000353 else
354 ofmt->current_dfmt = ofmt->debug_formats[0];
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000355 } else if (p[1]=='P' || p[1]=='p') { /* pre-include */
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000356 pp_pre_include (param);
H. Peter Anvin620515a2002-04-30 20:57:38 +0000357 } else if (p[1]=='D' || p[1]=='d') { /* pre-define */
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000358 pp_pre_define (param);
H. Peter Anvin620515a2002-04-30 20:57:38 +0000359 } else if (p[1]=='U' || p[1]=='u') { /* un-define */
360 pp_pre_undefine (param);
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000361 } else if (p[1]=='I' || p[1]=='i') { /* include search path */
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000362 pp_include_path (param);
363 } else if (p[1]=='l') { /* listing file */
364 strcpy (listname, param);
H. Peter Anvin620515a2002-04-30 20:57:38 +0000365 } else if (p[1]=='E') { /* error messages file */
366 error_file = fopen(param, "wt");
367 if ( !error_file ) {
368 error_file = stderr; /* Revert to default! */
369 report_error (ERR_FATAL | ERR_NOFILE | ERR_USAGE,
370 "cannot open file `%s' for error messages",
371 param);
372 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000373 } else if (p[1] == 'F') { /* specify debug format */
374 ofmt->current_dfmt = dfmt_find(ofmt, param);
375 if (!ofmt->current_dfmt) {
376 report_error (ERR_FATAL | ERR_NOFILE | ERR_USAGE,
377 "unrecognized debug format `%s' for"
378 " output format `%s'",
379 param, ofmt->shortname);
380 }
381 }
382 break;
383 case 'g':
384 using_debug_info = TRUE;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000385 break;
386 case 'h':
H. Peter Anvineba20a72002-04-30 20:53:55 +0000387 printf("usage: nasm [-@ response file] [-o outfile] [-f format] "
388 "[-l listfile]\n"
H. Peter Anvin620515a2002-04-30 20:57:38 +0000389 " [options...] [--] filename\n"
390 " or nasm -r for version info\n\n"
391 " -e preprocess only (writes output to stdout by default)\n"
392 " -a don't preprocess (assemble only)\n"
393 " -M generate Makefile dependencies on stdout\n\n"
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000394 " -E<file> redirect error messages to file\n"
395 " -s redirect error messages to stdout\n\n"
H. Peter Anvin620515a2002-04-30 20:57:38 +0000396 " -g enable debug info\n"
397 " -F format select a debugging format\n\n"
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000398 " -I<path> adds a pathname to the include file path\n"
399 " -P<file> pre-includes a file\n"
400 " -D<macro>[=<value>] pre-defines a macro\n"
401 " -U<macro> undefines a macro\n"
H. Peter Anvin620515a2002-04-30 20:57:38 +0000402 " -w+foo enables warnings about foo; -w-foo disables them\n"
403 "where foo can be:\n");
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000404 for (i=1; i<=ERR_WARN_MAX; i++)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000405 printf(" %-16s%s (default %s)\n",
406 suppressed_names[i], suppressed_what[i],
407 suppressed[i] ? "off" : "on");
408 printf ("\nresponse files should contain command line parameters"
409 ", one per line.\n");
410 if (p[2] == 'f') {
411 printf("\nvalid output formats for -f are"
412 " (`*' denotes default):\n");
413 ofmt_list(ofmt, stdout);
414 }
415 else {
416 printf ("\nFor a list of valid output formats, use -hf.\n");
417 printf ("For a list of debug formats, use -f <form> -y.\n");
418 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000419 exit (0); /* never need usage message here */
420 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000421 case 'y':
422 printf("\nvalid debug formats for '%s' output format are"
423 " ('*' denotes default):\n",
424 ofmt->shortname);
425 dfmt_list(ofmt, stdout);
426 exit(0);
427 break;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000428 case 'r':
H. Peter Anvineba20a72002-04-30 20:53:55 +0000429 printf("NASM version %s\n", NASM_VER);
430#ifdef DEBUG
431 printf("Compiled with -DDEBUG on " __DATE__ "\n");
432#endif
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000433 exit (0); /* never need usage message here */
434 break;
435 case 'e': /* preprocess only */
H. Peter Anvin620515a2002-04-30 20:57:38 +0000436 operating_mode = op_preprocess;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000437 break;
438 case 'a': /* assemble only - don't preprocess */
439 preproc = &no_pp;
440 break;
441 case 'w':
442 if (p[2] != '+' && p[2] != '-') {
443 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
444 "invalid option to `-w'");
445 } else {
446 for (i=1; i<=ERR_WARN_MAX; i++)
447 if (!nasm_stricmp(p+3, suppressed_names[i]))
448 break;
449 if (i <= ERR_WARN_MAX)
450 suppressed[i] = (p[2] == '-');
451 else
452 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
453 "invalid option to `-w'");
454 }
455 break;
H. Peter Anvin620515a2002-04-30 20:57:38 +0000456 case 'M':
457 operating_mode = op_depend;
458 break;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000459 default:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000460 if (!ofmt->setinfo(GI_SWITCH,&p))
461 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000462 "unrecognised option `-%c'",
463 p[1]);
464 break;
465 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000466 }
467 else
468 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000469 if (*inname) {
470 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
471 "more than one input file specified");
472 } else
473 strcpy(inname, p);
474 }
475
476 return advance;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000477}
478
H. Peter Anvineba20a72002-04-30 20:53:55 +0000479#define ARG_BUF_DELTA 128
480
481static void process_respfile (FILE *rfile)
482{
483 char *buffer, *p, *q, *prevarg;
484 int bufsize, prevargsize;
485
486 bufsize = prevargsize = ARG_BUF_DELTA;
487 buffer = nasm_malloc(ARG_BUF_DELTA);
488 prevarg = nasm_malloc(ARG_BUF_DELTA);
489 prevarg[0] = '\0';
490
491 while (1) { /* Loop to handle all lines in file */
492
493 p = buffer;
494 while (1) { /* Loop to handle long lines */
495 q = fgets(p, bufsize-(p-buffer), rfile);
496 if (!q)
497 break;
498 p += strlen(p);
499 if (p > buffer && p[-1] == '\n')
500 break;
501 if (p-buffer > bufsize-10) {
502 int offset;
503 offset = p - buffer;
504 bufsize += ARG_BUF_DELTA;
505 buffer = nasm_realloc(buffer, bufsize);
506 p = buffer + offset;
507 }
508 }
509
510 if (!q && p == buffer) {
511 if (prevarg[0])
512 process_arg (prevarg, NULL);
513 nasm_free (buffer);
514 nasm_free (prevarg);
515 return;
516 }
517
518 /*
519 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
520 * them are present at the end of the line.
521 */
522 *(p = &buffer[strcspn(buffer, "\r\n\032")]) = '\0';
523
524 while (p > buffer && isspace(p[-1]))
525 *--p = '\0';
526
527 p = buffer;
528 while (isspace(*p))
529 p++;
530
531 if (process_arg (prevarg, p))
532 *p = '\0';
533
534 if (strlen(p) > prevargsize-10) {
535 prevargsize += ARG_BUF_DELTA;
536 prevarg = nasm_realloc(prevarg, prevargsize);
537 }
538 strcpy (prevarg, p);
539 }
540}
541
542static void parse_cmdline(int argc, char **argv)
543{
544 FILE *rfile;
545 char *envreal, *envcopy=NULL, *p, *q, *arg, *prevarg;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000546 char separator = ' ';
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000547
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000548 *inname = *outname = *listname = '\0';
549
550 /*
551 * First, process the NASM environment variable.
552 */
553 envreal = getenv("NASM");
554 arg = NULL;
555 if (envreal) {
556 envcopy = nasm_strdup(envreal);
557 p = envcopy;
558 if (*p && *p != '-')
559 separator = *p++;
560 while (*p) {
561 q = p;
562 while (*p && *p != separator) p++;
563 while (*p == separator) *p++ = '\0';
564 prevarg = arg;
565 arg = q;
566 if (process_arg (prevarg, arg))
567 arg = NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000568 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000569 if (arg)
570 process_arg (arg, NULL);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000571 nasm_free (envcopy);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000572 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000573
574 /*
575 * Now process the actual command line.
576 */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000577 while (--argc)
578 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000579 int i;
580 argv++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000581 if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
582 if ((p = get_param (argv[0], argc > 1 ? argv[1] : NULL, &i)))
583 if ((rfile = fopen(p, "r"))) {
584 process_respfile (rfile);
585 fclose(rfile);
586 } else
587 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
588 "unable to open response file `%s'", p);
589 } else
590 i = process_arg (argv[0], argc > 1 ? argv[1] : NULL);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000591 argv += i, argc -= i;
592 }
593
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000594 if (!*inname)
595 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
596 "no input file specified");
597}
598
H. Peter Anvineba20a72002-04-30 20:53:55 +0000599static void assemble_file (char *fname)
600{
601 char * value, * p, * q, * special, * line, debugid[80];
602 insn output_ins;
603 int i, rn_error, validid;
604 long seg, offs;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000605 struct tokenval tokval;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000606 expr * e;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000607
H. Peter Anvineba20a72002-04-30 20:53:55 +0000608 /*
609 * pass one
610 */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000611 pass = 1;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000612 in_abs_seg = FALSE;
613 location.segment = ofmt->section(NULL, pass, &sb);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000614 preproc->reset(fname, 1, report_error, evaluate, &nasmlist);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000615 globallineno = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000616 location.known = TRUE;
617 location.offset = offs = get_curr_ofs;
618
619 while ( (line = preproc->getline()) )
620 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000621 globallineno++;
622
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000623 /* here we parse our directives; this is not handled by the 'real'
624 * parser. */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000625 if ( (i = getkw (line, &value)) )
626 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000627 switch (i) {
628 case 1: /* [SEGMENT n] */
629 seg = ofmt->section (value, pass, &sb);
630 if (seg == NO_SEG) {
631 report_error (ERR_NONFATAL,
632 "segment name `%s' not recognised",
633 value);
634 } else {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000635 in_abs_seg = FALSE;
636 location.segment = seg;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000637 }
638 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000639 case 2: /* [EXTERN label:special] */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000640 if (*value == '$')
641 value++; /* skip initial $ if present */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000642 q = value;
643 validid = TRUE;
644 if (!isidstart(*q))
645 validid = FALSE;
646 while (*q && *q != ':') {
647 if (!isidchar(*q))
648 validid = FALSE;
649 q++;
650 }
651 if (!validid) {
652 report_error (ERR_NONFATAL,
653 "identifier expected after EXTERN");
654 break;
655 }
656 if (*q == ':') {
657 *q++ = '\0';
658 special = q;
659 } else
660 special = NULL;
661 if (!is_extern(value)) { /* allow re-EXTERN to be ignored */
662 declare_as_global (value, special, report_error);
663 define_label (value, seg_alloc(), 0L, NULL, FALSE, TRUE,
664 ofmt, report_error);
665 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000666 break;
667 case 3: /* [BITS bits] */
668 switch (atoi(value)) {
669 case 16:
670 case 32:
671 sb = atoi(value);
672 break;
673 default:
674 report_error(ERR_NONFATAL,
675 "`%s' is not a valid argument to [BITS]",
676 value);
677 break;
678 }
679 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000680 case 4: /* [GLOBAL symbol:special] */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000681 if (*value == '$')
682 value++; /* skip initial $ if present */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000683 q = value;
684 validid = TRUE;
685 if (!isidstart(*q))
686 validid = FALSE;
687 while (*q && *q != ':') {
688 if (!isidchar(*q))
689 validid = FALSE;
690 q++;
691 }
692 if (!validid) {
693 report_error (ERR_NONFATAL,
694 "identifier expected after GLOBAL");
695 break;
696 }
697 if (*q == ':') {
698 *q++ = '\0';
699 special = q;
700 } else
701 special = NULL;
702 declare_as_global (value, special, report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000703 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000704 case 5: /* [COMMON symbol size:special] */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000705 p = value;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000706 validid = TRUE;
707 if (!isidstart(*p))
708 validid = FALSE;
709 while (*p && !isspace(*p)) {
710 if (!isidchar(*p))
711 validid = FALSE;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000712 p++;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000713 }
714 if (!validid) {
715 report_error (ERR_NONFATAL,
716 "identifier expected after COMMON");
717 break;
718 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000719 if (*p) {
720 long size;
721
722 while (*p && isspace(*p))
723 *p++ = '\0';
H. Peter Anvin76690a12002-04-30 20:52:49 +0000724 q = p;
725 while (*q && *q != ':')
726 q++;
727 if (*q == ':') {
728 *q++ = '\0';
729 special = q;
730 } else
731 special = NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000732 size = readnum (p, &rn_error);
733 if (rn_error)
734 report_error (ERR_NONFATAL, "invalid size specified"
735 " in COMMON declaration");
736 else
737 define_common (value, seg_alloc(), size,
H. Peter Anvin76690a12002-04-30 20:52:49 +0000738 special, ofmt, report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000739 } else
740 report_error (ERR_NONFATAL, "no size specified in"
741 " COMMON declaration");
742 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000743 case 6: /* [ABSOLUTE address] */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000744 stdscan_reset();
745 stdscan_bufptr = value;
746 tokval.t_type = TOKEN_INVALID;
747 e = evaluate(stdscan, NULL, &tokval, NULL, 1, report_error,
748 NULL);
749 if (e) {
750 if (!is_reloc(e))
751 report_error (ERR_NONFATAL, "cannot use non-"
752 "relocatable expression as ABSOLUTE"
753 " address");
754 else {
755 abs_seg = reloc_seg(e);
756 abs_offset = reloc_value(e);
757 }
758 } else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000759 abs_offset = 0x100;/* don't go near zero in case of / */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000760 in_abs_seg = TRUE;
761 location.segment = abs_seg;
762 break;
763 case 7:
764 p = value;
765 validid = TRUE;
766 if (!isidstart(*p))
767 validid = FALSE;
768 while (*p && !isspace(*p)) {
769 if (!isidchar(*p))
770 validid = FALSE;
771 p++;
772 }
773 if (!validid) {
774 report_error (ERR_NONFATAL,
775 "identifier expected after DEBUG");
776 break;
777 }
778 while (*p && isspace(*p)) p++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000779 break;
780 default:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000781 if (!ofmt->directive (line+1, value, 1))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000782 report_error (ERR_NONFATAL, "unrecognised directive [%s]",
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000783 line+1);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000784 break;
785 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000786 }
787 else /* it isn't a directive */
788 {
H. Peter Anvin76690a12002-04-30 20:52:49 +0000789 parse_line (1, line, &output_ins,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000790 report_error, evaluate, define_label);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000791
H. Peter Anvineba20a72002-04-30 20:53:55 +0000792 if (output_ins.forw_ref)
793 {
794 for(i = 0; i < output_ins.operands; i++)
795 {
796 if (output_ins.oprs[i].opflags & OPFLAG_FORWARD)
797 {
798 struct forwrefinfo *fwinf =
799 (struct forwrefinfo *)saa_wstruct(forwrefs);
800 fwinf->lineno = globallineno;
801 fwinf->operand = i;
802 }
803 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000804 }
805
H. Peter Anvineba20a72002-04-30 20:53:55 +0000806 if (output_ins.opcode == I_EQU)
807 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000808 /*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000809 * Special `..' EQUs get processed in pass two,
810 * except `..@' macro-processor EQUs which are done
811 * in the normal place.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000812 */
813 if (!output_ins.label)
814 report_error (ERR_NONFATAL,
815 "EQU not preceded by label");
H. Peter Anvineba20a72002-04-30 20:53:55 +0000816
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000817 else if (output_ins.label[0] != '.' ||
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000818 output_ins.label[1] != '.' ||
H. Peter Anvineba20a72002-04-30 20:53:55 +0000819 output_ins.label[2] == '@')
820 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000821 if (output_ins.operands == 1 &&
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000822 (output_ins.oprs[0].type & IMMEDIATE) &&
H. Peter Anvineba20a72002-04-30 20:53:55 +0000823 output_ins.oprs[0].wrt == NO_SEG)
824 {
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000825 int isext = output_ins.oprs[0].opflags & OPFLAG_EXTERN;
826 define_label (output_ins.label,
827 output_ins.oprs[0].segment,
828 output_ins.oprs[0].offset,
829 NULL, FALSE, isext, ofmt, report_error);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000830 }
831 else if (output_ins.operands == 2 &&
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000832 (output_ins.oprs[0].type & IMMEDIATE) &&
833 (output_ins.oprs[0].type & COLON) &&
834 output_ins.oprs[0].segment == NO_SEG &&
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000835 output_ins.oprs[0].wrt == NO_SEG &&
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000836 (output_ins.oprs[1].type & IMMEDIATE) &&
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000837 output_ins.oprs[1].segment == NO_SEG &&
H. Peter Anvineba20a72002-04-30 20:53:55 +0000838 output_ins.oprs[1].wrt == NO_SEG)
839 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000840 define_label (output_ins.label,
841 output_ins.oprs[0].offset | SEG_ABS,
842 output_ins.oprs[1].offset,
H. Peter Anvin76690a12002-04-30 20:52:49 +0000843 NULL, FALSE, FALSE, ofmt, report_error);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000844 }
845 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000846 report_error(ERR_NONFATAL, "bad syntax for EQU");
847 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000848 }
849 else /* instruction isn't an EQU */
850 {
851 long l = insn_size (location.segment, offs, sb,
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000852 &output_ins, report_error);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000853 if (using_debug_info && output_ins.opcode != -1) {
854 /* this is done here so we can do debug type info */
855 long typeinfo = TYS_ELEMENTS(output_ins.operands);
856 switch (output_ins.opcode) {
857 case I_RESB:
858 typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_BYTE;
859 break;
860 case I_RESW:
861 typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_WORD;
862 break;
863 case I_RESD:
864 typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_DWORD;
865 break;
866 case I_RESQ:
867 typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_QWORD;
868 break;
869 case I_REST:
870 typeinfo = TYS_ELEMENTS(output_ins.oprs[0].offset) | TY_TBYTE;
871 break;
872 case I_DB:
873 typeinfo |= TY_BYTE;
874 break;
875 case I_DW:
876 typeinfo |= TY_WORD;
877 break;
878 case I_DD:
879 if (output_ins.eops_float)
880 typeinfo |= TY_FLOAT;
881 else
882 typeinfo |= TY_DWORD;
883 break;
884 case I_DQ:
885 typeinfo |= TY_QWORD;
886 break;
887 case I_DT:
888 typeinfo |= TY_TBYTE;
889 break;
890 default:
891 typeinfo = TY_LABEL;
892 }
893 ofmt->current_dfmt->debug_typevalue(typeinfo);
894 }
895 if (l != -1) {
896 offs += l;
897 set_curr_ofs (offs);
898 }
899 /*
900 * else l == -1 => invalid instruction, which will be
901 * flagged as an error on pass 2
902 */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000903 }
904 cleanup_insn (&output_ins);
905 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000906 nasm_free (line);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000907 location.offset = offs = get_curr_ofs;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000908 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000909
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000910 preproc->cleanup();
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000911
912 if (terminate_after_phase) {
913 fclose(ofile);
914 remove(outname);
915 if (want_usage)
916 usage();
917 exit (1);
918 }
919
H. Peter Anvineba20a72002-04-30 20:53:55 +0000920 /*
921 * pass two
922 */
923
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000924 pass = 2;
H. Peter Anvinea838272002-04-30 20:51:53 +0000925 saa_rewind (forwrefs);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000926 if (*listname)
927 nasmlist.init(listname, report_error);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000928 forwref = saa_rstruct (forwrefs);
929 in_abs_seg = FALSE;
930 location.segment = ofmt->section(NULL, pass, &sb);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000931 raa_free (offsets);
932 offsets = raa_init();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000933 preproc->reset(fname, 2, report_error, evaluate, &nasmlist);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000934 globallineno = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000935 location.offset = offs = get_curr_ofs;
936
937 while ( (line = preproc->getline()) )
938 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000939 globallineno++;
940
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000941 /* here we parse our directives; this is not handled by
942 * the 'real' parser. */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000943 if ( (i = getkw (line, &value)) ) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000944 switch (i) {
945 case 1: /* [SEGMENT n] */
946 seg = ofmt->section (value, pass, &sb);
947 if (seg == NO_SEG) {
948 report_error (ERR_PANIC,
949 "invalid segment name on pass two");
950 } else
H. Peter Anvineba20a72002-04-30 20:53:55 +0000951 in_abs_seg = FALSE;
952 location.segment = seg;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000953 break;
954 case 2: /* [EXTERN label] */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000955 q = value;
956 while (*q && *q != ':')
957 q++;
958 if (*q == ':') {
959 *q++ = '\0';
960 ofmt->symdef(value, 0L, 0L, 3, q);
961 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000962 break;
963 case 3: /* [BITS bits] */
964 switch (atoi(value)) {
965 case 16:
966 case 32:
967 sb = atoi(value);
968 break;
969 default:
970 report_error(ERR_PANIC,
971 "invalid [BITS] value on pass two",
972 value);
973 break;
974 }
975 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000976 case 4: /* [GLOBAL symbol] */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000977 q = value;
978 while (*q && *q != ':')
979 q++;
980 if (*q == ':') {
981 *q++ = '\0';
982 ofmt->symdef(value, 0L, 0L, 3, q);
983 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000984 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000985 case 5: /* [COMMON symbol size] */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000986 q = value;
987 while (*q && *q != ':') {
988 if (isspace(*q))
989 *q = '\0';
990 q++;
991 }
992 if (*q == ':') {
993 *q++ = '\0';
994 ofmt->symdef(value, 0L, 0L, 3, q);
995 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000996 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000997 case 6: /* [ABSOLUTE addr] */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000998 stdscan_reset();
999 stdscan_bufptr = value;
1000 tokval.t_type = TOKEN_INVALID;
1001 e = evaluate(stdscan, NULL, &tokval, NULL, 2, report_error,
1002 NULL);
1003 if (e) {
1004 if (!is_reloc(e))
1005 report_error (ERR_PANIC, "non-reloc ABSOLUTE address"
1006 " in pass two");
1007 else {
1008 abs_seg = reloc_seg(e);
1009 abs_offset = reloc_value(e);
1010 }
1011 } else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001012 report_error (ERR_PANIC, "invalid ABSOLUTE address "
1013 "in pass two");
H. Peter Anvineba20a72002-04-30 20:53:55 +00001014 in_abs_seg = TRUE;
1015 location.segment = abs_seg;
1016 break;
1017 case 7:
1018 p = value;
1019 q = debugid;
1020 validid = TRUE;
1021 if (!isidstart(*p))
1022 validid = FALSE;
1023 while (*p && !isspace(*p)) {
1024 if (!isidchar(*p))
1025 validid = FALSE;
1026 *q++ = *p++;
1027 }
1028 *q++ = 0;
1029 if (!validid) {
1030 report_error (ERR_PANIC,
1031 "identifier expected after DEBUG in pass 2");
1032 break;
1033 }
1034 while (*p && isspace(*p))
1035 p++;
1036 ofmt->current_dfmt->debug_directive (debugid, p);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001037 break;
1038 default:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001039 if (!ofmt->directive (line+1, value, 2))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001040 report_error (ERR_PANIC, "invalid directive on pass two");
1041 break;
1042 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001043 }
1044 else /* not a directive */
1045 {
H. Peter Anvin76690a12002-04-30 20:52:49 +00001046 parse_line (2, line, &output_ins,
H. Peter Anvineba20a72002-04-30 20:53:55 +00001047 report_error, evaluate, redefine_label);
1048 if (forwref != NULL && globallineno == forwref->lineno) {
H. Peter Anvinea838272002-04-30 20:51:53 +00001049 output_ins.forw_ref = TRUE;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001050 do {
1051 output_ins.oprs[forwref->operand].opflags|= OPFLAG_FORWARD;
1052 forwref = saa_rstruct (forwrefs);
1053 } while (forwref != NULL && forwref->lineno == globallineno);
H. Peter Anvinea838272002-04-30 20:51:53 +00001054 } else
1055 output_ins.forw_ref = FALSE;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001056
1057 /*
1058 * Hack to prevent phase error in the code
1059 * rol ax,x
1060 * x equ 1
H. Peter Anvineba20a72002-04-30 20:53:55 +00001061 *
1062 * If the second operand is a forward reference,
1063 * the UNITY property of the number 1 in that
1064 * operand is cancelled. Otherwise the above
1065 * sequence will cause a phase error.
1066 *
1067 * This hack means that the above code will
1068 * generate 286+ code.
1069 *
1070 * The forward reference will mean that the
1071 * operand will not have the UNITY property on
1072 * the first pass, so the pass behaviours will
1073 * be consistent.
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001074 */
H. Peter Anvineba20a72002-04-30 20:53:55 +00001075
1076 if (output_ins.forw_ref &&
1077 output_ins.operands >= 2 &&
1078 (output_ins.oprs[1].opflags & OPFLAG_FORWARD))
1079 {
1080 output_ins.oprs[1].type &= ~ONENESS;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001081 }
1082
H. Peter Anvineba20a72002-04-30 20:53:55 +00001083 if (output_ins.opcode == I_EQU)
1084 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001085 /*
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001086 * Special `..' EQUs get processed here, except
1087 * `..@' macro processor EQUs which are done above.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001088 */
1089 if (output_ins.label[0] == '.' &&
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001090 output_ins.label[1] == '.' &&
H. Peter Anvineba20a72002-04-30 20:53:55 +00001091 output_ins.label[2] != '@')
1092 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001093 if (output_ins.operands == 1 &&
1094 (output_ins.oprs[0].type & IMMEDIATE)) {
1095 define_label (output_ins.label,
1096 output_ins.oprs[0].segment,
1097 output_ins.oprs[0].offset,
H. Peter Anvin76690a12002-04-30 20:52:49 +00001098 NULL, FALSE, FALSE, ofmt, report_error);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001099 }
1100 else if (output_ins.operands == 2 &&
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001101 (output_ins.oprs[0].type & IMMEDIATE) &&
1102 (output_ins.oprs[0].type & COLON) &&
1103 output_ins.oprs[0].segment == NO_SEG &&
1104 (output_ins.oprs[1].type & IMMEDIATE) &&
H. Peter Anvineba20a72002-04-30 20:53:55 +00001105 output_ins.oprs[1].segment == NO_SEG)
1106 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001107 define_label (output_ins.label,
1108 output_ins.oprs[0].offset | SEG_ABS,
1109 output_ins.oprs[1].offset,
H. Peter Anvin76690a12002-04-30 20:52:49 +00001110 NULL, FALSE, FALSE, ofmt, report_error);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001111 }
1112 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001113 report_error(ERR_NONFATAL, "bad syntax for EQU");
1114 }
1115 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001116 offs += assemble (location.segment, offs, sb,
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001117 &output_ins, ofmt, report_error, &nasmlist);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001118 cleanup_insn (&output_ins);
1119 set_curr_ofs (offs);
1120 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001121
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001122 nasm_free (line);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001123
H. Peter Anvineba20a72002-04-30 20:53:55 +00001124 location.offset = offs = get_curr_ofs;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001125 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001126
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001127 preproc->cleanup();
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001128 nasmlist.cleanup();
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001129}
1130
H. Peter Anvineba20a72002-04-30 20:53:55 +00001131static int getkw (char *buf, char **value)
1132{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001133 char *p, *q;
1134
1135 if (*buf!='[')
1136 return 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001137
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001138 p = buf;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001139
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001140 while (*p && *p != ']') p++;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001141
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001142 if (!*p)
1143 return 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001144
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001145 q = p++;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001146
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001147 while (*p && *p != ';') {
1148 if (!isspace(*p))
1149 return 0;
1150 p++;
1151 }
1152 q[1] = '\0';
1153
1154 p = buf+1;
1155 while (*buf && *buf!=' ' && *buf!=']' && *buf!='\t')
1156 buf++;
1157 if (*buf==']') {
1158 *buf = '\0';
1159 *value = buf;
1160 } else {
1161 *buf++ = '\0';
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001162 while (isspace(*buf)) buf++; /* beppu - skip leading whitespace */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001163 *value = buf;
1164 while (*buf!=']') buf++;
1165 *buf++ = '\0';
1166 }
1167 for (q=p; *q; q++)
1168 *q = tolower(*q);
1169 if (!strcmp(p, "segment") || !strcmp(p, "section"))
1170 return 1;
1171 if (!strcmp(p, "extern"))
1172 return 2;
1173 if (!strcmp(p, "bits"))
1174 return 3;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001175 if (!strcmp(p, "global"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001176 return 4;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001177 if (!strcmp(p, "common"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001178 return 5;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001179 if (!strcmp(p, "absolute"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001180 return 6;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001181 if (!strcmp(p, "debug"))
1182 return 7;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001183 return -1;
1184}
1185
H. Peter Anvineba20a72002-04-30 20:53:55 +00001186static void report_error (int severity, char *fmt, ...)
1187{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001188 va_list ap;
1189
H. Peter Anvin6768eb72002-04-30 20:52:26 +00001190 /*
1191 * See if it's a suppressed warning.
1192 */
1193 if ((severity & ERR_MASK) == ERR_WARNING &&
1194 (severity & ERR_WARN_MASK) != 0 &&
1195 suppressed[ (severity & ERR_WARN_MASK) >> ERR_WARN_SHR ])
1196 return; /* and bail out if so */
1197
H. Peter Anvin76690a12002-04-30 20:52:49 +00001198 /*
1199 * See if it's a pass-one only warning and we're not in pass one.
1200 */
1201 if ((severity & ERR_PASS1) && pass != 1)
1202 return;
1203
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001204 if (severity & ERR_NOFILE)
H. Peter Anvin620515a2002-04-30 20:57:38 +00001205 fputs ("nasm: ", error_file);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001206 else {
1207 char * currentfile = NULL;
1208 long lineno = 0;
1209 src_get (&lineno, &currentfile);
H. Peter Anvin620515a2002-04-30 20:57:38 +00001210 fprintf (error_file, "%s:%ld: ", currentfile, lineno);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001211 nasm_free (currentfile);
1212 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001213
1214 if ( (severity & ERR_MASK) == ERR_WARNING)
H. Peter Anvin620515a2002-04-30 20:57:38 +00001215 fputs ("warning: ", error_file);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001216 else if ( (severity & ERR_MASK) == ERR_PANIC)
H. Peter Anvin620515a2002-04-30 20:57:38 +00001217 fputs ("panic: ", error_file);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001218
1219 va_start (ap, fmt);
H. Peter Anvin620515a2002-04-30 20:57:38 +00001220 vfprintf (error_file, fmt, ap);
1221 fputc ('\n', error_file);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001222
1223 if (severity & ERR_USAGE)
1224 want_usage = TRUE;
1225
1226 switch (severity & ERR_MASK) {
1227 case ERR_WARNING:
1228 /* no further action, by definition */
1229 break;
1230 case ERR_NONFATAL:
1231 terminate_after_phase = TRUE;
1232 break;
1233 case ERR_FATAL:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001234 if (ofile) {
1235 fclose(ofile);
1236 remove(outname);
1237 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001238 if (want_usage)
1239 usage();
1240 exit(1); /* instantly die */
1241 break; /* placate silly compilers */
1242 case ERR_PANIC:
H. Peter Anvin620515a2002-04-30 20:57:38 +00001243 fflush(NULL);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001244 abort(); /* halt, catch fire, and dump core */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001245 break;
1246 }
1247}
1248
H. Peter Anvineba20a72002-04-30 20:53:55 +00001249static void usage(void)
1250{
H. Peter Anvin620515a2002-04-30 20:57:38 +00001251 fputs("type `nasm -h' for help\n", error_file);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001252}
1253
H. Peter Anvineba20a72002-04-30 20:53:55 +00001254static void register_output_formats(void)
1255{
1256 ofmt = ofmt_register (report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001257}
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001258
1259#define BUF_DELTA 512
1260
1261static FILE *no_pp_fp;
1262static efunc no_pp_err;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001263static ListGen *no_pp_list;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001264static long no_pp_lineinc;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001265
H. Peter Anvin76690a12002-04-30 20:52:49 +00001266static void no_pp_reset (char *file, int pass, efunc error, evalfunc eval,
H. Peter Anvineba20a72002-04-30 20:53:55 +00001267 ListGen *listgen)
1268{
1269 src_set_fname(nasm_strdup(file));
1270 src_set_linnum(0);
1271 no_pp_lineinc = 1;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001272 no_pp_err = error;
1273 no_pp_fp = fopen(file, "r");
1274 if (!no_pp_fp)
1275 no_pp_err (ERR_FATAL | ERR_NOFILE,
1276 "unable to open input file `%s'", file);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001277 no_pp_list = listgen;
1278 (void) pass; /* placate compilers */
1279 (void) eval; /* placate compilers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001280}
1281
H. Peter Anvineba20a72002-04-30 20:53:55 +00001282static char *no_pp_getline (void)
1283{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001284 char *buffer, *p, *q;
1285 int bufsize;
1286
1287 bufsize = BUF_DELTA;
1288 buffer = nasm_malloc(BUF_DELTA);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001289 src_set_linnum(src_get_linnum() + no_pp_lineinc);
1290
1291 while (1) { /* Loop to handle %line */
1292
1293 p = buffer;
1294 while (1) { /* Loop to handle long lines */
1295 q = fgets(p, bufsize-(p-buffer), no_pp_fp);
1296 if (!q)
1297 break;
1298 p += strlen(p);
1299 if (p > buffer && p[-1] == '\n')
1300 break;
1301 if (p-buffer > bufsize-10) {
1302 int offset;
1303 offset = p - buffer;
1304 bufsize += BUF_DELTA;
1305 buffer = nasm_realloc(buffer, bufsize);
1306 p = buffer + offset;
1307 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001308 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001309
1310 if (!q && p == buffer) {
1311 nasm_free (buffer);
1312 return NULL;
1313 }
1314
1315 /*
1316 * Play safe: remove CRs, LFs and any spurious ^Zs, if any of
1317 * them are present at the end of the line.
1318 */
1319 buffer[strcspn(buffer, "\r\n\032")] = '\0';
1320
1321 if (!strncmp(buffer, "%line", 5)) {
1322 long ln;
1323 int li;
1324 char *nm = nasm_malloc(strlen(buffer));
1325 if (sscanf(buffer+5, "%ld+%d %s", &ln, &li, nm) == 3) {
1326 nasm_free( src_set_fname(nm) );
1327 src_set_linnum(ln);
1328 no_pp_lineinc = li;
1329 continue;
1330 }
1331 nasm_free(nm);
1332 }
1333 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001334 }
1335
H. Peter Anvin76690a12002-04-30 20:52:49 +00001336 no_pp_list->line (LIST_READ, buffer);
1337
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001338 return buffer;
1339}
1340
H. Peter Anvineba20a72002-04-30 20:53:55 +00001341static void no_pp_cleanup (void)
1342{
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001343 fclose(no_pp_fp);
1344}