/************************************************************************* * * * YAP Prolog * * * * Yap Prolog was developed at NCCUP - Universidade do Porto * * * * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 * * * ************************************************************************** * * * File: init.c * * Last rev: * * mods: * * comments: initializing a prolog session * * * *************************************************************************/ #ifdef SCCS static char SccsId[] = "%W% %G%"; #endif /* * The code from this file is used to initialize the environment for prolog * */ #include #include "Yap.h" #include "clause.h" #include "pl-shared.h" #include "yapio.h" #include "alloc.h" #include "Foreign.h" #include "SWI-Prolog.h" #ifdef LOW_LEVEL_TRACER #include "tracer.h" #endif #ifdef YAPOR #ifdef YAPOR_COW #include #endif /* YAPOR_COW */ #include "or.macros.h" #endif /* YAPOR */ #if defined(YAPOR) || defined(TABLING) #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_STAT_H #include #endif #if HAVE_FCNTL_H #include #endif #endif /* YAPOR || TABLING */ #if HAVE_STRING_H #include #endif int Yap_output_msg = FALSE; #if DEBUG #define LOGFILE "logfile" #ifdef MACC static void InTTYLine(char *); #endif #endif static void SetOp(int, int, char *, Term); static void InitOps(void); static void InitDebug(void); static void CleanBack(PredEntry *, CPredicate, CPredicate, CPredicate); static void InitStdPreds(void); static void InitFlags(void); static void InitCodes(void); static void InitVersion(void); void exit(int); static void InitWorker(int wid); /************** YAP PROLOG GLOBAL VARIABLES *************************/ /************* variables related to memory allocation ***************/ ADDR Yap_HeapBase; /************** declarations local to init.c ************************/ static char *optypes[] = {"", "xfx", "xfy", "yfx", "xf", "yf", "fx", "fy"}; /* OS page size for memory allocation */ int Yap_page_size; #if USE_THREADED_CODE /* easy access to instruction opcodes */ void **Yap_ABSMI_OPCODES; #endif #if DEBUG #if COROUTINING int Yap_Portray_delays = FALSE; #endif #endif /** @defgroup Operators Summary of YAP Predefined Operators @ingroup Syntax @{ The Prolog syntax caters for operators of three main kinds: + prefix; + infix; + postfix. Each operator has precedence in the range 1 to 1200, and this precedence is used to disambiguate expressions where the structure of the term denoted is not made explicit using brackets. The operator of higher precedence is the main functor. If there are two operators with the highest precedence, the ambiguity is solved analyzing the types of the operators. The possible infix types are: _xfx_, _xfy_, and _yfx_. With an operator of type _xfx_ both sub-expressions must have lower precedence than the operator itself, unless they are bracketed (which assigns to them zero precedence). With an operator type _xfy_ only the left-hand sub-expression must have lower precedence. The opposite happens for _yfx_ type. A prefix operator can be of type _fx_ or _fy_. A postfix operator can be of type _xf_ or _yf_. The meaning of the notation is analogous to the above. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ a + b * c ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ means ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ a + (b * c) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ as + and \* have the following types and precedences: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :-op(500,yfx,'+'). :-op(400,yfx,'*'). ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Now defining ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :-op(700,xfy,'++'). :-op(700,xfx,'=:='). a ++ b =:= c ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ means ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ a ++ (b =:= c) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following is the list of the declarations of the predefined operators: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :-op(1200,fx,['?-', ':-']). :-op(1200,xfx,[':-','-->']). :-op(1150,fx,[block,dynamic,mode,public,multifile,meta_predicate, sequential,table,initialization]). :-op(1100,xfy,[';','|']). :-op(1050,xfy,->). :-op(1000,xfy,','). :-op(999,xfy,'.'). :-op(900,fy,['\+', not]). :-op(900,fx,[nospy, spy]). :-op(700,xfx,[@>=,@=<,@<,@>,<,=,>,=:=,=\=,\==,>=,=<,==,\=,=..,is]). :-op(500,yfx,['\/','/\','+','-']). :-op(500,fx,['+','-']). :-op(400,yfx,['<<','>>','//','*','/']). :-op(300,xfx,mod). :-op(200,xfy,['^','**']). :-op(50,xfx,same). ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ #define xfx 1 #define xfy 2 #define yfx 3 #define xf 4 #define yf 5 #define fx 6 #define fy 7 int Yap_IsOpType(char *type) { int i; for (i = 1; i <= 7; ++i) if (strcmp(type, optypes[i]) == 0) break; return (i <= 7); } static int OpDec(int p, const char *type, Atom a, Term m) { int i; AtomEntry *ae = RepAtom(a); OpEntry *info; if (m == TermProlog) m = PROLOG_MODULE; else if (m == USER_MODULE) m = PROLOG_MODULE; for (i = 1; i <= 7; ++i) if (strcmp(type, optypes[i]) == 0) break; if (i > 7) { Yap_Error(DOMAIN_ERROR_OPERATOR_SPECIFIER,MkAtomTerm(Yap_LookupAtom(type)),"op/3"); return(FALSE); } if (p) { if (i == 1 || i == 2 || i == 4) p |= DcrlpFlag; if (i == 1 || i == 3 || i == 6) p |= DcrrpFlag; } WRITE_LOCK(ae->ARWLock); info = Yap_GetOpPropForAModuleHavingALock(ae, m); if (EndOfPAEntr(info)) { info = (OpEntry *) Yap_AllocAtomSpace(sizeof(OpEntry)); info->KindOfPE = Ord(OpProperty); info->OpModule = m; info->OpName = a; //LOCK(OpListLock); info->OpNext = OpList; OpList = info; //UNLOCK(OpListLock); AddPropToAtom(ae, (PropEntry *)info); INIT_RWLOCK(info->OpRWLock); WRITE_LOCK(info->OpRWLock); WRITE_UNLOCK(ae->ARWLock); info->Prefix = info->Infix = info->Posfix = 0; } else { WRITE_LOCK(info->OpRWLock); WRITE_UNLOCK(ae->ARWLock); } if (i <= 3) { GET_LD if (truePrologFlag(PLFLAG_ISO) && info->Posfix != 0) /* there is a posfix operator */ { /* ISO dictates */ WRITE_UNLOCK(info->OpRWLock); Yap_Error(PERMISSION_ERROR_CREATE_OPERATOR,MkAtomTerm(a),"op/3"); return FALSE; } info->Infix = p; } else if (i <= 5) { GET_LD if (truePrologFlag(PLFLAG_ISO) && info->Infix != 0) /* there is an infix operator */ { /* ISO dictates */ WRITE_UNLOCK(info->OpRWLock); Yap_Error(PERMISSION_ERROR_CREATE_OPERATOR,MkAtomTerm(a),"op/3"); return FALSE; } info->Posfix = p; } else { info->Prefix = p; } WRITE_UNLOCK(info->OpRWLock); return (TRUE); } int Yap_OpDec(int p, char *type, Atom a, Term m) { return(OpDec(p,type,a,m)); } static void SetOp(int p, int type, char *at, Term m) { #if DEBUG if (GLOBAL_Option[5]) fprintf(stderr,"[setop %d %s %s]\n", p, optypes[type], at); #endif OpDec(p, optypes[type], Yap_LookupAtom(at), m); } /* Gets the info about an operator in a prop */ Atom Yap_GetOp(OpEntry *pp, int *prio, int fix) { int n; SMALLUNSGN p; if (fix == 0) { p = pp->Prefix; if (p & DcrrpFlag) n = 6, *prio = (p ^ DcrrpFlag); else n = 7, *prio = p; } else if (fix == 1) { p = pp->Posfix; if (p & DcrlpFlag) n = 4, *prio = (p ^ DcrlpFlag); else n = 5, *prio = p; } else { p = pp->Infix; if ((p & DcrrpFlag) && (p & DcrlpFlag)) n = 1, *prio = (p ^ (DcrrpFlag | DcrlpFlag)); else if (p & DcrrpFlag) n = 3, *prio = (p ^ DcrrpFlag); else if (p & DcrlpFlag) n = 2, *prio = (p ^ DcrlpFlag); else n = 4, *prio = p; } return Yap_LookupAtom(optypes[n]); } typedef struct OPSTRUCT { char *opName; short int opType, opPrio; } Opdef; static Opdef Ops[] = { {":-", xfx, 1200}, {"-->", xfx, 1200}, {"?-", fx, 1200}, {":-", fx, 1200}, {"dynamic", fx, 1150}, {"thread_local", fx, 1150}, {"initialization", fx, 1150}, {"volatile", fx, 1150}, {"mode", fx, 1150}, {"public", fx, 1150}, {"multifile", fx, 1150}, {"meta_predicate", fx, 1150}, {"module_transparent", fx, 1150}, {"discontiguous", fx, 1150}, #ifdef YAPOR {"sequential", fx, 1150}, #endif /* YAPOR */ #ifdef TABLING {"table", fx, 1150}, #endif /* TABLING */ #ifndef UNCUTABLE {"uncutable", fx, 1150}, #endif /*UNCUTABLE ceh:*/ {"|", xfy, 1105}, {";", xfy, 1100}, /* {";", yf, 1100}, not allowed in ISO */ {"->", xfy, 1050}, {"*->", xfy, 1050}, {",", xfy, 1000}, {".", xfy, 999}, {"\\+", fy, 900}, {"not", fy, 900}, {"=", xfx, 700}, {"\\=", xfx, 700}, {"is", xfx, 700}, {"=..", xfx, 700}, {"==", xfx, 700}, {"\\==", xfx, 700}, {"@<", xfx, 700}, {"@>", xfx, 700}, {"@=<", xfx, 700}, {"@>=", xfx, 700}, {"=@=", xfx, 700}, {"\\=@=", xfx, 700}, {"=:=", xfx, 700}, {"=\\=", xfx, 700}, {"<", xfx, 700}, {">", xfx, 700}, {"=<", xfx, 700}, {">=", xfx, 700}, {"as", xfx, 600}, {":", xfy, 600}, {"+", yfx, 500}, {"-", yfx, 500}, {"/\\", yfx, 500}, {"\\/", yfx, 500}, {"><", yfx, 500}, {"#", yfx, 500}, {"rdiv", yfx, 400}, {"div", yfx, 400}, {"xor", yfx, 400}, {"*", yfx, 400}, {"/", yfx, 400}, {"//", yfx, 400}, {"<<", yfx, 400}, {">>", yfx, 400}, {"mod", yfx, 400}, {"rem", yfx, 400}, {"+", fy, 200}, {"-", fy, 200}, {"\\", fy, 200}, {"//", yfx, 400}, {"**", xfx, 200}, {"^", xfy, 200} }; static void InitOps(void) { unsigned int i; for (i = 0; i < sizeof(Ops) / sizeof(*Ops); ++i) SetOp(Ops[i].opPrio, Ops[i].opType, Ops[i].opName, PROLOG_MODULE); } /// @} #if DEBUG #ifdef HAVE_ISATTY #include #endif #endif static void InitDebug(void) { Atom At; #if DEBUG int i; for (i = 1; i < 20; ++i) GLOBAL_Option[i] = 0; if (Yap_output_msg) { char ch; #if HAVE_ISATTY if (!isatty (0)) { return; } #endif fprintf(stderr,"absmi address:%p\n", FunAdr(Yap_absmi)); fprintf(stderr,"Set Trace Options:\n"); fprintf(stderr,"a getch\t\tb token\t\tc Lookup\td LookupVar\ti Index\n"); fprintf(stderr,"e SetOp\t\tf compile\tg icode\t\th boot\t\tl log\n"); fprintf(stderr,"m Machine\t p parser\n"); while ((ch = YP_putchar(YP_getchar())) != '\n') if (ch >= 'a' && ch <= 'z') GLOBAL_Option[ch - 'a' + 1] = 1; if (GLOBAL_Option['l' - 96]) { GLOBAL_logfile = fopen(LOGFILE, "w"); if (GLOBAL_logfile == NULL) { fprintf(stderr,"can not open %s\n", LOGFILE); getchar(); exit(0); } fprintf(stderr,"logging session to file 'logfile'\n"); #ifdef MAC Yap_SetTextFile(LOGFILE); lp = my_line; curfile = Nill; #endif } } #endif /* Set at full leash */ At = AtomLeash; Yap_PutValue(At, MkIntTerm(15)); } static UInt update_flags_from_prolog(UInt flags, PredEntry *pe) { if (pe->PredFlags & MetaPredFlag) flags |= MetaPredFlag; if (pe->PredFlags & SourcePredFlag) flags |= SourcePredFlag; if (pe->PredFlags & SequentialPredFlag) flags |= SequentialPredFlag; if (pe->PredFlags & UDIPredFlag) flags |= UDIPredFlag; if (pe->PredFlags & ModuleTransparentPredFlag) flags |= ModuleTransparentPredFlag; return flags; } void Yap_InitCPred(const char *Name, UInt Arity, CPredicate code, pred_flags_t flags) { CACHE_REGS Atom atom = NIL; PredEntry *pe = NULL; yamop *p_code; StaticClause *cl = NULL; Functor f = NULL; while (atom == NIL) { if (flags & UserCPredFlag) atom = Yap_LookupAtom(Name); else atom = Yap_FullLookupAtom(Name); if (atom == NIL && !Yap_growheap(FALSE, 0L, NULL)) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"while initialising %s", Name); return; } } if (Arity) { while (!f) { f = Yap_MkFunctor(atom,Arity); if (!f && !Yap_growheap(FALSE, 0L, NULL)) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"while initialising %s", Name); return; } } } while (pe == NULL) { if (Arity) pe = RepPredProp(PredPropByFunc(f,CurrentModule)); else pe = RepPredProp(PredPropByAtom(atom,CurrentModule)); if (!pe && !Yap_growheap(FALSE, sizeof(PredEntry), NULL)) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"while initialising %s", Name); return; } } if (pe->PredFlags & CPredFlag) { /* already exists */ flags = update_flags_from_prolog(flags, pe); cl = ClauseCodeToStaticClause(pe->CodeOfPred); if ((flags | StandardPredFlag | CPredFlag ) != pe->PredFlags) { Yap_ClauseSpace -= cl->ClSize; Yap_FreeCodeSpace((ADDR)cl); cl = NULL; } } p_code = cl->ClCode; while (!cl) { UInt sz; if (flags & SafePredFlag) { sz = (CELL)NEXTOP(NEXTOP(NEXTOP(p_code,Osbpp),p),l); } else { sz = (CELL)NEXTOP(NEXTOP(NEXTOP(NEXTOP(NEXTOP(p_code,e),p),Osbpp),p),l); } cl = (StaticClause *)Yap_AllocCodeSpace(sz); if (!cl) { if (!Yap_growheap(FALSE, sz, NULL)) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"while initialising %s", Name); return; } } else { Yap_ClauseSpace += sz; cl->ClFlags = StaticMask; cl->ClNext = NULL; cl->ClSize = sz; cl->usc.ClLine = Yap_source_line_no(); p_code = cl->ClCode; } } pe->CodeOfPred = p_code; pe->PredFlags = flags | StandardPredFlag | CPredFlag; pe->src.OwnerFile = Yap_ConsultingFile( PASS_REGS1 ); pe->cs.f_code = code; if (!(flags & SafePredFlag)) { p_code->opc = Yap_opcode(_allocate); p_code = NEXTOP(p_code,e); } if (flags & UserCPredFlag) p_code->opc = Yap_opcode(_call_usercpred); else p_code->opc = Yap_opcode(_call_cpred); p_code->y_u.Osbpp.bmap = NULL; p_code->y_u.Osbpp.s = -Signed(RealEnvSize); p_code->y_u.Osbpp.p = p_code->y_u.Osbpp.p0 = pe; p_code = NEXTOP(p_code,Osbpp); if (!(flags & SafePredFlag)) { p_code->opc = Yap_opcode(_deallocate); p_code->y_u.p.p = pe; p_code = NEXTOP(p_code,p); } p_code->opc = Yap_opcode(_procceed); p_code->y_u.p.p = pe; p_code = NEXTOP(p_code,p); p_code->opc = Yap_opcode(_Ystop); p_code->y_u.l.l = cl->ClCode; pe->OpcodeOfPred = pe->CodeOfPred->opc; } void Yap_InitCmpPred(const char *Name, UInt Arity, CmpPredicate cmp_code, pred_flags_t flags) { CACHE_REGS Atom atom = NIL; PredEntry *pe = NULL; yamop *p_code = NULL; StaticClause *cl = NULL; Functor f = NULL; while (atom == NIL) { atom = Yap_FullLookupAtom(Name); if (atom == NIL && !Yap_growheap(FALSE, 0L, NULL)) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"while initialising %s", Name); return; } } if (Arity) { while (!f) { f = Yap_MkFunctor(atom,Arity); if (!f && !Yap_growheap(FALSE, 0L, NULL)) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"while initialising %s", Name); return; } } } while (pe == NULL) { if (Arity) pe = RepPredProp(PredPropByFunc(f,CurrentModule)); else pe = RepPredProp(PredPropByAtom(atom,CurrentModule)); if (!pe && !Yap_growheap(FALSE, sizeof(PredEntry), NULL)) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"while initialising %s", Name); return; } } if (pe->PredFlags & BinaryPredFlag) { flags = update_flags_from_prolog(flags, pe); p_code = pe->CodeOfPred; /* already exists */ } else { while (!cl) { UInt sz = sizeof(StaticClause)+(CELL)NEXTOP(NEXTOP(NEXTOP(((yamop *)NULL),plxxs),p),l); cl = (StaticClause *)Yap_AllocCodeSpace(sz); if (!cl) { if (!Yap_growheap(FALSE, sz, NULL)) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"while initialising %s", Name); return; } } else { Yap_ClauseSpace += sz; cl->ClFlags = StaticMask; cl->ClNext = NULL; cl->ClSize = sz; cl->usc.ClLine = Yap_source_line_no(); p_code = cl->ClCode; break; } } } //pe->PredFlags = flags | StandardPredFlag; pe->CodeOfPred = p_code; pe->cs.d_code = cmp_code; pe->ModuleOfPred = CurrentModule; p_code->opc = pe->OpcodeOfPred = Yap_opcode(_call_bfunc_xx); p_code->y_u.plxxs.p = pe; p_code->y_u.plxxs.f = FAILCODE; p_code->y_u.plxxs.x1 = Yap_emit_x(1); p_code->y_u.plxxs.x2 = Yap_emit_x(2); p_code->y_u.plxxs.flags = Yap_compile_cmp_flags(pe); p_code = NEXTOP(p_code,plxxs); p_code->opc = Yap_opcode(_procceed); p_code->y_u.p.p = pe; p_code = NEXTOP(p_code,p); p_code->opc = Yap_opcode(_Ystop); p_code->y_u.l.l = cl->ClCode; } void Yap_InitAsmPred(const char *Name, UInt Arity, int code, CPredicate def, pred_flags_t flags) { CACHE_REGS Atom atom = NIL; PredEntry *pe = NULL; Functor f = NULL; while (atom == NIL) { atom = Yap_FullLookupAtom(Name); if (atom == NIL && !Yap_growheap(FALSE, 0L, NULL)) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"while initialising %s", Name); return; } } if (Arity) { while (!f) { f = Yap_MkFunctor(atom,Arity); if (!f && !Yap_growheap(FALSE, 0L, NULL)) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"while initialising %s", Name); return; } } } while (pe == NULL) { if (Arity) pe = RepPredProp(PredPropByFunc(f,CurrentModule)); else pe = RepPredProp(PredPropByAtom(atom,CurrentModule)); if (!pe && !Yap_growheap(FALSE, sizeof(PredEntry), NULL)) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"while initialising %s", Name); return; } } flags |= AsmPredFlag | StandardPredFlag | (code); if (pe->PredFlags & AsmPredFlag) { flags = update_flags_from_prolog(flags, pe); /* already exists */ } pe->PredFlags = flags; pe->cs.f_code = def; pe->ModuleOfPred = CurrentModule; if (def != NULL) { yamop *p_code = ((StaticClause *)NULL)->ClCode; StaticClause *cl; if (pe->CodeOfPred == (yamop *)(&(pe->OpcodeOfPred))) { if (flags & SafePredFlag) { cl = (StaticClause *)Yap_AllocCodeSpace((CELL)NEXTOP(NEXTOP(NEXTOP(((yamop *)p_code),Osbpp),p),l)); } else { cl = (StaticClause *)Yap_AllocCodeSpace((CELL)NEXTOP(NEXTOP(NEXTOP(NEXTOP(NEXTOP(((yamop *)p_code),e),Osbpp),p),p),l)); } if (!cl) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"No Heap Space in InitAsmPred"); return; } Yap_ClauseSpace += (CELL)NEXTOP(NEXTOP(NEXTOP(((yamop *)p_code),Osbpp),p),l); } else { cl = ClauseCodeToStaticClause(pe->CodeOfPred); } cl->ClFlags = StaticMask; cl->ClNext = NULL; if (flags & SafePredFlag) { cl->ClSize = (CELL)NEXTOP(NEXTOP(NEXTOP(((yamop *)p_code),Osbpp),e),e); } else { cl->ClSize = (CELL)NEXTOP(NEXTOP(NEXTOP(NEXTOP(NEXTOP(((yamop *)p_code),e),Osbpp),p),e),e); } cl->usc.ClLine = Yap_source_line_no(); p_code = cl->ClCode; pe->CodeOfPred = p_code; if (!(flags & SafePredFlag)) { p_code->opc = Yap_opcode(_allocate); p_code = NEXTOP(p_code,e); } p_code->opc = Yap_opcode(_call_cpred); p_code->y_u.Osbpp.bmap = NULL; p_code->y_u.Osbpp.s = -Signed(RealEnvSize); p_code->y_u.Osbpp.p = p_code->y_u.Osbpp.p0 = pe; p_code = NEXTOP(p_code,Osbpp); if (!(flags & SafePredFlag)) { p_code->opc = Yap_opcode(_deallocate); p_code->y_u.p.p = pe; p_code = NEXTOP(p_code,p); } p_code->opc = Yap_opcode(_procceed); p_code->y_u.p.p = pe; p_code = NEXTOP(p_code,p); p_code->opc = Yap_opcode(_Ystop); p_code->y_u.l.l = cl->ClCode; pe->OpcodeOfPred = pe->CodeOfPred->opc; } else { pe->OpcodeOfPred = Yap_opcode(_undef_p); pe->CodeOfPred = (yamop *)(&(pe->OpcodeOfPred)); } } static void CleanBack(PredEntry *pe, CPredicate Start, CPredicate Cont, CPredicate Cut) { yamop *code; if (pe->cs.p_code.FirstClause != pe->cs.p_code.LastClause || pe->cs.p_code.TrueCodeOfPred != pe->cs.p_code.FirstClause || pe->CodeOfPred != pe->cs.p_code.FirstClause) { Yap_Error(SYSTEM_ERROR,TermNil, "initiating a C Pred with backtracking"); return; } code = (yamop *)(pe->cs.p_code.FirstClause); code->y_u.OtapFs.p = pe; if (pe->PredFlags & UserCPredFlag) code->opc = Yap_opcode(_try_userc); else code->opc = Yap_opcode(_try_c); #ifdef YAPOR INIT_YAMOP_LTT(code, 2); PUT_YAMOP_SEQ(code); #endif /* YAPOR */ code->y_u.OtapFs.f = Start; code = NEXTOP(code,OtapFs); if (pe->PredFlags & UserCPredFlag) code->opc = Yap_opcode(_retry_userc); else code->opc = Yap_opcode(_retry_c); #ifdef YAPOR INIT_YAMOP_LTT(code, 1); PUT_YAMOP_SEQ(code); #endif /* YAPOR */ code->y_u.OtapFs.f = Cont; code = NEXTOP(code,OtapFs); if (pe->PredFlags & UserCPredFlag) code->opc = Yap_opcode(_cut_c); else code->opc = Yap_opcode(_cut_userc); code->y_u.OtapFs.p = pe; code->y_u.OtapFs.f = Cut; } void Yap_InitCPredBack(const char *Name, UInt Arity, unsigned int Extra, CPredicate Start, CPredicate Cont, pred_flags_t flags){ Yap_InitCPredBack_(Name,Arity,Extra,Start,Cont,NULL,flags); } void Yap_InitCPredBackCut(const char *Name, UInt Arity, unsigned int Extra, CPredicate Start, CPredicate Cont,CPredicate Cut, pred_flags_t flags){ Yap_InitCPredBack_(Name,Arity,Extra,Start,Cont,Cut,flags); } void Yap_InitCPredBack_(const char *Name, UInt Arity, unsigned int Extra, CPredicate Start, CPredicate Cont, CPredicate Cut, pred_flags_t flags) { CACHE_REGS PredEntry *pe = NULL; Atom atom = NIL; Functor f = NULL; while (atom == NIL) { atom = Yap_FullLookupAtom(Name); if (atom == NIL && !Yap_growheap(FALSE, 0L, NULL)) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"while initialising %s", Name); return; } } if (Arity) { while (!f) { f = Yap_MkFunctor(atom,Arity); if (!f && !Yap_growheap(FALSE, 0L, NULL)) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"while initialising %s", Name); return; } } } while (pe == NULL) { if (Arity) pe = RepPredProp(PredPropByFunc(f,CurrentModule)); else pe = RepPredProp(PredPropByAtom(atom,CurrentModule)); if (!pe && !Yap_growheap(FALSE, sizeof(PredEntry), NULL)) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"while initialising %s", Name); return; } } if (pe->cs.p_code.FirstClause != NIL) { flags = update_flags_from_prolog(flags, pe); CleanBack(pe, Start, Cont, Cut); } else { StaticClause *cl; yamop *code = ((StaticClause *)NULL)->ClCode; UInt sz = (CELL)NEXTOP(NEXTOP(NEXTOP(NEXTOP(code,OtapFs),OtapFs),OtapFs),l); if (flags & UserCPredFlag) pe->PredFlags = UserCPredFlag | BackCPredFlag| CompiledPredFlag | StandardPredFlag | flags; else pe->PredFlags = CompiledPredFlag | StandardPredFlag | BackCPredFlag; #ifdef YAPOR pe->PredFlags |= SequentialPredFlag; #endif /* YAPOR */ cl = (StaticClause *)Yap_AllocCodeSpace(sz); if (cl == NULL) { Yap_Error(OUT_OF_HEAP_ERROR,TermNil,"No Heap Space in InitCPredBack"); return; } cl->ClFlags = StaticMask; cl->ClNext = NULL; Yap_ClauseSpace += sz; cl->ClSize = (CELL)NEXTOP(NEXTOP(NEXTOP(NEXTOP(code,OtapFs),OtapFs),OtapFs),e); cl->usc.ClLine = Yap_source_line_no(); code = cl->ClCode; pe->cs.p_code.TrueCodeOfPred = pe->CodeOfPred = pe->cs.p_code.FirstClause = pe->cs.p_code.LastClause = code; if (flags & UserCPredFlag) pe->OpcodeOfPred = code->opc = Yap_opcode(_try_userc); else pe->OpcodeOfPred = code->opc = Yap_opcode(_try_c); code->y_u.OtapFs.f = Start; code->y_u.OtapFs.p = pe; code->y_u.OtapFs.s = Arity; code->y_u.OtapFs.extra = Extra; #ifdef YAPOR INIT_YAMOP_LTT(code, 2); PUT_YAMOP_SEQ(code); #endif /* YAPOR */ code = NEXTOP(code,OtapFs); if (flags & UserCPredFlag) code->opc = Yap_opcode(_retry_userc); else code->opc = Yap_opcode(_retry_c); code->y_u.OtapFs.f = Cont; code->y_u.OtapFs.p = pe; code->y_u.OtapFs.s = Arity; code->y_u.OtapFs.extra = Extra; #ifdef YAPOR INIT_YAMOP_LTT(code, 1); PUT_YAMOP_SEQ(code); #endif /* YAPOR */ code = NEXTOP(code,OtapFs); if (flags & UserCPredFlag) code->opc = Yap_opcode(_cut_userc); else code->opc = Yap_opcode(_cut_c); code->y_u.OtapFs.f = Cut; code->y_u.OtapFs.p = pe; code->y_u.OtapFs.s = Arity; code->y_u.OtapFs.extra = Extra; code = NEXTOP(code,OtapFs); code->opc = Yap_opcode(_Ystop); code->y_u.l.l = cl->ClCode; } } static void InitStdPreds(void) { void initIO(void); Yap_InitCPreds(); Yap_InitBackCPreds(); BACKUP_MACHINE_REGS(); Yap_InitYaamRegs( 0 ); #if HAVE_MPE Yap_InitMPE (); #endif initIO(); } static void InitFlags(void) { /* note that Yap_heap_regs must be set first */ yap_flags[LANGUAGE_MODE_FLAG] = 0; yap_flags[FLOATING_POINT_EXCEPTION_MODE_FLAG] = TRUE; yap_flags[SOURCE_MODE_FLAG] = FALSE; yap_flags[WRITE_QUOTED_STRING_FLAG] = FALSE; /* we do not garantee safe assert in parallel mode */ yap_flags[ALLOW_ASSERTING_STATIC_FLAG] = TRUE; /* current default */ yap_flags[INDEXING_MODE_FLAG] = INDEX_MODE_MULTI; yap_flags[TABLING_MODE_FLAG] = 0; yap_flags[QUIET_MODE_FLAG] = FALSE; yap_flags[INDEXING_TERM_DEPTH_FLAG] = 0L; } static void InitPredHash(void) { UInt i; PredHash = (PredEntry **)Yap_AllocAtomSpace(sizeof(PredEntry **) * PredHashInitialSize); PredHashTableSize = PredHashInitialSize; if (PredHash == NULL) { Yap_Error(FATAL_ERROR,MkIntTerm(0),"allocating initial predicate hash table"); } for (i = 0; i < PredHashTableSize; ++i) { PredHash[i] = NULL; } INIT_RWLOCK(PredHashRWLock); } static void InitEnvInst(yamop start[2], yamop **instp, op_numbers opc, PredEntry *pred) { yamop *ipc = start; /* make it look like the instruction is preceeded by a call instruction */ ipc->opc = Yap_opcode(_call); ipc->y_u.Osbpp.s = -Signed(RealEnvSize); ipc->y_u.Osbpp.bmap = NULL; ipc->y_u.Osbpp.p = pred; ipc->y_u.Osbpp.p0 = pred; ipc = NEXTOP(ipc, Osbpp); ipc->opc = Yap_opcode(opc); *instp = ipc; } static void InitOtaplInst(yamop start[1], OPCODE opc, PredEntry *pe) { yamop *ipc = start; /* this is a place holder, it should not really be used */ ipc->opc = Yap_opcode(opc); ipc->y_u.Otapl.s = 0; ipc->y_u.Otapl.p = pe; ipc->y_u.Otapl.d = NULL; #ifdef YAPOR INIT_YAMOP_LTT(ipc, 1); #endif /* YAPOR */ #ifdef TABLING ipc->y_u.Otapl.te = NULL; #endif /* TABLING */ } static void InitDBErasedMarker(void) { Yap_heap_regs->db_erased_marker = (DBRef)Yap_AllocCodeSpace(sizeof(DBStruct)); Yap_LUClauseSpace += sizeof(DBStruct); Yap_heap_regs->db_erased_marker->id = FunctorDBRef; Yap_heap_regs->db_erased_marker->Flags = ErasedMask; Yap_heap_regs->db_erased_marker->Code = NULL; Yap_heap_regs->db_erased_marker->DBT.DBRefs = NULL; Yap_heap_regs->db_erased_marker->Parent = NULL; } static void InitLogDBErasedMarker(void) { Yap_heap_regs->logdb_erased_marker = (LogUpdClause *)Yap_AllocCodeSpace(sizeof(LogUpdClause)+(UInt)NEXTOP((yamop*)NULL,e)); Yap_LUClauseSpace += sizeof(LogUpdClause)+(UInt)NEXTOP((yamop*)NULL,e); Yap_heap_regs->logdb_erased_marker->Id = FunctorDBRef; Yap_heap_regs->logdb_erased_marker->ClFlags = ErasedMask|LogUpdMask; Yap_heap_regs->logdb_erased_marker->lusl.ClSource = NULL; Yap_heap_regs->logdb_erased_marker->ClRefCount = 0; Yap_heap_regs->logdb_erased_marker->ClExt = NULL; Yap_heap_regs->logdb_erased_marker->ClPrev = NULL; Yap_heap_regs->logdb_erased_marker->ClNext = NULL; Yap_heap_regs->logdb_erased_marker->ClSize = (UInt)NEXTOP(((LogUpdClause *)NULL)->ClCode,e); Yap_heap_regs->logdb_erased_marker->ClCode->opc = Yap_opcode(_op_fail); INIT_CLREF_COUNT(Yap_heap_regs->logdb_erased_marker); } static void InitSWIAtoms(void) { extern atom_t ATOM_; int j=0; MaxAtomTranslations = 2*N_SWI_ATOMS ; SWI_Atoms = (Atom *)malloc(sizeof(Atom)*MaxAtomTranslations); SWI_Functors = (Functor *)malloc(sizeof(Functor)*2*N_SWI_ATOMS); #include "iswiatoms.h" Yap_InitSWIHash(); ATOM_ = PL_new_atom(""); } static void InitEmptyWakeups(void) { } static void InitAtoms(void) { int i; AtomHashTableSize = MaxHash; HashChain = (AtomHashEntry *)Yap_AllocAtomSpace(sizeof(AtomHashEntry) * MaxHash); if (HashChain == NULL) { Yap_Error(FATAL_ERROR,MkIntTerm(0),"allocating initial atom table"); } for (i = 0; i < MaxHash; ++i) { INIT_RWLOCK(HashChain[i].AERWLock); HashChain[i].Entry = NIL; } NOfAtoms = 0; #if THREADS SF_STORE->AtFoundVar = Yap_LookupAtom("**"); Yap_ReleaseAtom(AtomFoundVar); SF_STORE->AtFreeTerm = Yap_LookupAtom("?"); Yap_ReleaseAtom(AtomFreeTerm); SF_STORE->AtNil = Yap_LookupAtom("[]"); SF_STORE->AtDot = Yap_LookupAtom("."); #else Yap_LookupAtomWithAddress("**",&(SF_STORE->AtFoundVar)); Yap_ReleaseAtom(AtomFoundVar); Yap_LookupAtomWithAddress("?",&(SF_STORE->AtFreeTerm)); Yap_ReleaseAtom(AtomFreeTerm); Yap_LookupAtomWithAddress("[]",&(SF_STORE->AtNil)); Yap_LookupAtomWithAddress(".",&(SF_STORE->AtDot)); #endif } static void InitWideAtoms(void) { int i; WideAtomHashTableSize = MaxWideHash; WideHashChain = (AtomHashEntry *)Yap_AllocAtomSpace(sizeof(AtomHashEntry) * MaxWideHash); if (WideHashChain == NULL) { Yap_Error(FATAL_ERROR,MkIntTerm(0),"allocating wide atom table"); } for (i = 0; i < MaxWideHash; ++i) { INIT_RWLOCK(WideHashChain[i].AERWLock); WideHashChain[i].Entry = NIL; } NOfWideAtoms = 0; } static void InitInvisibleAtoms(void) { /* initialise invisible chain */ Yap_heap_regs->invisiblechain.Entry = NIL; INIT_RWLOCK(Yap_heap_regs->invisiblechain.AERWLock); } #ifdef YAPOR void Yap_init_yapor_workers(void) { CACHE_REGS int proc; #ifdef YAPOR_THREADS return; #endif /* YAPOR_THREADS */ #ifdef YAPOR_COW GLOBAL_master_worker = getpid(); if (GLOBAL_number_workers > 1) { int son; son = fork(); if (son == -1) Yap_Error(FATAL_ERROR, TermNil, "fork error (Yap_init_yapor_workers)"); if (son > 0) { /* I am the father, I must stay here and wait for my children to all die */ struct sigaction sigact; sigact.sa_handler = SIG_DFL; sigemptyset(&sigact.sa_mask); sigact.sa_flags = SA_RESTART; sigaction(SIGINT, &sigact, NULL); pause(); exit(0); } else GLOBAL_worker_pid(0) = getpid(); } #endif /* YAPOR_COW */ for (proc = 1; proc < GLOBAL_number_workers; proc++) { int son; son = fork(); if (son == -1) Yap_Error(FATAL_ERROR, TermNil, "fork error (Yap_init_yapor_workers)"); if (son == 0) { /* new worker */ worker_id = proc; Yap_remap_yapor_memory(); LOCAL = REMOTE(worker_id); memcpy(REMOTE(worker_id), REMOTE(0), sizeof(struct worker_local)); InitWorker(worker_id); break; } else GLOBAL_worker_pid(proc) = son; } } #endif /* YAPOR */ #ifdef THREADS static void InitThreadHandle(int wid) { REMOTE_ThreadHandle(wid).in_use = FALSE; REMOTE_ThreadHandle(wid).zombie = FALSE; REMOTE_ThreadHandle(wid).local_preds = NULL; #ifdef LOW_LEVEL_TRACER REMOTE_ThreadHandle(wid).thread_inst_count = 0LL; #endif pthread_mutex_init(&(REMOTE_ThreadHandle(wid).tlock), NULL); pthread_mutex_init(&(REMOTE_ThreadHandle(wid).tlock_status), NULL); REMOTE_ThreadHandle(wid).tdetach = (CELL)0; REMOTE_ThreadHandle(wid).cmod = (CELL)0; { mbox_t * mboxp = &REMOTE_ThreadHandle(wid).mbox_handle; pthread_mutex_t *mutexp; pthread_cond_t *condp; struct idb_queue *msgsp; mboxp->name = MkIntTerm(0); condp = & mboxp->cond; pthread_cond_init(condp, NULL); mutexp = & mboxp->mutex; pthread_mutex_init(mutexp, NULL); msgsp = & mboxp->msgs; mboxp->nmsgs = 0; mboxp->nclients = 0; mboxp->open = true; Yap_init_tqueue(msgsp); } } int Yap_InitThread(int new_id) { struct worker_local *new_s; if (new_id) { if (!(new_s = (struct worker_local *)calloc(sizeof(struct worker_local), 1))) return FALSE; Yap_local[new_id] = new_s; if (!((REGSTORE *)pthread_getspecific(Yap_yaamregs_key))) { REGSTORE *rs = (REGSTORE *)calloc(sizeof(REGSTORE),1); pthread_setspecific(Yap_yaamregs_key, (const void *)rs); REMOTE_ThreadHandle(new_id).default_yaam_regs = rs; REMOTE_ThreadHandle(new_id).current_yaam_regs = rs; rs->worker_id_ = new_id; rs->worker_local_ = REMOTE(new_id); } } InitWorker(new_id); return TRUE; } #endif static void InitScratchPad(int wid) { REMOTE_ScratchPad(wid).ptr = NULL; REMOTE_ScratchPad(wid).sz = SCRATCH_START_SIZE; REMOTE_ScratchPad(wid).msz = SCRATCH_START_SIZE; } void Yap_CloseScratchPad(void) { CACHE_REGS Yap_FreeCodeSpace(LOCAL_ScratchPad.ptr); LOCAL_ScratchPad.sz = SCRATCH_START_SIZE; LOCAL_ScratchPad.msz = SCRATCH_START_SIZE; } #include "iglobals.h" #include "ilocals.h" #if defined(YAPOR_COPY) || defined(YAPOR_COW) || defined(YAPOR_SBA) struct global_data *Yap_global; long Yap_worker_area_size; #else struct global_data Yap_Global; #endif #if defined(THREADS) struct worker_local *Yap_local[MAX_THREADS]; #elif defined(YAPOR) struct worker_local *Yap_local; #else /* !THREADS && !YAPOR */ struct worker_local Yap_local; #endif static void InitCodes(void) { CACHE_REGS #if THREADS int wid; for (wid = 1; wid < MAX_THREADS; wid++) { Yap_local[wid] = NULL; } #endif #include "ihstruct.h" #if THREADS Yap_InitThread(0); #endif /* THREADS */ InitGlobal(); #if !THREADS InitWorker(0); #endif /* THREADS */ Yap_InitFirstWorkerThreadHandle(); /* make sure no one else can use these two atoms */ LOCAL_SourceModule = CurrentModule = 0; Yap_ReleaseAtom(AtomOfTerm(TermReFoundVar)); /* make sure we have undefp defined */ /* predicates can only be defined after this point */ { /* make sure we know about the module predicate */ PredEntry *modp = RepPredProp(PredPropByFunc(FunctorModule,PROLOG_MODULE)); modp->PredFlags |= MetaPredFlag; } #ifdef YAPOR Yap_heap_regs->getwork_code->y_u.Otapl.p = RepPredProp(PredPropByAtom(AtomGetwork, PROLOG_MODULE)); Yap_heap_regs->getwork_seq_code->y_u.Otapl.p = RepPredProp(PredPropByAtom(AtomGetworkSeq, PROLOG_MODULE)); #endif /* YAPOR */ } static void InitVersion(void) { Yap_PutValue(AtomVersionNumber, MkAtomTerm(Yap_LookupAtom(YAP_FULL_VERSION))); } void Yap_InitWorkspace(UInt Heap, UInt Stack, UInt Trail, UInt Atts, UInt max_table_size, int n_workers, int sch_loop, int delay_load) { CACHE_REGS int i; /* initialise system stuff */ #if PUSH_REGS #ifdef THREADS if (!(Yap_local[0] = (struct worker_local *)calloc(sizeof(struct worker_local), 1))) return; pthread_key_create(&Yap_yaamregs_key, NULL); pthread_setspecific(Yap_yaamregs_key, (const void *)&Yap_standard_regs); GLOBAL_master_thread = pthread_self(); #else /* In this case we need to initialise the abstract registers */ Yap_regp = &Yap_standard_regs; /* the emulator will eventually copy them to its own local register array, but for now they exist */ #endif #endif /* PUSH_REGS */ #ifdef THREADS Yap_regp = ((REGSTORE *)pthread_getspecific(Yap_yaamregs_key)); LOCAL = REMOTE(0); #endif /* THREADS */ #if defined(YAPOR_COPY) || defined(YAPOR_COW) || defined(YAPOR_SBA) LOCAL = REMOTE(0); #endif /* YAPOR_COPY || YAPOR_COW || YAPOR_SBA */ if (Heap < MinHeapSpace) Heap = MinHeapSpace; Heap = AdjustPageSize(Heap * K); Heap /= (K); /* sanity checking for data areas */ if (Trail < MinTrailSpace) Trail = MinTrailSpace; Trail = AdjustPageSize(Trail * K); Trail /= (K); if (Stack < MinStackSpace) Stack = MinStackSpace; Stack = AdjustPageSize(Stack * K); Stack /= (K); if (!Atts) Atts = 2048*sizeof(CELL); else Atts = AdjustPageSize(Atts * K); Atts /= (K); #if defined(THREADS) || defined(YAPOR) worker_id = 0; #endif /* YAPOR || THREADS */ #ifdef YAPOR if (n_workers > MAX_WORKERS) Yap_Error(INTERNAL_ERROR, TermNil, "excessive number of workers"); #ifdef YAPOR_COPY INFORMATION_MESSAGE("YapOr: copy model with %d worker%s", n_workers, n_workers == 1 ? "":"s"); #elif YAPOR_COW INFORMATION_MESSAGE("YapOr: acow model with %d worker%s", n_workers, n_workers == 1 ? "":"s"); #elif YAPOR_SBA INFORMATION_MESSAGE("YapOr: sba model with %d worker%s", n_workers, n_workers == 1 ? "":"s"); #elif YAPOR_THREADS INFORMATION_MESSAGE("YapOr: threads model with %d worker%s", n_workers, n_workers == 1 ? "":"s"); #endif /* YAPOR_COPY - YAPOR_COW - YAPOR_SBA - YAPOR_THREADS */ #endif /* YAPOR */ #if defined(YAPOR_COPY) || defined(YAPOR_COW) || defined(YAPOR_SBA) Yap_init_yapor_stacks_memory(Trail, Heap, Stack+Atts, n_workers); #else Yap_InitMemory(Trail, Heap, Stack+Atts); #endif #if defined(YAPOR) || defined(TABLING) Yap_init_global_optyap_data(max_table_size, n_workers, sch_loop, delay_load); #endif /* YAPOR || TABLING */ Yap_AttsSize = Atts; Yap_InitTime( 0 ); /* InitAbsmi must be done before InitCodes */ /* This must be done before initialising predicates */ for (i = 0; i < NUMBER_OF_YAP_FLAGS; i++) { yap_flags[i] = 0; } #ifdef MPW Yap_InitAbsmi(REGS, FunctorList); #else Yap_InitAbsmi(); #endif InitCodes(); InitOps(); InitDebug(); InitVersion(); #if THREADS /* make sure we use the correct value of regcache */ regcache = ((REGSTORE *)pthread_getspecific(Yap_yaamregs_key)); LOCAL_PL_local_data_p->reg_cache = regcache; #endif #if USE_SYSTEM_MALLOC if (Trail < MinTrailSpace) Trail = MinTrailSpace; if (Stack < MinStackSpace) Stack = MinStackSpace; if (!(LOCAL_GlobalBase = (ADDR)malloc((Trail+Stack)*1024))) { Yap_Error(RESOURCE_ERROR_MEMORY, 0, "could not allocate stack space for main thread"); Yap_exit(1); } #if THREADS /* don't forget this is a thread */ LOCAL_ThreadHandle.stack_address = LOCAL_GlobalBase; LOCAL_ThreadHandle.tsize = Trail; LOCAL_ThreadHandle.ssize = Stack; #endif #endif GLOBAL_AllowGlobalExpansion = TRUE; GLOBAL_AllowLocalExpansion = TRUE; GLOBAL_AllowTrailExpansion = TRUE; Yap_InitExStacks (0, Trail, Stack); InitStdPreds(); /* make sure tmp area is available */ { Yap_ReleasePreAllocCodeSpace(Yap_PreAllocCodeSpace()); } } int Yap_HaltRegisterHook (HaltHookFunc f, void * env) { struct halt_hook *h; if (!(h = (struct halt_hook *)Yap_AllocCodeSpace(sizeof(struct halt_hook)))) return FALSE; h->environment = env; h->hook = f; LOCK(GLOBAL_BGL); h->next = GLOBAL_HaltHooks; GLOBAL_HaltHooks = h; UNLOCK(GLOBAL_BGL); return TRUE; } static void run_halt_hooks(int code) { struct halt_hook *hooke = GLOBAL_HaltHooks; while (hooke) { hooke->hook(code, hooke->environment); hooke = hooke->next; } } void Yap_exit (int value) { CACHE_REGS void closeFiles(int all); #if defined(YAPOR_COPY) || defined(YAPOR_COW) || defined(YAPOR_SBA) Yap_unmap_yapor_memory(); #endif /* YAPOR_COPY || YAPOR_COW || YAPOR_SBA */ if (! (LOCAL_PrologMode & BootMode) ) { #ifdef LOW_PROF remove("PROFPREDS"); remove("PROFILING"); #endif run_halt_hooks(value); Yap_ShutdownLoadForeign(); } closeFiles(TRUE); exit(value); }