scc

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

main.c (2296B)


      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 	extern int nerrors;
     96 	extern jmp_buf recover;
     97 
     98 	addinput(fname);
     99 	cleansecs();
    100 
    101 	endpass = 0;
    102 	setjmp(recover);
    103 	while (!endpass && nextline(&line)) {
    104 		linesym = NULL;
    105 
    106 		if (line.label)
    107 			linesym = deflabel(line.label);
    108 
    109 		if (line.op)
    110 			as(line.op, line.args);
    111 		else if (line.args)
    112 			error("arguments without an opcode");
    113 	}
    114 
    115 	return nerrors == 0;
    116 }
    117 
    118 static void
    119 usage(void)
    120 {
    121 	fputs("usage: as [-o outfile] filename ...\n", stderr);
    122 	exit(1);
    123 }
    124 
    125 int
    126 main(int argc, char *argv[])
    127 {
    128 	char **p;
    129 
    130 	outfile = "a.out";
    131 
    132 	ARGBEGIN {
    133 	case 'o':
    134 		outfile = EARGF(usage());
    135 		break;
    136 	default:
    137 		usage();
    138 	} ARGEND
    139 
    140 	if (argc == 0)
    141 		usage();
    142 
    143 	atexit(cleanup);
    144 	iarch();
    145 	isecs();
    146 
    147 	for (pass = 1; pass <= 2; pass++) {
    148 		for (p = argv; infile = *p; ++p) {
    149 			if (!dopass(infile))
    150 				return EXIT_FAILURE;
    151 		}
    152 		if (pass == 1)
    153 			killtmp();
    154 	}
    155 	writeout(outfile);
    156 	outfile = NULL;
    157 
    158 	return 0;
    159 }