001: /*
002: * Load.java
003: *
004: * Copyright (C) 2002-2003 Peter Graves
005: * $Id: Load.java,v 1.6 2003/11/15 11:03:30 beedlem Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.lisp;
023:
024: import java.io.File;
025: import java.io.FileInputStream;
026: import java.io.FileNotFoundException;
027: import java.io.IOException;
028: import java.io.InputStream;
029: import java.net.URL;
030:
031: public final class Load extends Lisp {
032: public static final LispObject load(String filename)
033: throws ConditionThrowable {
034: return load(filename,
035: _LOAD_VERBOSE_.symbolValueNoThrow() != NIL,
036: _LOAD_PRINT_.symbolValueNoThrow() != NIL);
037: }
038:
039: public static final LispObject load(final String filename,
040: boolean verbose, boolean print) throws ConditionThrowable {
041: File file = null;
042: boolean isFile = false;
043: if (Utilities.isFilenameAbsolute(filename)) {
044: file = new File(filename);
045: if (file != null) {
046: isFile = file.isFile();
047: if (!isFile) {
048: String extension = getExtension(filename);
049: if (extension == null) {
050: // No extension specified. Try appending ".lisp".
051: file = new File(filename.concat(".lisp"));
052: isFile = file.isFile();
053: }
054: }
055: }
056: } else {
057: // Filename is not absolute.
058: String dir = LispString
059: .getValue(_DEFAULT_PATHNAME_DEFAULTS_.symbolValue());
060: file = new File(dir, filename);
061: if (file != null) {
062: isFile = file.isFile();
063: if (!isFile) {
064: String extension = getExtension(filename);
065: if (extension == null) {
066: // No extension specified. Try appending ".lisp".
067: file = new File(dir, filename.concat(".lisp"));
068: isFile = file.isFile();
069: }
070: }
071: }
072: }
073: if (!isFile)
074: throw new ConditionThrowable(new LispError(
075: "file not found: " + filename));
076: String truename = filename;
077: InputStream in = null;
078: try {
079: in = new FileInputStream(file);
080: truename = file.getCanonicalPath();
081: } catch (FileNotFoundException e) {
082: throw new ConditionThrowable(new LispError(
083: "file not found: " + filename));
084: } catch (IOException e) {
085: throw new ConditionThrowable(new LispError(e.getMessage()));
086: }
087: LispObject result = loadFileFromStream(truename, in, verbose,
088: print, false);
089: try {
090: in.close();
091: } catch (IOException e) {
092: throw new ConditionThrowable(new LispError(e.getMessage()));
093: }
094: return result;
095: }
096:
097: public static final LispObject _load(String filename)
098: throws ConditionThrowable {
099: return _load(filename,
100: _LOAD_VERBOSE_.symbolValueNoThrow() != NIL,
101: _LOAD_PRINT_.symbolValueNoThrow() != NIL, false);
102: }
103:
104: public static final LispObject _load(String filename, boolean auto)
105: throws ConditionThrowable {
106: boolean verbose;
107: if (auto)
108: verbose = _AUTOLOAD_VERBOSE_.symbolValueNoThrow() != NIL;
109: else
110: verbose = _LOAD_VERBOSE_.symbolValueNoThrow() != NIL;
111: return _load(filename, verbose, _LOAD_PRINT_
112: .symbolValueNoThrow() != NIL, auto);
113: }
114:
115: public static final LispObject _load(final String filename,
116: boolean verbose, boolean print, boolean auto)
117: throws ConditionThrowable {
118: InputStream in = null;
119: String truename = null;
120: URL url = Lisp.class.getResource(filename);
121: if (url != null) {
122: try {
123: in = url.openStream();
124: truename = url.getPath();
125: } catch (IOException e) {
126: in = null;
127: }
128: } else {
129: // Look in current directory.
130: File file = new File(System.getProperty("user.dir"),
131: filename);
132: if (file.isFile()) {
133: try {
134: in = new FileInputStream(file);
135: truename = file.getCanonicalPath();
136: } catch (IOException e) {
137: in = null;
138: }
139: }
140: }
141: if (in != null) {
142: LispObject result = loadFileFromStream(truename, in,
143: verbose, print, auto);
144: try {
145: in.close();
146: } catch (IOException e) {
147: throw new ConditionThrowable(new LispError(e
148: .getMessage()));
149: }
150: return result;
151: }
152: throw new ConditionThrowable(new LispError("file not found: "
153: + filename));
154: }
155:
156: private static final LispObject loadFileFromStream(String truename,
157: InputStream in, boolean verbose, boolean print, boolean auto)
158: throws ConditionThrowable {
159: long start = System.currentTimeMillis();
160: LispThread thread = LispThread.currentThread();
161: Environment oldDynEnv = thread.getDynamicEnvironment();
162: thread.bindSpecial(_PACKAGE_, _PACKAGE_.symbolValue());
163: int loadDepth = Fixnum.getInt(_LOAD_DEPTH_.symbolValue());
164: thread.bindSpecial(_LOAD_DEPTH_, new Fixnum(++loadDepth));
165: final String prefix = getLoadVerbosePrefix(loadDepth);
166: try {
167: thread.bindSpecial(_LOAD_TRUENAME_,
168: new LispString(truename));
169: if (verbose) {
170: CharacterOutputStream out = getStandardOutput();
171: out.freshLine();
172: out.writeString(prefix);
173: out.writeString(auto ? " Autoloading " : " Loading ");
174: out.writeString(truename);
175: out.writeLine(" ...");
176: out.flushOutput();
177: LispObject result = loadStream(in, print);
178: long elapsed = System.currentTimeMillis() - start;
179: out.freshLine();
180: out.writeString(prefix);
181: out.writeString(auto ? " Autoloaded " : " Loaded ");
182: out.writeString(truename);
183: out.writeString(" (");
184: out.writeString(String
185: .valueOf(((float) elapsed) / 1000));
186: out.writeLine(" seconds)");
187: out.flushOutput();
188: return result;
189: } else
190: return loadStream(in, print);
191: } finally {
192: thread.setDynamicEnvironment(oldDynEnv);
193: }
194: }
195:
196: public static String getLoadVerbosePrefix(int loadDepth) {
197: StringBuffer sb = new StringBuffer(";");
198: for (int i = loadDepth - 1; i-- > 0;)
199: sb.append(' ');
200: return sb.toString();
201: }
202:
203: private static final LispObject loadStream(InputStream inputStream,
204: boolean print) throws ConditionThrowable {
205: CharacterInputStream in = new CharacterInputStream(inputStream);
206: final LispThread thread = LispThread.currentThread();
207: try {
208: final Environment env = new Environment();
209: while (true) {
210: LispObject obj = in.read(false, EOF, true);
211: if (obj == EOF)
212: break;
213: LispObject result = eval(obj, env, thread);
214: if (print) {
215: CharacterOutputStream out = getStandardOutput();
216: out.writeLine(String.valueOf(result));
217: out.flushOutput();
218: }
219: }
220: return T;
221: } catch (ConditionThrowable t) {
222: if (debug)
223: thread.saveBacktrace();
224: CharacterOutputStream out = getStandardOutput();
225: String truename = null;
226: LispObject obj = _LOAD_TRUENAME_.symbolValueNoThrow();
227: if (obj instanceof LispString)
228: truename = ((LispString) obj).getValue();
229: StringBuffer sb = new StringBuffer("Error");
230: if (truename != null) {
231: sb.append(" in ");
232: sb.append(truename);
233: }
234: sb.append(" at line ");
235: sb.append(in.getLineNumber() + 1);
236: sb.append(" (offset ");
237: sb.append(in.getOffset());
238: sb.append(')');
239: out.writeLine(sb.toString());
240: throw t;
241: }
242: }
243:
244: // Returns extension including leading '.'
245: private static final String getExtension(String filename) {
246: int index = filename.lastIndexOf('.');
247: if (index < 0)
248: return null;
249: if (index < filename.lastIndexOf(File.separatorChar))
250: return null; // Last dot was in path part of filename.
251: return filename.substring(index);
252: }
253:
254: private static final String getPath(URL url) {
255: if (url != null) {
256: String path = url.getPath();
257: if (path != null) {
258: if (System.getProperty("os.name").startsWith("Windows")) {
259: if (path.length() > 0 && path.charAt(0) == '/')
260: path = path.substring(1);
261: }
262: return path;
263: }
264: }
265: return null;
266: }
267:
268: // ### load
269: // Need to support keyword args.
270: // load filespec &key verbose print if-does-not-exist external-format
271: public static final Primitive LOAD = new Primitive("load") {
272: public LispObject execute(LispObject[] args)
273: throws ConditionThrowable {
274: if (args.length == 0)
275: throw new ConditionThrowable(
276: new WrongNumberOfArgumentsException(this ));
277: // FIXME Need to support streams as well as pathname designators.
278: String filename;
279: if (args[0] instanceof LispString)
280: filename = ((LispString) args[0]).getValue();
281: else if (args[0] instanceof Pathname)
282: filename = ((Pathname) args[0]).getNamestring();
283: else
284: throw new ConditionThrowable(new TypeError(args[0],
285: "pathname designator"));
286: if (filename.endsWith(".compiled"))
287: filename = filename.substring(0, filename.length() - 9);
288: return load(filename,
289: _LOAD_VERBOSE_.symbolValueNoThrow() != NIL,
290: _LOAD_PRINT_.symbolValueNoThrow() != NIL);
291: }
292: };
293:
294: // ### %load
295: public static final Primitive1 _LOAD = new Primitive1("%load",
296: PACKAGE_SYS, false) {
297: public LispObject execute(LispObject arg)
298: throws ConditionThrowable {
299: return _load(LispString.getValue(arg), _LOAD_VERBOSE_
300: .symbolValueNoThrow() != NIL, _LOAD_PRINT_
301: .symbolValueNoThrow() != NIL, false);
302: }
303: };
304: }
|