scc

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

main.c (2311B)


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