-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrunoff.c
154 lines (131 loc) · 3.17 KB
/
runoff.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "data.h"
#include "phases.h"
#include "auxiliary.h"
/* Some code copy pasted from plan9's /sys/include/libc.h
used to handle command line arguments. Modified to compile
on non-plan9 machines */
#define ARGBEGIN for(argv++,argc--;\
argv[0] && argv[0][0]=='-' && argv[0][1];\
argc--, argv++) {\
char *_args, *_argt;\
char _argc;\
_args = &argv[0][1];\
if(_args[0]=='-' && _args[1]==0){\
argc--; argv++; break;\
}\
_argc = 0;\
while(*_args && (_argc = *_args++))\
switch(_argc)
#define ARGEND }
#define EARGF(x) (_argt=_args, _args="",\
(*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0)))
char *filename;
void usage(void);
void verifycode(char *);
char *indent(char *);
void writeFile(char *, char *);
char *readFile(char *);
int
main(int argc, char *argv[])
{
int errors = 0;
AstNode *tree;
char *code;
int ppflag = 0;
int verifyflag = 0;
int indentflag = 0;
int parseonlyflag = 0;
char *outfile = NULL;
ARGBEGIN{
case 'p':
ppflag = 1;
break;
case 'o':
outfile = EARGF(usage());
break;
case 'v':
verifyflag = 1;
break;
case 'i':
indentflag = 1;
break;
case 'P':
parseonlyflag = 1;
break;
default:
usage();
}ARGEND
/* the file name is the only argument left */
if(argc != 1)
usage();
else
filename = argv[0];
tree = parse(filename);
if(tree == NULL)
return -1;
if(parseonlyflag)
return 0;
if(ppflag){
printf("%s\n", prettyprint(tree));
return 0;
}
errors += buildSymbolTable(tree);
if(errors != 0)
return errors;
errors += typeCheck(tree);
if(errors != 0)
return errors;
errors += contextualConstraintsCheck(tree);
if(errors != 0)
return errors;
errors += checkused(tree);
if(errors != 0)
return errors;
/* some code transformations that cannot fail */
removeNestedDecls(tree);
initializeVars(tree);
/* generate the code! */
code = codegen(tree);
if(indentflag)
/* Run indentation helper for output file */
code = indent(code);
if(outfile != NULL)
/* Save output code to file */
writeFile(code, outfile);
else
printf("%s\n", code);
if(verifyflag)
/* Run code checker */
verifycode(code);
return 0;
}
void usage(void){
printf("Usage: runoff [-pivP] [-o outfile] filename\n");
printf("\t-p: prettyprint the code, then exit.\n");
printf("\t-i: run the generated code through the indent command.\n");
printf("\t-v: run arduino --verify on the generated code.\n");
printf("\t-P: stop after parsing.\n");
printf("\t-o outfile: put the generated code in outfile instead of stdout.\n");
exit(EXIT_FAILURE);
}
void verifycode(char *code){
/* wrapper for using arduino c++ to verify output code */
char *tmpdirname = tmpnam(NULL);
char *tmpname = smprintf("%s/code.cpp", tmpdirname);
char *cmd1 = smprintf("mkdir %s", tmpdirname);
char *cmd2 = smprintf("cd %s && arduino --verify %s", tmpdirname, tmpname);
system(cmd1);
writeFile(code, tmpname);
system(cmd2);
}
char *indent(char *code){
/* Wrapper for running indent library */
char *tmpname = tmpnam(NULL);
char *cmd = smprintf("indent %s", tmpname);
writeFile(code, tmpname);
system(cmd);
return readFile(tmpname);
}