This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
vsc f11ab09a60 try to make initialisation process more robust
try to make name more robust (in case Lookup new atom fails)


git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1254 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
2005-03-02 18:35:49 +00:00

571 lines
13 KiB
C

/*************************************************************************
* *
* 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 <stdio.h>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
#if HAVE_STDARG_H
#include <stdarg.h>
#endif
#include <stdlib.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#if HAVE_STRING_H
#include <string.h>
#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 <unix.h>
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;
#if USE_MYPUTC
static void
myputc (int ch)
{
putc(ch,stderr);
}
#endif
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 USE_MALLOC
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(0,0L,"sockets must receive host to connect to");
p1 = *++argv;
argc--;
if (p1 == NULL || p1[0] == '-')
YAP_Error(0,0L,"sockets must receive port to connect to");
port = strtol(p1, &ptr, 10);
if (ptr == NULL || ptr[0] != '\0')
YAP_Error(0,0L,"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->PrologShouldHandleInterrupts = TRUE;
iap->Argc = argc;
iap->Argv = argv;
iap->ErrorNo = 0;
iap->ErrorCause = NULL;
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) {
BootMode = YAP_Init(iap);
} else {
BootMode = YAP_Init(iap);
}
if (iap->ErrorNo) {
/* boot failed */
YAP_Error(iap->ErrorNo,0L,iap->ErrorCause);
}
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"));
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_ERROR) {
fprintf(stderr,"[ FATAL ERROR: could not find saved state ]\n");
exit(1);
}
exec_top_level(BootMode, &init_args);
return(0);
}