DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T a

⟦55bb7dcc0⟧ TextFile

    Length: 10821 (0x2a45)
    Types: TextFile
    Names: »asm.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/asm/asm.c« 

TextFile

#include "asm.h"

main (argc, argv)
	int argc;
	char **argv;
{
	char *t1, *t2;

	srcin = stdin;
	filename[0] = "stdin";
	binout = stdout;
	getargs (argc, argv);
	init ();
	output = fopen ((t1 = mktemp ("/tmp/asm185XXXXXX")), "w+");
	input[0] = srcin;
	if (process ()) reporterr (E_PASS1);
	(void) fclose (input[0]);
	init2 ();
	rewind (output);
	input[0] = output;
	output = fopen ((t2 = mktemp ("/tmp/asm285XXXXXX")), "w+");
	if (process ()) reporterr (E_PASS2);
	(void) fclose (input[0]);
	(void) unlink (t1);
	input[0] = output;
	output = binout;
	rewind (input[0]);
	sort ();
	(void) fclose (input[0]);
	(void) unlink (t2);
	(void) fclose (output);
	if (xref) crossref ();
	exit (errorstat);
}


/*      Current arguments:
		infile  input file name (default stdin)
		-lfile  listing output to file (default no listing),
			(default file is infile.l);
		-ofile  binary output to file (default binary to stdout),
			(default file is infile.o);
		-xfile  cross reference output to listing file (default no xref);
*/
void getargs (argc, argv)
	int argc;
	char **argv;
{
	char *cp, *arg, *lname, *oname;

	while (--argc) {
		arg = *(++argv);
		if (*arg == '-') {
			switch (*(++arg)) {
			case 'l':
				listing ++;
				lname = ++arg;
				break;
			case 'o':
				binary ++;
				oname = ++arg;
				break;
			case 'x':
				xref ++;
				break;
			}
		} else {
			name = arg;
			if ((srcin = fopen (name, "r")) == NULL)
				reporterr (E_INPUT);
			filename[0] = strcpy (malloc ((unsigned) strlen (name) + 1), name);
			if (cp = index (name, '.'))
				*cp = '\0';
		}
	}
	if (binary) {
		if (!*oname) {
			(void) strcat (strcpy (buf, name), ".o");
			oname = buf;
		}
		binout = fopen (oname, "w");
	}
	if (listing || xref) {
		if (!*lname) {
			(void) strcat (strcpy (buf, name), ".l");
			lname = buf;
		}
		list = fopen (lname, "w");
	}
	return;
}


void init ()
{
	symbol *spt;
	int i;

	lc = seghd->lc = 0;
	symtab = (symbol *) malloc ((unsigned) sizeof (symbol) * NSYMS);
	for (i = 0; i < NSYMS; i++)
		symtab->name = (char *) 0;
	for (spt = predef; *(spt->name); spt++)
		insert (spt->name, spt->value, spt->type, spt->segp, NO);
	end_found = 0;
	return;
}


void init2 ()
{
	segmnt *sp;
	Memad acc;

	acc = seghd->lc;
	seghd->lc = 0;
	for (sp = seghd->next; sp; sp = sp->next) {
		acc += sp->lc;
		sp->lc = sp->start = acc - sp->lc;
	}
	curseg = seghd;
	lc = curseg->lc;
	errorstat =
	end_found =
		0;
	return;
}



/*      Gross syntax rules:      <and the rest of us simply obey>
	Input line:     [label] [op[optop] [operands]]
	Comments: Blank lines and anything following ';'
	White space is any combination of blank and/or tab chars.
	Operands & optop cannot contain white space (except within strings)
	    and are separated by commas. There must be the exact number of
	    operands that the instruction expects.
	optop can be anything, and is interpreted by the machine-specific
	    routine "optional". It is distinguished from op by starting
	    with a non-alphanumeric or upper-case character.
	Label must start in col 1 if it exists.
*/
int process ()
{
	char *ipt;
	int i, done;
	static char *zit = "";

	pass ++;
	lineno[0] = 0;
contproc:
	while (fgets (buf, LINEBUFLEN, input[currinput]) != NULL) {
		(void) strcpy (linecopy, buf);
		linecopy[strlen(linecopy)-1] = 0;
		if (pass == 1) fputs (buf, output);
		lineno[currinput]++;
		ipt = buf;
		label = ipt;
		op = opd = optop = zit;
		while (islabel (*ipt)) ipt++;
		if (iseol (*ipt))
			goto shortline;
		*ipt++ = 0;
		while (iswhite (*ipt)) ipt++;
		if (iseol (*ipt)) {
shortline:              if (pass == 2)
				listit (linecopy, lc, dummy, 0);
			continue;
		}
		op = ipt;
		while (isalnum (*ipt)) ipt++;
		if (iseol (*ipt)) {
			*ipt = 0;
			goto parsed;
		}
		if (!iswhite(*ipt) && islower(*ipt))
			(void) strcpy ((optop = malloc (strlen (ipt) + 1)), ipt);
		*ipt++ = 0;
		while (iswhite (*ipt)) ipt++;
		opd = ipt;
		while (*ipt != '\n') ipt++;
		*ipt = 0;
parsed:
		if ((i = opsrch (op, pseudotab, pseudolen)) >= 0) {
			done = (pseudotab[i].action) ();
		} else if ((i = opsrch (op, optab, instrlen)) >= 0) {
			(void) (optab[i].action) (i);
		} else {
			reporterr (E_ILLOP);
			listit (linecopy, lc, dummy, 0);
		}
		if (done) break;
	}
	if (!end_found) {
		do_end();
		reporterr (E_NOEND);
	}
	if (currinput > 0) {
		free (filename[currinput]);
		filename[currinput] = NULL;
		(void) fclose (input[currinput--]);
		goto contproc;
	}
	return (errorstat);
}

int opsrch (op, table, hi)
	char *op;
	opdef table[];
	int hi;
{
	int lo, mid, i;

/*      Binary search - assumes that list extends from optab[0] through
	optab[hi-2] inclusive. The hi and lo indicies always point to
	ruled out table locations plus 1, to keep away from rounding
	problems on the far side of zero. Whenever they come to within 1
	of each other, the jig is up (and gone......)
*/

	lo = 0;
	while (1) {
		mid = (hi + lo) / 2;
		if ((i = strcmp (table[mid - 1].name, op)) == 0)
			return (--mid);
		else if (i > 0)
			hi = mid;
		else
			lo = mid;
		if (hi - lo <= 1) break;
	}
	return (-1);
}


void listit (line, xlc, binbuf, length)
	char *line;
	Memad xlc;
	Word binbuf[];
	int length;
{
	int addit, i;

	addit = 0;
	do {
		listint (line, xlc + addit, &binbuf[addit], length - addit);
		addit += listlen;
		line = (char *)0;
	} while (addit < length);
	return;
}


void listint (line, xlc, binbuf, length)
	char *line;
	Memad xlc;
	Word *binbuf;
	int length;
{
	int i;

	if (listing && liston) {
		(void) fprintf (list, "%4ld %08x: ", lineno[currinput], xlc);
		if (length > listlen) length = listlen;
		for (i = 0; i < length; i++)
			(void) fprintf (list, "%02x ", binbuf[i]);
		for (; i < listlen; i++)
			(void) fprintf (list, "   ");
		/* move up to an 8 byte (tab) boundary */
		for (i = 0; i < (81-3*listlen)%8; i++)
			(void) fprintf (list, " ");
		if (line) (void) fprintf (list, "%s", line);
		(void) fprintf (list, "\n");
	}
	return;
}


/*      Binary output format:

	Intel standard hexadecimal format!!!!

        Output is a series of variable length records consisting of ascii
        characters 0-9, A-F (0x30-0x39, 0x41-0x6). Each character contains
        four bits of significant data; two such characters form a binary
	byte of data, the binary equivalent to the hexadecimal ascii
	characters.

	The data records have the format:

					    /  len covers this \
	+---+---+---+---+---+---+---+---+---+--------//--------+---+---+
	| : |  len  |    address    | 0 | 0 |    data bytes    | cksum |
	+---+---+---+---+---+---+---+---+---+--------//--------+---+---+
	    \             checksum covers this                 /

	Checksum computed such that sum of all bytes except ':' modulo
	the bytelength is 0.

	End Record:

	+---+---+---+---+---+---+---+---+---+---+---+
	| : | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | f | f |
	+---+---+---+---+---+---+---+---+---+---+---+


*/
void putoutbin (binbuf, length)
	Word binbuf[];
	int length;
{
	static Memad address;
	static int count;
	static Word checksum;
	static Word array[BINBUFLEN];
	static Word *curpt = 0;
	static Memad binlc = ~0;
	int i;

	if (binlc != lc) {
		if (curpt != 0) {
			(void) fwrite (":", 1, 1, output);
			putout ((Word) count);
			putout ((Word) (address >> 8));
			putout ((Word) (address & 0xff));
			(void) fwrite ("00", 2, 1, output);
			for (i = 0; i < count; i++)
				putout (array[i]);
			checksum += (count & 0xff) +
				    (address >> 8) +
				    (address & 0xff);
			putout (-checksum);
			if (length == 0) {
				(void) fwrite (":00000001ff", 11, 1, output);
			}
		}
		curpt = array;
		count = 0;
		address = binlc = lc;
		checksum = 0;
	}
	for (i = 0; i < length; i++) {
		*curpt++ = binbuf[i];
		checksum += binbuf[i];
		count++;
		binlc ++;
	}
	if (count > BINBUFLEN - MAXBYTPERINS)
		binlc = 0;
	return;
}

#define hex(x) x+(x<10?'0':'7')

void putout (c)
	Word c;
{
	Word outc[2], t;

	t = c>>4;
	c &= 0xf;
	outc[0] = hex(t);
	outc[1] = hex(c);
	(void) fwrite ((char *)outc, 2, 1, output);
	return;
}


void insert (name, value, type, segment, mult)
	char *name;
	long value;
	opdclass *type;
	segmnt *segment;
	int mult;
{
	int x, y;
	symbol *sp;

	x = y = hash (name);
	while ((sp = &symtab[x])->name != (char *) 0) {
		if (strcmp (sp->name, name) == 0) {
			if (!mult && value != sp->value && pass == 1) {
				reporterr (E_MULT);
				return;
			}
			break;
		}
		if (++x == y) reporterr (E_STOFLO);
		if (x == NSYMS) x = 0;
	}
	sp->name = malloc ((unsigned) strlen (name) + 1);
	(void) strcpy (sp->name, name);
	sp->value = value;
	sp->type = type;
	sp->segp = segment;
	return;
}


int lookup (name)
	char *name;
{
	int x, y;

	x = y = hash (name);
	while (symtab[x].name != (char *) 0) {
		if (strcmp (name, symtab[x].name) == 0)
			return (x);
		x++;
		if (x == y) return (-1);
		if (x == NSYMS) x = 0;
	}
	return (-1);
}


int hash (string)
	char *string;
{
	char *pt;
	int tot;

	tot = 0;
	for (pt = string; *pt; pt++)
		tot += *pt;
	if (NSYMS >= 256)
		tot += (tot << 8);
	return (tot % NSYMS);
}


void reporterr (errcode)
	int errcode;
{
	static char *elist[] = {
		"",
		"aborting at end of pass1",
		"aborting at end of pass2",
		"symbol table overflow",
		"input file error",
		"too many nested includes",
		"include syntax error",
		"illegal expression",
		"undefined symbol",
		"unknown op code",
		"multiply defined symbol",
		"insufficient operands",
		"value too large for field",
		"unsigned value negative",
		"segment violation",
		"opcode suffix syntax",
		"no end statement - simulated",
	};

	if (pass == 1) {
		if (list)
			(void) fprintf (list, "----> Error in file %s, line %d: %s\n", filename[currinput], lineno[currinput], elist[errcode]);
		(void) fprintf (stderr, "----> Error in file %s, line %d: %s\n", filename[currinput], lineno[currinput], elist[errcode]);
	} else {
		if (list)
			(void) fprintf (list, "----> %s: %s\n", filename[currinput], elist[errcode]);
		(void) fprintf (stderr, "----> %s: %s\n", filename[currinput], elist[errcode]);
	}
	(void) fflush (list);
	if (errcode <= A_MAX) {
		(void) fprintf (stderr, "asm: Abort error: %s\n", elist[errcode]);
		exit (1);
	}
	errorstat++;
	return;
}


void sort ()
{
	char c;

	while ((c = getc (input[0])) > 0)
		putc (c, output);
	return;
}


void crossref ()
{
	int i, j, k, gap;
	symbol symtemp;

	(void) fprintf (list, "\n\n\n                     Cross Reference\n\n");
	k = 0;
	for (i = 0; i < NSYMS; i++)
		if (symtab[i].name && *symtab[i].name)
			symtab[k++] = symtab[i];
	for (gap = k / 2; gap > 0; gap /= 2)
		for (i = gap; i < k; i++)
			for (j = i - gap; j >= 0; j -= gap) {
				if (strcmp (symtab[j].name,
						  symtab[j+gap].name) <= 0)
					break;
				symtemp = symtab[j];
				symtab[j] = symtab[j+gap];
				symtab[j+gap] = symtemp;
			}
	for (i = 0; i < k; i++)
		(void) fprintf (list, "    %s: 0x%x\n", symtab[i].name,
							symtab[i].value);
	return;
}