2001-04-09 20:54:03 +01:00
|
|
|
/*************************************************************************
|
|
|
|
* *
|
|
|
|
* YAP Prolog %W% %G% *
|
|
|
|
* *
|
|
|
|
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
|
|
|
* *
|
|
|
|
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
|
|
|
* *
|
|
|
|
**************************************************************************
|
|
|
|
* *
|
|
|
|
* File: clause.h *
|
|
|
|
* Last rev: *
|
|
|
|
* mods: *
|
|
|
|
* comments: clause info *
|
|
|
|
* *
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
#include "Yatom.h"
|
2009-10-23 14:22:17 +01:00
|
|
|
#include "YapHeap.h"
|
2001-04-09 20:54:03 +01:00
|
|
|
|
2002-01-01 05:26:25 +00:00
|
|
|
/* consulting files */
|
|
|
|
|
|
|
|
typedef union CONSULT_OBJ {
|
|
|
|
char *filename;
|
|
|
|
int mode;
|
|
|
|
Prop p;
|
|
|
|
UInt c;
|
|
|
|
} consult_obj;
|
|
|
|
|
2001-04-09 20:54:03 +01:00
|
|
|
/* Either we are assembling clauses or indexing code */
|
|
|
|
|
|
|
|
#define ASSEMBLING_CLAUSE 0
|
|
|
|
#define ASSEMBLING_INDEX 1
|
2004-02-05 16:57:02 +00:00
|
|
|
#define ASSEMBLING_EINDEX 2
|
2001-04-09 20:54:03 +01:00
|
|
|
|
2008-09-05 05:22:19 +01:00
|
|
|
#define NextDynamicClause(X) (((yamop *)X)->u.Otapl.d)
|
2001-04-09 20:54:03 +01:00
|
|
|
|
|
|
|
#define PredFirstClause 0
|
|
|
|
#define PredMiddleClause 1
|
|
|
|
#define PredLastClause 2
|
|
|
|
|
2003-08-27 14:37:10 +01:00
|
|
|
typedef struct logic_upd_index {
|
|
|
|
CELL ClFlags;
|
|
|
|
UInt ClRefCount;
|
2001-04-09 20:54:03 +01:00
|
|
|
#if defined(YAPOR) || defined(THREADS)
|
|
|
|
/* A lock for manipulating the clause */
|
2008-08-07 21:51:23 +01:00
|
|
|
// lockvar ClLock;
|
2001-04-09 20:54:03 +01:00
|
|
|
#endif
|
2004-03-05 15:26:33 +00:00
|
|
|
UInt ClSize;
|
2005-12-17 03:25:39 +00:00
|
|
|
struct logic_upd_index *ParentIndex;
|
2003-08-27 14:37:10 +01:00
|
|
|
struct logic_upd_index *SiblingIndex;
|
2005-05-31 20:42:28 +01:00
|
|
|
struct logic_upd_index *PrevSiblingIndex;
|
2003-08-27 14:37:10 +01:00
|
|
|
struct logic_upd_index *ChildIndex;
|
2001-04-09 20:54:03 +01:00
|
|
|
/* The instructions, at least one of the form sl */
|
2005-12-17 03:25:39 +00:00
|
|
|
PredEntry *ClPred;
|
2001-04-09 20:54:03 +01:00
|
|
|
yamop ClCode[MIN_ARRAY];
|
2003-08-27 14:37:10 +01:00
|
|
|
} LogUpdIndex;
|
|
|
|
|
2004-02-06 17:22:24 +00:00
|
|
|
/* The ordering of the first 3 fields should be compatible with dbrefs */
|
2003-08-27 14:37:10 +01:00
|
|
|
typedef struct logic_upd_clause {
|
|
|
|
Functor Id; /* allow pointers to this struct to id */
|
|
|
|
/* as dbref */
|
|
|
|
/* A set of flags describing info on the clause */
|
|
|
|
/* A set of flags describing info on the clause */
|
|
|
|
CELL ClFlags;
|
|
|
|
#if defined(YAPOR) || defined(THREADS)
|
|
|
|
/* A lock for manipulating the clause */
|
2008-08-07 21:51:23 +01:00
|
|
|
// lockvar ClLock;
|
2003-08-27 14:37:10 +01:00
|
|
|
#endif
|
2004-03-05 15:26:33 +00:00
|
|
|
UInt ClSize;
|
2003-08-27 14:37:10 +01:00
|
|
|
/* extra clause information for logical update indices and facts */
|
|
|
|
/* indices that may still backtrack to this clause */
|
|
|
|
UInt ClRefCount;
|
|
|
|
/* data for clauses with environments */
|
|
|
|
yamop *ClExt;
|
|
|
|
DBTerm *ClSource;
|
|
|
|
/* doubly linked list of clauses */
|
|
|
|
struct logic_upd_clause *ClPrev, *ClNext;
|
|
|
|
/* parent pointer */
|
|
|
|
PredEntry *ClPred;
|
2006-09-20 21:03:51 +01:00
|
|
|
UInt ClTimeStart, ClTimeEnd;
|
2003-08-27 14:37:10 +01:00
|
|
|
/* The instructions, at least one of the form sl */
|
|
|
|
yamop ClCode[MIN_ARRAY];
|
2003-04-30 18:46:05 +01:00
|
|
|
} LogUpdClause;
|
|
|
|
|
2006-10-10 15:08:17 +01:00
|
|
|
inline EXTERN int VALID_TIMESTAMP(UInt, struct logic_upd_clause *);
|
|
|
|
|
|
|
|
inline EXTERN int
|
|
|
|
VALID_TIMESTAMP(UInt timestamp, struct logic_upd_clause *cl)
|
|
|
|
{
|
|
|
|
return IN_BETWEEN(cl->ClTimeStart, timestamp, cl->ClTimeEnd);
|
|
|
|
}
|
|
|
|
|
2003-04-30 18:46:05 +01:00
|
|
|
typedef struct dynamic_clause {
|
|
|
|
/* A set of flags describing info on the clause */
|
|
|
|
CELL ClFlags;
|
|
|
|
#if defined(YAPOR) || defined(THREADS)
|
|
|
|
/* A lock for manipulating the clause */
|
|
|
|
lockvar ClLock;
|
|
|
|
#endif
|
2004-03-05 15:26:33 +00:00
|
|
|
UInt ClSize;
|
2003-08-27 14:37:10 +01:00
|
|
|
UInt ClRefCount;
|
2003-04-30 18:46:05 +01:00
|
|
|
yamop *ClPrevious; /* immediate update clause */
|
|
|
|
/* The instructions, at least one of the form sl */
|
|
|
|
yamop ClCode[MIN_ARRAY];
|
|
|
|
} DynamicClause;
|
|
|
|
|
2003-08-27 14:37:10 +01:00
|
|
|
typedef struct static_index {
|
|
|
|
/* A set of flags describing info on the clause */
|
|
|
|
CELL ClFlags;
|
2004-03-05 15:26:33 +00:00
|
|
|
UInt ClSize;
|
2003-08-27 14:37:10 +01:00
|
|
|
struct static_index *SiblingIndex;
|
|
|
|
struct static_index *ChildIndex;
|
|
|
|
/* The instructions, at least one of the form sl */
|
2005-12-17 03:25:39 +00:00
|
|
|
PredEntry *ClPred;
|
2003-08-27 14:37:10 +01:00
|
|
|
yamop ClCode[MIN_ARRAY];
|
|
|
|
} StaticIndex;
|
|
|
|
|
2003-04-30 18:46:05 +01:00
|
|
|
typedef struct static_clause {
|
|
|
|
/* A set of flags describing info on the clause */
|
|
|
|
CELL ClFlags;
|
2004-03-05 15:26:33 +00:00
|
|
|
UInt ClSize;
|
2003-11-24 00:00:43 +00:00
|
|
|
union {
|
|
|
|
DBTerm *ClSource;
|
|
|
|
PredEntry *ClPred;
|
|
|
|
} usc;
|
2003-11-26 18:36:35 +00:00
|
|
|
struct static_clause *ClNext;
|
2003-04-30 18:46:05 +01:00
|
|
|
/* The instructions, at least one of the form sl */
|
|
|
|
yamop ClCode[MIN_ARRAY];
|
|
|
|
} StaticClause;
|
|
|
|
|
2004-09-27 21:45:04 +01:00
|
|
|
typedef struct static_mega_clause {
|
|
|
|
/* A set of flags describing info on the clause */
|
|
|
|
CELL ClFlags;
|
|
|
|
UInt ClSize;
|
|
|
|
PredEntry *ClPred;
|
|
|
|
UInt ClItemSize;
|
2006-03-22 20:07:28 +00:00
|
|
|
struct static_mega_clause *ClNext;
|
2004-09-27 21:45:04 +01:00
|
|
|
/* The instructions, at least one of the form sl */
|
|
|
|
yamop ClCode[MIN_ARRAY];
|
|
|
|
} MegaClause;
|
|
|
|
|
2003-04-30 18:46:05 +01:00
|
|
|
typedef union clause_obj {
|
|
|
|
struct logic_upd_clause luc;
|
2003-08-27 14:37:10 +01:00
|
|
|
struct logic_upd_index lui;
|
2003-04-30 18:46:05 +01:00
|
|
|
struct dynamic_clause ic;
|
|
|
|
struct static_clause sc;
|
2004-09-27 21:45:04 +01:00
|
|
|
struct static_mega_clause mc;
|
2003-08-27 14:37:10 +01:00
|
|
|
struct static_index si;
|
2003-04-30 18:46:05 +01:00
|
|
|
} ClauseUnion;
|
|
|
|
|
2006-03-21 15:06:36 +00:00
|
|
|
typedef union clause_ptr {
|
|
|
|
struct logic_upd_clause *luc;
|
|
|
|
struct logic_upd_index *lui;
|
|
|
|
struct dynamic_clause *ic;
|
|
|
|
struct static_clause *sc;
|
|
|
|
struct static_mega_clause *mc;
|
|
|
|
struct static_index *si;
|
|
|
|
} ClausePointer;
|
|
|
|
|
2007-11-06 17:02:13 +00:00
|
|
|
typedef struct dbterm_list {
|
|
|
|
/* a list of dbterms associated with a clause */
|
|
|
|
DBTerm *dbterms;
|
|
|
|
yamop *clause_code;
|
|
|
|
PredEntry *p;
|
|
|
|
struct dbterm_list *next_dbl;
|
|
|
|
} DBTermList;
|
|
|
|
|
2003-04-30 18:46:05 +01:00
|
|
|
#define ClauseCodeToDynamicClause(p) ((DynamicClause *)((CODEADDR)(p)-(CELL)(((DynamicClause *)NULL)->ClCode)))
|
|
|
|
#define ClauseCodeToStaticClause(p) ((StaticClause *)((CODEADDR)(p)-(CELL)(((StaticClause *)NULL)->ClCode)))
|
|
|
|
#define ClauseCodeToLogUpdClause(p) ((LogUpdClause *)((CODEADDR)(p)-(CELL)(((LogUpdClause *)NULL)->ClCode)))
|
2004-09-27 21:45:04 +01:00
|
|
|
#define ClauseCodeToMegaClause(p) ((MegaClause *)((CODEADDR)(p)-(CELL)(((MegaClause *)NULL)->ClCode)))
|
2003-08-27 14:37:10 +01:00
|
|
|
#define ClauseCodeToLogUpdIndex(p) ((LogUpdIndex *)((CODEADDR)(p)-(CELL)(((LogUpdIndex *)NULL)->ClCode)))
|
|
|
|
#define ClauseCodeToStaticIndex(p) ((StaticIndex *)((CODEADDR)(p)-(CELL)(((StaticIndex *)NULL)->ClCode)))
|
2001-04-09 20:54:03 +01:00
|
|
|
|
2003-04-30 18:46:05 +01:00
|
|
|
#define ClauseFlagsToDynamicClause(p) ((DynamicClause *)(p))
|
2003-08-27 14:37:10 +01:00
|
|
|
#define ClauseFlagsToLogUpdClause(p) ((LogUpdClause *)((CODEADDR)(p)-(CELL)(&(((LogUpdClause *)NULL)->ClFlags))))
|
2003-10-14 01:53:10 +01:00
|
|
|
#define ClauseFlagsToLogUpdIndex(p) ((LogUpdIndex *)((CODEADDR)(p)-(CELL)(&(((LogUpdIndex *)NULL)->ClFlags))))
|
2003-04-30 18:46:05 +01:00
|
|
|
#define ClauseFlagsToStaticClause(p) ((StaticClause *)(p))
|
2001-04-09 20:54:03 +01:00
|
|
|
|
2003-04-30 18:46:05 +01:00
|
|
|
#define DynamicFlags(X) (ClauseCodeToDynamicClause(X)->ClFlags)
|
2001-04-09 20:54:03 +01:00
|
|
|
|
2003-04-30 18:46:05 +01:00
|
|
|
#define DynamicLock(X) (ClauseCodeToDynamicClause(X)->ClLock)
|
2001-04-09 20:54:03 +01:00
|
|
|
|
2011-04-14 18:51:11 +01:00
|
|
|
#if MULTIPLE_STACKS
|
2003-08-27 14:37:10 +01:00
|
|
|
#define INIT_CLREF_COUNT(X) (X)->ClRefCount = 0
|
|
|
|
#define INC_CLREF_COUNT(X) (X)->ClRefCount++
|
|
|
|
#define DEC_CLREF_COUNT(X) (X)->ClRefCount--
|
2008-08-08 15:05:34 +01:00
|
|
|
|
2004-02-20 02:28:19 +00:00
|
|
|
#define CL_IN_USE(X) ((X)->ClRefCount)
|
2001-04-09 20:54:03 +01:00
|
|
|
#else
|
|
|
|
#define INIT_CLREF_COUNT(X)
|
|
|
|
#define INC_CLREF_COUNT(X)
|
|
|
|
#define DEC_CLREF_COUNT(X)
|
2003-08-27 14:37:10 +01:00
|
|
|
#define CL_IN_USE(X) ((X)->ClFlags & InUseMask || (X)->ClRefCount)
|
2001-04-09 20:54:03 +01:00
|
|
|
#endif
|
|
|
|
|
2003-01-13 14:02:50 +00:00
|
|
|
/* amasm.c */
|
|
|
|
wamreg STD_PROTO(Yap_emit_x,(CELL));
|
2008-08-21 13:38:25 +01:00
|
|
|
COUNT STD_PROTO(Yap_compile_cmp_flags,(PredEntry *));
|
2003-01-29 14:47:17 +00:00
|
|
|
void STD_PROTO(Yap_InitComma,(void));
|
2003-01-13 14:02:50 +00:00
|
|
|
|
2001-04-09 20:54:03 +01:00
|
|
|
/* cdmgr.c */
|
2010-01-29 15:21:00 +00:00
|
|
|
void STD_PROTO(Yap_IPred,(PredEntry *, UInt, yamop *));
|
2004-10-31 02:18:04 +00:00
|
|
|
int STD_PROTO(Yap_addclause,(Term,yamop *,int,Term,Term*));
|
2003-08-27 14:37:10 +01:00
|
|
|
void STD_PROTO(Yap_add_logupd_clause,(PredEntry *,LogUpdClause *,int));
|
|
|
|
void STD_PROTO(Yap_kill_iblock,(ClauseUnion *,ClauseUnion *,PredEntry *));
|
2004-02-12 12:37:12 +00:00
|
|
|
void STD_PROTO(Yap_EraseStaticClause,(StaticClause *, Term));
|
2003-08-27 14:37:10 +01:00
|
|
|
ClauseUnion *STD_PROTO(Yap_find_owner_index,(yamop *, PredEntry *));
|
2001-04-09 20:54:03 +01:00
|
|
|
|
|
|
|
/* dbase.c */
|
2003-04-30 18:46:05 +01:00
|
|
|
void STD_PROTO(Yap_ErCl,(DynamicClause *));
|
|
|
|
void STD_PROTO(Yap_ErLogUpdCl,(LogUpdClause *));
|
2006-10-10 15:08:17 +01:00
|
|
|
void STD_PROTO(Yap_ErLogUpdIndex,(LogUpdIndex *));
|
2004-10-06 17:55:48 +01:00
|
|
|
Int STD_PROTO(Yap_Recordz,(Atom, Term));
|
2002-12-27 16:53:09 +00:00
|
|
|
|
2003-01-29 14:47:17 +00:00
|
|
|
/* exec.c */
|
|
|
|
Term STD_PROTO(Yap_cp_as_integer,(choiceptr));
|
|
|
|
|
2002-12-27 16:53:09 +00:00
|
|
|
/* index.c */
|
2010-01-29 15:21:00 +00:00
|
|
|
yamop *STD_PROTO(Yap_PredIsIndexable,(PredEntry *, UInt, yamop *));
|
2004-09-30 20:51:54 +01:00
|
|
|
yamop *STD_PROTO(Yap_ExpandIndex,(PredEntry *, UInt));
|
2006-10-10 15:08:17 +01:00
|
|
|
void STD_PROTO(Yap_CleanUpIndex,(struct logic_upd_index *));
|
2008-01-23 17:57:56 +00:00
|
|
|
void STD_PROTO(Yap_CleanKids,(struct logic_upd_index *));
|
2003-08-27 14:37:10 +01:00
|
|
|
void STD_PROTO(Yap_AddClauseToIndex,(PredEntry *,yamop *,int));
|
|
|
|
void STD_PROTO(Yap_RemoveClauseFromIndex,(PredEntry *,yamop *));
|
2003-12-01 19:22:01 +00:00
|
|
|
LogUpdClause *STD_PROTO(Yap_NthClause,(PredEntry *,Int));
|
2004-03-31 02:03:10 +01:00
|
|
|
LogUpdClause *STD_PROTO(Yap_FollowIndexingCode,(PredEntry *,yamop *, Term *, yamop *,yamop *));
|
2002-12-27 16:53:09 +00:00
|
|
|
|
2003-06-06 12:54:02 +01:00
|
|
|
#if USE_THREADED_CODE
|
|
|
|
|
|
|
|
#define OP_HASH_SIZE 2048
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
rtable_hash_op(OPCODE opc, int hash_mask) {
|
|
|
|
return((((CELL)opc) >> 3) & hash_mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* given an opcode find the corresponding opnumber. This should make
|
|
|
|
switches on ops a much easier operation */
|
|
|
|
static inline op_numbers
|
|
|
|
Yap_op_from_opcode(OPCODE opc)
|
|
|
|
{
|
|
|
|
int j = rtable_hash_op(opc,OP_HASH_SIZE-1);
|
|
|
|
|
|
|
|
while (OP_RTABLE[j].opc != opc) {
|
2004-09-27 21:45:04 +01:00
|
|
|
if (!OP_RTABLE[j].opc)
|
|
|
|
return _Nstop;
|
2003-06-06 12:54:02 +01:00
|
|
|
if (j == OP_HASH_SIZE-1) {
|
|
|
|
j = 0;
|
|
|
|
} else {
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return OP_RTABLE[j].opnum;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline op_numbers
|
|
|
|
Yap_op_from_opcode(OPCODE opc)
|
|
|
|
{
|
|
|
|
return((op_numbers)opc);
|
|
|
|
}
|
|
|
|
#endif /* USE_THREADED_CODE */
|
2003-08-27 14:37:10 +01:00
|
|
|
|
2004-06-29 20:04:46 +01:00
|
|
|
#if defined(YAPOR) || defined(THREADS)
|
2006-03-24 16:26:31 +00:00
|
|
|
static inline int same_lu_block(yamop **, yamop *);
|
2004-12-02 06:06:47 +00:00
|
|
|
|
2006-03-24 16:26:31 +00:00
|
|
|
static inline int
|
2004-06-29 20:04:46 +01:00
|
|
|
same_lu_block(yamop **paddr, yamop *p)
|
|
|
|
{
|
|
|
|
yamop *np = *paddr;
|
|
|
|
if (np != p) {
|
|
|
|
OPCODE jmp_op = Yap_opcode(_jump_if_nonvar);
|
|
|
|
|
|
|
|
while (np->opc == jmp_op) {
|
2005-04-10 05:01:15 +01:00
|
|
|
np = NEXTOP(np, xll);
|
2004-06-29 20:04:46 +01:00
|
|
|
if (np == p) return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-09-27 21:45:04 +01:00
|
|
|
static inline Term
|
|
|
|
Yap_MkStaticRefTerm(StaticClause *cp)
|
|
|
|
{
|
|
|
|
Term t[1];
|
|
|
|
t[0] = MkIntegerTerm((Int)cp);
|
|
|
|
return Yap_MkApplTerm(FunctorStaticClause,1,t);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline StaticClause *
|
|
|
|
Yap_ClauseFromTerm(Term t)
|
|
|
|
{
|
|
|
|
return (StaticClause *)IntegerOfTerm(ArgOfTerm(1,t));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Term
|
|
|
|
Yap_MkMegaRefTerm(PredEntry *ap,yamop *ipc)
|
|
|
|
{
|
|
|
|
Term t[2];
|
|
|
|
t[0] = MkIntegerTerm((Int)ap);
|
2004-09-30 20:51:54 +01:00
|
|
|
t[1] = MkIntegerTerm((Int)ipc);
|
2004-09-27 21:45:04 +01:00
|
|
|
return Yap_MkApplTerm(FunctorMegaClause,2,t);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline yamop *
|
|
|
|
Yap_MegaClauseFromTerm(Term t)
|
|
|
|
{
|
2004-10-06 22:15:49 +01:00
|
|
|
return (yamop *)IntegerOfTerm(ArgOfTerm(2,t));
|
2004-09-27 21:45:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline PredEntry *
|
|
|
|
Yap_MegaClausePredicateFromTerm(Term t)
|
|
|
|
{
|
2004-10-06 22:15:49 +01:00
|
|
|
return (PredEntry *)IntegerOfTerm(ArgOfTerm(1,t));
|
2004-09-27 21:45:04 +01:00
|
|
|
}
|
|
|
|
|
2004-10-26 21:16:18 +01:00
|
|
|
typedef enum {
|
|
|
|
FIND_PRED_FROM_ANYWHERE,
|
|
|
|
FIND_PRED_FROM_CP,
|
|
|
|
FIND_PRED_FROM_ENV
|
|
|
|
} find_pred_type;
|
|
|
|
|
2005-07-06 16:10:18 +01:00
|
|
|
Int STD_PROTO(Yap_PredForCode,(yamop *, find_pred_type, Atom *, UInt *, Term *));
|
2005-12-17 03:25:39 +00:00
|
|
|
PredEntry *STD_PROTO(Yap_PredEntryForCode,(yamop *, find_pred_type, CODEADDR *, CODEADDR *));
|
2005-06-01 14:53:46 +01:00
|
|
|
LogUpdClause *STD_PROTO(Yap_new_ludbe,(Term, PredEntry *, UInt));
|
|
|
|
Term STD_PROTO(Yap_LUInstance,(LogUpdClause *, UInt));
|
2005-07-06 16:10:18 +01:00
|
|
|
|
2009-02-12 16:39:20 +00:00
|
|
|
/* udi.c */
|
|
|
|
void STD_PROTO(Yap_udi_init,(void));
|
|
|
|
yamop *STD_PROTO(Yap_udi_search,(PredEntry *));
|
|
|
|
int STD_PROTO(Yap_new_udi_clause,(PredEntry *, yamop *, Term));
|
|
|
|
|
2005-07-06 16:10:18 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
void STD_PROTO(Yap_bug_location,(yamop *));
|
2004-10-26 21:16:18 +01:00
|
|
|
#endif
|
|
|
|
|
2005-12-17 03:25:39 +00:00
|
|
|
#if LOW_PROF
|
|
|
|
void STD_PROTO(Yap_InformOfRemoval,(CODEADDR));
|
|
|
|
void STD_PROTO(Yap_dump_code_area_for_profiler,(void));
|
|
|
|
#else
|
|
|
|
#define Yap_InformOfRemoval(X)
|
|
|
|
#endif
|