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.
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);
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 */
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 */
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
] = {
69 * The option names for the suppressible warnings. As before, entry
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
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
= {
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));
120 preprocess_only
= FALSE
;
124 register_output_formats();
126 parse_cmdline(argc
, argv
);
128 if (terminate_after_phase
) {
135 pp_extra_stdmac (ofmt
->stdmac
);
136 eval_global_info (ofmt
, lookup_label
);
138 if (preprocess_only
) {
142 ofile
= fopen(outname
, "w");
144 report_error (ERR_FATAL
| ERR_NOFILE
,
145 "unable to open output file `%s'", outname
);
149 eval_info ("%", 0L, 0L); /* disallow labels, $ or $$ in exprs */
151 preproc
->reset (inname
, 2, report_error
, evaluate
, &nasmlist
);
152 strcpy(currentfile
,inname
);
155 while ( (line
= preproc
->getline()) ) {
157 char buf
[FILENAME_MAX
];
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) {
168 strncpy (currentfile
, buf
, FILENAME_MAX
-1);
169 currentfile
[FILENAME_MAX
-1] = '\0';
181 if (ofile
&& terminate_after_phase
)
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
191 ofmt
->filename (inname
, outname
, report_error
);
193 ofile
= fopen(outname
, "wb");
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)
204 ofmt
->init (ofile
, report_error
, define_label
, evaluate
);
205 assemble_file (inname
);
206 if (!terminate_after_phase
) {
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.
216 if (terminate_after_phase
) {
228 if (terminate_after_phase
)
234 static int process_arg (char *p
, char *q
) {
247 case 'o': /* these parameters take values */
253 if (p
[2]) /* the parameter's in the option */
256 report_error (ERR_NONFATAL
| ERR_NOFILE
| ERR_USAGE
,
257 "option `-%c' requires an argument",
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
);
267 report_error (ERR_FATAL
| ERR_NOFILE
| ERR_USAGE
,
268 "unrecognised output format `%s'",
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
);
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 */
311 fprintf(use_stdout
? stdout
: stderr
,
312 "NASM version %s\n", NASM_VER
);
313 exit (0); /* never need usage message here */
315 case 'e': /* preprocess only */
316 preprocess_only
= TRUE
;
318 case 'a': /* assemble only - don't preprocess */
322 if (p
[2] != '+' && p
[2] != '-') {
323 report_error (ERR_NONFATAL
| ERR_NOFILE
| ERR_USAGE
,
324 "invalid option to `-w'");
326 for (i
=1; i
<=ERR_WARN_MAX
; i
++)
327 if (!nasm_stricmp(p
+3, suppressed_names
[i
]))
329 if (i
<= ERR_WARN_MAX
)
330 suppressed
[i
] = (p
[2] == '-');
332 report_error (ERR_NONFATAL
| ERR_NOFILE
| ERR_USAGE
,
333 "invalid option to `-w'");
337 report_error (ERR_NONFATAL
| ERR_NOFILE
| ERR_USAGE
,
338 "unrecognised option `-%c'",
344 report_error (ERR_NONFATAL
| ERR_NOFILE
| ERR_USAGE
,
345 "more than one input file specified");
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");
365 envcopy
= nasm_strdup(envreal
);
371 while (*p
&& *p
!= separator
) p
++;
372 while (*p
== separator
) *p
++ = '\0';
375 if (process_arg (prevarg
, arg
))
381 process_arg (arg
, NULL
);
384 * Now process the actual command line.
389 i
= process_arg (argv
[0], argc
> 1 ? argv
[1] : NULL
);
390 argv
+= i
, argc
-= i
;
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
;
401 int i
, rn_error
, validid
;
403 struct tokenval tokval
;
408 current_seg
= ofmt
->section(NULL
, pass
, &sb
);
409 preproc
->reset(fname
, 1, report_error
, evaluate
, &nasmlist
);
410 strcpy(currentfile
,fname
);
415 eval_info (NULL
, current_seg
, offs
); /* set $ */
416 while ( (line
= preproc
->getline()) ) {
420 if (line
[0] == '%') {
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");
439 strncpy (currentfile
, buf
, FILENAME_MAX
-1);
440 currentfile
[FILENAME_MAX
-1] = '\0';
445 /* here we parse our directives; this is not handled by the 'real'
447 if ( (i
= getkw (line
, &value
)) ) {
449 case 1: /* [SEGMENT n] */
450 seg
= ofmt
->section (value
, pass
, &sb
);
452 report_error (ERR_NONFATAL
,
453 "segment name `%s' not recognised",
459 case 2: /* [EXTERN label:special] */
461 value
++; /* skip initial $ if present */
466 while (*q
&& *q
!= ':') {
472 report_error (ERR_NONFATAL
,
473 "identifier expected after EXTERN");
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
,
487 case 3: /* [BITS bits] */
488 switch (atoi(value
)) {
494 report_error(ERR_NONFATAL
,
495 "`%s' is not a valid argument to [BITS]",
500 case 4: /* [GLOBAL symbol:special] */
502 value
++; /* skip initial $ if present */
507 while (*q
&& *q
!= ':') {
513 report_error (ERR_NONFATAL
,
514 "identifier expected after GLOBAL");
522 declare_as_global (value
, special
, report_error
);
524 case 5: /* [COMMON symbol size:special] */
529 while (*p
&& !isspace(*p
)) {
535 report_error (ERR_NONFATAL
,
536 "identifier expected after COMMON");
542 while (*p
&& isspace(*p
))
545 while (*q
&& *q
!= ':')
552 size
= readnum (p
, &rn_error
);
554 report_error (ERR_NONFATAL
, "invalid size specified"
555 " in COMMON declaration");
557 define_common (value
, seg_alloc(), size
,
558 special
, ofmt
, report_error
);
560 report_error (ERR_NONFATAL
, "no size specified in"
561 " COMMON declaration");
563 case 6: /* [ABSOLUTE address] */
564 current_seg
= NO_SEG
;
566 stdscan_bufptr
= value
;
567 tokval
.t_type
= TOKEN_INVALID
;
568 e
= evaluate(stdscan
, NULL
, &tokval
, NULL
, 1, report_error
,
572 report_error (ERR_NONFATAL
, "cannot use non-"
573 "relocatable expression as ABSOLUTE"
576 abs_seg
= reloc_seg(e
);
577 abs_offset
= reloc_value(e
);
580 abs_offset
= 0x100;/* don't go near zero in case of / */
583 if (!ofmt
->directive (line
+1, value
, 1))
584 report_error (ERR_NONFATAL
, "unrecognised directive [%s]",
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
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
) {
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
);
644 report_error(ERR_NONFATAL
, "bad syntax for EQU");
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
);
655 cleanup_insn (&output_ins
);
659 eval_info (NULL
, current_seg
, offs
); /* set $ */
663 if (terminate_after_phase
) {
673 saa_rewind (forwrefs
);
675 nasmlist
.init(listname
, report_error
);
677 int *p
= saa_rstruct (forwrefs
);
683 current_seg
= ofmt
->section(NULL
, pass
, &sb
);
685 offsets
= raa_init();
686 preproc
->reset(fname
, 2, report_error
, evaluate
, &nasmlist
);
687 strcpy(currentfile
,fname
);
692 eval_info (NULL
, current_seg
, offs
); /* set $ */
693 while ( (line
= preproc
->getline()) ) {
697 if (line
[0] == '%') {
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) {
710 strncpy (currentfile
, buf
, FILENAME_MAX
-1);
711 currentfile
[FILENAME_MAX
-1] = '\0';
716 /* here we parse our directives; this is not handled by
717 * the 'real' parser. */
718 if ( (i
= getkw (line
, &value
)) ) {
720 case 1: /* [SEGMENT n] */
721 seg
= ofmt
->section (value
, pass
, &sb
);
723 report_error (ERR_PANIC
,
724 "invalid segment name on pass two");
728 case 2: /* [EXTERN label] */
730 while (*q
&& *q
!= ':')
734 ofmt
->symdef(value
, 0L, 0L, 3, q
);
737 case 3: /* [BITS bits] */
738 switch (atoi(value
)) {
744 report_error(ERR_PANIC
,
745 "invalid [BITS] value on pass two",
750 case 4: /* [GLOBAL symbol] */
752 while (*q
&& *q
!= ':')
756 ofmt
->symdef(value
, 0L, 0L, 3, q
);
759 case 5: /* [COMMON symbol size] */
761 while (*q
&& *q
!= ':') {
768 ofmt
->symdef(value
, 0L, 0L, 3, q
);
771 case 6: /* [ABSOLUTE addr] */
772 current_seg
= NO_SEG
;
774 stdscan_bufptr
= value
;
775 tokval
.t_type
= TOKEN_INVALID
;
776 e
= evaluate(stdscan
, NULL
, &tokval
, NULL
, 2, report_error
,
780 report_error (ERR_PANIC
, "non-reloc ABSOLUTE address"
783 abs_seg
= reloc_seg(e
);
784 abs_offset
= reloc_value(e
);
787 report_error (ERR_PANIC
, "invalid ABSOLUTE address "
791 if (!ofmt
->directive (line
+1, value
, 2))
792 report_error (ERR_PANIC
, "invalid directive on pass two");
796 parse_line (2, line
, &output_ins
,
797 report_error
, evaluate
, eval_info
);
798 if (globallineno
== forwline
) {
799 int *p
= saa_rstruct (forwrefs
);
804 output_ins
.forw_ref
= TRUE
;
806 output_ins
.forw_ref
= FALSE
;
809 * Hack to prevent phase error in the code
813 if (output_ins
.forw_ref
) {
815 for (i
=0; i
<output_ins
.operands
; i
++)
816 output_ins
.oprs
[i
].type
&= ~ONENESS
;
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
);
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
);
858 eval_info (NULL
, current_seg
, offs
); /* set $ */
864 static int getkw (char *buf
, char **value
) {
870 while (*p
&& *p
!= ']') p
++;
874 while (*p
&& *p
!= ';') {
882 while (*buf
&& *buf
!=' ' && *buf
!=']' && *buf
!='\t')
889 while (isspace(*buf
)) buf
++; /* beppu - skip leading whitespace */
891 while (*buf
!=']') buf
++;
896 if (!strcmp(p
, "segment") || !strcmp(p
, "section"))
898 if (!strcmp(p
, "extern"))
900 if (!strcmp(p
, "bits"))
902 if (!strcmp(p
, "global"))
904 if (!strcmp(p
, "common"))
906 if (!strcmp(p
, "absolute"))
911 static void report_error (int severity
, char *fmt
, ...) {
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)
928 if (severity
& ERR_NOFILE
)
929 fputs ("nasm: ", use_stdout
? stdout
: stderr
);
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
);
940 vfprintf (use_stdout
? stdout
: stderr
, fmt
, ap
);
941 fputc ('\n', use_stdout
? stdout
: stderr
);
943 if (severity
& ERR_USAGE
)
946 switch (severity
& ERR_MASK
) {
948 /* no further action, by definition */
951 terminate_after_phase
= TRUE
;
960 exit(1); /* instantly die */
961 break; /* placate silly compilers */
963 abort(); /* halt, catch fire, and dump core */
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 */
975 extern struct ofmt of_bin
;
977 /* Unix formats: a.out, COFF, ELF */
979 extern struct ofmt of_aout
;
982 extern struct ofmt of_aoutb
;
985 extern struct ofmt of_coff
;
988 extern struct ofmt of_elf
;
990 /* Linux strange format: as86 */
992 extern struct ofmt of_as86
;
994 /* DOS and DOS-ish formats: OBJ, OS/2, Win32 */
996 extern struct ofmt of_obj
;
999 extern struct ofmt of_win32
;
1002 extern struct ofmt of_rdf
;
1004 #ifdef OF_DBG /* debug format must be included specifically */
1005 extern struct ofmt of_dbg
;
1009 ofmt_register (&of_bin
);
1012 ofmt_register (&of_aout
);
1015 ofmt_register (&of_aoutb
);
1018 ofmt_register (&of_coff
);
1021 ofmt_register (&of_elf
);
1024 ofmt_register (&of_as86
);
1027 ofmt_register (&of_obj
);
1030 ofmt_register (&of_win32
);
1033 ofmt_register (&of_rdf
);
1036 ofmt_register (&of_dbg
);
1039 * set the default format
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
,
1053 no_pp_fp
= fopen(file
, "r");
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
;
1066 bufsize
= BUF_DELTA
;
1067 buffer
= nasm_malloc(BUF_DELTA
);
1070 q
= fgets(p
, bufsize
-(p
-buffer
), no_pp_fp
);
1074 if (p
> buffer
&& p
[-1] == '\n')
1076 if (p
-buffer
> bufsize
-10) {
1077 bufsize
+= BUF_DELTA
;
1078 buffer
= nasm_realloc(buffer
, bufsize
);
1082 if (!q
&& p
== buffer
) {
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'))
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
);
1105 static void no_pp_cleanup (void) {