💾 Archived View for uscoffings.net › retro-computing › systems › TI994a › assemblers › tiasm › usene… captured on 2024-08-18 at 22:08:23.
⬅️ Previous capture (2022-07-16)
-=-=-=-=-=-=-
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site unmvax.UUCP From: lee@unmvax.UUCP Newsgroups: net.sources Subject: TI 99 assembler, the assembler itself Message-ID: <374@unmvax.UUCP> Date: Sun, 22-Jul-84 13:15:47 EDT Article-I.D.: unmvax.374 Posted: Sun Jul 22 13:15:47 1984 Date-Received: Mon, 30-Jul-84 00:18:51 EDT Organization: Univ. of New Mexico, Albuquerque Lines: 2456 To unarchive, remove the first line through and including the dashed line. Then type: % sh <thisfilename> Don't forget to strip off the .signature at the end! ------------------------------------------- : Run this with sh NOT csh! echo extracting Makefile cat << //*FUNKYSTUFF*// > Makefile YACC= yacc -d -v LEX= lex LIBS= -ll CFLAGS= -g -DLEXDEBUG -DYYDEBUG -DDEBUG PR= pr LPR= lpr DESTDIR= /usr/local/bin DESTLIB= /usr/local/lib CSRC= util.c aabort.c hash.c main.c rsrvd.c tiasm.c filutil.c Tild.c adrinf.c \\ tiload.c OBJ= hash.o y.tab.o lex.yy.o util.o main.o rsrvd.o filutil.o aabort.o adrinf.o FRONTEND= tiasm.o LOADO= Tild.o hash.o aabort.o adrinf.o install: all install tiasm \$(DESTDIR) install tiasm1 \$(DESTLIB) install tild \$(DESTDIR) all: tiasm tiasm1 tild tiload tiasm: \$(FRONTEND) cc \$(CFLAGS) \$(LDFLAGS) -o tiasm \$(FRONTEND) tiasm1: \$(OBJ) cc \$(CFLAGS) \$(LDFLAGS) -o tiasm1 \$(OBJ) \$(LIBS) tild: \$(LOADO) cc \$(CFLAGS) \$(LDFLAGS) -o tild \$(LOADO) tiload: tiload.o cc \$(CFLAGS) \$(LDFLAGS) -o tiload tiload.o print: \$(CSRC) lex.lex parse.y TIasm.h opcodes.h mio.h TI.out.h \$(PR) TIasm.h opcodes.h parse.y lex.lex \$(CSRC) \\ mio.h TI.out.h \\ | \$(LPR) clean: @-rm *.o core tiasm y.tab.h y.tab.c lex.yy.c tiasm1 y.output tild \\ tiload y.tab.c: parse.y \$(YACC) parse.y lex.yy.c: lex.lex y.tab.h \$(LEX) lex.lex y.tab.h: y.tab.c \$(OBJ) y.tab.c lex.yy.c: TIasm.h rsrvd.o: opcodes.h //*FUNKYSTUFF*// echo extracting TI.out.h cat << //*FUNKYSTUFF*// > TI.out.h /* Format for an object file and loadable image */ /* Magic numbers */ #define OMAGIC 0x100 /* This is an obj file, not link edited yet */ #define BOBJ 0x80 /* Down loadable binary */ struct format { short f_magic; /* Magic number */ short f_laddr; /* Load address */ short f_saddr; /* Start address */ short f_csiz; /* Size (in bytes) of executable */ }; /* Max size of an identifier */ #define IDENTSIZ 6 struct symbol { char s_symnm[IDENTSIZ]; /* Symbol name */ short s_flags; /* Flags from st_type */ short s_raddr; /* Resolution address */ short s_naddr; /* Addresses to 16-bit patch */ }; //*FUNKYSTUFF*// echo extracting TIasm.h cat << //*FUNKYSTUFF*// > TIasm.h #include "TI.out.h" /* Size of vector for internal symbol table * Not only is this a magic number but it SHOULD be the lower of twin * primes and large enough to make the lists of buckets small. */ #define SYMVECSIZ 1103 /* Maximum number of files that can be assembled */ #define NFILES 50 /* Template for temp file names */ #define TFILNM "/tmp/TiXXXXXX" /* Location of pass1 */ #define PASS1 "/usr/local/lib/tiasm1" #ifdef DEBUG #undef DEBUG #define DEBUG(l,s,a) if (Debug > (l)) fprintf (stderr, (s), (a)) #else DEBUG #define DEBUG(l,s,a) #endif DEBUG #define TRUE 1 #define FALSE 0 typedef short flag; /* Types of entries in the symbol table */ #define TYRSRVD 0x1 #define TYLCLID 0x2 #define TYEXTID 0x4 #define TYRSLVD 0x8 #define TYDIR 0x10 /* A member of the list of addresses referencing an identifier */ struct a_lst { short a_addr; /* address of opnd making ref */ struct a_lst *a_next; /* next member of list */ }; /* A symbol table entry */ struct stab { char st_symnm[IDENTSIZ + 1]; /* Identifier/keyword name */ short st_type; /* Type of this entry */ union st_ent { struct op_info { unsigned short op_cod; /* opcode */ unsigned char op_fmt; /* Format code */ } en_op; struct r_info { struct a_lst *ri_lst; /* List of references */ struct j_lst *ri_jl; /* Jumps having this target */ short ri_addr; /* Resolution address */ } en_rinf; } st_ent; struct stab *st_next; /* Next bucket */ }; #define st_opc st_ent.en_op.op_cod #define st_fmt st_ent.en_op.op_fmt #define en_lst st_ent.en_rinf.ri_lst #define en_addr st_ent.en_rinf.ri_addr #define en_jl st_ent.en_rinf.ri_jl /* A structure to store info about a symbol (absolute address or * pointer to symbol table entry. */ struct symb { short sy_tag; /* Tag */ union { struct stab *sy_stb; short sy_loc; } sy_un; }; #define SYMTAG 0x1 /* Operand is indexed */ #define RELOCATABLE 0x2 /* Relocatable as opposed to absolute */ /* Information about an operand specifier */ struct infop { int t; /* T code */ int r; /* register */ struct symb sy_info; }; #define in_stb sy_info.sy_un.sy_stb #define in_loc sy_info.sy_un.sy_loc #define in_tag sy_info.sy_tag /* A member of the list of addresses and targets necessary to resolve jumps */ struct j_lst { short j_addr; /* Word address for patch */ struct j_lst *j_next; /* Next member in list */ }; #define j_tag j_trgt.sy_tag #define j_loc j_trgt.sy_un.sy_loc #define j_stb j_trgt.sy_un.sy_stb /* Structure for the initialization tables. * op_fmt is for machine type formats 1 through 9 * op_fmt of zero is reserved to this program. * op_code would be the opcode to plug in to the object file providing * it is a valid machine format. */ struct ops { char *op_name; unsigned short op_code; unsigned char op_fmt; }; /* The following is used to reclaim space in the list of forward referencing * jumps. It, obviously, will need to be changed if another storage method * is used. */ #define rmjinf(x) (free((x))) /* Is arg (integer) an odd number */ #define odd(x) ((x) % 2) //*FUNKYSTUFF*// echo extracting mio.h cat << //*FUNKYSTUFF*// > mio.h /* Some absolutely RUDE macros for doing portable (buffered) reads and writes. * The open routine should be a macro but is just too large. * The ideas behind these is that they will look EXACTLY like * the UNIX primitives read, write and open but do their stuff * buffered to keep us from going to the kernel too often. * Close must be a routine as it must return something. */ extern int fread(), fwrite(); #define read(fd,bf,sz) fread((char *)&(bf),1,(sz),Sdvec[(fd)]) #define write(fd,bf,sz) fwrite((char *)&(bf),1,(sz),Sdvec[(fd)]) #define lseek(fd,x,w) fseek(Sdvec[(fd)],(x),(w)) /* Macros to do error checking */ #define xwrite(fd,bf,sz) if(Ferror == FALSE)if(write(fd,bf,sz) != sz)\\ aabort("Write error") #define xseek(fd,x,w) if(Ferror == FALSE)if(lseek((fd),(x),(w)) == -1)\\ aabort("Seek error") /* Is arg (integer) an odd number */ #define odd(x) ((x) % 2) //*FUNKYSTUFF*// echo extracting opcodes.h cat << //*FUNKYSTUFF*// > opcodes.h /* Machine instructions */ #define LI 0x200 /* Load Immediate */ #define AI 0x220 /* Add Immediate */ #define ANDI 0x240 /* AND Immediate */ #define ORI 0x0260 /* OR Immediate */ #define CI 0x0280 /* Compare Immediate */ #define STWP 0x02a0 /* STore Workspace Pointer */ #define STST 0x02c0 /* STore STatus register */ #define LWPI 0x02e0 /* Load Workspace Pointer Immediate */ #define LIMI 0x0300 /* Load Interrupt Mask Immediate */ #define IDLE 0x0340 /* IDLE */ #define RSET 0x0360 /* ReSET arithmetic unit */ #define RTWP 0x0380 /* ReTurn to old Workspace Pointer */ #define CKON 0x03a0 /* user defined */ #define CKOF 0x03c0 /* user defined */ #define LREX 0x03e0 /* Load Register and EXecute */ #define BLWP 0x0400 /* Branch, Load new Workspace Pointer */ #define B 0x0440 /* Branch */ #define X 0x0480 /* eXecute */ #define CLR 0x04c0 /* CLeaR to zeros */ #define NEG 0x0500 /* NEGate to ones */ #define INV 0x0540 /* INVert */ #define INC 0x0580 /* INCrement by one */ #define INCT 0x05c0 /* Increment by Two */ #define DEC 0x0600 /* DECrement by one */ #define DECT 0x0640 /* DECrement by two */ #define BL 0x0680 /* Branch and Link */ #define SWPB 0x06c0 /* SWaP Bytes */ #define SETO 0x0700 /* SET to Ones */ #define ABS 0x0740 /* ABSolute value */ #define SRA 0x0800 /* Shift Right Arithmetic */ #define SRL 0x0900 /* Shift Right Logical */ #define SLA 0x0a00 /* Shift Left Arithmetic */ #define SRC 0x0b00 /* Shift Right Circular */ #define JMP 0x1000 /* unconditional JuMP */ #define JLT 0x1100 /* Jump on Less Than */ #define JLE 0x1200 /* Jump on Less than or Equal */ #define JEQ 0x1300 /* Jump on EQual */ #define JHE 0x1400 /* Jump on High or Equal */ #define JGT 0x1500 /* Jump on Greater Than */ #define JNE 0x1600 /* Jump on Not Equal */ #define JNC 0x1700 /* Jump on No Carry */ #define JOC 0x1800 /* Jump on Overflow/Carry */ #define JNO 0x1900 /* Jump on No Overflow */ #define JL 0x1a00 /* Jump on Low */ #define JH 0x1b00 /* Jump on High */ #define JOP 0x1c00 /* Jump on Odd Parity */ #define SBO 0x1d00 /* Set cru Bits to Ones */ #define SBZ 0x1e00 /* Set cru Bits to Zeros */ #define TB 0x1f00 /* Test cru Bit */ #define COC 0x2000 /* Compare Ones Corresponding */ #define CZC 0x2400 /* Compare Zeros Corresponding */ #define XOR 0x2800 /* eXclusive OR */ #define LDCR 0x3000 /* LoaD CRu */ #define STCR 0x3400 /* STore CRu */ #define MPY 0x3800 /* MultiPlY */ #define DIV 0x3c00 /* DIVide */ #define SZC 0x4000 /* Set Zeros Corresponding (word) */ #define SZCB 0x5000 /* Set Zeros Corresponding (Byte) */ #define S 0x6000 /* Subtract (word) */ #define SB 0x7000 /* Subtract (Byte) */ #define C 0x8000 /* Compare (word) */ #define CB 0x9000 /* Compare (Byte) */ #define A 0xa000 /* Add (word) */ #define AB 0xb000 /* Add (Byte) */ #define MOV 0xc000 /* MOVe (word) */ #define MOVB 0xd000 /* MOVe (Byte) */ #define SOC 0xe000 /* Set Ones Corresponding (word) */ #define SOCB 0xf000 /* Set Ones Corresponding (Byte) */ #define XOP 0x2c00 /* eXtended OPeration */ //*FUNKYSTUFF*// echo extracting Tild.c cat << //*FUNKYSTUFF*// > Tild.c #include "TIasm.h" #include <stdio.h> /* Some globals */ short laddr = 0x200; /* Default load address of bin file */ short saddr = 0x200; /* Default start address */ int Ofd; /* The fildes for the bin file */ short locctr = 0; /* The location counter */ short Debug; main (argc, argv) int argc; char *argv[]; { char *fvec[BUFSIZ]; /* Should be enough */ char *tmp, **avec, *arg; char *outfil = "ti.out"; /* The output file */ int x; int filcnt = 0; /* Number of files to edit */ struct format header; argv[argc] = NULL; avec = &argv[1]; while (*avec != NULL) if (**avec != '-') fvec[filcnt++] = *avec++; else { arg = *avec++; while (*++arg != NULL) switch (*arg) { case 'd': /* Debug */ break; case 's': /* Start address */ if (sscanf (*avec++, "%x", &saddr) != 1) { fprintf (stderr, "Bad start address\\n"); exit (1); } break; case 'l': /* Load adress */ if (sscanf (*avec++, "%x", &laddr) != 1) { fprintf (stderr, "Bad load address\\n"); exit (1); } break; default: fprintf (stderr, "Unknown switch -%c\\n", *arg); } } if ((Ofd = creat(outfil, 0777)) < 0) { fprintf (stderr, "cannot create \\"%s\\", aborting!\\n", outfil); exit (1); } /* First write the execute header */ header.f_magic = BOBJ; header.f_laddr = laddr; header.f_saddr = saddr; header.f_csiz = 0; /* Don't need this */ if (write(Ofd, (char *)&header, sizeof(header)) != sizeof(header)) aabort ("Error writing header"); for (x = 0; x < filcnt; ++x) grabit (fvec[x]); } /* grabit * * Grab the file from the object module and copy it over to the .out. When * done we get the symbol table info out and attempt to make patches. If we * can't we'll save 'em for later. The routine that figures out what to do with * the symbols makes the patches or whatever.... * * RETURNS: * nothing */ grabit (file) char *file; { int ifd; int x; int nbytes, rmnng; struct format header; char buf[BUFSIZ]; if ((ifd = open(file, 0)) < 0) { fprintf (stderr, "Could not open %s\\n", file); exit (1); } /* Read in the header */ mread (ifd, (char *)&header, sizeof(header)); /* Check the magic number and abort if incorrect */ if (header.f_magic != OMAGIC) { switch (header.f_magic) { case BOBJ: /* Already link edited */ fprintf (stderr, "File \\"%s\\" has been link edited!\\n", file); break; default: fprintf (stderr, "What is \\"%s\\" ????\\n", file); break; } exit (1); } /* Copy the code section across (buffered no less) */ for (x = 0; x < header.f_csiz; ) { rmnng = header.f_csiz - x; x += nbytes = rmnng / BUFSIZ > 0 ? BUFSIZ : rmnng; if (read(ifd, buf, nbytes) != nbytes) { /* Arghh!!!!!!! */ fprintf (stderr, "Read error on %s\\n", file); exit (1); } if (write(Ofd, buf, nbytes) != nbytes) { /* Geez, just can't win! */ fprintf (stderr, "Write error\\n"); exit (1); } } /* Ok, we have everything positioned to grab the symbol table info * out. So, what are ya waitin' fer... */ getsymb (ifd); /* Last thing, bump the location counter */ locctr += header.f_csiz; } /* getsymb * * Here we get the symbol table info out of the file and deal with it. If * a given symbol's address is already known we just make the patch. If the * symbol was not defined but is by a particular symbol we patch all the * addresses we have been saving up for just such an occasion. If it is * just a reference then, alas, we save it up for christmas when all the * little symbols come running home. * * RETURNS: * nothing * */ getsymb (ifd) int ifd; { struct a_lst *tmp; struct stab *ent; struct symbol symb; struct stab *lookup(), *insert(), *newent(); struct a_lst *build(); void splice(); void resolve(); extern void mseek(); /* Read in each entry until EOF */ while (read(ifd, &symb, sizeof(symb)) == sizeof(symb)) /* Has the symbol been resolved? */ if (!(symb.s_flags & TYRSLVD)) { /* Ok, do we have it in the symbol table? */ if ((ent = lookup(symb.s_symnm)) == NULL) { /* Do not have to deal with externel * definitions here as it would mean a * reference and not a resolution was declared * externel. Which is, of course, IMPOSSIBLE! * * Ok, let us build it then.. */ ent = newent (symb.s_symnm); strncpy (ent->st_symnm, symb.s_symnm, IDENTSIZ); ent->st_type = symb.s_flags; /* Now, build a linked list of addresses that * need to be patched and attach them to the * symbol table entry. */ ent->en_lst = build (ifd, symb.s_naddr); /* And, finally, enter it */ if (insert(ent) == NULL) aabort ("Symbol table overflow!"); } else { /* Is in symbol table */ tmp = build (ifd, symb.s_naddr); splice (ent->en_lst, tmp); if (ent->st_type & TYEXTID) { /* Ok, resolve them now! */ resolve (ent->en_lst, ent->en_addr); ent->en_lst = NULL; /* Chuck it! */ } } } else { /* Is resolved */ tmp = build (ifd, symb.s_naddr); resolve (tmp, symb.s_raddr + locctr); /* Now then, is it externally declared? */ if (symb.s_flags & TYEXTID) { /* Then we need to enter it into the table */ if ((ent = lookup(symb.s_symnm)) == NULL) { ent = newent(symb.s_symnm); strncpy (ent->st_symnm, symb.s_symnm, IDENTSIZ); if (insert(ent) == NULL) aabort ( "Symbol table overflow!"); } else if (ent->st_type & TYEXTID) { fprintf (stderr, "Symbol %s multiply defined\\n", ent->st_symnm); exit (1); } ent->en_addr = symb.s_raddr + locctr; ent->st_type = symb.s_flags; /* resolve the references we may have picked * up from earlier */ if (ent->en_lst != NULL) resolve (ent->en_lst, ent->en_addr); } } /* Put Ofd back at EOF as those resolves could have left * the file positioned ANYWHERE! */ mseek (Ofd, 0L, 2); } /* mseek * * Seek on a file. Do error checking and abort on same. * * RETURNS: * nothing * */ void mseek (fd, offset, whence) int fd; long offset; int whence; { if (lseek(fd, offset, whence) < 0) aabort ("Seek error"); } /* mread * * Do a read. Check for error. Premature EOF is considered an error. * * RETURNS: * nada * */ mread (fd, buf, nbytes) int fd; char *buf; int nbytes; { if (read(fd, buf, nbytes) == nbytes) return; fprintf (stderr, "Read error\\n"); exit (1); } struct a_lst *build (fd, naddr) int fd; short naddr; { short buf[30]; int x, rmnng, y, nwrds; struct stab fakeit; /* adrinf wants a stab ent */ fakeit.en_lst = NULL; for (x = 0; x < naddr; x += nwrds) { rmnng = naddr - x; nwrds = 30 / rmnng == 0 ? 30 : rmnng; mread (fd, (char *)buf, rmnng * sizeof(short)); for (y = 0; y < nwrds; ++y) /* Add the location counter and offset for header * so we get the addresses right. */ adrinf (&fakeit, buf[y] + locctr + sizeof(struct format)); } return (fakeit.en_lst); } /* splice * * Take the two a_lsts and splice them into one. The second will be added * onto the end of the second. I guess this is really a concatenation, huh? * Oh well, the name is already this, so there! * * RETURNS: * nothing */ void splice (l1, l2) struct a_lst *l1, *l2; { struct a_lst *tmp; for (tmp = l1; tmp->a_next != NULL; tmp = tmp->a_next) ; tmp->a_next = l2; } /* resolve * * resolve a list of references to the given address. * Throw the list away as we go through it. Leaves the fd pointed wherever * it pleases. * * RETURNS: * nothing * * NOTE: May abort on a seek or write error */ void resolve (lst, addr) struct a_lst *lst; short addr; { struct a_lst *tmp; addr += laddr; while (lst) { mseek(Ofd, (long )lst->a_addr, 0); if (write (Ofd, &addr, sizeof(addr)) != sizeof(addr)) aabort ("Write error on resolve"); tmp = lst->a_next; free (lst); lst = tmp; } } //*FUNKYSTUFF*// echo extracting aabort.c cat << //*FUNKYSTUFF*// > aabort.c #include <stdio.h> #include "TIasm.h" extern flag Debug; /* aabort * An error internal to the assembler has been discovered. abort processing. * print a short but cryptic message intended for maintainers. * * Does NOT return */ void aabort (string) char *string; { fflush (stdout); fprintf (stderr, "Internal error: %s\\n", string); fflush (stderr); exit (1); } //*FUNKYSTUFF*// echo extracting adrinf.c cat << //*FUNKYSTUFF*// > adrinf.c #include "TIasm.h" #include <stdio.h> /* adrinf * * Add an address to be relocated in to the list in the symbol table entry * reserved for just such a purpose. * * RETURNS: * nothing * * NOTE: May abort if the malloc fails. */ void adrinf (stab, loc) struct stab *stab; short loc; { struct a_lst *ainfo; extern char *malloc(); if ((ainfo = (struct a_lst *)malloc(sizeof(struct a_lst))) == NULL) aabort ("adrinf: no mem!"); ainfo->a_addr = loc; ainfo->a_next = stab->en_lst; stab->en_lst = ainfo; } //*FUNKYSTUFF*// echo extracting filutil.c cat << //*FUNKYSTUFF*// > filutil.c /* File utilities, open and close */ #include <stdio.h> #include <sys/param.h> /* For mapping purposes */ FILE *Sdvec[NOFILE]; /* xopen * Open a file buffered but make it look like the UNIX "open" sys call. * * returns: * fd for a successful open. * -1 for a failure */ int xopen (file, mode) char *file; int mode; { char *md; int fd; extern FILE *fdopen(); switch (mode) { case 0: /* read */ md = "r"; break; case 1: /* write */ md = "w"; break; case 2: /* read & write */ md = "r+"; break; default: return (-1); } if (file == NULL || (fd = open(file, mode) < 0)) return (-1); if ((Sdvec[fd] = fdopen(fd, md)) == NULL) { close (fd); return (-1); } return (fd); } /* xclose * close a file * * returns: * 0 if succesful * -1 for error */ int xclose (fd) int fd; { if (fd < 0 || fd >= NOFILE) return (-1); if (fclose (Sdvec[fd]) == EOF) return (-1); Sdvec[fd] = NULL; return (0); } /* xcreat * create a file * * returns: * fildes for success * -1 on error */ int xcreat (file, modes) char *file; int modes; { int fd; FILE *fdopen(); if (file == NULL || (fd = creat(file, modes)) < 0) return (-1); if ((Sdvec[fd] = fdopen(fd, "w+")) == NULL) return (-1); return (fd); } //*FUNKYSTUFF*// echo extracting hash.c cat << //*FUNKYSTUFF*// > hash.c #include "TIasm.h" #include <stdio.h> extern int Debug; struct stab *Symtab[SYMVECSIZ]; /* initab * Init the hash table. * * Returns: * Nothing. */ void initab() { register struct stab **tptr; register int x; tptr = Symtab; for (x = 0; x < SYMVECSIZ; ++x) *tptr++ = NULL; } /* hash * return a hash key based on the symbol. */ int hash (symbol) register char *symbol; { register int ac = 0; /* Accumulator */ register int x; for (x = 0; x < IDENTSIZ && *symbol != NULL; ++x) { DEBUG (200, "hash: adding %d to ", (int )*symbol); DEBUG (200, "accumulator which is %d\\n", ac); ac += (int )*symbol++; } DEBUG (200, "hash: returning %d\\n", ac % SYMVECSIZ); return (ac % SYMVECSIZ); } /* lookup * Look up a symbol in the symbol table. * * Returns: * pointer to entry if succesful. * NULL if not found. */ struct stab *lookup(symbol) char *symbol; { struct stab *entry; DEBUG (100, "lookup: symbol is \\"%s\\"\\n", symbol); DEBUG (100, "lookup: hashcode = %d\\n", hash(symbol)); if ((entry = Symtab[hash(symbol)]) == NULL) return (NULL); /* The vector was empty */ do if (strcmp(symbol, entry->st_symnm) == 0) return (entry); while ((entry = entry->st_next) != NULL); return (NULL); /* Doesn't exist */ } /* insert * Insert a symbol table entry into the symbol table. * * Returns: * The entry inserted. * * NOTE: The return here is fairly redundant as this CANNOT fail. But, * should a quadratic hashing scheme ever be implemented the fail here is * possible. So, for the sake of modularity, I include the redundant return. * A fail would be signified by a NULL return. */ struct stab *insert(entry) struct stab *entry; { struct stab *list, *eolist; int key; DEBUG (100, "insert: Inserting \\"%s\\" to vector", entry->st_symnm); DEBUG (100, " %d\\n", hash(entry->st_symnm)); if ((list = Symtab[(key = hash(entry->st_symnm))]) == NULL) { /* vector was empty */ Symtab[key] = entry; return (entry); } /* Find the end of the list */ do { eolist = list; list = list->st_next; } while (list != NULL); /* Do the actual insert */ eolist->st_next = entry; return (entry); } /* newent * This routine creates and initializes to NULL's a symbol table entry. * * Returns: * NULL on error (malloc failed) * pointer to an initialized entry on success */ struct stab *newent() { extern char *calloc(); return ((struct stab *)calloc(1, sizeof(struct stab))); } /* The following routines and global variables are for use when dumping * the symbol table. */ static int vec; /* Which vector we are currently on */ static struct stab *stent; /* Which entry we are on */ /* sstab * * Set up to dump the table. Zero the globals. * * RETURNS: * nothing */ void sstab () { vec = 0; while (vec < SYMVECSIZ && Symtab[vec] == NULL) ++vec; stent = Symtab[vec]; } /* nxtent * * Return the next entry in the table. Does not return reserved words or * directives. * * RETURNS: * A symbol table entry on success * NULL if the table is empty */ struct stab *nxtent () { struct stab *tmp; while (vec < SYMVECSIZ) { while (stent != NULL) { if (!(stent->st_type & TYRSRVD || stent->st_type & TYDIR)) { tmp = stent; stent = stent->st_next; return (tmp); } stent = stent->st_next; } ++vec; stent = Symtab[vec]; } /* Oops, all done */ return (NULL); } //*FUNKYSTUFF*// echo extracting lex.lex cat << //*FUNKYSTUFF*// > lex.lex %{ #include "TIasm.h" #include "y.tab.h" extern int Lincnt; extern int Debug; extern flag Ferror; extern flag Error; extern struct stab *lookup(), *newsym(); extern void aabort(); %} %% \\"[^\\"\\n]* { /* Special operators in string possibly */ if (yytext[yyleng - 1] == '\\\\') yymore(); else { if ((yytext[yyleng++] = input()) == '\\n') unput(yytext[--yyleng]); yytext[yyleng++] = NULL; } DEBUG (11, "Lex finds string \\"%s\\"\\n", yytext); return (STRING); } [\\t ]* /* Eat white space. This goes after the string stuff so * we don't eat white space inside the string. */ ; "\\n" ++Lincnt; [rR][0-9]+ { DEBUG (11, "lex finds register \\"%s\\"\\n", yytext); switch (atoi(&yytext[1])) { case 0: yylval.val = 0; return (REG); /* NOTREACHED */ break; case 1: yylval.val = 1; return (REG); /* NOTREACHED */ break; case 2: yylval.val = 2; return (REG); /* NOTREACHED */ break; case 3: yylval.val = 3; return (REG); /* NOTREACHED */ break; case 4: yylval.val = 4; return (REG); /* NOTREACHED */ break; case 5: yylval.val = 5; return (REG); /* NOTREACHED */ break; case 6: yylval.val = 6; return (REG); /* NOTREACHED */ break; case 7: yylval.val = 7; return (REG); /* NOTREACHED */ break; case 8: yylval.val = 8; return (REG); /* NOTREACHED */ break; case 9: yylval.val = 9; return (REG); /* NOTREACHED */ break; case 10: yylval.val = 10; return (REG); /* NOTREACHED */ break; case 11: yylval.val = 11; return (REG); /* NOTREACHED */ break; case 12: yylval.val = 12; return (REG); /* NOTREACHED */ break; case 13: yylval.val = 13; return (REG); /* NOTREACHED */ break; case 14: yylval.val = 14; return (REG); /* NOTREACHED */ break; case 15: yylval.val = 15; return (REG); /* NOTREACHED */ break; default: /* It isn't a register. Try something else. */ REJECT; break; } }; [+\\-]0[xX][0-9a-fA-F]+ { yylval.val = getnum(yytext); DEBUG (11, "lex: +/- hexnum = %d\\n", yylval.val); if (Error == TRUE) { DEBUG (12, "lex: error for +/- hexnum \\"%s\\"\\n", yytext); return (ERROR); /* Will cause syntax error */ } return (NUMBER); } 0[xX][0-9a-fA-F]+ { yylval.val = getnum(yytext); DEBUG (11, "lex: hexnum = %d\\n", yylval.val); if (Error == TRUE) { DEBUG (12, "lex: error for hexnum \\"%s\\"\\n", yytext); return (ERROR); /* Will cause syntax error */ } return (NUMBER); } [+\\-]0[oO][0-7]+ { yylval.val = getnum(yytext); DEBUG (11, "lex: +/- octnum = %d\\n", yylval.val); if (Error == TRUE) { DEBUG (12, "lex: error for +/- octnum\\"%s\\"\\n", yytext); return (ERROR); /* Will cause syntax error */ } return (NUMBER); } 0[oO][0-7]+ { yylval.val = getnum(yytext); DEBUG (11, "lex: octnum = %d\\n", yylval.val); if (Error == TRUE) { DEBUG (12, "lex: error for octnum \\"%s\\"\\n", yytext); return (ERROR); /* Will cause syntax error */ } return (NUMBER); } [+\\-]0[bB][01]+ { yylval.val = getnum(yytext); DEBUG (11, "lex: +/- binnum = %d\\n", yylval.val); if (Error == TRUE) { DEBUG (12, "lex: error for +/- binnum\\"%s\\"\\n", yytext); return (ERROR); /* Will cause syntax error */ } return (NUMBER); } 0[bB][01]+ { yylval.val = getnum(yytext); DEBUG (11, "lex: binnum = %d\\n", yylval.val); if (Error == TRUE) { DEBUG (12, "lex: error for binnum \\"%s\\"\\n", yytext); return (ERROR); /* Will cause syntax error */ } return (NUMBER); } [+\\-][dD][0-9]+ { yylval.val = getnum(yytext); DEBUG (11, "lex: +/- decnum = %d\\n", yylval.val); if (Error == TRUE) { DEBUG (12, "lex: err for +/- decnum \\"%s\\"\\n", yytext); return (ERROR); /* Will cause syntax error */ } return (NUMBER); } [dD][0-9]+ { yylval.val = getnum(yytext); DEBUG (11, "lex: decnum = %d\\n", yylval.val); if (Error == TRUE) { DEBUG (12, "lex: error for decnum \\"%s\\"\\n", yytext); return (ERROR); /* Will cause syntax error */ } return (NUMBER); } [0-9]+ { yylval.val = getnum(yytext); DEBUG (11, "lex: undcl num = %d\\n", yylval.val); if (Error == TRUE) { DEBUG (12, "lex: error for undcl num\\"%s\\"\\n", yytext); return (ERROR); /* Will cause syntax error */ } return (NUMBER); } [+\\-][0-9]+ { yylval.val = getnum(yytext); DEBUG (11, "lex: +/- undcl num = %d\\n", yylval.val); if (Error == TRUE) { DEBUG (12, "lex: error for +/- undcl \\"%s\\"\\n", yytext); return (ERROR); /* Will cause syntax error */ } return (NUMBER); } ";" { /* Eat comments */ while (input() != '\\n') ; unput ('\\n'); }; "'"."'" { yylval.val = (short )yytext[1]; return (NUMBER); }; [+-]"'"."'" { yylval.val = (short )yytext[2]; if (yytext[0] == '-') /* Make negative in that case */ yylval.val *= -1; return (NUMBER); }; "."[_a-zA-Z][\\-_a-zA-Z0-9]* { struct stab *Entry; DEBUG (11, "lex: directive ===== \\"%s\\"\\n", yytext); if ((Entry = lookup(yytext)) == NULL) { /* No such directive */ DEBUG (12, "lex: No directive \\"%s\\"\\n", yytext); return (ERROR); } return (Entry->st_opc); } [_a-zA-Z][\\-_a-zA-Z0-9]* { extern struct stab *lookup(); if ((yylval.sinfo.pntr = lookup(yytext)) == NULL) { /* Create the symbol table entry for this ident */ yylval.sinfo.pntr = newsym (yytext); yylval.sinfo.pntr->st_type = TYLCLID; yylval.sinfo.enterd = FALSE; DEBUG (11, "lex creates \\"%s\\"\\n", yytext); return (IDENT); } else { if (yylval.sinfo.pntr->st_type & TYRSRVD) { /* This is a reserved word. Return the format */ DEBUG (11, "lex returns RSRVD fmt = %d\\n", yylval.sinfo.pntr->st_fmt); return (yylval.sinfo.pntr->st_fmt); } if (yylval.sinfo.pntr->st_type & TYLCLID || yylval.sinfo.pntr->st_type & TYEXTID) { DEBUG (11, "lex returns LCL or EXTNL IDENT\\n", NULL); yylval.sinfo.enterd = TRUE; return (IDENT); } DEBUG (11, "ERR: stab, name = \\"%s\\"\\n", yylval.sinfo.pntr->st_symnm); DEBUG (11, "ERR: stab, type = 0o%o\\n", yylval.sinfo.pntr->st_type); aabort ("lex: Null stab ent"); } }; \\, { return (','); } \\: { return (':'); } \\( { return ('('); } \\) { return (')'); } \\[ { return ('['); } \\] { return (']'); } \\+ { return ('+'); } { return (ERROR); } %% //*FUNKYSTUFF*// echo extracting main.c cat << //*FUNKYSTUFF*// > main.c #include "TIasm.h" #include <stdio.h> #include "mio.h" /* Globals */ flag Ferror; /* To flag an error in assembly */ int Lincnt = 1; /* To count the lines in the source */ struct stab *Entry; /* Current symbol table entry */ int Debug; /* debug flag */ int Ofd; /* Object file descriptor */ char objtfl[40]; /* Temp file for object */ extern short lcctr; /* The (re)location counter */ main(argc, argv) int argc; char *argv[]; { char *tmp; int x; int fcnt = 0; int fd; char *outfil; struct format header; struct stab *ent; struct symbol symb; struct a_lst *atmp; extern void resrv(); extern yydebug; extern debug; extern struct stab *nxtent(); extern Sdvec[]; argv[argc] = NULL; umask (0111); /* No execute bit set */ /* Parse switches */ for (x = 1; x < argc - 1; ++x) if (*(tmp = argv[x]) != '-') /* Should have been handled by the front end */ aabort ("Non-switch"); else { ++tmp; while (*tmp != NULL) switch (*tmp++) { case 'd': ++x; Debug = atoi(argv[x]); break; case 'o': ++x; outfil = argv[x]; break; default: aabort ("Unrecognized switch\\n"); } } if ((Ofd = xcreat(outfil, 0777)) < 0) aabort ("Cannot create output file"); xwrite (Ofd, header, sizeof(header)); resrv(); Ferror = FALSE; yyparse(); /* Put the header together */ header.f_csiz = lcctr; header.f_magic = OMAGIC; xseek (Ofd, 0L, 0); xwrite (Ofd, header, sizeof(header)); xseek (Ofd, 0L, 2); /* Write out the symbol table info */ sstab(); while ((ent = nxtent()) != NULL) { for (x = 0, atmp = ent->en_lst; atmp != NULL; atmp = atmp->a_next) ++x; if (x == 0) continue; /* if (ent->st_type & TYEXTID) x *= -1;