From d078a2b2c4e15ae8b3ad3843740b19b0f05281bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Thu, 10 Jan 2013 23:22:11 +0000 Subject: [PATCH 1/9] thread support --- C/absmi.c | 15 ++++++++------- C/exo.c | 36 +++++++++++++++++++----------------- H/clause.h | 2 +- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/C/absmi.c b/C/absmi.c index 392e5bee3..b791cf3c6 100755 --- a/C/absmi.c +++ b/C/absmi.c @@ -968,7 +968,7 @@ Yap_absmi(int inp) { yamop *pt; saveregs(); - pt = Yap_ExoLookup(PredFromDefCode(PREG)); + pt = Yap_ExoLookup(PredFromDefCode(PREG) PASS_REGS); setregs(); #ifdef SHADOW_S SREG = S; @@ -1050,12 +1050,13 @@ Yap_absmi(int inp) Op(retry_exo, lp); BEGD(d0); CACHE_Y(B); - saveregs(); - d0 = Yap_NextExo(B_YREG, (struct index_t *)PREG->u.lp.l); - setregs(); -#ifdef SHADOW_S - SREG = S; -#endif + { + struct index_t *it = (struct index_t *)(PREG->u.lp.l); + CELL offset = EXO_ADDRESS_TO_OFFSET(it,(CELL *)((CELL *)(B+1))[it->arity]); + d0 = it->links[offset]; + ((CELL *)(B+1))[it->arity] = (CELL)EXO_OFFSET_TO_ADDRESS(it, d0); + SREG = it->cls+it->arity*offset; + } if (d0) { /* After retry, cut should be pointing at the parent * choicepoint for the current B */ diff --git a/C/exo.c b/C/exo.c index e827e1f16..68543ce85 100644 --- a/C/exo.c +++ b/C/exo.c @@ -58,12 +58,12 @@ HASH(UInt hash0, UInt j, CELL *cl, struct index_t *it) /* search for matching elements */ static int -MATCH(CELL *clp, CELL *kvp, UInt j, struct index_t *it) +MATCH(CELL *clp, CELL *kvp, UInt j, struct index_t *it, UInt bnds[]) { if ((kvp - it->cls)%it->arity != j) return FALSE; do { - if ( LOCAL_ibnds[j] && *clp != *kvp) + if ( bnds[j] && *clp != *kvp) return FALSE; clp--; kvp--; @@ -112,14 +112,14 @@ ADD_TO_TRY_CHAIN(CELL *kvp, CELL *cl, struct index_t *it) * else */ static void -INSERT(CELL *cl, struct index_t *it, UInt arity, UInt base, UInt hash0) +INSERT(CELL *cl, struct index_t *it, UInt arity, UInt base, UInt hash0, UInt bnds[]) { UInt j = base; CELL *kvp; UInt hash; /* skip over argument */ - while (!LOCAL_ibnds[j]) { + while (!bnds[j]) { j++; } /* j is the firs bound element */ @@ -134,16 +134,16 @@ INSERT(CELL *cl, struct index_t *it, UInt arity, UInt base, UInt hash0) it->nentries++; it->key[hash] = cl+j; return; - } else if (MATCH(cl+j, kvp, j, it)) { + } else if (MATCH(cl+j, kvp, j, it, bnds)) { /* collision */ UInt k; CELL *target; for (k =j+1, target = kvp+1; k < arity; k++,target++ ) { - if (LOCAL_ibnds[k]) { + if (bnds[k]) { if (*target != cl[k]) { /* found a new forking point */ - INSERT(cl, it, arity, k, hash0); + INSERT(cl, it, arity, k, hash0, bnds); return; } } @@ -160,8 +160,9 @@ INSERT(CELL *cl, struct index_t *it, UInt arity, UInt base, UInt hash0) } static yamop * -LOOKUP(struct index_t *it, UInt arity, UInt j) +LOOKUP(struct index_t *it, UInt arity, UInt j, UInt bnds[]) { + CACHE_REGS CELL *kvp; UInt hash, hash0 = 0; @@ -175,13 +176,13 @@ LOOKUP(struct index_t *it, UInt arity, UInt j) if (kvp == NULL) { /* simple case, no element */ return FAILCODE; - } else if (MATCH(XREGS+(j+1), kvp, j, it)) { + } else if (MATCH(XREGS+(j+1), kvp, j, it, bnds)) { /* found element */ UInt k; CELL *target; for (k =j+1, target = kvp+1; k < arity; k++ ) { - if (LOCAL_ibnds[k]) { + if (bnds[k]) { if (*target != XREGS[k+1]) { j = k; goto hash; @@ -202,14 +203,14 @@ LOOKUP(struct index_t *it, UInt arity, UInt j) } static void -fill_hash(UInt bmap, struct index_t *it) +fill_hash(UInt bmap, struct index_t *it, UInt bnds[]) { UInt i; UInt arity = it->arity; CELL *cl = it->cls; for (i=0; i < it->nels; i++) { - INSERT(cl, it, arity, 0, 0); + INSERT(cl, it, arity, 0, 0, bnds); cl += arity; } for (i=0; i < it->hsize; i++) { @@ -226,7 +227,7 @@ fill_hash(UInt bmap, struct index_t *it) } static struct index_t * -add_index(struct index_t **ip, UInt bmap, PredEntry *ap, UInt count) +add_index(struct index_t **ip, UInt bmap, PredEntry *ap, UInt count, UInt bnds[]) { UInt ncls = ap->cs.p_code.NOfClauses, j; CELL *base = NULL; @@ -269,7 +270,7 @@ add_index(struct index_t **ip, UInt bmap, PredEntry *ap, UInt count) i->cls = (CELL *)((ADDR)ap->cs.p_code.FirstClause+2*sizeof(struct index_t *)); *ip = i; if (count) { - fill_hash(bmap, i); + fill_hash(bmap, i, bnds); printf("entries=%ld collisions=%ld trys=%ld\n", i->nentries, i->ncollisions, i->ntrys); if (!i->ntrys) { i->is_key = TRUE; @@ -311,7 +312,7 @@ add_index(struct index_t **ip, UInt bmap, PredEntry *ap, UInt count) } yamop * -Yap_ExoLookup(PredEntry *ap) +Yap_ExoLookup(PredEntry *ap USES_REGS) { UInt arity = ap->ArityOfPE; UInt bmap = 0L, bit = 1, count = 0, j, j0 = 0; @@ -345,10 +346,10 @@ Yap_ExoLookup(PredEntry *ap) i = i->next; } if (!i) { - i = add_index(ip, bmap, ap, count); + i = add_index(ip, bmap, ap, count, LOCAL_ibnds); } if (count) - return LOOKUP(i, arity, j0); + return LOOKUP(i, arity, j0, LOCAL_ibnds); else return i->code; } @@ -356,6 +357,7 @@ Yap_ExoLookup(PredEntry *ap) CELL Yap_NextExo(choiceptr cptr, struct index_t *it) { + CACHE_REGS CELL offset = EXO_ADDRESS_TO_OFFSET(it,(CELL *)((CELL *)(B+1))[it->arity]); CELL next = it->links[offset]; ((CELL *)(B+1))[it->arity] = (CELL)EXO_OFFSET_TO_ADDRESS(it, next); diff --git a/H/clause.h b/H/clause.h index 65662ddc6..53362ad29 100644 --- a/H/clause.h +++ b/H/clause.h @@ -263,7 +263,7 @@ LogUpdClause *STD_PROTO(Yap_NthClause,(PredEntry *,Int)); LogUpdClause *STD_PROTO(Yap_FollowIndexingCode,(PredEntry *,yamop *, Term *, yamop *,yamop *)); /* exo.c */ -yamop *Yap_ExoLookup(PredEntry *ap); +yamop *Yap_ExoLookup(PredEntry *ap USES_REGS); CELL Yap_NextExo(choiceptr cpt, struct index_t *it); #if USE_THREADED_CODE From f83379648ceffb5831f2f17dd93b53b6daa607bc Mon Sep 17 00:00:00 2001 From: Vitor Santos Costa Date: Fri, 11 Jan 2013 16:45:14 +0000 Subject: [PATCH 2/9] fix use of exo preds. --- C/cdmgr.c | 35 +++++++++++++++++++++++++++++++++-- C/dbase.c | 7 +++++++ C/exo.c | 4 ++-- C/heapgc.c | 8 ++++++++ H/iatoms.h | 2 ++ H/ratoms.h | 2 ++ H/tatoms.h | 4 ++++ misc/ATOMS | 2 ++ pl/preds.yap | 13 ++++++++++--- 9 files changed, 70 insertions(+), 7 deletions(-) diff --git a/C/cdmgr.c b/C/cdmgr.c index ac0cc6161..7b5a0d30d 100644 --- a/C/cdmgr.c +++ b/C/cdmgr.c @@ -544,6 +544,9 @@ PredForChoicePt(yamop *p_code) { case _retry_me: case _trust_me: return p_code->u.Otapl.p; + case _retry_exo: + case _retry_all_exo: + return p_code->u.lp.p; case _try_logical: case _retry_logical: case _trust_logical: @@ -891,7 +894,7 @@ Yap_BuildMegaClause(PredEntry *ap) ap->cs.p_code.FirstClause = ap->cs.p_code.LastClause = mcl->ClCode; - ap->PredFlags |= MegaClausePredFlag; + ap->PredFlags |= MegaClausePredFlag|SourcePredFlag; Yap_inform_profiler_of_clause(mcl, (char *)mcl+required, ap, GPROF_MEGA); } @@ -3003,6 +3006,27 @@ p_is_source( USES_REGS1 ) return(out); } +static Int +p_is_exo( USES_REGS1 ) +{ /* '$is_dynamic'(+P) */ + PredEntry *pe; + Int out; + MegaClause *mcl; + + pe = get_pred(Deref(ARG1), Deref(ARG2), "$is_exo"); + if (EndOfPAEntr(pe)) + return FALSE; + PELOCK(28,pe); + out = (pe->PredFlags & MegaClausePredFlag); + if (out) { + mcl = + ClauseCodeToMegaClause(pe->cs.p_code.FirstClause); + out = mcl->ClFlags & ExoMask; + } + UNLOCKPE(46,pe); + return(out); +} + static Int p_owner_file( USES_REGS1 ) { /* '$owner_file'(+P,M,F) */ @@ -5769,6 +5793,12 @@ p_choicepoint_info( USES_REGS1 ) pe = ipc->u.Otapl.p; t = BuildActivePred(pe, cptr->cp_args); break; + case _retry_exo: + case _retry_all_exo: + ncl = NULL; + pe = ipc->u.lp.p; + t = BuildActivePred(pe, cptr->cp_args); + break; case _Nstop: { Atom at = AtomLive; @@ -5978,7 +6008,7 @@ p_dbload_get_space( USES_REGS1 ) ap->cs.p_code.FirstClause = ap->cs.p_code.LastClause = mcl->ClCode; - ap->PredFlags |= MegaClausePredFlag; + ap->PredFlags |= (MegaClausePredFlag|SourcePredFlag); ap->cs.p_code.NOfClauses = ncls; if (ap->PredFlags & (SpiedPredFlag|CountPredFlag|ProfiledPredFlag)) { ap->OpcodeOfPred = Yap_opcode(_spy_pred); @@ -6037,6 +6067,7 @@ Yap_InitCdMgr(void) Yap_InitCPred("$is_expand_goal_or_meta_predicate", 2, p_is_expandgoalormetapredicate, TestPredFlag | SafePredFlag); Yap_InitCPred("$is_log_updatable", 2, p_is_log_updatable, TestPredFlag | SafePredFlag); Yap_InitCPred("$is_source", 2, p_is_source, TestPredFlag | SafePredFlag); + Yap_InitCPred("$is_exo", 2, p_is_exo, TestPredFlag | SafePredFlag); Yap_InitCPred("$owner_file", 3, p_owner_file, SafePredFlag); Yap_InitCPred("$mk_d", 2, p_mk_d, SafePredFlag); Yap_InitCPred("$pred_exists", 2, p_pred_exists, TestPredFlag | SafePredFlag); diff --git a/C/dbase.c b/C/dbase.c index 99438d338..a90db27ce 100755 --- a/C/dbase.c +++ b/C/dbase.c @@ -4501,6 +4501,10 @@ p_erase_clause( USES_REGS1 ) Yap_EraseMegaClause(Yap_MegaClauseFromTerm(t1), Yap_MegaClausePredicateFromTerm(t1)); return TRUE; } + if (FunctorOfTerm(t1) == FunctorExoClause) { + Yap_Error(TYPE_ERROR_DBREF, t1, "erase exo clause"); + return FALSE; + } } Yap_Error(TYPE_ERROR_DBREF, t1, "erase"); return FALSE; @@ -4688,6 +4692,9 @@ p_instance( USES_REGS1 ) if (FunctorOfTerm(t1) == FunctorMegaClause) { return mega_instance(Yap_MegaClauseFromTerm(t1), Yap_MegaClausePredicateFromTerm(t1) PASS_REGS); } + if (FunctorOfTerm(t1) == FunctorExoClause) { + return Yap_unify(ARG2,ArgOfTerm(2,t1)); + } } return FALSE; } else { diff --git a/C/exo.c b/C/exo.c index e827e1f16..4d3a68fa8 100644 --- a/C/exo.c +++ b/C/exo.c @@ -420,7 +420,7 @@ p_exodb_get_space( USES_REGS1 ) } Yap_ClauseSpace += required; /* cool, it's our turn to do the conversion */ - mcl->ClFlags = MegaMask; + mcl->ClFlags = MegaMask|ExoMask; mcl->ClSize = required-sizeof(MegaClause); mcl->ClPred = ap; mcl->ClItemSize = arity*sizeof(CELL); @@ -430,7 +430,7 @@ p_exodb_get_space( USES_REGS1 ) ap->cs.p_code.FirstClause = ap->cs.p_code.LastClause = mcl->ClCode; - ap->PredFlags |= MegaClausePredFlag; + ap->PredFlags |= MegaClausePredFlag|SourcePredFlag; ap->cs.p_code.NOfClauses = ncls; if (ap->PredFlags & (SpiedPredFlag|CountPredFlag|ProfiledPredFlag)) { ap->OpcodeOfPred = Yap_opcode(_spy_pred); diff --git a/C/heapgc.c b/C/heapgc.c index 31b453dba..993051d13 100644 --- a/C/heapgc.c +++ b/C/heapgc.c @@ -2307,6 +2307,10 @@ mark_choicepoints(register choiceptr gc_B, tr_fr_ptr saved_TR, int very_verbose mark_ref_in_use((DBRef)rtp->u.OtILl.block PASS_REGS); nargs = rtp->u.OtILl.d->ClPred->ArityOfPE+1; break; + case _retry_exo: + case _retry_all_exo: + nargs = rtp->u.lp.p->ArityOfPE; + break; #ifdef DEBUG case _retry_me: case _trust_me: @@ -3223,6 +3227,10 @@ sweep_choicepoints(choiceptr gc_B USES_REGS) case _retry4: sweep_b(gc_B, 4 PASS_REGS); break; + case _retry_exo: + case _retry_all_exo: + sweep_b(gc_B, rtp->u.lp.p->ArityOfPE PASS_REGS); + break; case _retry_c: case _retry_userc: { diff --git a/H/iatoms.h b/H/iatoms.h index 46fdc415c..d1f1db115 100644 --- a/H/iatoms.h +++ b/H/iatoms.h @@ -99,6 +99,7 @@ AtomExecuteWoMod = Yap_FullLookupAtom("$execute_wo_mod"); AtomExist = Yap_LookupAtom("exist"); AtomExistenceError = Yap_LookupAtom("existence_error"); + AtomExoClause = Yap_FullLookupAtom("$exo_clause"); AtomExpectedNumber = Yap_LookupAtom("expected_number_syntax"); AtomExtendFileSearchPath = Yap_FullLookupAtom("$extend_file_search_path"); AtomFB = Yap_LookupAtom("fb"); @@ -374,6 +375,7 @@ FunctorExecuteInMod = Yap_MkFunctor(AtomExecuteInMod,2); FunctorExecuteWithin = Yap_MkFunctor(AtomExecuteWithin,1); FunctorExistenceError = Yap_MkFunctor(AtomExistenceError,2); + FunctorExoClause = Yap_MkFunctor(AtomExoClause,2); FunctorFunctor = Yap_MkFunctor(AtomFunctor,3); FunctorGAtom = Yap_MkFunctor(AtomAtom,1); FunctorGAtomic = Yap_MkFunctor(AtomAtomic,1); diff --git a/H/ratoms.h b/H/ratoms.h index 6dfabb879..eceae68a3 100644 --- a/H/ratoms.h +++ b/H/ratoms.h @@ -99,6 +99,7 @@ AtomExecuteWoMod = AtomAdjust(AtomExecuteWoMod); AtomExist = AtomAdjust(AtomExist); AtomExistenceError = AtomAdjust(AtomExistenceError); + AtomExoClause = AtomAdjust(AtomExoClause); AtomExpectedNumber = AtomAdjust(AtomExpectedNumber); AtomExtendFileSearchPath = AtomAdjust(AtomExtendFileSearchPath); AtomFB = AtomAdjust(AtomFB); @@ -374,6 +375,7 @@ FunctorExecuteInMod = FuncAdjust(FunctorExecuteInMod); FunctorExecuteWithin = FuncAdjust(FunctorExecuteWithin); FunctorExistenceError = FuncAdjust(FunctorExistenceError); + FunctorExoClause = FuncAdjust(FunctorExoClause); FunctorFunctor = FuncAdjust(FunctorFunctor); FunctorGAtom = FuncAdjust(FunctorGAtom); FunctorGAtomic = FuncAdjust(FunctorGAtomic); diff --git a/H/tatoms.h b/H/tatoms.h index cf0c4a98f..ecc2f5d6d 100644 --- a/H/tatoms.h +++ b/H/tatoms.h @@ -196,6 +196,8 @@ #define AtomExist Yap_heap_regs->AtomExist_ Atom AtomExistenceError_; #define AtomExistenceError Yap_heap_regs->AtomExistenceError_ + Atom AtomExoClause_; +#define AtomExoClause Yap_heap_regs->AtomExoClause_ Atom AtomExpectedNumber_; #define AtomExpectedNumber Yap_heap_regs->AtomExpectedNumber_ Atom AtomExtendFileSearchPath_; @@ -746,6 +748,8 @@ #define FunctorExecuteWithin Yap_heap_regs->FunctorExecuteWithin_ Functor FunctorExistenceError_; #define FunctorExistenceError Yap_heap_regs->FunctorExistenceError_ + Functor FunctorExoClause_; +#define FunctorExoClause Yap_heap_regs->FunctorExoClause_ Functor FunctorFunctor_; #define FunctorFunctor Yap_heap_regs->FunctorFunctor_ Functor FunctorGAtom_; diff --git a/misc/ATOMS b/misc/ATOMS index b2ece67cc..06eb8b509 100644 --- a/misc/ATOMS +++ b/misc/ATOMS @@ -104,6 +104,7 @@ A ExecuteWithin F "$execute_within" A ExecuteWoMod F "$execute_wo_mod" A Exist N "exist" A ExistenceError N "existence_error" +A ExoClause F "$exo_clause" A ExpectedNumber N "expected_number_syntax" A ExtendFileSearchPath F "$extend_file_search_path" A FB N "fb" @@ -379,6 +380,7 @@ F Execute2InMod ExecuteWoMod 2 F ExecuteInMod ExecuteInMod 2 F ExecuteWithin ExecuteWithin 1 F ExistenceError ExistenceError 2 +F ExoClause ExoClause 2 F Functor Functor 3 F GAtom Atom 1 F GAtomic Atomic 1 diff --git a/pl/preds.yap b/pl/preds.yap index 484730eeb..754c31e10 100644 --- a/pl/preds.yap +++ b/pl/preds.yap @@ -281,12 +281,19 @@ clause(V,Q,R) :- ( T = (H :- B) -> P = H, Q = B ; P=T, Q = true). '$clause'(V,M,Q,R) :- var(V), !, '$do_error'(instantiation_error,clause(M:V,Q,R)). -'$clause'(C,M,Q,R) :- number(C), !, +'$clause'(C,M,Q,R) :- + number(C), !, '$do_error'(type_error(callable,C),clause(M:C,Q,R)). -'$clause'(R,M,Q,R) :- db_reference(R), !, - '$do_error'(type_error(callable,R),clause(M:R,Q,R)). +'$clause'(C,M,Q,R) :- + db_reference(C), !, + '$do_error'(type_error(callable,C),clause(M:R,Q,R)). '$clause'(M:P,_,Q,R) :- !, '$clause'(P,M,Q,R). +'$clause'(P,M,Q,R) :- + '$is_exo'(P, M), !, + Q = true, + R = '$exo_clause'(M,P), + '$execute0'(P, M). '$clause'(P,M,Q,R) :- '$is_source'(P, M), !, '$static_clause'(P,M,Q,R). From e9d04ef9f596254aae36f2bc7a1fcc881477d60b Mon Sep 17 00:00:00 2001 From: Vitor Santos Costa Date: Fri, 11 Jan 2013 18:36:34 +0000 Subject: [PATCH 3/9] save/restore exo --- C/exo.c | 2 +- C/qlyr.c | 11 ++++++++++- C/qlyw.c | 1 + H/rheap.h | 19 +++++++++++++++---- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/C/exo.c b/C/exo.c index 4d3a68fa8..afb6dedd5 100644 --- a/C/exo.c +++ b/C/exo.c @@ -421,7 +421,7 @@ p_exodb_get_space( USES_REGS1 ) Yap_ClauseSpace += required; /* cool, it's our turn to do the conversion */ mcl->ClFlags = MegaMask|ExoMask; - mcl->ClSize = required-sizeof(MegaClause); + mcl->ClSize = required; mcl->ClPred = ap; mcl->ClItemSize = arity*sizeof(CELL); mcl->ClNext = NULL; diff --git a/C/qlyr.c b/C/qlyr.c index 5c473b718..00417535d 100755 --- a/C/qlyr.c +++ b/C/qlyr.c @@ -849,6 +849,7 @@ read_clauses(IOSTREAM *stream, PredEntry *pp, UInt nclauses, UInt flags) { } else if (pp->PredFlags & MegaClausePredFlag) { CACHE_REGS char *base = (void *)read_uint(stream); + UInt mask = read_uint(stream); UInt size = read_uint(stream); MegaClause *cl = (MegaClause *)Yap_AlwaysAllocCodeSpace(size); @@ -857,12 +858,20 @@ read_clauses(IOSTREAM *stream, PredEntry *pp, UInt nclauses, UInt flags) { } LOCAL_HDiff = (char *)cl-base; read_bytes(stream, cl, size); + cl->ClFlags = mask; pp->cs.p_code.FirstClause = pp->cs.p_code.LastClause = cl->ClCode; pp->PredFlags |= MegaClausePredFlag; /* enter index mode */ - pp->OpcodeOfPred = INDEX_OPCODE; + if (mask & ExoMask) { + struct index_t **icl = (struct index_t **)(cl->ClCode); + pp->OpcodeOfPred = Yap_opcode(_enter_exo); + icl[0] = NULL; + icl[1] = NULL; + } else { + pp->OpcodeOfPred = INDEX_OPCODE; + } pp->CodeOfPred = pp->cs.p_code.TrueCodeOfPred = (yamop *)(&(pp->OpcodeOfPred)); /* This must be set for restoremegaclause */ pp->cs.p_code.NOfClauses = nclauses; diff --git a/C/qlyw.c b/C/qlyw.c index 0bde3d2e6..cb5187921 100755 --- a/C/qlyw.c +++ b/C/qlyw.c @@ -649,6 +649,7 @@ save_clauses(IOSTREAM *stream, PredEntry *pp) { UInt size = cl->ClSize; CHECK(save_uint(stream, (UInt)cl)); + CHECK(save_uint(stream, (UInt)(cl->ClFlags))); CHECK(save_uint(stream, size)); CHECK(save_bytes(stream, cl, size)); } else if (pp->PredFlags & DynamicPredFlag) { diff --git a/H/rheap.h b/H/rheap.h index 5c04ef8f2..663b443bf 100644 --- a/H/rheap.h +++ b/H/rheap.h @@ -588,10 +588,21 @@ RestoreMegaClause(MegaClause *cl USES_REGS) } max = (yamop *)((CODEADDR)cl+cl->ClSize); - for (ptr = cl->ClCode; ptr < max; ) { - nextptr = (yamop *)((char *)ptr + cl->ClItemSize); - restore_opcodes(ptr, nextptr PASS_REGS); - ptr = nextptr; + if (cl->ClFlags & ExoMask) { + CELL *base = (CELL *)((ADDR)cl->ClCode+2*sizeof(struct index_t *)); + CELL *end = (CELL*)max, *ptr; + + for (ptr = base; ptr < end; ptr++) { + Term t = *ptr; + if (IsAtomTerm(t)) *ptr = AtomTermAdjust(t); + /* don't handle other complex terms just yet, ints are ok */ + } + } else { + for (ptr = cl->ClCode; ptr < max; ) { + nextptr = (yamop *)((char *)ptr + cl->ClItemSize); + restore_opcodes(ptr, nextptr PASS_REGS); + ptr = nextptr; + } } } From 480e9aea69438c9eeda637118ad73d5918c1728a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Sun, 13 Jan 2013 11:48:31 +0000 Subject: [PATCH 4/9] fix bad ints (obs from Mei). --- C/c_interface.c | 10 +++++----- include/YapInterface.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/C/c_interface.c b/C/c_interface.c index 775a4992a..d19ad7e7a 100644 --- a/C/c_interface.c +++ b/C/c_interface.c @@ -438,8 +438,8 @@ X_API PredEntry *STD_PROTO(YAP_AtomToPred,(Atom)); X_API PredEntry *STD_PROTO(YAP_FunctorToPredInModule,(Functor, Term)); X_API PredEntry *STD_PROTO(YAP_AtomToPredInModule,(Atom, Term)); X_API Int STD_PROTO(YAP_CallProlog,(Term)); -X_API void *STD_PROTO(YAP_AllocSpaceFromYap,(unsigned int)); -X_API void *STD_PROTO(YAP_ReallocSpaceFromYap,(void*,unsigned int)); +X_API void *STD_PROTO(YAP_AllocSpaceFromYap,(size_t)); +X_API void *STD_PROTO(YAP_ReallocSpaceFromYap,(void*,size_t)); X_API void STD_PROTO(YAP_FreeSpaceFromYap,(void *)); X_API int STD_PROTO(YAP_StringToBuffer, (Term, char *, unsigned int)); X_API Term STD_PROTO(YAP_ReadBuffer, (char *,Term *)); @@ -1909,7 +1909,7 @@ YAP_CallProlog(Term t) } X_API void * -YAP_ReallocSpaceFromYap(void *ptr,unsigned int size) { +YAP_ReallocSpaceFromYap(void *ptr,size_t size) { CACHE_REGS void *new_ptr; BACKUP_MACHINE_REGS(); @@ -1923,7 +1923,7 @@ YAP_ReallocSpaceFromYap(void *ptr,unsigned int size) { return new_ptr; } X_API void * -YAP_AllocSpaceFromYap(unsigned int size) +YAP_AllocSpaceFromYap(size_t size) { CACHE_REGS void *ptr; @@ -2836,7 +2836,7 @@ YAP_CompileClause(Term t) { CACHE_REGS yamop *codeaddr; - int mod = CurrentModule; + Term mod = CurrentModule; Term tn = TermNil; BACKUP_MACHINE_REGS(); diff --git a/include/YapInterface.h b/include/YapInterface.h index 4f4f07944..80f9e6e7f 100755 --- a/include/YapInterface.h +++ b/include/YapInterface.h @@ -263,10 +263,10 @@ extern X_API void PROTO(YAP_cut_up,(void)); #define YAP_cut_fail() do { YAP_cut_up(); return FALSE; } while(0) /* void *AllocSpaceFromYAP_(int) */ -extern X_API void *PROTO(YAP_AllocSpaceFromYap,(unsigned int)); +extern X_API void *PROTO(YAP_AllocSpaceFromYap,(size_t)); /* void *ReallocSpaceFromYAP_(void*,int) */ -extern X_API void *PROTO(YAP_ReallocSpaceFromYap,(void*,unsigned int)); +extern X_API void *PROTO(YAP_ReallocSpaceFromYap,(void*,size_t)); /* void FreeSpaceFromYAP_(void *) */ extern X_API void PROTO(YAP_FreeSpaceFromYap,(void *)); From e054db052d1a7d8fa91301a5f9a47b6414dc2bd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Sun, 13 Jan 2013 11:49:12 +0000 Subject: [PATCH 5/9] fix hashing function. --- C/exo.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/C/exo.c b/C/exo.c index 2a85c8a1b..ac393b7ab 100644 --- a/C/exo.c +++ b/C/exo.c @@ -52,8 +52,14 @@ HASH(UInt hash0, UInt j, CELL *cl, struct index_t *it) Term t = cl[j]; UInt sz = it->hsize; if (IsIntTerm(t)) - return (IntOfTerm(t) * 17* (hash0+1)*(j+1) ) % sz; - return (((UInt)AtomOfTerm(t) >> 5)* 17*(hash0+1)*(j+1) ) % sz; + return (17*(IntOfTerm(t) + (hash0+1)*j ) ) % sz; + return (17*(((UInt)AtomOfTerm(t)>>5) + (hash0+1)*j ) ) % sz; +} + +static UInt +NEXT(UInt hash, Term t, UInt j, struct index_t *it) +{ + return (hash+(j+1)*997) % (it->hsize); } /* search for matching elements */ @@ -71,12 +77,6 @@ MATCH(CELL *clp, CELL *kvp, UInt j, struct index_t *it, UInt bnds[]) return TRUE; } -static UInt -NEXT(UInt hash, Term t, UInt j, struct index_t *it) -{ - return (hash+(t>>4)+j+1) % (it->hsize); -} - static void ADD_TO_TRY_CHAIN(CELL *kvp, CELL *cl, struct index_t *it) { @@ -265,7 +265,7 @@ add_index(struct index_t **ip, UInt bmap, PredEntry *ap, UInt count, UInt bnds[] bzero(base, 3*sizeof(CELL)*ncls); } i->key = (CELL **)base; - i->links = (CELL *)(base+2*ncls); + i->links = (CELL *)(base+i->hsize); i->ncollisions = i->nentries = i->ntrys = 0; i->cls = (CELL *)((ADDR)ap->cs.p_code.FirstClause+2*sizeof(struct index_t *)); *ip = i; @@ -274,7 +274,7 @@ add_index(struct index_t **ip, UInt bmap, PredEntry *ap, UInt count, UInt bnds[] printf("entries=%ld collisions=%ld trys=%ld\n", i->nentries, i->ncollisions, i->ntrys); if (!i->ntrys) { i->is_key = TRUE; - if (base != realloc(base, 2*sizeof(CELL)*ncls)) + if (base != realloc(base, i->hsize*sizeof(CELL))) return FALSE; } } From ec37045ca3c34701debd4cadf5dcd285d6923b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Sun, 13 Jan 2013 11:53:58 +0000 Subject: [PATCH 6/9] new versions. --- packages/pldoc | 2 +- packages/zlib | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/pldoc b/packages/pldoc index fa667ecac..9beecb390 160000 --- a/packages/pldoc +++ b/packages/pldoc @@ -1 +1 @@ -Subproject commit fa667ecacf4128c10dc51215ff54f25672a782c8 +Subproject commit 9beecb39041e1faf95e5d2af257e7be8cdda467c diff --git a/packages/zlib b/packages/zlib index 980a0b995..b98ea2bb6 160000 --- a/packages/zlib +++ b/packages/zlib @@ -1 +1 @@ -Subproject commit 980a0b9950ca0b52b327234fd2f66e0790f9c4e1 +Subproject commit b98ea2bb69599c44bdda52c7f1d3e6e3152b97aa From 798afc81c49034e8f8cfa6210c9b6cc4aa899454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Sun, 13 Jan 2013 17:55:13 +0000 Subject: [PATCH 7/9] fix argv[0] discovery. --- C/c_interface.c | 11 +++++++++-- C/load_aix.c | 5 +++-- C/load_aout.c | 6 +++--- C/load_coff.c | 11 ++++++----- C/load_dl.c | 32 ++++++++++++++++++++++++++++---- C/load_dld.c | 8 ++++---- C/load_dll.c | 1 + C/load_dyld.c | 12 ++++++++++++ C/load_foreign.c | 4 ---- C/load_none.c | 5 +++-- C/load_shl.c | 2 +- C/stdpreds.c | 7 +++++-- H/Foreign.h | 2 +- config.h.in | 1 + configure | 11 +++++++++++ configure.in | 1 + 16 files changed, 89 insertions(+), 30 deletions(-) diff --git a/C/c_interface.c b/C/c_interface.c index d19ad7e7a..f40c193bf 100644 --- a/C/c_interface.c +++ b/C/c_interface.c @@ -333,6 +333,7 @@ #include "Yap.h" #include "clause.h" #include "yapio.h" +#include "Foreign.h" #include "attvar.h" #include "SWI-Stream.h" #if HAVE_STDARG_H @@ -3261,8 +3262,14 @@ YAP_FastInit(char saved_state[]) init_args.DelayedReleaseLoad = 3; init_args.PrologShouldHandleInterrupts = FALSE; init_args.ExecutionMode = INTERPRETED; - init_args.Argc = 0; - init_args.Argv = NULL; + init_args.Argc = 1; + { + size_t l1 = 2*sizeof(char *); + if (!(init_args.Argv = (char **)malloc(l1))) + return YAP_BOOT_ERROR; + init_args.Argv[0] = Yap_FindExecutable (); + init_args.Argv[1] = NULL; + } init_args.ErrorNo = 0; init_args.ErrorCause = NULL; init_args.QuietMode = FALSE; diff --git a/C/load_aix.c b/C/load_aix.c index 7e9bf1c51..8cd864d6f 100644 --- a/C/load_aix.c +++ b/C/load_aix.c @@ -26,9 +26,10 @@ * FindExecutable(argv[0]) should be called on yap initialization to * locate the executable of Yap */ -void -Yap_FindExecutable(char *name) +char * +Yap_FindExecutable(void) { + return NULL; } diff --git a/C/load_aout.c b/C/load_aout.c index bc96d8b8b..5778427b7 100644 --- a/C/load_aout.c +++ b/C/load_aout.c @@ -54,8 +54,8 @@ this code is no being maintained anymore * YAP_FindExecutable(argv[0]) should be called on yap initialization to * locate the executable of Yap */ -void -Yap_FindExecutable(char *name) +char * +Yap_FindExecutable(void) { register char *cp, *cp2; struct stat stbuf; @@ -94,7 +94,7 @@ Yap_FindExecutable(char *name) strcpy(LOCAL_FileNameBuf, GLOBAL_argv[0]); Yap_TrueFileName(LOCAL_FileNameBuf, GLOBAL_Executable, TRUE); if (oktox(GLOBAL_Executable)) - return; + return GLOBAL_Executable; else Yap_Error(SYSTEM_ERROR,MkAtomTerm(Yap_LookupAtom(GLOBAL_Executable)), "cannot find file being executed"); diff --git a/C/load_coff.c b/C/load_coff.c index 89fb345dc..e7f6da572 100644 --- a/C/load_coff.c +++ b/C/load_coff.c @@ -50,8 +50,8 @@ this code is no being maintained anymore * YAP_FindExecutable(argv[0]) should be called on yap initialization to * locate the executable of Yap */ -void -Yap_FindExecutable(char *name) +char * +Yap_FindExecutable(void) { register char *cp, *cp2; struct stat stbuf; @@ -64,7 +64,7 @@ Yap_FindExecutable(char *name) if (oktox(GLOBAL_argv[0])) { strcpy(LOCAL_FileNameBuf, GLOBAL_argv[0]); Yap_TrueFileName(LOCAL_FileNameBuf, GLOBAL_Executable, TRUE); - return; + return NULL; } } if (*cp == ':') @@ -84,16 +84,17 @@ Yap_FindExecutable(char *name) if (!oktox(LOCAL_FileNameBuf)) continue; Yap_TrueFileName(LOCAL_FileNameBuf, GLOBAL_Executable, TRUE); - return; + return GLOBAL_Executable; } /* one last try for dual systems */ strcpy(LOCAL_FileNameBuf, GLOBAL_argv[0]); Yap_TrueFileName(LOCAL_FileNameBuf, GLOBAL_Executable, TRUE); if (oktox(GLOBAL_Executable)) - return; + return GLOBAL_Executable; else Yap_Error(SYSTEM_ERROR,MkAtomTerm(Yap_LookupAtom(GLOBAL_Executable)), "cannot find file being executed"); + return NULL; } diff --git a/C/load_dl.c b/C/load_dl.c index f172e78b2..bbd2d040e 100755 --- a/C/load_dl.c +++ b/C/load_dl.c @@ -24,6 +24,10 @@ #include #include #include +#if defined(__APPLE__) +#include +#endif + typedef void (*prismf)(void); @@ -57,9 +61,29 @@ Yap_CallFunctionByName(const char *thing_string) * YAP_FindExecutable(argv[0]) should be called on yap initialization to * locate the executable of Yap */ -void -Yap_FindExecutable(char *name) +char * +Yap_FindExecutable(void) { + if (GLOBAL_argv && GLOBAL_argv[0]) + return GLOBAL_argv[0]; +#if HAVE_GETEXECNAME + return getxecname(); +#elif __APPLE__ + char path[1024]; + uint32_t size = sizeof(path); + if (!_NSGetExecutablePath(path, &size)) { + size_t sz = strlen(path); + char *rc = malloc(sz+1); + strncpy(rc, path, sz); + return rc; + } else { + char *rc = malloc(size+1); + if (_NSGetExecutablePath(rc, &size) == 0) + return "yap"; + return rc; + } +#endif + return "yap"; } void * @@ -200,7 +224,7 @@ Yap_ShutdownLoadForeign(void) if (dlclose(objs->handle) != 0) return; /* ERROR */ objs = objs->next; - Yap_FreeCodeSpace(old); + Yap_FreeCodeSpace((ADDR)old); } libs = f_code->libs; while (libs != NULL) { @@ -208,7 +232,7 @@ Yap_ShutdownLoadForeign(void) if (dlclose(libs->handle) != 0) return; /* ERROR */ libs = libs->next; - Yap_FreeCodeSpace(old); + Yap_FreeCodeSpace((ADDR)old); } f_code = f_code->next; Yap_FreeCodeSpace((ADDR)of_code); diff --git a/C/load_dld.c b/C/load_dld.c index e697011d8..bdcc0dfc6 100644 --- a/C/load_dld.c +++ b/C/load_dld.c @@ -26,15 +26,15 @@ this code is no being maintained anymore * YAP_FindExecutable(argv[0]) should be called on yap initialization to * locate the executable of Yap */ -void -Yap_FindExecutable(char *name) +char * +Yap_FindExecutable(void) { /* use dld_find_executable */ char *res; if(name != NULL && (res=dld_find_executable(name))) { - strcpy(GLOBAL_Executable,res); + return GLOBAL_Executable; } else { - strcpy(GLOBAL_Executable,"./yap"); + return "yap"; } } diff --git a/C/load_dll.c b/C/load_dll.c index 9aaed2c90..6fb238355 100755 --- a/C/load_dll.c +++ b/C/load_dll.c @@ -30,6 +30,7 @@ void Yap_FindExecutable(char *name) { + return NULL; } void * diff --git a/C/load_dyld.c b/C/load_dyld.c index 1367a9c9c..4ff5028c4 100644 --- a/C/load_dyld.c +++ b/C/load_dyld.c @@ -65,6 +65,18 @@ mydlerror(void) void Yap_FindExecutable(char *name) { + char path[1024]; + uint32_t size = sizeof(path); + if (_NSGetExecutablePath(path, &size) == 0) { + char *rc = malloc(size+1); + strncpy(rc, path, size); + return rc; + } else { + char *rc = malloc(size+1); + if (_NSGetExecutablePath(rc, &size) == 0) + return "yap"; + return rc; + } } diff --git a/C/load_foreign.c b/C/load_foreign.c index 4d96f19b4..2247dfea3 100644 --- a/C/load_foreign.c +++ b/C/load_foreign.c @@ -225,10 +225,6 @@ p_open_shared_objects( USES_REGS1 ) { void Yap_InitLoadForeign( void ) { - if (GLOBAL_argv == NULL) - Yap_FindExecutable("yap"); - else - Yap_FindExecutable(GLOBAL_argv[0]); Yap_InitCPred("$load_foreign_files", 3, p_load_foreign, SafePredFlag|SyncPredFlag); Yap_InitCPred("$open_shared_objects", 0, p_open_shared_objects, SafePredFlag); Yap_InitCPred("$open_shared_object", 3, p_open_shared_object, SyncPredFlag); diff --git a/C/load_none.c b/C/load_none.c index 9a9c4a01c..86e7d6bc1 100644 --- a/C/load_none.c +++ b/C/load_none.c @@ -26,9 +26,10 @@ * YAP_FindExecutable(argv[0]) should be called on yap initialization to * locate the executable of Yap */ -void -Yap_FindExecutable(char *name) +char * +Yap_FindExecutable(void) { + return NULL; } diff --git a/C/load_shl.c b/C/load_shl.c index 25c1f573c..15c412404 100644 --- a/C/load_shl.c +++ b/C/load_shl.c @@ -16,7 +16,7 @@ * locate the executable of Yap */ -void Yap_FindExecutable(char *name) +char * Yap_FindExecutable(void) { } diff --git a/C/stdpreds.c b/C/stdpreds.c index 89ed774bb..d77e1603d 100644 --- a/C/stdpreds.c +++ b/C/stdpreds.c @@ -4007,8 +4007,11 @@ p_argv( USES_REGS1 ) static Int p_executable( USES_REGS1 ) { - - Yap_TrueFileName (GLOBAL_argv[0], LOCAL_FileNameBuf, FALSE); + if (GLOBAL_argv && GLOBAL_argv[0]) + Yap_TrueFileName (GLOBAL_argv[0], LOCAL_FileNameBuf, FALSE); + else + strncpy(LOCAL_FileNameBuf,Yap_FindExecutable (), YAP_FILENAME_MAX) ; + return Yap_unify(MkAtomTerm(Yap_LookupAtom(LOCAL_FileNameBuf)),ARG1); } diff --git a/H/Foreign.h b/H/Foreign.h index a4aa88632..a1934d286 100644 --- a/H/Foreign.h +++ b/H/Foreign.h @@ -105,7 +105,7 @@ typedef void (*YapInitProc)(void); #define STD_PROTO(F,A) F A #endif -void STD_PROTO(Yap_FindExecutable,(char *)); +char *STD_PROTO(Yap_FindExecutable,(void)); void *STD_PROTO(Yap_LoadForeignFile,(char *, int)); int STD_PROTO(Yap_CallForeignFile,(void *, char *)); int STD_PROTO(Yap_CloseForeignFile,(void *)); diff --git a/config.h.in b/config.h.in index d270df6ad..cd8593981 100755 --- a/config.h.in +++ b/config.h.in @@ -186,6 +186,7 @@ #undef HAVE_FTIME #undef HAVE_GETCWD #undef HAVE_GETENV +#undef HAVE_GETEXECNAME #undef HAVE_GETHOSTBYNAME #undef HAVE_GETHOSTENT #undef HAVE_GETHOSTID diff --git a/configure b/configure index d343dbcde..384bc051f 100755 --- a/configure +++ b/configure @@ -10250,6 +10250,17 @@ _ACEOF fi done +for ac_func in getexecname +do : + ac_fn_c_check_func "$LINENO" "getexecname" "ac_cv_func_getexecname" +if test "x$ac_cv_func_getexecname" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETEXECNAME 1 +_ACEOF + +fi +done + for ac_func in gethostbyname gethostent gethostid gethostname do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` diff --git a/configure.in b/configure.in index eec71b7de..07aa1e68a 100755 --- a/configure.in +++ b/configure.in @@ -2069,6 +2069,7 @@ AC_CHECK_FUNCS(alloca asinh atanh chdir clock clock_gettime) AC_CHECK_FUNCS(ctime dlopen dup2) AC_CHECK_FUNCS(erf feclearexcept) AC_CHECK_FUNCS(fesettrapenable fgetpos finite fpclass ftime getcwd getenv) +AC_CHECK_FUNCS(getexecname) AC_CHECK_FUNCS(gethostbyname gethostent gethostid gethostname) AC_CHECK_FUNCS(gethrtime getpagesize) AC_CHECK_FUNCS(getpwnam getrlimit getrusage gettimeofday getwd) From 48ea1f5ec59ab2083ed8438f9d9c6e573baa458a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Mon, 14 Jan 2013 09:48:05 +0000 Subject: [PATCH 8/9] exo clause support --- C/cdmgr.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/C/cdmgr.c b/C/cdmgr.c index 7b5a0d30d..f76bd8551 100644 --- a/C/cdmgr.c +++ b/C/cdmgr.c @@ -907,9 +907,13 @@ split_megaclause(PredEntry *ap) yamop *ptr; UInt ncls = ap->cs.p_code.NOfClauses, i; - RemoveIndexation(ap); mcl = ClauseCodeToMegaClause(ap->cs.p_code.FirstClause); + if (mcl->ClFlags & ExoMask) { + Yap_Error(PERMISSION_ERROR_MODIFY_STATIC_PROCEDURE,TermNil,"while deleting clause from exo predicate %s/%d\n",RepAtom(NameOfFunctor(ap->FunctorOfPred))->StrOfAE,ap->ArityOfPE); + return; + } + RemoveIndexation(ap); for (i = 0, ptr = mcl->ClCode; i < ncls; i++) { StaticClause *new = (StaticClause *)Yap_AllocCodeSpace(sizeof(StaticClause)+mcl->ClItemSize+(UInt)NEXTOP((yamop *)NULL,p)); if (new == NULL) { @@ -2710,7 +2714,7 @@ p_purge_clauses( USES_REGS1 ) Term t = Deref(ARG1); Term mod = Deref(ARG2); MegaClause *before = DeadMegaClauses; - + Yap_PutValue(AtomAbol, MkAtomTerm(AtomNil)); if (IsVarTerm(t)) return FALSE; @@ -5252,6 +5256,15 @@ p_nth_clause( USES_REGS1 ) UNLOCK(pe->PELock); return Yap_unify(MkDBRefTerm((DBRef)cl), ARG4); } else if (pe->PredFlags & MegaClausePredFlag) { + MegaClause *mcl = ClauseCodeToMegaClause(pe->cs.p_code.FirstClause); + if (mcl->ClFlags & ExoMask) { + Term tf[2]; + tf[0] = pe->ModuleOfPred; + tf[1] = Yap_MkApplTerm(pe->FunctorOfPred, pe->ArityOfPE, (CELL *)((char *)mcl->ClCode+(ncls-1)*mcl->ClItemSize)); + UNLOCK(pe->PELock); + return Yap_unify(Yap_MkApplTerm(FunctorExoClause, 2, tf), ARG4); + } + /* fast access to nth element, all have same size */ UNLOCK(pe->PELock); return Yap_unify(Yap_MkMegaRefTerm(pe,(yamop *)cl), ARG4); } else { From 0c9342466b57ce898f3e309f34f2ccbedc2e684b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Mon, 14 Jan 2013 09:56:25 +0000 Subject: [PATCH 9/9] handle random on big ints (jan burse) --- C/arith1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/C/arith1.c b/C/arith1.c index 6d7c7601a..86c9b8379 100644 --- a/C/arith1.c +++ b/C/arith1.c @@ -689,7 +689,7 @@ eval1(Int fi, Term t) { return Yap_ArithError(TYPE_ERROR_INTEGER, t, "random(%f)", FloatOfTerm(t)); case big_int_e: #ifdef USE_GMP - return Yap_ArithError(TYPE_ERROR_INTEGER, t, "random(%f)", FloatOfTerm(t)); + return Yap_gmp_mul_float_big(Yap_random(), t); #endif default: RERROR();