Mercurial > repo
comparison interps/rail/src/main.cpp @ 996:859f9b4339e6
<Gregor> tar xf egobot.tar.xz
author | HackBot |
---|---|
date | Sun, 09 Dec 2012 19:30:08 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
995:6883f5911eb7 | 996:859f9b4339e6 |
---|---|
1 // main.cpp | |
2 | |
3 #include "lib.h" | |
4 #include "Thread.h" | |
5 #include "Board.h" | |
6 #include "interactive.h" | |
7 | |
8 using namespace std; | |
9 | |
10 void parseAllArguments(int argc, char * argv[]); | |
11 void parseArgument(string const & arg); | |
12 bool hasPrefix(string const & subject, string const & prefix); | |
13 void parseInput(map<string, Board> & globals); | |
14 void parseFile(ifstream & file, map<string, Board> & globals); | |
15 void parseField(ifstream & file, list<string> & field, string & line); | |
16 string parseHeader(string const & line); | |
17 | |
18 int main(int argc, char * argv[]) | |
19 { | |
20 int result = 0; | |
21 try | |
22 { | |
23 parseAllArguments(argc, argv); | |
24 map<string, Board> globals; | |
25 parseInput(globals); | |
26 | |
27 Thread program; | |
28 map<string, Board>::iterator mainPos = globals.find("main"); | |
29 if (mainPos != globals.end()) | |
30 { | |
31 program.reset(mainPos->second, &globals); | |
32 } | |
33 else | |
34 { | |
35 throw InternalException("Crash: No 'main' function found"); | |
36 } | |
37 if (args::isBatch) | |
38 { | |
39 program.go(); | |
40 } | |
41 else | |
42 { | |
43 runInteractive(program); | |
44 } | |
45 } | |
46 catch(ArgumentException & error) | |
47 { | |
48 cerr << "Argument Error: " << error.what() << endl; | |
49 cerr << "Usage: " << argv[0] << " [--batch] [--interactive] " << endl | |
50 << " [--input=<file>] [--output=<file>] <sourcefile> " << endl | |
51 << " [<sourcefile> [...]]" << endl << endl; | |
52 | |
53 cerr << "--batch Runs in batch mode. The interpreted program will run" << endl | |
54 << " silently to completion." << endl; | |
55 | |
56 cerr << "--interactive Runs in interactive mode. A step by step readout of the" << endl | |
57 << " interpreted program is displayed with debugging controls." << endl | |
58 << " If the run is interactive, then input and output must both" | |
59 << " be bound to files." << endl; | |
60 | |
61 cerr << "--input=<file> Sets standard input of the interpreted program to <file>." << endl | |
62 << " Default is the outer program's standard input." << endl; | |
63 | |
64 cerr << "--ouput=<file> Sets standard output of the interpreted program to <file>" << endl | |
65 << " Default is the outer program's standard output." << endl; | |
66 | |
67 result = 2; | |
68 } | |
69 catch(std::exception & error) | |
70 { | |
71 cerr << "Internal Error: " << error.what() << endl; | |
72 result = 1; | |
73 } | |
74 return result; | |
75 } | |
76 | |
77 void parseAllArguments(int argc, char * argv[]) | |
78 { | |
79 for (int i = 1; i < argc; ++i) | |
80 { | |
81 parseArgument(argv[i]); | |
82 } | |
83 if (!(args::isBatch) && (args::output == NULL || args::input == NULL)) | |
84 { | |
85 throw ArgumentException("If the run is interactive, then input and output must both be bound to files."); | |
86 } | |
87 else if (args::sourceFiles.empty()) | |
88 { | |
89 throw ArgumentException("No source files to interpret."); | |
90 } | |
91 | |
92 if (args::output == NULL) | |
93 { | |
94 args::output = &cout; | |
95 } | |
96 if (args::input == NULL) | |
97 { | |
98 args::input = &cin; | |
99 } | |
100 } | |
101 | |
102 void parseArgument(string const & arg) | |
103 { | |
104 static const string batchFlag = "--batch"; | |
105 static const string interactiveFlag = "--interactive"; | |
106 static const string inputPrefix = "--input="; | |
107 static const string outputPrefix = "--output="; | |
108 | |
109 static ifstream input; | |
110 static ofstream output; | |
111 if (arg == batchFlag) | |
112 { | |
113 args::isBatch = true; | |
114 } | |
115 else if (arg == interactiveFlag) | |
116 { | |
117 args::isBatch = false; | |
118 } | |
119 else if (hasPrefix(arg, inputPrefix)) | |
120 { | |
121 if (args::input == NULL) | |
122 { | |
123 input.open(arg.substr(inputPrefix.size()).c_str(), ios::in); | |
124 if (!input) | |
125 { | |
126 throw ArgumentException("Failed to open '--input' file: " | |
127 + arg.substr(inputPrefix.size())); | |
128 } | |
129 args::input = &input; | |
130 } | |
131 else | |
132 { | |
133 throw ArgumentException("Only one '--input' file is allowed: " + arg); | |
134 } | |
135 } | |
136 else if (hasPrefix(arg, outputPrefix)) | |
137 { | |
138 if (args::output == NULL) | |
139 { | |
140 output.open(arg.substr(outputPrefix.size()).c_str(), | |
141 ios::out | ios::trunc); | |
142 if (!output) | |
143 { | |
144 throw ArgumentException("Failed to open '--output' file: " | |
145 + arg.substr(outputPrefix.size())); | |
146 } | |
147 args::output = &output; | |
148 } | |
149 else | |
150 { | |
151 throw ArgumentException("Only one '--output' file is allowed: " + arg); | |
152 } | |
153 } | |
154 else | |
155 { | |
156 // This must be a source filename. | |
157 args::sourceFiles.push_back(arg); | |
158 } | |
159 } | |
160 | |
161 bool hasPrefix(string const & subject, string const & prefix) | |
162 { | |
163 return subject.compare(0, prefix.size(), prefix) == 0; | |
164 } | |
165 | |
166 void parseInput(map<string, Board> & globals) | |
167 { | |
168 list<string>::iterator pos = args::sourceFiles.begin(); | |
169 list<string>::iterator limit = args::sourceFiles.end(); | |
170 for (; pos != limit; ++pos) | |
171 { | |
172 ifstream source(pos->c_str(), ios::in); | |
173 if (!source) | |
174 { | |
175 throw ArgumentException("Failed to open source file: " + *pos); | |
176 } | |
177 parseFile(source, globals); | |
178 } | |
179 } | |
180 | |
181 void parseFile(ifstream & file, map<string, Board> & globals) | |
182 { | |
183 list<string> field; | |
184 string line; | |
185 string name; | |
186 parseField(file, field, line); | |
187 while (file) | |
188 { | |
189 field.clear(); | |
190 field.push_back(line); | |
191 name = parseHeader(line); | |
192 parseField(file, field, line); | |
193 if (name != "") | |
194 { | |
195 globals[name].reset(name, field); | |
196 } | |
197 } | |
198 } | |
199 | |
200 void parseField(ifstream & file, list<string> & field, string & line) | |
201 { | |
202 getline(file, line); | |
203 while (file && line[0] != '$') | |
204 { | |
205 field.push_back(line); | |
206 getline(file, line); | |
207 } | |
208 } | |
209 | |
210 string parseHeader(string const & line) | |
211 { | |
212 string result; | |
213 size_t first = line.find('\''); | |
214 if (first != string::npos) | |
215 { | |
216 size_t second = line.find('\'', first + 1); | |
217 if (second != string::npos) | |
218 { | |
219 result = line.substr(first + 1, second - (first + 1)); | |
220 } | |
221 } | |
222 return result; | |
223 } |