💾 Archived View for uscoffings.net › retro-computing › systems › TI994a › assemblers › tiasm › src ›… captured on 2022-06-04 at 01:14:04.

View Raw

More Information

-=-=-=-=-=-=-

#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);
}