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.
yap-6.3/console/yap.c
2003-02-19 16:43:24 +00:00

513 lines
12 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";
#ifdef lint
/* VARARGS1 */
#endif
#ifdef M_WILLIAMS
long _stksize = 32000;
#endif
static FILE *bootfile;
static int eof_found = FALSE;
static int yap_lineno = 0;
#ifdef DEBUG
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;
int BootMode = YAP_BOOT_FROM_SAVED_CODE;
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[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 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->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);
/* init memory */
if (BootMode == YAP_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)
{
YAP_Atom livegoal;
/* read the bootfile */
do_bootfile (iap->YapPrologBootFile ? iap->YapPrologBootFile : BootFile);
livegoal = YAP_FullLookupAtom("$live");
/* initialise the top-level */
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;
#ifdef SIMICS
fprintf(stdout,"Entering YAP\n");
#endif /* SIMICS */
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);
}
#if defined(YAPOR) || defined(TABLING)
start_workers();
#endif /* YAPOR || TABLING */
exec_top_level(BootMode, &init_args);
return(0);
}