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