/************************************************************************* * * * Yap Prolog * * * * Yap Prolog Was Developed At Nccup - Universidade Do Porto * * * * Copyright L.Damas, V.S.Costa And Universidade Do Porto 1985-1997 * * * ************************************************************************** * * * File: Yap.C * Last *Rev: * Mods: ** Comments: Yap's Main File: parse arguments * * * *************************************************************************/ /* static char SccsId[] = "X 4.3.3"; */ #include "Yap.h" #include "YapHeap.h" #include "YapInterface.h" #include "YapStreams.h" #include "iopreds.h" #if HAVE_UNISTD_H #include #endif #if HAVE_STDINT_H #include #endif #include #include #ifdef _MSC_VER /* Microsoft's Visual C++ Compiler */ #ifdef HAVE_UNISTD_H #undef HAVE_UNISTD_H #endif #endif #include #if HAVE_STRING_H #include #endif #if HAVE_ERRNO_H #include #endif #if HAVE_DIRECT_H #include #endif #if HAVE_LIBGEN_H #include #endif X_API bool YAP_initialized = false; static int n_mdelays = 0; static YAP_delaymodule_t *m_delays; static void init_globals(YAP_init_args *yap_init) { GLOBAL_FAST_BOOT_FLAG = yap_init->FastBoot; #if defined(YAPOR) || defined(TABLING) Yap_init_root_frames(); #endif /* YAPOR || TABLING */ #ifdef YAPOR Yap_init_yapor_workers(); if ( #if YAPOR_THREADS Yap_thread_self() != 0 #else worker_id != 0 #endif ) { #if defined(YAPOR_COPY) || defined(YAPOR_SBA) /* In the SBA we cannot just happily inherit registers from the other workers */ Yap_InitYaamRegs(worker_id, true); #endif /* YAPOR_COPY || YAPOR_SBA */ #ifndef YAPOR_THREADS Yap_InitPreAllocCodeSpace(0); #endif /* YAPOR_THREADS */ /* slaves, waiting for work */ CurrentModule = USER_MODULE; P = GETWORK_FIRST_TIME; Yap_exec_absmi(FALSE, YAP_EXEC_ABSMI); Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "abstract machine unexpected exit (YAP_Init)"); } #endif /* YAPOR */ RECOVER_MACHINE_REGS(); /* make sure we do this after restore */ if (yap_init->MaxStackSize) { GLOBAL_AllowLocalExpansion = FALSE; } else { GLOBAL_AllowLocalExpansion = TRUE; } if (yap_init->MaxGlobalSize) { GLOBAL_AllowGlobalExpansion = FALSE; } else { GLOBAL_AllowGlobalExpansion = TRUE; } if (yap_init->MaxTrailSize) { GLOBAL_AllowTrailExpansion = FALSE; } else { GLOBAL_AllowTrailExpansion = TRUE; } if (yap_init->PrologRCFile) { Yap_PutValue(AtomConsultOnBoot, MkAtomTerm(Yap_LookupAtom(yap_init->PrologRCFile))); /* This must be done again after restore, as yap_flags has been overwritten .... */ setBooleanGlobalPrologFlag(HALT_AFTER_CONSULT_FLAG, yap_init->HaltAfterBoot); } if (yap_init->PrologTopLevelGoal) { Yap_PutValue(AtomTopLevelGoal, MkAtomTerm(Yap_LookupAtom(yap_init->PrologTopLevelGoal))); } if (yap_init->PrologGoal) { Yap_PutValue(AtomInitGoal, MkAtomTerm(Yap_LookupAtom(yap_init->PrologGoal))); } if (yap_init->PrologAddPath) { Yap_PutValue(AtomExtendFileSearchPath, MkAtomTerm(Yap_LookupAtom(yap_init->PrologAddPath))); } if (yap_init->QuietMode) { setVerbosity(TermSilent); } } const char *Yap_BINDIR, *Yap_ROOTDIR, *Yap_SHAREDIR, *Yap_LIBDIR, *Yap_DLLDIR, *Yap_PLDIR, *Yap_BOOTSTRAP, *Yap_COMMONSDIR, *Yap_INPUT_STARTUP, *Yap_OUTPUT_STARTUP, *Yap_SOURCEBOOT, *Yap_INCLUDEDIR, *Yap_PLBOOTDIR; /** * consult loop in C: used to boot the system, butt supports goal execution and * recursive consulting. * * */ static bool load_file(const char *b_file USES_REGS) { Term t; int c_stream, osno, oactive; Functor functor_query = Yap_MkFunctor(Yap_LookupAtom("?-"), 1); Functor functor_command1 = Yap_MkFunctor(Yap_LookupAtom(":-"), 1); Functor functor_compile2 = Yap_MkFunctor(Yap_LookupAtom("c_compile"), 1); /* consult in C */ int lvl = push_text_stack(); char *full; /* the consult mode does not matter here, really */ if ((osno = Yap_CheckAlias(AtomLoopStream)) < 0) { osno = 0; } c_stream = YAP_InitConsult(YAP_BOOT_MODE, b_file, &full, &oactive); __android_log_print( ANDROID_LOG_INFO, "YAPDroid", "done init_consult %s ",b_file); if (c_stream < 0) { fprintf(stderr, "[ FATAL ERROR: could not open file %s\n", b_file); pop_text_stack(lvl); exit(1); } if (!Yap_AddAlias(AtomLoopStream, c_stream)) { pop_text_stack(lvl); return false; } __android_log_print( ANDROID_LOG_INFO, "YAPDroid", "do reset %s ",b_file); t = 0; while (t != TermEof) { CACHE_REGS YAP_Reset(YAP_FULL_RESET, false); Yap_StartSlots(); Term vs = MkVarTerm(), pos = MkVarTerm(); t = YAP_ReadClauseFromStream(c_stream, vs, pos); // Yap_GetNèwSlot(t); if (t == TermEof || t == TermNil) { continue; } else if (t == 0) { fprintf(stderr, "%s:" Int_FORMAT " :0: error: SYNTAX ERROR\n", b_file, GLOBAL_Stream[c_stream].linecount); // // { // char buu[1024]; //1 // YAP_WriteBuffer(t, buu, 1023, 0); // fprintf(stderr, "[ %s ]\n" , buu); // } continue; } else if (IsVarTerm(t)) { fprintf(stderr, "%s:" Int_FORMAT ":0: error: unbound or NULL parser output\n\n", b_file, GLOBAL_Stream[c_stream].linecount); continue; } else if (IsApplTerm(t) && (FunctorOfTerm(t) == functor_query || FunctorOfTerm(t) == functor_command1)) { t = ArgOfTerm(1, t); if (IsApplTerm(t) && FunctorOfTerm(t) == functor_compile2) { load_file(RepAtom(AtomOfTerm(ArgOfTerm(1, t)))->StrOfAE); Yap_ResetException(LOCAL_ActiveError); continue; } else { YAP_RunGoalOnce(t); } } else { YAP_CompileClause(t); } yap_error_descriptor_t *errd; if ((errd = Yap_GetException(LOCAL_ActiveError)) && (errd->errorNo != YAP_NO_ERROR)) { fprintf(stderr, "%s:" Int_FORMAT ":0: error: %s/%s %s\n\n", b_file, errd->errorLine, errd->errorAsText, errd->classAsText, errd->errorMsg); } } BACKUP_MACHINE_REGS(); YAP_EndConsult(c_stream, &osno, full); if (!Yap_AddAlias(AtomLoopStream, osno)) { pop_text_stack(lvl); return false; } pop_text_stack(lvl); return t == TermEof; } static const char * EOLIST ="EOLINE"; static bool is_install; static bool is_dir( const char *path, const void *info) { if (is_install) return true; if (Yap_isDirectory( path )) return true; char s[YAP_FILENAME_MAX + 1]; Int i = strlen(path); strncpy(s, path, YAP_FILENAME_MAX); while (--i) { if (Yap_dir_separator((int)path[i])) break; } if (i == 0) { s[0] = '.'; i = 1; } s[i] = '\0'; if (info == NULL) return true; return strcmp(info,s) == 0 || Yap_isDirectory( s ); } static bool is_file( const char *path, const void *info) { if (is_install) return true; return Yap_Exists( path ); } static bool is_wfile( const char *path, const void *info) { return true; } typedef bool testf(const char *s, const void *info); /// /// static const char *sel( testf test, const void *info, const char *s1, ...) { const char *fmt = s1; va_list ap; char *buf = malloc(FILENAME_MAX + 1); va_start(ap, s1); while (fmt != EOLIST) { if (fmt == NULL || fmt[0]=='\0') { fmt = va_arg(ap, const char *); continue; } strncpy(buf, fmt, FILENAME_MAX); // Yap_AbsoluteFile(fmt,true), FILENAME_MAX); if (test(buf,info)) { buf = realloc(buf, strlen(buf) + 1); va_end(ap); return buf; } fmt = va_arg(ap, const char *); } va_end(ap); free(buf); return NULL; } static const char *join(const char *s0, const char *s1) { CACHE_REGS if (!s0 || s0[0] == '\0') { if (s1 && s1[0]) return s1; else return NULL; } if (!s1 || s1[0] == '\0') return s0; // int lvl = push_text_stack(); char *buf = malloc(strlen(s0)+strlen(s1) + 2); strcpy(buf, s0); if (Yap_dir_separator(s0[strlen(s0)-1])) { if (Yap_dir_separator(s1[0])) { s1 += 1; } } else { if (!Yap_dir_separator(s1[0]-1)) { strcat(buf, "/"); } } strcat(buf, s1); return buf; } static void Yap_set_locations(YAP_init_args *iap) { is_install= iap->install; /// ROOT_DIR is the home of the YAP system. It can be: /// -- provided by the user; /// -- obtained from DESTDIR + DE=efalkRoot /// /// It is: // --_not useful in Android, WIN32; /// -- DESTDIR/ in Anaconda /// -- /usr/loca77l in most Unix style systems Yap_ROOTDIR = sel( is_dir, NULL, iap->ROOTDIR, getenv("YAPROOTDIR"), join(getenv("DESTDIR"), YAP_ROOTDIR), #if __ANDROID__ "/", #else join(getenv("DESTDIR"), YAP_ROOTDIR), join(getenv("DESTDIR"), join(getenv("ḦOME"),".local")), join(getenv("DESTDIR"), "/usr/local"), join(getenv("DESTDIR"), "/usr"), join(getenv("DESTDIR"), "/opt"), #endif EOLIST ); __android_log_print( ANDROID_LOG_INFO,"YAPDroid", "Yap_ROOTDIR %s", Yap_ROOTDIR); /// BINDIR: where the OS stores header files, namely libYap... Yap_BINDIR = sel( is_dir, Yap_ROOTDIR, iap->BINDIR, getenv("YAPBINDIR"), #if !defined(__ANDROID__) join(getenv("DESTDIR"), YAP_BINDIR), #endif join(Yap_ROOTDIR, "bin"), EOLIST); /// LIBDIR: where the OS stores dynamic libraries, namely libYap... Yap_LIBDIR = sel( is_dir, Yap_ROOTDIR, iap->LIBDIR, #if !defined(__ANDROID__) join(getenv("DESTDIR"), YAP_LIBDIR), #endif join(Yap_ROOTDIR, "lib"), EOLIST); /// DLLDIR: where libraries can find expicitely loaded DLLs Yap_DLLDIR = sel(is_dir, Yap_LIBDIR, iap->DLLDIR, getenv("YAPLIBDIR"), join(getenv("DESTDIR"), YAP_DLLDIR), join(Yap_DLLDIR, "Yap"), EOLIST); /// INCLUDEDIR: where the OS stores header files, namely libYap... Yap_INCLUDEDIR = sel(is_dir, Yap_ROOTDIR, iap->INCLUDEDIR, #if !defined(__ANDROID__) join(getenv("DESTDIR"), YAP_INCLUDEDIR), #endif join(Yap_ROOTDIR, "include"), EOLIST); /// SHAREDIR: where OS & ARCH independent files live Yap_SHAREDIR = sel( is_dir, Yap_ROOTDIR, iap->SHAREDIR, getenv("YAPSHAREDIR"), #if __ANDROID__ "/data/data/pt.up.yap/files", "/assets", #endif join(getenv("DESTDIR"), YAP_SHAREDIR), join(Yap_ROOTDIR, "share"), join(Yap_ROOTDIR, "files"), EOLIST); __android_log_print( ANDROID_LOG_INFO,"YAPDroid", "Yap_SHAREDIR %s", Yap_SHAREDIR); /// PLDIR: where we can find Prolog files Yap_PLDIR = sel( is_dir, Yap_SHAREDIR, iap->PLDIR, join(getenv("DESTDIR"), join(Yap_SHAREDIR, "Yap")), EOLIST); __android_log_print( ANDROID_LOG_INFO, "YAPDroid","Yap_PLDIR %s", Yap_PLDIR); /// ``COMMONSDIR: Prolog Commons Yap_COMMONSDIR = sel(is_dir, Yap_SHAREDIR, iap->COMMONSDIR, join(getenv("DESTDIR"), join(Yap_SHAREDIR, "PrologCommons")), EOLIST); /// SOURCEBOOT: booting from the Prolog boot file at compilation-time so we should not assume pl is installed. Yap_SOURCEBOOT = sel( is_file, Yap_AbsoluteFile("pl",false), iap->SOURCEBOOT, YAP_SOURCEBOOT, "boot.yap", "../pl/boot.yap", EOLIST); __android_log_print( ANDROID_LOG_INFO, "YAPDroid","Yap_SOURCEBOOT %s", Yap_SOURCEBOOT); Yap_PLBOOTDIR = sel( is_dir, Yap_PLDIR, iap->BOOTDIR, join(getenv("DESTDIR"),join(Yap_PLDIR, "pl")), EOLIST); __android_log_print( ANDROID_LOG_INFO, "YAPDroid","Yap_BOOTSTRAP %s", Yap_BOOTSTRAP); /// BOOTSTRAP: booting from the Prolog boot file after YAP is installed Yap_BOOTSTRAP = sel( is_file, Yap_PLBOOTDIR, iap->BOOTSTRAP, join(getenv("DESTDIR"),YAP_BOOTSTRAP), join(getenv("DESTDIR"),join(Yap_PLBOOTDIR, "boot.yap")), EOLIST); __android_log_print( ANDROID_LOG_INFO,"YAPDroid", "Yap_BOOTSTRAP %s", Yap_PLBOOTDIR); /// STARTUP: where we can find the core Prolog bootstrap file Yap_OUTPUT_STARTUP = sel( is_wfile, ".", iap->OUTPUT_STARTUP, YAP_OUTPUT_STARTUP, join(getenv("DESTDIR"), join(Yap_DLLDIR, "startup.yss")), join(getenv("DESTDIR"), join(Yap_DLLDIR,iap->OUTPUT_STARTUP)), "startup.yss", EOLIST); Yap_INPUT_STARTUP = sel( is_file, Yap_DLLDIR, iap->INPUT_STARTUP, "startup.yss", join(getenv("DESTDIR"), join(Yap_DLLDIR, "startup.yss")), #if !defined(__ANDROID__) join(getenv("DESTDIR"), YAP_INPUT_STARTUP), #endif "/usr/local/lib/Yap/startup.yss", "/usr/lib/Yap/startup.yss", EOLIST); if (Yap_ROOTDIR) setAtomicGlobalPrologFlag(HOME_FLAG, MkAtomTerm(Yap_LookupAtom(Yap_ROOTDIR))); if (Yap_PLDIR) setAtomicGlobalPrologFlag(PROLOG_LIBRARY_DIRECTORY_FLAG, MkAtomTerm(Yap_LookupAtom(Yap_PLDIR))); if (Yap_DLLDIR) setAtomicGlobalPrologFlag(PROLOG_FOREIGN_DIRECTORY_FLAG, MkAtomTerm(Yap_LookupAtom(Yap_DLLDIR))); } static void print_usage(void) { fprintf(stderr, "\n[ Valid switches for command line arguments: ]\n"); fprintf(stderr, " -? Shows this screen\n"); fprintf(stderr, " -B Used during compilation: boot from ../pl/boot.yap and generate a saved state. \n"); fprintf(stderr, " -b Boot file \n"); fprintf(stderr, " -dump-runtime-variables\n"); fprintf(stderr, " -f initialization file or \"none\"\n"); fprintf(stderr, " -g Run Goal Before Top-Level \n"); fprintf(stderr, " -z Run Goal Before Top-Level \n"); fprintf(stderr, " -q start with informational messages off\n"); fprintf(stderr, " -l load Prolog file\n"); fprintf(stderr, " -L run Prolog file and exit\n"); fprintf(stderr, " -p extra path for file-search-path\n"); fprintf(stderr, " -hSize Heap area in Kbytes (default: %d, minimum: %d)\n", DefHeapSpace, MinHeapSpace); fprintf(stderr, " -sSize Stack area in Kbytes (default: %d, minimum: %d)\n", DefStackSpace, MinStackSpace); fprintf(stderr, " -tSize Trail area in Kbytes (default: %d, minimum: %d)\n", DefTrailSpace, MinTrailSpace); fprintf(stderr, " -GSize Max Area for Global Stack\n"); fprintf(stderr, " -LSize Max Area for Local Stack (number must follow L)\n"); fprintf(stderr, " -TSize Max Area for Trail (number must follow T)\n"); fprintf(stderr, " -nosignals disable signal handling from Prolog\n"); fprintf(stderr, "\n[Execution Modes]\n"); fprintf(stderr, " -J0 Interpreted mode (default)\n"); fprintf(stderr, " -J1 Mixed mode only for user predicates\n"); fprintf(stderr, " -J2 Mixed mode for all predicates\n"); fprintf(stderr, " -J3 Compile all user predicates\n"); fprintf(stderr, " -J4 Compile all predicates\n"); #ifdef TABLING fprintf(stderr, " -ts Maximum table space area in Mbytes (default: unlimited)\n"); #endif /* TABLING */ #if defined(YAPOR_COPY) || defined(YAPOR_COW) || defined(YAPOR_SBA) || \ defined(YAPOR_THREADS) fprintf(stderr, " -w Number of workers (default: %d)\n", DEFAULT_NUMBERWORKERS); fprintf(stderr, " -sl Loop scheduler executions before look for hiden " "shared work (default: %d)\n", DEFAULT_SCHEDULERLOOP); fprintf(stderr, " -d Value of delayed release of load (default: %d)\n", DEFAULT_DELAYEDRELEASELOAD); #endif /* YAPOR_COPY || YAPOR_COW || YAPOR_SBA || YAPOR_THREADS */ /* nf: Preprocessor */ /* fprintf(stderr," -DVar=Name Persistent definition\n"); */ fprintf(stderr, "\n"); } static int myisblank(int c) { switch (c) { case ' ': case '\t': case '\n': case '\r': return TRUE; default: return FALSE; } } static char *add_end_dot(char arg[]) { int sz = strlen(arg), i; i = sz; while (i && myisblank(arg[--i])) ; if (i && arg[i] != ',') { char *p = (char *)malloc(sz + 2); if (!p) return NULL; strncpy(p, arg, sz); p[sz] = '.'; p[sz + 1] = '\0'; return p; } return arg; } static int dump_runtime_variables(void) { fprintf(stdout, "CC=\"%s\"\n", C_CC); fprintf(stdout, "YAP_ROOTDIR=\"%s\"\n", YAP_ROOTDIR); fprintf(stdout, "YAP_LIBS=\"%s\"\n", C_LIBS); fprintf(stdout, "YAP_SHLIB_SUFFIX=\"%s\"\n", SO_EXT); fprintf(stdout, "YAP_VERSION=%s\n", YAP_NUMERIC_VERSION); exit(0); return 1; } X_API YAP_file_type_t Yap_InitDefaults(void *x, char *saved_state, int argc, char *argv[]) { if (!LOCAL_TextBuffer) LOCAL_TextBuffer = Yap_InitTextAllocator(); YAP_init_args *iap = x; memset(iap, 0, sizeof(YAP_init_args)); iap->Argc = argc; iap->Argv = argv; #if __ANDROID__ iap->boot_file_type = YAP_PL; iap->INPUT_STARTUP = NULL; iap->assetManager = NULL; return YAP_PL; #else iap->boot_file_type = YAP_QLY; iap->INPUT_STARTUP = saved_state; return YAP_QLY; #endif } /** * @short Parse command line * @param argc number of arguments * @param argv arguments * @param iap options, see YAP_init_args * @return boot from saved state or restore; error */ X_API YAP_file_type_t YAP_parse_yap_arguments(int argc, char *argv[], YAP_init_args *iap) { char *p; size_t *ssize; Yap_InitDefaults(iap, NULL, argc, argv); while (--argc > 0) { p = *++argv; if (*p == '-') switch (*++p) { case 'b': iap->boot_file_type = YAP_PL; if (p[1]) iap->BOOTSTRAP = p + 1; else if (argv[1] && *argv[1] != '-') { iap->BOOTSTRAP = *++argv; argc--; } break; case 'B': iap->boot_file_type = YAP_SOURCE_PL; if (p[1]) iap->SOURCEBOOT = p + 1; else if (argv[1] && *argv[1] != '-') { iap->SOURCEBOOT = *++argv; argc--; } iap->install = true; break; case '?': print_usage(); exit(EXIT_SUCCESS); case 'q': iap->QuietMode = TRUE; break; #if defined(YAPOR_COPY) || defined(YAPOR_COW) || defined(YAPOR_SBA) || \ defined(YAPOR_THREADS) case 'w': ssize = &(iap->NumberWorkers); goto GetSize; case 'd': if (!strcmp("dump-runtime-variables", p)) return dump_runtime_variables(); ssize = &(iap->DelayedReleaseLoad); goto GetSize; #else case 'd': if (!strcmp("dump-runtime-variables", p)) return dump_runtime_variables(); #endif /* YAPOR_COPY || YAPOR_COW || YAPOR_SBA || YAPOR_THREADS */ case 'F': /* just ignore for now */ argc--; argv++; break; case 'f': iap->FastBoot = TRUE; if (argc > 1 && argv[1][0] != '-') { argc--; argv++; if (strcmp(*argv, "none")) { iap->PrologRCFile = *argv; } break; } break; // execution mode case 'J': switch (p[1]) { case '0': iap->ExecutionMode = YAPC_INTERPRETED; break; case '1': iap->ExecutionMode = YAPC_MIXED_MODE_USER; break; case '2': iap->ExecutionMode = YAPC_MIXED_MODE_ALL; break; case '3': iap->ExecutionMode = YAPC_COMPILE_USER; break; case '4': iap->ExecutionMode = YAPC_COMPILE_ALL; break; default: fprintf(stderr, "[ YAP unrecoverable error: unknown switch -%c%c ]\n", *p, p[1]); exit(EXIT_FAILURE); } p++; break; case 'G': ssize = &(iap->MaxGlobalSize); goto GetSize; break; case 's': case 'S': ssize = &(iap->StackSize); #if defined(YAPOR_COPY) || defined(YAPOR_COW) || defined(YAPOR_SBA) || \ defined(YAPOR_THREADS) if (p[1] == 'l') { p++; ssize = &(iap->SchedulerLoop); } #endif /* YAPOR_COPY || YAPOR_COW || YAPOR_SBA || YAPOR_THREADS */ goto GetSize; case 'a': case 'A': ssize = &(iap->AttsSize); goto GetSize; case 'T': ssize = &(iap->MaxTrailSize); goto get_trail_size; case 't': ssize = &(iap->TrailSize); #ifdef TABLING if (p[1] == 's') { p++; ssize = &(iap->MaxTableSpaceSize); } #endif /* TABLING */ get_trail_size: if (*++p == '\0') { if (argc > 1) --argc, p = *++argv; else { fprintf(stderr, "[ YAP unrecoverable error: missing size in flag %s ]", argv[0]); print_usage(); exit(EXIT_FAILURE); } } { unsigned long int i = 0, ch; while ((ch = *p++) >= '0' && ch <= '9') i = i * 10 + ch - '0'; switch (ch) { case 'M': case 'm': i *= 1024; ch = *p++; break; case 'g': i *= 1024 * 1024; ch = *p++; break; case 'k': case 'K': ch = *p++; break; } if (ch) { iap->PrologTopLevelGoal = add_end_dot(*argv); } else { *ssize = i; } } break; case 'h': case 'H': ssize = &(iap->HeapSize); GetSize: if (*++p == '\0') { if (argc > 1) --argc, p = *++argv; else { fprintf(stderr, "[ YAP unrecoverable error: missing size in flag %s ]", argv[0]); print_usage(); exit(EXIT_FAILURE); } } { unsigned long int i = 0, ch; while ((ch = *p++) >= '0' && ch <= '9') i = i * 10 + ch - '0'; switch (ch) { case 'M': case 'm': i *= 1024; ch = *p++; break; case 'g': case 'G': i *= 1024 * 1024; ch = *p++; break; case 'k': case 'K': ch = *p++; break; } if (ch) { fprintf( stderr, "[ YAP unrecoverable error: illegal size specification %s ]", argv[-1]); Yap_exit(1); } *ssize = i; } break; #ifdef DEBUG case 'P': if (p[1] != '\0') { while (p[1] != '\0') { int ch = p[1]; if (ch >= 'A' && ch <= 'Z') ch += ('a' - 'A'); if (ch >= 'a' && ch <= 'z') GLOBAL_Option[ch - 96] = 1; p++; } } else { YAP_SetOutputMessage(); } break; #endif case 'L': if (p[1] && p[1] >= '0' && p[1] <= '9') /* hack to emulate SWI's L local option */ { ssize = &(iap->MaxStackSize); goto GetSize; } iap->QuietMode = TRUE; iap->HaltAfterBoot = true; case 'l': p++; if (!*++argv) { fprintf(stderr, "%% YAP unrecoverable error: missing load file name\n"); exit(1); } else if (!strcmp("--", *argv)) { /* shell script, the next entry should be the file itself */ iap->PrologRCFile = argv[1]; argc = 1; break; } else { iap->PrologRCFile = *argv; argc--; } if (*p) { /* we have something, usually, of the form: -L -- FileName ExtraArgs */ /* being called from a script */ while (*p && (*p == ' ' || *p == '\t')) p++; if (p[0] == '-' && p[1] == '-') { /* ignore what is next */ argc = 1; } } break; /* run goal before top-level */ case 'g': if ((*argv)[0] == '\0') iap->PrologGoal = *argv; else { argc--; if (argc == 0) { fprintf(stderr, " [ YAP unrecoverable error: missing " "initialization goal for option 'g' ]\n"); exit(EXIT_FAILURE); } argv++; iap->PrologGoal = *argv; } break; /* run goal as top-level */ case 'z': if ((*argv)[0] == '\0') iap->PrologTopLevelGoal = *argv; else { argc--; if (argc == 0) { fprintf(stderr, " [ YAP unrecoverable error: missing goal for " "option 'z' ]\n"); exit(EXIT_FAILURE); } argv++; iap->PrologTopLevelGoal = add_end_dot(*argv); } iap->HaltAfterBoot = true; break; case 'n': if (!strcmp("nosignals", p)) { iap->PrologCannotHandleInterrupts = true; break; } break; case '-': if (!strcmp("-nosignals", p)) { iap->PrologCannotHandleInterrupts = true; break; } else if (!strncmp("-output-saved-state=", p, strlen("-output-saved-state="))) { iap->OUTPUT_STARTUP = p + strlen("-output-saved-state="); } else if (!strncmp("-home=", p, strlen("-home="))) { iap->ROOTDIR = p + strlen("-home="); } else if (!strncmp("-system-library-directory=", p, strlen("-system-library-directory="))) { iap->LIBDIR = p + strlen("-system-library-directory="); } else if (!strncmp("-system-shared-directory=", p, strlen("-system-shared-directory="))) { iap->SHAREDIR = p + strlen("-system-shared-directory="); } else if (!strncmp("-prolog-library-directory=", p, strlen("-prolog-library-directory="))) { iap->PLDIR = p + strlen("-prolog-library-directory="); } else if (!strncmp("-dll-library-directory=", p, strlen("-dll-library-directory="))) { iap->DLLDIR = p + strlen("-dll-library-directory="); } else if (!strncmp("-home=", p, strlen("-home="))) { iap->ROOTDIR = p + strlen("-home="); } else if (!strncmp("-cwd=", p, strlen("-cwd="))) { if (!Yap_ChDir(p + strlen("-cwd="))) { fprintf(stderr, " [ YAP unrecoverable error in setting cwd: %s ]\n", strerror(errno)); } } else if (!strncmp("-stack=", p, strlen("-stack="))) { ssize = &(iap->StackSize); p += strlen("-stack="); goto GetSize; } else if (!strncmp("-trail=", p, strlen("-trail="))) { ssize = &(iap->TrailSize); p += strlen("-trail="); goto GetSize; } else if (!strncmp("-heap=", p, strlen("-heap="))) { ssize = &(iap->HeapSize); p += strlen("-heap="); goto GetSize; } else if (!strncmp("-max-stack=", p, strlen("-max-stack="))) { ssize = &(iap->MaxStackSize); p += strlen("-max-stack="); goto GetSize; } else if (!strncmp("-max-trail=", p, strlen("-max-trail="))) { ssize = &(iap->MaxTrailSize); p += strlen("-max-trail="); goto GetSize; } else if (!strncmp("-max-heap=", p, strlen("-max-heap="))) { ssize = &(iap->MaxHeapSize); p += strlen("-max-heap="); goto GetSize; } else if (!strncmp("-goal=", p, strlen("-goal="))) { iap->PrologGoal = p + strlen("-goal="); } else if (!strncmp("-top-level=", p, strlen("-top-level="))) { iap->PrologTopLevelGoal = p + strlen("-top-level="); } else if (!strncmp("-table=", p, strlen("-table="))) { ssize = &(iap->MaxTableSpaceSize); p += strlen("-table="); goto GetSize; } else if (!strncmp("-", p, strlen("-="))) { ssize = &(iap->MaxTableSpaceSize); p += strlen("-table="); /* skip remaining arguments */ argc = 1; } break; case 'p': if ((*argv)[0] == '\0') iap->PrologAddPath = *argv; else { argc--; if (argc == 0) { fprintf(stderr, " [ YAP unrecoverable error: missing paths for " "option 'p' ]\n"); exit(EXIT_FAILURE); } argv++; iap->PrologAddPath = *argv; } break; /* nf: Begin preprocessor code */ case 'D': { char *var, *value; ++p; var = p; if (var == NULL || *var == '\0') break; while (*p != '=' && *p != '\0') ++p; if (*p == '\0') break; *p = '\0'; ++p; value = p; if (*value == '\0') break; if (iap->def_c == YAP_MAX_YPP_DEFS) break; iap->def_var[iap->def_c] = var; iap->def_value[iap->def_c] = value; ++(iap->def_c); break; } /* End preprocessor code */ default: { fprintf(stderr, "[ YAP unrecoverable error: unknown switch -%c ]\n", *p); print_usage(); exit(EXIT_FAILURE); } } else { iap->INPUT_STARTUP = p; } } return iap->boot_file_type; } /** YAP_DelayInit() ensures initialization is done after engine creation. It receives a pointer to function and a string describing the module. */ X_API bool YAP_DelayInit(YAP_ModInit_t f, const char s[]) { if (m_delays) { m_delays = realloc(m_delays, (n_mdelays + 1) * sizeof(YAP_delaymodule_t)); } else { m_delays = malloc(sizeof(YAP_delaymodule_t)); } m_delays[n_mdelays].f = f; m_delays[n_mdelays].s = s; n_mdelays++; return true; } bool Yap_LateInit(const char s[]) { int i; for (i = 0; i < n_mdelays; i++) { if (!strcmp(m_delays[i].s, s)) { m_delays[i].f(); return true; } } return false; } struct ssz_t { size_t Heap, Stack, Trail; }; bool Yap_Embedded; static void init_hw(YAP_init_args *yap_init, struct ssz_t *spt) { Yap_page_size = Yap_InitPageSize(); /* init memory page size, required by later functions */ #if defined(YAPOR_COPY) || defined(YAPOR_COW) || defined(YAPOR_SBA) Yap_init_yapor_global_local_memory(); #endif /* YAPOR_COPY || YAPOR_COW || YAPOR_SBA */ if (yap_init->Embedded) { yap_init->install = false; GLOBAL_PrologShouldHandleInterrupts = yap_init->PrologCannotHandleInterrupts = true; } else { GLOBAL_PrologShouldHandleInterrupts = !yap_init->PrologCannotHandleInterrupts; } Yap_InitSysbits(0); /* init signal handling and time, required by later functions */ GLOBAL_argv = yap_init->Argv; GLOBAL_argc = yap_init->Argc; #if __ANDROID__ // if (yap_init->assetManager) // Yap_InitAssetManager(); #endif if (yap_init->TrailSize == 0) { if (spt->Trail == 0) spt->Trail = DefTrailSpace; } else { spt->Trail = yap_init->TrailSize; } // Atts = yap_init->AttsSize; if (yap_init->StackSize == 0) { spt->Stack = DefStackSpace; } else { spt->Stack = yap_init->StackSize; } #ifndef USE_SYSTEM_MALLOC if (yap_init->HeapSize == 0) { if (spt->Heap == 0) spt->Heap = DefHeapSpace; } else { spt->Heap = yap_init->HeapSize; } #endif } static void end_init(YAP_init_args *iap) { YAP_initialized = true; if (iap->HaltAfterBoot) Yap_exit(0); LOCAL_PrologMode &= ~BootMode; CurrentModule = USER_MODULE; LOCAL_SourceModule = USER_MODULE; } static void start_modules(void) { Term cm = CurrentModule; size_t i; for (i = 0; i < n_mdelays; i++) { CurrentModule = MkAtomTerm(YAP_LookupAtom(m_delays[i].s)); m_delays[i].f(); } CurrentModule = cm; } /* this routine is supposed to be called from an external program that wants to control Yap */ X_API void YAP_Init(YAP_init_args *yap_init) { bool try_restore = yap_init->boot_file_type == YAP_QLY; bool do_bootstrap = yap_init->boot_file_type == YAP_PL || yap_init->boot_file_type == YAP_SOURCE_PL; struct ssz_t minfo; __android_log_print( ANDROID_LOG_INFO, "YAPDroid", "start init "); if (YAP_initialized) /* ignore repeated calls to YAP_Init */ return; if (!LOCAL_TextBuffer) LOCAL_TextBuffer = Yap_InitTextAllocator(); Yap_Embedded = yap_init->Embedded; minfo.Trail = 0, minfo.Stack = 0, minfo.Trail = 0; init_hw(yap_init, &minfo); Yap_InitWorkspace(yap_init, minfo.Heap, minfo.Stack, minfo.Trail, 0, yap_init->MaxTableSpaceSize, yap_init->NumberWorkers, yap_init->SchedulerLoop, yap_init->DelayedReleaseLoad); // CACHE_REGS CurrentModule = PROLOG_MODULE; if (yap_init->QuietMode) { setVerbosity(TermSilent); } if (yap_init->PrologRCFile != NULL) { /* This must be done before restore, otherwise restore will print out messages .... */ setBooleanGlobalPrologFlag(HALT_AFTER_CONSULT_FLAG, yap_init->HaltAfterBoot); } /* tell the system who should cope with interrupts */ Yap_ExecutionMode = yap_init->ExecutionMode; Yap_set_locations(yap_init); if (Yap_INPUT_STARTUP==NULL) try_restore = false; if (do_bootstrap || !try_restore || !Yap_SavedInfo(Yap_INPUT_STARTUP, &minfo.Trail, &minfo.Stack, &minfo.Heap)) { init_globals(yap_init); start_modules(); TermEof = MkAtomTerm(Yap_LookupAtom("end_of_file")); LOCAL_consult_level = -1; __android_log_print( ANDROID_LOG_INFO, "YAPDroid", "init %s ", Yap_BOOTSTRAP); if (yap_init->install) { load_file(Yap_SOURCEBOOT PASS_REGS); setAtomicGlobalPrologFlag(RESOURCE_DATABASE_FLAG, MkAtomTerm(Yap_LookupAtom(Yap_SOURCEBOOT))); } else { load_file(Yap_BOOTSTRAP PASS_REGS); setAtomicGlobalPrologFlag(RESOURCE_DATABASE_FLAG, MkAtomTerm(Yap_LookupAtom(Yap_BOOTSTRAP))); } CurrentModule = LOCAL_SourceModule = TermUser; setBooleanGlobalPrologFlag(SAVED_PROGRAM_FLAG, false); } else { if (yap_init->QuietMode) { setVerbosity(TermSilent); } __android_log_print( ANDROID_LOG_INFO, "YAPDroid", "restore %s ",Yap_INPUT_STARTUP ); Yap_Restore(Yap_INPUT_STARTUP); CurrentModule = LOCAL_SourceModule = TermUser; init_globals(yap_init); start_modules(); if (yap_init->install && Yap_OUTPUT_STARTUP) { setAtomicGlobalPrologFlag(RESOURCE_DATABASE_FLAG, MkAtomTerm(Yap_LookupAtom(Yap_INPUT_STARTUP))); setBooleanGlobalPrologFlag(SAVED_PROGRAM_FLAG, true); } LOCAL_consult_level = -1; } YAP_RunGoalOnce(TermInitProlog); if (yap_init->install && Yap_OUTPUT_STARTUP) { Term t = MkAtomTerm(Yap_LookupAtom(Yap_OUTPUT_STARTUP)); Term g = Yap_MkApplTerm(Yap_MkFunctor(Yap_LookupAtom("qsave_program"), 1), 1, &t); YAP_RunGoalOnce(g); } end_init(yap_init); } #if (DefTrailSpace < MinTrailSpace) #undef DefTrailSpace #define DefTrailSpace MinTrailSpace #endif #if (DefStackSpace < MinStackSpace) #undef DefStackSpace #define DefStackSpace MinStackSpace #endif #if (DefHeapSpace < MinHeapSpace) #undef DefHeapSpace #define DefHeapSpace MinHeapSpace #endif #define DEFAULT_NUMBERWORKERS 1 #define DEFAULT_SCHEDULERLOOP 10 #define DEFAULT_DELAYEDRELEASELOAD 3 X_API void YAP_FastInit(char *saved_state, int argc, char *argv[]) { YAP_init_args init_args; YAP_file_type_t out; if ((out = Yap_InitDefaults(&init_args, saved_state, argc, argv)) != YAP_FOUND_BOOT_ERROR) YAP_Init(&init_args); if (out == YAP_FOUND_BOOT_ERROR) { Yap_Error(init_args.ErrorNo, TermNil, init_args.ErrorCause); } }