1 package acl2s.lib.session;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileReader;
6 import java.io.IOException;
7 import java.net.URISyntaxException;
8 import java.net.URL;
9 import java.util.ArrayList;
10 import java.util.Arrays;
11 import java.util.HashSet;
12 import java.util.Iterator;
13 import java.util.LinkedList;
14 import java.util.List;
15 import java.util.Map;
16
17 import org.peterd.util.Misc;
18
19 import acl2s.lib.parse.obj.Sym;
20 import acl2s.lib_driver.IAcl2sLibErrorHandler;
21 import acl2s.lib_example.BasicInteractiveSessionConfig;
22
23 public class MyBaseConfig implements IBaseConfig {
24 private static final long serialVersionUID = 2L;
25
26 public MyBaseConfig(IAcl2sLibErrorHandler err, File hooksHome, File acl2Home, File[] modeHomes) {
27 this.err = err;
28 this.hooksHome = hooksHome;
29 this.acl2Home = acl2Home;
30 updateForNewHooksHome();
31 updateForNewAcl2Home();
32 addModeHomes(modeHomes);
33 }
34
35 protected IAcl2sLibErrorHandler err;
36 protected File acl2Home;
37 protected String htmlHomeUrl;
38 protected String[] pathsToTry;
39
40 protected File hooksHome;
41 protected String hooksAcl2Path;
42
43 protected ModeDir[] modeDirs = {}; // after update, dependency-respecting sequence
44 protected SessionMode[] modes = { SessionMode.compatible }; // kept as sequence of all known modes
45 protected String modeAddIncludeBooks = "";
46
47 public void setHooksHome(File f) {
48 if (!Misc.equal(f, hooksHome)) {
49 hooksHome = f;
50 updateForNewHooksHome();
51 }
52 }
53
54 protected void updateForNewHooksHome() {
55 if (hooksHome == null) {
56 hooksAcl2Path = null;
57 } else {
58 hooksAcl2Path = toAcl2PathDir(hooksHome);
59 }
60 }
61
62 public String getHooksAcl2Path() {
63 return hooksAcl2Path;
64 }
65
66 public File getHooksHome() {
67 return hooksHome;
68 }
69
70
71 public void setAcl2Home(File f) {
72 if (!Misc.equal(f, acl2Home)) {
73 acl2Home = f;
74 updateForNewAcl2Home();
75 }
76 }
77
78 protected void updateForNewAcl2Home() {
79 htmlHomeUrl = findHtmlHome(acl2Home);
80 pathsToTry = findPaths(acl2Home);
81 }
82
83
84 public void addModeHomes(File... modeHomes) {
85 if (modeHomes == null || modeHomes.length == 0) return;
86
87 LinkedList<ModeDir> phase1 = new LinkedList<ModeDir>();
88 for (File modeHome : modeHomes) {
89 ModeDir d = ModeDir.maybeCreate(err, modeHome);
90 if (d != null) {
91 phase1.add(d);
92 }
93 }
94 if (phase1.size() == 0) return;
95 phase1.addAll(Arrays.asList(modeDirs));
96 updateModes(phase1);
97 }
98
99 public void removeModeHomes(File... removeHomes) {
100 if (removeHomes == null || removeHomes.length == 0) return;
101 ArrayList<ModeDir> toRemove = new ArrayList<ModeDir>();
102 for (File home : removeHomes) {
103 ModeDir d = lookupModeDir(home);
104 if (d != null) {
105 toRemove.add(d);
106 }
107 }
108 removeModeDirs(toRemove);
109 }
110
111 public void removeModeDirs(ModeDir... removeDirs) {
112 removeModeDirs(Arrays.asList(removeDirs));
113 }
114
115 public void removeModeDirs(List<ModeDir> removeDirs) {
116 if (removeDirs == null || removeDirs.size() == 0) return;
117
118 LinkedList<ModeDir> phase1 = new LinkedList<ModeDir>();
119 phase1.addAll(Arrays.asList(modeDirs));
120 if (!phase1.removeAll(removeDirs)) return;
121
122 updateModes(phase1);
123 }
124
125 static Sym systemKeyword = Sym.createKeyword("SYSTEM");
126
127 protected void updateModes(LinkedList<ModeDir> phase1) {
128 // order to satisfy dependencies
129 ArrayList<ModeDir> phase2 = new ArrayList<ModeDir>(phase1.size());
130 boolean added;
131 HashSet<Sym> dirSyms = new HashSet<Sym>(phase1.size());
132 dirSyms.add(systemKeyword);
133 do {
134 added = false;
135 Iterator<ModeDir> rem = phase1.iterator();
136 while (rem.hasNext()) {
137 ModeDir modeDir = rem.next();
138 boolean sat = true;
139 for (Sym dep : modeDir.deps) {
140 if (!dirSyms.contains(dep) && !Misc.equal(dep, modeDir.includeBookDirSym)) {
141 sat = false;
142 }
143 }
144 if (sat) {
145 phase2.add(modeDir);
146 rem.remove();
147 if (modeDir.includeBookDirSym != null) {
148 dirSyms.add(modeDir.includeBookDirSym);
149 added = true;;
150 }
151 }
152 }
153 } while (added);
154
155
156 for (ModeDir bad : phase1) {
157 err.error("Mode dir has unsatisfied dependencies: " + bad.home.getAbsolutePath(), null);
158 }
159
160 modeDirs = phase2.toArray(new ModeDir[phase2.size()]);
161
162 ArrayList<SessionMode> allModes = new ArrayList<SessionMode>();
163 allModes.add(SessionMode.compatible);
164 StringBuilder addInclBook = new StringBuilder();
165 for (ModeDir modeDir : modeDirs) {
166 addInclBook.append(modeDir.getAddIncludeBookDirString());
167 for (SessionMode mode : modeDir.modes) {
168 allModes.add(mode);
169 }
170 }
171 modes = allModes.toArray(new SessionMode[allModes.size()]);
172 Arrays.sort(modes); // by precedence
173 modeAddIncludeBooks = addInclBook.toString();
174 }
175
176
177 public String getDocBaseURL() {
178 return htmlHomeUrl;
179 }
180
181 public String[] getCmdLine() {
182 String cmd = fallbackCmd;
183 for (String path : pathsToTry) {
184 File f = new File(path);
185 if (f.exists()) {
186 cmd = path;
187 break;
188 }
189 }
190 return new String[] { cmd };
191 }
192
193
194 public void setupEnvironment(Map<String, String> env) {
195 // script should set ACL2_SYSTEM_BOOKS better than we can
196 env.put("ACL2-CUSTOMIZATION", "NONE"); // we will load it if we want it
197 }
198
199 public String getACL2sDocURL() {
200 return Versions.getAcl2sDocInternetURLString();
201 }
202
203 public SessionMode[] getModes() {
204 return modes;
205 }
206
207 public SessionMode getDefaultMode() {
208 return modes[0];
209 }
210
211 public ModeDir[] getModeDirs() {
212 return modeDirs;
213 }
214
215 public String getModeAddIncludeBooks() {
216 return modeAddIncludeBooks;
217 }
218
219 public SessionMode lookupMode(String name) {
220 for (SessionMode m : modes) {
221 if (m.getName().equalsIgnoreCase(name)) {
222 return m;
223 }
224 }
225 return null;
226 }
227
228 public ModeDir lookupModeDir(File home) {
229 for (ModeDir modeDir : modeDirs) {
230 if (modeDir.home.equals(home)) {
231 return modeDir;
232 }
233 }
234 return null;
235 }
236
237 public ModeDir lookupModeDir(Sym dir) {
238 for (ModeDir modeDir : modeDirs) {
239 if (modeDir.includeBookDirSym == dir) {
240 return modeDir;
241 }
242 }
243 return null;
244 }
245
246 // ********************** STATIC STUFF ********************** //
247
248 public static File getACL2HomeFromEnvironment() {
249 return acl2HomeFromEnvironment;
250 }
251
252 public static File getHooksHomeFromEnvironment() {
253 return hooksHomeFromEnvironment;
254 }
255
256 static final File acl2HomeFromEnvironment = findAcl2HomeFromEnvironment();
257 static final File hooksHomeFromEnvironment = findHooksHomeFromEnvironment();
258
259 static File findAcl2HomeFromEnvironment() {
260 String tmp = System.getenv("ACL2_HOME");
261 if (tmp == null || ! new File(tmp).isDirectory()) {
262 tmp = System.getProperty("ACL2_HOME");
263 }
264 if (tmp == null || ! new File(tmp).isDirectory()) {
265 tmp = System.getProperty("acl2.home");
266 }
267 if (tmp == null || ! new File(tmp).isDirectory()) {
268 return null;
269 } else {
270 return new File(tmp).getAbsoluteFile();
271 }
272 }
273
274 static File findHooksHomeFromEnvironment() {
275 String tmp;
276 tmp = System.getenv("ACL2S_HOOKS");
277 if (tmp != null) {
278 File f = new File(tmp);
279 if (f.isDirectory()) {
280 return f;
281 }
282 }
283 tmp = System.getProperty("ACL2S_HOOKS");
284 if (tmp != null) {
285 File f = new File(tmp);
286 if (f.isDirectory()) {
287 return f;
288 }
289 }
290 tmp = System.getProperty("acl2s.hooks");
291 if (tmp != null) {
292 File f = new File(tmp);
293 if (f.isDirectory()) {
294 return f;
295 }
296 }
297 try {
298 URL u = BasicInteractiveSessionConfig.class.getResource("hooks/preinit.lsp");
299 if (u != null) {
300 File f = new File(u.toURI()).getParentFile();
301 if (f.isDirectory()) {
302 return f;
303 }
304 }
305 } catch (IllegalArgumentException e) {
306 } catch (URISyntaxException e) {
307 }
308 try {
309 URL u = BasicInteractiveSessionConfig.class.getResource("../hooks/preinit.lsp");
310 if (u != null) {
311 File f = new File(u.toURI()).getParentFile();
312 if (f.isDirectory()) {
313 return f;
314 }
315 }
316 } catch (IllegalArgumentException e) {
317 } catch (URISyntaxException e) {
318 }
319 return null; // could not find
320 }
321
322
323
324 public static final String fallbackCmd = "acl2";
325
326
327
328 public static String findHtmlHome(File acl2HomeOption) {
329 String tmp = null;
330 if (acl2HomeOption != null) {
331 File f = new File(new File(acl2HomeOption, "doc"), "HTML");
332 if (new File(f, "acl2-doc.html").exists()) {
333 tmp = "file://" + toAcl2PathDir(f);
334 }
335 }
336 if (tmp == null) {
337 tmp = Versions.getAcl2DocInternetURLString();
338 }
339 return tmp;
340 }
341
342 //harshrc:: Acl2HomeOption can be
343 //1. ACL2 build path set in eclipse preferences
344 //2. ACL2s image plugin path (bundle in eclipse terminology)
345 //3. ACL2_HOME environment variable set in OS
346 //4. null (in which case we try to execute 'acl2')
347 public static String[] findPaths(File acl2HomeOption) {
348 boolean windows = File.separatorChar == '\\';
349
350 ArrayList<String> paths = new ArrayList<String>();
351
352 if (acl2HomeOption != null) {
353 String hpath = acl2HomeOption.getAbsolutePath();
354 if (windows) {
355 paths.add(hpath + File.separator + "run_acl2.exe");
356 paths.add(hpath + File.separator + "saved_acl2.bat");
357 paths.add(hpath + File.separator + "bin" + File.separator + "acl2.exe");
358 } else {
359 paths.add(hpath + File.separator + "run_acl2");
360 paths.add(hpath + File.separator + "saved_acl2");
361 }
362 }
363
364 if (windows) {
365 String minVer = Versions.getAcl2MinVersionString();
366 String maxVer = Versions.getAcl2MaxVersionString();
367
368 paths.add("C:\\ACL2-" + maxVer + "\\bin\\acl2.exe");
369 paths.add("C:\\Program Files\\ACL2 " + maxVer + "\\bin\\acl2.exe");
370 if (! minVer.equals(maxVer)) {
371 paths.add("C:\\ACL2-" + minVer + "\\bin\\acl2.exe");
372 paths.add("C:\\Program Files\\ACL2 " + minVer + "\\bin\\acl2.exe");
373 }
374 }
375
376 return paths.toArray(new String[paths.size()]);
377 }
378
379 /*
380 static final Sym BOOK_DEV = Sym.createKeyword("BOOK-DEV");
381 static final Sym TTAGS = Sym.createKeyword("TTAGS");
382 static final Sym IMPORTS = Sym.createKeyword("IMPORTS");
383 static final Sym PRECEDENCE = Sym.createKeyword("PRECEDENCE");
384
385 public static SessionMode[] getModesFromHome(File root) {
386 try {
387 File[] modeFiles = root.listFiles();
388 ArrayList<SessionMode> foundModes = new ArrayList<SessionMode>(modeFiles.length);
389 for (File mf : modeFiles) {
390 if (!mf.getName().toLowerCase().endsWith("mode.lsp")) continue;
391 try {
392 FileInputStream stream = new FileInputStream(mf);
393 LispObject[] md = LispObject.parseAll(new StreamParser(BootstrapParseContext.instance, stream));
394 stream.close();
395 if (md.length < 4) throw new ParseException("Expecting at least four lisp objects in file " + mf);
396 if (!(md[0] instanceof Str) ||
397 !(md[1] instanceof Str) ||
398 !(md[2] instanceof Str)) {
399 throw new ParseException("First three objects must be strings in file " + mf);
400 }
401 String name = ((Str)md[0]).value;
402 String sdesc = ((Str)md[1]).value;
403 String ldesc = ((Str)md[2]).value;
404
405 // option defaults
406 boolean bookdev = true;
407 boolean ttags = false;
408 LispObject extraImports = Sym.nilInstance;
409 int precedence = Integer.MAX_VALUE;
410
411 // options given with keywords
412 if (!(md[3].isNil())) {
413 try {
414 LispObject optLst = Cons.deQuote(md[3]);
415 while (!optLst.isNil()) {
416 Cons c = (Cons) optLst;
417 Sym opt = (Sym) c.car;
418 c = (Cons) c.cdr;
419 LispObject val = c.car;
420 optLst = c.cdr;
421
422 if (opt == BOOK_DEV) {
423 bookdev = Cons.maybeDeQuote(val).isNotNil();
424 } else if (opt == TTAGS) {
425 ttags = Cons.maybeDeQuote(val).isNotNil();
426 } else if (opt == IMPORTS) {
427 // ensure either (unquoted) nil or quoted list
428 extraImports = Cons.maybeDeQuote(val);
429
430 if (extraImports.isNotNil()) {
431 extraImports = Cons.quote(extraImports);
432 }
433 } else if (opt == PRECEDENCE) {
434 val = Cons.maybeDeQuote(val);
435 if (val instanceof Int) {
436 BigInteger precInt = ((Int) val).v;
437 if (precInt.bitLength() <= 31) {
438 precedence = precInt.intValue();
439 }
440 }
441 } else {
442 // unrecognized
443 }
444 }
445 } catch (Exception e) {
446 throw new ParseException("Malformed keyword options in fourth object of file " + mf);
447 }
448 }
449 LispObject[] initData = new LispObject[md.length - 4];
450 System.arraycopy(md, 4, initData, 0, initData.length);
451 foundModes.add(new SessionMode(root, name, sdesc, ldesc, bookdev, ttags, extraImports, precedence, initData));
452 } catch (ParseException pe) {
453 System.err.println("Unable to parse mode in registry (" + mf + "): " + pe.toString());
454 }
455 }
456
457 if (foundModes.size() > 0) {
458 SessionMode[] modes = foundModes.toArray(new SessionMode[foundModes.size()]);
459 Arrays.sort(modes);
460 return modes;
461 }
462 // otherwise, fallback:
463 } catch (IOException ioe) {
464 System.err.println("While reading mode registry: " + ioe.toString());
465 }
466 return SessionMode.compatibleOnly;
467 }*/
468
469 public static File[] getCertifyOrder(File hooksHome) throws IOException {
|
Event modeled_event: |
Opening a resource with "new java.io.FileReader()". |
|
Event transitive_modeled_event: |
Opening a resource with "new java.io.BufferedReader()". |
|
Event alias: |
Assigning: r = new java.io.BufferedReader() |
| Also see events: |
[return_without_close] |
470 BufferedReader r = new BufferedReader(new FileReader(new File(hooksHome, "certify-order.txt")));
471
472 ArrayList<File> order = new ArrayList<File>();
473 for (;;) {
|
At conditional (3): uncaught exception java.io.IOException thrown on line 474: Taking true branch.
|
474 String line = r.readLine();
|
At conditional (1): (line == null): Taking false branch.
|
475 if (line == null) break;
|
At conditional (2): (line.length() > 0): Taking false branch.
|
476 if (line.length() > 0 && Character.isLetterOrDigit(line.charAt(0))) {
477 File f = new File(hooksHome, line + ".lisp");
478 if (f.exists()) {
479 order.add(f);
480 } else {
481 System.err.println("Skipping non-existant hooks file: " + f);
482 }
483 }
484 }
485 return order.toArray(new File[order.size()]);
486 }
487
488 public static boolean isConsoleInterrupt(String line) {
489 if (line.startsWith("************ ABORTING from raw Lisp ***********")) {
490 return true; // ACL2's abort message, for everything but non-ansi GCL
491 }
492 if (line.startsWith("debugger invoked")) {
493 return true; //harshrc// one of abort messages SBCL
494 }
495 if (line.startsWith("> Break: interrupt signal")) {
496 return true; //harshrc// one of abort messages CCL
497 }
498 if (line.equals("Error: Console interrupt.\n")) {
499 return true; // non-ansi GCL is special
500 }
501 /* These should not be needed now that we use ACL2's have the ABORTING line
502 if (line.startsWith("Error: ")) {
503 if (line.startsWith("Error: interrupted ")) {
504 return true; // SBCL (older)
505 }
506 if (line.startsWith("Error: Interactive interrupt ")) {
507 return true; // SBCL (newer)
508 }
509 }
510 if (line.startsWith("> Break in process ")) {
511 return true; // OpenMCL
512 }
513 */
514 return false;
515 }
516
517 public static String toAcl2PathString(String path) {
518 if (File.separatorChar == '/') {
519 return path;
520 } else {
521 return path.replace(File.separatorChar, '/');
522 }
523 }
524
525 public static String toSystemPathString(String acl2Path) {
526 if (File.separatorChar == '/') {
527 return acl2Path;
528 } else {
529 return acl2Path.replace('/', File.separatorChar);
530 }
531 }
532
533 public static String toAcl2PathFile(File f) {
534 return toAcl2PathString(f.getAbsolutePath());
535 }
536
537 public static String toAcl2PathDir(File f) {
538 String path = toAcl2PathFile(f);
539 if (!path.endsWith("/")) {
540 path += "/";
541 }
542 return path;
543 }
544 }