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 }