scc

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

main.c (2355B)


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