diff --git a/src/pl-ext.c b/src/pl-ext.c index adc8c62467..4a5350a6c8 100644 --- a/src/pl-ext.c +++ b/src/pl-ext.c @@ -196,13 +196,11 @@ static const PL_extension foreigns[] = { #define SIGNATURE_SEED (0x1a3be34a) static unsigned int -predicate_signature(const Definition def) +predicate_signature(const char *name, size_t arity, uint64_t flags) { char str[256]; - Ssprintf(str, "%s/%zd/0x%" PRIx64, - stringAtom(def->functor->name), - def->functor->arity, - def->flags); + Ssnprintf(str, sizeof(str), "%s/%zd/0x%" PRIx64, + name, arity, flags); return MurmurHashAligned2(str, strlen(str), SIGNATURE_SEED); } @@ -303,46 +301,133 @@ cleanupExtensions(void) ext_head = ext_tail = NULL; } +static uint64_t +builtin_pred_flags(short regflags, uint64_t defflags) +{ uint64_t flags = defflags|P_FOREIGN|HIDE_CHILDS|P_LOCKED; + if ( regflags & PL_FA_NOTRACE ) flags &= ~TRACE_ME; + if ( regflags & PL_FA_TRANSPARENT ) flags |= P_TRANSPARENT; + if ( regflags & PL_FA_NONDETERMINISTIC ) flags |= P_NONDET; + if ( regflags & PL_FA_VARARGS ) flags |= P_VARARG; + if ( regflags & PL_FA_CREF ) flags |= P_FOREIGN_CREF; + if ( regflags & PL_FA_ISO ) flags |= P_ISO; + if ( regflags & PL_FA_SIG_ATOMIC ) flags |= P_SIG_ATOMIC; + + return flags; +} static void -registerBuiltins(const PL_extension *f) +registerBuiltins(const PL_extension *f, bool signonly) { Module m = MODULE_system; for(; f->predicate_name; f++) - { Procedure proc; - atom_t name = PL_new_atom(f->predicate_name); - functor_t fdef = lookupFunctorDef(name, f->arity); - - PL_unregister_atom(name); - if ( (proc = lookupProcedure(fdef, m)) ) - { Definition def = proc->definition; - set(def, P_FOREIGN|HIDE_CHILDS|P_LOCKED); - - if ( f->flags & PL_FA_NOTRACE ) clear(def, TRACE_ME); - if ( f->flags & PL_FA_TRANSPARENT ) set(def, P_TRANSPARENT); - if ( f->flags & PL_FA_NONDETERMINISTIC ) set(def, P_NONDET); - if ( f->flags & PL_FA_VARARGS ) set(def, P_VARARG); - if ( f->flags & PL_FA_CREF ) set(def, P_FOREIGN_CREF); - if ( f->flags & PL_FA_ISO ) set(def, P_ISO); - if ( f->flags & PL_FA_SIG_ATOMIC ) set(def, P_SIG_ATOMIC); - - def->impl.foreign.function = f->function; - createForeignSupervisor(def, f->function); - - if ( !extensions_loaded ) - GD->foreign.signature ^= predicate_signature(def); + { bool userpred = f->predicate_name[0] != '$'; + uint64_t defflags = userpred ? TRACE_ME : 0; + uint64_t flags = builtin_pred_flags(f->flags, defflags); + + if ( signonly ) + { if ( !extensions_loaded ) + GD->foreign.signature ^= predicate_signature(f->predicate_name, + f->arity, + flags); } else - { assert(0); + { Procedure proc; + atom_t name = PL_new_atom(f->predicate_name); + functor_t fdef = lookupFunctorDef(name, f->arity); + + PL_unregister_atom(name); + if ( (proc = lookupProcedure(fdef, m)) ) + { Definition def = proc->definition; + assert(def->flags == defflags); + def->flags = flags; + def->impl.foreign.function = f->function; + createForeignSupervisor(def, f->function); + } else + { assert(0); + } } } } +static void +setBuiltinPredicateProperties(void) +{ Module m = MODULE_system; + +#define LOOKUPPROC(name) \ + { GD->procedures.name = lookupProcedure(FUNCTOR_ ## name, m); \ + DEBUG(CHK_SECURE, assert(GD->procedures.name)); \ + } + + LOOKUPPROC(dgarbage_collect1); + LOOKUPPROC(catch3); + LOOKUPPROC(reset3); + LOOKUPPROC(dmeta_call1); + LOOKUPPROC(true0); + LOOKUPPROC(fail0); + LOOKUPPROC(equals2); + LOOKUPPROC(is2); + LOOKUPPROC(strict_equal2); + LOOKUPPROC(not_strict_equal2); + LOOKUPPROC(arg3); + LOOKUPPROC(print_message2); + LOOKUPPROC(dcall1); + LOOKUPPROC(dthread_init0); + LOOKUPPROC(dc_call_prolog0); + LOOKUPPROC(dinit_goal3); +#ifdef O_ATTVAR + LOOKUPPROC(dwakeup1); +#endif + + GD->procedures.heartbeat0 = lookupProcedure(FUNCTOR_heartbeat0, + PL_new_module(ATOM_prolog)); + PROCEDURE_exception_hook5 = + PL_predicate("prolog_exception_hook", 5, "prolog"); + PROCEDURE_tune_gc3 = + PL_predicate("tune_gc", 3, "prolog"); + /* allow debugging in call/1 */ + clear(PROCEDURE_dcall1->definition, HIDE_CHILDS|TRACE_ME); + set(PROCEDURE_dcall1->definition, P_DYNAMIC|P_LOCKED); + + PL_meta_predicate(PL_predicate("assert", 1, "system"), ":"); + PL_meta_predicate(PL_predicate("asserta", 1, "system"), ":"); + PL_meta_predicate(PL_predicate("assertz", 1, "system"), ":"); + PL_meta_predicate(PL_predicate("assert", 2, "system"), ":-"); + PL_meta_predicate(PL_predicate("asserta", 2, "system"), ":-"); + PL_meta_predicate(PL_predicate("assertz", 2, "system"), ":-"); + PL_meta_predicate(PL_predicate("retract", 1, "system"), ":"); + PL_meta_predicate(PL_predicate("retractall", 1, "system"), ":"); + PL_meta_predicate(PL_predicate("clause", 2, "system"), ":?"); + + PL_meta_predicate(PL_predicate("format", 2, "system"), "+:"); + PL_meta_predicate(PL_predicate("format", 3, "system"), "++:"); + PL_meta_predicate(PL_predicate("format_predicate", 2, "system"), "+0"); + + PL_meta_predicate(PL_predicate("notrace", 1, "system"), "0"); + PL_meta_predicate(PL_predicate("with_mutex", 2, "system"), "+0"); + PL_meta_predicate(PL_predicate("with_output_to", 2, "system"), "+0"); +#ifdef O_PLMT + PL_meta_predicate(PL_predicate("thread_create", 3, "system"), "0?+"); + PL_meta_predicate(PL_predicate("thread_signal", 2, "system"), "+0"); + PL_meta_predicate(PL_predicate("thread_wait", 2, "system"), "0:"); + PL_meta_predicate(PL_predicate("thread_update", 2, "system"), "0:"); +#endif + PL_meta_predicate(PL_predicate("thread_idle", 2, "system"), "0+"); + PL_meta_predicate(PL_predicate("prolog_frame_attribute", 3, "system"), "++:"); + PL_meta_predicate(PL_predicate("compile_predicates", 1, "system"), ":"); + PL_meta_predicate(PL_predicate("op", 3, "system"), "++:"); + PL_meta_predicate(PL_predicate("current_op", 3, "system"), "++:"); + PL_meta_predicate(PL_predicate("unwrap_predicate", 2, "system"), ":?"); + PL_meta_predicate(PL_predicate("prolog_listen", 2, "system"), "+:"); + PL_meta_predicate(PL_predicate("prolog_listen", 3, "system"), "+:+"); + PL_meta_predicate(PL_predicate("prolog_unlisten", 2, "system"), "+:"); + PL_meta_predicate(PL_predicate("with_tty_raw", 1, "system"), "0"); + PL_meta_predicate(PL_predicate("sig_atomic", 1, "system"), "0"); +} #define DECL_PLIST(id) \ extern const PL_extension PL_predicates_from_ ## id[] #define REG_PLIST(id) \ - registerBuiltins(PL_predicates_from_ ## id) + registerBuiltins(PL_predicates_from_ ## id, signonly) DECL_PLIST(alloc); DECL_PLIST(atom); @@ -409,13 +494,11 @@ DECL_PLIST(wasm); #endif void -initBuildIns(void) -{ ExtensionCell ecell; - Module m = MODULE_system; - - initProcedures(); +initBuildIns(bool signonly) +{ if ( !signonly ) + initProcedures(); - registerBuiltins(foreigns); + registerBuiltins(foreigns, signonly); REG_PLIST(alloc); REG_PLIST(atom); REG_PLIST(arith); @@ -492,77 +575,12 @@ initBuildIns(void) REG_PLIST(wasm); #endif -#define LOOKUPPROC(name) \ - { GD->procedures.name = lookupProcedure(FUNCTOR_ ## name, m); \ - DEBUG(CHK_SECURE, assert(GD->procedures.name)); \ - } - - LOOKUPPROC(dgarbage_collect1); - LOOKUPPROC(catch3); - LOOKUPPROC(reset3); - LOOKUPPROC(dmeta_call1); - LOOKUPPROC(true0); - LOOKUPPROC(fail0); - LOOKUPPROC(equals2); - LOOKUPPROC(is2); - LOOKUPPROC(strict_equal2); - LOOKUPPROC(not_strict_equal2); - LOOKUPPROC(arg3); - LOOKUPPROC(print_message2); - LOOKUPPROC(dcall1); - LOOKUPPROC(dthread_init0); - LOOKUPPROC(dc_call_prolog0); - LOOKUPPROC(dinit_goal3); -#ifdef O_ATTVAR - LOOKUPPROC(dwakeup1); -#endif - GD->procedures.heartbeat0 = lookupProcedure(FUNCTOR_heartbeat0, - PL_new_module(PL_new_atom("prolog"))); - PROCEDURE_exception_hook5 = - PL_predicate("prolog_exception_hook", 5, "prolog"); - PROCEDURE_tune_gc3 = - PL_predicate("tune_gc", 3, "prolog"); - /* allow debugging in call/1 */ - clear(PROCEDURE_dcall1->definition, HIDE_CHILDS|TRACE_ME); - set(PROCEDURE_dcall1->definition, P_DYNAMIC|P_LOCKED); - - PL_meta_predicate(PL_predicate("assert", 1, "system"), ":"); - PL_meta_predicate(PL_predicate("asserta", 1, "system"), ":"); - PL_meta_predicate(PL_predicate("assertz", 1, "system"), ":"); - PL_meta_predicate(PL_predicate("assert", 2, "system"), ":-"); - PL_meta_predicate(PL_predicate("asserta", 2, "system"), ":-"); - PL_meta_predicate(PL_predicate("assertz", 2, "system"), ":-"); - PL_meta_predicate(PL_predicate("retract", 1, "system"), ":"); - PL_meta_predicate(PL_predicate("retractall", 1, "system"), ":"); - PL_meta_predicate(PL_predicate("clause", 2, "system"), ":?"); - - PL_meta_predicate(PL_predicate("format", 2, "system"), "+:"); - PL_meta_predicate(PL_predicate("format", 3, "system"), "++:"); - PL_meta_predicate(PL_predicate("format_predicate", 2, "system"), "+0"); - - PL_meta_predicate(PL_predicate("notrace", 1, "system"), "0"); - PL_meta_predicate(PL_predicate("with_mutex", 2, "system"), "+0"); - PL_meta_predicate(PL_predicate("with_output_to", 2, "system"), "+0"); -#ifdef O_PLMT - PL_meta_predicate(PL_predicate("thread_create", 3, "system"), "0?+"); - PL_meta_predicate(PL_predicate("thread_signal", 2, "system"), "+0"); - PL_meta_predicate(PL_predicate("thread_wait", 2, "system"), "0:"); - PL_meta_predicate(PL_predicate("thread_update", 2, "system"), "0:"); -#endif - PL_meta_predicate(PL_predicate("thread_idle", 2, "system"), "0+"); - PL_meta_predicate(PL_predicate("prolog_frame_attribute", 3, "system"), "++:"); - PL_meta_predicate(PL_predicate("compile_predicates", 1, "system"), ":"); - PL_meta_predicate(PL_predicate("op", 3, "system"), "++:"); - PL_meta_predicate(PL_predicate("current_op", 3, "system"), "++:"); - PL_meta_predicate(PL_predicate("unwrap_predicate", 2, "system"), ":?"); - PL_meta_predicate(PL_predicate("prolog_listen", 2, "system"), "+:"); - PL_meta_predicate(PL_predicate("prolog_listen", 3, "system"), "+:+"); - PL_meta_predicate(PL_predicate("prolog_unlisten", 2, "system"), "+:"); - PL_meta_predicate(PL_predicate("with_tty_raw", 1, "system"), "0"); - PL_meta_predicate(PL_predicate("sig_atomic", 1, "system"), "0"); + if ( !signonly ) + { setBuiltinPredicateProperties(); - for( ecell = ext_head; ecell; ecell = ecell->next ) - bindExtensions(ecell->module, ecell->extensions); + for(ExtensionCell ecell = ext_head; ecell; ecell = ecell->next ) + bindExtensions(ecell->module, ecell->extensions); - extensions_loaded = true; + extensions_loaded = true; + } } diff --git a/src/pl-ext.h b/src/pl-ext.h index 964a583177..9578c1bea0 100644 --- a/src/pl-ext.h +++ b/src/pl-ext.h @@ -44,7 +44,7 @@ * FUNCTION DECLARATIONS * *******************************/ -void initBuildIns(void); +void initBuildIns(bool signonly); void cleanupExtensions(void); void rememberExtensions(const char *module, const PL_extension *e); diff --git a/src/pl-init.c b/src/pl-init.c index 10cb1ce4e3..19123a640c 100644 --- a/src/pl-init.c +++ b/src/pl-init.c @@ -3,7 +3,7 @@ Author: Jan Wielemaker E-mail: J.Wielemaker@vu.nl WWW: http://www.swi-prolog.org - Copyright (c) 2012-2022, University of Amsterdam + Copyright (c) 2012-2024, University of Amsterdam VU University Amsterdam CWI, Amsterdam SWI-Prolog Solutions b.v. @@ -99,8 +99,12 @@ option parsing, initialisation and handling of errors and warnings. #endif static int usage(void); -static int giveVersionInfo(const char *a); +static bool giveVersionInfo(const char *a); static bool vsysError(const char *errtype, const char *fm, va_list args); +static const char* abi_version(void); + +#define ABI_MAX 50 +static char abi_version_buf[ABI_MAX]; #define optionString(s) { if (argc > 1) \ { if ( s ) remove_string(s); \ @@ -224,6 +228,75 @@ opt_append(opt_list **l, const char *s) return true; } +static void +remove_trailing_whitespace(char *s) +{ char *e = s+strlen(s); + while(e>s && e[-1] <= ' ') + e--; + *e = EOS; +} + + +#define BAD_HOME_NO_ABI -1 +#define BAD_HOME_BAD_ABI -2 +#define BAD_HOME_ABI_MISMATCH -3 +#define BAD_HOME_NO_DIR -4 + +static int +match_abi_version(const char *required, const char *match) +{ return strcmp(required, match) == 0 ? 1 : BAD_HOME_ABI_MISMATCH; +} + +static int +check_home(const char *dir) +{ char abi_file_name[PATH_MAX]; + char abi_buf[ABI_MAX]; + IOSTREAM *fd; + + Ssnprintf(abi_file_name, sizeof(abi_file_name), + "%s/ABI", dir); + if ( (fd = Sopen_file(abi_file_name, "r")) ) + { char *abi_string = Sfgets(abi_buf, sizeof(abi_buf), fd); + Sclose(fd); + if ( abi_string ) + { remove_trailing_whitespace(abi_string); + return match_abi_version(abi_version(), abi_string); + } else + { return BAD_HOME_BAD_ABI; + } + } else + { if ( ExistsDirectory(dir) ) + return BAD_HOME_NO_ABI; + else + return BAD_HOME_NO_DIR; + } + + return false; +} + +static void +warn_bad_home(const char *prefix, const char *dir, int code) +{ const char *why = "?"; + + switch(code) + { case BAD_HOME_NO_ABI: + why = "no ABI file"; + break; + case BAD_HOME_BAD_ABI: + why = "invalid ABI file"; + break; + case BAD_HOME_ABI_MISMATCH: + why = "ABI mismatch"; + break; + case BAD_HOME_NO_DIR: + why = "no such directory"; + break; + } + + Sdprintf("%s%s: %s\n", prefix, dir, why); +} + + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Find the installation location of the SWI-Prolog resources, notably @@ -240,127 +313,229 @@ If `--home` is given (without a dir), follow the above steps exept for status 1. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* Try to find the home directory from PLHOMEVAR_1 or PLHOMEVAR_2 + */ + +#if defined(PLHOMEVAR_1) || defined(PLHOMEVAR_2) static char * -findHome(const char *symbols, int argc, const char **argv) -{ char *home = NULL; - char *maybe_home; - char envbuf[PATH_MAX]; - char plp[PATH_MAX]; - const char *homeopt = find_longopt("home", argc, argv); - const char *val; +findHomeFromEnvironment(char *buf, size_t size) +{ char envbuf[PATH_MAX]; const char *envvar; - - if ( homeopt && (val=is_longopt(homeopt, "home")) && val[0] ) - { if ( (home=PrologPath(val, plp, sizeof(plp))) ) - return store_string(home); - return NULL; - } + char *home; #ifdef PLHOMEVAR_1 - if ( !(maybe_home = Getenv((envvar=PLHOMEVAR_1), envbuf, sizeof(envbuf))) ) + if ( !(home = Getenv((envvar=PLHOMEVAR_1), envbuf, sizeof(envbuf))) ) { #ifdef PLHOMEVAR_2 - maybe_home = Getenv((envvar=PLHOMEVAR_2), envbuf, sizeof(envbuf)); + home = Getenv((envvar=PLHOMEVAR_2), envbuf, sizeof(envbuf)); #endif } - if ( maybe_home && - (maybe_home = PrologPath(maybe_home, plp, sizeof(plp))) && - ExistsDirectory(maybe_home) ) - { home = maybe_home; - DEBUG(MSG_INITIALISE, - Sdprintf("Found home using env %s\n", envvar)); - goto out; + + if ( home && (home = PrologPath(home, buf, size)) ) + { DEBUG(MSG_INITIALISE, + Sdprintf("Trying home from env %s\n", envvar)); } (void)envvar; + + return home; +#endif + + return NULL; +} #endif #ifdef PLHOMEFILE - if ( (maybe_home = (char*)symbols) ) - { char buf[PATH_MAX]; +static char * +findHomeFromExecutable(const char *symbols, char *buf, size_t size) +{ char *home; + + if ( (home = (char*)symbols) ) + { char linkfile[PATH_MAX]; /* PLHOMEFILE ("swipl.home") */ char parent[PATH_MAX]; IOSTREAM *fd; char *pparent; - if ( !(pparent=DirName(DirName(AbsoluteFile(maybe_home,parent,sizeof(parent)), + if ( !(pparent=DirName(DirName(AbsoluteFile(home,parent,sizeof(parent)), parent), parent)) || strlen(PLHOMEFILE) + 1 + strlen(pparent) + 1 > sizeof(parent) ) - fatalError("File name too long: %s", home); + { fatalError("File name too long: %s", home); + return NULL; + } - Ssnprintf(buf, sizeof(buf), "%s/" PLHOMEFILE, pparent); + Ssnprintf(linkfile, sizeof(linkfile), "%s/" PLHOMEFILE, pparent); - if ( (fd = Sopen_file(buf, "r")) ) - { DEBUG(MSG_INITIALISE, Sdprintf("Found home link file %s\n", buf)); + if ( (fd = Sopen_file(linkfile, "r")) ) + { char linkbuf[PATH_MAX]; + char *link = Sfgets(linkbuf, sizeof(linkbuf), fd); - if ( Sfgets(buf, sizeof(buf), fd) ) - { size_t l = strlen(buf); + Sclose(fd); + DEBUG(MSG_INITIALISE, Sdprintf("Found home link file %s\n", linkfile)); - while(l > 0 && buf[l-1] <= ' ') - l--; - buf[l] = EOS; + if ( link ) + { remove_trailing_whitespace(link); #if O_XOS - { char buf2[PATH_MAX]; - _xos_canonical_filename(buf, buf2, PATH_MAX, 0); - strcpy(buf, buf2); - } + char buf2[PATH_MAX]; + _xos_canonical_filename(link, buf2, sizeof(buf2), 0); + strcpy(link, buf2); #endif - - if ( !IsAbsolutePath(buf) ) + if ( !IsAbsolutePath(link) ) { char buf2[PATH_MAX]; - if ( Ssnprintf(buf2, sizeof(buf2), "%s/%s", parent, buf) < 0 || - !(maybe_home = AbsoluteFile(buf2, plp, sizeof(plp))) ) - fatalError("Path name too long: %s/%s", parent, buf); + if ( Ssnprintf(buf2, sizeof(buf2), "%s/%s", parent, link) < 0 || + !(home = AbsoluteFile(buf2, buf, size)) ) + { fatalError("Path name too long: %s/%s", parent, link); + return NULL; + } } else - { if ( !(maybe_home = AbsoluteFile(buf, plp, sizeof(plp))) ) - fatalError("Path name too long: %s/%s", buf); + { if ( !(home = AbsoluteFile(link, buf, size)) ) + { fatalError("Path name too long: %s", link); + return NULL; + } } - if ( ExistsDirectory(maybe_home) ) - { home = maybe_home; - DEBUG(MSG_INITIALISE, - Sdprintf("Found home %s using link file\n", home)); - } + DEBUG(MSG_INITIALISE, + Sdprintf("Trying home %s from link file\n", home)); + return home; } - Sclose(fd); } } + + return NULL; +} #endif /*PLHOMEFILE*/ + +/* Find home is absoluteFile(dirName(symbols)+"/"+PLRELHOME) + */ + #ifdef PLRELHOME - if ( !home && symbols ) +static char * +findRelHome(const char *symbols, char *buf, size_t size) +{ char *home; + + if ( symbols ) { char bindir[PATH_MAX]; char *o; strcpy(bindir, symbols); DirName(bindir, bindir); if ( strlen(bindir)+strlen(PLRELHOME)+2 > sizeof(bindir) ) - fatalError("Executable path name too long"); + { fatalError("Executable path name too long"); + return NULL; + } o = bindir+strlen(bindir); *o++ = '/'; strcpy(o, PLRELHOME); - if ( ExistsDirectory(bindir) ) - { if ( !(home=AbsoluteFile(bindir, plp, sizeof(plp))) ) - fatalError("Executable path name too long"); - DEBUG(MSG_INITIALISE, - Sdprintf("Found home using %s from %s\n", PLRELHOME, symbols)); + if ( !(home=AbsoluteFile(bindir, buf, size)) ) + { fatalError("Executable path name too long"); + return NULL; } + DEBUG(MSG_INITIALISE, + Sdprintf("Trying home %s from dir(%s)/" PLRELHOME "\n", home, symbols)); + return home; } + + return NULL; +} +#endif + + +static char * +searchHome(const char *symbols, bool verbose) +{ char *home = NULL; + char plp[PATH_MAX]; + const char *source; + const char *ctx; + +#ifdef __WINDOWS__ +#define ENVA "%" +#define ENVZ "%" +#else +#define ENVA "$" +#define ENVZ "" #endif + for(int i=0; ; i++) + { ctx = NULL; + switch(i) + { +#if defined(PLHOMEVAR_1) || defined(PLHOMEVAR_2) + case 0: + source = "environment " ENVA PLHOMEVAR_1 ENVZ + " or " ENVA PLHOMEVAR_2 ENVZ; + home = findHomeFromEnvironment(plp, sizeof(plp)); + break; +#endif +#ifdef PLHOMEFILE + case 1: + source = "using \"" PLHOMEFILE "\" from"; + ctx = symbols; + home = findHomeFromExecutable(symbols, plp, sizeof(plp)); + break; +#endif +#ifdef PLRELHOME + case 2: + source = PLRELHOME " relative relative to"; + ctx = symbols; + home = findRelHome(symbols, plp, sizeof(plp)); + break; +#endif #ifdef PLHOME - if ( !home && - ( (maybe_home = PrologPath(PLHOME, plp, sizeof(plp))) && - ExistsDirectory(maybe_home) - ) ) - { home = maybe_home; - DEBUG(MSG_INITIALISE, Sdprintf("Using compiled-in home at %s\n", PLHOME)); - } + case 3: + source = "compiled in"; + home = PrologPath(PLHOME, plp, sizeof(plp)); #endif + default: + return NULL; + } + + int rc = 0; + if ( home && (rc=check_home(home)) > 0 ) + { char abs[PATH_MAX]; + + if ( !IsAbsolutePath(home) && + !(home=AbsoluteFile(home, abs, sizeof(abs))) ) + { fatalError("Executable path name too long"); + return NULL; + } -out: - if ( home ) - home = store_string(home); + return store_string(home); + } else if ( verbose ) + { if ( ctx ) + Sdprintf(" Tried source: %s \"%s\"\n", source, ctx); + else + Sdprintf(" Tried source: %s\n", source); + if ( home ) + warn_bad_home(" Found ", home, rc); + } + } +} + +static char * +findHome(const char *symbols, int argc, const char **argv) +{ char *home = NULL; + const char *homeopt = find_longopt("home", argc, argv); + const char *val; + + if ( homeopt && (val=is_longopt(homeopt, "home")) && val[0] ) + { char tmp[PATH_MAX]; + char plp[PATH_MAX]; + + if ( (home=PrologPath(val, tmp, sizeof(tmp))) && + (home=AbsoluteFile(home, plp, sizeof(plp))) ) + { home = store_string(home); + int rc = check_home(home); + if ( rc < 0 ) + warn_bad_home("WARNING: Invalid SWI-Prolog home directory ", home, rc); + return home; + } else + { fatalError("--home option too long"); + return NULL; + } + } + + home = searchHome(symbols, false); if ( homeopt ) { if ( home ) @@ -375,6 +550,17 @@ findHome(const char *symbols, int argc, const char **argv) return home; } +static void +fatalNoResources(void) +{ if ( systemDefaults.home ) + { fatalError("Could not find system resources at %s", systemDefaults.home); + } else + { Sdprintf("FATAL: could not find SWI-Prolog home\n"); + searchHome(GD->paths.executable, true); + exit(1); + } +} + /* -- atoenne -- convert state to an absolute path. This allows relative SWI_HOME_DIR and cleans up non-canonical paths. @@ -1157,11 +1343,11 @@ PL_initialise(int argc, char **argv) #endif if ( !GD->resources.DB ) - { if ( (GD->resources.DB = zip_open_archive(GD->paths.executable, RC_RDONLY)) ) + { if ( (GD->resources.DB=zip_open_archive(GD->paths.executable, RC_RDONLY)) ) rcpath = GD->paths.executable; #ifdef __WINDOWS__ else if ( !streq(GD->paths.module, GD->paths.executable) && - (GD->resources.DB = zip_open_archive(GD->paths.module, RC_RDONLY)) ) + (GD->resources.DB=zip_open_archive(GD->paths.module, RC_RDONLY)) ) rcpath = GD->paths.module; #endif } @@ -1208,7 +1394,7 @@ PL_initialise(int argc, char **argv) { IOSTREAM *opts = NULL; if ( !(GD->resources.DB = openResourceDB(is_hash_bang)) ) - fatalError("Could not find system resources"); + fatalNoResources(); rcpath = zipper_file(GD->resources.DB); opts = SopenZIP(GD->resources.DB, "$prolog/options.txt", RC_RDONLY); @@ -1435,16 +1621,25 @@ version(void) #define PLPKGNAME "swipl" #endif -static int +static const char * abi_version(void) -{ initDefaultOptions(); - setupProlog(); - Sprintf(PLPKGNAME "-abi-%d-%d-%08x-%08x\n", - PL_FLI_VERSION, - PL_QLF_LOADVERSION, - GD->foreign.signature, - VM_SIGNATURE); - PL_cleanup(0); +{ if ( !abi_version_buf[0] ) + { initBuildIns(true); + snprintf(abi_version_buf, sizeof(abi_version_buf), + PLPKGNAME "-abi-%d-%d-%08x-%08x", + PL_FLI_VERSION, + PL_QLF_LOADVERSION, + GD->foreign.signature, + VM_SIGNATURE); + } + + return abi_version_buf; +} + + +static bool +print_abi_version(void) +{ Sprintf("%s\n", abi_version()); return true; } @@ -1458,7 +1653,7 @@ arch(void) } -static int +static bool giveVersionInfo(const char *a) { const char *v; @@ -1472,7 +1667,7 @@ giveVersionInfo(const char *a) if ( (v=is_longopt(a, "version")) && !*v ) return version(); if ( (v=is_longopt(a, "abi_version")) && !*v ) - return abi_version(); + return print_abi_version(); return false; } diff --git a/src/pl-proc.c b/src/pl-proc.c index 0a590707df..e87e3a41e5 100644 --- a/src/pl-proc.c +++ b/src/pl-proc.c @@ -396,7 +396,7 @@ resetProcedure(Procedure proc, bool isnew) ATOMIC_SUB(&GD->clauses.dirty, def->impl.clauses.number_of_clauses); uint64_t flags0, flags; - int userpred = stringAtom(def->functor->name)[0] != '$'; + bool userpred = stringAtom(def->functor->name)[0] != '$'; do { flags0 = def->flags; flags = flags0 ^ (flags0 & ~(SPY_ME|P_DIRTYREG)); diff --git a/src/pl-setup.c b/src/pl-setup.c index 3897764188..51a2767aca 100644 --- a/src/pl-setup.c +++ b/src/pl-setup.c @@ -150,7 +150,7 @@ setupProlog(void) DEBUG(1, Sdprintf("Flags ...\n")); initFlags(); DEBUG(1, Sdprintf("Foreign Predicates ...\n")); - initBuildIns(); + initBuildIns(false); DEBUG(1, Sdprintf("Malloc binding ...\n")); initMalloc(); DEBUG(1, Sdprintf("Operators ...\n"));