diff options
-rw-r--r-- | eval.c | 8 | ||||
-rw-r--r-- | eval.h | 3 | ||||
-rw-r--r-- | match.c | 4 | ||||
-rw-r--r-- | parser.c | 26 | ||||
-rw-r--r-- | parser.h | 3 | ||||
-rw-r--r-- | stdlib/doc-syms.tl | 1 | ||||
-rw-r--r-- | txr.1 | 92 | ||||
-rw-r--r-- | txr.c | 13 |
8 files changed, 131 insertions, 19 deletions
@@ -102,7 +102,7 @@ val vector_lit_s, vec_list_s, tree_lit_s, tree_construct_s; val macro_time_s, macrolet_s; val defsymacro_s, symacrolet_s, prof_s, switch_s, struct_s; val fbind_s, lbind_s, flet_s, labels_s; -val load_path_s, load_hooks_s, load_recursive_s; +val load_path_s, load_hooks_s, load_recursive_s, load_search_dirs_s; val load_time_s, load_time_lit_s; val eval_only_s, compile_only_s; val const_foldable_s; @@ -4669,13 +4669,13 @@ val load(val target) cat_str(nappend2(sub_list(split_str(parent, lit("/")), zero, negone), cons(target, nil)), lit("/"))); - val name, stream; + val name = target, stream; val txr_lisp_p = t; val saved_dyn_env = dyn_env; val load_dyn_env = make_env(nil, nil, dyn_env); val rec = cdr(lookup_var(nil, load_recursive_s)); - open_txr_file(path, &txr_lisp_p, &name, &stream, self); + open_txr_file(path, &txr_lisp_p, &name, &stream, t, self); if (match_str(or2(get_line(stream), null_string), lit("#!"), nil)) parser_set_lineno(self, stream, two); @@ -6751,6 +6751,7 @@ void eval_init(void) load_path_s = intern(lit("*load-path*"), user_package); load_hooks_s = intern(lit("*load-hooks*"), user_package); load_recursive_s = intern(lit("*load-recursive*"), system_package); + load_search_dirs_s = intern(lit("*load-search-dirs*"), user_package); load_time_s = intern(lit("load-time"), user_package); load_time_lit_s = intern(lit("load-time-lit"), system_package); eval_only_s = intern(lit("eval-only"), user_package); @@ -7081,6 +7082,7 @@ void eval_init(void) reg_var(load_path_s, nil); reg_symacro(intern(lit("self-load-path"), user_package), load_path_s); reg_var(load_recursive_s, nil); + reg_var(load_search_dirs_s, nil); reg_var(load_hooks_s, nil); reg_fun(intern(lit("expand"), user_package), func_n2o(no_warn_expand, 1)); reg_fun(intern(lit("expand*"), user_package), func_n2o(expand, 1)); @@ -34,12 +34,13 @@ extern val eval_error_s, if_s, call_s, identity_s; extern val eq_s, eql_s, equal_s, less_s; extern val car_s, cdr_s; extern val last_form_evaled; -extern val load_path_s, load_hooks_s, load_recursive_s; +extern val load_path_s, load_hooks_s, load_recursive_s, load_search_dirs_s; extern val special_s, struct_s; extern val dyn_env; #define load_path (deref(lookup_var_l(nil, load_path_s))) +#define load_search_dirs (deref(lookup_var_l(nil, load_search_dirs_s))) NORETURN val eval_error(val ctx, val fmt, ...); val ctx_form(val obj); @@ -4609,14 +4609,14 @@ static val v_load(match_files_ctx *c) cat_str(nappend2(sub_list(split_str(parent, lit("/")), zero, negone), cons(target, nil)), lit("/"))); - val stream, name; + val stream, name = target; val txr_lisp_p = nil; val ret = nil; val saved_dyn_env = dyn_env; val load_dyn_env = make_env(nil, nil, dyn_env); val rec = cdr(lookup_var(nil, load_recursive_s)); - open_txr_file(path, &txr_lisp_p, &name, &stream, self); + open_txr_file(path, &txr_lisp_p, &name, &stream, t, self); uw_simple_catch_begin; @@ -513,7 +513,8 @@ val parser_circ_ref(parser_t *p, val num) } void open_txr_file(val first_try_path, val *txr_lisp_p, - val *orig_in_resolved_out, val *stream, val self) + val *orig_in_resolved_out, val *stream, + val search_dirs, val self) { enum { none, tl, tlo, txr } suffix; @@ -599,11 +600,26 @@ void open_txr_file(val first_try_path, val *txr_lisp_p, } if (in == 0) { + val try_next; #ifdef ENOENT except: #endif - uw_ethrowf(errno_to_file_error(errno), - lit("unable to open ~a"), try_path, nao); + if (abs_path_p(*orig_in_resolved_out)) + search_dirs = nil; + else if (search_dirs == t) + search_dirs = load_search_dirs; + +#ifdef ENOENT + if (errno != ENOENT || search_dirs == nil) +#else + if (search_dirs == nil) +#endif + uw_ethrowf(errno_to_file_error(errno), + lit("~a: ~a not found"), self, *orig_in_resolved_out, nao); + try_next = path_cat(pop(&search_dirs), *orig_in_resolved_out); + open_txr_file(try_next, txr_lisp_p, orig_in_resolved_out, stream, + search_dirs, self); + return; } found: @@ -899,14 +915,14 @@ static void report_security_problem(val name) static void load_rcfile(val name) { val self = lit("listener"); - val resolved_name; + val resolved_name = name; val lisp_p = t; val stream = nil; val path_private_to_me_p = intern(lit("path-private-to-me-p"), user_package); uw_catch_begin (catch_error, sy, va); - open_txr_file(name, &lisp_p, &resolved_name, &stream, self); + open_txr_file(name, &lisp_p, &resolved_name, &stream, nil, self); if (stream) { if (!funcall1(path_private_to_me_p, stream)) { @@ -102,7 +102,8 @@ void yyset_extra(parser_t *, yyscan_t); void yyset_hold_char(yyscan_t, int); void parser_l_init(void); void open_txr_file(val first_try_path, val *txr_lisp_p, - val *orig_in_resolved_out, val *stream, val self); + val *orig_in_resolved_out, val *stream, + val search_dirs, val self); void prime_parser(parser_t *, val name, enum prime_parser); void prime_parser_post(parser_t *, enum prime_parser); #ifdef SPACE diff --git a/stdlib/doc-syms.tl b/stdlib/doc-syms.tl index 53d01739..037675db 100644 --- a/stdlib/doc-syms.tl +++ b/stdlib/doc-syms.tl @@ -19,6 +19,7 @@ ("*listener-sel-inclusive-p*" "N-02E4924F") ("*load-hooks*" "N-02D09712") ("*load-path*" "N-01D1DB58") + ("*load-search-dirs*" "N-004CCBF6") ("*match-macro*" "N-012A473F") ("*opt-level*" "N-03FDEBBC") ("*package*" "N-000CBBA0") @@ -9098,6 +9098,19 @@ is tried, and so forth, as described for the .code load function. +If these initial attempts to find the file fail, and the failure +is due to the file not being found rather than some other problem such as a +permission error, and +.meta expr +isn't an absolute path according to +.codn abs-path-p , +then additional attempts are made by searching for the file in the +list of directories given in the +.code *load-search-dirs* +variable. Details are given in the description of the \*(TL +.code load +function. + Both the .code load and @@ -77572,8 +77585,33 @@ with the resulting path. If that file is not found, then the suffix .code .tl is similarly tried. -If an unsuffixed file is opened, its contents are treated as interpreted Lisp. -Files ending in +If the above +.I "initial attempts" +to find the file fail, and the failure +is due to the file not being found rather than some other problem such as a +permission error, and +.meta target +isn't an absolute path according to +.codn abs-path-p , +then additional attempts are made by searching for the file in the +list of directories given in the +.code *load-search-dirs* +variable. For each directory taken from this variable, the directory +is combined with the relative +.meta target +as if using the +.code path-cat +function, and the resulting path is tried, with all the same suffix probing +that is performed by the initial attempts. If any such a path is pure relative, +it is interpreted relative to the current working directory, and not relative +.codn *load-path* : +only the initial attempts have that special behavior. + +An exception is thrown if a file is not found, or if any attempt to open +a file results in an error other than non-existence. + +If an unsuffixed file is successfully opened, its contents are treated as +interpreted Lisp. Files ending in .code .txr_profile are also treated as interpreted Lisp. Files ending in .code .tlo @@ -77729,6 +77767,40 @@ parsing and processing of a loaded \*(TX source file. Also, during the processing of the profile file (see Interactive Profile File), the variable is bound to the name of that file. +.coNP Special variable @ *load-search-dirs* +.desc +The +.code *load-search-dirs* +variable holds a list of directories which are searched for a file to be +loaded by the +.code load +function, the +.code @(load) +and +.code @(include) +directives, as well as by \*(TX's command line processing. + +Each of these situations first searches for a file in its characteristic +way. If that fails due to the file not being found, and the name is +a relative path, then the directories in +.code *load-search-dirs* +are probed, in order. + +The variable is initialized to a list which contains exactly one directory: a +.code lib/ +directory dynamically calculated relative to \*(TX the executable location. +Then intent is that third-party library modules may be installed there, +and easily found by +.codn load . +For more information, see the section Deployment Directory Structure. + +The +.code *load-search-dirs* +isn't influenced by any environment variables, which is deliberate. +If a system has multiple installations of different versions of \*(TX +in different locations, an environment variable intended for one installation +could be mistakenly used by the others, resulting in chaos. + .coNP Special variable @ *load-hooks* .desc The @@ -87610,6 +87682,8 @@ The executable may be renamed, it need not be called .../stdlib/cadr.tlo .../stdlib/except.tl ... + .../share/txr/lib/... + .brev The above structure is assumed if the executable finds itself @@ -87626,11 +87700,19 @@ the following structure is expected: .../stdlib/cadr.tl .../stdlib/cadr.tlo .../stdlib/except.tl - ... + ... + .../lib/... .brev -Note that this has changed starting in \*(TX 264. Older versions -of \*(TX, when the executable is not in a directory named +The +.strn lib/ +directory shown above is for third-party libraries. +This is the directory indicated in the default value of the +.code *load-search-dirs* +special variable. The directory is not required to exist. + +Note that this structure had changed starting in \*(TX 264. Older versions of +\*(TX, when the executable is not in a directory named .strn bin , expect the following structure: @@ -345,6 +345,14 @@ static void sysroot_init(void) lit("share/txr/stdlib/"), lit("stdlib/"))); + { + loc lsd = lookup_var_l(nil, load_search_dirs_s); + set(lsd, cons(sysroot(if3(share_txr_stdlib, + lit("share/txr/lib/"), + lit("lib/"))), + nil)); + } + reg_varl(intern(lit("stdlib"), user_package), stdlib_path); reg_varl(intern(lit("*txr-version*"), user_package), toint(lit(TXR_VER), nil)); @@ -599,7 +607,7 @@ int txr_main(int argc, char **argv) if (car(arg) != chr('-')) { if (!parse_stream) { spec_file_str = arg; - open_txr_file(arg, &txr_lisp_p, &spec_file_str, &parse_stream, self); + open_txr_file(arg, &txr_lisp_p, &spec_file_str, &parse_stream, t, self); simulate_setuid_setgid(parse_stream); dyn_env = make_env(nil, nil, dyn_env); env_vbind(dyn_env, load_path_s, spec_file_str); @@ -968,8 +976,9 @@ int txr_main(int argc, char **argv) return EXIT_FAILURE; } if (wcscmp(c_str(spec_file, self), L"-") != 0) { + spec_file_str = spec_file; open_txr_file(spec_file, &txr_lisp_p, &spec_file_str, - &parse_stream, self); + &parse_stream, t, self); simulate_setuid_setgid(parse_stream); dyn_env = make_env(nil, nil, dyn_env); env_vbind(dyn_env, load_path_s, spec_file_str); |