/************************************************************************* * * * 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 * * * *************************************************************************/ /* static char SccsId[] = "X 4.3.3"; */ #include "config.h" #include "YapInterface.h" #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 #ifdef _MSC_VER /* Microsoft's Visual C++ Compiler */ #ifdef HAVE_UNISTD_H #undef HAVE_UNISTD_H #endif #endif #include #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_STAT_H #include #endif #if HAVE_FCNTL_H #include #endif #if HAVE_STDARG_H #include #endif #include #if HAVE_UNISTD_H #include #endif #if HAVE_ERRNO_H #include #endif #if HAVE_STRING_H #include #endif static int PROTO(mygetc, (void)); static void PROTO(do_bootfile, (char *)); static void PROTO(do_top_goal,(YAP_Term)); static void PROTO(exec_top_level,(int, YAP_init_args *)); #ifndef LIGHT void PROTO (exit, (int)); #endif #ifdef LIGHT #include int _main (int, char **); #else int PROTO (main, (int, char **)); #endif #ifdef DEBUG static int output_msg; #endif static char BootFile[] = "boot.yap"; static char InitFile[] = "init.yap"; #ifdef lint /* VARARGS1 */ #endif #ifdef M_WILLIAMS long _stksize = 32000; #endif static FILE *bootfile; static int eof_found = FALSE; static int yap_lineno = 0; static void myputc (int ch) { putc(ch,stderr); } static int mygetc (void) { int ch; if (eof_found) return (EOF); ch = getc (bootfile); if (ch == EOF) eof_found = TRUE; if (ch == '\n') { #ifdef MPW ch = 10; #endif yap_lineno++; } return (ch); } static void do_top_goal (YAP_Term Goal) { #ifdef DEBUG if (output_msg) fprintf(stderr,"Entering absmi\n"); #endif /* PlPutc(0,'a'); PlPutc(0,'\n'); */ YAP_RunGoal(Goal); } /* do initial boot by consulting the file boot.yap */ static void do_bootfile (char *bootfilename) { YAP_Term t; YAP_Term term_nil = YAP_MkAtomTerm(YAP_LookupAtom("[]")); YAP_Term term_end_of_file = YAP_MkAtomTerm(YAP_LookupAtom("end_of_file")); YAP_Term term_true = YAP_MkAtomTerm(YAP_LookupAtom("true")); YAP_Functor functor_query = YAP_MkFunctor(YAP_LookupAtom("?-"),1); /* consult boot.pl */ bootfile = fopen (bootfilename, "r"); if (bootfile == NULL) { fprintf(stderr, "[ FATAL ERROR: could not open bootfile %s ]\n", bootfilename); exit(1); } /* the consult mode does not matter here, really */ /* To be honest, YAP_InitConsult does not really do much, it's here for the future. It also makes what we want to do clearer. */ YAP_InitConsult(YAP_CONSULT_MODE,bootfilename); while (!eof_found) { t = YAP_Read(mygetc); if (eof_found) { break; } if (t == 0) { fprintf(stderr, "[ SYNTAX ERROR: while parsing bootfile %s at line %d ]\n", bootfilename, yap_lineno); exit(1); } if (YAP_IsVarTerm (t) || t == term_nil) { continue; } else if (t == term_true) { YAP_Exit(0); } else if (t == term_end_of_file) { break; } else if (YAP_IsPairTerm (t)) { fprintf(stderr, "[ SYSTEM ERROR: consult not allowed in boot file ]\n"); fprintf(stderr, "error found at line %d and pos %d", yap_lineno, fseek(bootfile,0L,SEEK_CUR)); } else if (YAP_IsApplTerm (t) && YAP_FunctorOfTerm (t) == functor_query) { do_top_goal(YAP_ArgOfTerm (1, t)); } else { char *ErrorMessage = YAP_CompileClause(t); if (ErrorMessage) fprintf(stderr, ErrorMessage); } /* do backtrack */ YAP_Reset(); } YAP_EndConsult(); fclose (bootfile); #ifdef DEBUG if (output_msg) fprintf(stderr,"Boot loaded\n"); #endif } static void print_usage(void) { fprintf(stderr,"\n[ Valid switches for command line arguments: ]\n"); fprintf(stderr," -? Shows this screen\n"); fprintf(stderr," -b Boot file \n"); fprintf(stderr," -l Prolog file\n"); fprintf(stderr," -h Heap area in Kbytes (default: %d, minimum: %d)\n", DefHeapSpace, MinHeapSpace); fprintf(stderr," -s Stack area in Kbytes (default: %d, minimum: %d)\n", DefStackSpace, MinStackSpace); fprintf(stderr," -t Trail area in Kbytes (default: %d, minimum: %d)\n", DefTrailSpace, MinTrailSpace); #ifdef YAPOR fprintf(stderr," -w YapOr option: Number of workers (default: %d)\n", DEFAULT_NUMBERWORKERS); fprintf(stderr," -sl YapOr option: Loop scheduler executions before look for hiden shared work (default: %d)\n", DEFAULT_SCHEDULERLOOP); fprintf(stderr," -d YapOr option: Value of delayed release of load (default: %d)\n", DEFAULT_DELAYEDRELEASELOAD); #endif fprintf(stderr,"\n"); } /* * proccess command line arguments: valid switches are: -b boot -s * stack area size (K) -h heap area size -a aux stack size -e * emacs_mode -m reserved memory for alloc IF DEBUG -p if you * want to check out startup IF MAC -mpw if we are using the mpw * shell */ static int parse_yap_arguments(int argc, char *argv[], YAP_init_args *iap) { char *p; #if defined(SUPPORT_THREADS) || defined(SUPPORT_CONDOR) int BootMode = YAP_FULL_BOOT_FROM_PROLOG; #else int BootMode = YAP_BOOT_FROM_SAVED_CODE; #endif int *ssize; while (--argc > 0) { p = *++argv; if (*p == '-') switch (*++p) { case 'b': BootMode = YAP_BOOT_FROM_PROLOG; iap->YapPrologBootFile = *++argv; argc--; break; case '?': print_usage(); exit(EXIT_SUCCESS); case 'w': ssize = &(iap->NumberWorkers); goto GetSize; case 'd': ssize = &(iap->DelayedReleaseLoad); goto GetSize; #ifdef USE_SOCKET case 'c': /* running as client */ { char *host, *p1; long port; char *ptr; host = *++argv; argc--; if (host == NULL || host[0] == '-') YAP_Error("sockets must receive host to connect to"); p1 = *++argv; argc--; if (p1 == NULL || p1[0] == '-') YAP_Error("sockets must receive port to connect to"); port = strtol(p1, &ptr, 10); if (ptr == NULL || ptr[0] != '\0') YAP_Error("port argument to socket must be a number"); YAP_InitSocks(host,port); } break; #endif #ifdef EMACS case 'e': emacs_mode = TRUE; { File fd; strcpy (emacs_tmp, ++p); if ((fd = fopen (emacs_tmp, "w")) == NIL) fprintf(stderr, "[ Warning: unable to communicate with emacs: failed to open %s ]\n", emacs_tmp); fclose (fd); unlink (emacs_tmp); p = *++argv; --argc; strcpy (emacs_tmp2, p); if ((fd = fopen (emacs_tmp2, "w")) == NIL) fprintf(stderr, "Unable to communicate with emacs: failed to open %s\n", emacs_tmp2); fclose (fd); unlink (emacs_tmp2); } break; #endif /* EMACS */ case 'f': iap->FastBoot = TRUE; break; #ifdef MPWSHELL case 'm': if (*++p == 'p' && *++p == 'w' && *++p == '\0') mpwshell = TRUE; break; #endif case 's': case 'S': ssize = &(iap->StackSize); if (p[1] == 'l') { p++; ssize = &(iap->SchedulerLoop); } goto GetSize; case 'h': case 'H': ssize = &(iap->HeapSize); goto GetSize; case 't': case 'T': ssize = &(iap->TrailSize); 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); } } { int i = 0, ch; while ((ch = *p++) >= '0' && ch <= '9') i = i * 10 + ch - '0'; if (ch) { fprintf(stderr,"[ YAP unrecoverable error: illegal size specification %s ]", argv[-1]); YAP_Exit(1); } *ssize = i; } break; #ifdef DEBUG case 'p': YAP_SetOutputMessage(); output_msg = TRUE; break; #endif case 'L': p++; while (*p != '\0' && (*p == ' ' || *p == '\t')) p++; /* skip zeroth argument */ argc--; if (argc == 0) { fprintf(stderr," [ YAP unrecoverable error: missing file name with option 'l' ]\n"); exit(1); } argv++; if (p[0] == '-' && p[1] == '-'&& p[2] == '\0') { /* we're done here */ argc = 1; } iap->YapPrologRCFile = *argv; argv++; iap->HaltAfterConsult = TRUE; break; case 'l': if ((*argv)[0] == '\0') iap->YapPrologRCFile = *argv; else { argc--; if (argc == 0) { fprintf(stderr," [ YAP unrecoverable error: missing file name with option 'l' ]\n"); exit(EXIT_FAILURE); } argv++; iap->YapPrologRCFile = *argv; } break; case '-': /* skip remaining arguments */ argc = 1; break; default: { fprintf(stderr,"[ YAP unrecoverable error: unknown switch -%c ]\n", *p); print_usage(); exit(EXIT_FAILURE); } } else { iap->SavedState = p; } } return(BootMode); } static char boot_file[256]; static int init_standard_system(int argc, char *argv[], YAP_init_args *iap) { int BootMode; iap->SavedState = NULL; iap->HeapSize = 0; iap->StackSize = 0; iap->TrailSize = 0; iap->YapLibDir = NULL; iap->YapPrologBootFile = NULL; iap->YapPrologInitFile = NULL; iap->YapPrologRCFile = NULL; iap->HaltAfterConsult = FALSE; iap->FastBoot = FALSE; iap->NumberWorkers = DEFAULT_NUMBERWORKERS; iap->SchedulerLoop = DEFAULT_SCHEDULERLOOP; iap->DelayedReleaseLoad = DEFAULT_DELAYEDRELEASELOAD; iap->Argc = argc; iap->Argv = argv; BootMode = parse_yap_arguments(argc,argv,iap); if (BootMode == YAP_FULL_BOOT_FROM_PROLOG) { #if HAVE_STRNCAT strncpy(boot_file, PL_SRC_DIR, 256); #else strcpy(boot_file, PL_SRC_DIR); #endif #if HAVE_STRNCAT strncat(boot_file, BootFile, 256); #else strcat(boot_file, BootFile); #endif iap->YapPrologBootFile = boot_file; } /* init memory */ if (BootMode == YAP_BOOT_FROM_PROLOG || BootMode == YAP_FULL_BOOT_FROM_PROLOG) { YAP_Init(iap); } else { BootMode = YAP_Init(iap); } return(BootMode); } static void exec_top_level(int BootMode, YAP_init_args *iap) { YAP_Term atomfalse; YAP_Atom livegoal; if (BootMode == YAP_BOOT_FROM_SAVED_STACKS) { /* continue executing from the frozen stacks */ YAP_ContinueGoal(); } else if (BootMode == YAP_BOOT_FROM_PROLOG || BootMode == YAP_FULL_BOOT_FROM_PROLOG) { YAP_Atom livegoal; /* read the bootfile */ do_bootfile (iap->YapPrologBootFile ? iap->YapPrologBootFile : BootFile); livegoal = YAP_FullLookupAtom("$live"); /* initialise the top-level */ if (BootMode == YAP_FULL_BOOT_FROM_PROLOG) { char init_file[256]; YAP_Atom atfile; YAP_Functor fgoal; YAP_Term goal, as[2]; #if HAVE_STRNCAT strncpy(init_file, PL_SRC_DIR, 256); #else strcpy(init_file, PL_SRC_DIR); #endif #if HAVE_STRNCAT strncat(init_file, InitFile, 256); #else strcat(init_file, InitFile); #endif /* consult init file */ atfile = YAP_LookupAtom(init_file); as[0] = YAP_MkAtomTerm(atfile); as[1] = YAP_MkAtomTerm(YAP_LookupAtom("prolog")); fgoal = YAP_MkFunctor(YAP_FullLookupAtom("$consult"), 2); goal = YAP_MkApplTerm(fgoal, 2, as); /* launch consult */ YAP_RunGoal(goal); /* set default module to user */ as[0] = YAP_MkAtomTerm(YAP_LookupAtom("user")); fgoal = YAP_MkFunctor(YAP_FullLookupAtom("module"), 1); goal = YAP_MkApplTerm(fgoal, 1, as); YAP_RunGoal(goal); } YAP_PutValue(livegoal, YAP_MkAtomTerm (YAP_FullLookupAtom("$true"))); } /* the top-level is now ready */ /* read it before case someone, that is, Ashwin, hides the atom false away ;-). */ livegoal = YAP_FullLookupAtom("$live"); atomfalse = YAP_MkAtomTerm (YAP_FullLookupAtom("$false")); { YAP_Term t = YAP_ReadBuffer("a(1)",NULL); if (t) YAP_Write(t,myputc,0); } while (YAP_GetValue (livegoal) != atomfalse) { YAP_Reset(); do_top_goal (YAP_MkAtomTerm (livegoal)); } YAP_Exit(EXIT_SUCCESS); } #ifdef LIGHT int _main (int argc, char **argv) #else int main (int argc, char **argv) #endif { int BootMode; YAP_init_args init_args; BootMode = init_standard_system(argc, argv, &init_args); if (BootMode == YAP_BOOT_FROM_SAVED_ERROR) { fprintf(stderr,"[ FATAL ERROR: could not find saved state ]\n"); exit(1); } exec_top_level(BootMode, &init_args); return(0); }