Mercurial > ~dholland > hg > ag > index.cgi
comparison anagram/agcore/operations.cpp @ 0:13d2b8934445
Import AnaGram (near-)release tree into Mercurial.
author | David A. Holland |
---|---|
date | Sat, 22 Dec 2007 17:52:45 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:13d2b8934445 |
---|---|
1 /* | |
2 * AnaGram, A System for Syntax Directed Programming | |
3 * Copyright 1993-2002 Parsifal Software. All Rights Reserved. | |
4 * Copyright 2006 David A. Holland. All Rights Reserved. | |
5 * See the file COPYING for license and usage terms. | |
6 * | |
7 * operations.cpp - central operations | |
8 */ | |
9 | |
10 #ifdef AG_ON_UNIX | |
11 #include <sys/types.h> | |
12 #include <sys/param.h> // for MAXPATHLEN (see below) | |
13 #endif | |
14 | |
15 #ifdef AG_ON_WINDOWS | |
16 #include <windows.h> // for HMODULE and GetModuleFileName | |
17 #endif | |
18 | |
19 #include "port.h" | |
20 | |
21 #ifdef VACLGUI | |
22 //#include <imsgbox.hpp> | |
23 #include "action.h" | |
24 #endif | |
25 | |
26 #include "agdict.h" | |
27 #include "aglib.h" | |
28 #include "agstring.h" | |
29 #include "assert.h" | |
30 #include "bpe3.h" | |
31 #include "bpu.h" | |
32 #include "cf-defs.h" | |
33 #include "checksum.h" | |
34 #include "config.h" | |
35 #include "configparam.h" | |
36 #include "data.h" | |
37 #include "engdef.h" | |
38 #include "error.h" | |
39 #include "file.h" | |
40 #include "ftpar.h" | |
41 #include "keyword.h" | |
42 #include "operations.h" | |
43 #include "p.h" | |
44 #include "q1a.h" | |
45 #include "rproc.h" | |
46 #include "rule.h" | |
47 #include "stacks.h" | |
48 #include "sums-defs.h" | |
49 #include "symbol.h" | |
50 #include "token.h" | |
51 #include "tree.h" | |
52 #include "textfile.h" | |
53 | |
54 //#define INCLUDE_LOGGING | |
55 #include "log.h" | |
56 | |
57 | |
58 /* | |
59 extern int bytesAllocated; | |
60 extern int constructorCalls; | |
61 extern int copyConstructorCalls; | |
62 extern int destructorCalls; | |
63 | |
64 extern int nodesCreated; | |
65 extern int nodesDeleted; | |
66 extern int nodesAllocated; | |
67 extern int nodesFreed; | |
68 | |
69 extern int myallocs; | |
70 extern int myfrees; | |
71 extern int myallocBytes; | |
72 extern int myfreeBytes; | |
73 extern int arrayBytesAllocated; | |
74 extern int arrayBytesFreed; | |
75 extern int arraysAllocated; | |
76 extern int arraysFreed; | |
77 | |
78 extern int newCalls; | |
79 extern int newArrayCalls; | |
80 extern int deleteCalls; | |
81 extern int deleteArrayCalls; | |
82 | |
83 extern int dcsCreated; | |
84 extern int dcsDestroyed; | |
85 extern int sconConstructorCalls; | |
86 extern int sconDestructorCalls; | |
87 */ | |
88 | |
89 | |
90 static unsigned n_config_errors; | |
91 | |
92 // XXX does this really accomplish anything? | |
93 #ifdef VACLGUI | |
94 static AgAction startAction; | |
95 #endif | |
96 | |
97 unsigned char *input_base; | |
98 static AgString my_own_dir; | |
99 | |
100 | |
101 /* first thing that happens; comes from main() */ | |
102 void init(char *argv_0) { | |
103 LOGINIT(); | |
104 LOGSECTION("init"); | |
105 LOGV(argv_0); | |
106 | |
107 #ifdef AG_ON_WINDOWS | |
108 /* Is this necessary or even useful? */ | |
109 char buf[MAX_PATH]; | |
110 //_fullpath(buf, argv_0, MAX_PATH); | |
111 HMODULE module = GetModuleHandle(0); | |
112 GetModuleFileName(module, buf, MAX_PATH); | |
113 LOGV(buf); | |
114 argv_0 = buf; | |
115 #endif | |
116 | |
117 #ifdef AG_ON_UNIX | |
118 // realpath is documented with MAXPATHLEN from sys/param.h, not | |
119 // PATH_MAX from limits.h. | |
120 // | |
121 // I don't think there are systems where these are different, but | |
122 // never underestimate the power of stupidity when people decide | |
123 // to release their very own System-V-derived Buggix. | |
124 // | |
125 //char buf[PATH_MAX]; | |
126 char buf[MAXPATHLEN]; | |
127 if (realpath(argv_0, buf) != NULL) { | |
128 LOGV(buf); | |
129 argv_0 = buf; | |
130 } | |
131 #endif | |
132 | |
133 sum_remember_argv0(argv_0); | |
134 | |
135 AgString myself = argv_0; | |
136 my_own_dir = myself.lastCut(PATH_DELIMITER).leftX(); | |
137 } | |
138 | |
139 void init_parser(void) { | |
140 LOGSECTION("init_parser"); | |
141 no_assertions = 0; | |
142 | |
143 init_stk(); | |
144 init_data(); | |
145 Cast::reset(); | |
146 Symbol::reset(); | |
147 Token::reset(); | |
148 set_work_dir(); | |
149 read_config(my_own_dir); | |
150 ConfigParam::initAll(); | |
151 | |
152 n_config_errors = errorList.size(); //nerrors; | |
153 reset_parser(); | |
154 } | |
155 | |
156 #if 0 /* NOT USED */ | |
157 int netAllocations() { | |
158 return newArrayCalls - deleteArrayCalls | |
159 + newCalls - deleteCalls | |
160 - (arraysAllocated - arraysFreed); | |
161 } | |
162 #endif | |
163 | |
164 #if 0 /* NOT USED */ | |
165 void logAlloc() { | |
166 LOGV(bytesAllocated) LCV(constructorCalls) LCV(copyConstructorCalls) | |
167 LCV(destructorCalls); | |
168 LOGV(nodesCreated - nodesDeleted); | |
169 LOGV(newArrayCalls) LCV(deleteArrayCalls) LCV(newCalls) LCV(deleteCalls); | |
170 LOGV(myallocs - myfrees) LCV(myallocBytes- myfreeBytes); | |
171 LOGV(newArrayCalls - deleteArrayCalls) LCV(newCalls - deleteCalls); | |
172 LOGV(arraysAllocated - arraysFreed) | |
173 LCV(arrayBytesAllocated - arrayBytesFreed); | |
174 // note: this line wasn't in agsa.cpp, only main.cpp | |
175 LOGV(dcsCreated) LCV(dcsDestroyed) | |
176 LCV(sconConstructorCalls) LCV(sconDestructorCalls); | |
177 } | |
178 #endif | |
179 | |
180 void reset_parser(void) { | |
181 LOGSECTION("reset_parser"); | |
182 if (syntax_state == syntax_reset) { | |
183 return; | |
184 } | |
185 syntax_state = syntax_reset; | |
186 #if 0 | |
187 logAlloc(); | |
188 #endif | |
189 reset_result_data(); | |
190 LOGS("result data reset"); | |
191 reset_summary_data(); | |
192 LOGS("summary data reset"); | |
193 cSegmentStack.reset(); | |
194 LOGS("cSegmentStack reset"); | |
195 extensionStack.reset(); | |
196 LOGS("extenstionStack.reset"); | |
197 cVariableList.reset(); | |
198 LOGS("cVariablelist reset"); | |
199 //errorList.reset(); | |
200 traceCounts.reset(); | |
201 LOGS("traceCounts reset"); | |
202 valueToken.reset(); | |
203 LOGS("valueToken reset"); | |
204 | |
205 Cast::reset(); | |
206 LOGS("Cast reset"); | |
207 Keyword::reset(); | |
208 LOGS("Keyword reset"); | |
209 ParseTree::reset(); | |
210 LOGS("ParseTree reset"); | |
211 Procedure::reset(); | |
212 Rule::reset(); | |
213 //State::reset(); | |
214 Symbol::reset(); | |
215 Token::reset(); | |
216 // note: the following line was not in agsa.cpp, only main.cpp. | |
217 // but I suspect that was a bug... | |
218 VpRule::reset(); | |
219 | |
220 LOGS("Tables reset"); | |
221 ConfigParam::resetAll(); | |
222 nPrologueSegments = 0; | |
223 } | |
224 | |
225 void analyzeGrammar(AgString data, int hasGui) { | |
226 LOGSECTION("analyzeGrammar"); | |
227 reset_parser(); | |
228 input_base = (unsigned char *) data.pointer(); | |
229 syntax_state = syntax_loaded; | |
230 syntax_error_flag = parse_abort_flag = 0; | |
231 badRecursionFlag = 0; | |
232 scan_input(); | |
233 LOGS("input scan complete"); | |
234 if (badRecursionFlag && hasGui) { | |
235 ssprintf("File Trace disabled: %s", badRecursionFlag); | |
236 log_error(); | |
237 } | |
238 if (syntax_error_flag || | |
239 parse_abort_flag || | |
240 nprods == 0 || | |
241 grammar_token == 0 || | |
242 //badRecursionFlag || | |
243 syntax_state != syntax_parsed) { | |
244 return; | |
245 } | |
246 new_syntax_analyzer(); | |
247 assert(int_stack_top == 0); | |
248 assert(nc == 0); | |
249 assert(nw == 0); | |
250 } | |
251 | |
252 void buildParser() { | |
253 LOGSECTION("Build parser"); | |
254 LOGV(syntax_state); | |
255 if (syntax_state == syntax_analyzed) { | |
256 LOGS("build engine"); | |
257 *buildErrorMsg = 0; | |
258 build_parse_engine(); | |
259 if (*buildErrorMsg) { | |
260 errorList.push(Error(buildErrorMsg)); | |
261 } | |
262 LOGS("build complete"); | |
263 syntax_state = engine_built; | |
264 } | |
265 assert(int_stack_top == 0); | |
266 assert(nc == 0); | |
267 assert(nw == 0); | |
268 } | |
269 | |
270 static void dump_errors() { | |
271 LOGSECTION("dump_errors"); | |
272 unsigned i; | |
273 | |
274 LOGV(errorList.size()); | |
275 for (i = 0; i < errorList.size(); i++) { | |
276 Error &e = errorList[i]; | |
277 LOGV(i) LCV(e.line) LCV(e.column); | |
278 LOGV(e.file.pointer()); | |
279 LOGV((int) e.key) LCV(Error::keyString[e.key]); | |
280 // XXX if AG_ON_UNIX should default to gcc's format, and go to stderr | |
281 printf("%s(%d-%d): %s: %s\n", | |
282 e.file.pointer(), e.line, e.column, | |
283 Error::keyString[e.key], e.message.pointer()); | |
284 } | |
285 fflush(stdout); | |
286 } | |
287 | |
288 static text_file buildFile; | |
289 | |
290 static void doBuild(void) { | |
291 if (buildFile.text.exists()) { | |
292 analyzeGrammar(buildFile.text, 0 /* no GUI */); | |
293 buildParser(); | |
294 } | |
295 else { | |
296 ssprintf("Cannot read %s",infile_name.pointer()); | |
297 log_error(); | |
298 errorList.top().setFatal(); | |
299 } | |
300 if (errorList.size()) { | |
301 dump_errors(); | |
302 } | |
303 } | |
304 | |
305 int commandLineBuild(char *n) { | |
306 LOGSECTION("commandLineBuild"); | |
307 | |
308 //AgString path(fp); | |
309 engdef_init(); | |
310 init_parser(); | |
311 const char *failure = checksums_ok(); | |
312 if (failure) { | |
313 fprintf(stderr, "Initialization failure: %s\n", failure); | |
314 AgString whine = code_segment("broken").pointer(); | |
315 fprintf(stderr, "%s\n", whine.pointer()); | |
316 return 1; | |
317 } | |
318 | |
319 AgString name(n); | |
320 LOGV(name); | |
321 | |
322 // XXX. Does this really need to be conditional? | |
323 #ifdef VACLGUI | |
324 startAction = actionObject(doBuild); | |
325 #endif | |
326 | |
327 #ifdef AG_ON_WINDOWS | |
328 AgString fullpath(_MAX_PATH); | |
329 _fullpath(fullpath.pointer(), name.pointer(), _MAX_PATH); | |
330 AgString fileName = fullpath.lastCut("\\/:").rightX(); | |
331 #endif | |
332 | |
333 #ifdef AG_ON_UNIX | |
334 #if 0 /* Don't use realpath; it's not the canonical Unix way */ | |
335 // realpath is documented to use MAXPATHLEN, not PATH_MAX. sigh. | |
336 // (see longer comment above) | |
337 //AgString fullpath(PATH_MAX); | |
338 AgString fullpath(MAXPATHLEN); | |
339 | |
340 realpath(name.pointer(), fullpath.pointer()); | |
341 AgString fileName = fullpath.lastCut('/').rightX(); | |
342 #else | |
343 AgString fullpath = name; | |
344 AgString fileName = fullpath.lastCut('/').rightX(); | |
345 if (fileName.size() == 0) { | |
346 fileName = fullpath; | |
347 } | |
348 #endif /* 0 */ | |
349 #endif /* AG_ON_UNIX */ | |
350 | |
351 infile_name = fullpath; // Store selected file name | |
352 errorReportFile = infile_name; // Store selected file name | |
353 | |
354 simple_file_name = fileName.lastCut('.').leftX(); | |
355 | |
356 LOGV(fileName.pointer()); | |
357 LOGV(simple_file_name.pointer()); | |
358 text_file inputFile(infile_name); | |
359 | |
360 if (!inputFile.text.exists() && fileName == simple_file_name) { | |
361 infile_name = infile_name.concat(".syn"); | |
362 inputFile = text_file(infile_name); | |
363 LOGV(infile_name.pointer()); | |
364 } | |
365 buildFile = inputFile; | |
366 | |
367 // XXX as above | |
368 #ifdef VACLGUI | |
369 startAction(); | |
370 #else | |
371 doBuild(); | |
372 #endif | |
373 | |
374 return syntax_state != engine_built; | |
375 } |