scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  1#include <errno.h>
  2#include <ctype.h>
  3#include <setjmp.h>
  4#include <stdio.h>
  5#include <stdlib.h>
  6#include <string.h>
  7
  8#include <scc/arg.h>
  9#include <scc/mach.h>
 10#include <scc/scc.h>
 11
 12#include "as.h"
 13
 14char *argv0;
 15char *outfile = "a.out", *infile;
 16int endpass;
 17
 18static void
 19cleanup(void)
 20{
 21	if (outfile)
 22		remove(outfile);
 23}
 24
 25static Ins *
 26decode(char *s)
 27{
 28	int c;
 29	char *p;
 30	unsigned h, id;
 31	Ins *ins;
 32
 33	for (p = s; c = *p; ++p)
 34		*p = toupper(c);
 35
 36	h = (unsigned short) genhash(s);
 37	h = (h*K >> S) & M;
 38	id = hashmap[h];
 39	if (id == 0)
 40		return NULL;
 41
 42	ins = &instab[id-1];
 43	if (strcmp(ins->str, s) != 0)
 44		return NULL;
 45
 46	return ins;
 47}
 48
 49static void
 50translate(char *text, char *xargs)
 51{
 52	Ins *ins;
 53	Op *op, *lim;
 54	Node **args;
 55
 56	ins = decode(text);
 57	if (!ins) {
 58		error("invalid instruction '%s'", text);
 59		return;
 60	}
 61
 62	args = getargs(xargs);
 63	lim = &optab[ins->end];
 64	for (op = &optab[ins->begin]; op < lim; ++op) {
 65		if (match(op, args))
 66			break;
 67	}
 68	if (op == lim) {
 69		error("invalid operands for '%s'", text);
 70		return;
 71	}
 72	(*op->format)(op, args);
 73}
 74
 75static int
 76dopass(char *fname)
 77{
 78	struct line line;
 79	extern int nerrors;
 80	extern jmp_buf recover;
 81
 82	addinput(fname);
 83	cleansecs();
 84
 85	endpass = 0;
 86	setjmp(recover);
 87	while (!endpass && nextline(&line)) {
 88		linesym = NULL;
 89
 90		if (line.label)
 91			linesym = deflabel(line.label);
 92
 93		if (line.op)
 94			translate(line.op, line.args);
 95		else if (line.args)
 96			error("arguments without an opcode");
 97
 98		if (linesym)
 99			linesym->flags |= FDEF;
100	}
101
102	return nerrors == 0;
103}
104
105static void
106asm(char *argv[])
107{
108	char **p;
109
110	for (pass = 1; pass <= 2; pass++) {
111		for (p = argv; infile = *p; ++p) {
112			if (!dopass(infile))
113				exit(EXIT_FAILURE);
114		}
115		if (pass == 1)
116			killtmp();
117	}
118}
119
120static void
121usage(void)
122{
123	fputs("usage: as [-o outfile] filename ...\n", stderr);
124	exit(1);
125}
126
127int
128main(int argc, char *argv[])
129{
130	ARGBEGIN {
131	case 'o':
132		outfile = EARGF(usage());
133		break;
134	default:
135		usage();
136	} ARGEND
137
138	if (argc == 0)
139		usage();
140
141	atexit(cleanup);
142	iarch();
143	ibinfmt();
144	asm(argv);
145	writeout(outfile);
146
147	return 0;
148}