X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=as%2Fz80%2Fasmain.c;h=b072acc22b574e54e738d7bbbf46f9a6461553e1;hb=22ec133e94d056a395025c302b6c331c8cd04658;hp=a74d7648856d6873d711d1df6b9c315279a881fc;hpb=0abb805fd2d72a89b41a10144ded610ebfc072bc;p=fw%2Fsdcc diff --git a/as/z80/asmain.c b/as/z80/asmain.c index a74d7648..b072acc2 100644 --- a/as/z80/asmain.c +++ b/as/z80/asmain.c @@ -1,1189 +1,1251 @@ -/* asmain.c */ +/* asmain.c -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ + Copyright (C) 1989-1995 Alan R. Baldwin + 721 Berkeley St., Kent, Ohio 44240 + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . */ /* * Extensions: P. Felber + * 13-Feb-08 AD -j and -c as in 8051 as */ #include #include #include -#include + #ifdef SDK #include #include #undef HUGE #endif #include "asm.h" +#include "z80.h" -/*)Module asmain.c +/*)Module asmain.c * - * The module asmain.c includes the command argument parser, - * the three pass sequencer, and the machine independent - * assembler parsing code. + * The module asmain.c includes the command argument parser, + * the three pass sequencer, and the machine independent + * assembler parsing code. * - * asmain.c contains the following functions: - * VOID main(argc, argv) - * VOID asexit() - * VOID asmbl() - * FILE * afile(fn, ft, wf) - * VOID newdot(nap) - * VOID phase(ap, a) - * VOID usage() + * asmain.c contains the following functions: + * VOID main(argc, argv) + * VOID asexit() + * VOID asmbl() + * FILE * afile(fn, ft, wf) + * VOID newdot(nap) + * VOID phase(ap, a) + * VOID usage() * - * asmain.c contains the array char *usetxt[] which - * references the usage text strings printed by usage(). + * asmain.c contains the array char *usetxt[] which + * references the usage text strings printed by usage(). */ -/*)Function VOID main(argc, argv) +/*)Function VOID main(argc, argv) * - * int argc argument count - * char * argv array of pointers to argument strings + * int argc argument count + * char * argv array of pointers to argument strings * - * The function main() is the entry point to the assembler. - * The purpose of main() is to (1) parse the command line - * arguments for options and source file specifications and - * (2) to process the source files through the 3 pass assembler. - * Before each assembler pass various variables are initialized - * and source files are rewound to their beginning. During each - * assembler pass each assembler-source text line is processed. - * After each assembler pass the assembler information is flushed - * to any opened output files and the if-else-endif processing - * is checked for proper termination. + * The function main() is the entry point to the assembler. + * The purpose of main() is to (1) parse the command line + * arguments for options and source file specifications and + * (2) to process the source files through the 3 pass assembler. + * Before each assembler pass various variables are initialized + * and source files are rewound to their beginning. During each + * assembler pass each assembler-source text line is processed. + * After each assembler pass the assembler information is flushed + * to any opened output files and the if-else-endif processing + * is checked for proper termination. * - * The function main() is also responsible for opening all - * output files (REL, LST, and SYM), sequencing the global (-g) - * and all-global (-a) variable definitions, and dumping the - * REL file header information. + * The function main() is also responsible for opening all + * output files (REL, LST, and SYM), sequencing the global (-g) + * and all-global (-a) variable definitions, and dumping the + * REL file header information. * - * local variables: - * char * p pointer to argument string - * int c character from argument string - * int i argument loop counter - * area * ap pointer to area structure + * local variables: + * char * p pointer to argument string + * int c character from argument string + * int i argument loop counter + * area * ap pointer to area structure * - * global variables: - * int aflag -a, make all symbols global flag - * char afn[] afile() constructed filespec - * area * areap pointer to an area structure - * int cb[] array of assembler output values - * int cbt[] array of assembler relocation types - * describing the data in cb[] - * int cfile current file handle index - * of input assembly files - * int * cp pointer to assembler output array cb[] - * int * cpt pointer to assembler relocation type - * output array cbt[] - * char eb[] array of generated error codes - * char * ep pointer into error list array eb[] - * int fflag -f(f), relocations flagged flag - * int flevel IF-ELSE-ENDIF flag will be non - * zero for false conditional case - * addr_t fuzz tracks pass to pass changes in the - * address of symbols caused by - * variable length instruction formats - * int gflag -g, make undefined symbols global flag - * char ib[] assembler-source text line - * int inpfil count of assembler - * input files specified - * int ifcnd[] array of IF statement condition - * values (0 = FALSE) indexed by tlevel - * int iflvl[] array of IF-ELSE-ENDIF flevel - * values indexed by tlevel - * int incfil current file handle index - * for include files - * char * ip pointer into the assembler-source - * text line in ib[] - * jmp_buf jump_env compiler dependent structure - * used by setjmp() and longjmp() - * int lflag -l, generate listing flag - * int line current assembler source - * line number - * int lop current line number on page - * int oflag -o, generate relocatable output flag - * int page current page number - * int pflag enable listing pagination - * int pass assembler pass number - * int radix current number conversion radix: - * 2 (binary), 8 (octal), 10 (decimal), - * 16 (hexadecimal) - * int sflag -s, generate symbol table flag - * char srcfn[][] array of source file names - * int srcline[] current source file line - * char stb[] Subtitle string buffer - * sym * symp pointer to a symbol structure - * int tlevel current conditional level - * int xflag -x, listing radix flag - * FILE * lfp list output file handle - * FILE * ofp relocation output file handle - * FILE * tfp symbol table output file handle - * FILE * sfp[] array of assembler-source file handles + * global variables: + * int aflag -a, make all symbols global flag + * char afn[] afile() constructed filespec + * area * areap pointer to an area structure + * int cb[] array of assembler output values + * int cbt[] array of assembler relocation types + * describing the data in cb[] + * int cfile current file handle index + * of input assembly files + * int * cp pointer to assembler output array cb[] + * int * cpt pointer to assembler relocation type + * output array cbt[] + * char eb[] array of generated error codes + * char * ep pointer into error list array eb[] + * int fflag -f(f), relocations flagged flag + * int flevel IF-ELSE-ENDIF flag will be non + * zero for false conditional case + * Addr_T fuzz tracks pass to pass changes in the + * address of symbols caused by + * variable length instruction formats + * int gflag -g, make undefined symbols global flag + * char ib[] assembler-source text line + * int inpfil count of assembler + * input files specified + * int ifcnd[] array of IF statement condition + * values (0 = FALSE) indexed by tlevel + * int iflvl[] array of IF-ELSE-ENDIF flevel + * values indexed by tlevel + * int incfil current file handle index + * for include files + * char * ip pointer into the assembler-source + * text line in ib[] + * jmp_buf jump_env compiler dependent structure + * used by setjmp() and longjmp() + * int lflag -l, generate listing flag + * int line current assembler source + * line number + * int lop current line number on page + * int oflag -o, generate relocatable output flag + * int jflag -j, generate debug info flag + * int page current page number + * int pflag enable listing pagination + * int pass assembler pass number + * int radix current number conversion radix: + * 2 (binary), 8 (octal), 10 (decimal), + * 16 (hexadecimal) + * int sflag -s, generate symbol table flag + * char srcfn[][] array of source file names + * int srcline[] current source file line + * char stb[] Subtitle string buffer + * sym * symp pointer to a symbol structure + * int tlevel current conditional level + * int xflag -x, listing radix flag + * FILE * lfp list output file handle + * FILE * ofp relocation output file handle + * FILE * tfp symbol table output file handle + * FILE * sfp[] array of assembler-source file handles * - * called functions: - * FILE * afile() asmain.c - * VOID allglob() assym.c - * VOID asexit() asmain.c - * VOID diag() assubr.c - * VOID err() assubr.c - * int fprintf() c-library - * int getline() aslex.c - * VOID list() aslist.c - * VOID lstsym() aslist.c - * VOID minit() ___mch.c - * VOID newdot() asmain.c - * VOID outchk() asout.c - * VOID outgsd() asout.c - * int rewind() c-library - * int setjmp() c-library - * VOID symglob() assym.c - * VOID syminit() assym.c - * VOID usage() asmain.c + * called functions: + * FILE * afile() asmain.c + * VOID allglob() assym.c + * VOID asexit() asmain.c + * VOID diag() assubr.c + * VOID err() assubr.c + * int fprintf() c-library + * int as_getline() aslex.c + * VOID list() aslist.c + * VOID lstsym() aslist.c + * VOID minit() ___mch.c + * VOID newdot() asmain.c + * VOID outchk() asout.c + * VOID outgsd() asout.c + * int rewind() c-library + * int setjmp() c-library + * VOID symglob() assym.c + * VOID syminit() assym.c + * VOID usage() asmain.c * - * side effects: - * Completion of main() completes the assembly process. - * REL, LST, and/or SYM files may be generated. + * side effects: + * Completion of main() completes the assembly process. + * REL, LST, and/or SYM files may be generated. */ int main(int argc, char **argv) { - register char *p; - register int c, i; - struct area *ap; + register char *p; + register int c, i; + struct area *ap; + /* Check to make sure there are the right number of filenames */ + /* before openning any of them */ #ifdef SDK - inpfil = -2; + inpfil = -2; #else /* SDK */ - fprintf(stdout, "\n"); - inpfil = -1; + inpfil = -1; #endif /* SDK */ - pflag = 1; - for (i=1; i= 0) - usage(); - ++p; - while ((c = *p++) != 0) - switch(c) { - - case 'a': - case 'A': - ++aflag; - break; - - case 'g': - case 'G': - ++gflag; - break; - - case 'l': - case 'L': - ++lflag; - break; - - case 'o': - case 'O': - ++oflag; - break; - - case 's': - case 'S': - ++sflag; - break; - - case 'p': - case 'P': - pflag = 0; - break; - - case 'x': - case 'X': - xflag = 0; - break; - - case 'q': - case 'Q': - xflag = 1; - break; - - case 'd': - case 'D': - xflag = 2; - break; - - case 'f': - case 'F': - ++fflag; - break; - - default: - usage(); - } - } else { + for (i=1; i= 0) + usage(); + ++p; + while ((c = *p++) != 0) + switch(c) { + + case 'a': + case 'A': + ++aflag; + break; + + case 'c': + case 'C': + ++cflag; + break; + + case 'g': + case 'G': + ++gflag; + break; + + case 'j': /* JLH: debug info */ + case 'J': + ++jflag; + ++oflag; /* force object */ + break; + + case 'l': + case 'L': + ++lflag; + break; + + case 'o': + case 'O': + ++oflag; + break; + + case 's': + case 'S': + ++sflag; + break; + + case 'p': + case 'P': + pflag = 0; + break; + + case 'x': + case 'X': + xflag = 0; + break; + + case 'q': + case 'Q': + xflag = 1; + break; + + case 'd': + case 'D': + xflag = 2; + break; + + case 'f': + case 'F': + ++fflag; + break; + + default: + usage(); + } + } else { #ifdef SDK - if(inpfil != -2) { + if(inpfil != -2) { #endif /* SDK */ - if (++inpfil == MAXFIL) { - fprintf(stderr, "too many input files\n"); - asexit(1); - } - sfp[inpfil] = afile(p, "", 0); - strcpy(srcfn[inpfil],afn); + if (++inpfil == MAXFIL) { + fprintf(stderr, "too many input files\n"); + asexit(1); + } + sfp[inpfil] = afile(p, "", 0); + strcpy(srcfn[inpfil],afn); #ifdef SDK - } else - inpfil++; - if (inpfil == -1) { - if (lflag) - lfp = afile(p, "lst", 1); - if (oflag) - ofp = afile(p, "", 1); - if (sflag) - tfp = afile(p, "sym", 1); - } + } else + inpfil++; + if (inpfil == -1) { + if (lflag) + lfp = afile(p, "lst", 1); + if (oflag) + ofp = afile(p, "", 1); + if (sflag) + tfp = afile(p, "sym", 1); + } #else /* SDK */ - if (inpfil == 0) { - if (lflag) - lfp = afile(p, "LST", 1); - if (oflag) - ofp = afile(p, "REL", 1); - if (sflag) - tfp = afile(p, "SYM", 1); - } + if (inpfil == 0) { + if (lflag) + lfp = afile(p, "LST", 1); + if (oflag) + ofp = afile(p, "REL", 1); + if (sflag) + tfp = afile(p, "SYM", 1); + } #endif /* SDK */ - } - } - if (inpfil < 0) - usage(); - syminit(); - for (pass=0; pass<3; ++pass) { - if (gflag && pass == 1) - symglob(); - if (aflag && pass == 1) - allglob(); - if (oflag && pass == 2) - outgsd(); - flevel = 0; - tlevel = 0; - ifcnd[0] = 0; - iflvl[0] = 0; - radix = 10; - srcline[0] = 0; - page = 0; - stb[0] = 0; - lop = NLPP; - cfile = 0; - incfil = -1; - for (i = 0; i <= inpfil; i++) - rewind(sfp[i]); - ap = areap; - while (ap) { - ap->a_fuzz = 0; - ap->a_size = 0; - ap = ap->a_ap; - } - fuzz = 0; - dot.s_addr = 0; - dot.s_area = &dca; - symp = ˙ - minit(); - while (getline()) { - cp = cb; - cpt = cbt; - ep = eb; - ip = ib; - if (setjmp(jump_env) == 0) - asmbl(); - if (pass == 2) { - diag(); - list(); - } - } - newdot(dot.s_area); /* Flush area info */ - if (flevel || tlevel) - err('i'); - } - if (oflag) - outchk(HUGE, HUGE); /* Flush */ - if (sflag) { - lstsym(tfp); - } else - if (lflag) { - lstsym(lfp); - } - asexit(aserr); - /* Never reached */ - return 0; + } + } + if (inpfil < 0) + usage(); + syminit(); + for (pass=0; pass<3; ++pass) { + if (gflag && pass == 1) + symglob(); + if (aflag && pass == 1) + allglob(); + if (oflag && pass == 2) + outgsd(); + flevel = 0; + tlevel = 0; + ifcnd[0] = 0; + iflvl[0] = 0; + radix = 10; + srcline[0] = 0; + page = 0; + stb[0] = 0; + lop = NLPP; + cfile = 0; + incfil = -1; + for (i = 0; i <= inpfil; i++) + rewind(sfp[i]); + ap = areap; + while (ap) { + ap->a_fuzz = 0; + ap->a_size = 0; + ap = ap->a_ap; + } + fuzz = 0; + dot.s_addr = 0; + dot.s_area = &dca; + symp = ˙ + minit(); + while (as_getline()) { + cp = cb; + cpt = cbt; + ep = eb; + ip = ib; + if (setjmp(jump_env) == 0) + asmbl(); + if (pass == 2) { + diag(); + list(); + } + } + newdot(dot.s_area); /* Flush area info */ + if (flevel || tlevel) + err('i'); + } + if (oflag) + outchk(HUGE, HUGE); /* Flush */ + if (sflag) { + lstsym(tfp); + } else + if (lflag) { + lstsym(lfp); + } + asexit(aserr != 0); + /* Never reached */ + return 0; } -/*)Function VOID asexit(i) +/*)Function VOID asexit(i) * - * int i exit code + * int i exit code * - * The function asexit() explicitly closes all open - * files and then terminates the program. + * The function asexit() explicitly closes all open + * files and then terminates the program. * - * local variables: - * int j loop counter + * local variables: + * int j loop counter * - * global variables: - * FILE * ifp[] array of include-file file handles - * FILE * lfp list output file handle - * FILE * ofp relocation output file handle - * FILE * tfp symbol table output file handle - * FILE * sfp[] array of assembler-source file handles + * global variables: + * FILE * ifp[] array of include-file file handles + * FILE * lfp list output file handle + * FILE * ofp relocation output file handle + * FILE * tfp symbol table output file handle + * FILE * sfp[] array of assembler-source file handles * - * functions called: - * int fclose() c-library - * VOID exit() c-library + * functions called: + * int fclose() c-library + * VOID exit() c-library * - * side effects: - * All files closed. Program terminates. + * side effects: + * All files closed. Program terminates. */ VOID -asexit(i) -int i; +asexit(int i) { - int j; + int j; - if (lfp != NULL) fclose(lfp); - if (ofp != NULL) fclose(ofp); - if (tfp != NULL) fclose(tfp); + if (lfp != NULL) fclose(lfp); + if (ofp != NULL) fclose(ofp); + if (tfp != NULL) fclose(tfp); - for (j=0; j= 0) { - n = 10*n + d; - c = get(); - } - if (c != '$' || get() != ':') - qerr(); - tp = symp->s_tsym; - if (pass == 0) { - while (tp) { - if (n == tp->t_num) { - tp->t_flg |= S_MDF; - break; - } - tp = tp->t_lnk; - } - if (tp == NULL) { - tp=(struct tsym *) new (sizeof(struct tsym)); - tp->t_lnk = symp->s_tsym; - tp->t_num = n; - tp->t_flg = 0; - tp->t_area = dot.s_area; - tp->t_addr = dot.s_addr; - symp->s_tsym = tp; - } - } else { - while (tp) { - if (n == tp->t_num) { - break; - } - tp = tp->t_lnk; - } - if (tp) { - if (pass == 1) { - fuzz = tp->t_addr - dot.s_addr; - tp->t_area = dot.s_area; - tp->t_addr = dot.s_addr; - } else { - phase(tp->t_area, tp->t_addr); - if (tp->t_flg & S_MDF) - err('m'); - } - } else { - err('u'); - } - } - lmode = ALIST; - goto loop; - } - /* - * If the first character is a letter then assume a lable, - * symbol, assembler directive, or assembler mnemonic is - * being processed. - */ - if ((ctype[c] & LETTER) == 0) - if (flevel) { - return; - } else { - qerr(); - } - getid(id, c); - c = getnb(); - /* - * If the next character is a : then a label is being processed. - * A double :: defines a global label. If this is new label - * then create a symbol structure. - * pass 0: - * Flag multiply defined labels. - * pass 1: - * Load area, address, and fuzz values - * into structure symp. - * pass 2: - * Check for assembler phase error and - * multiply defined error. - */ - if (c == ':') { - if (flevel) - return; - if ((c = get()) != ':') { - unget(c); - c = 0; - } - symp = lookup(id); - if (symp == &dot) - err('.'); - if (pass == 0) - if ((symp->s_type != S_NEW) && - ((symp->s_flag & S_ASG) == 0)) - symp->s_flag |= S_MDF; - if (pass != 2) { - fuzz = symp->s_addr - dot.s_addr; - symp->s_type = S_USER; - symp->s_area = dot.s_area; - symp->s_addr = dot.s_addr; - } else { - if (symp->s_flag & S_MDF) - err('m'); - phase(symp->s_area, symp->s_addr); - } - if (c) { - symp->s_flag |= S_GBL; - } - lmode = ALIST; - goto loop; - } - /* - * If the next character is a = then an equate is being processed. - * A double == defines a global equate. If this is new variable - * then create a symbol structure. - */ - if (c == '=') { - if (flevel) - return; - if ((c = get()) != '=') { - unget(c); - c = 0; - } - clrexpr(&e1); - expr(&e1, 0); - sp = lookup(id); - if (sp == &dot) { - outall(); - if (e1.e_flag || e1.e_base.e_ap != dot.s_area) - err('.'); - } else - if (sp->s_type != S_NEW && (sp->s_flag & S_ASG) == 0) { - err('m'); - } - sp->s_type = S_USER; - sp->s_area = e1.e_base.e_ap; - sp->s_addr = laddr = e1.e_addr; - sp->s_flag |= S_ASG; - if (c) { - sp->s_flag |= S_GBL; - } - lmode = ELIST; - goto loop; - } - unget(c); - lmode = flevel ? SLIST : CLIST; - if ((mp = mlookup(id)) == NULL) { - if (!flevel) - err('o'); - return; - } - /* - * If we have gotten this far then we have found an - * assembler directive or an assembler mnemonic. - * - * Check for .if, .else, .endif, and .page directives - * which are not controlled by the conditional flags - */ - switch (mp->m_type) { - - case S_IF: - n = absexpr(); - if (tlevel < MAXIF) { - ++tlevel; - ifcnd[tlevel] = n; - iflvl[tlevel] = flevel; - if (n == 0) { - ++flevel; - } - } else { - err('i'); - } - lmode = ELIST; - laddr = n; - return; - - case S_ELSE: - if (ifcnd[tlevel]) { - if (++flevel > (iflvl[tlevel]+1)) { - err('i'); - } - } else { - if (--flevel < iflvl[tlevel]) { - err('i'); - } - } - lmode = SLIST; - return; - - case S_ENDIF: - if (tlevel) { - flevel = iflvl[tlevel--]; - } else { - err('i'); - } - lmode = SLIST; - return; - - case S_PAGE: - lop = NLPP; - lmode = NLIST; - return; - - default: - break; - } - if (flevel) - return; - /* - * If we are not in a false state for .if/.else then - * process the assembler directives here. - */ - switch (mp->m_type) { - - case S_EVEN: - outall(); - laddr = dot.s_addr = (dot.s_addr + 1) & ~1; - lmode = ALIST; - break; - - case S_ODD: - outall(); - laddr = dot.s_addr |= 1; - lmode = ALIST; - break; - - case S_BYTE: - case S_WORD: - do { - clrexpr(&e1); - expr(&e1, 0); - if (mp->m_type == S_BYTE) { - outrb(&e1, R_NORM); - } else { - outrw(&e1, R_NORM); - } - } while ((c = getnb()) == ','); - unget(c); - break; + if ((c=endline()) == 0) { return; } + /* + * If the first character is a digit then assume + * a local symbol is being specified. The symbol + * must end with $: to be valid. + * pass 0: + * Construct a tsym structure at the first + * occurance of the symbol. Flag the symbol + * as multiply defined if not the first occurance. + * pass 1: + * Load area, address, and fuzz values + * into structure tsym. + * pass 2: + * Check for assembler phase error and + * multiply defined error. + */ + if (ctype[c] & DIGIT) { + if (flevel) + return; + n = 0; + while ((d = digit(c, 10)) >= 0) { + n = 10*n + d; + c = get(); + } + if (c != '$' || get() != ':') + qerr(); + tp = symp->s_tsym; + if (pass == 0) { + while (tp) { + if (n == tp->t_num) { + tp->t_flg |= S_MDF; + break; + } + tp = tp->t_lnk; + } + if (tp == NULL) { + tp=(struct tsym *) new (sizeof(struct tsym)); + tp->t_lnk = symp->s_tsym; + tp->t_num = n; + tp->t_flg = 0; + tp->t_area = dot.s_area; + tp->t_addr = dot.s_addr; + symp->s_tsym = tp; + } + } else { + while (tp) { + if (n == tp->t_num) { + break; + } + tp = tp->t_lnk; + } + if (tp) { + if (pass == 1) { + fuzz = tp->t_addr - dot.s_addr; + tp->t_area = dot.s_area; + tp->t_addr = dot.s_addr; + } else { + phase(tp->t_area, tp->t_addr); + if (tp->t_flg & S_MDF) + err('m'); + } + } else { + err('u'); + } + } + lmode = ALIST; + goto loop; + } + /* + * If the first character is a letter then assume a label, + * symbol, assembler directive, or assembler mnemonic is + * being processed. + */ + if ((ctype[c] & LETTER) == 0) { + if (flevel) { + return; + } else { + qerr(); + } + } + getid(id, c); + c = getnb(); + /* + * If the next character is a : then a label is being processed. + * A double :: defines a global label. If this is new label + * then create a symbol structure. + * pass 0: + * Flag multiply defined labels. + * pass 1: + * Load area, address, and fuzz values + * into structure symp. + * pass 2: + * Check for assembler phase error and + * multiply defined error. + */ + if (c == ':') { + if (flevel) + return; + if ((c = get()) != ':') { + unget(c); + c = 0; + } + symp = lookup(id); + if (symp == &dot) + err('.'); + if (pass == 0) + if ((symp->s_type != S_NEW) && + ((symp->s_flag & S_ASG) == 0)) + symp->s_flag |= S_MDF; + if (pass != 2) { + fuzz = symp->s_addr - dot.s_addr; + symp->s_type = S_USER; + symp->s_area = dot.s_area; + symp->s_addr = dot.s_addr; + } else { + if (symp->s_flag & S_MDF) + err('m'); + phase(symp->s_area, symp->s_addr); + } + if (c) { + symp->s_flag |= S_GBL; + } + lmode = ALIST; + goto loop; + } + /* + * If the next character is a = then an equate is being processed. + * A double == defines a global equate. If this is new variable + * then create a symbol structure. + */ + if (c == '=') { + if (flevel) + return; + if ((c = get()) != '=') { + unget(c); + c = 0; + } + clrexpr(&e1); + expr(&e1, 0); + sp = lookup(id); + if (sp == &dot) { + outall(); + if (e1.e_flag || e1.e_base.e_ap != dot.s_area) + err('.'); + } else + if (sp->s_type != S_NEW && (sp->s_flag & S_ASG) == 0) { + err('m'); + } + sp->s_type = S_USER; + sp->s_area = e1.e_base.e_ap; + sp->s_addr = laddr = e1.e_addr; + sp->s_flag |= S_ASG; + if (c) { + sp->s_flag |= S_GBL; + } + lmode = ELIST; + goto loop; + } + unget(c); + lmode = flevel ? SLIST : CLIST; + if ((mp = mlookup(id)) == NULL) { + if (!flevel) + err('o'); + return; + } + /* + * If we have gotten this far then we have found an + * assembler directive or an assembler mnemonic. + * + * Check for .if, .else, .endif, and .page directives + * which are not controlled by the conditional flags + */ + switch (mp->m_type) { + + case S_IF: + n = absexpr(); + if (tlevel < MAXIF) { + ++tlevel; + ifcnd[tlevel] = n; + iflvl[tlevel] = flevel; + if (n == 0) { + ++flevel; + } + } else { + err('i'); + } + lmode = ELIST; + laddr = n; + return; + + case S_ELSE: + if (ifcnd[tlevel]) { + if (++flevel > (iflvl[tlevel]+1)) { + err('i'); + } + } else { + if (--flevel < iflvl[tlevel]) { + err('i'); + } + } + lmode = SLIST; + return; + + case S_ENDIF: + if (tlevel) { + flevel = iflvl[tlevel--]; + } else { + err('i'); + } + lmode = SLIST; + return; + + case S_PAGE: + lop = NLPP; + lmode = NLIST; + return; + + default: + break; + } + if (flevel) + return; + /* + * If we are not in a false state for .if/.else then + * process the assembler directives here. + */ + switch (mp->m_type) { + + case S_EVEN: + outall(); + laddr = dot.s_addr = (dot.s_addr + 1) & ~1; + lmode = ALIST; + break; + + case S_ODD: + outall(); + laddr = dot.s_addr |= 1; + lmode = ALIST; + break; + + case S_BYTE: + case S_WORD: + do { + clrexpr(&e1); + expr(&e1, 0); + if (mp->m_type == S_BYTE) { + outrb(&e1, R_NORM); + } else { + outrw(&e1, R_NORM); + } + } while ((c = getnb()) == ','); + unget(c); + break; #ifdef SDK - case S_FLOAT: - do { - getid( readbuffer, ' ' ); /* Hack :) */ - if ((c=getnb())=='.') - { - getid(&readbuffer[strlen(readbuffer)],'.'); - } - else - unget(c); - - f1 = strtod( readbuffer, (char **)NULL ); - /* Convert f1 to a gb-lib type fp - * 24 bit mantissa followed by 7 bit exp and 1 bit sign - */ - - if (f1!=0) - { - - f2 = floor(log(fabs(f1))/log(2))+1; - mantissa = (0x1000000*fabs(f1))/exp(f2*log(2)); - mantissa &=0xffffff; - exponent = f2 + 0x40; - if (f1<0) - exponent |=0x80; - } - - else - { - mantissa=0; - exponent=0; - } - - outab(mantissa&0xff); - outab((mantissa>>8)&0xff); - outab((mantissa>>16)&0xff); - outab(exponent&0xff); - - } while ((c = getnb()) == ','); - unget(c); - break; + case S_FLOAT: + do { + getid( readbuffer, ' ' ); /* Hack :) */ + if ((c=getnb())=='.') + { + getid(&readbuffer[strlen(readbuffer)],'.'); + } + else + unget(c); + + f1 = strtod( readbuffer, (char **)NULL ); + /* Convert f1 to a gb-lib type fp + * 24 bit mantissa followed by 7 bit exp and 1 bit sign + */ + + if (f1!=0) + { + + f2 = floor(log(fabs(f1))/log(2))+1; + mantissa = (unsigned int) ((0x1000000*fabs(f1))/exp(f2*log(2))) ; + mantissa &=0xffffff; + exponent = (unsigned int) (f2 + 0x40) ; + if (f1<0) + exponent |=0x80; + } + + else + { + mantissa=0; + exponent=0; + } + + outab(mantissa&0xff); + outab((mantissa>>8)&0xff); + outab((mantissa>>16)&0xff); + outab(exponent&0xff); + + } while ((c = getnb()) == ','); + unget(c); + break; #endif - case S_ASCII: - case S_ASCIZ: - if ((d = getnb()) == '\0') - qerr(); - while ((c = getmap(d)) >= 0) - outab(c); - if (mp->m_type == S_ASCIZ) - outab(0); - break; - - case S_ASCIS: - if ((d = getnb()) == '\0') - qerr(); - c = getmap(d); - while (c >= 0) { - if ((n = getmap(d)) >= 0) { - outab(c); - } else { - outab(c | 0x80); - } - c = n; - } - break; - - case S_BLK: - clrexpr(&e1); - expr(&e1, 0); - dot.s_addr += e1.e_addr*mp->m_valu; - outchk(HUGE,HUGE); - lmode = BLIST; - break; - - case S_TITLE: - p = tb; - if ((c = getnb()) != 0) { - do { - if (p < &tb[NTITL-1]) - *p++ = c; - } while ((c = get()) != 0); - } - *p = 0; - unget(c); - lmode = SLIST; - break; - - case S_SBTL: - p = stb; - if ((c = getnb()) != 0) { - do { - if (p < &stb[NSBTL-1]) - *p++ = c; - } while ((c = get()) != 0); - } - *p = 0; - unget(c); - lmode = SLIST; - break; - - case S_MODUL: - getst(id, -1); - if (pass == 0) { - if (module[0]) { - err('m'); - } else { - strncpy(module, id, NCPS); - } - } - lmode = SLIST; - break; - - case S_GLOBL: - do { - getid(id, -1); - sp = lookup(id); - sp->s_flag |= S_GBL; - } while ((c = getnb()) == ','); - unget(c); - lmode = SLIST; - break; - - case S_DAREA: - getid(id, -1); - uaf = 0; - uf = A_CON|A_REL; - if ((c = getnb()) == '(') { - do { - getid(opt, -1); - mp = mlookup(opt); - if (mp && mp->m_type == S_ATYP) { - ++uaf; - uf |= mp->m_valu; - } else { - err('u'); - } - } while ((c = getnb()) == ','); - if (c != ')') - qerr(); - } else { - unget(c); - } - if ((ap = alookup(id)) != NULL) { - if (uaf && uf != ap->a_flag) - err('m'); - } else { - ap = (struct area *) new (sizeof(struct area)); - ap->a_ap = areap; - strncpy(ap->a_id, id, NCPS); - ap->a_ref = areap->a_ref + 1; - ap->a_size = 0; - ap->a_fuzz = 0; - ap->a_flag = uaf ? uf : (A_CON|A_REL); - areap = ap; - } - newdot(ap); - lmode = SLIST; - break; - - case S_ORG: - if (dot.s_area->a_flag & A_ABS) { - outall(); - laddr = dot.s_addr = absexpr(); - } else { - err('o'); - } - outall(); - lmode = ALIST; - break; - - case S_RADIX: - if (more()) { - switch (getnb()) { - case 'b': - case 'B': - radix = 2; - break; - case '@': - case 'o': - case 'O': - case 'q': - case 'Q': - radix = 8; - break; - case 'd': - case 'D': - radix = 10; - break; - case 'h': - case 'H': - case 'x': - case 'X': - radix = 16; - break; - default: - radix = 10; - qerr(); - break; - } - } else { - radix = 10; - } - lmode = SLIST; - break; - - case S_INCL: - d = getnb(); - p = fn; - while ((c = get()) != d) { - if (p < &fn[FILSPC-1]) { - *p++ = c; - } else { - break; - } - } - *p = 0; - if (++incfil == MAXINC || - (ifp[incfil] = fopen(fn, "r")) == NULL) { - --incfil; - err('i'); - } else { - lop = NLPP; - incline[incfil] = 0; - strcpy(incfn[incfil],fn); - } - lmode = SLIST; - break; - - /* - * If not an assembler directive then go to - * the machine dependent function which handles - * all the assembler mnemonics. - */ - default: - machine(mp); - } - goto loop; + case S_ASCII: + case S_ASCIZ: + if ((d = getnb()) == '\0') + qerr(); + while ((c = getmap(d)) >= 0) + outab(c); + if (mp->m_type == S_ASCIZ) + outab(0); + break; + + case S_ASCIS: + if ((d = getnb()) == '\0') + qerr(); + c = getmap(d); + while (c >= 0) { + if ((n = getmap(d)) >= 0) { + outab(c); + } else { + outab(c | 0x80); + } + c = n; + } + break; + + case S_BLK: + clrexpr(&e1); + expr(&e1, 0); + dot.s_addr += e1.e_addr*mp->m_valu; + outchk(HUGE,HUGE); + lmode = BLIST; + break; + + case S_TITLE: + p = tb; + if ((c = getnb()) != 0) { + do { + if (p < &tb[NTITL-1]) + *p++ = c; + } while ((c = get()) != 0); + } + *p = 0; + unget(c); + lmode = SLIST; + break; + + case S_SBTL: + p = stb; + if ((c = getnb()) != 0) { + do { + if (p < &stb[NSBTL-1]) + *p++ = c; + } while ((c = get()) != 0); + } + *p = 0; + unget(c); + lmode = SLIST; + break; + + case S_MODUL: + getst(id, getnb()); // a module can start with a digit + if (pass == 0) { + if (module[0]) { + err('m'); + } else { + strncpy(module, id, NCPS); + } + } + lmode = SLIST; + break; + + case S_OPTSDCC: + p = optsdcc; + if ((c = getnb()) != 0) { + do { + if (p < &optsdcc[NINPUT-1]) + *p++ = c; + } while ((c = get()) != 0); + } + *p = 0; + unget(c); + lmode = SLIST; + break; + + case S_GLOBL: + do { + getid(id, -1); + sp = lookup(id); + sp->s_flag |= S_GBL; + } while ((c = getnb()) == ','); + unget(c); + lmode = SLIST; + break; + + case S_DAREA: + getid(id, -1); + uaf = 0; + uf = A_CON|A_REL; + if ((c = getnb()) == '(') { + do { + getid(opt, -1); + mp = mlookup(opt); + if (mp && mp->m_type == S_ATYP) { + ++uaf; + uf |= mp->m_valu; + } else { + err('u'); + } + } while ((c = getnb()) == ','); + if (c != ')') + qerr(); + } else { + unget(c); + } + if ((ap = alookup(id)) != NULL) { + if (uaf && uf != ap->a_flag) + err('m'); + } else { + ap = (struct area *) new (sizeof(struct area)); + ap->a_ap = areap; + ap->a_id = strsto(id); + ap->a_ref = areap->a_ref + 1; + ap->a_size = 0; + ap->a_fuzz = 0; + ap->a_flag = uaf ? uf : (A_CON|A_REL); + areap = ap; + } + newdot(ap); + lmode = SLIST; + break; + + case S_ORG: + if (dot.s_area->a_flag & A_ABS) { + outall(); + laddr = dot.s_addr = absexpr(); + } else { + err('o'); + } + outall(); + lmode = ALIST; + break; + + case S_RADIX: + if (more()) { + switch (getnb()) { + case 'b': + case 'B': + radix = 2; + break; + case '@': + case 'o': + case 'O': + case 'q': + case 'Q': + radix = 8; + break; + case 'd': + case 'D': + radix = 10; + break; + case 'h': + case 'H': + case 'x': + case 'X': + radix = 16; + break; + default: + radix = 10; + qerr(); + break; + } + } else { + radix = 10; + } + lmode = SLIST; + break; + + case S_INCL: + d = getnb(); + p = fn; + while ((c = get()) != d) { + if (p < &fn[FILSPC-1]) { + *p++ = c; + } else { + break; + } + } + *p = 0; + if (++incfil == MAXINC || + (ifp[incfil] = fopen(fn, "r")) == NULL) { + --incfil; + err('i'); + } else { + lop = NLPP; + incline[incfil] = 0; + strcpy(incfn[incfil],fn); + } + lmode = SLIST; + break; + + /* + * If not an assembler directive then go to + * the machine dependent function which handles + * all the assembler mnemonics. + */ + default: + /* if cdb information then generate the line info */ + if (cflag && (pass == 1)) + DefineCDB_Line(); + + /* JLH: if -j, generate a line number symbol */ + if (jflag && (pass == 1)) + { + DefineNoICE_Line(); + } + + + machine(mp); + } + goto loop; } -/*)Function FILE * afile(fn, ft, wf) +/*)Function FILE * afile(fn, ft, wf) * - * char * fn file specification string - * char * ft file type string - * int wf read(0)/write(1) flag + * char * fn file specification string + * char * ft file type string + * int wf read(0)/write(1) flag * - * The function afile() opens a file for reading or writing. - * (1) If the file type specification string ft - * is not NULL then a file specification is - * constructed with the file path\name in fn - * and the extension in ft. - * (2) If the file type specification string ft - * is NULL then the file specification is - * constructed from fn. If fn does not have - * a file type then the default source file - * type dsft is appended to the file specification. + * The function afile() opens a file for reading or writing. + * (1) If the file type specification string ft + * is not NULL then a file specification is + * constructed with the file path\name in fn + * and the extension in ft. + * (2) If the file type specification string ft + * is NULL then the file specification is + * constructed from fn. If fn does not have + * a file type then the default source file + * type dsft is appended to the file specification. * - * afile() returns a file handle for the opened file or aborts - * the assembler on an open error. + * afile() returns a file handle for the opened file or aborts + * the assembler on an open error. * - * local variables: - * int c character value - * FILE * fp filehandle for opened file - * char * p1 pointer to filespec string fn - * char * p2 pointer to filespec string fb - * char * p3 pointer to filetype string ft + * local variables: + * int c character value + * FILE * fp filehandle for opened file + * char * p1 pointer to filespec string fn + * char * p2 pointer to filespec string fb + * char * p3 pointer to filetype string ft * - * global variables: - * char afn[] afile() constructed filespec - * char dsft[] default assembler file type string - * char afn[] constructed file specification string + * global variables: + * char afn[] afile() constructed filespec + * char dsft[] default assembler file type string + * char afn[] constructed file specification string * - * functions called: - * VOID asexit() asmain.c - * FILE * fopen() c_library - * int fprintf() c_library + * functions called: + * VOID asexit() asmain.c + * FILE * fopen() c_library + * int fprintf() c_library * - * side effects: - * File is opened for read or write. + * side effects: + * File is opened for read or write. */ FILE * -afile(fn, ft, wf) -char *fn; -char *ft; -int wf; +afile(char *fn, char *ft, int wf) { - register char *p1, *p2, *p3; - register int c; - FILE *fp; - - p1 = fn; - p2 = afn; - p3 = ft; - while ((c = *p1++) != 0 && c != FSEPX) { - if (p2 < &afn[FILSPC-4]) - *p2++ = c; - } - *p2++ = FSEPX; - if (*p3 == 0) { - if (c == FSEPX) { - p3 = p1; - } else { - p3 = dsft; - } - } - while ((c = *p3++) != 0) { - if (p2 < &afn[FILSPC-1]) - *p2++ = c; - } - *p2++ = 0; - if ((fp = fopen(afn, wf?"w":"r")) == NULL) { - fprintf(stderr, "%s: cannot %s.\n", afn, wf?"create":"open"); - asexit(1); - } - return (fp); + register char *p2, *p3; + register int c; + FILE *fp; + + p2 = afn; + p3 = ft; + + strcpy (afn, fn); + p2 = strrchr (afn, FSEPX); // search last '.' + if (!p2) + p2 = afn + strlen (afn); + if (p2 > &afn[FILSPC-4]) // truncate filename, if it's too long + p2 = &afn[FILSPC-4]; + *p2++ = FSEPX; + + // choose a file-extension + if (*p3 == 0) { // extension supplied? + p3 = strrchr (fn, FSEPX); // no: extension in fn? + if (p3) + ++p3; + else + p3 = dsft; // no: default extension + } + + while ((c = *p3++) != 0) { // strncpy + if (p2 < &afn[FILSPC-1]) + *p2++ = c; + } + *p2++ = 0; + + if ((fp = fopen(afn, wf?"w":"r")) == NULL) { + fprintf(stderr, "%s: cannot %s.\n", afn, wf?"create":"open"); + asexit(1); + } + return (fp); } -/*)Function VOID newdot(nap) +/*)Function VOID newdot(nap) * - * area * nap pointer to the new area structure + * area * nap pointer to the new area structure * - * The function newdot(): - * (1) copies the current values of fuzz and the last - * address into the current area referenced by dot - * (2) loads dot with the pointer to the new area and - * loads the fuzz and last address parameters - * (3) outall() is called to flush any remaining - * bufferred code from the old area to the output + * The function newdot(): + * (1) copies the current values of fuzz and the last + * address into the current area referenced by dot + * (2) loads dot with the pointer to the new area and + * loads the fuzz and last address parameters + * (3) outall() is called to flush any remaining + * bufferred code from the old area to the output * - * local variables: - * area * oap pointer to old area + * local variables: + * area * oap pointer to old area * - * global variables: - * sym dot defined as sym[0] - * addr_t fuzz tracks pass to pass changes in the - * address of symbols caused by - * variable length instruction formats + * global variables: + * sym dot defined as sym[0] + * Addr_T fuzz tracks pass to pass changes in the + * address of symbols caused by + * variable length instruction formats * - * functions called: - * none + * functions called: + * none * - * side effects: - * Current area saved, new area loaded, buffers flushed. + * side effects: + * Current area saved, new area loaded, buffers flushed. */ VOID -newdot(nap) -register struct area *nap; +newdot(struct area *nap) { - register struct area *oap; - - oap = dot.s_area; - oap->a_fuzz = fuzz; - oap->a_size = dot.s_addr; - fuzz = nap->a_fuzz; - dot.s_area = nap; - dot.s_addr = nap->a_size; - outall(); + register struct area *oap; + + oap = dot.s_area; + oap->a_fuzz = fuzz; + oap->a_size = dot.s_addr; + fuzz = nap->a_fuzz; + dot.s_area = nap; + dot.s_addr = nap->a_size; + outall(); } -/*)Function VOID phase(ap, a) +/*)Function VOID phase(ap, a) * - * area * ap pointer to area - * addr_t a address in area + * area * ap pointer to area + * Addr_T a address in area * - * Function phase() compares the area ap and address a - * with the current area dot.s_area and address dot.s_addr - * to determine if the position of the symbol has changed - * between assembler passes. + * Function phase() compares the area ap and address a + * with the current area dot.s_area and address dot.s_addr + * to determine if the position of the symbol has changed + * between assembler passes. * - * local variables: - * none + * local variables: + * none * - * global varaibles: - * sym * dot defined as sym[0] + * global varaibles: + * sym * dot defined as sym[0] * - * functions called: - * none + * functions called: + * none * - * side effects: - * The p error is invoked if the area and/or address - * has changed. + * side effects: + * The p error is invoked if the area and/or address + * has changed. */ VOID -phase(ap, a) -struct area *ap; -addr_t a; +phase(struct area *ap, Addr_T a) { - if (ap != dot.s_area || a != dot.s_addr) - err('p'); + if (ap != dot.s_area || a != dot.s_addr) + err('p'); } char *usetxt[] = { #ifdef SDK - "Usage: [-dqxgalopsf] outfile file1 [file2 file3 ...]", + "Usage: [-dqxjgalopscf] outfile file1 [file2 file3 ...]", #else /* SDK */ - "Usage: [-dqxgalopsf] file1 [file2 file3 ...]", + "Usage: [-dqxjgalopscf] file1 [file2 file3 ...]", #endif /* SDK */ - " d decimal listing", - " q octal listing", - " x hex listing (default)", - " g undefined symbols made global", - " a all user symbols made global", + " d decimal listing", + " q octal listing", + " x hex listing (default)", + " j add line number and debug information to file", /* JLH */ + " g undefined symbols made global", + " a all user symbols made global", #ifdef SDK - " l create list output outfile[LST]", - " o create object output outfile[o]", - " s create symbol output outfile[SYM]", + " l create list output outfile[LST]", + " o create object output outfile[o]", + " s create symbol output outfile[SYM]", #else /* SDK */ - " l create list output file1[LST]", - " o create object output file1[REL]", - " s create symbol output file1[SYM]", + " l create list output file1[LST]", + " o create object output file1[REL]", + " s create symbol output file1[SYM]", #endif /* SDK */ - " p disable listing pagination", - " f flag relocatable references by ` in listing file", - " ff flag relocatable references by mode in listing file", - "", - 0 + " c generate sdcdb debug information", + " p disable listing pagination", + " f flag relocatable references by ` in listing file", + " ff flag relocatable references by mode in listing file", + "", + 0 }; -/*)Function VOID usage() +/*)Function VOID usage() * - * The function usage() outputs to the stderr device the - * assembler name and version and a list of valid assembler options. + * The function usage() outputs to the stderr device the + * assembler name and version and a list of valid assembler options. * - * local variables: - * char ** dp pointer to an array of - * text string pointers. + * local variables: + * char ** dp pointer to an array of + * text string pointers. * - * global variables: - * char cpu[] assembler type string - * char * usetxt[] array of string pointers + * global variables: + * char cpu[] assembler type string + * char * usetxt[] array of string pointers * - * functions called: - * VOID asexit() asmain.c - * int fprintf() c_library + * functions called: + * VOID asexit() asmain.c + * int fprintf() c_library * - * side effects: - * program is terminated + * side effects: + * program is terminated */ VOID -usage() +usage(void) { - register char **dp; + register char **dp; - fprintf(stderr, "\nASxxxx Assembler %s (%s)\n\n", VERSION, cpu); - for (dp = usetxt; *dp; dp++) - fprintf(stderr, "%s\n", *dp); - asexit(1); + fprintf(stderr, "\nASxxxx Assembler %s (%s)\n\n", VERSION, cpu); + for (dp = usetxt; *dp; dp++) + fprintf(stderr, "%s\n", *dp); + asexit(1); }