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 }