💾 Archived View for uscoffings.net › retro-computing › systems › TI994a › assemblers › tiasm › src ›… captured on 2022-06-04 at 01:14:04.
-=-=-=-=-=-=-
#include <stdio.h> #include "TIasm.h" extern flag Debug; flag Error; /* To indicate an error for routines * that can't pass back bad values */ /* getnum * Based on certain format specifiers in the string (which have already * been validated) convert a character representation to a number no larger * than a 16 bit word. Overflow is checked. * * Returns: * 0 on error * the internal representation on success * * Note: * A possible abort. */ short getnum (string) char *string; { flag fminus = FALSE; /* number should be negative */ flag radix = 10; /* radix to interpret number */ short ac; /* An accumulator */ short tmp; /* A temporary */ extern flag Error; void aabort(); void yyeror(); if (*string == '-') { fminus = TRUE; ++string; } else if (*string == '+') ++string; /* Next char is a '0'? Then it is a literal specification */ if (*string == '0' && *(string + 1) != NULL) { ++string; /* Next is the radix of the number */ switch (*string++) { case 'o': case 'O': radix = 8; break; case 'x': case 'X': radix = 16; break; case 'b': case 'B': radix = 2; break; case 'D': case 'd': radix = 10; break; default: /* Number starts with a zero but has * no declerator. Assume octal. */ radix = 8; --string; /* Adjust string */ break; /*NOTREACHED*/ } } /* Ok, now get the number performing radix "conversion" in a portable * (non character dependent) manner. Hey, check for overflow too! */ ac = 0; while (*string != NULL) { ac *= radix; switch (*string++) { case '0': tmp = 0; break; case '1': tmp = 1; break; case '2': tmp = 2; break; case '3': tmp = 3; break; case '4': tmp = 4; break; case '5': tmp = 5; break; case '6': tmp = 6; break; case '7': tmp = 7; break; case '8': tmp = 8; break; case '9': tmp = 9; break; case 'a': case 'A': tmp = 10; break; case 'b': case 'B': tmp = 11; break; case 'c': case 'C': tmp = 12; break; case 'd': case 'D': tmp = 13; break; case 'e': case 'E': tmp = 14; break; case 'f': case 'F': tmp = 15; break; default: /* This CANNOT happen! */ aabort ("getnum2"); /*NOTREACHED*/ break; } /* Magic number is MAXINT for 16 bit word size */ if (tmp > 0xffff - ac ) { yyerror ("literal greater than word size"); Error = TRUE; return (0); } ac += tmp; } /* Negative number? */ if (fminus == TRUE) ac *= -1; return (ac); } /* adjinf * * Add an address that is a jump instruction's target. These lists in the * symbol table entries will hold ONLY forward references to save on * space. * * RETURNS: * nothing * * NOTE: May abort if the malloc fails. */ void adjinf (stab, loc) struct stab *stab; short loc; { struct j_lst *jinfo; extern char *malloc(); if ((jinfo = (struct j_lst *)malloc(sizeof(struct j_lst))) == NULL) aabort ("adjinf: no mem!"); jinfo->j_addr = loc; jinfo->j_next = stab->en_jl; stab->en_jl = jinfo; } /* The translation table for escaped characters */ char ctab[] = { '\a', '\b', '\c', '\d', '\e', '\f', '\g', '\h', '\i', '\j', '\k', '\l', '\m', '\n', '\o', '\p', '\q', '\r', '\s', '\t', '\u', '\v', '\w', '\x', '\y', '\z', 0 }; /* dostr * Interpret a string directives argument. * * RETURNS: * * modified buf arg * new length of string (by reference) * * Note: Error may be set here for an illegal meta-character */ void dostr (buf, leng) char buf[]; int *leng; { char null = NULL; char *tmp, *begin; extern int Ofd; extern FILE *Sdvec[]; tmp = begin = buf; /* Find first quote */ while (*tmp++ != '"') ; /* Now transfer characters to the start of buf and interpret * special characters as we go. */ while (*tmp != '"' && *tmp != NULL) if (*tmp == '\\') { ++tmp; if (*tmp >= 'a' && *tmp <= 'z') *begin++ = ctab[*tmp++ - 'a']; else switch (*tmp) { case '\\': case '"': *begin++ = *tmp++; default: Error = TRUE; } } else { *begin++ = *tmp++; } /* Null terminate */ *begin = NULL; /* Find new length */ *leng = begin - buf; } /* resrv * make the entries in the tables reserved. They may NOT be declared again. * * Returns: * Nothing * * NOTE: * May abort if any errors occur loading the symbol table */ void resrv() { register struct stab *entry; register struct ops *tptr; register char *ctmp; extern struct stab *newent(), *insert(); extern struct ops Optab[]; extern void aabort(), initab(); extern struct ops Dirtab[]; initab(); /* Init the symbol table */ /* First the opcodes as they will be accessed most often. * Use pointers for speed. */ tptr = Optab; while ((ctmp = tptr->op_name) != NULL) { if((entry = newent()) == NULL) aabort ("Symbol table overflow\n"); strcpy(entry->st_symnm, ctmp); entry->st_type = TYRSRVD; entry->st_opc = tptr->op_code; entry->st_fmt = tptr->op_fmt; if (insert (entry) == NULL) aabort ("reserv: Could not insert\n"); ++tptr; /* Get next entry */ } /* Now, the directives */ tptr = Dirtab; while ((ctmp = tptr->op_name) != NULL) { if((entry = newent()) == NULL) aabort ("Symbol table overflow\n"); strcpy(entry->st_symnm, ctmp); entry->st_type = TYDIR; entry->st_opc = tptr->op_code; entry->st_fmt = tptr->op_fmt; if (insert (entry) == NULL) aabort ("rsrv: Could not insert directive"); ++tptr; /* Get next entry */ } } /* newsym * Create and partially initialize a symbol table entry. The entry is * NOT inserted here! st_type is left blank so that the parser may determine * that it is a new entry and do the insert. * * Returns: * NUll on error. * The partially initialized entry on success. */ struct stab *newsym (ident) char *ident; { struct stab *ent; extern struct stab *newent(); if ((ent = newent()) == NULL) return (NULL); strncpy (ent->st_symnm, ident, IDENTSIZ); return (ent); }