mark@unisec.UUCP (05/11/87)
Here's the source to the C-Power (tm) compatible assembler that I promised. This source will compile under C-Power or Unix, depending upon the state of the preprocessor define "UNIX". ----------------- cut here ------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # assm.d1 # assm.d2 # assm.readme # assm0.c # assm1.c # assm2.c # assm3.c # assm4.c # assm5.c # openfile.c # This archive created: Mon May 11 13:46:41 1987 export PATH; PATH=/bin:$PATH if test -f 'assm.d1' then echo shar: will not over-write existing file "'assm.d1'" else cat << \SHAR_EOF > 'assm.d1' /* * 6502 Assembler - Data Definitions * Filename: assm.d1 * */ /* Define UNIX to compile under unix */ #undef UNIX /* Limit Values */ #define HTSIZE 32 /* hash table size */ #define LAST_CH_POS 132 #define NUMOPS 74 #define OPSZ 5 #define SFIELD 23 #define SBOLSZ 12 /* symbol flags */ #define UNDEF 1 /* undefined - may be zero page */ #define DEFZRO 2 /* defined - page zero address */ #define MDEF 3 /* multiply defined */ #define DEFABS 4 /* defined - two byte address */ #define DEFREL 5 /* defined - relocatable */ #define XREF 6 /* external reference */ #define isrel(t) (t==DEFREL) /* operation code flags */ #define CASSM 0x7000 #define PSEUDO 0x6000 #define CLASS1 0x2000 #define CLASS2 0x4000 #define IMM1 0x1000 /* opval + 0x00 2 byte */ #define IMM2 0x0800 /* opval + 0x08 2 byte */ #define ABS 0x0400 /* opval + 0x0C 3 byte */ #define ZER 0x0200 /* opval + 0x04 2 byte */ #define INDX 0x0100 /* opval + 0x00 2 byte */ #define ABSY2 0x0080 /* opval + 0x1C 3 byte */ #define INDY 0x0040 /* opval + 0x10 2 byte */ #define ZERX 0x0020 /* opval + 0x14 2 byte */ #define ABSX 0x0010 /* opval + 0x1C 3 byte */ #define ABSY 0x0008 /* opval + 0x18 3 byte */ #define ACC 0x0004 /* opval + 0x08 1 byte */ #define IND 0x0002 /* opval + 0x2C 3 byte */ #define ZERY 0x0001 /* opval + 0x14 2 byte */ /* pass flags */ #define FIRST_PASS 0 #define LAST_PASS 1 /* Types */ struct symtype { struct symtype *next; char *name; char flag; int value; char xdflag; }; SHAR_EOF fi # end of overwriting check if test -f 'assm.d2' then echo shar: will not over-write existing file "'assm.d2'" else cat << \SHAR_EOF > 'assm.d2' /* * 6502 Assembler - External Definitions * Filename: assm.d2 * */ #ifdef UNIX typedef FILE *FILETYPE; #else typedef int FILETYPE; #endif extern FILETYPE optr; extern FILETYPE iptr; extern char filename[]; /* current filename */ extern int ch; /* current character */ extern char cpos; /* current character position */ extern char dflag; /* debug flag */ extern char listed; /* source line has been listed */ extern unsigned errcnt; /* error counter */ extern unsigned exprmc; /* expression modification code */ extern struct symtype *exprsym; /* expression external reference symbol */ extern char exprtyp; /* expression relocation type flag */ extern char hex[]; /* hexadecimal character buffer */ extern char iflag; /* ignore .nlst flag */ extern int lflag; /* disable listing flag */ extern char cflag; /* list excluded cond assmbly */ extern unsigned loccnt; /* location counter */ extern char fflag; /* formatted listing switch */ extern char oflag; /* object output flag */ extern unsigned opflg; /* operation code flags */ extern char opval; /* operation code value */ extern char pass; /* pass counter */ extern char prlnbuf[]; /* print line buffer */ extern char sflag; /* symbol table output flag */ extern unsigned slnum; /* source line number counter */ extern char symbol[]; /* temporary symbol storage */ extern unsigned value; /* operand field value */ extern unsigned fullvalue; /* operand value before 0-pg truncation */ extern char zpref; /* zero page reference flag */ extern char undef; /* expression contains undef symbol */ extern char casmflg; /* zero to inhibit assembly */ extern struct symtype *lablptr; /* statement label pointer */ extern struct symtype *hash_tbl[];/* pointers to symbol lists */ #define VOID int extern VOID initialize(); #ifdef UNIX extern FILETYPE fileopen(); #endif /* c-power bug: don't declare fileopen() */ extern VOID usage(); extern int readline(); extern VOID include(); extern VOID error(); extern VOID wrapup(); extern VOID stprnt(); extern char nextch(); extern char getch(); extern char skip(); extern char cskip(); extern char tolower (); extern VOID assemble(); extern VOID println(); extern unsigned colsym(); extern unsigned islstrt (); extern struct symtype *stlook(); extern struct symtype *stinstal(); extern int oplook(); extern VOID loadlc(); extern VOID loadv(); extern VOID hexcon(); extern int labldef(); extern VOID class1(); extern VOID class2(); extern VOID class3(); extern VOID pseudo(); extern VOID cassm(); extern char ca_op(); extern char noasm(); extern VOID clearln(); extern unsigned evaluate(); extern unsigned colexpr (); extern unsigned colterm (); extern unsigned colnum(); extern unsigned isabs (); extern VOID addrec(); extern VOID adddef(); extern VOID putoc(); extern VOID putrecs(); extern VOID putname(); extern char *makerec(); extern VOID relchk(); extern VOID put1r(); extern VOID put1(); extern VOID put2(); extern VOID put3(); extern VOID putn(); extern VOID putdseg(); extern VOID halfchk (); extern char *index(); extern VOID quit(); SHAR_EOF fi # end of overwriting check if test -f 'assm.readme' then echo shar: will not over-write existing file "'assm.readme'" else cat << \SHAR_EOF > 'assm.readme' 08/15/85 The C-ASSM assembler is built as follows: 1. There are 9 source elements, named as follows: a. assm.d1 - global #defines b. assm.d2 - external definitions c. assm0.c - global data d. assm1.c - main program e. assm2.c - opcode/symbol routines f. assm3.c - instruction, pseudo-op processors g. assm4.c - expression evaluator h. assm5.c - relocatable object formatter i. openfile.c - filename extensions Compile elements c through i. 2. Link the assembler. This must be done with an intermediate library search due to the number of xrefs contained in the object modules: $ link > assm0.o > assm1.o > assm2.o > ^ > assm3.o > assm4.o > assm5.o > openfile.o > ^ > output to: assm.sh $ 3. Test the assembler by first assembling the general purpose test source, assmtest.a: $ assm -fis assmtest.a >> Examine the listing for errors and correct code generation. There should be no errors. The next program tests the external definition / external reference capabilities: $ assm -fis chrtest1.a chrtest2.a $ link > chrtest1.o > chrtest2.o > output to: chrtest.sh $ chrtest ABCDEFGHIJKLMNOPQRSTUVWXYZ $ The printout of the alphabet is performed by chrtest2, which is called from chrtest1. The string containing the alphabet is defined in chrtest1. Thus, both modules mutually reference each other for symbol resolution. 4. More complete test of relocatablity and external reference capacity: $ cc -fs atest1.a atest2.a $ link > atest1.o > atest2.o output to: atest.sh The program prints: Hello, world! This is an external message Goodbye! 5. The file condtest.a tests the conditional assembly features. assm -f condtest.a Check the listing to see that the proper lines generate code. SHAR_EOF fi # end of overwriting check if test -f 'assm0.c' then echo shar: will not over-write existing file "'assm0.c'" else cat << \SHAR_EOF > 'assm0.c' /* * 6502 Assembler - Code Segment 0 * Filename: assm0.c * */ #include "stdio.h" #include "assm.d1" #ifdef UNIX FILE *iptr, *optr; #else FILE iptr, optr; #endif char filename[20]; /* current filename */ int ch; /* current input character */ char cpos; /* current character position */ char dflag; /* debug flag */ char listed; /* listing line has been printed */ unsigned errcnt; /* error counter */ unsigned exprmc; /* expression modification code */ struct symtype *exprsym; /* expression external reference symbol */ char exprtyp; /* expression type */ char hex[5]; /* hexadecimal character buffer */ char iflag; /* ignore .nlst flag */ int lflag; /* disable listing flag */ char cflag; /* list excluded conditional assmbly */ unsigned loccnt; /* location counter */ char fflag; /* formatted listing switch */ char oflag; /* object output flag */ unsigned opflg; /* operation code flags */ char opval; /* operation code value */ char pass; /* pass counter */ char prlnbuf[LAST_CH_POS+1]; /* print line buffer */ char sflag; /* symbol table output flag */ unsigned slnum; /* source line number counter */ char symbol[SBOLSZ+1];/* temporary symbol storage */ unsigned value; /* operand field value */ unsigned fullvalue; /* operand value before 0-pg truncation */ char zpref; /* zero page reference flag */ char undef; /* expression contains undef symbol */ char casmflg; /* 0 to inhibit assembly*/ struct symtype *lablptr; /* label pointer into symbol table */ struct symtype *hash_tbl[HTSIZE];/* pointers to starting symbols */ /* The opcode mnemonics are stored as an array of fixed length strings */ char *opmnem[NUMOPS] = { ".bss ", ".byte", /* '.' is 46 decimal */ ".dbyt", ".def ", ".dseg", ".else", ".fi ", ".ifeq", ".ifge", ".ifgt", ".ifle", ".iflt", ".ifne", ".list", ".nlst", ".ref ", ".word", "= ", /* '=' is 61 decimal */ "adc ","and ","asl ", "bcc ","bcs ","beq ", "bit ","bmi ","bne ", "bpl ","brk ","bvc ", "bvs ","clc ","cld ", "cli ","clv ","cmp ", "cpx ","cpy ","dec ", "dex ","dey ","eor ", "inc ","inx ","iny ", "jmp ","jsr ","lda ", "ldx ","ldy ","lsr ", "nop ","ora ","pha ", "php ","pla ","plp ", "rol ","ror ","rti ", "rts ","sbc ","sec ", "sed ","sei ","sta ", "stx ","sty ","tax ", "tay ","tsx ","txa ", "txs ","tya " }; /* The opcode definitions consist of 2 word pairs: The first word is the instruction class or legal mode flag word. The second word is the base value of the opcode. */ unsigned optab[2*NUMOPS] = /* nmemonic operation code table */ { /* .bss */ PSEUDO,7, /* .byte */ PSEUDO,0, /* .dbyt */ PSEUDO,6, /* .def */ PSEUDO,8, /* .dseg */ PSEUDO,3, /* .else */ CASSM,1, /* .fi */ CASSM,0, /* .ifeq */ CASSM,4, /* .ifge */ CASSM,5, /* .ifgt */ CASSM,3, /* .ifle */ CASSM,6, /* .iflt */ CASSM,2, /* .ifne */ CASSM,7, /* .list */ PSEUDO,4, /* .nlst */ PSEUDO,5, /* .ref */ PSEUDO,9, /* .word */ PSEUDO,2, /* = */ PSEUDO,1, /* adc */ IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x61, /* and */ IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x21, /* asl */ ABS|ZER|ZERX|ABSX|ACC,0x02, /* bcc */ CLASS2,0x90, /* bcs */ CLASS2,0xb0, /* beq */ CLASS2,0xf0, /* bit */ ABS|ZER,0x20, /* bmi */ CLASS2,0x30, /* bne */ CLASS2,0xd0, /* bpl */ CLASS2,0x10, /* brk */ CLASS1,0x00, /* bvc */ CLASS2,0x50, /* bvs */ CLASS2,0x70, /* clc */ CLASS1,0x18, /* cld */ CLASS1,0xd8, /* cli */ CLASS1,0x58, /* clv */ CLASS1,0xb8, /* cmp */ IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0xc1, /* cpx */ IMM1|ABS|ZER,0xe0, /* cpy */ IMM1|ABS|ZER,0xc0, /* dec */ ABS|ZER|ZERX|ABSX,0xc2, /* dex */ CLASS1,0xca, /* dey */ CLASS1,0x88, /* eor */ IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x41, /* inc */ ABS|ZER|ZERX|ABSX,0xe2, /* inx */ CLASS1,0xe8, /* iny */ CLASS1,0xc8, /* jmp */ ABS|IND,0x40, /* jsr */ ABS,0x14, /* lda */ IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0xa1, /* ldx */ IMM1|ABS|ZER|ABSY2|ZERY,0xa2, /* ldy */ IMM1|ABS|ZER|ABSX|ZERX,0xa0, /* lsr */ ABS|ZER|ZERX|ABSX|ACC,0x42, /* nop */ CLASS1,0xea, /* ora */ IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x01, /* pha */ CLASS1,0x48, /* php */ CLASS1,0x08, /* pla */ CLASS1,0x68, /* plp */ CLASS1,0x28, /* rol */ ABS|ZER|ZERX|ABSX|ACC,0x22, /* ror */ ABS|ZER|ZERX|ABSX|ACC,0x62, /* rti */ CLASS1,0x40, /* rts */ CLASS1,0x60, /* sbc */ IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0xe1, /* sec */ CLASS1,0x38, /* sed */ CLASS1,0xf8, /* sei */ CLASS1,0x78, /* sta */ ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x81, /* stx */ ABS|ZER|ZERY,0x82, /* sty */ ABS|ZER|ZERX,0x80, /* tax */ CLASS1,0xaa, /* tay */ CLASS1,0xa8, /* tsx */ CLASS1,0xba, /* txa */ CLASS1,0x8a, /* txs */ CLASS1,0x9a, /* tya */ CLASS1,0x98 }; SHAR_EOF fi # end of overwriting check if test -f 'assm1.c' then echo shar: will not over-write existing file "'assm1.c'" else cat << \SHAR_EOF > 'assm1.c' /* * 6502 Assembler - Code segment 1 * Filename: assm1.c * History: * 05/09/86 - v 2.1 - removed open and replace (@0:) on object file * 05/21/86 - v 2.1 - object filename was not correctly formed for * multi-file assemblies * 05/21/86 - v 2.1 - allow abort via stop key * 05/22/86 - v 2.1 - sped up readline processing */ #include <stdio.h> #include <strings.h> #include "assm.d1" #include "assm.d2" #define peek(x) *((char *)x) #define poke(x,y) *((char *)x)=y static unsigned including; static FILETYPE sviptr; /* saved input file pointer */ static unsigned svline; static char *progname; /* name of this assembler */ main(argc, argv) unsigned argc; char *argv[]; { char c; unsigned cnt; unsigned i; progname = argv[0]; printf("C/ASSM - version 2.1 - 05/09/86\n"); dflag = 0; iflag = 0; lflag = 0; fflag = 1; /* default formatted listing */ cflag = 1; /* default list excluded cond assembly */ oflag = 1; /* default = create object */ sflag = 0; while (--argc && (*++argv)[0] == '-') { for (i = 1; (c = tolower((*argv)[i])) != '\0'; i++) { if (c == 'd') /* debug flag */ dflag++; else if (c == 'i')/* ignore .nlst flag */ iflag++; else if (c == 'l')/* disable listing flag */ lflag--; else if (c == 'f')/* inhibit formatting listing */ fflag = 0; else if (c == 'c')/* no list excluded conditional assmbly */ cflag = 0; else if (c == 'o')/* object output flag */ oflag = 0; else if (c == 's')/* list symbol table flag */ sflag = 1; else usage(); } } if (!argc) usage(); while ( argc ) { pass = FIRST_PASS; for (i = 0; i < HTSIZE; i++) hash_tbl[i] = NULL; initialize( argc, argv ); while (readline() != EOF) assemble(); wrapup(); pass = LAST_PASS; if (!errcnt) { if (lflag == 0) lflag++; initialize ( argc, argv ); while ( readline() != EOF ) { listed = 0; assemble(); if (!listed) println(); } } wrapup(); stprnt(); printf( "End of assembly, %d errors\n", errcnt); if (dflag) { cnt = 0; for (i = 0; i < HTSIZE; i++) if (!hash_tbl[i]) cnt++; printf( "%d unused hash table pointers out of %d\n", cnt, HTSIZE); } argc--; argv++; } } /* initialize this pass */ VOID initialize (ac, av) unsigned ac; char *av[]; { unsigned lng; char *s,oname[30]; s = *av; lng = strlen(s); /* look for '.a' suffix */ if (pass == FIRST_PASS) printf("%s:\n", s); if (lng <= 2 || strcmp(&s[lng-2],".a")) { printf("Not an assembler source (.a expected).\n"); quit(); } strncpy ( filename, s, lng-2 ); filename[lng-2] = '\0'; /* strncpy doesn't do it?? */ if (pass == LAST_PASS && oflag) { strcpy(oname,filename); strcat(oname,".o"); optr = fileopen(oname, "w"); putoc(); /* initialize object output routines */ } iptr = fileopen(s, "r"); including = 0; errcnt = 0; loccnt = 0; slnum = 0; casmflg = 1; } FILETYPE fileopen(fname,dir) char *fname, *dir; { FILETYPE fd; char err; #ifndef UNIX char scrcmd[41]; /* scratch file command string */ #endif err = 0; #ifdef UNIX if ((fd = fopen(fname,dir))==NULL) #else if (*dir=='w') { strcpy(scrcmd,"s0:"); /* scratch old object */ strcat(scrcmd,fname); open(9,8,15,scrcmd); fclose(9); } if ((fd = openfile(fname,dir))==NULL || (err = ferror())) #endif { printf("Can't open %s", fname); if (err) printf(", error = %d", err); putchar('\n'); quit(); } return fd; } VOID usage() { printf( "Usage: %s [-cdfilos] file.a [file.a ...]\n",progname); quit(); } char field[] = { SFIELD, SFIELD + SBOLSZ, SFIELD + SBOLSZ + 6, SFIELD + SBOLSZ + 15 }; /* See if user wants an abort. This is signalled by depressing the * stop key. */ ckabort() { if (peek(197)==63) exit(); } /* readline reads and formats an input line, returns * -1 at end of file. */ static char inbuf[81]; int readline() { unsigned i; /* pointer into prlnbuf */ unsigned j; /* pointer to current field start */ char cmnt; /* comment line flag */ unsigned spcnt; /* consecutive space counter */ char string; /* ASCII string flag */ unsigned temp1; /* temp used for line number conversion */ /* unsigned endfile; */ /* local eof signal */ /* char *s; */ /* temp string pointer */ do { /* 05/21/86 - Test for user abort */ ckabort(); cpos = SFIELD; temp1 = ++slnum; for (i = 0; i < LAST_CH_POS; i++) prlnbuf[i] = ' '; i = 3; while (temp1) { /* put source line number into prlnbuf */ prlnbuf[i--] = temp1 % 10 + '0'; temp1 /= 10; } if (including) prlnbuf[4] = '#'; i = SFIELD; cmnt = 0; spcnt = 0; string = 0; j = 1; /* endfile = (fgets(inbuf,81,iptr)==0); */ /* s = inbuf; */ /* while (((ch = *s++) != '\n') && ch) { */ /* if (endfile) ch = EOF; */ while ((ch = getc(iptr)) !='\n') { prlnbuf[i++] = ch; if (ch == EOF) { if (including) { prlnbuf[--i] = '\0'; /* erase EOF character */ fclose(iptr); iptr = sviptr; /* restore previous file */ slnum = svline; including--; } else return(EOF); } else if (fflag == 0) ; else if ((ch == ' ') && (string == 0)) { if (spcnt) --i; else if (cmnt == 0) { ++spcnt; if (i < field[j]) i = field[j]; if (++j > 3) { spcnt = 0; ++cmnt; } } } else if ((ch == ';') && (string == 0)) { spcnt = 0; if (i == SFIELD + 1) ++cmnt; else if (prlnbuf[i - 2] != '\'') { ++cmnt; prlnbuf[i-1] = ' '; if (i < field[3]) i = field[3]; prlnbuf[i++] = ';'; } } else { if ((ch == '"') && (cmnt == 0)) string = string ^ 1; spcnt = 0; if (i >= LAST_CH_POS - 1) --i; } } prlnbuf[i] = 0; if (prlnbuf[SFIELD]=='#') include(); } while (prlnbuf[SFIELD]=='#'); return(0); } /* ** Process include statement. ** */ VOID include() { static char *icldstr = "include "; char c,flnm[30]; unsigned i; if (including) { printf("Only one include level supported!\n"); quit(); } i=0; while (nextch()!=' ' && ch==icldstr[i]) i++; if (i!=7) { bad: printf("%s\n",prlnbuf); printf("Bad include syntax\n"); quit(); } skip(); if ( !index("\"<",(c=ch)) ) goto bad; if (pass == LAST_PASS) println(); if (c=='<') c='>'; i=0; while (nextch()!=c && ch) flnm[i++]=ch; flnm[i]='\0'; svline = slnum; slnum = 0; sviptr = iptr; including++; #ifdef UNIX if ((iptr=fileopen(flnm,"r")) == NULL) #else if ((iptr=openfile(flnm,"r")) == NULL || ferror()) #endif { printf("Can't open include: %s\n",flnm); quit(); } } /* ** 08/04/85 - Centralize error strings ** to avoid redundancy and eliminate ** 'pseudo-xrefs' in other objects. */ VOID error(code) unsigned code; { static char *errmsg[] = { /* 0 */ "UNKNOWN ERROR!!!", /* 1 */ "Internal error", /* 2 */ "Invalid operation code", /* 3 */ "A,X,Y are reserved symbols", /* 4 */ "Symbol table overflow", /* 5 */ "Duplicate definition", /* 6 */ "Sync error", /* 7 */ "Branch out of range", /* 8 */ "Missing operand", /* 9 */ "Invalid addressing mode", /* 10 */ "Missing string terminator", /* 11 */ "Value error", /* 12 */ "Undefined symbol", /* 13 */ "Symbol required", /* 14 */ "Multiply defined", /* 15 */ "Relocation error", /* 16 */ "Cond assbly nested too deeply", /* 17 */ "Unbalanced parentheses", /* 18 */ "Divide by zero", /* 19 */ "Hi/Lo operator must be first", /* 20 */ "Invalid operand field", /* 21 */ "Out of memory", /* 22 */ ".fi without .if", /* 23 */ "Label required", /* 24 */ "Label not allowed" }; printf("%s\n",prlnbuf); listed = 1; /* Output a position marker */ printf ("%*s!\n", cpos, ""); if (code<1 || code>24) code = 0; printf("%2d %s\n\n", code, errmsg[code]); errcnt++; } /* * wrapup() closes the source, * outputs remaining object data and * closes the object file. */ VOID wrapup() { fclose(iptr); if (pass == LAST_PASS && oflag && !errcnt) { putrecs(0); /* relocation data */ putrecs(1); /* external identifiers */ putrecs(2); /* external references */ putrecs(3); /* data blocks */ fclose(optr); } return; } /* symbol table print */ VOID stprnt() { static char symtp[] = { /* ?????? */ '?', /* UNDEF */ 'U', /* DEFZRO */ 'Z', /* MDEF */ 'M', /* DEFABS */ 'A', /* DEFREL */ 'R', /* XREF */ 'X' }; char i,j; struct symtype *ptr, *nxtptr; if (sflag) printf("\nSYMBOL TABLE:\n"); j = 1; for (i=0; i<HTSIZE; i++) { for (ptr = hash_tbl[i]; ptr ; ptr=nxtptr) { if (sflag) { printf("%-*s%04x %c", SBOLSZ, ptr->name,ptr->value, symtp[ptr->flag]); if (ptr->xdflag) putchar('D'); else putchar(' '); if (j ^= 1) putchar('\n'); else putchar(' '); } nxtptr = ptr->next; free(ptr->name); free(ptr); } } if (sflag && !j) putchar('\n'); } SHAR_EOF fi # end of overwriting check if test -f 'assm2.c' then echo shar: will not over-write existing file "'assm2.c'" else cat << \SHAR_EOF > 'assm2.c' /* * 6502 Assembler - Code Segment 2 * Filename: assm2.c * */ #include <stdio.h> #include <strings.h> #include "assm.d1" #include "assm.d2" extern char *opmnem[]; extern unsigned optab[]; struct symtype *stlook(); struct symtype *stinstal(); static unsigned symlen; /* Advance line pointer to next character and store character in 'ch' */ char nextch() { return((ch = prlnbuf[++cpos])); } /* Insure we have the current character */ char getch() { return((ch = prlnbuf[cpos])); } /* Unconditional skip to next non-blank */ char skip() { while (nextch()==' '); return (ch); } /* Conditional skip to next non-blank */ char cskip() { if (ch==' ') skip(); return (ch); } char tolower ( c ) char c; { return (c>='A' && c<='Z'? c+'a'-'A': c); } /* translate source line to machine language */ VOID assemble() { int flg; cpos = SFIELD; /* set starting position */ getch(); /* get starting character */ if ((ch == ';') || (ch == 0)) return; lablptr = NULL; if ( colsym() ) lablptr = stlook(); cskip(); if ((flg = oplook()) >= 0 && opflg == CASSM) { cassm(); return; } if (noasm()) { listed |= !cflag; return; } if (flg < 0) { labldef(loccnt,DEFREL); if (flg == -1) error(2); /* invalid opcode */ if ((flg == -2) && (pass == LAST_PASS)) if (lablptr) loadlc(loccnt, 1); return; } if (opflg == PSEUDO) pseudo(); else { labldef(loccnt,DEFREL); if (opflg == CLASS1) class1(); else if (opflg == CLASS2) class2(); else class3(); } return; } /* printline prints the contents of prlnbuf */ VOID println() { if (lflag > 0) printf("%s\n", prlnbuf); } /* colsym() collects a symbol from prlnbuf into symbol[], * leaves prlnbuf pointer at first invalid symbol character, * returns * symbol length, or * 0 => no symbol collected */ unsigned colsym() { unsigned i,valid; valid = 1; i = 0; while (valid) { if ( islstrt() ); else if (i >= 1 && index("0123456789$",ch)); else valid = 0; if (valid) { if (i < SBOLSZ ) symbol[i++] = ch; nextch(); } } if (i == 1 && index("AaXxYy", *symbol)) { error(3); /* reserved symbol */ i = 0; } symbol[i] = 0; return(i); } unsigned islstrt () { char c; c = tolower( ch ); return (index("_.abcdefghijklmnopqrstuvwxyz", c)); } /* symbol table lookup * if found, return pointer to symbol * else, install symbol as undefined, and return pointer */ struct symtype *stlook() { char *sym; struct symtype *ptr; int hashv; hashv = 0; for (sym=symbol; *sym ; sym++) hashv += *sym; symlen = sym - symbol; hashv %= HTSIZE; for (ptr=hash_tbl[hashv]; ptr ; ptr = ptr->next) { if (!strcmp(symbol,ptr->name)) return(ptr); } return(stinstal(hashv)); } /* install symbol */ struct symtype *stinstal(hv) int hv; { struct symtype *newsym; newsym = (struct symtype *) makerec(sizeof(struct symtype)); newsym->flag = UNDEF; newsym->xdflag = 0; newsym->name = (char *) makerec(symlen+1); strcpy(newsym->name,symbol); newsym->value = 0; newsym->next = hash_tbl[hv]; hash_tbl[hv] = newsym; /* put at head of list */ return(newsym); } /* operation code table lookup * returns: * index in 'opmnem' of symbol, if valid * -1 if invalid * -2 if no opcode collected */ int oplook() { unsigned c,i; unsigned j; int k; char temp[OPSZ+1]; for (i=0;i<OPSZ;i++) temp[i] = ' '; i = 0; j = 0; while( ch && !index(" ;", ch) ) { c = tolower(ch); if ( index(".=abcdefghijklmnopqrstuvwxyz", c) ) temp[j] = c; else return(-1); if (++j > OPSZ) /* too long? */ return(-1); if (c == '=') break; nextch(); } if (j==0) return(-2); /* no opcode field */ /* use variables as follows: * i = mnemonic table index * j = 2 * i for optab index * k = compare designator */ temp[OPSZ] = '\0'; /* terminate with null */ /* Do this quick and dirty for now... */ for (i=0;i<NUMOPS;i++) { if (!(k=strcmp(temp,opmnem[i]))) { j = i << 1 ; /* fast multiply x 2 */ opflg = optab[j]; opval = optab[++j]; return(i); } if (k<0) return(-1); /* beyond? */ } return(-1); } /* load 16 bit value in printable form into prlnbuf */ VOID loadlc(val, f) unsigned val,f; { char i; char *p1, *p2; static char pos[] = {6, 13, 18}; i = pos[ f ]; hexcon(4, val); for (p1 = &prlnbuf[i],p2=hex; p2<hex+4; ) *p1++ = *p2++; } /* load value in hex into prlnbuf[contents[i]] */ VOID loadv(val,f) unsigned val,f; { char i; i = 3*f; hexcon(2, val); prlnbuf[13 + i] = hex[0]; prlnbuf[14 + i] = hex[1]; } /* convert number supplied as argument to hexadecimal in hex[digit-1] (lsd) through hex[0] (msd) */ VOID hexcon(digit, num) unsigned digit,num; { hex[digit] = 0; while (digit) { hex[--digit] = (num & 0x0f) + '0'; if (hex[digit] > '9') hex[digit] += 'A' -'9' - 1; num >>= 4; } } /* assign <value> to label pointed to by lablptr, * checking for valid definition, etc. * called with: * value to be assigned * label type (flag) * returns: * 0 => success * 1 => multiply defined label * 2 => sync error */ VOID labldef(lval,ltyp) unsigned lval,ltyp; { if (lablptr) { if (pass == FIRST_PASS) { if (lablptr->flag == UNDEF ) { lablptr->value = lval; lablptr->flag = ltyp; } else { lablptr->flag = MDEF; lablptr->value = 0; error(5); /* multiply defined */ return; } } else { if (pass == LAST_PASS) { if (lablptr->value != lval) { error(6); return; } else { /* Add XDEF to reloc. info? */ if (lablptr->xdflag) adddef(lablptr); } } } } return; } SHAR_EOF fi # end of overwriting check if test -f 'assm3.c' then echo shar: will not over-write existing file "'assm3.c'" else cat << \SHAR_EOF > 'assm3.c' /* * 6502 Assembler - Code Segment 3 * Filename: assm3.c * */ #include "stdio.h" #include "assm.d1" #include "assm.d2" /* class 1 machine operations processor - 1 byte, no operand field */ VOID class1() { if (pass == LAST_PASS) { loadlc(loccnt, 0); loadv(opval, 0); if (oflag) put1(opval); } loccnt++; } /* class 2 machine operations processor - 2 byte, relative addressing */ VOID class2() { loadlc(loccnt, 0); loadv(opval, 0); skip(); if (pass != LAST_PASS || evaluate()) { loccnt += 2; return; } loccnt += 2; if (!isrel(exprtyp)) { error(15); return; } if ((int)(value -= loccnt) < -128 || (int) value > 127) { error(7); return; } loadv(value, 1); if (oflag) { exprtyp = NULL; put2(opval,value); } } /* class 3 machine operations processor - various addressing modes */ VOID class3() { unsigned code,flag,i,ztmask; char c; skip(); loadlc(loccnt, 0); switch(ch) { case 0: case ';': error(8); return; case 'A': case 'a': if ( (c = prlnbuf[cpos + 1])==' ' || c==0 ) { flag = ACC; break; } default: switch(ch) { case '#': case '=': flag = IMM1 | IMM2; nextch(); break; case '(': flag = IND | INDX | INDY; nextch(); break; default: flag = ABS | ZER | ZERX | ABSX | ABSY | ABSY2 | ZERY; } if (evaluate()) { if ((flag & IMM1) || (ch == ')' && prlnbuf[cpos+1] == ',' )) loccnt += 2; else loccnt += 3; return; } if (undef) ztmask = ABS | ABSX | ABSY | ABSY2; else if (zpref) { flag &= (ABS | ABSX | ABSY | ABSY2 | IND); ztmask = 0; } else ztmask = ZER | ZERX | ZERY; code = 0; i = 0; while (ch != ' ' && ch != ';' && ch != 0 && i++ < 4) { code *= 8; switch(ch) { case ')': /* ) = 4 */ ++code; case ',': /* , = 3 */ ++code; case 'X': /* X = 2 */ case 'x': ++code; case 'Y': /* Y = 1 */ case 'y': ++code; break; default: flag = 0; } nextch(); } switch(code) { case 0: /* no termination characters */ flag &= (ABS | ZER | IMM1 | IMM2); break; case 4: /* termination = ) */ flag &= IND; break; case 25: /* termination = ,Y */ flag &= (ABSY | ABSY2 | ZERY); break; case 26: /* termination = ,X */ flag &= (ABSX | ZERX); break; case 212: /* termination = ,X) */ flag &= INDX; break; case 281: /* termination = ),Y */ flag &= INDY; break; default: flag = 0; } } if ((opflg &= flag) == 0) { loccnt += 3; error(9); return; } if ((opflg & ztmask) ) opflg &= ztmask; switch(opflg) { case ACC: /* single byte - class 3 */ loadv(opval + 8, 0); if (pass == LAST_PASS) put1(opval + 8); loccnt++; return; case ZERX: case ZERY: /* double byte - class 3 */ opval += 4; case INDY: opval += 8; case IMM2: opval += 4; case ZER: opval += 4; case INDX: case IMM1: loadv(opval, 0); loadv(value, 1); if (pass == LAST_PASS) put2(opval,value); loccnt += 2; return; case IND: /* triple byte - class 3 */ opval += 16; case ABSX: case ABSY2: opval += 4; case ABSY: opval += 12; case ABS: opval += 12; loadv(opval, 0); loadv(value, 1); loadv(value >> 8, 2); if (pass == LAST_PASS) put3(opval,value); loccnt += 3; return; default: error(9); loccnt += 3; return; } } /* pseudo operations processor */ VOID pseudo() { unsigned count,tvalue; switch(opval) { case 0: /* .byte pseudo */ labldef(loccnt,DEFREL); loadlc(loccnt, 0); count = 0; do { skip(); if (ch == '"') { while ((ch=nextch()) != '"') { if ((tvalue=ch) == 0) { error(10); return; } if (tvalue == '\\') { if ((tvalue=nextch())=='l') tvalue = '\014'; /* form feed */ else if (tvalue=='n') tvalue = '\n'; } loccnt++; if (pass == LAST_PASS) { put1(tvalue); loadv(tvalue, count); if (++count >= 3) { println(); clearln(); count = 0; loadlc(loccnt, 0); } } } nextch(); } else { evaluate(); if (value > 0xff) { error(11); value = 0; } loccnt++; if (pass == LAST_PASS) { put1r(value); loadv(value, count); if (++count >= 3) { println(); clearln(); count = 0; loadlc(loccnt, 0); } } } } while (ch == ','); listed = (count == 0); return; case 1: /* = pseudo */ if (!lablptr) { error(23); return; } skip(); /* oplook leaves '=' current */ if (evaluate()) return; if ( !isrel(exprtyp) && !isabs(exprtyp) ) error(15); labldef(value,exprtyp); if (pass == LAST_PASS) loadlc(value, 1); return; case 2: /* .word pseudo */ labldef(loccnt,DEFREL); do { loadlc(loccnt, 0); skip(); listed = evaluate(); if (pass == LAST_PASS) { loadv(value, 0); loadv(value>>8, 1); put2(value,value>>8); if (!listed) println(); clearln(); } loccnt += 2; } while (ch == ','); listed = 1; return; case 3: /* .dseg pseudo */ if (!lablptr) { error( 23 ); return; } if (pass == FIRST_PASS) { if (lablptr->flag != UNDEF) { error(14); /* multiply defined */ return; } labldef ( 0, XREF ); } else { if ( evaluate() ) return; loadlc ( value, 1 ); putdseg ( value ); } return; case 4: /* .list pseudo */ case 5: /* .nlst pseudo */ if (lablptr) { error(24); return; } if (lflag >= 0) lflag = (opval==4? 1: iflag); return; case 6: /* .dbyt pseudo */ labldef(loccnt,DEFREL); loadlc(loccnt, 0); do { skip(); listed = evaluate(); loccnt += 2; if (pass == LAST_PASS) { loadv(value>>8, 0); loadv(value, 1); put1r(value>>8); put1r(value); if (!listed) println(); loadlc(loccnt, 0); } clearln(); } while (ch == ','); listed = 1; return; case 7: /* .bss */ labldef(loccnt,DEFREL); loadlc(loccnt, 0); if (evaluate()) return; if (undef) { error(12); return; } if ( !isabs ( exprtyp ) ) { error(15); return; } if ( value & 0x8000 ) /* negative? */ { error(11); return; } loadlc(value, 1); if (pass == LAST_PASS) { putn ( value ); } loccnt += value; return; case 8: /* .def */ case 9: /* .ref */ if (lablptr) { error(24); return; } do { skip(); if (!colsym()) { error(13); return; } lablptr = stlook(); /* define label */ if (opval==8) { if (pass == FIRST_PASS) lablptr->xdflag = 1; } else { if (lablptr->flag != UNDEF && lablptr->flag != XREF) error(15); else { lablptr->flag = XREF; lablptr->xdflag = 0; } } } while (ch == ','); return; } } VOID cassm() { unsigned tval; if (lablptr) error(24); if (opval == 0) /* .fi */ { if (casmflg == 1) error(22); /* .fi without .if */ else casmflg >>= 1; return; } else if (opval == 1) /* .else */ { casmflg = casmflg ^ 1; return; } casmflg <<= 1; casmflg |= 1; if (noasm()) return; if (ca_op(1)) return; tval = value; if (ch != ',') { error(8); return; } nextch(); if (ca_op(2)) return; casmflg &= 0xfffe; if (casmflg & 0x80) { error(16); quit(); } switch (opval) { case 2: /* .iflt */ casmflg |= (tval < value); break; case 3: /* .ifgt */ casmflg |= (tval > value); break; case 4: /* .ifeq */ casmflg |= (tval == value); break; case 5: /* .ifge */ casmflg |= (tval >= value); break; case 6: /* .ifle */ casmflg |= (tval <= value); break; case 7: /* .ifne */ casmflg |= (tval != value); break; } } /* evaluate operand #f for cond asm */ char ca_op( f ) char f; { if (evaluate()) return 1; if (undef) { error(12); return 1; } loadlc ( value, f ); return 0; } /* determine whether to assemble code due to conditional assembly */ char noasm() { return !index("\01\03\07\017\037\077\177", casmflg); } /* Clear contents of print line buffer */ VOID clearln() { unsigned i; for (i = 0; i < SFIELD; i++) prlnbuf[i] = ' '; prlnbuf[i] = 0; } SHAR_EOF fi # end of overwriting check if test -f 'assm4.c' then echo shar: will not over-write existing file "'assm4.c'" else cat << \SHAR_EOF > 'assm4.c' /* * 6502 Assembler - Code Segment 4 * Filename: assm4.c * */ #undef EXPRTRACE #include "stdio.h" #include "assm.d1" #include "assm.d2" static char err; /* evaluate expression */ unsigned evaluate() { if ( colexpr () ) { error ( err ); return err; } if ( undef && pass != FIRST_PASS ) { error ( 12 ); return 12; } return 0; } unsigned colexpr () /* calculate the value and type of an expression. returns 0 if no errors; else error message number. sets globals: value = value of expression exprtyp = type of expression exprsym = ptr to symbol table entry for expressions which consist of a single symbolic entry exprmc = 1 or 2 if high byte or low byte undef = 1 if any term is undefined. in that case, value, exprtyp, exprsym are meaningless. */ { char force; static char terms[] = "\n ,;)"; /* \n will be changed to \0 */ *terms = '\0'; #ifdef EXPRTRACE if (dflag) printf ( ">>colexpr:\n" ); #endif undef = 0; err = 0; exprmc = NULL; /* both bytes of operand assumed */ exprsym = NULL; exprtyp = NULL; value = 0; cskip (); if ( index ("!<>",ch) ) { force = ch; nextch (); } else force = ' '; zpref = 1; if ( colterm (terms) || undef ) { exprtyp = NULL; value = 0; } fullvalue = value; if ( isabs ( exprtyp ) && value < 256 ) zpref = 0; switch (force) { case '!': zpref = 1; break; case '<': zpref = 0; exprmc = 2; value &= 0xff; break; case '>': zpref = 0; exprmc = 1; value >>= 8; break; } #ifdef EXPRTRACE if (dflag) printf ( "<< value=%x(%x),undef=%d,zpref=%d,err=%d,exprmc=%d\n", value, exprtyp, undef, zpref, err, exprmc ); #endif if (pass != FIRST_PASS) halfchk (); return err; } unsigned colterm ( ts ) char *ts; /* ts is a string of valid terminators. If end of line is to be a terminator, \0 must be the first character of the string. */ { unsigned tvalue, evalue, ttype, etype; char op, monop; struct symtype *xsym; evalue = 0; etype = NULL; op = ' '; monop = ' '; while ( 1 ) { /* recognize monadic operators */ if ( index("~-+", ch ) ) { monop = ch; nextch (); } /* recognize a term */ if ( etype == XREF ) { cpos--; getch(); /* include + or - as monadic */ op = '+'; xsym = exprsym; /* save ext sym data */ if (colterm ( ts )) /* evaluate offset */ return err; exprsym = xsym; tvalue = value; ttype = exprtyp; } else if ( index ("0123456789$@%", ch) ) { tvalue = colnum (); ttype = DEFABS; } else if ( islstrt () ) { colsym (); exprsym = stlook(); if (exprsym->flag == UNDEF) { undef = 1; tvalue = 0; ttype = UNDEF; } else { tvalue = exprsym->value; ttype = exprsym->flag; } } else switch ( ch ) { case '*': tvalue = loccnt; ttype = DEFREL; nextch (); break; case '\'': tvalue = nextch (); ttype = DEFABS; if (tvalue) nextch (); else tvalue = ' '; break; case '[': nextch (); if ( colterm ( "]" ) ) return err; if ( ch != ']' ) return (err = 17); tvalue = value; ttype = exprtyp; nextch (); break; default: return ( err = 20 ); } #ifdef EXPRTRACE if (dflag) printf("op=%c,monop=%c,e=%x(%x),t=%x(%x),err=%d\n", op,monop,evalue,etype,tvalue,ttype,err); #endif /* do any monadic operator */ switch ( monop ) { case '+': case ' ': break; case '~': case '-': exprsym = NULL; if ( isabs ( ttype ) ) tvalue = (monop=='-'? -tvalue: ~tvalue); else return ( err = 15 ); break; default: return ( err = 16 ); } monop = ' '; /* Relocatability checks */ if ( etype == XREF ) if ((isabs(ttype) || undef) && op == '+') evalue = tvalue; else return ( err = 15 ); else if ( op != ' ' ) { exprsym = NULL; if ( ttype == XREF ) return ( err = 15 ); } /* Do any dyadic operation */ if ( etype != XREF && !undef) switch(op) { case ' ': evalue = tvalue; etype = ttype; break; case '+': if ( isrel ( etype ) && isrel ( ttype ) ) return ( err = 15 ); evalue += tvalue; if ( isrel ( etype ) || isrel ( ttype ) ) etype = DEFREL; else etype = DEFABS; break; case '-': if ( isabs ( etype ) && isrel ( ttype ) ) return ( err = 15 ); evalue -= tvalue; if ( isrel ( etype ) && isabs ( ttype ) ) etype = DEFREL; else etype = DEFABS; break; default: if ( isrel ( etype ) || isrel (ttype ) ) return ( err = 15 ); switch (op) { case '/': case '%': if (!tvalue) return ( err = 18 ); if (op=='/') evalue /= tvalue; else evalue %= tvalue; break; case '*': evalue *= tvalue; break; case '^': evalue ^= tvalue; break; case '&': evalue &= tvalue; break; case '|': evalue |= tvalue; break; default: return (err = 1); } } /* get next dyadic operator */ if ( index ("+-*/%^&|", ch) ) { op = ch; nextch (); } /* check for end of expression */ else if ( ch == *ts || index ( ts+1, ch ) ) { value = evalue; exprtyp = etype; return err; } else { #ifdef EXPRTRACE if (dflag) printf ( "Illegal operator = %d\n", ch ); #endif return ( err = 20 ); } } } /* collect number operand */ unsigned colnum() { char c; /* local copy of 'ch' */ char mul; unsigned nval; nval = 0; c=ch; /* copy to local */ if (c == '$') mul = 16; else if (c >= '1' && c <= '9') { mul = 10; nval = c - '0'; } else if (c == '@' || c == '0') mul = 8; else if (c == '%') mul = 2; c = nextch(); while ((c = (c - '0')) >= 0) { if (c > 9) { c -= ('a' - '9' - 1); if (c > 15) c -= ('A' - 'a'); if (c > 15) break; if (c < 10) break; } if (c >= mul) break; nval = (nval * mul) + c; c = nextch(); } return(nval); } unsigned isabs ( t ) unsigned t; { return t==DEFABS || t==DEFZRO; } SHAR_EOF fi # end of overwriting check if test -f 'assm5.c' then echo shar: will not over-write existing file "'assm5.c'" else cat << \SHAR_EOF > 'assm5.c' /* * 6502 Assembler Object Ouptput * Filename: assm5.c * */ #undef DEFTRACE #include <stdio.h> #include "assm.d1" #include "assm.d2" /* * The structures describing the various * external and relocatable objects must * all have a link pointer as the first * field, so they may be processed using * a common routine. Struct extrec is * a generic name for this common structure. */ struct extrec /* generic relocation/external record */ { struct extrec *ext_next; }; struct relrec /* relocation record */ { struct relrec *rel_next; unsigned rel_offset; }; struct defrec /* external definition */ { struct defrec *def_next; struct symtype *def_symdef; }; struct refrec /* external reference */ { struct refrec *ref_next; struct symtype *ref_symdef; unsigned modcode; /* 0,1 or 2, plus (increment << 2) */ unsigned ref_offset; }; struct datrec /* data segment */ { struct datrec *dat_next; struct symtype *dat_symdef; unsigned size; }; /* pointers to the ends of four circular * lists: */ #define REL 0 #define DEF 1 #define REF 2 #define DAT 3 static struct extrec *listtail[4]; static unsigned cnt[4]; static unsigned objloc; /************************************** * * Add item to a relocation info list. * */ VOID addrec(p, list) struct extrec *p; char list; { struct extrec *tail; tail = listtail[list]; if ( tail ) { p->ext_next = tail->ext_next; tail->ext_next = p; } else p->ext_next = p; listtail[list] = p; cnt[list]++; #ifdef DEFTRACE if (dflag) printf("Ext/Rel record, type %d\n", list); #endif } /* * Add label definition to relocation info list. * */ VOID adddef(p) struct symtype *p; { struct defrec *rp; if (p->xdflag) { rp = (struct defrec *) makerec ( sizeof(struct defrec) ); rp->def_symdef = p; addrec(rp,DEF); /* add to info list */ } } /* * Output object count and initialize * reference list pointers * */ VOID putoc() { char i; putw(loccnt,optr); /* first word in object file */ for (i=0; i<4; i++) { listtail[i] = NULL; cnt[i] = 0; } objloc = 0; } /* * Output external/relocation entries and * free the records * */ VOID putrecs(list) char list; { struct extrec *ptr, *nxtptr; struct symtype *sp; struct relrec *relptr; struct defrec *defptr; struct refrec *refptr; struct datrec *datptr; putw(cnt[list], optr); if ((ptr = listtail[list])==NULL) return; nxtptr = ptr->next; do { ptr = nxtptr; switch (list) { case REL: relptr = (struct relrec *) ptr; putw(relptr->rel_offset, optr); break; case DEF: defptr = (struct defrec *) ptr; sp = defptr->def_symdef; putname(sp); if (isrel(sp->flag)) fputc(1,optr); else fputc(0,optr); putw(sp->value, optr); break; case REF: refptr = (struct refrec *) ptr; sp = refptr->ref_symdef; putname(sp); putw(refptr->modcode, optr); putw(refptr->ref_offset, optr); break; case DAT: datptr = (struct datrec *) ptr; sp = datptr->dat_symdef; putname(sp); putw(datptr->size, optr); break; } nxtptr = ptr->next; free(ptr); } while ( ptr != listtail[list] ); } /* ** Output symbol name reference. ** */ VOID putname(sp) struct symtype *sp; { char c; char *p; p = sp->name; do { c = *p++; fputc(c,optr); } while (c); } /* ** Allocate size bytes of storage ** Returns: pointer to empty entry. ** */ char *makerec(size) unsigned size; { char *ptr; ptr = malloc(size); if (ptr==NULL) { error(21); quit(); } return (ptr); } /* * Check the current object byte against * 'exprtyp' to determine if it is relocatable, * or makes an external reference. */ VOID relchk(loc) unsigned loc; { struct relrec *relptr; struct refrec *refptr; if (isrel(exprtyp) && !exprmc) { relptr = (struct relrec *) makerec(sizeof(struct relrec)); relptr->rel_offset = loc; addrec ( relptr, REL ); } else if (exprtyp==XREF || (isrel(exprtyp) && exprmc)) { refptr = (struct refrec *) makerec(sizeof(struct refrec)); refptr->modcode = exprmc; refptr->ref_offset = loc; refptr->ref_symdef = exprsym; if (exprsym->flag == XREF) { if ( fullvalue >= 0x2000 && fullvalue < 0xe000 ) error ( 11 ); refptr->modcode |= (fullvalue << 2); } addrec(refptr, REF); } } /* * Put 1 byte value to object file, * including relocation check * */ VOID put1r(v) unsigned v; { if (oflag) { relchk(objloc - 1); put1(v); } } /* * Put 1 byte value to object file * * Note: no relocation check performed */ VOID put1(v) unsigned v; { if (oflag) { fputc(v,optr); } objloc++; } /* * Put 2 byte value to object file * */ VOID put2(v1,v2) unsigned v1,v2; { if (oflag) { fputc(v1,optr); fputc(v2,optr); if (exprmc) relchk(objloc); else relchk(objloc - 1); } objloc += 2; } /* * Put 3 bytes to object file. * First value is opcode, second is * operand. * */ VOID put3(v1,v2) unsigned v1,v2; { if (oflag) { fputc(v1,optr); putw(v2,optr); relchk(objloc); } objloc += 3; } VOID putn(n) int n; /* * put n bytes of zero */ { char buf[256]; int i; objloc += n; if (!oflag) return; for (i=0; i<256; i++) buf[i] = 0; while ( n > 0 ) { if ( n >= 256 ) i = 256; else i = n; n -= i; fwrite ( buf, i, 1, optr ); } } /* create a data segment */ VOID putdseg( len ) unsigned len; { struct datrec *ptr; ptr = (struct datrec *) makerec(sizeof(struct datrec)); ptr->dat_symdef = lablptr; ptr->size = len; addrec(ptr,DAT); } VOID halfchk () /* any reloctable expression used with * a '<' or '>' operation must be made * external, since the linker cannot * relocate half-addresses which are not * external. */ { if ( exprmc ) { if ( exprsym && exprsym->xdflag ) return; if ( isabs ( exprtyp ) || exprtyp==XREF ) return; strcpy ( symbol, ">" ); strncat ( symbol, filename, SBOLSZ-5 ); hexcon ( 4, fullvalue ); strncat ( symbol, hex, 4 ); exprsym = stlook (); if (pass==LAST_PASS && !exprsym->xdflag) { exprsym->flag = exprtyp; exprtyp = XREF; exprsym->value = fullvalue; exprsym->xdflag = 1; if (oflag) adddef ( exprsym ); } } } #ifdef UNIX char *index(s,c) char *s, c; { while (*s) if (c == *s) return s; else s++; return 0; } #endif VOID quit() { #ifdef UNIX exit ( 1 ); #else exit (); #endif } SHAR_EOF fi # end of overwriting check if test -f 'openfile.c' then echo shar: will not over-write existing file "'openfile.c'" else cat << \SHAR_EOF > 'openfile.c' /* home-brew file extensions */ /* author: Mark R. Rinfret */ /* date: 04/19/84 */ /* filename: openfile.c */ #include <stdio.h> #include <strings.h> openfile(name,how) char *name,how; { char *xname; char c; unsigned dvc; xname = name; /* copy pointer */ dvc = 8; /* default is device 8 */ if ((c=*xname) == '#') { xname++; if (((c=*xname) == '8') || ((c=*xname) == '9')) { xname++; dvc = (8 + (c - '8')); if (*xname==':') xname++; else { printf("missing ':' in device specification\n%s\n",xname); return NULL; } } else { printf("illegal device number:\n%s\n",xname); return NULL; } } device(dvc); return (fopen(xname,how)); } SHAR_EOF fi # end of overwriting check # End of shell archive exit 0 -- | Mark R. Rinfret, SofTech, Inc. mark@unisec.usi.com | | Guest of UniSecure Systems, Inc., Newport, RI | | UUCP: {gatech|mirror|cbosgd|uiucdcs|ihnp4}!rayssd!unisec!mark | | work: (401)-849-4174 home: (401)-846-7639 |