source: branches/0.22.x/abcl/src/org/armedbear/lisp/Load.java

Last change on this file was 12760, checked in by ehuelsmann, 14 years ago

Remove separate FaslVersionMismatch? exception in favor of
raising a lispy error directly.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 29.4 KB
Line 
1/*
2 * Load.java
3 *
4 * Copyright (C) 2002-2007 Peter Graves
5 * $Id: Load.java 12760 2010-06-20 20:38:08Z ehuelsmann $
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 abclPathname;  // fasl file is newer
93              } else {
94                  return lispPathname;
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        finally {
202            if (in != null) {
203                try {
204                   in.close();
205                }
206                catch (IOException e) {
207                    return error(new LispError(e.getMessage()));
208                }
209            }
210        }
211    }
212
213    public static final LispObject loadSystemFile(String filename, boolean auto)
214
215    {
216        LispThread thread = LispThread.currentThread();
217        if (auto) {
218            final SpecialBindingsMark mark = thread.markSpecialBindings();
219            thread.bindSpecial(Symbol.CURRENT_READTABLE,
220                               STANDARD_READTABLE.symbolValue(thread));
221            thread.bindSpecial(Symbol._PACKAGE_, PACKAGE_CL_USER);
222            try {
223                return loadSystemFile(filename,
224                                      _AUTOLOAD_VERBOSE_.symbolValue(thread) != NIL,
225                                      Symbol.LOAD_PRINT.symbolValue(thread) != NIL,
226                                      auto);
227            }
228            finally {
229                thread.resetSpecialBindings(mark);
230            }
231        } else {
232            return loadSystemFile(filename,
233                                  Symbol.LOAD_VERBOSE.symbolValue(thread) != NIL,
234                                  Symbol.LOAD_PRINT.symbolValue(thread) != NIL,
235                                  auto);
236        }
237    }
238
239    private static final Symbol FASL_LOADER = PACKAGE_SYS.intern("*FASL-LOADER*");
240    static final LispObject COMPILE_FILE_INIT_FASL_TYPE = new SimpleString("_");
241
242    public static final LispObject loadSystemFile(final String filename,
243                                                  boolean verbose,
244                                                  boolean print,
245                                                  boolean auto)
246
247    {
248        InputStream in = null;
249        Pathname pathname = null;
250        Pathname truename = null;
251        pathname = new Pathname(filename);
252        LispObject bootPath = Site.getLispHome();
253        Pathname mergedPathname;
254        if (bootPath instanceof Pathname) {
255            mergedPathname = Pathname.mergePathnames(pathname, (Pathname)bootPath);
256        } else {
257            mergedPathname = pathname;
258        }
259        URL url = null;
260        truename = findLoadableFile(mergedPathname);
261        if (truename == null || truename.equals(NIL) || bootPath.equals(NIL)) {
262            // Make an attempt to use the boot classpath
263            String path = pathname.asEntryPath();
264            url = Lisp.class.getResource(path);
265            if (url == null || url.toString().endsWith("/")) {
266                url = Lisp.class.getResource(path.replace('-', '_') + ".abcl");
267                if (url == null) {
268                    url = Lisp.class.getResource(path + ".lisp");
269                }
270            }
271            if (url == null) {
272                return error(new LispError("Failed to find loadable system file "
273                                           + "'" + path + "'"
274                                           + " in boot classpath."));
275            }               
276            if (!bootPath.equals(NIL)) {
277                Pathname urlPathname = new Pathname(url);
278                truename = findLoadableFile(urlPathname);
279                if (truename == null) {
280                    return error(new LispError("Failed to find loadable system file in boot classpath "
281                                               + "'" + url + "'"));
282                }
283            } else {
284                truename = null; // We can't represent the FASL in a Pathname (q.v. OSGi)
285            }
286        }
287
288        // Look for a init FASL inside a packed FASL
289        if (truename != null
290            && truename.type.writeToString().equals(COMPILE_FILE_TYPE) && Utilities.checkZipFile(truename))  {
291            Pathname init = new Pathname(truename.getNamestring());
292            init.type = COMPILE_FILE_INIT_FASL_TYPE;
293            LispObject t = Pathname.truename(init);
294            if (t instanceof Pathname) {
295                truename = (Pathname)t;
296            } else {
297                return error (new LispError("Failed to find loadable init FASL in "
298                                            + "'" + init.getNamestring() + "'"));
299            }
300        }
301
302        if (truename != null) {
303            in = truename.getInputStream();
304        } else { 
305            try {
306                Debug.assertTrue(url != null);
307                in = url.openStream();
308            } catch (IOException e) {
309                error(new FileError("Failed to load system file: " 
310                                    + "'" + filename + "'"
311                                    + " from URL: " 
312                                    + "'" + url + "'"));
313            } 
314        }
315
316        if (in != null) {
317            final LispThread thread = LispThread.currentThread();
318            final SpecialBindingsMark mark = thread.markSpecialBindings();
319            thread.bindSpecial(_WARN_ON_REDEFINITION_, NIL);
320      thread.bindSpecial(FASL_LOADER, NIL);
321            try {
322                Stream stream = new Stream(Symbol.SYSTEM_STREAM, in, Symbol.CHARACTER);
323                return loadFileFromStream(pathname, truename, stream,
324                                          verbose, print, auto);
325            } finally {
326                thread.resetSpecialBindings(mark);
327                try {
328                    in.close();
329                }
330                catch (IOException e) {
331                    return error(new LispError(e.getMessage()));
332                }
333            }
334        }
335        return error(new FileError("Failed to load system file: " 
336                                   + "'" + filename + "'"
337                                   + " resolved as " 
338                                   + "'" + mergedPathname + "'" , 
339                                   truename));
340    }
341
342    // ### *fasl-version*
343    // internal symbol
344    static final Symbol _FASL_VERSION_ =
345        exportConstant("*FASL-VERSION*", PACKAGE_SYS, Fixnum.getInstance(36));
346
347    // ### *fasl-external-format*
348    // internal symbol
349    private static final Symbol _FASL_EXTERNAL_FORMAT_ =
350        internConstant("*FASL-EXTERNAL-FORMAT*", PACKAGE_SYS,
351                       new SimpleString("UTF-8"));
352
353    // ### *fasl-uninterned-symbols*
354    // internal symbol
355    /**
356     * This variable gets bound to NIL upon loading a FASL, but
357     * gets set to a vector of symbols as one of the first actions
358     * by the FASL itself.
359     *
360     */
361    public static final Symbol _FASL_UNINTERNED_SYMBOLS_ =
362        internSpecial("*FASL-UNINTERNED-SYMBOLS*", PACKAGE_SYS, NIL);
363
364    // Function to access the uninterned symbols "array"
365    public final static LispObject getUninternedSymbol(int n) {
366        LispThread thread = LispThread.currentThread();
367        LispObject uninternedSymbols =
368            Load._FASL_UNINTERNED_SYMBOLS_.symbolValue(thread);
369
370        if (! (uninternedSymbols instanceof Cons)) // it must be a vector
371            return uninternedSymbols.AREF(n);
372
373        // During normal loading, we won't get to this bit, however,
374        // with eval-when processing, we may need to fall back to
375        // *FASL-UNINTERNED-SYMBOLS* being an alist structure
376        LispObject label = LispInteger.getInstance(n);
377        while (uninternedSymbols != NIL)
378            {
379                LispObject item = uninternedSymbols.car();
380                if (label.eql(item.cdr()))
381                  return item.car();
382
383                uninternedSymbols = uninternedSymbols.cdr();
384            }
385        return error(new LispError("No entry for uninterned symbol."));
386    }
387
388
389    // ### init-fasl &key version
390    private static final Primitive INIT_FASL = new init_fasl();
391    private static class init_fasl extends Primitive {
392        init_fasl() {
393            super("init-fasl", PACKAGE_SYS, true, "&key version");
394        }
395        @Override
396        public LispObject execute(LispObject first, LispObject second)
397
398        {
399            final LispThread thread = LispThread.currentThread();
400            if (first == Keyword.VERSION) {
401                if (second.eql(_FASL_VERSION_.getSymbolValue())) {
402                    // OK
403                    thread.bindSpecial(_FASL_UNINTERNED_SYMBOLS_, NIL);
404                    thread.bindSpecial(_SOURCE_, NIL);
405                    return faslLoadStream(thread);
406                }
407            }
408            return
409                error(new SimpleError("FASL version mismatch; found '"
410                        + second.writeToString() + "' but expected '"
411                        + _FASL_VERSION_.getSymbolValue().writeToString()
412                        + "' in "
413                        + Symbol.LOAD_PATHNAME.symbolValue(thread).writeToString()));
414        }
415    }
416
417    private static final LispObject loadFileFromStream(Pathname pathname,
418                                                       Pathname truename,
419                                                       Stream in,
420                                                       boolean verbose,
421                                                       boolean print,
422                                                       boolean auto)
423        {
424            return loadFileFromStream(pathname == null ? NIL : pathname,
425                                      truename == null ? NIL : truename,
426                                      in, verbose, print, auto, false);
427    }
428
429    private static Symbol[] savedSpecials =
430        new Symbol[] { // CLHS Specified
431                       Symbol.CURRENT_READTABLE, Symbol._PACKAGE_,
432                       // Compiler policy
433                       _SPEED_, _SPACE_, _SAFETY_, _DEBUG_, _EXPLAIN_ };
434
435    // A nil TRUENAME signals a load from stream which has no possible path
436    private static final LispObject loadFileFromStream(LispObject pathname,
437                                                       LispObject truename,
438                                                       Stream in,
439                                                       boolean verbose,
440                                                       boolean print,
441                                                       boolean auto,
442                                                       boolean returnLastResult)
443
444    {
445        long start = System.currentTimeMillis();
446        final LispThread thread = LispThread.currentThread();
447        final SpecialBindingsMark mark = thread.markSpecialBindings();
448
449        for (Symbol special : savedSpecials)
450            thread.bindSpecialToCurrentValue(special);
451
452        int loadDepth = Fixnum.getValue(_LOAD_DEPTH_.symbolValue(thread));
453        thread.bindSpecial(_LOAD_DEPTH_, Fixnum.getInstance(++loadDepth));
454        final String prefix = getLoadVerbosePrefix(loadDepth);
455        try {
456            thread.bindSpecial(Symbol.LOAD_PATHNAME, pathname);
457
458            // The motivation behind the following piece of complexity
459            // is the need to preserve the semantics of
460            // *LOAD-TRUENAME* as always containing the truename of
461            // the current "Lisp file".  Since an ABCL packed FASL
462            // actually has a Lisp file (aka "the init FASL") and one
463            // or more Java classes from the compiler, we endeavor to
464            // make *LOAD-TRUENAME* refer to the "overall" truename so
465            // that a (LOAD *LOAD-TRUENAME*) would be equivalent to
466            // reloading the complete current "Lisp file".  If this
467            // value diverges from the "true" truename, we set the
468            // symbol SYS::*LOAD-TRUENAME-FASL* to that divergent
469            // value.  Currently the only code that uses this value is
470            // Lisp.readFunctionBytes().
471            Pathname truePathname = null;
472            if (!truename.equals(NIL)) {
473                truePathname = new Pathname(((Pathname)truename).getNamestring());
474                String type = truePathname.type.getStringValue();
475                if (type.equals(COMPILE_FILE_TYPE)
476                    || type.equals(COMPILE_FILE_INIT_FASL_TYPE.toString())) {
477                    Pathname truenameFasl = new Pathname(truePathname);
478                    thread.bindSpecial(Symbol.LOAD_TRUENAME_FASL, truenameFasl);
479                }
480                if (truePathname.type.getStringValue()
481                    .equals(COMPILE_FILE_INIT_FASL_TYPE.getStringValue())
482                    && truePathname.isJar()) {
483                    if (truePathname.device.cdr() != NIL ) {
484                        // We set *LOAD-TRUENAME* to the argument that
485                        // a user would pass to LOAD.
486                        Pathname enclosingJar = (Pathname)truePathname.device.cdr().car();
487                        truePathname.device = new Cons(truePathname.device.car(), NIL);
488                        truePathname.host = NIL;
489                        truePathname.directory = enclosingJar.directory;
490                        if (truePathname.directory.car().equals(Keyword.RELATIVE)) {
491                            truePathname.directory.setCar(Keyword.ABSOLUTE);
492                        }
493                        truePathname.name = enclosingJar.name;
494                        truePathname.type = enclosingJar.type;
495                        truePathname.invalidateNamestring();
496                    } else {
497                        // XXX There is something fishy in the asymmetry
498                        // between the "jar:jar:http:" and "jar:jar:file:"
499                        // cases but this currently passes the tests.
500                        if (!(truePathname.device.car() instanceof AbstractString)) {
501                            truePathname = (Pathname)truePathname.device.car();
502                            truePathname.invalidateNamestring();
503                        }
504                    }
505                    thread.bindSpecial(Symbol.LOAD_TRUENAME, truePathname);
506                } else {
507                    thread.bindSpecial(Symbol.LOAD_TRUENAME, truename);
508                }
509            } else {
510                thread.bindSpecial(Symbol.LOAD_TRUENAME, truename);
511            }
512            thread.bindSpecial(_SOURCE_,
513                               pathname != null ? pathname : NIL);
514            if (verbose) {
515                Stream out = getStandardOutput();
516                out.freshLine();
517                out._writeString(prefix);
518                out._writeString(auto ? " Autoloading " : " Loading ");
519                out._writeString(!truename.equals(NIL) ? truePathname.writeToString() : "stream");
520                out._writeLine(" ...");
521                out._finishOutput();
522                LispObject result = loadStream(in, print, thread, returnLastResult);
523                long elapsed = System.currentTimeMillis() - start;
524                out.freshLine();
525                out._writeString(prefix);
526                out._writeString(auto ? " Autoloaded " : " Loaded ");
527                out._writeString(!truename.equals(NIL) ? truePathname.writeToString() : "stream");
528                out._writeString(" (");
529                out._writeString(String.valueOf(((float)elapsed)/1000));
530                out._writeLine(" seconds)");
531                out._finishOutput();
532                return result;
533            } else
534                return loadStream(in, print, thread, returnLastResult);
535        }
536        finally {
537            thread.resetSpecialBindings(mark);
538        }
539    }
540
541    public static String getLoadVerbosePrefix(int loadDepth)
542    {
543        StringBuilder sb = new StringBuilder(";");
544        for (int i = loadDepth - 1; i-- > 0;)
545            sb.append(' ');
546        return sb.toString();
547    }
548
549    private static final LispObject loadStream(Stream in, boolean print,
550                                               LispThread thread, boolean returnLastResult)
551
552    {
553        final SpecialBindingsMark mark = thread.markSpecialBindings();
554        thread.bindSpecial(_LOAD_STREAM_, in);
555        SpecialBinding sourcePositionBinding =
556            thread.bindSpecial(_SOURCE_POSITION_, Fixnum.ZERO);
557        try {
558            final Environment env = new Environment();
559            LispObject result = NIL;
560            while (true) {
561                sourcePositionBinding.value = Fixnum.getInstance(in.getOffset());
562                LispObject obj = in.read(false, EOF, false,
563                                         thread, Stream.currentReadtable);
564                if (obj == EOF)
565                    break;
566    result = eval(obj, env, thread);
567                if (print) {
568                    Stream out =
569                        checkCharacterOutputStream(Symbol.STANDARD_OUTPUT.symbolValue(thread));
570                    out._writeLine(result.writeToString());
571                    out._finishOutput();
572                }
573            }
574            if(returnLastResult) {
575                return result;
576            } else {
577                return T;
578            }
579        }
580        finally {
581            thread.resetSpecialBindings(mark);
582        }
583    }
584
585    static final LispObject faslLoadStream(LispThread thread)
586    {
587        Stream in = (Stream) _LOAD_STREAM_.symbolValue(thread);
588        final Environment env = new Environment();
589        final SpecialBindingsMark mark = thread.markSpecialBindings();
590        LispObject result = NIL;
591        try {
592            thread.bindSpecial(AUTOLOADING_CACHE,
593                               AutoloadedFunctionProxy.makePreloadingContext());
594            in.setExternalFormat(_FASL_EXTERNAL_FORMAT_.symbolValue(thread));
595            while (true) {
596                LispObject obj = in.read(false, EOF, true, thread, Stream.faslReadtable);
597                if (obj == EOF)
598                    break;
599                result = eval(obj, env, thread);
600            }
601        }
602        finally {
603            thread.resetSpecialBindings(mark);
604        }
605        return result;
606        //There's no point in using here the returnLastResult flag like in
607        //loadStream(): this function is only called from init-fasl, which is
608        //only called from load, which already has its own policy for choosing
609        //whether to return T or the last value.
610    }
611
612
613    // ### %load filespec verbose print if-does-not-exist => generalized-boolean
614    private static final Primitive _LOAD = new _load();
615    private static class _load extends Primitive {
616        _load() {
617            super("%load", PACKAGE_SYS, false,
618                  "filespec verbose print if-does-not-exist");
619        }
620        @Override
621        public LispObject execute(LispObject filespec, LispObject verbose,
622                                  LispObject print, LispObject ifDoesNotExist)
623        {
624            return load(filespec, verbose, print, ifDoesNotExist, NIL);
625        }
626    }
627
628    // ### %load-returning-last-result filespec verbose print if-does-not-exist => object
629    private static final Primitive _LOAD_RETURNING_LAST_RESULT = new _load_returning_last_result();
630    private static class _load_returning_last_result extends Primitive {
631        _load_returning_last_result() {
632            super("%load-returning-last-result", PACKAGE_SYS, false,
633                  "filespec verbose print if-does-not-exist");
634        }
635        @Override
636        public LispObject execute(LispObject filespec, LispObject verbose,
637                                  LispObject print, LispObject ifDoesNotExist)
638            {
639            return load(filespec, verbose, print, ifDoesNotExist, T);
640        }
641    }
642
643    static final LispObject load(LispObject filespec,
644                                         LispObject verbose,
645                                         LispObject print,
646                                         LispObject ifDoesNotExist,
647                                         LispObject returnLastResult)
648        {
649        if (filespec instanceof Stream) {
650            if (((Stream)filespec).isOpen()) {
651                LispObject pathname;
652                if (filespec instanceof FileStream)
653                    pathname = ((FileStream)filespec).getPathname();
654                else
655                    pathname = NIL;
656                LispObject truename;
657                if (pathname instanceof Pathname)
658                    truename = pathname;
659                else
660                    truename = NIL;
661                return loadFileFromStream(pathname,
662                                          truename,
663                                          (Stream) filespec,
664                                          verbose != NIL,
665                                          print != NIL,
666                                          false,
667                                          returnLastResult != NIL);
668            }
669            // If stream is closed, fall through...
670        }
671        Pathname pathname = coerceToPathname(filespec);
672        if (pathname instanceof LogicalPathname)
673            pathname = LogicalPathname.translateLogicalPathname((LogicalPathname)pathname);
674        return load(pathname,
675                    verbose != NIL,
676                    print != NIL,
677                    ifDoesNotExist != NIL,
678                    returnLastResult != NIL);
679    }
680
681    // ### load-system-file
682    private static final Primitive LOAD_SYSTEM_FILE = new load_system_file();
683    private static class load_system_file extends Primitive {
684        load_system_file () {
685            super("load-system-file", PACKAGE_SYS, true);
686        }
687        @Override
688        public LispObject execute(LispObject arg)
689        {
690            final LispThread thread = LispThread.currentThread();
691            return loadSystemFile(arg.getStringValue(),
692                                  Symbol.LOAD_VERBOSE.symbolValue(thread) != NIL,
693                                  Symbol.LOAD_PRINT.symbolValue(thread) != NIL,
694                                  false);
695        }
696    }
697}
Note: See TracBrowser for help on using the repository browser.