source: trunk/abcl/src/org/armedbear/lisp/Load.java @ 12559

Last change on this file since 12559 was 12550, checked in by Mark Evenson, 15 years ago

Fix loading of packed FASLs which have been renamed.

Bug was present since at least 0.18.1.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 28.9 KB
Line 
1/*
2 * Load.java
3 *
4 * Copyright (C) 2002-2007 Peter Graves
5 * $Id: Load.java 12550 2010-03-16 15:20:01Z mevenson $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36import static org.armedbear.lisp.Lisp.*;
37
38import java.io.IOException;
39import java.io.InputStream;
40import java.net.URL;
41
42/* This file holds ABCL's (FASL and non-FASL) loading behaviours.
43 *
44 * The loading process works like this:
45 *   The loader associates the input filename with a special variable
46 *   and starts evaluating the forms in the file.
47 *
48 *   If one of the forms is (INIT-FASL :VERSION <version>), from that
49 *   point the file is taken to be a FASL.
50 *   The FASL loader takes over and retrieves the file being loaded
51 *   from the special variable and continues loading from there.
52 *
53 */
54public final class Load
55{
56    public static final LispObject load(String filename)
57    {
58        final LispThread thread = LispThread.currentThread();
59        return load(new Pathname(filename),
60                    Symbol.LOAD_VERBOSE.symbolValue(thread) != NIL,
61                    Symbol.LOAD_PRINT.symbolValue(thread) != NIL,
62                    true);
63    }
64 
65    /** @return Pathname of loadable file based on NAME, or null if
66     * none can be determined. */
67    private static final Pathname findLoadableFile(Pathname name) {
68        LispObject truename  = Pathname.truename(name, false);
69        if (truename instanceof Pathname) {
70            Pathname t = (Pathname)truename;
71            if (t.name != NIL
72                && t.name != null) {
73                return t;
74            }
75        }
76        if (name.type == NIL
77            && (name.name != NIL || name.name != null)) {
78            Pathname lispPathname = new Pathname(name);
79            lispPathname.type = new SimpleString("lisp");
80            lispPathname.invalidateNamestring();
81            LispObject lisp = Pathname.truename(lispPathname, false);
82            Pathname abclPathname = new Pathname(name);
83            abclPathname.type = new SimpleString("abcl");
84            abclPathname.invalidateNamestring();
85            LispObject abcl = Pathname.truename(abclPathname, false);
86            if (lisp instanceof Pathname && abcl instanceof Pathname) {
87                lispPathname = (Pathname)lisp;
88                abclPathname = (Pathname)abcl;
89                long lispLastModified = lispPathname.getLastModified();
90                long abclLastModified = abclPathname.getLastModified();
91              if (abclLastModified > lispLastModified) {
92                  return lispPathname;
93              } else {
94                  return abclPathname;
95              }
96            } else if (abcl instanceof Pathname) {
97                return (Pathname) abcl;
98            } else if (lisp instanceof Pathname) { 
99                return (Pathname) lisp;
100            }
101        }
102        if (name.isJar()) {
103            if (name.type.equals(NIL)) {
104                name.type = COMPILE_FILE_INIT_FASL_TYPE;
105                name.invalidateNamestring();
106                Pathname result = findLoadableFile(name);
107                if (result != null) {
108                    return result;
109                }
110                name.type = new SimpleString(COMPILE_FILE_TYPE);
111                name.invalidateNamestring();
112                result = findLoadableFile(name);
113                if (result != null) {
114                    return result;
115                }
116            }
117        }
118        return null;
119    }
120 
121    public static final LispObject load(Pathname pathname,
122                                        boolean verbose,
123                                        boolean print,
124                                        boolean ifDoesNotExist)
125    {
126        return load(pathname, verbose, print, ifDoesNotExist, false);
127    }
128
129    public static final LispObject load(final Pathname pathname,
130                                        boolean verbose,
131                                        boolean print,
132                                        boolean ifDoesNotExist,
133                                        boolean returnLastResult)
134
135    {
136        Pathname mergedPathname = null;
137        if (!pathname.isAbsolute() && !pathname.isJar()) {
138            Pathname pathnameDefaults
139                = coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue());
140            mergedPathname = Pathname.mergePathnames(pathname, pathnameDefaults);
141        }
142
143        Pathname truename = findLoadableFile(mergedPathname != null ? mergedPathname : pathname);
144
145        if (truename == null || truename.equals(NIL)) {
146            if (ifDoesNotExist) {
147                return error(new FileError("File not found.", pathname));
148            } else {
149                Debug.warn("Failed to load " + pathname.getNamestring());
150                return NIL;
151            }
152        }
153
154        if (Utilities.checkZipFile(truename)) {
155            String n = truename.getNamestring();
156            if (n.startsWith("jar:")) {
157                n = "jar:" + n + "!/" + truename.name.getStringValue() + "."
158                    + COMPILE_FILE_INIT_FASL_TYPE;
159            } else {
160                n = "jar:file:" + n + "!/" + truename.name.getStringValue() + "."
161                    + COMPILE_FILE_INIT_FASL_TYPE;
162            }
163            mergedPathname = new Pathname(n);
164            LispObject initTruename = Pathname.truename(mergedPathname);
165            if (initTruename == null || initTruename.equals(NIL)) {
166                // Maybe the enclosing JAR has been renamed?
167                Pathname p = new Pathname(mergedPathname);
168                p.name = Keyword.WILD;
169                p.invalidateNamestring();
170                LispObject result = Pathname.MATCH_WILD_JAR_PATHNAME.execute(p);
171
172                if      (result instanceof Cons
173                    && ((Cons)result).length() == 1
174                    && ((Cons)result).car() instanceof Pathname) {
175                    initTruename = (Pathname)result.car();
176                } else {
177                  String errorMessage
178                      = "Loadable FASL not found for "
179                      + "'" + pathname + "'"
180                      + " in "
181                      + "'" + mergedPathname + "'";
182                  if (ifDoesNotExist) {
183                      return error(new FileError(errorMessage, mergedPathname));
184                  } else {
185                      Debug.trace(errorMessage);
186                      return NIL;
187                  }
188                }
189            }
190            truename = (Pathname)initTruename;
191        }
192       
193        InputStream in = truename.getInputStream();
194        Debug.assertTrue(in != null);
195   
196        try {
197            return loadFileFromStream(pathname, truename,
198                                      new Stream(Symbol.SYSTEM_STREAM, in, Symbol.CHARACTER),
199                                      verbose, print, false, returnLastResult);
200        }
201        catch (FaslVersionMismatch e) {
202            StringBuilder sb =
203                new StringBuilder("Incorrect fasl version: ");
204            sb.append(truename);
205            return error(new SimpleError(sb.toString()));
206        }
207        finally {
208            if (in != null) {
209                try {
210                   in.close();
211                }
212                catch (IOException e) {
213                    return error(new LispError(e.getMessage()));
214                }
215            }
216        }
217    }
218
219    public static final LispObject loadSystemFile(String filename)
220
221    {
222        final LispThread thread = LispThread.currentThread();
223        return loadSystemFile(filename,
224                              Symbol.LOAD_VERBOSE.symbolValue(thread) != NIL,
225                              Symbol.LOAD_PRINT.symbolValue(thread) != NIL,
226                              false);
227    }
228
229    public static final LispObject loadSystemFile(String filename, boolean auto)
230
231    {
232        LispThread thread = LispThread.currentThread();
233        if (auto) {
234            final SpecialBindingsMark mark = thread.markSpecialBindings();
235            thread.bindSpecial(Symbol.CURRENT_READTABLE,
236                               STANDARD_READTABLE.symbolValue(thread));
237            thread.bindSpecial(Symbol._PACKAGE_, PACKAGE_CL_USER);
238            try {
239                return loadSystemFile(filename,
240                                      _AUTOLOAD_VERBOSE_.symbolValue(thread) != NIL,
241                                      Symbol.LOAD_PRINT.symbolValue(thread) != NIL,
242                                      auto);
243            }
244            finally {
245                thread.resetSpecialBindings(mark);
246            }
247        } else {
248            return loadSystemFile(filename,
249                                  Symbol.LOAD_VERBOSE.symbolValue(thread) != NIL,
250                                  Symbol.LOAD_PRINT.symbolValue(thread) != NIL,
251                                  auto);
252        }
253    }
254
255    static final LispObject COMPILE_FILE_INIT_FASL_TYPE = new SimpleString("_");
256
257    public static final LispObject loadSystemFile(final String filename,
258                                                  boolean verbose,
259                                                  boolean print,
260                                                  boolean auto)
261
262    {
263        InputStream in = null;
264        Pathname pathname = null;
265        Pathname truename = null;
266        pathname = new Pathname(filename);
267        LispObject bootPath = Site.getLispHome();
268        Pathname mergedPathname;
269        if (bootPath instanceof Pathname) {
270            mergedPathname = Pathname.mergePathnames(pathname, (Pathname)bootPath);
271        } else {
272            mergedPathname = pathname;
273        }
274        URL url = null;
275        truename = findLoadableFile(mergedPathname);
276        if (truename == null || truename.equals(NIL) || bootPath.equals(NIL)) {
277            // Make an attempt to use the boot classpath
278            String path = pathname.asEntryPath();
279            url = Lisp.class.getResource(path);
280            if (url == null || url.toString().endsWith("/")) {
281                url = Lisp.class.getResource(path + ".abcl");
282                if (url == null) {
283                    url = Lisp.class.getResource(path + ".lisp");
284                }
285            }
286            if (url == null) {
287                return error(new LispError("Failed to find loadable system file "
288                                           + "'" + path + "'"
289                                           + " in boot classpath."));
290            }               
291            if (!bootPath.equals(NIL)) {
292                Pathname urlPathname = new Pathname(url);
293                truename = findLoadableFile(urlPathname);
294                if (truename == null) {
295                    return error(new LispError("Failed to find loadable system file in boot classpath "
296                                               + "'" + url + "'"));
297                }
298            } else {
299                truename = null; // We can't represent the FASL in a Pathname (q.v. OSGi)
300            }
301        }
302
303        // Look for a init FASL inside a packed FASL
304        if (truename != null
305            && truename.type.writeToString().equals(COMPILE_FILE_TYPE) && Utilities.checkZipFile(truename))  {
306            Pathname init = new Pathname(truename.getNamestring());
307            init.type = COMPILE_FILE_INIT_FASL_TYPE;
308            LispObject t = Pathname.truename(init);
309            if (t instanceof Pathname) {
310                truename = (Pathname)t;
311            } else {
312                return error (new LispError("Failed to find loadable init FASL in "
313                                            + "'" + init.getNamestring() + "'"));
314            }
315        }
316
317        if (truename != null) {
318            in = truename.getInputStream();
319        } else { 
320            try {
321                Debug.assertTrue(url != null);
322                in = url.openStream();
323            } catch (IOException e) {
324                error(new FileError("Failed to load system file: " 
325                                    + "'" + filename + "'"
326                                    + " from URL: " 
327                                    + "'" + url + "'"));
328            } 
329        }
330
331        if (in != null) {
332            final LispThread thread = LispThread.currentThread();
333            final SpecialBindingsMark mark = thread.markSpecialBindings();
334            thread.bindSpecial(_WARN_ON_REDEFINITION_, NIL);
335            try {
336                Stream stream = new Stream(Symbol.SYSTEM_STREAM, in, Symbol.CHARACTER);
337                return loadFileFromStream(pathname, truename, stream,
338                                          verbose, print, auto);
339            } catch (FaslVersionMismatch e) {
340                StringBuilder sb =
341                    new StringBuilder("; Incorrect fasl version: ");
342                sb.append(truename);
343                System.err.println(sb.toString());
344            } finally {
345                thread.resetSpecialBindings(mark);
346                try {
347                    in.close();
348                }
349                catch (IOException e) {
350                    return error(new LispError(e.getMessage()));
351                }
352            }
353        }
354        return error(new FileError("Failed to load system file: " 
355                                   + "'" + filename + "'"
356                                   + " resolved as " 
357                                   + "'" + mergedPathname + "'" , 
358                                   truename));
359    }
360
361    // ### *fasl-version*
362    // internal symbol
363    static final Symbol _FASL_VERSION_ =
364        exportConstant("*FASL-VERSION*", PACKAGE_SYS, Fixnum.getInstance(35));
365
366    // ### *fasl-external-format*
367    // internal symbol
368    private static final Symbol _FASL_EXTERNAL_FORMAT_ =
369        internConstant("*FASL-EXTERNAL-FORMAT*", PACKAGE_SYS,
370                       new SimpleString("UTF-8"));
371
372    // ### *fasl-anonymous-package*
373    // internal symbol
374    /**
375     * This variable gets bound to a package with no name in which the
376     * reader can intern its uninterned symbols.
377     *
378     */
379    public static final Symbol _FASL_ANONYMOUS_PACKAGE_ =
380        internSpecial("*FASL-ANONYMOUS-PACKAGE*", PACKAGE_SYS, NIL);
381
382    // ### init-fasl &key version
383    private static final Primitive INIT_FASL = new init_fasl();
384    private static class init_fasl extends Primitive {
385        init_fasl() {
386            super("init-fasl", PACKAGE_SYS, true, "&key version");
387        }
388        @Override
389        public LispObject execute(LispObject first, LispObject second)
390
391        {
392            if (first == Keyword.VERSION) {
393                if (second.eql(_FASL_VERSION_.getSymbolValue())) {
394                    // OK
395                    final LispThread thread = LispThread.currentThread();
396                    thread.bindSpecial(_FASL_ANONYMOUS_PACKAGE_, NIL);
397                    thread.bindSpecial(_SOURCE_, NIL);
398                    return faslLoadStream(thread);
399                }
400            }
401            throw new FaslVersionMismatch(second);
402        }
403    }
404
405    private static final LispObject loadFileFromStream(Pathname pathname,
406                                                       Pathname truename,
407                                                       Stream in,
408                                                       boolean verbose,
409                                                       boolean print,
410                                                       boolean auto)
411        {
412            return loadFileFromStream(pathname == null ? NIL : pathname, 
413                                      truename == null ? NIL : truename, 
414                                      in, verbose, print, auto, false);
415    }
416
417    // A nil TRUENAME signals a load from stream which has no possible path
418    private static final LispObject loadFileFromStream(LispObject pathname,
419                                                       LispObject truename,
420                                                       Stream in,
421                                                       boolean verbose,
422                                                       boolean print,
423                                                       boolean auto,
424                                                       boolean returnLastResult)
425
426    {
427        long start = System.currentTimeMillis();
428        final LispThread thread = LispThread.currentThread();
429        final SpecialBindingsMark mark = thread.markSpecialBindings();
430        // "LOAD binds *READTABLE* and *PACKAGE* to the values they held before
431        // loading the file."
432        thread.bindSpecialToCurrentValue(Symbol.CURRENT_READTABLE);
433        thread.bindSpecialToCurrentValue(Symbol._PACKAGE_);
434        int loadDepth = Fixnum.getValue(_LOAD_DEPTH_.symbolValue(thread));
435        thread.bindSpecial(_LOAD_DEPTH_, Fixnum.getInstance(++loadDepth));
436        // Compiler policy.
437        thread.bindSpecialToCurrentValue(_SPEED_);
438        thread.bindSpecialToCurrentValue(_SPACE_);
439        thread.bindSpecialToCurrentValue(_SAFETY_);
440        thread.bindSpecialToCurrentValue(_DEBUG_);
441        thread.bindSpecialToCurrentValue(_EXPLAIN_);
442        final String prefix = getLoadVerbosePrefix(loadDepth);
443        try {
444            thread.bindSpecial(Symbol.LOAD_PATHNAME, pathname);
445
446            // The motivation behind the following piece of complexity
447            // is the need to preserve the semantics of
448            // *LOAD-TRUENAME* as always containing the truename of
449            // the current "Lisp file".  Since an ABCL packed FASL
450            // actually has a Lisp file (aka "the init FASL") and one
451            // or more Java classes from the compiler, we endeavor to
452            // make *LOAD-TRUENAME* refer to the "overall" truename so
453            // that a (LOAD *LOAD-TRUENAME*) would be equivalent to
454            // reloading the complete current "Lisp file".  If this
455            // value diverges from the "true" truename, we set the
456            // symbol SYS::*LOAD-TRUENAME-FASL* to that divergent
457            // value.  Currently the only code that uses this value is
458            // Lisp.readFunctionBytes().
459            Pathname truePathname = null;
460            if (!truename.equals(NIL)) {
461                truePathname = new Pathname(((Pathname)truename).getNamestring());
462                String type = truePathname.type.getStringValue();
463                if (type.equals(COMPILE_FILE_TYPE)
464                    || type.equals(COMPILE_FILE_INIT_FASL_TYPE.toString())) {
465                    thread.bindSpecial(Symbol.LOAD_TRUENAME_FASL, truePathname);
466                }
467                if (truePathname.type.getStringValue()
468                    .equals(COMPILE_FILE_INIT_FASL_TYPE.getStringValue())
469                    && truePathname.isJar()) {
470                    if (truePathname.device.cdr() != NIL ) {
471                        // set truename to the enclosing JAR
472                        truePathname.host = NIL;
473                        truePathname.directory = NIL;
474                        truePathname.name = NIL;
475                        truePathname.type = NIL;
476                        truePathname.invalidateNamestring();
477                    } else {
478                        // XXX There is something fishy in the asymmetry
479                        // between the "jar:jar:http:" and "jar:jar:file:"
480                        // cases but this currently passes the tests.
481                        if (!(truePathname.device.car() instanceof AbstractString)) {
482                            truePathname = (Pathname)truePathname.device.car();
483                            truePathname.invalidateNamestring();
484                        }
485                    }
486                    thread.bindSpecial(Symbol.LOAD_TRUENAME, truePathname);
487                } else {
488                    thread.bindSpecial(Symbol.LOAD_TRUENAME, truename);
489                }
490            } else {
491                thread.bindSpecial(Symbol.LOAD_TRUENAME, truename);
492            }
493            thread.bindSpecial(_SOURCE_,
494                               pathname != null ? pathname : NIL);
495            if (verbose) {
496                Stream out = getStandardOutput();
497                out.freshLine();
498                out._writeString(prefix);
499                out._writeString(auto ? " Autoloading " : " Loading ");
500                out._writeString(!truename.equals(NIL) ? truePathname.writeToString() : "stream");
501                out._writeLine(" ...");
502                out._finishOutput();
503                LispObject result = loadStream(in, print, thread, returnLastResult);
504                long elapsed = System.currentTimeMillis() - start;
505                out.freshLine();
506                out._writeString(prefix);
507                out._writeString(auto ? " Autoloaded " : " Loaded ");
508                out._writeString(!truename.equals(NIL) ? truePathname.writeToString() : "stream");
509                out._writeString(" (");
510                out._writeString(String.valueOf(((float)elapsed)/1000));
511                out._writeLine(" seconds)");
512                out._finishOutput();
513                return result;
514            } else
515                return loadStream(in, print, thread, returnLastResult);
516        }
517        finally {
518            thread.resetSpecialBindings(mark);
519        }
520    }
521
522    public static String getLoadVerbosePrefix(int loadDepth)
523    {
524        StringBuilder sb = new StringBuilder(";");
525        for (int i = loadDepth - 1; i-- > 0;)
526            sb.append(' ');
527        return sb.toString();
528    }
529
530    private static final LispObject loadStream(Stream in, boolean print,
531                                               LispThread thread)
532        {
533        return loadStream(in, print, thread, false);
534    }
535
536    private static final LispObject loadStream(Stream in, boolean print,
537                                               LispThread thread, boolean returnLastResult)
538
539    {
540        final SpecialBindingsMark mark = thread.markSpecialBindings();
541        thread.bindSpecial(_LOAD_STREAM_, in);
542        SpecialBinding sourcePositionBinding =
543            thread.bindSpecial(_SOURCE_POSITION_, Fixnum.ZERO);
544        try {
545            final Environment env = new Environment();
546            LispObject result = NIL;
547            while (true) {
548                sourcePositionBinding.value = Fixnum.getInstance(in.getOffset());
549                LispObject obj = in.read(false, EOF, false, thread);
550                if (obj == EOF)
551                    break;
552                result = eval(obj, env, thread);
553                if (print) {
554                    Stream out =
555                        checkCharacterOutputStream(Symbol.STANDARD_OUTPUT.symbolValue(thread));
556                    out._writeLine(result.writeToString());
557                    out._finishOutput();
558                }
559            }
560            if(returnLastResult) {
561                return result;
562            } else {
563                return T;
564            }
565        }
566        finally {
567            thread.resetSpecialBindings(mark);
568        }
569    }
570
571    static final LispObject faslLoadStream(LispThread thread)
572    {
573        Stream in = (Stream) _LOAD_STREAM_.symbolValue(thread);
574        final Environment env = new Environment();
575        final SpecialBindingsMark mark = thread.markSpecialBindings();
576        LispObject result = NIL;
577        try {
578            thread.bindSpecial(_FASL_ANONYMOUS_PACKAGE_, new Package());
579            thread.bindSpecial(AUTOLOADING_CACHE,
580                               AutoloadedFunctionProxy.makePreloadingContext());
581            in.setExternalFormat(_FASL_EXTERNAL_FORMAT_.symbolValue(thread));
582            while (true) {
583                LispObject obj = in.faslRead(false, EOF, true, thread);
584                if (obj == EOF)
585                    break;
586                result = eval(obj, env, thread);
587            }
588        }
589        finally {
590            thread.resetSpecialBindings(mark);
591        }
592        return result;
593        //There's no point in using here the returnLastResult flag like in
594        //loadStream(): this function is only called from init-fasl, which is
595        //only called from load, which already has its own policy for choosing
596        //whether to return T or the last value.
597    }
598
599
600    // ### %load filespec verbose print if-does-not-exist => generalized-boolean
601    private static final Primitive _LOAD = new _load();
602    private static class _load extends Primitive {
603        _load() {
604            super("%load", PACKAGE_SYS, false,
605                  "filespec verbose print if-does-not-exist");
606        }
607        @Override
608        public LispObject execute(LispObject filespec, LispObject verbose,
609                                  LispObject print, LispObject ifDoesNotExist)
610        {
611            return load(filespec, verbose, print, ifDoesNotExist, NIL);
612        }
613    }
614
615    // ### %load-returning-last-result filespec verbose print if-does-not-exist => object
616    private static final Primitive _LOAD_RETURNING_LAST_RESULT = new _load_returning_last_result();
617    private static class _load_returning_last_result extends Primitive {
618        _load_returning_last_result() {
619            super("%load-returning-last-result", PACKAGE_SYS, false,
620                  "filespec verbose print if-does-not-exist");
621        }
622        @Override
623        public LispObject execute(LispObject filespec, LispObject verbose,
624                                  LispObject print, LispObject ifDoesNotExist)
625            {
626            return load(filespec, verbose, print, ifDoesNotExist, T);
627        }
628    }
629
630    static final LispObject load(LispObject filespec,
631                                         LispObject verbose,
632                                         LispObject print,
633                                         LispObject ifDoesNotExist,
634                                         LispObject returnLastResult)
635        {
636        if (filespec instanceof Stream) {
637            if (((Stream)filespec).isOpen()) {
638                LispObject pathname;
639                if (filespec instanceof FileStream)
640                    pathname = ((FileStream)filespec).getPathname();
641                else
642                    pathname = NIL;
643                LispObject truename;
644                if (pathname instanceof Pathname)
645                    truename = pathname;
646                else
647                    truename = NIL;
648                return loadFileFromStream(pathname,
649                                          truename,
650                                          (Stream) filespec,
651                                          verbose != NIL,
652                                          print != NIL,
653                                          false,
654                                          returnLastResult != NIL);
655            }
656            // If stream is closed, fall through...
657        }
658        Pathname pathname = coerceToPathname(filespec);
659        if (pathname instanceof LogicalPathname)
660            pathname = LogicalPathname.translateLogicalPathname((LogicalPathname)pathname);
661        return load(pathname,
662                    verbose != NIL,
663                    print != NIL,
664                    ifDoesNotExist != NIL,
665                    returnLastResult != NIL);
666    }
667
668    // ### load-system-file
669    private static final Primitive LOAD_SYSTEM_FILE = new load_system_file();
670    private static class load_system_file extends Primitive {
671        load_system_file () {
672            super("load-system-file", PACKAGE_SYS, true);
673        }
674        @Override
675        public LispObject execute(LispObject arg)
676        {
677            final LispThread thread = LispThread.currentThread();
678            return loadSystemFile(arg.getStringValue(),
679                                  Symbol.LOAD_VERBOSE.symbolValue(thread) != NIL,
680                                  Symbol.LOAD_PRINT.symbolValue(thread) != NIL,
681                                  false);
682        }
683    }
684
685    private static class FaslVersionMismatch extends Error
686    {
687        private final LispObject version;
688
689        public FaslVersionMismatch(LispObject version)
690        {
691            this.version = version;
692        }
693
694        public LispObject getVersion()
695        {
696            return version;
697        }
698    }
699}
Note: See TracBrowser for help on using the repository browser.