scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

main.c (2060B)


      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 
     14 char *argv0;
     15 char *outfile = "a.out", *infile;
     16 int endpass;
     17 
     18 static void
     19 cleanup(void)
     20 {
     21 	if (outfile)
     22 		remove(outfile);
     23 }
     24 
     25 static Ins *
     26 decode(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 
     49 static void
     50 translate(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 
     75 static int
     76 dopass(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 
    105 static void
    106 asm(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 
    120 static void
    121 usage(void)
    122 {
    123 	fputs("usage: as [-o outfile] filename ...\n", stderr);
    124 	exit(1);
    125 }
    126 
    127 int
    128 main(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 }