1#include <errno.h>2#include <ctype.h>3#include <setjmp.h>4#include <stdio.h>5#include <stdlib.h>6#include <string.h>78#include <scc/arg.h>9#include <scc/mach.h>10#include <scc/scc.h>1112#include "as.h"1314char *argv0;15char *outfile = "a.out", *infile;16int endpass;1718static void19cleanup(void)20{21 if (outfile)22 remove(outfile);23}2425static Ins *26decode(char *s)27{28 int c;29 char *p;30 unsigned h, id;31 Ins *ins;3233 for (p = s; c = *p; ++p)34 *p = toupper(c);3536 h = (unsigned short) genhash(s);37 h = (h*K >> S) & M;38 id = hashmap[h];39 if (id == 0)40 return NULL;4142 ins = &instab[id-1];43 if (strcmp(ins->str, s) != 0)44 return NULL;4546 return ins;47}4849static void50translate(char *text, char *xargs)51{52 Ins *ins;53 Op *op, *lim;54 Node **args;5556 ins = decode(text);57 if (!ins) {58 error("invalid instruction '%s'", text);59 return;60 }6162 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}7475static int76dopass(char *fname)77{78 struct line line;79 extern int nerrors;80 extern jmp_buf recover;8182 addinput(fname);83 cleansecs();8485 endpass = 0;86 setjmp(recover);87 while (!endpass && nextline(&line)) {88 linesym = NULL;8990 if (line.label)91 linesym = deflabel(line.label);9293 if (line.op)94 translate(line.op, line.args);95 else if (line.args)96 error("arguments without an opcode");9798 if (linesym)99 linesym->flags |= FDEF;100 }101102 return nerrors == 0;103}104105static void106asm(char *argv[])107{108 char **p;109110 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}119120static void121usage(void)122{123 fputs("usage: as [-o outfile] filename ...\n", stderr);124 exit(1);125}126127int128main(int argc, char *argv[])129{130 ARGBEGIN {131 case 'o':132 outfile = EARGF(usage());133 break;134 default:135 usage();136 } ARGEND137138 if (argc == 0)139 usage();140141 atexit(cleanup);142 iarch();143 ibinfmt();144 asm(argv);145 writeout(outfile);146147 return 0;148}