blob: a1e4dd8aba6ee02bfaf373e39613e4dee27b2032 [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
25static void report_error (int, char *, ...);
26static void parse_cmdline (int, char **);
27static void assemble_file (char *);
28static int getkw (char *buf, char **value);
29static void register_output_formats(void);
30static void usage(void);
31
32static char *obuf;
33static char inname[FILENAME_MAX];
34static char outname[FILENAME_MAX];
H. Peter Anvin6768eb72002-04-30 20:52:26 +000035static char listname[FILENAME_MAX];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000036static int lineno; /* for error reporting */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000037static int lineinc; /* set by [LINE] or [ONELINE] */
38static int globallineno; /* for forward-reference tracking */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000039static int pass;
40static struct ofmt *ofmt = NULL;
41
42static FILE *ofile = NULL;
43static int sb = 16; /* by default */
44
H. Peter Anvin6768eb72002-04-30 20:52:26 +000045static int use_stdout = FALSE; /* by default, errors to stderr */
46
H. Peter Anvin76690a12002-04-30 20:52:49 +000047static long current_seg, abs_seg;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000048static struct RAA *offsets;
49static long abs_offset;
H. Peter Anvinea838272002-04-30 20:51:53 +000050
51static struct SAA *forwrefs; /* keep track of forward references */
52static int forwline;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000053
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000054static Preproc *preproc;
55static int preprocess_only;
56
57/* used by error function to report location */
58static char currentfile[FILENAME_MAX];
59
60/*
H. Peter Anvin6768eb72002-04-30 20:52:26 +000061 * Which of the suppressible warnings are suppressed. Entry zero
62 * doesn't do anything. Initial defaults are given here.
63 */
64static char suppressed[1+ERR_WARN_MAX] = {
H. Peter Anvin76690a12002-04-30 20:52:49 +000065 0, FALSE, TRUE, FALSE
H. Peter Anvin6768eb72002-04-30 20:52:26 +000066};
67
68/*
69 * The option names for the suppressible warnings. As before, entry
70 * zero does nothing.
71 */
72static char *suppressed_names[1+ERR_WARN_MAX] = {
H. Peter Anvin76690a12002-04-30 20:52:49 +000073 NULL, "macro-params", "orphan-labels", "number-overflow"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000074};
75
76/*
77 * The explanations for the suppressible warnings. As before, entry
78 * zero does nothing.
79 */
80static char *suppressed_what[1+ERR_WARN_MAX] = {
81 NULL, "macro calls with wrong no. of params",
H. Peter Anvin76690a12002-04-30 20:52:49 +000082 "labels alone on lines without trailing `:'",
83 "numeric constants greater than 0xFFFFFFFF"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000084};
85
86/*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000087 * 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.
90 */
91
H. Peter Anvin76690a12002-04-30 20:52:49 +000092static void no_pp_reset (char *, int, efunc, evalfunc, ListGen *);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000093static char *no_pp_getline (void);
94static void no_pp_cleanup (void);
95static Preproc no_pp = {
96 no_pp_reset,
97 no_pp_getline,
98 no_pp_cleanup
99};
100
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000101/*
102 * get/set current offset...
103 */
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))))
108
109static int want_usage;
110static int terminate_after_phase;
111
112int main(int argc, char **argv) {
113 want_usage = terminate_after_phase = FALSE;
114
115 nasm_set_malloc_error (report_error);
116 offsets = raa_init();
H. Peter Anvinea838272002-04-30 20:51:53 +0000117 forwrefs = saa_init ((long)sizeof(int));
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000118
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000119 preproc = &nasmpp;
120 preprocess_only = FALSE;
121
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000122 seg_init();
123
124 register_output_formats();
125
126 parse_cmdline(argc, argv);
127
128 if (terminate_after_phase) {
129 if (want_usage)
130 usage();
131 return 1;
132 }
133
H. Peter Anvin76690a12002-04-30 20:52:49 +0000134 if (ofmt->stdmac)
135 pp_extra_stdmac (ofmt->stdmac);
136 eval_global_info (ofmt, lookup_label);
137
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000138 if (preprocess_only) {
139 char *line;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000140
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000141 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;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000148
149 eval_info ("%", 0L, 0L); /* disallow labels, $ or $$ in exprs */
150
151 preproc->reset (inname, 2, report_error, evaluate, &nasmlist);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000152 strcpy(currentfile,inname);
153 lineno = 0;
154 lineinc = 1;
155 while ( (line = preproc->getline()) ) {
H. Peter Anvin76690a12002-04-30 20:52:49 +0000156 int ln, li;
157 char buf[FILENAME_MAX];
158
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000159 lineno += lineinc;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000160 /*
161 * We must still check for %line directives, so that we
162 * can report errors accurately.
163 */
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';
170 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000171 if (ofile) {
172 fputs(line, ofile);
173 fputc('\n', ofile);
174 } else
175 puts(line);
176 nasm_free (line);
177 }
178 preproc->cleanup();
179 if (ofile)
180 fclose(ofile);
181 if (ofile && terminate_after_phase)
182 remove(outname);
183 } else {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000184 /*
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.
190 */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000191 ofmt->filename (inname, outname, report_error);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000192
193 ofile = fopen(outname, "wb");
194 if (!ofile) {
195 report_error (ERR_FATAL | ERR_NOFILE,
196 "unable to open output file `%s'", outname);
197 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000198 /*
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)
202 */
203 init_labels ();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000204 ofmt->init (ofile, report_error, define_label, evaluate);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000205 assemble_file (inname);
206 if (!terminate_after_phase) {
207 ofmt->cleanup ();
208 cleanup_labels ();
209 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000210 /*
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);
215 */
216 if (terminate_after_phase) {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000217 remove(outname);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000218 if (listname[0])
219 remove(listname);
220 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000221 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000222
223 if (want_usage)
224 usage();
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000225 raa_free (offsets);
226 saa_free (forwrefs);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000227
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000228 if (terminate_after_phase)
229 return 1;
230 else
231 return 0;
232}
233
234static int process_arg (char *p, char *q) {
235 char *param;
236 int i;
237 int advance = 0;
238
239 if (!p || !p[0])
240 return 0;
241
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);
270 }
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);
279 }
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'");
334 }
335 break;
336 default:
337 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
338 "unrecognised option `-%c'",
339 p[1]);
340 break;
341 }
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);
348 }
349
350 return advance;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000351}
352
353static void parse_cmdline(int argc, char **argv) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000354 char *envreal, *envcopy, *p, *q, *arg, *prevarg;
355 char separator = ' ';
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000356
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000357 *inname = *outname = *listname = '\0';
358
359 /*
360 * First, process the NASM environment variable.
361 */
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;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000377 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000378 nasm_free (envcopy);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000379 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000380 if (arg)
381 process_arg (arg, NULL);
382
383 /*
384 * Now process the actual command line.
385 */
386 while (--argc) {
387 int i;
388 argv++;
389 i = process_arg (argv[0], argc > 1 ? argv[1] : NULL);
390 argv += i, argc -= i;
391 }
392
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000393 if (!*inname)
394 report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
395 "no input file specified");
396}
397
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000398static void assemble_file (char *fname) {
H. Peter Anvin76690a12002-04-30 20:52:49 +0000399 char *value, *p, *q, *special, *line;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000400 insn output_ins;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000401 int i, rn_error, validid;
402 long seg, offs;
403 struct tokenval tokval;
404 expr *e;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000405
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000406 /* pass one */
407 pass = 1;
408 current_seg = ofmt->section(NULL, pass, &sb);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000409 preproc->reset(fname, 1, report_error, evaluate, &nasmlist);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000410 strcpy(currentfile,fname);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000411 lineno = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000412 lineinc = 1;
413 globallineno = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000414 offs = get_curr_ofs;
415 eval_info (NULL, current_seg, offs); /* set $ */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000416 while ( (line = preproc->getline()) ) {
417 lineno += lineinc;
418 globallineno++;
419
420 if (line[0] == '%') {
421 int ln, li;
422 char buf[FILENAME_MAX];
423
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000424 /*
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000425 * 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.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000428 */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000429 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';
441 }
442 continue;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000443 }
444
445 /* here we parse our directives; this is not handled by the 'real'
446 * parser. */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000447 if ( (i = getkw (line, &value)) ) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000448 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;
457 }
458 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000459 case 2: /* [EXTERN label:special] */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000460 if (*value == '$')
461 value++; /* skip initial $ if present */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000462 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++;
470 }
471 if (!validid) {
472 report_error (ERR_NONFATAL,
473 "identifier expected after EXTERN");
474 break;
475 }
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);
485 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000486 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;
498 }
499 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000500 case 4: /* [GLOBAL symbol:special] */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000501 if (*value == '$')
502 value++; /* skip initial $ if present */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000503 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++;
511 }
512 if (!validid) {
513 report_error (ERR_NONFATAL,
514 "identifier expected after GLOBAL");
515 break;
516 }
517 if (*q == ':') {
518 *q++ = '\0';
519 special = q;
520 } else
521 special = NULL;
522 declare_as_global (value, special, report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000523 break;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000524 case 5: /* [COMMON symbol size:special] */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000525 p = value;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000526 validid = TRUE;
527 if (!isidstart(*p))
528 validid = FALSE;
529 while (*p && !isspace(*p)) {
530 if (!isidchar(*p))
531 validid = FALSE;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000532 p++;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000533 }
534 if (!validid) {
535 report_error (ERR_NONFATAL,
536 "identifier expected after COMMON");
537 break;
538 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000539 if (*p) {
540 long size;
541
542 while (*p && isspace(*p))
543 *p++ = '\0';
H. Peter Anvin76690a12002-04-30 20:52:49 +0000544 q = p;
545 while (*q && *q != ':')
546 q++;
547 if (*q == ':') {
548 *q++ = '\0';
549 special = q;
550 } else
551 special = NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000552 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,
H. Peter Anvin76690a12002-04-30 20:52:49 +0000558 special, ofmt, report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000559 } else
560 report_error (ERR_NONFATAL, "no size specified in"
561 " COMMON declaration");
562 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000563 case 6: /* [ABSOLUTE address] */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000564 current_seg = NO_SEG;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000565 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);
578 }
579 } else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000580 abs_offset = 0x100;/* don't go near zero in case of / */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000581 break;
582 default:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000583 if (!ofmt->directive (line+1, value, 1))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000584 report_error (ERR_NONFATAL, "unrecognised directive [%s]",
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000585 line+1);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000586 break;
587 }
588 } else {
H. Peter Anvin76690a12002-04-30 20:52:49 +0000589 parse_line (1, line, &output_ins,
590 report_error, evaluate, eval_info);
H. Peter Anvinea838272002-04-30 20:51:53 +0000591 if (output_ins.forw_ref)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000592 *(int *)saa_wstruct(forwrefs) = globallineno;
593
594 /*
595 * Hack to prevent phase error in the code
596 * rol ax,x
597 * x equ 1
598 *
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.
605 */
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;
610 }
611
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000612 if (output_ins.opcode == I_EQU) {
613 /*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000614 * Special `..' EQUs get processed in pass two,
615 * except `..@' macro-processor EQUs which are done
616 * in the normal place.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000617 */
618 if (!output_ins.label)
619 report_error (ERR_NONFATAL,
620 "EQU not preceded by label");
621 else if (output_ins.label[0] != '.' ||
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000622 output_ins.label[1] != '.' ||
623 output_ins.label[2] == '@') {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000624 if (output_ins.operands == 1 &&
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000625 (output_ins.oprs[0].type & IMMEDIATE) &&
626 output_ins.oprs[0].wrt == NO_SEG) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000627 define_label (output_ins.label,
628 output_ins.oprs[0].segment,
629 output_ins.oprs[0].offset,
H. Peter Anvin76690a12002-04-30 20:52:49 +0000630 NULL, FALSE, FALSE, ofmt, report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000631 } 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 &&
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000635 output_ins.oprs[0].wrt == NO_SEG &&
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000636 (output_ins.oprs[1].type & IMMEDIATE) &&
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000637 output_ins.oprs[1].segment == NO_SEG &&
638 output_ins.oprs[1].wrt == NO_SEG) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000639 define_label (output_ins.label,
640 output_ins.oprs[0].offset | SEG_ABS,
641 output_ins.oprs[1].offset,
H. Peter Anvin76690a12002-04-30 20:52:49 +0000642 NULL, FALSE, FALSE, ofmt, report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000643 } else
644 report_error(ERR_NONFATAL, "bad syntax for EQU");
645 }
646 } else {
647 if (output_ins.label)
648 define_label (output_ins.label,
H. Peter Anvin76690a12002-04-30 20:52:49 +0000649 current_seg==NO_SEG ? abs_seg : current_seg,
650 offs, NULL, TRUE, FALSE, ofmt, report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000651 offs += insn_size (current_seg, offs, sb,
652 &output_ins, report_error);
653 set_curr_ofs (offs);
654 }
655 cleanup_insn (&output_ins);
656 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000657 nasm_free (line);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000658 offs = get_curr_ofs;
659 eval_info (NULL, current_seg, offs); /* set $ */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000660 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000661 preproc->cleanup();
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000662
663 if (terminate_after_phase) {
664 fclose(ofile);
665 remove(outname);
666 if (want_usage)
667 usage();
668 exit (1);
669 }
670
671 /* pass two */
672 pass = 2;
H. Peter Anvinea838272002-04-30 20:51:53 +0000673 saa_rewind (forwrefs);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000674 if (*listname)
675 nasmlist.init(listname, report_error);
H. Peter Anvinea838272002-04-30 20:51:53 +0000676 {
677 int *p = saa_rstruct (forwrefs);
678 if (p)
679 forwline = *p;
680 else
681 forwline = -1;
682 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000683 current_seg = ofmt->section(NULL, pass, &sb);
684 raa_free (offsets);
685 offsets = raa_init();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000686 preproc->reset(fname, 2, report_error, evaluate, &nasmlist);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000687 strcpy(currentfile,fname);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000688 lineno = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000689 lineinc = 1;
690 globallineno = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000691 offs = get_curr_ofs;
692 eval_info (NULL, current_seg, offs); /* set $ */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000693 while ( (line = preproc->getline()) ) {
694 lineno += lineinc;
695 globallineno++;
696
697 if (line[0] == '%') {
698 int ln, li;
699 char buf[FILENAME_MAX];
700
701 /*
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.
705 */
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';
712 }
713 continue;
714 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000715
716 /* here we parse our directives; this is not handled by
717 * the 'real' parser. */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000718 if ( (i = getkw (line, &value)) ) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000719 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] */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000729 q = value;
730 while (*q && *q != ':')
731 q++;
732 if (*q == ':') {
733 *q++ = '\0';
734 ofmt->symdef(value, 0L, 0L, 3, q);
735 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000736 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;
748 }
749 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000750 case 4: /* [GLOBAL symbol] */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000751 q = value;
752 while (*q && *q != ':')
753 q++;
754 if (*q == ':') {
755 *q++ = '\0';
756 ofmt->symdef(value, 0L, 0L, 3, q);
757 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000758 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000759 case 5: /* [COMMON symbol size] */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000760 q = value;
761 while (*q && *q != ':') {
762 if (isspace(*q))
763 *q = '\0';
764 q++;
765 }
766 if (*q == ':') {
767 *q++ = '\0';
768 ofmt->symdef(value, 0L, 0L, 3, q);
769 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000770 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000771 case 6: /* [ABSOLUTE addr] */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000772 current_seg = NO_SEG;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000773 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);
785 }
786 } else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000787 report_error (ERR_PANIC, "invalid ABSOLUTE address "
788 "in pass two");
789 break;
790 default:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000791 if (!ofmt->directive (line+1, value, 2))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000792 report_error (ERR_PANIC, "invalid directive on pass two");
793 break;
794 }
795 } else {
H. Peter Anvin76690a12002-04-30 20:52:49 +0000796 parse_line (2, line, &output_ins,
797 report_error, evaluate, eval_info);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000798 if (globallineno == forwline) {
H. Peter Anvinea838272002-04-30 20:51:53 +0000799 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;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000807
808 /*
809 * Hack to prevent phase error in the code
810 * rol ax,x
811 * x equ 1
812 */
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;
817 }
818
819 obuf = line;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000820 if (output_ins.label)
821 define_label_stub (output_ins.label, report_error);
822 if (output_ins.opcode == I_EQU) {
823 /*
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000824 * Special `..' EQUs get processed here, except
825 * `..@' macro processor EQUs which are done above.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000826 */
827 if (output_ins.label[0] == '.' &&
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000828 output_ins.label[1] == '.' &&
829 output_ins.label[2] != '@') {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000830 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,
H. Peter Anvin76690a12002-04-30 20:52:49 +0000835 NULL, FALSE, FALSE, ofmt, report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000836 } 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,
H. Peter Anvin76690a12002-04-30 20:52:49 +0000845 NULL, FALSE, FALSE, ofmt, report_error);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000846 } else
847 report_error(ERR_NONFATAL, "bad syntax for EQU");
848 }
849 }
850 offs += assemble (current_seg, offs, sb,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000851 &output_ins, ofmt, report_error, &nasmlist);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000852 cleanup_insn (&output_ins);
853 set_curr_ofs (offs);
854 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000855 nasm_free (line);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000856
857 offs = get_curr_ofs;
858 eval_info (NULL, current_seg, offs); /* set $ */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000859 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000860 preproc->cleanup();
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000861 nasmlist.cleanup();
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000862}
863
864static int getkw (char *buf, char **value) {
865 char *p, *q;
866
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++;
878 }
879 q[1] = '\0';
880
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';
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000889 while (isspace(*buf)) buf++; /* beppu - skip leading whitespace */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000890 *value = buf;
891 while (*buf!=']') buf++;
892 *buf++ = '\0';
893 }
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;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000902 if (!strcmp(p, "global"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000903 return 4;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000904 if (!strcmp(p, "common"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000905 return 5;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000906 if (!strcmp(p, "absolute"))
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000907 return 6;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000908 return -1;
909}
910
911static void report_error (int severity, char *fmt, ...) {
912 va_list ap;
913
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000914 /*
915 * See if it's a suppressed warning.
916 */
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 */
921
H. Peter Anvin76690a12002-04-30 20:52:49 +0000922 /*
923 * See if it's a pass-one only warning and we're not in pass one.
924 */
925 if ((severity & ERR_PASS1) && pass != 1)
926 return;
927
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000928 if (severity & ERR_NOFILE)
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000929 fputs ("nasm: ", use_stdout ? stdout : stderr);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000930 else
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000931 fprintf (use_stdout ? stdout : stderr, "%s:%d: ", currentfile,
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000932 lineno + (severity & ERR_OFFBY1 ? lineinc : 0));
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000933
934 if ( (severity & ERR_MASK) == ERR_WARNING)
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000935 fputs ("warning: ", use_stdout ? stdout : stderr);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000936 else if ( (severity & ERR_MASK) == ERR_PANIC)
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000937 fputs ("panic: ", use_stdout ? stdout : stderr);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000938
939 va_start (ap, fmt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000940 vfprintf (use_stdout ? stdout : stderr, fmt, ap);
941 fputc ('\n', use_stdout ? stdout : stderr);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000942
943 if (severity & ERR_USAGE)
944 want_usage = TRUE;
945
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:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000954 if (ofile) {
955 fclose(ofile);
956 remove(outname);
957 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000958 if (want_usage)
959 usage();
960 exit(1); /* instantly die */
961 break; /* placate silly compilers */
962 case ERR_PANIC:
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000963 abort(); /* halt, catch fire, and dump core */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000964 break;
965 }
966}
967
968static void usage(void) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000969 fputs("type `nasm -h' for help\n", use_stdout ? stdout : stderr);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000970}
971
972static 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
H. Peter Anvin76690a12002-04-30 20:52:49 +0000981#ifdef OF_AOUTB
982 extern struct ofmt of_aoutb;
983#endif
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000984#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
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000994 /* DOS and DOS-ish formats: OBJ, OS/2, Win32 */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000995#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
1007
1008#ifdef OF_BIN
1009 ofmt_register (&of_bin);
1010#endif
1011#ifdef OF_AOUT
1012 ofmt_register (&of_aout);
1013#endif
H. Peter Anvin76690a12002-04-30 20:52:49 +00001014#ifdef OF_AOUTB
1015 ofmt_register (&of_aoutb);
1016#endif
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001017#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
1038 /*
1039 * set the default format
1040 */
1041 ofmt = &OF_DEFAULT;
1042}
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001043
1044#define BUF_DELTA 512
1045
1046static FILE *no_pp_fp;
1047static efunc no_pp_err;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001048static ListGen *no_pp_list;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001049
H. Peter Anvin76690a12002-04-30 20:52:49 +00001050static void no_pp_reset (char *file, int pass, efunc error, evalfunc eval,
1051 ListGen *listgen) {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001052 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);
H. Peter Anvin76690a12002-04-30 20:52:49 +00001057 no_pp_list = listgen;
1058 (void) pass; /* placate compilers */
1059 (void) eval; /* placate compilers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001060}
1061
1062static char *no_pp_getline (void) {
1063 char *buffer, *p, *q;
1064 int bufsize;
1065
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);
1079 }
1080 }
1081
1082 if (!q && p == buffer) {
1083 nasm_free (buffer);
1084 return NULL;
1085 }
1086
1087 /*
1088 * Play safe: remove CRs as well as LFs, if any of either are
1089 * present at the end of the line.
1090 */
1091 while (p > buffer && (p[-1] == '\n' || p[-1] == '\r'))
1092 *--p = '\0';
1093
1094 /*
1095 * Handle spurious ^Z, which may be inserted into source files
1096 * by some file transfer utilities.
1097 */
1098 buffer[strcspn(buffer, "\032")] = '\0';
1099
H. Peter Anvin76690a12002-04-30 20:52:49 +00001100 no_pp_list->line (LIST_READ, buffer);
1101
H. Peter Anvind7ed89e2002-04-30 20:52:08 +00001102 return buffer;
1103}
1104
1105static void no_pp_cleanup (void) {
1106 fclose(no_pp_fp);
1107}