1 /*
2 HEADER: ;
3 TITLE: Frankenstein Cross Assemblers;
4 VERSION: 2.0;
5 DESCRIPTION: " Reconfigurable Cross-assembler producing Intel (TM)
6 Hex format object records. ";
7 KEYWORDS: cross-assemblers, 1805, 2650, 6301, 6502, 6805, 6809,
8 6811, tms7000, 8048, 8051, 8096, z8, z80;
9 SYSTEM: UNIX, MS-Dos ;
10 FILENAME: frasmain.c;
11 WARNINGS: "This software is in the public domain.
12 Any prior copyright claims are relinquished.
13
14 This software is distributed with no warranty whatever.
15 The author takes no responsibility for the consequences
16 of its use.
17
18 Yacc (or Bison) required to compile." ;
19 SEE-ALSO: base.doc, as*.doc (machine specific appendices) ,
20 as*.1 (man pages);
21 AUTHORS: Mark Zenier;
22 COMPILERS: Microport Sys V/AT, ATT Yacc, Turbo C V1.5, Bison (CUG disk 285)
23 (previous versions Xenix, Unisoft 68000 Version 7, Sun 3);
24 */
25 /*
26 description Main file
27 usage Unix, framework crossassembler
28 history September 25, 1987
29 August 3, 1988 v 1.4
30 September 14, 1990 v 1.5 Dosified
31 */
32
33 #include "config.h"
34 #include "lzoe/lzoe.h"
35 #include "file/file.h"
36 #include "frasmdat.h"
37 #include "file/file.h"
38 #include "../imasm/c_wrap.h"
39 #include "icart/icartrom.h"
40 #include "as1600_types.h"
41 #include "protos.h"
42 #include "intermed.h"
43 #include "collect.h"
44
45 FILE *romoutf, *binoutf, *cfgoutf, *loutf;
46 char *cfgfn = NULL, *binfn = NULL, *romfn = NULL;
47 char *hexfn = NULL, *loutfn = NULL, *srcmapfn = NULL;
48 int errorcnt = 0, warncnt = 0;
49 int listflag = FALSE, hexflag = FALSE, hexvalid = FALSE;
50 static int debugmode = FALSE;
51 static FILE *symbf;
52 static char *symbfn;
53 static int symbflag = FALSE;
54 char hexcva[17] = "0123456789ABCDEF";
55 FILE *smapf = NULL;
56 int currseg, currpag;
57 int *(chtatab[NUM_CHTA]);
58 int locctr;
59 ictype_t icart_type = ICART;
60 struct evalrel evalr[NUMPEXP];
61
62 //unsigned int memory_bitmap[65536 >> 5];
63 int show_map = FALSE;
64
65 time_t asm_time = 0;
66 struct tm asm_time_local;
67 struct tm asm_time_gmt;
68
69 path_t *as1600_search_path = NULL;
70
71 extern struct parser_callbacks imasm_hooks;
72
usage(void)73 LOCAL void usage(void)
74 {
75 printf("AS1600 (%s)\n", svn_revision ? svn_revision : "revision unknown");
76 printf(
77 "Usage:\n"
78 " as1600 [flags] input.asm\n"
79 "\n"
80 "Flags:\n"
81 "\n"
82 " -o <file> --out-file=<file> Output file name\n"
83 " -l <file> --list-file=<file> Specify listing file\n"
84 " -s <file> --sym-file=<file> Specify symbol dump file\n"
85 " -j <file> --src-map=<file> Specify source-map file\n"
86 " -i <path> --include=<path> Append <path> to include path\n"
87 " -m --show-map Summarize memory map after assembly\n"
88 " -3 -c --cc3 Assemble .ROMs for CC3\n"
89 " -h -? --help Show this usage info\n"
90 " -v --version Show assembler version\n"
91 " -e --err-if-overwritten Set ERR_IF_OVERWRITTEN to 1 initially\n"
92 "\n"
93 "The output file type is determined by the extension on the provided output\n"
94 "filename (.bin or .rom). If you omit the extension, AS1600 will attempt to\n"
95 "output both formats. Some features, such as page-flipping or bankswitching\n"
96 "only work in one format; AS1600 will warn if it detects a mismatch.\n"
97 "\n"
98 );
99 }
100
101 static struct option longopts[] =
102 {
103 { "cc3", 0, NULL, '3' },
104 { "include", 1, NULL, 'i' },
105 { "list-file", 1, NULL, 'l' },
106 { "out-file", 1, NULL, 'o' },
107 { "show-map", 0, NULL, 'm' },
108 { "sym-file", 1, NULL, 's' },
109 { "src-map", 1, NULL, 'j' },
110 { "version", 0, NULL, 'v' },
111 { "help", 0, NULL, '?' },
112 { "err-if-overwritten", 0, NULL, 'e' },
113 { NULL, 0, NULL, 0 },
114 };
115
asm_main(int argc,char * argv[])116 int asm_main(int argc, char *argv[])
117 /*
118 description top driver routine for framework cross assembler
119 set the cpu type if implemented in parser
120 process the command line parameters
121 setup the tables
122 call the first pass parser
123 print the symbol table
124 call the second pass
125 close down and delete the outputs if any errors
126 return exit(2) for error, exit(0) for OK
127 */
128 {
129 extern char *optarg;
130 extern int optind;
131 int grv;
132 int cart_type = 0;
133 int err_if_overwrite = 0;
134
135 /* Set the "current assembly time" to the time we started, not some
136 later time, and keep it fixed throughout. */
137 asm_time = time(0);
138 asm_time_local = *localtime(&asm_time);
139 asm_time_gmt = *gmtime(&asm_time);
140
141 /* -------------------------------------------------------------------- */
142 /* Figure out out our executable's path. If none, don't set one. */
143 /* -------------------------------------------------------------------- */
144 if (!exe_path)
145 exe_path = get_exe_dir(argv[0]);
146
147 grv = cpumatch(argv[0]);
148
149 while( (grv = getopt_long(argc, argv, "mdj:o:l:s:p:i:c3v?he",
150 longopts, NULL)) != EOF)
151 {
152 switch(grv)
153 {
154 case 'i':
155 as1600_search_path = append_path(as1600_search_path, optarg);
156 break;
157 case 'o':
158 hexfn = optarg;
159 hexflag = hexvalid = TRUE;
160 break;
161
162 case 'j':
163 srcmapfn = optarg;
164 break;
165
166 case 'l':
167 loutfn = optarg;
168 listflag = TRUE;
169 break;
170
171 case 'd':
172 debugmode = TRUE;
173 break;
174
175 case 's':
176 symbflag = TRUE;
177 symbfn = optarg;
178 break;
179
180 case 'm':
181 show_map = TRUE;
182 break;
183
184 case 'p':
185 if( ! cpumatch(optarg) )
186 {
187 fprintf(stderr, "%s: no match on CPU type %s, default used\n",
188 argv[0], optarg);
189 }
190 break;
191
192 case '3':
193 case 'c':
194 cart_type++;
195 if (cart_type == 1) icart_type = CC3_STD;
196 if (cart_type == 2) icart_type = CC3_ADV;
197 break;
198
199 case 'v':
200 if (svn_revision)
201 printf("AS1600 built from %s\n", svn_revision);
202 else
203 printf("AS1600 revision unknown\n");
204 exit(0);
205
206 case 'e':
207 err_if_overwrite = 1;
208 break;
209
210 case '?':
211 case 'h':
212 usage();
213 exit(0);
214 }
215 }
216
217 if(optind < argc)
218 {
219 if(strcmp(argv[optind], "-") == 0)
220 {
221 yyin = lzoe_filep( stdin );
222 }
223 else
224 {
225 if( !(yyin = lzoe_fopen(argv[optind], "r")) )
226 {
227 fprintf(stderr,
228 "%s: cannot open input file %s\n",
229 argv[0], argv[optind]);
230 exit(1);
231 }
232 }
233 }
234 else
235 {
236 fprintf(stderr, "%s: no input file\n", argv[0]);
237 exit(1);
238 }
239
240 as1600_search_path = append_path(as1600_search_path, ".");
241
242 as1600_search_path = parse_path_string(as1600_search_path,
243 getenv("AS1600_PATH"));
244
245 if(listflag)
246 {
247 if(strcmp(argv[optind], loutfn) == 0)
248 {
249 fprintf(stderr, "%s: list file overwrites input %s\n",
250 argv[0], loutfn);
251 listflag = FALSE;
252 }
253 else if( (loutf = fopen(loutfn, "w")) == (FILE *) NULL)
254 {
255 fprintf(stderr, "%s: cannot open list file %s\n",
256 argv[0], loutfn);
257 listflag = FALSE;
258 }
259 }
260
261 if( ! listflag)
262 {
263 loutf = stdout;
264 }
265
266 if (srcmapfn)
267 {
268 if(strcmp(argv[optind], srcmapfn) == 0)
269 {
270 fprintf(stderr, "%s: source map file overwrites input %s\n",
271 argv[0], srcmapfn);
272 srcmapfn = NULL;
273 }
274 else if( (smapf = fopen(srcmapfn, "w")) == (FILE *) NULL)
275 {
276 fprintf(stderr, "%s: cannot open source map file %s\n",
277 argv[0], srcmapfn);
278 srcmapfn = NULL;
279 }
280 }
281
282 intermed_start_pass_1();
283
284 setophash();
285 setreserved();
286 elseifstk[0] = endifstk[0] = If_Err;
287 expmacstk[0] = TRUE;
288 emit_entering_file(argv[optind]);
289 infilestk[0].fpt = yyin;
290 infilestk[0].fnm = argv[optind];
291 infilestk[0].line = 0;
292 currfstk = 0;
293 currseg = 0;
294 currpag = -1;
295
296 init_parser(&imasm_hooks);
297 collect_init();
298 if (err_if_overwrite)
299 collect_set_overwrite_flags(1, -1);
300
301 yyparse();
302
303 close_parser();
304
305 if(ifstkpt != 0)
306 fraerror("active IF at end of file");
307
308 if(frarptact != FALSE || frarptcnt != -1 || frarptskip != FALSE)
309 fraerror("active REPEAT at end of file");
310
311 buildsymbolindex();
312 if(listflag)
313 printsymbols();
314
315 if(symbflag)
316 {
317 if(strcmp(argv[optind], symbfn) == 0)
318 {
319 fprintf(stderr, "%s: symbol file overwrites input %s\n",
320 argv[0], symbfn);
321 }
322 else if( (symbf = fopen(symbfn, "w")) == (FILE *) NULL)
323 {
324 fprintf(stderr, "%s: cannot open symbol file %s\n",
325 argv[0], symbfn);
326 }
327 else
328 {
329 filesymbols();
330 fclose(symbf);
331 }
332 }
333
334
335 intermed_start_pass_2();
336
337 if(errorcnt > 0)
338 hexflag = FALSE;
339
340 if(hexflag)
341 {
342 int hexfn_len = strlen(hexfn);
343 char *s = hexfn + hexfn_len;
344 char *ext, *tail1, *tail2;
345
346 /* Only examine the last path component */
347 tail1 = strrchr(hexfn, '/');
348 if (!tail1) tail1 = hexfn;
349 tail2 = strrchr(tail1, '\\');
350 if (!tail2) tail2 = tail1;
351
352 ext = strrchr(tail2, '.'); /* look for an extension */
353
354 if (ext == NULL || ext == hexfn)
355 { /* no extension */
356 binfn = (char *)malloc(hexfn_len + 5);
357 cfgfn = (char *)malloc(hexfn_len + 5);
358 romfn = (char *)malloc(hexfn_len + 5);
359 if (!binfn || !cfgfn || !romfn)
360 {
361 fprintf(stderr, "%s: Out of memory\n", argv[0]);
362 exit(1);
363 }
364 snprintf(binfn, hexfn_len+5, "%s.bin", hexfn);
365 snprintf(cfgfn, hexfn_len+5, "%s.cfg", hexfn);
366 snprintf(romfn, hexfn_len+5, "%s.rom", hexfn);
367 if (!cart_type) icart_type = ICART;
368 } else if (stricmp(ext, ".rom")==0)
369 {
370 if (!cart_type) icart_type = ICART;
371 romfn = hexfn;
372 } else if (stricmp(ext, ".cc3")==0)
373 {
374 if (!cart_type) icart_type = CC3_STD;
375 romfn = hexfn;
376 } else if (stricmp(ext, ".bin")==0)
377 {
378 binfn = hexfn;
379 cfgfn = strdup(hexfn);
380 if (!cfgfn)
381 {
382 fprintf(stderr, "%s: Out of memory\n", argv[0]);
383 exit(1);
384 }
385
386 s = cfgfn + hexfn_len - 4;
387 strcpy(s, ".cfg");
388 } else
389 {
390 fprintf(stderr, "%s: Unknown output file extension '%s'\n",
391 argv[0], ext);
392 hexflag = FALSE;
393 }
394
395 {
396 char *tmp[3] = {binfn, cfgfn, romfn};
397 FILE **ftmp[3] = {&binoutf, &cfgoutf, &romoutf};
398 int ck;
399
400 for (ck = 0; ck < 3; ck++)
401 if (tmp[ck] && strcmp(argv[optind], tmp[ck]) == 0)
402 {
403 fprintf(stderr, "%s: binary output overwrites input %s\n",
404 argv[0], tmp[ck]);
405 hexflag = FALSE;
406 break;
407 }
408
409 if (hexflag)
410 for (ck = 0; ck < 3; ck++)
411 {
412 if (!tmp[ck])
413 continue;
414 *ftmp[ck] = fopen(tmp[ck], "wb");
415 if (!*ftmp[ck])
416 {
417 fprintf(stderr, "%s: cannot open output file %s\n",
418 argv[0], tmp[ck]);
419 hexflag = FALSE;
420 break;
421 }
422 }
423 }
424
425 if (hexflag == FALSE)
426 {
427 fprintf(stderr, "%s: Warning: output file not written due to "
428 "previous errors\n", argv[0]);
429 }
430 }
431
432
433 currfstk = 0;
434 outphase();
435
436 if(errorcnt > 0)
437 hexvalid = FALSE;
438
439 fprintf(loutf, " ERROR SUMMARY - ERRORS DETECTED %d\n", errorcnt);
440 fprintf(loutf, " - WARNINGS %d\n", warncnt);
441 listlineno += 2;
442
443 if(listflag)
444 {
445 fprintf(stderr, " ERROR SUMMARY - ERRORS DETECTED %d\n",
446 errorcnt);
447 fprintf(stderr, " - WARNINGS %d\n",
448 warncnt);
449 }
450
451 if(listflag)
452 fclose(loutf);
453
454 if(srcmapfn)
455 fclose(smapf);
456
457 if(hexflag)
458 {
459 if (binoutf) fclose(binoutf);
460 if (cfgoutf) fclose(cfgoutf);
461 if (romoutf) fclose(romoutf);
462 if (!hexvalid)
463 {
464 if (binfn) unlink(binfn);
465 if (cfgfn) unlink(cfgfn);
466 if (romfn) unlink(romfn);
467 }
468 }
469
470 if (show_map)
471 collect_show_map();
472
473 intermed_finish(debugmode);
474
475 exit(errorcnt > 0 ? 2 : 0);
476 }
477
478
frafatal(char * str)479 void frafatal(char * str)
480 /*
481 description Fatal error subroutine, shutdown and quit right now!
482 parameters message
483 globals if debug mode is true, save intermediate file
484 return exit(2)
485 */
486 {
487 fprintf(stderr, "Fatal error - %s\n",str);
488
489 intermed_finish(debugmode);
490
491 exit(2);
492 }
493
frawarn(char * str)494 void frawarn(char * str)
495 /*
496 description first pass - generate warning message by writing line
497 to intermediate file
498 parameters message
499 globals the count of warnings
500 */
501 {
502 emit_warnerr(infilestk[currfstk].fnm, infilestk[currfstk].line,
503 WARNING, "%s", str);
504 }
505
fraerror(const char * str)506 void fraerror(const char * str)
507 /*
508 description first pass - generate error message by writing line to
509 intermediate file
510 parameters message
511 globals count of errors
512 */
513 {
514 emit_warnerr(infilestk[currfstk].fnm, infilestk[currfstk].line,
515 ERROR, "%s", str);
516 }
517
fracherror(char * str,char * start,char * beyond)518 void fracherror(char *str, char *start, char *beyond)
519 /*
520 description first pass - generate error message by writing line to
521 intermediate file
522 parameters message
523 pointer to bad character definition
524 pointer after bad definition
525 globals count of errors
526 */
527 {
528 char bcbuff[8];
529 int cnt;
530
531 for(cnt=0; start < beyond && *start != '\0' && cnt < 7; cnt++)
532 {
533 bcbuff[cnt] = *start++;
534 }
535 bcbuff[cnt] = '\0';
536
537 emit_warnerr(infilestk[currfstk].fnm, infilestk[currfstk].line,
538 ERROR, "%s '%s'", str, bcbuff);
539 }
540
541 #define SYMPERLINE 2
542
printsymbols(void)543 void printsymbols(void)
544 /*
545 description print the symbols on the listing file, 3 symbols
546 across. Only the first 15 characters are printed
547 though all are significant. Reserved symbols are
548 not assigned symbol numbers and thus are not printed.
549 globals the symbol index array and the symbol table elements.
550 */
551 {
552 int syn, npl = 0;
553 struct symel *syp;
554
555 for(syn = 1; syn <nextsymnum; syn++)
556 {
557 if(npl >= SYMPERLINE)
558 {
559 fputc('\n', loutf);
560 listlineno++;
561 npl = 0;
562 }
563
564 syp = symbindex[syn];
565
566 if (syp -> flags & SFLAG_QUIET)
567 continue;
568
569 if(syp -> seg != SSG_UNDEF)
570 fprintf(loutf, "%8.8X %-25.25s ", 0xFFFFFFFF & syp -> value,
571 syp -> symstr);
572 else
573 fprintf(loutf, "???????? %-25.25s ", syp -> symstr);
574 npl++;
575 }
576
577 if(npl > 0)
578 {
579 listlineno++;
580 fputc('\n', loutf);
581 }
582
583 fputc('\f', loutf);
584 }
585
586
filesymbols(void)587 void filesymbols(void)
588 /*
589 description print the symbols to the symbol table file
590 globals the symbol index array and the symbol table elements.
591 */
592 {
593 int syn;
594 struct symel *syp;
595
596 for(syn = 1; syn <nextsymnum; syn++)
597 {
598 syp = symbindex[syn];
599
600 if (syp -> flags & SFLAG_QUIET)
601 continue;
602
603 if(syp -> seg != SSG_UNDEF)
604 fprintf(symbf, "%8.8X %s\n",syp -> value,
605 syp -> symstr);
606 else
607 fprintf(symbf, "???????? %s\n", syp -> symstr);
608 }
609 }
610
611