NASM 0.96
[nasm/avx512.git] / nasm.c
bloba1e4dd8aba6ee02bfaf373e39613e4dee27b2032
1 /* The Netwide Assembler main program module
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 */
9 #include <stdio.h>
10 #include <stdarg.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
15 #include "nasm.h"
16 #include "nasmlib.h"
17 #include "preproc.h"
18 #include "parser.h"
19 #include "eval.h"
20 #include "assemble.h"
21 #include "labels.h"
22 #include "outform.h"
23 #include "listing.h"
25 static void report_error (int, char *, ...);
26 static void parse_cmdline (int, char **);
27 static void assemble_file (char *);
28 static int getkw (char *buf, char **value);
29 static void register_output_formats(void);
30 static void usage(void);
32 static char *obuf;
33 static char inname[FILENAME_MAX];
34 static char outname[FILENAME_MAX];
35 static char listname[FILENAME_MAX];
36 static int lineno; /* for error reporting */
37 static int lineinc; /* set by [LINE] or [ONELINE] */
38 static int globallineno; /* for forward-reference tracking */
39 static int pass;
40 static struct ofmt *ofmt = NULL;
42 static FILE *ofile = NULL;
43 static int sb = 16; /* by default */
45 static int use_stdout = FALSE; /* by default, errors to stderr */
47 static long current_seg, abs_seg;
48 static struct RAA *offsets;
49 static long abs_offset;
51 static struct SAA *forwrefs; /* keep track of forward references */
52 static int forwline;
54 static Preproc *preproc;
55 static int preprocess_only;
57 /* used by error function to report location */
58 static char currentfile[FILENAME_MAX];
61 * Which of the suppressible warnings are suppressed. Entry zero
62 * doesn't do anything. Initial defaults are given here.
64 static char suppressed[1+ERR_WARN_MAX] = {
65 0, FALSE, TRUE, FALSE
69 * The option names for the suppressible warnings. As before, entry
70 * zero does nothing.
72 static char *suppressed_names[1+ERR_WARN_MAX] = {
73 NULL, "macro-params", "orphan-labels", "number-overflow"
77 * The explanations for the suppressible warnings. As before, entry
78 * zero does nothing.
80 static char *suppressed_what[1+ERR_WARN_MAX] = {
81 NULL, "macro calls with wrong no. of params",
82 "labels alone on lines without trailing `:'",
83 "numeric constants greater than 0xFFFFFFFF"
87 * This is a null preprocessor which just copies lines from input
88 * to output. It's used when someone explicitly requests that NASM
89 * not preprocess their source file.
92 static void no_pp_reset (char *, int, efunc, evalfunc, ListGen *);
93 static char *no_pp_getline (void);
94 static void no_pp_cleanup (void);
95 static Preproc no_pp = {
96 no_pp_reset,
97 no_pp_getline,
98 no_pp_cleanup
102 * get/set current offset...
104 #define get_curr_ofs (current_seg==NO_SEG?abs_offset:\
105 raa_read(offsets,current_seg))
106 #define set_curr_ofs(x) (current_seg==NO_SEG?(void)(abs_offset=(x)):\
107 (void)(offsets=raa_write(offsets,current_seg,(x))))
109 static int want_usage;
110 static int terminate_after_phase;
112 int main(int argc, char **argv) {
113 want_usage = terminate_after_phase = FALSE;
115 nasm_set_malloc_error (report_error);
116 offsets = raa_init();
117 forwrefs = saa_init ((long)sizeof(int));
119 preproc = &nasmpp;
120 preprocess_only = FALSE;
122 seg_init();
124 register_output_formats();
126 parse_cmdline(argc, argv);
128 if (terminate_after_phase) {
129 if (want_usage)
130 usage();
131 return 1;
134 if (ofmt->stdmac)
135 pp_extra_stdmac (ofmt->stdmac);
136 eval_global_info (ofmt, lookup_label);
138 if (preprocess_only) {
139 char *line;
141 if (*outname) {
142 ofile = fopen(outname, "w");
143 if (!ofile)
144 report_error (ERR_FATAL | ERR_NOFILE,
145 "unable to open output file `%s'", outname);
146 } else
147 ofile = NULL;
149 eval_info ("%", 0L, 0L); /* disallow labels, $ or $$ in exprs */
151 preproc->reset (inname, 2, report_error, evaluate, &nasmlist);
152 strcpy(currentfile,inname);
153 lineno = 0;
154 lineinc = 1;
155 while ( (line = preproc->getline()) ) {
156 int ln, li;
157 char buf[FILENAME_MAX];
159 lineno += lineinc;
161 * We must still check for %line directives, so that we
162 * can report errors accurately.
164 if (!strncmp(line, "%line", 5) &&
165 sscanf(line, "%%line %d+%d %s", &ln, &li, buf) == 3) {
166 lineno = ln - li;
167 lineinc = li;
168 strncpy (currentfile, buf, FILENAME_MAX-1);
169 currentfile[FILENAME_MAX-1] = '\0';
171 if (ofile) {
172 fputs(line, ofile);
173 fputc('\n', ofile);
174 } else
175 puts(line);
176 nasm_free (line);
178 preproc->cleanup();
179 if (ofile)
180 fclose(ofile);
181 if (ofile && terminate_after_phase)
182 remove(outname);
183 } else {
185 * We must call ofmt->filename _anyway_, even if the user
186 * has specified their own output file, because some
187 * formats (eg OBJ and COFF) use ofmt->filename to find out
188 * the name of the input file and then put that inside the
189 * file.
191 ofmt->filename (inname, outname, report_error);
193 ofile = fopen(outname, "wb");
194 if (!ofile) {
195 report_error (ERR_FATAL | ERR_NOFILE,
196 "unable to open output file `%s'", outname);
199 * We must call init_labels() before ofmt->init() since
200 * some object formats will want to define labels in their
201 * init routines. (eg OS/2 defines the FLAT group)
203 init_labels ();
204 ofmt->init (ofile, report_error, define_label, evaluate);
205 assemble_file (inname);
206 if (!terminate_after_phase) {
207 ofmt->cleanup ();
208 cleanup_labels ();
211 * We had an fclose on the output file here, but we
212 * actually do that in all the object file drivers as well,
213 * so we're leaving out the one here.
214 * fclose (ofile);
216 if (terminate_after_phase) {
217 remove(outname);
218 if (listname[0])
219 remove(listname);
223 if (want_usage)
224 usage();
225 raa_free (offsets);
226 saa_free (forwrefs);
228 if (terminate_after_phase)
229 return 1;
230 else
231 return 0;
234 static int process_arg (char *p, char *q) {
235 char *param;
236 int i;
237 int advance = 0;
239 if (!p || !p[0])
240 return 0;
242 if (p[0]=='-') {
243 switch (p[1]) {
244 case 's':
245 use_stdout = TRUE;
246 break;
247 case 'o': /* these parameters take values */
248 case 'f':
249 case 'p':
250 case 'd':
251 case 'i':
252 case 'l':
253 if (p[2]) /* the parameter's in the option */
254 param = p+2;
255 else if (!q) {
256 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
257 "option `-%c' requires an argument",
258 p[1]);
259 break;
260 } else
261 advance = 1, param = q;
262 if (p[1]=='o') { /* output file */
263 strcpy (outname, param);
264 } else if (p[1]=='f') { /* output format */
265 ofmt = ofmt_find(param);
266 if (!ofmt) {
267 report_error (ERR_FATAL | ERR_NOFILE | ERR_USAGE,
268 "unrecognised output format `%s'",
269 param);
271 } else if (p[1]=='p') { /* pre-include */
272 pp_pre_include (param);
273 } else if (p[1]=='d') { /* pre-define */
274 pp_pre_define (param);
275 } else if (p[1]=='i') { /* include search path */
276 pp_include_path (param);
277 } else if (p[1]=='l') { /* listing file */
278 strcpy (listname, param);
280 break;
281 case 'h':
282 fprintf(use_stdout ? stdout : stderr,
283 "usage: nasm [-o outfile] [-f format] [-l listfile]"
284 " [options...] filename\n");
285 fprintf(use_stdout ? stdout : stderr,
286 " or nasm -r for version info\n\n");
287 fprintf(use_stdout ? stdout : stderr,
288 " -e means preprocess only; "
289 "-a means don't preprocess\n");
290 fprintf(use_stdout ? stdout : stderr,
291 " -s means send errors to stdout not stderr\n");
292 fprintf(use_stdout ? stdout : stderr,
293 " -i<path> adds a pathname to the include file"
294 " path\n -p<file> pre-includes a file;"
295 " -d<macro>[=<value] pre-defines a macro\n");
296 fprintf(use_stdout ? stdout : stderr,
297 " -w+foo enables warnings about foo; "
298 "-w-foo disables them\n where foo can be:\n");
299 for (i=1; i<=ERR_WARN_MAX; i++)
300 fprintf(use_stdout ? stdout : stderr,
301 " %-16s%s (default %s)\n",
302 suppressed_names[i], suppressed_what[i],
303 suppressed[i] ? "off" : "on");
304 fprintf(use_stdout ? stdout : stderr,
305 "\nvalid output formats for -f are"
306 " (`*' denotes default):\n");
307 ofmt_list(ofmt, use_stdout ? stdout : stderr);
308 exit (0); /* never need usage message here */
309 break;
310 case 'r':
311 fprintf(use_stdout ? stdout : stderr,
312 "NASM version %s\n", NASM_VER);
313 exit (0); /* never need usage message here */
314 break;
315 case 'e': /* preprocess only */
316 preprocess_only = TRUE;
317 break;
318 case 'a': /* assemble only - don't preprocess */
319 preproc = &no_pp;
320 break;
321 case 'w':
322 if (p[2] != '+' && p[2] != '-') {
323 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
324 "invalid option to `-w'");
325 } else {
326 for (i=1; i<=ERR_WARN_MAX; i++)
327 if (!nasm_stricmp(p+3, suppressed_names[i]))
328 break;
329 if (i <= ERR_WARN_MAX)
330 suppressed[i] = (p[2] == '-');
331 else
332 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
333 "invalid option to `-w'");
335 break;
336 default:
337 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
338 "unrecognised option `-%c'",
339 p[1]);
340 break;
342 } else {
343 if (*inname) {
344 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
345 "more than one input file specified");
346 } else
347 strcpy(inname, p);
350 return advance;
353 static void parse_cmdline(int argc, char **argv) {
354 char *envreal, *envcopy, *p, *q, *arg, *prevarg;
355 char separator = ' ';
357 *inname = *outname = *listname = '\0';
360 * First, process the NASM environment variable.
362 envreal = getenv("NASM");
363 arg = NULL;
364 if (envreal) {
365 envcopy = nasm_strdup(envreal);
366 p = envcopy;
367 if (*p && *p != '-')
368 separator = *p++;
369 while (*p) {
370 q = p;
371 while (*p && *p != separator) p++;
372 while (*p == separator) *p++ = '\0';
373 prevarg = arg;
374 arg = q;
375 if (process_arg (prevarg, arg))
376 arg = NULL;
378 nasm_free (envcopy);
380 if (arg)
381 process_arg (arg, NULL);
384 * Now process the actual command line.
386 while (--argc) {
387 int i;
388 argv++;
389 i = process_arg (argv[0], argc > 1 ? argv[1] : NULL);
390 argv += i, argc -= i;
393 if (!*inname)
394 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
395 "no input file specified");
398 static void assemble_file (char *fname) {
399 char *value, *p, *q, *special, *line;
400 insn output_ins;
401 int i, rn_error, validid;
402 long seg, offs;
403 struct tokenval tokval;
404 expr *e;
406 /* pass one */
407 pass = 1;
408 current_seg = ofmt->section(NULL, pass, &sb);
409 preproc->reset(fname, 1, report_error, evaluate, &nasmlist);
410 strcpy(currentfile,fname);
411 lineno = 0;
412 lineinc = 1;
413 globallineno = 0;
414 offs = get_curr_ofs;
415 eval_info (NULL, current_seg, offs); /* set $ */
416 while ( (line = preproc->getline()) ) {
417 lineno += lineinc;
418 globallineno++;
420 if (line[0] == '%') {
421 int ln, li;
422 char buf[FILENAME_MAX];
425 * This will be a line number directive. They come
426 * straight from the preprocessor, so we'll subject
427 * them to only minimal error checking.
429 if (strncmp(line, "%line", 5)) {
430 if (preproc == &no_pp)
431 report_error (ERR_WARNING, "unknown `%%' directive in "
432 " preprocessed source");
433 } else if (sscanf(line, "%%line %d+%d %s", &ln, &li, buf) != 3) {
434 report_error (ERR_WARNING, "bogus line number directive in"
435 " preprocessed source");
436 } else {
437 lineno = ln - li;
438 lineinc = li;
439 strncpy (currentfile, buf, FILENAME_MAX-1);
440 currentfile[FILENAME_MAX-1] = '\0';
442 continue;
445 /* here we parse our directives; this is not handled by the 'real'
446 * parser. */
447 if ( (i = getkw (line, &value)) ) {
448 switch (i) {
449 case 1: /* [SEGMENT n] */
450 seg = ofmt->section (value, pass, &sb);
451 if (seg == NO_SEG) {
452 report_error (ERR_NONFATAL,
453 "segment name `%s' not recognised",
454 value);
455 } else {
456 current_seg = seg;
458 break;
459 case 2: /* [EXTERN label:special] */
460 if (*value == '$')
461 value++; /* skip initial $ if present */
462 q = value;
463 validid = TRUE;
464 if (!isidstart(*q))
465 validid = FALSE;
466 while (*q && *q != ':') {
467 if (!isidchar(*q))
468 validid = FALSE;
469 q++;
471 if (!validid) {
472 report_error (ERR_NONFATAL,
473 "identifier expected after EXTERN");
474 break;
476 if (*q == ':') {
477 *q++ = '\0';
478 special = q;
479 } else
480 special = NULL;
481 if (!is_extern(value)) { /* allow re-EXTERN to be ignored */
482 declare_as_global (value, special, report_error);
483 define_label (value, seg_alloc(), 0L, NULL, FALSE, TRUE,
484 ofmt, report_error);
486 break;
487 case 3: /* [BITS bits] */
488 switch (atoi(value)) {
489 case 16:
490 case 32:
491 sb = atoi(value);
492 break;
493 default:
494 report_error(ERR_NONFATAL,
495 "`%s' is not a valid argument to [BITS]",
496 value);
497 break;
499 break;
500 case 4: /* [GLOBAL symbol:special] */
501 if (*value == '$')
502 value++; /* skip initial $ if present */
503 q = value;
504 validid = TRUE;
505 if (!isidstart(*q))
506 validid = FALSE;
507 while (*q && *q != ':') {
508 if (!isidchar(*q))
509 validid = FALSE;
510 q++;
512 if (!validid) {
513 report_error (ERR_NONFATAL,
514 "identifier expected after GLOBAL");
515 break;
517 if (*q == ':') {
518 *q++ = '\0';
519 special = q;
520 } else
521 special = NULL;
522 declare_as_global (value, special, report_error);
523 break;
524 case 5: /* [COMMON symbol size:special] */
525 p = value;
526 validid = TRUE;
527 if (!isidstart(*p))
528 validid = FALSE;
529 while (*p && !isspace(*p)) {
530 if (!isidchar(*p))
531 validid = FALSE;
532 p++;
534 if (!validid) {
535 report_error (ERR_NONFATAL,
536 "identifier expected after COMMON");
537 break;
539 if (*p) {
540 long size;
542 while (*p && isspace(*p))
543 *p++ = '\0';
544 q = p;
545 while (*q && *q != ':')
546 q++;
547 if (*q == ':') {
548 *q++ = '\0';
549 special = q;
550 } else
551 special = NULL;
552 size = readnum (p, &rn_error);
553 if (rn_error)
554 report_error (ERR_NONFATAL, "invalid size specified"
555 " in COMMON declaration");
556 else
557 define_common (value, seg_alloc(), size,
558 special, ofmt, report_error);
559 } else
560 report_error (ERR_NONFATAL, "no size specified in"
561 " COMMON declaration");
562 break;
563 case 6: /* [ABSOLUTE address] */
564 current_seg = NO_SEG;
565 stdscan_reset();
566 stdscan_bufptr = value;
567 tokval.t_type = TOKEN_INVALID;
568 e = evaluate(stdscan, NULL, &tokval, NULL, 1, report_error,
569 NULL);
570 if (e) {
571 if (!is_reloc(e))
572 report_error (ERR_NONFATAL, "cannot use non-"
573 "relocatable expression as ABSOLUTE"
574 " address");
575 else {
576 abs_seg = reloc_seg(e);
577 abs_offset = reloc_value(e);
579 } else
580 abs_offset = 0x100;/* don't go near zero in case of / */
581 break;
582 default:
583 if (!ofmt->directive (line+1, value, 1))
584 report_error (ERR_NONFATAL, "unrecognised directive [%s]",
585 line+1);
586 break;
588 } else {
589 parse_line (1, line, &output_ins,
590 report_error, evaluate, eval_info);
591 if (output_ins.forw_ref)
592 *(int *)saa_wstruct(forwrefs) = globallineno;
595 * Hack to prevent phase error in the code
596 * rol ax,x
597 * x equ 1
599 * We rule that the presence of a forward reference
600 * cancels out the UNITY property of the number 1. This
601 * isn't _strictly_ necessary in pass one, since the
602 * problem occurs in pass two, but for the sake of
603 * having the passes as near to identical as we can
604 * manage, we do it like this.
606 if (output_ins.forw_ref) {
607 int i;
608 for (i=0; i<output_ins.operands; i++)
609 output_ins.oprs[i].type &= ~ONENESS;
612 if (output_ins.opcode == I_EQU) {
614 * Special `..' EQUs get processed in pass two,
615 * except `..@' macro-processor EQUs which are done
616 * in the normal place.
618 if (!output_ins.label)
619 report_error (ERR_NONFATAL,
620 "EQU not preceded by label");
621 else if (output_ins.label[0] != '.' ||
622 output_ins.label[1] != '.' ||
623 output_ins.label[2] == '@') {
624 if (output_ins.operands == 1 &&
625 (output_ins.oprs[0].type & IMMEDIATE) &&
626 output_ins.oprs[0].wrt == NO_SEG) {
627 define_label (output_ins.label,
628 output_ins.oprs[0].segment,
629 output_ins.oprs[0].offset,
630 NULL, FALSE, FALSE, ofmt, report_error);
631 } else if (output_ins.operands == 2 &&
632 (output_ins.oprs[0].type & IMMEDIATE) &&
633 (output_ins.oprs[0].type & COLON) &&
634 output_ins.oprs[0].segment == NO_SEG &&
635 output_ins.oprs[0].wrt == NO_SEG &&
636 (output_ins.oprs[1].type & IMMEDIATE) &&
637 output_ins.oprs[1].segment == NO_SEG &&
638 output_ins.oprs[1].wrt == NO_SEG) {
639 define_label (output_ins.label,
640 output_ins.oprs[0].offset | SEG_ABS,
641 output_ins.oprs[1].offset,
642 NULL, FALSE, FALSE, ofmt, report_error);
643 } else
644 report_error(ERR_NONFATAL, "bad syntax for EQU");
646 } else {
647 if (output_ins.label)
648 define_label (output_ins.label,
649 current_seg==NO_SEG ? abs_seg : current_seg,
650 offs, NULL, TRUE, FALSE, ofmt, report_error);
651 offs += insn_size (current_seg, offs, sb,
652 &output_ins, report_error);
653 set_curr_ofs (offs);
655 cleanup_insn (&output_ins);
657 nasm_free (line);
658 offs = get_curr_ofs;
659 eval_info (NULL, current_seg, offs); /* set $ */
661 preproc->cleanup();
663 if (terminate_after_phase) {
664 fclose(ofile);
665 remove(outname);
666 if (want_usage)
667 usage();
668 exit (1);
671 /* pass two */
672 pass = 2;
673 saa_rewind (forwrefs);
674 if (*listname)
675 nasmlist.init(listname, report_error);
677 int *p = saa_rstruct (forwrefs);
678 if (p)
679 forwline = *p;
680 else
681 forwline = -1;
683 current_seg = ofmt->section(NULL, pass, &sb);
684 raa_free (offsets);
685 offsets = raa_init();
686 preproc->reset(fname, 2, report_error, evaluate, &nasmlist);
687 strcpy(currentfile,fname);
688 lineno = 0;
689 lineinc = 1;
690 globallineno = 0;
691 offs = get_curr_ofs;
692 eval_info (NULL, current_seg, offs); /* set $ */
693 while ( (line = preproc->getline()) ) {
694 lineno += lineinc;
695 globallineno++;
697 if (line[0] == '%') {
698 int ln, li;
699 char buf[FILENAME_MAX];
702 * This will be a line number directive. They come
703 * straight from the preprocessor, so we'll subject
704 * them to only minimal error checking.
706 if (!strncmp(line, "%line", 5) &&
707 sscanf(line, "%%line %d+%d %s", &ln, &li, buf) == 3) {
708 lineno = ln - li;
709 lineinc = li;
710 strncpy (currentfile, buf, FILENAME_MAX-1);
711 currentfile[FILENAME_MAX-1] = '\0';
713 continue;
716 /* here we parse our directives; this is not handled by
717 * the 'real' parser. */
718 if ( (i = getkw (line, &value)) ) {
719 switch (i) {
720 case 1: /* [SEGMENT n] */
721 seg = ofmt->section (value, pass, &sb);
722 if (seg == NO_SEG) {
723 report_error (ERR_PANIC,
724 "invalid segment name on pass two");
725 } else
726 current_seg = seg;
727 break;
728 case 2: /* [EXTERN label] */
729 q = value;
730 while (*q && *q != ':')
731 q++;
732 if (*q == ':') {
733 *q++ = '\0';
734 ofmt->symdef(value, 0L, 0L, 3, q);
736 break;
737 case 3: /* [BITS bits] */
738 switch (atoi(value)) {
739 case 16:
740 case 32:
741 sb = atoi(value);
742 break;
743 default:
744 report_error(ERR_PANIC,
745 "invalid [BITS] value on pass two",
746 value);
747 break;
749 break;
750 case 4: /* [GLOBAL symbol] */
751 q = value;
752 while (*q && *q != ':')
753 q++;
754 if (*q == ':') {
755 *q++ = '\0';
756 ofmt->symdef(value, 0L, 0L, 3, q);
758 break;
759 case 5: /* [COMMON symbol size] */
760 q = value;
761 while (*q && *q != ':') {
762 if (isspace(*q))
763 *q = '\0';
764 q++;
766 if (*q == ':') {
767 *q++ = '\0';
768 ofmt->symdef(value, 0L, 0L, 3, q);
770 break;
771 case 6: /* [ABSOLUTE addr] */
772 current_seg = NO_SEG;
773 stdscan_reset();
774 stdscan_bufptr = value;
775 tokval.t_type = TOKEN_INVALID;
776 e = evaluate(stdscan, NULL, &tokval, NULL, 2, report_error,
777 NULL);
778 if (e) {
779 if (!is_reloc(e))
780 report_error (ERR_PANIC, "non-reloc ABSOLUTE address"
781 " in pass two");
782 else {
783 abs_seg = reloc_seg(e);
784 abs_offset = reloc_value(e);
786 } else
787 report_error (ERR_PANIC, "invalid ABSOLUTE address "
788 "in pass two");
789 break;
790 default:
791 if (!ofmt->directive (line+1, value, 2))
792 report_error (ERR_PANIC, "invalid directive on pass two");
793 break;
795 } else {
796 parse_line (2, line, &output_ins,
797 report_error, evaluate, eval_info);
798 if (globallineno == forwline) {
799 int *p = saa_rstruct (forwrefs);
800 if (p)
801 forwline = *p;
802 else
803 forwline = -1;
804 output_ins.forw_ref = TRUE;
805 } else
806 output_ins.forw_ref = FALSE;
809 * Hack to prevent phase error in the code
810 * rol ax,x
811 * x equ 1
813 if (output_ins.forw_ref) {
814 int i;
815 for (i=0; i<output_ins.operands; i++)
816 output_ins.oprs[i].type &= ~ONENESS;
819 obuf = line;
820 if (output_ins.label)
821 define_label_stub (output_ins.label, report_error);
822 if (output_ins.opcode == I_EQU) {
824 * Special `..' EQUs get processed here, except
825 * `..@' macro processor EQUs which are done above.
827 if (output_ins.label[0] == '.' &&
828 output_ins.label[1] == '.' &&
829 output_ins.label[2] != '@') {
830 if (output_ins.operands == 1 &&
831 (output_ins.oprs[0].type & IMMEDIATE)) {
832 define_label (output_ins.label,
833 output_ins.oprs[0].segment,
834 output_ins.oprs[0].offset,
835 NULL, FALSE, FALSE, ofmt, report_error);
836 } else if (output_ins.operands == 2 &&
837 (output_ins.oprs[0].type & IMMEDIATE) &&
838 (output_ins.oprs[0].type & COLON) &&
839 output_ins.oprs[0].segment == NO_SEG &&
840 (output_ins.oprs[1].type & IMMEDIATE) &&
841 output_ins.oprs[1].segment == NO_SEG) {
842 define_label (output_ins.label,
843 output_ins.oprs[0].offset | SEG_ABS,
844 output_ins.oprs[1].offset,
845 NULL, FALSE, FALSE, ofmt, report_error);
846 } else
847 report_error(ERR_NONFATAL, "bad syntax for EQU");
850 offs += assemble (current_seg, offs, sb,
851 &output_ins, ofmt, report_error, &nasmlist);
852 cleanup_insn (&output_ins);
853 set_curr_ofs (offs);
855 nasm_free (line);
857 offs = get_curr_ofs;
858 eval_info (NULL, current_seg, offs); /* set $ */
860 preproc->cleanup();
861 nasmlist.cleanup();
864 static int getkw (char *buf, char **value) {
865 char *p, *q;
867 if (*buf!='[')
868 return 0;
869 p = buf;
870 while (*p && *p != ']') p++;
871 if (!*p)
872 return 0;
873 q = p++;
874 while (*p && *p != ';') {
875 if (!isspace(*p))
876 return 0;
877 p++;
879 q[1] = '\0';
881 p = buf+1;
882 while (*buf && *buf!=' ' && *buf!=']' && *buf!='\t')
883 buf++;
884 if (*buf==']') {
885 *buf = '\0';
886 *value = buf;
887 } else {
888 *buf++ = '\0';
889 while (isspace(*buf)) buf++; /* beppu - skip leading whitespace */
890 *value = buf;
891 while (*buf!=']') buf++;
892 *buf++ = '\0';
894 for (q=p; *q; q++)
895 *q = tolower(*q);
896 if (!strcmp(p, "segment") || !strcmp(p, "section"))
897 return 1;
898 if (!strcmp(p, "extern"))
899 return 2;
900 if (!strcmp(p, "bits"))
901 return 3;
902 if (!strcmp(p, "global"))
903 return 4;
904 if (!strcmp(p, "common"))
905 return 5;
906 if (!strcmp(p, "absolute"))
907 return 6;
908 return -1;
911 static void report_error (int severity, char *fmt, ...) {
912 va_list ap;
915 * See if it's a suppressed warning.
917 if ((severity & ERR_MASK) == ERR_WARNING &&
918 (severity & ERR_WARN_MASK) != 0 &&
919 suppressed[ (severity & ERR_WARN_MASK) >> ERR_WARN_SHR ])
920 return; /* and bail out if so */
923 * See if it's a pass-one only warning and we're not in pass one.
925 if ((severity & ERR_PASS1) && pass != 1)
926 return;
928 if (severity & ERR_NOFILE)
929 fputs ("nasm: ", use_stdout ? stdout : stderr);
930 else
931 fprintf (use_stdout ? stdout : stderr, "%s:%d: ", currentfile,
932 lineno + (severity & ERR_OFFBY1 ? lineinc : 0));
934 if ( (severity & ERR_MASK) == ERR_WARNING)
935 fputs ("warning: ", use_stdout ? stdout : stderr);
936 else if ( (severity & ERR_MASK) == ERR_PANIC)
937 fputs ("panic: ", use_stdout ? stdout : stderr);
939 va_start (ap, fmt);
940 vfprintf (use_stdout ? stdout : stderr, fmt, ap);
941 fputc ('\n', use_stdout ? stdout : stderr);
943 if (severity & ERR_USAGE)
944 want_usage = TRUE;
946 switch (severity & ERR_MASK) {
947 case ERR_WARNING:
948 /* no further action, by definition */
949 break;
950 case ERR_NONFATAL:
951 terminate_after_phase = TRUE;
952 break;
953 case ERR_FATAL:
954 if (ofile) {
955 fclose(ofile);
956 remove(outname);
958 if (want_usage)
959 usage();
960 exit(1); /* instantly die */
961 break; /* placate silly compilers */
962 case ERR_PANIC:
963 abort(); /* halt, catch fire, and dump core */
964 break;
968 static void usage(void) {
969 fputs("type `nasm -h' for help\n", use_stdout ? stdout : stderr);
972 static void register_output_formats(void) {
973 /* Flat-form binary format */
974 #ifdef OF_BIN
975 extern struct ofmt of_bin;
976 #endif
977 /* Unix formats: a.out, COFF, ELF */
978 #ifdef OF_AOUT
979 extern struct ofmt of_aout;
980 #endif
981 #ifdef OF_AOUTB
982 extern struct ofmt of_aoutb;
983 #endif
984 #ifdef OF_COFF
985 extern struct ofmt of_coff;
986 #endif
987 #ifdef OF_ELF
988 extern struct ofmt of_elf;
989 #endif
990 /* Linux strange format: as86 */
991 #ifdef OF_AS86
992 extern struct ofmt of_as86;
993 #endif
994 /* DOS and DOS-ish formats: OBJ, OS/2, Win32 */
995 #ifdef OF_OBJ
996 extern struct ofmt of_obj;
997 #endif
998 #ifdef OF_WIN32
999 extern struct ofmt of_win32;
1000 #endif
1001 #ifdef OF_RDF
1002 extern struct ofmt of_rdf;
1003 #endif
1004 #ifdef OF_DBG /* debug format must be included specifically */
1005 extern struct ofmt of_dbg;
1006 #endif
1008 #ifdef OF_BIN
1009 ofmt_register (&of_bin);
1010 #endif
1011 #ifdef OF_AOUT
1012 ofmt_register (&of_aout);
1013 #endif
1014 #ifdef OF_AOUTB
1015 ofmt_register (&of_aoutb);
1016 #endif
1017 #ifdef OF_COFF
1018 ofmt_register (&of_coff);
1019 #endif
1020 #ifdef OF_ELF
1021 ofmt_register (&of_elf);
1022 #endif
1023 #ifdef OF_AS86
1024 ofmt_register (&of_as86);
1025 #endif
1026 #ifdef OF_OBJ
1027 ofmt_register (&of_obj);
1028 #endif
1029 #ifdef OF_WIN32
1030 ofmt_register (&of_win32);
1031 #endif
1032 #ifdef OF_RDF
1033 ofmt_register (&of_rdf);
1034 #endif
1035 #ifdef OF_DBG
1036 ofmt_register (&of_dbg);
1037 #endif
1039 * set the default format
1041 ofmt = &OF_DEFAULT;
1044 #define BUF_DELTA 512
1046 static FILE *no_pp_fp;
1047 static efunc no_pp_err;
1048 static ListGen *no_pp_list;
1050 static void no_pp_reset (char *file, int pass, efunc error, evalfunc eval,
1051 ListGen *listgen) {
1052 no_pp_err = error;
1053 no_pp_fp = fopen(file, "r");
1054 if (!no_pp_fp)
1055 no_pp_err (ERR_FATAL | ERR_NOFILE,
1056 "unable to open input file `%s'", file);
1057 no_pp_list = listgen;
1058 (void) pass; /* placate compilers */
1059 (void) eval; /* placate compilers */
1062 static char *no_pp_getline (void) {
1063 char *buffer, *p, *q;
1064 int bufsize;
1066 bufsize = BUF_DELTA;
1067 buffer = nasm_malloc(BUF_DELTA);
1068 p = buffer;
1069 while (1) {
1070 q = fgets(p, bufsize-(p-buffer), no_pp_fp);
1071 if (!q)
1072 break;
1073 p += strlen(p);
1074 if (p > buffer && p[-1] == '\n')
1075 break;
1076 if (p-buffer > bufsize-10) {
1077 bufsize += BUF_DELTA;
1078 buffer = nasm_realloc(buffer, bufsize);
1082 if (!q && p == buffer) {
1083 nasm_free (buffer);
1084 return NULL;
1088 * Play safe: remove CRs as well as LFs, if any of either are
1089 * present at the end of the line.
1091 while (p > buffer && (p[-1] == '\n' || p[-1] == '\r'))
1092 *--p = '\0';
1095 * Handle spurious ^Z, which may be inserted into source files
1096 * by some file transfer utilities.
1098 buffer[strcspn(buffer, "\032")] = '\0';
1100 no_pp_list->line (LIST_READ, buffer);
1102 return buffer;
1105 static void no_pp_cleanup (void) {
1106 fclose(no_pp_fp);