4 * (C) Copyright 1989-1995
11 * 29-Oct-97 JLH pass ";!" comments to output file
17 #if !defined(_MSC_VER)
23 extern VOID machine(struct mne *);
26 * The module asmain.c includes the command argument parser,
27 * the three pass sequencer, and the machine independent
28 * assembler parsing code.
30 * asmain.c contains the following functions:
31 * VOID main(argc, argv)
34 * FILE * afile(fn, ft, wf)
39 * asmain.c contains the array char *usetxt[] which
40 * references the usage text strings printed by usage().
43 /*)Function VOID main(argc, argv)
45 * int argc argument count
46 * char * argv array of pointers to argument strings
48 * The function main() is the entry point to the assembler.
49 * The purpose of main() is to (1) parse the command line
50 * arguments for options and source file specifications and
51 * (2) to process the source files through the 3 pass assembler.
52 * Before each assembler pass various variables are initialized
53 * and source files are rewound to their beginning. During each
54 * assembler pass each assembler-source text line is processed.
55 * After each assembler pass the assembler information is flushed
56 * to any opened output files and the if-else-endif processing
57 * is checked for proper termination.
59 * The function main() is also responsible for opening all
60 * output files (REL, LST, and SYM), sequencing the global (-g)
61 * and all-global (-a) variable definitions, and dumping the
62 * REL file header information.
65 * char * p pointer to argument string
66 * int c character from argument string
67 * int i argument loop counter
68 * area * ap pointer to area structure
71 * int aflag -a, make all symbols global flag
72 * char afn[] afile() constructed filespec
73 * area * areap pointer to an area structure
74 * int cb[] array of assembler output values
75 * int cbt[] array of assembler relocation types
76 * describing the data in cb[]
77 * int cfile current file handle index
78 * of input assembly files
79 * int * cp pointer to assembler output array cb[]
80 * int * cpt pointer to assembler relocation type
82 * char eb[] array of generated error codes
83 * char * ep pointer into error list array eb[]
84 * int fflag -f(f), relocations flagged flag
85 * int flevel IF-ELSE-ENDIF flag will be non
86 * zero for false conditional case
87 * Addr_T fuzz tracks pass to pass changes in the
88 * address of symbols caused by
89 * variable length instruction formats
90 * int gflag -g, make undefined symbols global flag
91 * char ib[] assembler-source text line
92 * int inpfil count of assembler
93 * input files specified
94 * int ifcnd[] array of IF statement condition
95 * values (0 = FALSE) indexed by tlevel
96 * int iflvl[] array of IF-ELSE-ENDIF flevel
97 * values indexed by tlevel
98 * int incfil current file handle index
100 * char * ip pointer into the assembler-source
102 * jmp_buf jump_env compiler dependent structure
103 * used by setjmp() and longjmp()
104 * int lflag -l, generate listing flag
105 * int line current assembler source
107 * int lop current line number on page
108 * int oflag -o, generate relocatable output flag
109 * int jflag -j, generate debug info flag
110 * int page current page number
111 * int pflag enable listing pagination
112 * int pass assembler pass number
113 * int radix current number conversion radix:
114 * 2 (binary), 8 (octal), 10 (decimal),
116 * int sflag -s, generate symbol table flag
117 * char srcfn[][] array of source file names
118 * int srcline[] current source file line
119 * char stb[] Subtitle string buffer
120 * sym * symp pointer to a symbol structure
121 * int tlevel current conditional level
122 * int xflag -x, listing radix flag
123 * FILE * lfp list output file handle
124 * FILE * ofp relocation output file handle
125 * FILE * tfp symbol table output file handle
126 * FILE * sfp[] array of assembler-source file handles
129 * FILE * afile() asmain.c
130 * VOID allglob() assym.c
131 * VOID asexit() asmain.c
132 * VOID diag() assubr.c
133 * VOID err() assubr.c
134 * int fprintf() c-library
135 * int getline() aslex.c
136 * VOID list() aslist.c
137 * VOID lstsym() aslist.c
138 * VOID minit() ___mch.c
139 * VOID newdot() asmain.c
140 * VOID outchk() asout.c
141 * VOID outgsd() asout.c
142 * int rewind() c-library
143 * int setjmp() c-library
144 * VOID symglob() assym.c
145 * VOID syminit() assym.c
146 * VOID usage() asmain.c
149 * Completion of main() completes the assembly process.
150 * REL, LST, and/or SYM files may be generated.
164 /*fprintf(stdout, "\n");*/
167 for (i=1; i<argc; ++i) {
173 while ((c = *p++) != 0)
191 case 'j': /* JLH: debug info */
194 ++oflag; /* force object */
241 if (++inpfil == MAXFIL) {
242 fprintf(stderr, "too many input files\n");
245 sfp[inpfil] = afile(p, "", 0);
246 strcpy(srcfn[inpfil],afn);
249 lfp = afile(p, "lst", 1);
251 ofp = afile(p, "rel", 1);
252 // save the file name if we have to delete it on error
256 tfp = afile(p, "sym", 1);
263 for (pass=0; pass<3; ++pass) {
264 if (gflag && pass == 1)
266 if (aflag && pass == 1)
268 if (oflag && pass == 2)
281 for (i = 0; i <= inpfil; i++)
300 /* JLH: if line begins with ";!", then
301 * pass this comment on to the output file
303 if (oflag && (pass == 1) &&
304 (ip[0] == ';') && (ip[1] == '!'))
306 fprintf(ofp, "%s\n", ip );
309 if (setjmp(jump_env) == 0)
317 newdot(dot.s_area); /* Flush area info */
318 if (flevel || tlevel)
322 outchk(HUGE, HUGE); /* Flush */
329 //printf ("aserr: %d\n", aserr);
330 //printf ("fatalErrors: %d\n", fatalErrors);
332 return 0; // hush the compiler
335 /*)Function VOID asexit(i)
339 * The function asexit() explicitly closes all open
340 * files and then terminates the program.
346 * FILE * ifp[] array of include-file file handles
347 * FILE * lfp list output file handle
348 * FILE * ofp relocation output file handle
349 * FILE * tfp symbol table output file handle
350 * FILE * sfp[] array of assembler-source file handles
353 * int fclose() c-library
354 * VOID exit() c-library
357 * All files closed. Program terminates.
366 if (lfp != NULL) fclose(lfp);
367 if (ofp != NULL) fclose(ofp);
368 if (tfp != NULL) fclose(tfp);
370 for (j=0; j<MAXFIL && sfp[j] != NULL; j++) {
374 /*for (j=0; j<MAXINC && ifp[j] != NULL; j++) {
378 // remove output file
379 printf ("removing %s\n", relFile);
385 /*)Function VOID asmbl()
387 * The function asmbl() scans the assembler-source text for
388 * (1) labels, global labels, equates, global equates, and local
389 * symbols, (2) .if, .else, .endif, and .page directives,
390 * (3) machine independent assembler directives, and (4) machine
391 * dependent mnemonics.
394 * mne * mp pointer to a mne structure
395 * sym * sp pointer to a sym structure
396 * tsym * tp pointer to a tsym structure
397 * int c character from assembler-source
399 * area * ap pointer to an area structure
400 * expr e1 expression structure
401 * char id[] id string
402 * char opt[] options string
403 * char fn[] filename string
404 * char * p pointer into a string
405 * int d temporary value
406 * int n temporary value
407 * int uaf user area options flag
408 * int uf area options
411 * area * areap pointer to an area structure
412 * char ctype[] array of character types, one per
414 * int flevel IF-ELSE-ENDIF flag will be non
415 * zero for false conditional case
416 * Addr_T fuzz tracks pass to pass changes in the
417 * address of symbols caused by
418 * variable length instruction formats
419 * int ifcnd[] array of IF statement condition
420 * values (0 = FALSE) indexed by tlevel
421 * int iflvl[] array of IF-ELSE-ENDIF flevel
422 * values indexed by tlevel
423 * FILE * ifp[] array of include-file file handles
424 * char incfn[][] array of include file names
425 * int incline[] current include file line
426 * int incfil current file handle index
428 * Addr_T laddr address of current assembler line
429 * or value of .if argument
430 * int lmode listing mode
431 * int lop current line number on page
432 * char module[] module name string
433 * int pass assembler pass number
434 * int radix current number conversion radix:
435 * 2 (binary), 8 (octal), 10 (decimal),
437 * char stb[] Subtitle string buffer
438 * sym * symp pointer to a symbol structure
439 * char tb[] Title string buffer
440 * int tlevel current conditional level
443 * Addr_T absexpr() asexpr.c
444 * area * alookup() assym.c
445 * VOID clrexpr() asexpr.c
446 * int digit() asexpr.c
447 * char endline() aslex.c
448 * VOID err() assubr.c
449 * VOID expr() asexpr.c
450 * FILE * fopen() c-library
452 * VOID getid() aslex.c
453 * int getmap() aslex.c
454 * char getnb() aslex.c
455 * VOID getst() aslex.c
456 * sym * lookup() assym.c
457 * VOID machin() ___mch.c
458 * mne * mlookup() assym.c
460 * VOID * new() assym.c
461 * VOID newdot() asmain.c
462 * VOID outall() asout.c
463 * VOID outab() asout.c
464 * VOID outchk() asout.c
465 * VOID outrb() asout.c
466 * VOID outrw() asout.c
467 * VOID phase() asmain.c
468 * VOID qerr() assubr.c
469 * char * strcpy() c-library
470 * char * strncpy() c-library
471 * VOID unget() aslex.c
477 register struct mne *mp;
478 register struct sym *sp;
479 register struct tsym *tp;
492 if ((c=endline()) == 0) { return; }
494 * If the first character is a digit then assume
495 * a local symbol is being specified. The symbol
496 * must end with $: to be valid.
498 * Construct a tsym structure at the first
499 * occurance of the symbol. Flag the symbol
500 * as multiply defined if not the first occurance.
502 * Load area, address, and fuzz values
503 * into structure tsym.
505 * Check for assembler phase error and
506 * multiply defined error.
508 if (ctype[c] & DIGIT) {
512 while ((d = digit(c, 10)) >= 0) {
516 if (c != '$' || get() != ':')
521 if (n == tp->t_num) {
528 tp=(struct tsym *) new (sizeof(struct tsym));
529 tp->t_lnk = symp->s_tsym;
532 tp->t_area = dot.s_area;
533 tp->t_addr = dot.s_addr;
538 if (n == tp->t_num) {
545 fuzz = tp->t_addr - dot.s_addr;
546 tp->t_area = dot.s_area;
547 tp->t_addr = dot.s_addr;
549 phase(tp->t_area, tp->t_addr);
550 if (tp->t_flg & S_MDF)
561 * If the first character is a letter then assume a lable,
562 * symbol, assembler directive, or assembler mnemonic is
565 if ((ctype[c] & LETTER) == 0) {
575 * If the next character is a : then a label is being processed.
576 * A double :: defines a global label. If this is new label
577 * then create a symbol structure.
579 * Flag multiply defined labels.
581 * Load area, address, and fuzz values
582 * into structure symp.
584 * Check for assembler phase error and
585 * multiply defined error.
590 if ((c = get()) != ':') {
598 if ((symp->s_type != S_NEW) &&
599 ((symp->s_flag & S_ASG) == 0))
600 symp->s_flag |= S_MDF;
602 fuzz = symp->s_addr - dot.s_addr;
603 symp->s_type = S_USER;
604 symp->s_area = dot.s_area;
605 symp->s_addr = dot.s_addr;
607 if (symp->s_flag & S_MDF)
609 phase(symp->s_area, symp->s_addr);
612 symp->s_flag |= S_GBL;
618 * If the next character is a = then an equate is being processed.
619 * A double == defines a global equate. If this is new variable
620 * then create a symbol structure.
625 if ((c = get()) != '=') {
634 if (e1.e_flag || e1.e_base.e_ap != dot.s_area)
637 if (sp->s_type != S_NEW && (sp->s_flag & S_ASG) == 0) {
641 sp->s_area = e1.e_base.e_ap;
642 sp->s_addr = laddr = e1.e_addr;
651 lmode = flevel ? SLIST : CLIST;
652 if ((mp = mlookup(id)) == NULL) {
658 * If we have gotten this far then we have found an
659 * assembler directive or an assembler mnemonic.
661 * Check for .if, .else, .endif, and .page directives
662 * which are not controlled by the conditional flags
664 switch (mp->m_type) {
668 if (tlevel < MAXIF) {
671 iflvl[tlevel] = flevel;
684 if (++flevel > (iflvl[tlevel]+1)) {
688 if (--flevel < iflvl[tlevel]) {
697 flevel = iflvl[tlevel--];
715 * If we are not in a false state for .if/.else then
716 * process the assembler directives here.
718 switch (mp->m_type) {
722 laddr = dot.s_addr = (dot.s_addr + 1) & ~1;
728 laddr = dot.s_addr |= 1;
737 if (mp->m_type == S_BYTE) {
742 } while ((c = getnb()) == ',');
748 if ((d = getnb()) == '\0')
750 while ((c = getmap(d)) >= 0)
752 if (mp->m_type == S_ASCIZ)
757 if ((d = getnb()) == '\0')
761 if ((n = getmap(d)) >= 0) {
774 dot.s_addr += e1.e_addr*mp->m_valu;
780 if ((c = getnb()) != 0) {
782 if (p < &tb[NTITL-1])
784 } while ((c = get()) != 0);
793 if ((c = getnb()) != 0) {
795 if (p < &stb[NSBTL-1])
797 } while ((c = get()) != 0);
810 strncpy(module, id, NCPS);
821 } while ((c = getnb()) == ',');
830 if ((c = getnb()) == '(') {
834 if (mp && mp->m_type == S_ATYP) {
840 } while ((c = getnb()) == ',');
846 if ((ap = alookup(id)) != NULL) {
847 if (uaf && uf != ap->a_flag)
849 if (ap->a_flag & A_OVR) {
854 ap = (struct area *) new (sizeof(struct area));
856 strncpy(ap->a_id, id, NCPS);
857 ap->a_ref = areap->a_ref + 1;
860 ap->a_flag = uaf ? uf : (A_CON|A_REL);
868 if (dot.s_area->a_flag & A_ABS) {
870 laddr = dot.s_addr = absexpr();
916 while ((c = get()) != d) {
917 if (p < &fn[FILSPC-1]) {
924 if (++incfil == MAXINC ||
925 (ifp[incfil] = fopen(fn, "r")) == NULL) {
931 strcpy(incfn[incfil],fn);
941 if (!strcmpi(id, "on"))
943 /* Quick sanity check: size of
944 * Addr_T must be at least 24 bits.
946 if (sizeof(Addr_T) < 3)
950 "Cannot enable Flat24 mode: "
951 "host system must have 24 bit "
952 "or greater integers.\n");
959 else if (!strcmpi(id, "off"))
974 printf("as8051: ds390 flat mode %sabled.\n",
975 flat24Mode ? "en" : "dis");
981 * If not an assembler directive then go to
982 * the machine dependent function which handles
983 * all the assembler mnemonics.
987 /* if cdb information the generate the line info */
988 if (cflag && (pass == 1))
991 /* JLH: if -j, generate a line number symbol */
992 if (jflag && (pass == 1))
1001 /*)Function FILE * afile(fn, ft, wf)
1003 * char * fn file specification string
1004 * char * ft file type string
1005 * int wf read(0)/write(1) flag
1007 * The function afile() opens a file for reading or writing.
1008 * (1) If the file type specification string ft
1009 * is not NULL then a file specification is
1010 * constructed with the file path\name in fn
1011 * and the extension in ft.
1012 * (2) If the file type specification string ft
1013 * is NULL then the file specification is
1014 * constructed from fn. If fn does not have
1015 * a file type then the default source file
1016 * type dsft is appended to the file specification.
1018 * afile() returns a file handle for the opened file or aborts
1019 * the assembler on an open error.
1022 * int c character value
1023 * FILE * fp filehandle for opened file
1024 * char * p1 pointer to filespec string fn
1025 * char * p2 pointer to filespec string fb
1026 * char * p3 pointer to filetype string ft
1029 * char afn[] afile() constructed filespec
1030 * char dsft[] default assembler file type string
1031 * char afn[] constructed file specification string
1034 * VOID asexit() asmain.c
1035 * FILE * fopen() c_library
1036 * int fprintf() c_library
1039 * File is opened for read or write.
1048 register char *p1, *p2, *p3;
1055 while ((c = *p1++) != 0 && c != FSEPX) {
1056 if (p2 < &afn[FILSPC-4])
1067 while ((c = *p3++) != 0) {
1068 if (p2 < &afn[FILSPC-1])
1072 if ((fp = fopen(afn, wf?"w":"r")) == NULL) {
1073 fprintf(stderr, "%s: cannot %s.\n", afn, wf?"create":"open");
1079 /*)Function VOID newdot(nap)
1081 * area * nap pointer to the new area structure
1083 * The function newdot():
1084 * (1) copies the current values of fuzz and the last
1085 * address into the current area referenced by dot
1086 * (2) loads dot with the pointer to the new area and
1087 * loads the fuzz and last address parameters
1088 * (3) outall() is called to flush any remaining
1089 * bufferred code from the old area to the output
1092 * area * oap pointer to old area
1095 * sym dot defined as sym[0]
1096 * Addr_T fuzz tracks pass to pass changes in the
1097 * address of symbols caused by
1098 * variable length instruction formats
1104 * Current area saved, new area loaded, buffers flushed.
1109 register struct area *nap;
1111 register struct area *oap;
1115 oap->a_size = dot.s_addr;
1118 dot.s_addr = nap->a_size;
1122 /*)Function VOID phase(ap, a)
1124 * area * ap pointer to area
1125 * Addr_T a address in area
1127 * Function phase() compares the area ap and address a
1128 * with the current area dot.s_area and address dot.s_addr
1129 * to determine if the position of the symbol has changed
1130 * between assembler passes.
1136 * sym * dot defined as sym[0]
1142 * The p error is invoked if the area and/or address
1151 if (ap != dot.s_area || a != dot.s_addr)
1156 "Usage: [-dqxjgalopsf] file1 [file2 file3 ...]",
1157 " d decimal listing",
1159 " x hex listing (default)",
1160 " j add line number and debug information to file", /* JLH */
1161 " g undefined symbols made global",
1162 " a all user symbols made global",
1163 " l create list output file1[LST]",
1164 " o create object output file1[REL]",
1165 " s create symbol output file1[SYM]",
1166 " p disable listing pagination",
1167 " f flag relocatable references by ` in listing file",
1168 " ff flag relocatable references by mode in listing file",
1173 /*)Function VOID usage()
1175 * The function usage() outputs to the stderr device the
1176 * assembler name and version and a list of valid assembler options.
1179 * char ** dp pointer to an array of
1180 * text string pointers.
1183 * char cpu[] assembler type string
1184 * char * usetxt[] array of string pointers
1187 * VOID asexit() asmain.c
1188 * int fprintf() c_library
1191 * program is terminated
1199 fprintf(stderr, "\nASxxxx Assembler %s (%s)\n\n", VERSION, cpu);
1200 for (dp = usetxt; *dp; dp++)
1201 fprintf(stderr, "%s\n", *dp);