main.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
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 }