builtin.c

00001 /* File:      builtin.c
00002 ** Author(s): Xu, Warren, Sagonas, Swift, Freire, Johnson
00003 ** Contact:   xsb-contact@cs.sunysb.edu
00004 ** 
00005 ** Copyright (C) The Research Foundation of SUNY, 1986, 1993-1999
00006 ** Copyright (C) ECRC, Germany, 1990
00007 ** 
00008 ** XSB is free software; you can redistribute it and/or modify it under the
00009 ** terms of the GNU Library General Public License as published by the Free
00010 ** Software Foundation; either version 2 of the License, or (at your option)
00011 ** any later version.
00012 ** 
00013 ** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
00014 ** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00015 ** FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
00016 ** more details.
00017 ** 
00018 ** You should have received a copy of the GNU Library General Public License
00019 ** along with XSB; if not, write to the Free Software Foundation,
00020 ** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00021 **
00022 ** $Id: builtin.c,v 1.269 2006/07/07 21:08:14 dwarren Exp $
00023 ** 
00024 */
00025 
00026 #include "xsb_config.h"
00027 #include "xsb_debug.h"
00028 
00029 /* Private debugs */
00030 #include "debugs/debug_delay.h"
00031 #include "context.h"
00032 
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include <errno.h>
00037 #include <sys/types.h>
00038 #include <sys/stat.h>
00039 #include <signal.h>
00040 #include <math.h>
00041 
00042 #ifdef WIN_NT
00043 #include <windows.h>
00044 #include <direct.h>
00045 #include <io.h>
00046 #include <process.h>
00047 #include <stdarg.h>
00048 #include <winsock.h>
00049 #include "wsipx.h"
00050 #include <tchar.h>
00051 #else /* Unix */
00052 #include <unistd.h> 
00053 #include <sys/socket.h>
00054 #include <sys/uio.h>
00055 #include <netdb.h>
00056 #include <netinet/in.h>
00057 #include <arpa/inet.h>
00058 #endif
00059 
00060 #include <fcntl.h>
00061 
00062 #include "auxlry.h"
00063 #include "cell_xsb.h"
00064 #include "error_xsb.h"
00065 #include "psc_xsb.h"
00066 
00067 #include "ubi_BinTree.h"
00068 #include "ubi_SplayTree.h"
00069 
00070 #include "hash_xsb.h"
00071 #include "tries.h"
00072 #include "choice.h"
00073 #include "deref.h"
00074 #include "memory_xsb.h"
00075 #include "heap_xsb.h"
00076 #include "register.h"
00077 #include "flags_xsb.h"
00078 #include "loader_xsb.h"
00079 #include "binding.h"
00080 #include "macro_xsb.h"
00081 #include "builtin.h"
00082 #include "sig_xsb.h"
00083 #include "subp.h"
00084 #include "tr_utils.h"
00085 #include "trassert.h"
00086 #include "dynload.h"
00087 #include "cinterf.h"
00088 #include "residual.h"
00089 #include "tables.h"
00090 #include "trie_internals.h"
00091 #include "table_status_defs.h"
00092 #include "rw_lock.h"
00093 #include "deadlock.h"
00094 #ifdef ORACLE
00095 #include "oracle_xsb.h"
00096 #endif
00097 
00098 #ifdef XSB_ODBC
00099 #include "odbc_xsb.h"
00100 #endif
00101 
00102 #ifdef XSB_INTERPROLOG
00103 #include "interprolog_xsb.h"
00104 #endif
00105 
00106 #ifdef PROFILE
00107 #include "inst_xsb.h"
00108 #include "subinst.h"
00109 #endif
00110 
00111 #include "io_builtins_xsb.h"
00112 #include "storage_xsb.h"
00113 
00114 /* wind2unix.h must be included after sys/stat.h */
00115 #include "wind2unix.h"
00116 #include "system_xsb.h"
00117 #include "random_xsb.h"
00118 #include "thread_xsb.h"
00119 #ifdef DEMAND
00120 #include "demand.h"
00121 #endif
00122 #include "debug_xsb.h"
00123 
00124 #include "thread_xsb.h"
00125 
00126 int mem_flag;
00127 
00128 /*======================================================================*/
00129 extern struct token_t *GetToken(CTXTdeclc FILE *, STRFILE *, int);
00130 
00131 extern int  sys_syscall(CTXTdeclc int);
00132 extern xsbBool sys_system(CTXTdeclc int);
00133 extern xsbBool formatted_io(CTXTdecl), read_canonical(CTXTdecl);
00134 extern xsbBool private_builtin(void);
00135 
00136 extern void xsb_segfault_quitter(int err);
00137 
00138 extern int xsb_profiling_enabled;
00139 
00140 #ifdef WIN_NT
00141 extern xsbBool startInterruptThread(SOCKET intSocket);
00142 #endif
00143 
00144 // Externs for profiler
00145 
00146 long if_profiling = 0;
00147 long profile_thread_started = 0;
00148 static long prof_unk_count = 0;
00149 static long prof_total = 0;
00150 
00151 static long total_prog_segments = 0;
00152 static long prof_table_length = 0;
00153 static long prof_table_count = 0;
00154 
00155 /*static Psc colon_psc = NULL;*/
00156 
00157 extern xsbBool startProfileThread();
00158 extern void dump_prof_table();
00159 extern void retrieve_prof_table();
00160 
00161 // Externs for assert/retract
00162 extern xsbBool assert_code_to_buff(CTXTdecl), assert_buff_to_clref(CTXTdecl);
00163 extern xsbBool gen_retract_all(CTXTdecl), db_retract0(CTXTdecl), 
00164   db_get_clause(CTXTdecl);
00165 extern xsbBool db_get_last_clause(CTXTdecl);
00166 extern xsbBool db_build_prref(CTXTdecl), db_abolish0(CTXTdecl), 
00167                db_reclaim0(CTXTdecl), db_get_prref(CTXTdecl);
00168 extern xsbBool dynamic_code_function(CTXTdecl);
00169 
00170 extern char *dirname_canonic(char *);
00171 extern xsbBool almost_search_module(CTXTdeclc char *);
00172 extern char *expand_filename(char *filename);
00173 extern char *existing_file_extension(char *);
00174 extern char *tilde_expand_filename(char *filename);
00175 extern xsbBool is_absolute_filename(char *filename);
00176 extern void parse_filename(char *filenam, char **dir, char **base, char **ext);
00177 
00178 int print_xsb_backtrace(CTXTdecl);
00179 prolog_term build_xsb_backtrace(CTXTdecl);
00180 
00181 extern xsbBool xsb_socket_request(CTXTdecl);
00182 
00183 extern int  findall_init(CTXTdecl), findall_add(CTXTdecl),
00184   findall_get_solutions(CTXTdecl);
00185 extern int  copy_term(CTXTdecl);
00186 
00187 extern xsbBool substring(CTXTdecl);
00188 extern xsbBool string_substitute(CTXTdecl);
00189 extern xsbBool str_cat(CTXTdecl);
00190 extern xsbBool str_sub(void);
00191 extern xsbBool str_match(CTXTdecl);
00192 
00193 // For force_truth_value (which may not be used much)
00194 extern void force_answer_true(BTNptr);
00195 extern void force_answer_false(BTNptr);
00196 
00197 // catch/throw.
00198 extern int set_scope_marker(CTXTdecl);
00199 extern int unwind_stack(CTXTdecl);
00200 extern int clean_up_block(CTXTdecl);
00201 
00202 extern double realtime_count_gl; /* from subp.c */
00203 
00204 extern BTNptr trie_asserted_trienode(CPtr clref);
00205 extern int gc_dynamic(CTXTdecl);
00206 
00207 /* ------- variables also used in other parts of the system ----------- */
00208 
00209 Cell flags[MAX_FLAGS];                    /* System flags + user flags */
00210 #ifndef MULTI_THREAD
00211 Cell pflags[MAX_PRIVATE_FLAGS];           /* Thread private flags */
00212 #endif
00213 
00214 /* ------- utility routines ------------------------------------------- */
00215 
00216 
00217 #include "ptoc_tag_xsb_i.h"
00218 
00219 
00220 DllExport prolog_int call_conv ptoc_int(CTXTdeclc int regnum)
00221 {
00222   /* reg is global array in register.h in the single-threaded engine
00223    * and is defined as a thread-specific macro in context.h in the
00224    * multi-threaded engine
00225    */  
00226   register Cell addr = cell(reg+regnum);
00227 
00228   /* XSB_Deref and then check the type */
00229   XSB_Deref(addr);
00230 
00231   switch (cell_tag(addr)) {
00232   case XSB_STRUCT:
00233     if (isboxedinteger(addr)) return(boxedint_val(addr));
00234   case XSB_FREE:
00235   case XSB_REF1: 
00236   case XSB_ATTV:
00237   case XSB_LIST:
00238   case XSB_FLOAT: xsb_abort("[PTOC_INT] Integer argument expected, %d tag found\n",cell_tag(addr));
00239   case XSB_STRING: return (prolog_int)string_val(addr); /* dsw */
00240   case XSB_INT: return int_val(addr);
00241   default: xsb_abort("[PTOC_INT] Argument of unknown type");
00242   }
00243   return FALSE;
00244 }
00245 
00246 DllExport prolog_float call_conv ptoc_float(CTXTdeclc int regnum)
00247 {
00248   /* reg is global array in register.h in the single-threaded engine
00249    * and is defined as a thread-specific macro in context.h in the
00250    * multi-threaded engine
00251    */  
00252   register Cell addr = cell(reg+regnum);
00253 
00254   /* XSB_Deref and then check the type */
00255   XSB_Deref( addr );
00256   switch (cell_tag(addr)) {
00257   case XSB_FREE:
00258   case XSB_REF1: 
00259   case XSB_ATTV: 
00260   case XSB_LIST:
00261   case XSB_INT:
00262   case XSB_STRING:
00263     xsb_abort("[PTOC_FLOAT] Float argument expected");
00264   case XSB_STRUCT: 
00265       if (!isboxedfloat(addr))
00266           xsb_abort("[PTOC_FLOAT] Float argument expected");      
00267   case XSB_FLOAT: return (prolog_float)ofloat_val(addr);
00268   default:
00269     xsb_abort("[PTOC_FLOAT] Argument of unknown type");
00270   }
00271   return 0.0;
00272 }
00273 
00274 DllExport char* call_conv ptoc_string(CTXTdeclc int regnum)
00275 {
00276   /* reg is global array in register.h in the single-threaded engine
00277    * and is defined as a thread-specific macro in context.h in the
00278    * multi-threaded engine
00279    */  
00280 
00281   register Cell addr = cell(reg+regnum);
00282   
00283   /* XSB_Deref and then check the type */
00284   XSB_Deref(addr);
00285   //printf("\nBUILTIN.C: dereferenced address: %lu\n", addr);
00286   switch (cell_tag(addr)) {
00287   case XSB_FREE:
00288   case XSB_REF1:
00289   case XSB_ATTV:
00290   case XSB_LIST:
00291   case XSB_FLOAT:
00292     xsb_abort("[PTOC_STRING] String (atom) argument expected");
00293   case XSB_STRUCT:  /* tentative approach to fix boxed ints --lfcastro */
00294     if (isboxedinteger(addr)) 
00295       return (char *)boxedint_val(addr);
00296     else
00297       xsb_abort("[PTOC_STRING] String (atom) argument expected");
00298   case XSB_INT: 
00299       return (char *)int_val(addr);
00300   case XSB_STRING: 
00301       return string_val(addr); 
00302   default:
00303     xsb_abort("[PTOC_STRING] Argument of unknown type");
00304   }
00305   return "";
00306 }
00307 
00308 /* Used to pass integer or float values to math functions 
00309    that do the conversion. */
00310 DllExport prolog_float call_conv ptoc_number(CTXTdeclc int regnum)
00311 {
00312   /* reg is global array in register.h in the single-threaded engine
00313    * and is defined as a thread-specific macro in context.h in the
00314    * multi-threaded engine
00315    */  
00316   register Cell addr = cell(reg+regnum);
00317 
00318   /* XSB_Deref and then check the type */
00319   XSB_Deref(addr);
00320   switch (cell_tag(addr)) {
00321   case XSB_STRUCT:
00322     if (isboxedfloat(addr)) return(boxedfloat_val(addr));
00323     if (isboxedinteger(addr)) return(boxedint_val(addr));
00324   case XSB_FREE:
00325   case XSB_REF1: 
00326   case XSB_ATTV:
00327   case XSB_LIST: xsb_abort("[PTOC_INT] Float-convertable argument expected");
00328   case XSB_FLOAT: return (prolog_float)float_val(addr);
00329   case XSB_STRING: return (prolog_int)string_val(addr); /* dsw */
00330   case XSB_INT: return int_val(addr);
00331   default: xsb_abort("[PTOC_INT] Argument of unknown type");
00332   }
00333   return 0.0;
00334 }
00335 
00336 
00337 #define MAXSBUFFS 30 /* also defined in init_xsb.c (for mt), so if change here.... */
00338 #ifndef MULTI_THREAD
00339 static VarString *LSBuff[MAXSBUFFS] = {NULL};
00340 #endif
00341 
00342 /* construct a long string from prolog... concatenates atoms,
00343 flattening lists and comma-lists, and treating small ints as ascii
00344 codes.  Puts result in a fixed buffer (if nec.) automatically extended */
00345 
00346 void constructString(CTXTdeclc Cell addr, int ivstr)
00347 {
00348   int val;
00349 
00350  constructStringBegin:
00351   XSB_Deref(addr);
00352   switch (cell_tag(addr)) {
00353   case XSB_FREE:
00354   case XSB_REF1:
00355   case XSB_ATTV:
00356   case XSB_FLOAT:
00357     xsb_abort("[PTOC_LONGSTRING] Argument of unknown type");
00358   case XSB_STRUCT:  
00359     if (get_str_psc(addr) == comma_psc) {
00360       constructString(CTXTc cell(clref_val(addr)+1),ivstr);
00361       addr = cell(clref_val(addr)+2);  /* tail recursion opt */
00362       goto constructStringBegin;
00363     } else xsb_abort("[PTOC_LONGSTRING] Argument of unknown type");
00364   case XSB_LIST:
00365     constructString(CTXTc cell(clref_val(addr)),ivstr);
00366     addr = cell(clref_val(addr)+1);  /* tail recursion opt */
00367     goto constructStringBegin;
00368   case XSB_INT: 
00369     val = int_val(addr);
00370     if (val < 256 && val >= 0) {
00371       XSB_StrAppendC(LSBuff[ivstr],(char)val);
00372       return;
00373     } else xsb_abort("[PTOC_LONGSTRING] Argument of unknown type");
00374   case XSB_STRING: 
00375     if (isnil(addr)) return;
00376     XSB_StrAppend(LSBuff[ivstr],string_val(addr));
00377     return;
00378   default:
00379     xsb_abort("[PTOC_LONGSTRING] Argument of unknown type");
00380   }
00381 }
00382 
00383 DllExport char* call_conv ptoc_longstring(CTXTdeclc int regnum)
00384 {
00385   /* reg is global array in register.h in the single-threaded engine
00386    * and is defined as a thread-specific macro in context.h in the
00387    * multi-threaded engine
00388    */  
00389   register Cell addr = cell(reg+regnum);
00390   XSB_Deref(addr);
00391   if (isstring(addr)) return string_val(addr);
00392   if (isinteger(addr)) return (char *)int_val(addr);
00393   
00394   if (LSBuff[regnum]==NULL) {
00395     XSB_StrCreate(&LSBuff[regnum]);
00396   }
00397   XSB_StrSet(LSBuff[regnum],"");
00398   constructString(CTXTc addr,regnum);
00399   return(LSBuff[regnum]->string);
00400 }
00401 
00402 /*
00403  *  For decoding object pointers, like PSC, PSC-PAIR and Subgoal frames.
00404  */
00405 #define ptoc_addr(regnum)       (void *)ptoc_int(CTXTc regnum)
00406 #define is_encoded_addr(term)   (isinteger(term) || isboxedinteger(term))
00407 #define decode_addr(term)       (void *)oint_val(term)
00408 
00409 
00410 /*
00411  *  Deref's the variable of register `regnum', trails the binding,
00412  *  creates an INT Cell containing `value', and binds the variable to it.
00413  */
00414 DllExport void call_conv ctop_int(CTXTdeclc int regnum, prolog_int value)
00415 {
00416   register Cell addr = cell(reg+regnum);
00417   
00418   XSB_Deref(addr);
00419   if (isref(addr)) {
00420     bind_oint(vptr(addr),value);
00421   }
00422   else {
00423     if (isstring(addr)) printf("string %s\n",string_val(addr));
00424     if (isinteger(addr)) printf("int %d\n",int_val(addr));
00425     xsb_abort("[CTOP_INT] Wrong type of argument %lx (Reg = %d)", addr, regnum);
00426   }
00427 }
00428 
00429 
00430 /* from float value form an int node */
00431 DllExport void call_conv ctop_float(CTXTdeclc int regnum, prolog_float value)
00432 {
00433   /* reg is global array in register.h in the single-threaded engine
00434    * and is defined as a thread-specific macro in context.h in the
00435    * multi-threaded engine
00436    */  
00437   register Cell addr = cell(reg+regnum);
00438 
00439   XSB_Deref(addr);
00440   if (isref(addr)) {
00441     bind_boxedfloat(vptr(addr), value);
00442   }
00443   else xsb_abort("[CTOP_FLOAT] Wrong type of argument: %lux", addr);
00444 }
00445 
00446 /* take a C string, form a string node */
00447 DllExport void call_conv ctop_string(CTXTdeclc int regnum, char *value)
00448 {
00449   /* reg is global array in register.h in the single-threaded engine
00450    * and is defined as a thread-specific macro in context.h in the
00451    * multi-threaded engine
00452    */  
00453   register Cell addr = cell(reg+regnum);
00454 
00455   XSB_Deref(addr);
00456   if (isref(addr)) {
00457     bind_string(vptr(addr), string_find(value,1));  //?? did not intern before??
00458   }
00459   else
00460     xsb_abort("[CTOP_STRING] Wrong type of argument: %lux", addr);
00461 }
00462 
00463 DllExport void call_conv extern_ctop_string(CTXTdeclc int regnum, char *value)
00464 {
00465   ctop_string(CTXTc regnum,string_find(value,1)) ;
00466 }
00467 
00468 inline static void ctop_constr(CTXTdeclc int regnum, Pair psc_pair)
00469 {                               /* from psc_pair ptr form an constr node */
00470   register Cell addr = cell(reg+regnum);
00471 
00472   XSB_Deref(addr);
00473   if (isref(addr)) {
00474     bind_cs(vptr(addr), psc_pair);
00475   }
00476   else xsb_abort("[CTOP_CONSTR] Wrong type of argument: %lux", addr);
00477 }
00478 
00479 /*
00480  *  Bind the variable pointed to by the "regnum"th argument register to the
00481  *  term at address "term".  Make an entry in the trail for this binding.
00482  */
00483 inline static void ctop_tag(CTXTdeclc int regnum, Cell term)
00484 {
00485   register Cell addr = cell(reg+regnum);
00486 
00487   XSB_Deref(addr);
00488   if (isref(addr)) {
00489     bind_copy(vptr(addr), term);
00490   }
00491   else
00492     xsb_abort("[CTOP_TAG] Wrong type of argument: %lux", addr);
00493 }
00494 
00495 
00496 /*
00497  *  For encoding object pointer, like PSC, PSC-PAIR and Subgoal frames.
00498  */
00499 #define ctop_addr(regnum, val)    ctop_int(CTXTc regnum, (prolog_int)val)
00500 
00501 /* -------------------------------------------------------------------- */
00502 
00503 Cell  val_to_hash(Cell term)
00504 {
00505   Cell value;
00506 
00507   switch(cell_tag(term)) {
00508     case XSB_INT:
00509       value = (Cell)int_val(term);
00510       break;
00511     case XSB_FLOAT:
00512       value = (Cell)int_val(term);
00513       break;
00514     case XSB_LIST:
00515       value = (Cell)(list_pscPair);
00516       break;
00517     case XSB_STRUCT:
00518       //to make a hash val for a boxed int, we take the int value inside the box and cast it
00519       //to a Cell.
00520       if (isboxedinteger(term))
00521       {
00522           value = (Cell)boxedint_val(term);
00523           break;
00524       }
00525       //to make a hash val for a boxed float, we take the int values inside the 3 boxes for
00526       //the float bits, and XOR them together
00527       else if (isboxedfloat(term))
00528       {
00529           value = int_val(cell(clref_val(term)+1)) ^
00530                     int_val(cell(clref_val(term)+2)) ^
00531                     int_val(cell(clref_val(term)+3));
00532           break;
00533       }
00534       //but if this structure isn't any special boxed representation, then we use its PSC as
00535       //a hash value.
00536       value = (Cell)get_str_psc(term);
00537       break;
00538     case XSB_STRING:
00539       value = (Cell)(string_val(term));
00540       break;
00541     default: xsb_abort("[term_hash/3] Indexing on illegal argument");
00542       value = 0;
00543       break;
00544   }
00545   return value;
00546 }
00547 
00548 /* -------------------------------------------------------------------- */
00549 
00550 Cell  det_val_to_hash(Cell term)
00551 {
00552   Cell value;
00553   Psc psc;
00554 
00555   switch(cell_tag(term)) {
00556     case XSB_INT:
00557       value = (Cell)int_val(term);
00558       break;
00559     case XSB_FLOAT:
00560       value = (Cell)int_val(term);
00561       break;
00562     case XSB_LIST:
00563       value = (Cell)(list_pscPair);
00564       break;
00565     case XSB_STRUCT:
00566       //to make a hash val for a boxed int, we take the int value inside the box and cast it
00567       //to a Cell.
00568       if (isboxedinteger(term))
00569       {
00570           value = (Cell)boxedint_val(term);
00571           break;
00572       }
00573       //to make a hash val for a boxed float, we take the int values inside the 3 boxes for
00574       //the float bits, and XOR them together
00575       else if (isboxedfloat(term))
00576       {
00577           value = int_val(cell(clref_val(term)+1)) ^
00578                     int_val(cell(clref_val(term)+2)) ^
00579                     int_val(cell(clref_val(term)+3));
00580           break;
00581       }
00582       //but if this structure isn't any special boxed representation, then we hash its name for
00583       //a hash value.
00584       psc = get_str_psc(term);
00585       value = hash(get_name(psc),get_arity(psc),4194301);
00586       break;
00587     case XSB_STRING:
00588       value = hash(string_val(term),0,4194301);
00589       break;
00590     default: xsb_abort("[term_hash/3] Indexing on illegal argument");
00591       value = 0;
00592       break;
00593   }
00594   return value;
00595 }
00596 
00597 /* -------------------------------------------------------------------- */
00598 
00599 static int ground(CTXTdeclc CPtr temp)
00600 {
00601  int j, arity;
00602  groundBegin:
00603   XSB_CptrDeref(temp);
00604   switch(cell_tag(temp)) {
00605   case XSB_FREE: 
00606   case XSB_REF1: 
00607   case XSB_ATTV:
00608     return FALSE;
00609 
00610   case XSB_STRING: 
00611   case XSB_INT: 
00612   case XSB_FLOAT:
00613     return TRUE;
00614 
00615   case XSB_LIST:
00616     if (!ground(CTXTc clref_val(temp))) 
00617       return FALSE;
00618     temp = clref_val(temp)+1;
00619     goto groundBegin;
00620 
00621   case XSB_STRUCT:
00622     arity = (int) get_arity(get_str_psc(temp));
00623     if (arity == 0) return TRUE;
00624     for (j=1; j < arity ; j++) 
00625       if (!ground(CTXTc clref_val(temp)+j))
00626         return FALSE;
00627     temp = clref_val(temp)+arity;
00628     goto groundBegin;
00629 
00630   default:
00631     xsb_abort("[ground/1] Term with unknown tag (%d)",
00632               (int)cell_tag(temp));
00633     return -1;  /* so that g++ does not complain */
00634   }
00635 }
00636 
00637 /* -------------------------------------------------------------------- */
00638 
00639 int is_proper_list(Cell term)   /* for standard preds */
00640 {
00641   register Cell addr;
00642 
00643   addr = term;
00644   XSB_Deref(addr);
00645   while (islist(addr)) {
00646     addr = cell(clref_val(addr)+1);
00647     XSB_Deref(addr);
00648   }
00649   return isnil(addr);
00650 }
00651 
00652 /* -------------------------------------------------------------------- */
00653 
00654 #define mini_undo_bindings                      \
00655     while (mini_trail_top >= mini_trail) {      \
00656         untrail(*mini_trail_top);               \
00657         mini_trail_top--;                       \
00658     }   
00659 
00660 #define mini_bind_variable(addr)                \
00661    follow(addr) = makenil;                      \
00662    *(++mini_trail_top) = (CPtr)addr;
00663 
00664 int is_most_general_term(Cell term)
00665 {
00666   CPtr mini_trail[MAX_ARITY];
00667   CPtr *mini_trail_top;
00668 
00669   XSB_Deref(term);
00670   switch (cell_tag(term)) {
00671   case XSB_STRING:
00672     return TRUE;
00673   case XSB_STRUCT:
00674     {
00675       Psc psc;
00676       CPtr taddr;
00677       int i, arity;
00678       register Cell addr;
00679 
00680       mini_trail_top = (CPtr *)(& mini_trail[0]) - 1;
00681       psc = get_str_psc(term);
00682       taddr = clref_val(term);
00683       arity = (int) get_arity(psc);
00684 
00685       for (i = 1; i <= arity ; ++i) {
00686         addr = cell(taddr+i);
00687         XSB_Deref(addr);
00688         if (isnonvar(addr)) {
00689           mini_undo_bindings;
00690           return FALSE;
00691         } else {
00692           mini_bind_variable(addr);
00693         }
00694       }
00695       mini_undo_bindings;
00696       return TRUE;
00697     }
00698   case XSB_LIST:
00699     {
00700       register Cell addr;
00701 
00702       mini_trail_top = (CPtr *) (& mini_trail[0]) -1;
00703       while (islist(term)) {
00704         addr = cell(clref_val(term));
00705         XSB_Deref(addr);
00706         if (isnonvar(addr)) {
00707           mini_undo_bindings;
00708           return FALSE;
00709         } else {
00710           mini_bind_variable(addr);
00711           term = cell(clref_val(term)+1);
00712           XSB_Deref(term);
00713         }
00714       }
00715       mini_undo_bindings;
00716       return isnil(term);
00717     }
00718   default:
00719     return FALSE;
00720   }
00721 }
00722 
00723 /* -------------------------------------------------------------------- */
00724 
00725 #include "term_psc_xsb_i.h"
00726 #include "conget_xsb_i.h"
00727 
00728 /* -------------------------------------------------------------------- */
00729 
00730 inline static void xsb_fprint_variable(CTXTdeclc FILE *fptr, CPtr var)
00731 {
00732   if (var >= (CPtr)glstack.low && var <= top_of_heap)
00733     fprintf(fptr, "_h%ld", ((Cell)var-(Cell)glstack.low+1)/sizeof(CPtr));
00734   else {
00735     if (var >= top_of_localstk && var <= (CPtr)glstack.high)
00736       fprintf(fptr, "_l%ld", ((Cell)glstack.high-(Cell)var+1)/sizeof(CPtr));
00737     else fprintf(fptr, "_%p", var);   /* Should never happen */
00738   }
00739 }
00740 
00741 void xsb_sprint_variable(CTXTdeclc char *sptr, CPtr var)
00742 {
00743   if (var >= (CPtr)glstack.low && var <= top_of_heap)
00744     sprintf(sptr, "_h%ld", ((Cell)var-(Cell)glstack.low+1)/sizeof(CPtr));
00745   else {
00746     if (var >= top_of_localstk && var <= (CPtr)glstack.high)
00747       sprintf(sptr, "_l%ld", ((Cell)glstack.high-(Cell)var+1)/sizeof(CPtr));
00748     else sprintf(sptr, "_%p", var);   /* Should never happen */
00749   }
00750 }
00751 
00752 /* -------------------------------------------------------------------- */
00753 
00754 Cell builtin_table[BUILTIN_TBL_SZ][2];
00755 
00756 #define BuiltinName(Code)       ( (char *)builtin_table[Code][0] )
00757 #define set_builtin_table(Code,String)          \
00758    builtin_table[Code][0] = (Cell)(String);
00759 
00760 void init_builtin_table(void)
00761 {
00762   int i;
00763 
00764   for (i = 0; i < BUILTIN_TBL_SZ; i++) builtin_table[i][1] = 0;
00765   
00766   set_builtin_table(PSC_NAME, "psc_name");
00767   set_builtin_table(PSC_ARITY, "psc_arity");
00768   set_builtin_table(PSC_TYPE, "psc_type");
00769   set_builtin_table(PSC_PROP, "psc_prop");
00770   set_builtin_table(PSC_SET_TYPE, "psc_set_type");
00771   set_builtin_table(PSC_SET_PROP, "psc_set_prop");
00772   set_builtin_table(CONGET_TERM, "conget");
00773   set_builtin_table(CONSET_TERM, "conset");
00774   set_builtin_table(PSC_SET_SPY, "psc_set_spy");
00775   set_builtin_table(PSC_EP, "psc_ep");
00776   set_builtin_table(PSC_SET_EP, "psc_set_ep");
00777 
00778   set_builtin_table(TERM_NEW_MOD, "term_new_mod");
00779   set_builtin_table(TERM_PSC, "term_psc");
00780   set_builtin_table(TERM_TYPE, "term_type");
00781   set_builtin_table(TERM_COMPARE, "term_compare");
00782   set_builtin_table(TERM_NEW, "term_new");
00783   set_builtin_table(TERM_ARG, "term_arg");
00784   set_builtin_table(TERM_SET_ARG, "term_set_arg");
00785   set_builtin_table(STAT_FLAG, "stat_flag");
00786   set_builtin_table(STAT_SET_FLAG, "stat_set_flag");
00787   set_builtin_table(BUFF_ALLOC, "buff_alloc");
00788   set_builtin_table(BUFF_WORD, "buff_word");
00789   set_builtin_table(BUFF_SET_WORD, "buff_set_word");
00790   set_builtin_table(BUFF_BYTE, "buff_byte");
00791   set_builtin_table(BUFF_SET_BYTE, "buff_set_byte");
00792   set_builtin_table(CODE_CALL, "code_call");
00793 
00794   set_builtin_table(STR_LEN, "str_len");
00795   set_builtin_table(SUBSTRING, "substring");
00796   set_builtin_table(STR_CAT, "str_cat");
00797   set_builtin_table(STR_CMP, "str_cmp");
00798   set_builtin_table(STRING_SUBSTITUTE, "string_substitute");
00799 
00800   set_builtin_table(CALL0, "call0");
00801   set_builtin_table(STAT_STA, "stat_sta");
00802   set_builtin_table(STAT_CPUTIME, "stat_cputime");
00803   set_builtin_table(CODE_LOAD, "code_load");
00804   set_builtin_table(BUFF_SET_VAR, "buff_set_var");
00805   set_builtin_table(BUFF_DEALLOC, "buff_dealloc");
00806   set_builtin_table(BUFF_CELL, "buff_cell");
00807   set_builtin_table(BUFF_SET_CELL, "buff_set_cell");
00808   set_builtin_table(COPY_TERM,"copy_term");
00809   set_builtin_table(XWAM_STATE,"xwam_state");
00810 
00811   set_builtin_table(STR_MATCH, "str_match");
00812   set_builtin_table(DIRNAME_CANONIC, "dirname_canonic");
00813 
00814   set_builtin_table(PSC_INSERT, "psc_insert");
00815   set_builtin_table(PSC_IMPORT, "psc_import");
00816   set_builtin_table(PSC_DATA, "psc_data");
00817   set_builtin_table(PSC_INSERTMOD, "psc_insertmod");
00818 
00819   set_builtin_table(FILE_GETTOKEN, "file_gettoken");
00820   set_builtin_table(FILE_PUTTOKEN, "file_puttoken");
00821   set_builtin_table(TERM_HASH, "term_hash");
00822   set_builtin_table(UNLOAD_SEG, "unload_seg");
00823   set_builtin_table(LOAD_OBJ, "load_obj");
00824 
00825   set_builtin_table(GETENV, "getenv");
00826   set_builtin_table(SYS_SYSCALL, "sys_syscall");
00827   set_builtin_table(SYS_SYSTEM, "sys_system");
00828   set_builtin_table(SYS_GETHOST, "sys_gethost");
00829   set_builtin_table(SYS_ERRNO, "sys_errno");
00830   set_builtin_table(FILE_WRITEQUOTED, "file_writequoted");
00831   set_builtin_table(GROUND, "ground");
00832 
00833   set_builtin_table(INTERN_STRING, "intern_string");
00834   set_builtin_table(EXPAND_FILENAME, "expand_filename");
00835   set_builtin_table(TILDE_EXPAND_FILENAME, "tilde_expand_filename");
00836   set_builtin_table(IS_ABSOLUTE_FILENAME, "is_absolute_filename");
00837   set_builtin_table(PARSE_FILENAME, "parse_filename");
00838   set_builtin_table(ALMOST_SEARCH_MODULE, "almost_search_module");
00839   set_builtin_table(EXISTING_FILE_EXTENSION, "existing_file_extension");
00840 
00841   set_builtin_table(DO_ONCE, "do_once");
00842 
00843   set_builtin_table(GET_DATE, "get_date");
00844   set_builtin_table(STAT_WALLTIME, "stat_walltime");
00845 
00846   set_builtin_table(PSC_GET_SET_ENV_BYTE, "psc_get_set_env_byte");
00847   set_builtin_table(PSC_ENV, "psc_env");
00848   set_builtin_table(PSC_SPY, "psc_spy");
00849   set_builtin_table(PSC_TABLED, "psc_tabled");
00850   set_builtin_table(PSC_SET_TABLED, "psc_set_tabled");
00851 
00852   set_builtin_table(IS_INCOMPLETE, "is_incomplete");
00853 
00854   set_builtin_table(GET_PTCP, "get_ptcp");
00855   set_builtin_table(GET_PRODUCER_CALL, "get_producer_call");
00856   set_builtin_table(DEREFERENCE_THE_BUCKET, "dereference_the_bucket");
00857   set_builtin_table(PAIR_PSC, "pair_psc");
00858   set_builtin_table(PAIR_NEXT, "pair_next");
00859   set_builtin_table(NEXT_BUCKET, "next_bucket");
00860 
00861   set_builtin_table(SLG_NOT, "slg_not");
00862   set_builtin_table(IS_XWAMMODE, "is_xwammode");
00863   set_builtin_table(CLOSE_OPEN_TABLES, "close_open_tables");
00864 
00865   set_builtin_table(FILE_FUNCTION, "file_function");
00866   set_builtin_table(SLASH_BUILTIN, "slash");
00867 
00868   set_builtin_table(ABOLISH_TABLE_INFO, "abolish_table_info");
00869   set_builtin_table(ABOLISH_MODULE_TABLES, "abolish_module_tables");
00870   set_builtin_table(ZERO_OUT_PROFILE, "zero_out_profile");
00871   set_builtin_table(WRITE_OUT_PROFILE, "write_out_profile");
00872   set_builtin_table(ASSERT_CODE_TO_BUFF, "assert_code_to_buff");
00873   set_builtin_table(ASSERT_BUFF_TO_CLREF, "assert_buff_to_clref");
00874 
00875   set_builtin_table(FILE_READ_CANONICAL, "file_read_canonical");
00876   set_builtin_table(GEN_RETRACT_ALL, "gen_retract_all");
00877 
00878   set_builtin_table(DB_GET_LAST_CLAUSE, "db_get_last_clause");
00879   set_builtin_table(DB_RETRACT0, "db_retract0");
00880   set_builtin_table(DB_GET_CLAUSE, "db_get_clause");
00881   set_builtin_table(DB_BUILD_PRREF, "db_build_prref");
00882   set_builtin_table(DB_GET_PRREF, "db_get_prref");
00883   set_builtin_table(DB_ABOLISH0, "db_abolish0");
00884   set_builtin_table(DB_RECLAIM0, "db_reclaim0");
00885 
00886   set_builtin_table(FORMATTED_IO, "formatted_io");
00887   set_builtin_table(TABLE_STATUS, "table_status");
00888   set_builtin_table(GET_DELAY_LISTS, "get_delay_lists");
00889 
00890   set_builtin_table(ABOLISH_TABLE_PREDICATE, "abolish_table_pred");
00891   set_builtin_table(ABOLISH_TABLE_CALL, "abolish_table_call");
00892   set_builtin_table(TRIE_ASSERT, "trie_assert");
00893   set_builtin_table(TRIE_RETRACT, "trie_retract");
00894   set_builtin_table(TRIE_RETRACT_SAFE, "trie_retract_safe");
00895   set_builtin_table(TRIE_DELETE_RETURN, "trie_delete_return");
00896   set_builtin_table(TRIE_GET_RETURN, "trie_get_return");
00897   set_builtin_table(TRIE_ASSERT_HDR_INFO, "trie_assert_hdr_info");
00898 
00899 
00900   /* Note: TRIE_GET_CALL previously used for get_calls/1, before get_call/3
00901      was made a builtin itself. */
00902   set_builtin_table(TRIE_UNIFY_CALL, "get_calls");
00903   set_builtin_table(GET_LASTNODE_CS_RETSKEL, "get_lastnode_cs_retskel");
00904   set_builtin_table(TRIE_GET_CALL, "get_call");
00905   set_builtin_table(BREG_RETSKEL,"breg_retskel");
00906 
00907   set_builtin_table(TRIMCORE, "trimcore");
00908   set_builtin_table(NEWTRIE, "newtrie");
00909   set_builtin_table(TRIE_INTERN, "trie_intern");
00910   set_builtin_table(TRIE_INTERNED, "trie_interned");
00911   set_builtin_table(TRIE_DISPOSE, "trie_dispose");
00912   set_builtin_table(BOTTOM_UP_UNIFY, "bottom_up_unify");
00913   set_builtin_table(DELETE_TRIE, "delete_trie");
00914   set_builtin_table(TRIE_DISPOSE_NR, "trie_dispose_nr");
00915   set_builtin_table(TRIE_UNDISPOSE, "trie_undispose");
00916   set_builtin_table(RECLAIM_UNINTERNED_NR, "reclaim_uninterned_nr");
00917   set_builtin_table(GLOBALVAR, "globalvar");
00918 
00919   set_builtin_table(SET_TABLED_EVAL, "set_tabled_eval_method");
00920   set_builtin_table(UNIFY_WITH_OCCURS_CHECK, "unify_with_occurs_check");
00921 
00922   set_builtin_table(PUT_ATTRIBUTES, "put_attributes");
00923   set_builtin_table(GET_ATTRIBUTES, "get_attributes");
00924   set_builtin_table(DELETE_ATTRIBUTES, "delete_attributes");
00925   set_builtin_table(ATTV_UNIFY, "attv_unify");
00926   set_builtin_table(PRIVATE_BUILTIN, "private_builtin");
00927   set_builtin_table(SEGFAULT_HANDLER, "segfault_handler");
00928 
00929   set_builtin_table(FLOAT_OP, "float_op");
00930   set_builtin_table(IS_ATTV, "is_attv");
00931   set_builtin_table(VAR, "var");
00932   set_builtin_table(NONVAR, "nonvar");
00933   set_builtin_table(ATOM, "atom");
00934   set_builtin_table(INTEGER, "integer");
00935   set_builtin_table(REAL, "real");
00936   set_builtin_table(NUMBER, "number");
00937   set_builtin_table(ATOMIC, "atomic");
00938   set_builtin_table(COMPOUND, "compound");
00939   set_builtin_table(CALLABLE, "callable");
00940   set_builtin_table(IS_LIST, "is_list");
00941 
00942   set_builtin_table(FUNCTOR, "functor");
00943   set_builtin_table(ARG, "arg");
00944   set_builtin_table(UNIV, "univ");
00945   set_builtin_table(IS_MOST_GENERAL_TERM, "is_most_general_term");
00946   set_builtin_table(HiLog_ARG, "hilog_arg");
00947   set_builtin_table(HiLog_UNIV, "hilog_univ");
00948   set_builtin_table(ATOM_CODES, "atom_codes");
00949   set_builtin_table(ATOM_CHARS, "atom_chars");
00950   set_builtin_table(NUMBER_CHARS, "number_chars");
00951   set_builtin_table(NUMBER_CODES, "number_codes");
00952   set_builtin_table(IS_CHARLIST, "is_charlist");
00953   set_builtin_table(NUMBER_DIGITS, "number_digits");
00954 
00955   set_builtin_table(PUT, "put");
00956   set_builtin_table(TAB, "tab");
00957   set_builtin_table(SORT, "sort");
00958   set_builtin_table(KEYSORT, "keysort");
00959   set_builtin_table(PARSORT, "parsort");
00960 
00961   set_builtin_table(ORACLE_QUERY, "oracle_query");
00962   set_builtin_table(ODBC_EXEC_QUERY, "odbc_exec_query");
00963   set_builtin_table(SET_SCOPE_MARKER, "set_scope_marker");
00964   set_builtin_table(UNWIND_STACK, "unwind_stack");
00965   set_builtin_table(CLEAN_UP_BLOCK, "clean_up_block");
00966 
00967   set_builtin_table(THREAD_REQUEST, "thread_request");
00968   set_builtin_table(MT_RANDOM_REQUEST, "mt_random_request");
00969 
00970   set_builtin_table(XSB_POW, "xsb_pow");
00971 
00972   set_builtin_table(PRINT_LS, "print_ls");
00973   set_builtin_table(PRINT_TR, "print_tr");
00974   set_builtin_table(PRINT_HEAP, "print_heap");
00975   set_builtin_table(PRINT_CP, "print_cp");
00976   set_builtin_table(PRINT_REGS, "print_regs");
00977   set_builtin_table(PRINT_ALL_STACKS, "print_all_stacks");
00978   set_builtin_table(MARK_HEAP, "mark_heap");
00979   set_builtin_table(GC_STUFF, "gc_stuff");
00980   set_builtin_table(FINDALL_INIT, "$$findall_init");
00981   set_builtin_table(FINDALL_ADD, "$$findall_add");
00982   set_builtin_table(FINDALL_GET_SOLS, "$$findall_get_solutions");
00983 
00984 #ifdef HAVE_SOCKET
00985   set_builtin_table(SOCKET_REQUEST, "socket_request");
00986 #endif
00987 
00988   set_builtin_table(JAVA_INTERRUPT, "setupJavaInterrupt");
00989   set_builtin_table(FORCE_TRUTH_VALUE, "force_truth_value");
00990   set_builtin_table(INTERPROLOG_CALLBACK, "interprolog_callback");
00991 }
00992 
00993 /* -------------------------------------------------------------------- */
00994 
00995 #if defined(PROFILE) && !defined(MULTI_THREAD)
00996 static void write_out_profile(void)
00997 { 
00998   unsigned long i, isum, ssum, tot;
00999   double rat1, rat2;
01000 
01001   isum = ssum = tot = 0;
01002   for (i = 0; i < BUILTIN_TBL_SZ; i++) {
01003     if (inst_table[i][0] != 0) isum = isum + inst_table[i][5];
01004   }
01005   for (i = 0; i < BUILTIN_TBL_SZ; i++) {
01006     if (subinst_table[i][0] != 0) ssum = ssum + subinst_table[i][1];
01007   }
01008     tot = isum + ssum;
01009   if (tot!=0) {
01010     fprintf(stdout,
01011             "max subgoals %u max completed %u max consumers in ascc %u max compl_susps in ascc %u\n",
01012                   max_subgoals,max_completed,max_consumers_in_ascc,
01013                   max_compl_susps_in_ascc);
01014     rat1 = isum / tot;
01015     rat2 = ssum / tot;
01016     fprintf(stdout,
01017             "trapped Prolog choice point memory (%d bytes).\n",trapped_prolog_cps);
01018     fprintf(stdout,
01019             "summary(total(%d),inst(%d),pct(%f),subinst(%d),pct(%f)).\n",
01020             tot,isum,rat1,ssum,rat2);
01021     for (i = 0; i < BUILTIN_TBL_SZ; i++) {
01022       if (inst_table[i][5] != 0)
01023         fprintf(stdout,"instruction(%s,%x,%d,%.3f).\n",
01024                 (char *) inst_table[i][0],i,
01025                 inst_table[i][5],(((float)inst_table[i][5])/(float)tot));
01026     }
01027 /*      fprintf(stdout,"_______________subinsts_______________\n"); */
01028     for (i = 0; i < BUILTIN_TBL_SZ; i++) {
01029       if (subinst_table[i][0] != 0) {
01030         ssum = subinst_table[i][1];
01031         rat1 = ssum/tot;
01032         fprintf(stdout,"subinst(%s,%x,%d,%g).\n",
01033                 (char *) subinst_table[i][0],i,
01034                 subinst_table[i][1],rat1);
01035       }
01036     }
01037 /*      fprintf(stdout,"_______________builtins_______________\n"); */
01038     for (i = 0; i < BUILTIN_TBL_SZ; i++)
01039       if (builtin_table[i][1] > 0 && builtin_table[i][0] != 0)
01040         fprintf(stdout,"builtin(%s,%d,%d).\n",
01041                 BuiltinName(i), i, builtin_table[i][1]);
01042     fprintf(stdout,"switch_envs(%d).\n",
01043             num_switch_envs);
01044     fprintf(stdout,"switch_envs_iter(%d).\n",
01045             num_switch_envs_iter);
01046   }
01047   else 
01048     fprintf(stdout,"Instruction profiling not turned On\n");
01049 }
01050 #endif
01051 
01052 /*----------------------------------------------------------------------*/
01053 
01054 /* inlined definition of file_function */
01055 #include "io_builtins_xsb_i.h"
01056 
01057 /* inlined functions for prolog standard builtins */
01058 #include "std_pred_xsb_i.h"
01059 #include "call_xsb_i.h"
01060 
01061 /* --- built in predicates -------------------------------------------- */
01062 
01063 int builtin_call(CTXTdeclc byte number)
01064 {
01065   switch (number) {
01066   case PSC_NAME: {      /* R1: +PSC; R2: -String */
01067     Psc psc = (Psc)ptoc_addr(1);
01068     ctop_string(CTXTc 2, get_name(psc));
01069     break;
01070   }
01071   case PSC_ARITY: {     /* R1: +PSC; R2: -int */
01072     Psc psc = (Psc)ptoc_addr(1);
01073     ctop_int(CTXTc 2, (Integer)get_arity(psc));
01074     break;
01075   }
01076   case PSC_TYPE: {      /* R1: +PSC; R2: -int */
01077                         /* type: see psc_xsb.h, `entry_type' field defs */
01078     Psc psc = (Psc)ptoc_addr(1);
01079     ctop_int(CTXTc 2, (Integer)get_type(psc));
01080     break;
01081   }
01082   case PSC_SET_TYPE: {  /* R1: +PSC; R2: +type (int): see psc_xsb.h */
01083     Psc psc = (Psc)ptoc_addr(1);
01084     set_type(psc, ptoc_int(CTXTc 2));
01085     break;
01086   }
01087   case PSC_PROP: {      /* R1: +PSC; R2: -term */
01088                         /* prop: as a buffer pointer */
01089     Psc psc = (Psc)ptoc_addr(1);
01090     if ((get_type(psc) == T_PRED || get_type(psc) == T_DYNA) && get_env(psc) != T_IMPORTED) {
01091       char str[100];
01092       sprintf(str,"[psc_prop/2] Cannot get property of predicate: %s/%d\n",
01093               get_name(psc),get_arity(psc));
01094       xsb_warn(str);
01095       return FALSE;
01096     }
01097     ctop_int(CTXTc 2, (Integer)get_data(psc));
01098     break;
01099   }
01100   case PSC_SET_PROP: {         /* R1: +PSC; R2: +int */
01101     Psc psc = (Psc)ptoc_addr(1);
01102     if (get_type(psc) == T_PRED || get_type(psc) == T_DYNA) {
01103       xsb_warn("[psc_set_prop/2] Cannot set property of predicate.\n");
01104       return FALSE;
01105     }
01106     set_data(psc, (Psc)ptoc_int(CTXTc 2));
01107     break;
01108   }
01109 
01110   case CONGET_TERM: {
01111     Integer res = conget((Cell)ptoc_tag(CTXTc 1));
01112     prolog_term arg2 = reg_term(CTXTc 2);
01113     if (isref(arg2)) {
01114       c2p_int(CTXTc res,arg2);
01115       return TRUE;
01116     } else {
01117       return (int_val(arg2) == res);
01118     }
01119   }
01120   case CONSET_TERM: {
01121     return conset((Cell)ptoc_tag(CTXTc 1), (Integer)ptoc_int(CTXTc 2));
01122   }
01123   case PSC_EP: {        /* R1: +PSC; R2: -term */
01124                         /* prop: as a buffer pointer */
01125     Psc psc = (Psc)ptoc_addr(1);
01126     ctop_int(CTXTc 2, (Integer)get_ep(psc));
01127     break;
01128   }
01129   case PSC_SET_EP: {           /* R1: +PSC; R2: +int */
01130     Psc psc = (Psc)ptoc_addr(1);
01131     byte *ep = (pb)ptoc_int(CTXTc 2);
01132     if (ep == (byte *)NULL) set_ep(psc,(byte *)(&(psc->load_inst)));
01133     else if (ep == (byte *)4) set_ep(psc,(byte *)&fail_inst);
01134     break;
01135   }
01136 
01137   case PSC_SET_SPY: {          /* R1: +PSC; R2: +int */
01138     Psc psc = (Psc)ptoc_addr(1);
01139     set_spy(psc, ptoc_int(CTXTc 2));
01140     break;
01141   }
01142 
01143   case FILE_FUNCTION:  /* file_open/close/put/get/truncate/seek/pos */
01144   { int tmp ;
01145     //    SYS_MUTEX_LOCK( MUTEX_IO );
01146     tmp = file_function(CTXT);
01147     //    SYS_MUTEX_UNLOCK( MUTEX_IO );
01148     return tmp;
01149   }
01150  
01151   case TERM_PSC:                /* R1: +term; R2: -PSC */
01152     /* Assumes that `term' is a XSB_STRUCT-tagged Cell. */
01153     /*    ctop_addr(2, get_str_psc(ptoc_tag(CTXTc 1))); */
01154     ctop_addr(2, term_psc((Cell)(ptoc_tag(CTXTc 1))));
01155     break;
01156   case TERM_TYPE: {     /* R1: +term; R2: tag (-int)                      */
01157                         /* <0 - var, 1 - cs, 2 - int, 3 - list, 7 - ATTV> */
01158     Cell term = ptoc_tag(CTXTc 1);
01159     if (isref(term)) {
01160         ctop_int(CTXTc 2, XSB_FREE);
01161     }
01162     else {
01163         if (isboxedinteger(term)) {
01164             ctop_int(CTXTc 2, XSB_INT);
01165             break;
01166         }
01167         if (isboxedfloat(term)) {
01168             ctop_int(CTXTc 2, XSB_FLOAT);
01169             break;
01170         }
01171         ctop_int(CTXTc 2, cell_tag(term));
01172     }
01173     break;
01174   }
01175   case TERM_COMPARE:    /* R1, R2: +term; R3: res (-int) */
01176     ctop_int(CTXTc 3, compare(CTXTc (void *)ptoc_tag(CTXTc 1), (void *)ptoc_tag(CTXTc 2)));
01177     break;
01178   case TERM_NEW_MOD: {  /* R1: +ModName, R2: +Term, R3: -NewTerm */
01179     int new, disp;
01180     Psc termpsc, modpsc, newtermpsc;
01181     Cell arg, term = ptoc_tag(CTXTc 2);
01182     XSB_Deref(term);
01183     if (isref(term)) {
01184       err_handle(CTXTc INSTANTIATION, 2, BuiltinName(TERM_NEW_MOD), 3, "", term);
01185       break;
01186     }
01187     termpsc = term_psc(term);
01188     modpsc = pair_psc(insert_module(0,ptoc_string(CTXTc 1)));
01189     /*    if (!colon_psc) colon_psc = pair_psc(insert(":",2,global_mod,&new));*/
01190     while (termpsc == colon_psc) {
01191       term = cell(clref_val(term)+2);
01192       XSB_Deref(term);
01193       termpsc = term_psc(term);
01194     }
01195     newtermpsc = pair_psc(insert(get_name(termpsc),get_arity(termpsc),modpsc,&new));
01196     if (new) set_data(newtermpsc, modpsc);
01197     env_type_set(newtermpsc, T_IMPORTED, T_ORDI, (xsbBool)new);
01198     ctop_constr(CTXTc 3, (Pair)hreg);
01199     new_heap_functor(hreg, newtermpsc);
01200     for (disp=1; disp <= get_arity(newtermpsc); disp++) {
01201       arg = cell(clref_val(term)+disp);
01202       nbldval(arg);
01203     }
01204   }
01205   break;
01206   case TERM_NEW: {              /* R1: +PSC, R2: -term */
01207     int disp;
01208     Psc psc = (Psc)ptoc_addr(1);
01209     sreg = hreg;
01210     hreg += get_arity(psc) + 1;
01211     ctop_constr(CTXTc 2, (Pair)sreg);
01212     new_heap_functor(sreg, psc);
01213     for (disp=0; disp < (int)get_arity(psc); sreg++,disp++) {
01214       bld_free(sreg);
01215     }
01216     break;
01217   }
01218   case TERM_ARG: {      /* R1: +term; R2: index (+int); R3: arg (-term) */
01219     int  disp = ptoc_int(CTXTc 2);
01220     Cell term = ptoc_tag(CTXTc 1);
01221     ctop_tag(CTXTc 3, cell(clref_val(term)+disp));
01222     break;
01223   }
01224 
01225     /* TLS: it turns out that term_set_arg, and the perm. flag are
01226        still used in array.P. */
01227   case TERM_SET_ARG: {  /* R1: +term; R2: index (+int) */
01228                         /* R3: newarg (+term) */
01229     /* used in file_read.P, array.P, array1.P */
01230     int  disp = ptoc_int(CTXTc 2);
01231     Cell term = ptoc_tag(CTXTc 1);
01232     CPtr arg_loc = clref_val(term)+disp;
01233     Cell new_val = cell(reg+3);
01234     int perm_flag = ptoc_int(CTXTc 4);
01235     if (perm_flag == 0) {
01236       pushtrail(arg_loc,new_val);
01237     } else if (perm_flag < 0) {
01238       push_pre_image_trail(arg_loc,new_val);
01239     }
01240     bld_copy(arg_loc, new_val);
01241     break;
01242   }
01243   case STAT_FLAG: {     /* R1: flagname(+int); R2: value(-int) */
01244     int flagname = ptoc_int(CTXTc 1);
01245     int flagval;
01246     if (flagname < MAX_PRIVATE_FLAGS ) flagval = pflags[flagname];
01247     else flagval = flags[flagname];
01248     ctop_int(CTXTc 2, flagval);
01249     break;
01250   }
01251   case STAT_SET_FLAG: { /* R1: flagname(+int); R2: value(+int); */
01252     int flagval = ptoc_int(CTXTc 2);
01253     int flagname = ptoc_int(CTXTc 1);
01254     if (flagname < MAX_PRIVATE_FLAGS )
01255         pflags[flagname] = flagval;
01256     else flags[flagname] = flagval;
01257     if (flags[DEBUG_ON]||flags[TRACE_STA]||flags[HITRACE]||pflags[CLAUSE_INT])
01258       asynint_val |= MSGINT_MARK;
01259     else asynint_val &= ~MSGINT_MARK;
01260     break;
01261   }
01262   case BUFF_ALLOC: {    /* R1: size (+integer); R2: -buffer; */
01263                    /* the length of the buffer is also stored at position 0 */
01264     char *addr;
01265     int  value = ((ptoc_int(CTXTc 1)+7)>>3)<<3;
01266     value *= ZOOM_FACTOR ;
01267     addr = (char *)mem_alloc(value,BUFF_SPACE);
01268     value /= ZOOM_FACTOR ;
01269     *(Integer *)addr = value;   /* store buffer size at buf[0] */
01270     ctop_int(CTXTc 2, (Integer)addr);   /* use "integer" type now! */
01271     break;
01272   }
01273   case BUFF_DEALLOC: {  /* R1: +buffer; R2: +oldsize; R3: +newsize; */
01274     int  value;
01275     char *addr = (char *) ptoc_int(CTXTc 1);
01276     int  disp = ((ptoc_int(CTXTc 2)+7)>>3)<<3;
01277     disp *= ZOOM_FACTOR ;
01278     value = ((ptoc_int(CTXTc 3)+7)>>3)<<3;      /* alignment */
01279     value *= ZOOM_FACTOR ;
01280     if (value > disp) {
01281       xsb_warn("[BUFF_DEALLOC] New Buffer Size (%d) Cannot exceed the old one (%d)!!",
01282                value, disp);
01283       break;
01284     }
01285     mem_dealloc((byte *)(addr+value), disp-value,BUFF_SPACE);
01286     break;
01287   }
01288   case BUFF_WORD: {     /* R1: +buffer; r2: displacement(+integer); */
01289                         /* R3: value (-integer) */
01290     char *addr = (char *) ptoc_int(CTXTc 1);
01291     int  disp = ptoc_int(CTXTc 2);
01292     disp *= ZOOM_FACTOR ;
01293     ctop_int(CTXTc 3, *(Integer *)(addr+disp));
01294     break;
01295   }
01296   case BUFF_SET_WORD: { /* R1: +buffer; r2: displacement(+integer); */
01297                         /* R3: value (+integer) */
01298     char *addr = (char *) ptoc_int(CTXTc 1);
01299     int  disp = ptoc_int(CTXTc 2);
01300     disp *= ZOOM_FACTOR ;
01301     *(CPtr)(addr+disp) = ptoc_int(CTXTc 3);
01302     break;
01303   }
01304   case BUFF_BYTE: {     /* R1: +buffer; r2: displacement(+integer); */
01305                         /* R3: value (-integer) */
01306     char *addr = (char *) ptoc_int(CTXTc 1);
01307     int  disp = ptoc_int(CTXTc 2);
01308     ctop_int(CTXTc 3, (Integer)(*(byte *)(addr+disp)));
01309     break;
01310   }
01311   case BUFF_SET_BYTE: { /* R1: +buffer; R2: displacement(+integer); */
01312                         /* R3: value (+integer) */
01313     char *addr = (char *) ptoc_int(CTXTc 1);
01314     int  disp = ptoc_int(CTXTc 2);
01315     *(pb)(addr+disp) = ptoc_int(CTXTc 3);
01316     break;
01317   }
01318   case BUFF_CELL: {     /* R1: +buffer; R2: displacement(+integer); */
01319                         /* R3: -Cell at that location */
01320     char *addr = (char *) ptoc_int(CTXTc 1);
01321     int  disp = ptoc_int(CTXTc 2);
01322     disp *= ZOOM_FACTOR ;
01323     ctop_tag(CTXTc 3, (Cell)(addr+disp));
01324     break;
01325   }
01326   case BUFF_SET_CELL: { /* R1: +buffer; R2: displacement(+integer);*/
01327                         /* R3: type (+integer); R4: +term */
01328     /* When disp<0, set the type of the buff itself */
01329     /* The last function is not implemented */
01330     int  value;
01331     char *addr = (char *) ptoc_int(CTXTc 1);
01332     int  disp = ptoc_int(CTXTc 2);
01333     disp *= ZOOM_FACTOR ;
01334     value = ptoc_int(CTXTc 3);
01335     switch (value) {
01336     case XSB_REF:
01337     case XSB_REF1:
01338       bld_ref(vptr(addr+disp), (CPtr)ptoc_int(CTXTc 4)); break;
01339     case XSB_INT: {
01340       int tmpval = ptoc_int(CTXTc 4);
01341       bld_int(vptr(addr+disp), tmpval); break;
01342     }
01343     case XSB_FLOAT:
01344       bld_float(vptr(addr+disp),(float)ptoc_float(CTXTc 4)); break;
01345     case XSB_STRUCT: 
01346       bld_cs(vptr(addr+disp), (Pair)ptoc_int(CTXTc 4)); break;
01347     case XSB_STRING:
01348       bld_string(vptr(addr+disp), (char *)ptoc_int(CTXTc 4)); break;
01349     case XSB_LIST:
01350       bld_list(vptr(addr+disp), (CPtr)ptoc_int(CTXTc 4)); break;
01351     default:
01352       xsb_warn("[BUFF_SET_CELL] Type %d is not implemented", value);
01353     }
01354     break;
01355   }
01356   case BUFF_SET_VAR: {
01357     int  disp;
01358     Cell term;
01359     char *addr;
01360     /* This procedure is used to make an external variable pointing to the
01361        buffer. The linkage inside the buffer will not be trailed so remains
01362        after backtracking. */
01363     /* R1: +buffer; R2: +disp; */
01364     /* R3: +buffer length; R4: External var */
01365     addr = (char *) ptoc_int(CTXTc 1);
01366     disp = ptoc_int(CTXTc 2);
01367     disp *= ZOOM_FACTOR;
01368     term = ptoc_tag(CTXTc 4);
01369     bld_free(vptr(addr+disp));
01370     if ((Cell)term < (Cell)addr || 
01371         (Cell)term > (Cell)addr+ptoc_int(CTXTc 3)) { /* var not in buffer, trail */
01372       bind_ref(vptr(term), (CPtr)(addr+disp));
01373     } else {            /* already in buffer */
01374       bld_ref(vptr(term), (CPtr)(addr+disp));   
01375     }
01376     break;
01377   }
01378   case COPY_TERM: /* R1: +term to copy; R2: -variant */
01379     return copy_term(CTXT);
01380     
01381   case CALL0: {                 /* R1: +Term, the call to be made */
01382     /* Note: this procedure does not save cpreg, hence is more like */
01383     /* an "execute" instruction, and must be used as the last goal!!!*/
01384     Cell term = ptoc_tag(CTXTc 1);
01385     /* in call_xsb_i.h */
01386     return prolog_call0(CTXTc term);
01387   }
01388 
01389   case CODE_CALL: {             /* R1: +Code (addr), the code address */
01390                                 /* R2: +Term, the call to be made */
01391                                 /* R3: +Type, code type (same as psc->type)  */
01392                                 /* may need to resume interrupt testing here */
01393     /* Note: this procedure does not save cpreg, hence is more like */
01394     /* an "execute" instruction, and must be used as the last goal!!!*/
01395     Cell term = ptoc_tag(CTXTc 2);
01396     int  value = ptoc_int(CTXTc 3);  /* Cannot be delayed! R3 may be reused */
01397     pcreg = (byte *)ptoc_int(CTXTc 1);
01398 
01399     /* in call_xsb_i.h */
01400     return prolog_code_call(CTXTc term,value);
01401   }
01402   case SUBSTRING: /* R1: +String; R2,R3: +begin/end offset; R4: -OutSubstr */
01403     return substring(CTXT); 
01404   case STRING_SUBSTITUTE: /* R1: +Str, R2: [s(a1,b1),s(a2,b2),...], 
01405                              R3: [str1,str2,...], R4: -OutStr */
01406     return string_substitute(CTXT);
01407   case STR_LEN: {       /* R1: +String; R2: -Length */
01408     Cell term = ptoc_tag(CTXTc 1);
01409     Cell num = ptoc_tag(CTXTc 2);
01410     if (isstring(term)) {
01411       char *addr = string_val(term);
01412       if (isref(num) || (isinteger(num) && int_val(num) >= 0))
01413         return int_unify(CTXTc makeint(strlen(addr)), num);
01414       else if (!isinteger(num)) xsb_type_error(CTXTc "integer",num,"atom_length",2,2);
01415       else xsb_domain_error(CTXTc "not_less_than_zero",num,"atom_length",2,2);
01416     } else if (isref(term)) xsb_instantiation_error(CTXTc "atom_length",2,1,NULL);
01417       else xsb_type_error(CTXTc "atom",term,"atom_length",2,1);
01418     return FALSE;
01419   }
01420   case STR_CAT:         /* R1: +Str1; R2: +Str2: R3: -Str3 */
01421     return str_cat(CTXT);
01422   case STR_CMP:         /* R1: +Str1; R2: +Str2: R3: -Res */
01423     ctop_int(CTXTc 3, strcmp(ptoc_string(CTXTc 1), ptoc_string(CTXTc 2)));
01424     break;
01425   case STR_MATCH:
01426     return str_match(CTXT);
01427   case INTERN_STRING: /* R1: +String1; R2: -String2 ; Intern string */
01428     ctop_string(CTXTc 2, string_find(ptoc_string(CTXTc 1), 1));
01429     break;
01430   case STAT_STA: {              /* R1: +Amount */
01431     int value = ptoc_int(CTXTc 1);
01432     print_statistics(CTXTc value);
01433     break;
01434   }
01435   case STAT_CPUTIME: {  /* R1: -cputime, in miliseconds */      
01436     int value = (int)(cpu_time() * 1000);
01437     ctop_int(CTXTc 1, value);
01438     break;
01439   }
01440   case GET_DATE: {
01441     int year=0, month=0, day=0, hour=0, minute=0, second=0;
01442     get_date(&year,&month,&day,&hour,&minute,&second);
01443     ctop_int(CTXTc 1,year);
01444     ctop_int(CTXTc 2,month);
01445     ctop_int(CTXTc 3,day);
01446     ctop_int(CTXTc 4,hour);
01447     ctop_int(CTXTc 5,minute);
01448     ctop_int(CTXTc 6,second);
01449     break;
01450   }
01451   case STAT_WALLTIME: {
01452     int value;
01453     value = (int) ((real_time() - realtime_count_gl) * 1000);
01454     ctop_int(CTXTc 1, value);
01455     break;
01456   }
01457   case XWAM_STATE: { /* return info about xwam state: R1: +InfoCode, R2: -ReturnedValue */
01458     switch (ptoc_int(CTXTc 1)) { /* extend as needed */
01459     case 0: /* current trail size */
01460       ctop_int(CTXTc 2, (pb)trreg-(pb)tcpstack.low);
01461       break;
01462     case 1: /* current CP Stack size */
01463       ctop_int(CTXTc 2, (pb)tcpstack.high - (pb)breg);
01464       break;
01465     case 2: /* value of delayreg */
01466       ctop_int(CTXTc 2, (Integer)delayreg);
01467       break;
01468     default: xsb_error("Undefined component of XWAM_STATE");
01469     }
01470     break;
01471   }
01472   case CODE_LOAD:               /* R1: +FileName, bytecode file to be loaded */
01473                                 /* R2: -int, addr of 1st instruction;        */
01474                                 /*      0 indicates an error                 */
01475                                 /* R3 = 1 if exports to be exported, 0 otw   */
01476     ctop_int(CTXTc 2, (Integer)loader(CTXTc ptoc_string(CTXTc 1), ptoc_int(CTXTc 3)));
01477     break;
01478 
01479   case PSC_INSERT: {    /* R1: +String, symbol name
01480                            R2: +Arity
01481                            R3: -PSC, the new PSC
01482                            R4: +String, module to be inserted */
01483     /* inserts or finds a symbol in a given module.     */
01484     /* When the given module is 0 (null string), current module is used. */
01485     Psc  psc;
01486     Pair sym;
01487     int  value;
01488     char *addr = ptoc_string(CTXTc 4);
01489     if (addr)
01490       psc = pair_psc(insert_module(0, addr));
01491     else
01492       psc = (Psc)flags[CURRENT_MODULE];
01493     sym = insert(ptoc_string(CTXTc 1), (char)ptoc_int(CTXTc 2), psc, &value);
01494     ctop_addr(3, pair_psc(sym));
01495     break;
01496   }
01497 
01498   case PSC_IMPORT: {    /* R1: +String, functor name to be imported
01499                            R2: +Arity
01500                            R3: +String, Module name where functor lives  */
01501     /*
01502      * Creates a PSC record for a predicate and its module (if they
01503      * don't already exist) and links the predicate into usermod.
01504      */
01505     int  value;
01506     Psc  psc = pair_psc(insert_module(0, ptoc_string(CTXTc 3)));
01507     Pair sym = insert(ptoc_string(CTXTc 1), (char)ptoc_int(CTXTc 2), psc, &value);
01508     if (value)       /* if predicate is new */
01509       set_data(pair_psc(sym), (psc));
01510     env_type_set(pair_psc(sym), T_IMPORTED, T_ORDI, (xsbBool)value);
01511     link_sym(pair_psc(sym), (Psc)flags[CURRENT_MODULE]);
01512     break;
01513   }
01514 
01515   case PSC_DATA:  {     /* R1: +PSC; R2: -int */
01516     Psc psc = (Psc)ptoc_addr(1);
01517     ctop_int(CTXTc 2, (Integer)get_data(psc));
01518     break;
01519   }
01520 
01521     /* TLS: No MUTEX in FILE_GETTOKEN.  Its assumed that this is
01522        called from some other predicate with a stream lock, such as
01523        file_read. */
01524 
01525   case FILE_GETTOKEN: {    /* R1: +File, R2: +PrevCh, R3: -Type; */
01526                                 /* R4: -Value, R5: -NextCh */
01527 
01528     int tmpval = ptoc_int(CTXTc 1);
01529     if ((tmpval < 0) && (tmpval >= -MAXIOSTRS))
01530       token = GetToken(CTXTc NULL,strfileptr(tmpval), ptoc_int(CTXTc 2));
01531     else {
01532       FILE* fptr;
01533       SET_FILEPTR(fptr, tmpval);
01534       token = GetToken(CTXTc fptr, NULL, ptoc_int(CTXTc 2));
01535     }
01536     if (token->type == TK_ERROR) {
01537       //      pcreg = (pb)&fail_inst;
01538       return FALSE;
01539     }
01540     else {
01541       ctop_int(CTXTc 3, token->type);
01542       ctop_int(CTXTc 5, token->nextch);
01543       switch (token->type) {
01544         case TK_ATOM : case TK_FUNC : case TK_STR : case TK_LIST :
01545         case TK_VAR : case TK_VVAR : case TK_VARFUNC : case TK_VVARFUNC :
01546           ctop_string(CTXTc 4, string_find(token->value,1));  // NOW INTERNED, CALLER MUST DO SO SOON!!
01547           break;
01548         case TK_INT : case TK_INTFUNC :
01549           ctop_int(CTXTc 4, *(long *)(token->value));
01550           break;
01551         case TK_REAL : case TK_REALFUNC : 
01552           ctop_float(CTXTc 4, *(double *)(token->value));
01553           break;
01554         case TK_PUNC : case TK_HPUNC :
01555           ctop_int(CTXTc 4, *(token->value)); break;
01556         case TK_EOC : case TK_EOF :
01557           ctop_int(CTXTc 4, 0); break;
01558       }
01559     }
01560     break;
01561   }
01562     /* TLS: No MUTEX in FILE_PUTTOKEN.  Its assumed that this is
01563        called from some other predicate with a stream lock, such as
01564        file_write. */
01565 
01566   case FILE_PUTTOKEN: { /* R1: +File, R2: +Type, R3: +Value; */
01567     FILE* fptr;
01568     int tmpval = ptoc_int(CTXTc 1);
01569     //    SYS_MUTEX_LOCK(MUTEX_IO);
01570     SET_FILEPTR(fptr,tmpval);
01571     switch (ptoc_int(CTXTc 2)) {
01572     case XSB_FREE   : {
01573       CPtr var = (CPtr)ptoc_tag(CTXTc 3);
01574       xsb_fprint_variable(CTXTc fptr, var);
01575       break;
01576     }
01577     case XSB_ATTV   : {
01578       CPtr var = (CPtr)dec_addr(ptoc_tag(CTXTc 3));
01579       xsb_fprint_variable(CTXTc fptr, var);
01580       break;
01581     }
01582     case XSB_INT    : fprintf(fptr, "%ld", (long)ptoc_int(CTXTc 3)); break;
01583     case XSB_STRING : fprintf(fptr, "%s", ptoc_string(CTXTc 3)); break;
01584     case XSB_FLOAT  : fprintf(fptr, "%2.4lf", ptoc_float(CTXTc 3)); break;
01585     case TK_INT_0  : {
01586       int tmp = (int) ptoc_int(CTXTc 3);
01587       fix_bb4((byte *)&tmp);
01588       fwrite(&tmp, 4, 1, fptr); break;
01589     }
01590     case TK_FLOAT_0: {
01591       //printf("TK_FLOAT_0 case in put token entered\n");
01592       float ftmp = (float)ptoc_float(CTXTc 3);
01593       fix_bb4((byte *)&ftmp);
01594       fwrite(&ftmp, 4, 1, fptr); 
01595       //printf("TK_FLOAT_0 case in put token left\n"); 
01596       break;
01597     }
01598     case TK_PREOP  : print_op(fptr, ptoc_string(CTXTc 3), 1); break;
01599     case TK_INOP   : print_op(fptr, ptoc_string(CTXTc 3), 2); break;
01600     case TK_POSTOP : print_op(fptr, ptoc_string(CTXTc 3), 3); break;
01601     case TK_QATOM  : print_qatom(fptr, ptoc_string(CTXTc 3)); break;
01602     case TK_AQATOM : print_aqatom(fptr, ptoc_string(CTXTc 3)); break;
01603     case TK_QSTR   : print_dqatom(fptr, ptoc_string(CTXTc 3)); break;
01604     case TK_TERML  : print_term_canonical(CTXTc fptr, ptoc_tag(CTXTc 3), 1); break;
01605     case TK_TERM   : print_term_canonical(CTXTc fptr, ptoc_tag(CTXTc 3), 0); break;
01606     default : printf("flg: %ld\n",(long)ptoc_int(CTXTc 2));
01607       xsb_abort("[FILE_PUTTOKEN] Unknown token type %d");
01608     }
01609     //    SYS_MUTEX_UNLOCK(MUTEX_IO);
01610     break;
01611   }
01612   case PSC_INSERTMOD: { /* R1: +String, Module name */
01613                         /* R2: +Def (4 - is a definition; 0 -not) */
01614                         /* R3: -PSC of the Module entry */
01615     Pair sym = insert_module(ptoc_int(CTXTc 2), ptoc_string(CTXTc 1));
01616     ctop_addr(3, pair_psc(sym));
01617     break;
01618   }
01619   case TERM_HASH:               /* R1: +Term    */
01620                                 /* R2: +Size (of hash table) */
01621                                 /* R3: -HashVal */
01622     ctop_int(CTXTc 3, ihash(det_val_to_hash(ptoc_tag(CTXTc 1)),ptoc_int(CTXTc 2)));
01623     break;
01624   case UNLOAD_SEG:      /* R1: -Code buffer */
01625     unload_seg((pseg)ptoc_int(CTXTc 1));
01626     break;
01627   case LOAD_OBJ:                /* R1: +FileName, R2: +Module (Psc) */
01628                                 /* R3: +ld option, R4: -InitAddr */
01629 #ifdef FOREIGN
01630     ctop_int(CTXTc 4, (Integer)load_obj(ptoc_string(CTXTc 1),(Psc)ptoc_addr(2),
01631                                   ptoc_string(CTXTc 3)));
01632 #else
01633     xsb_abort("Loading foreign object files is not implemented for this configuration");
01634 #endif
01635     break;
01636 
01637   case WH_RANDOM:               /* R1: +Type of operation */
01638     switch (ptoc_int(CTXTc 1)) {
01639     case RET_RANDOM:            /* return a random float in [0.0, 1.0) */
01640       return ret_random(CTXT);
01641       break;
01642     case GET_RAND:              /* getrand */
01643       return getrand(CTXT);
01644       break;
01645     case SET_RAND:              /* setrand */
01646       setrand(CTXT);
01647       break;
01648     }
01649     break;
01650 
01651   case EXPAND_FILENAME:        /* R1: +FileName, R2: -ExpandedFileName */
01652     {char *filename = expand_filename(ptoc_longstring(CTXTc 1));
01653     ctop_string(CTXTc 2, string_find(filename,1));
01654     mem_dealloc(filename,MAXPATHLEN,OTHER_SPACE);
01655     }
01656     break;
01657   case TILDE_EXPAND_FILENAME:  /* R1: +FileN, R2: -TildeExpanded FN */
01658     ctop_string(CTXTc 2, tilde_expand_filename(ptoc_longstring(CTXTc 1)));
01659     break;
01660   case IS_ABSOLUTE_FILENAME: /* R1: +FN. Ret 1 if name is absolute, 0 else */
01661     return is_absolute_filename(ptoc_longstring(CTXTc 1));
01662  case PARSE_FILENAME: {    /* R1: +FN, R2: -Dir, R3: -Basename, R4: -Ext */
01663     char *dir, *basename, *extension;
01664     parse_filename(ptoc_longstring(CTXTc 1), &dir, &basename, &extension);
01665     ctop_string(CTXTc 2, dir);
01666     ctop_string(CTXTc 3, basename);
01667     ctop_string(CTXTc 4, extension);
01668     break;
01669   }
01670   case ALMOST_SEARCH_MODULE: /* R1: +FileName, R2: -Dir, R3: -Mod,
01671                                 R4: -Ext, R5: -BaseName */
01672     return almost_search_module(CTXTc ptoc_longstring(CTXTc 1));
01673   case EXISTING_FILE_EXTENSION: { /* R1: +FileN, R2: ?Ext */
01674     char *extension = existing_file_extension(ptoc_longstring(CTXTc 1));
01675     if (extension == NULL) return FALSE;
01676     else {
01677       extension = string_find(extension,1);
01678       return atom_unify(CTXTc makestring(extension), ptoc_tag(CTXTc 2));
01679     }
01680   }
01681 
01682   case DO_ONCE: { /* R1: +Breg */
01683 #ifdef DEMAND
01684     perform_once();
01685 #else
01686     xsb_abort("This executable was not compiled with support for demand.\n");
01687 #endif
01688     break;
01689   }
01690   case GETENV:  {       /* R1: +environment variable */
01691                         /* R2: -value of that environment variable */
01692     char *env = getenv(ptoc_longstring(CTXTc 1));
01693     if (env == NULL)
01694       /* otherwise, string_find dumps core */
01695       return FALSE;
01696     else
01697       ctop_string(CTXTc 2, string_find(env,1));
01698     break;
01699   }
01700   case SYS_SYSCALL:     /* R1: +int (call #, see <syscall.h> */
01701                                 /* R2: -int, returned value */
01702                                 /* R3, ...: Arguments */
01703     ctop_int(CTXTc 2, sys_syscall(CTXTc ptoc_int(CTXTc 1)));
01704     break;
01705   case SYS_SYSTEM:      /* R1: call mubler, R2: +String (of command);
01706                            R3: -Int (res), or mode: read/write;
01707                            R4: undefined or Stream used for output/input
01708                            from/to the shell command. */
01709     {
01710       xsbBool sys_system_return;
01711       SYS_MUTEX_LOCK( MUTEX_SYS_SYSTEM );
01712       sys_system_return = sys_system(CTXTc ptoc_int(CTXTc 1));
01713       SYS_MUTEX_UNLOCK( MUTEX_SYS_SYSTEM );
01714       return sys_system_return;
01715     }
01716   case SYS_GETHOST: {
01717     /* +R1: a string indicating the host name  */
01718     /* +R2: a buffer (of length 16) for returned structure */
01719 #ifdef HAVE_GETHOSTBYNAME
01720     static struct hostent *hostptr;
01721     hostptr = gethostbyname(ptoc_longstring(CTXTc 1));
01722 #ifdef DARWIN   /* OS X returns an array of hostnames in h_addr_list */
01723     memmove(ptoc_longstring(CTXTc 2), hostptr->h_addr_list[0], hostptr->h_length);
01724 #else
01725     memmove(ptoc_longstring(CTXTc 2), hostptr->h_addr, hostptr->h_length);
01726 #endif
01727 #else
01728     xsb_abort("[SYS_GETHOST] Operation not available for this configuration");
01729 #endif
01730     break;
01731   }
01732   case SYS_ERRNO:                       /* R1: -Int (errno) */
01733     ctop_int(CTXTc 1, errno);
01734     break;
01735   case FILE_WRITEQUOTED: {
01736     FILE* fptr;
01737     int   tmpval = ptoc_int(CTXTc 1);
01738     SET_FILEPTR(fptr, tmpval);
01739     write_quotedname(fptr ,ptoc_string(CTXTc 2));
01740     break;
01741   }
01742   case GROUND:
01743     return ground(CTXTc (CPtr)ptoc_tag(CTXTc 1));
01744 
01745   case PSC_GET_SET_ENV_BYTE: { /* reg 1: +PSC, reg 2: +And-bits, reg 3: +Or-bits, reg 4: -Result */
01746     Psc psc = (Psc)ptoc_addr(1);
01747     psc->env = (psc->env & (byte)ptoc_int(CTXTc 2)) | (byte)ptoc_int(CTXTc 3);
01748     ctop_int(CTXTc 4, (Integer)(psc->env));
01749     break;
01750   }
01751 
01752   case PSC_ENV: {       /* reg 1: +PSC; reg 2: -int */
01753     /* env: 0 = exported, 1 = local, 2 = imported */
01754     Psc psc = (Psc)ptoc_addr(1);
01755     ctop_int(CTXTc 2, (Integer)get_env(psc));
01756     break;
01757   }
01758   case PSC_SPY: {       /* reg 1: +PSC; reg 2: -int */
01759                                 /* env: 0 = non-spied else spied */
01760     Psc psc = (Psc)ptoc_addr(1);
01761     ctop_int(CTXTc 2, (Integer)get_spy(psc));
01762     break;
01763   }
01764   case PSC_TABLED: {    /* reg 1: +PSC; reg 2: -int */
01765     Psc psc = (Psc)ptoc_addr(1);
01766     ctop_int(CTXTc 2, (get_tabled(psc)?TRUE:FALSE));  //(Integer)get_tip(CTXTc psc));
01767     break;
01768   }
01769   case PSC_SET_TABLED: {        /* reg 1: +PSC; reg 2: +int */
01770     Psc psc = (Psc)ptoc_addr(1);
01771     if (ptoc_int(CTXTc 2)) set_tabled(psc,0x08);
01772     else psc->env = psc->env & ~0x8; /* turn off */
01773     break;
01774   }
01775     //  case PSC_ENV: { /* reg 1: +PSC; reg 2: +int-anded; reg 3: +int-orred; reg 4: -Result*/
01776     //    Psc psc = (Psc)ptoc_addr(1);
01777     //    psc->env = ((psc->env & ptoc_int(CTXTc 2)) | ptoc_int(CTXTc 3));
01778     //    ctop_int(CTXTc 4, psc->env);
01779     //    break;
01780     //  }
01781 
01782 
01783 
01784 /*----------------------------------------------------------------------*/
01785 
01786 #include "bineg_xsb_i.h"
01787 
01788 /*----------------------------------------------------------------------*/
01789 
01790   case GET_PRODUCER_CALL: {
01791     const int Arity = 3;
01792     const int regCallTerm = 1;  /* in: tabled subgoal */
01793     const int regSF       = 2;  /* out: subgoal frame of producer from
01794                                         which subgoal can consume */
01795     const int regRetTerm  = 3;  /* out: answer template in ret/N form */
01796 
01797     Cell term;
01798     Psc  psc;
01799     TIFptr tif;
01800     void *sf;
01801     Cell retTerm;
01802 
01803     term = ptoc_tag(CTXTc regCallTerm);
01804     if ( isref(term) ) {
01805       err_handle(CTXTc INSTANTIATION, regCallTerm,
01806                  BuiltinName(GET_PRODUCER_CALL), Arity, "", term);
01807       break;
01808     }
01809     psc = term_psc(term);
01810     if ( IsNULL(psc) ) {
01811       err_handle(CTXTc TYPE, regCallTerm,
01812                  BuiltinName(GET_PRODUCER_CALL), Arity,
01813                  "Callable term", term);
01814       break;
01815     }
01816     tif = get_tip(CTXTc psc);
01817     if ( IsNULL(tif) )
01818       xsb_abort("Illegal table operation\n\t Untabled predicate (%s/%d)"
01819                 "\n\t In argument %d of %s/%d",
01820                 get_name(psc), get_arity(psc), regCallTerm,
01821                 BuiltinName(GET_PRODUCER_CALL), Arity);
01822 
01823     if ( IsSubsumptivePredicate(tif) )
01824       sf = get_subsumer_sf(CTXTc term, tif, &retTerm);
01825     else
01826       sf = get_variant_sf(CTXTc term, tif, &retTerm);
01827     if ( IsNULL(sf) )
01828       return FALSE;
01829     ctop_addr(regSF, sf);
01830     ctop_tag(CTXTc regRetTerm, retTerm);
01831     break;
01832   }
01833 
01834   case DEREFERENCE_THE_BUCKET:
01835     /*
01836      * Given an index into the symbol table, return the first Pair
01837      * in that bucket's chain.
01838      */
01839     ctop_int(CTXTc 2, (Integer)(symbol_table.table[ptoc_int(CTXTc 1)]));
01840     break;
01841   case PAIR_PSC:
01842     ctop_addr(2, pair_psc((Pair)ptoc_addr(1)));
01843     break;
01844   case PAIR_NEXT:
01845     ctop_addr(2, pair_next((Pair)ptoc_addr(1)));
01846     break;
01847   case NEXT_BUCKET: {     /* R1: +Index of Symbol Table Bucket. */
01848     /* R2: -Next Index (0 if end of Hash Table) */
01849     int value = ptoc_int(CTXTc 1);
01850     if ( ((unsigned int)value >= (symbol_table.size - 1)) || (value < 0) )
01851       ctop_int(CTXTc 2, 0);
01852     else 
01853       ctop_int(CTXTc 2, (value + 1));
01854     break;
01855   }
01856 
01857   case IS_XWAMMODE:     /* R1: -int flag for xwammode */  
01858 
01859     if (xwammode) ctop_int(CTXTc 1,1);
01860     else ctop_int(CTXTc 1,0);
01861     break;
01862 
01863   case CLOSE_OPEN_TABLES:       /* No registers needed */
01864     remove_incomplete_tables_reset_freezes(CTXT);
01865 #ifdef MULTI_THREAD
01866     release_held_mutexes(CTXT);
01867 #endif
01868     break;
01869 
01870     /* Abolish_all_tables */
01871   case ABOLISH_TABLE_INFO:
01872     abolish_table_info(CTXT);
01873     break;
01874 
01875   case ZERO_OUT_PROFILE:
01876 #if defined(PROFILE) && !defined(MULTI_THREAD)
01877     { 
01878       int i;
01879       for (i = 0 ; i <= BUILTIN_TBL_SZ ; i++) {
01880         inst_table[i][5] = 0;
01881         builtin_table[i][1] = 0;
01882         subinst_table[i][1] = 0;
01883       }
01884       num_switch_envs=0;
01885     }
01886     break;
01887 #else
01888     xsb_abort("Profiling is not enabled for this configuration");  
01889 #endif
01890 case WRITE_OUT_PROFILE:
01891 #if defined(PROFILE) && !defined(MULTI_THREAD)
01892     write_out_profile();
01893     break;
01894 #else
01895     xsb_abort("Profiling is not enabled for this configuration");  
01896 #endif
01897   case ASSERT_CODE_TO_BUFF:
01898     assert_code_to_buff(CTXT);
01899     break;
01900   case ASSERT_BUFF_TO_CLREF:
01901     assert_buff_to_clref(CTXT);
01902     break;
01903   case DIRNAME_CANONIC: /* R1: +Dirname, R2: -Canonicized Dirname:
01904                            If file is a directory, add trailing slash and
01905                            rectify filename (delete multiple slashes, '..' and
01906                            '.'. */
01907     ctop_string(CTXTc 2, dirname_canonic(ptoc_longstring(CTXTc 1)));
01908     break;
01909   case SLASH_BUILTIN: {  /* R1: -Slash. Tells what kind of slash the OS uses */
01910     static char slash_string[2];
01911     slash_string[0] = SLASH;
01912     slash_string[1] = '\0';
01913     ctop_string(CTXTc 1, string_find(slash_string, 1));
01914     break;
01915   }
01916   case FORMATTED_IO:
01917     return formatted_io(CTXT);
01918   case FILE_READ_CANONICAL:
01919     return read_canonical(CTXT);
01920 
01921   case GEN_RETRACT_ALL:
01922     return gen_retract_all(CTXT);
01923   case DB_GET_LAST_CLAUSE:
01924     return db_get_last_clause(CTXT);
01925     break;
01926   case DB_RETRACT0:
01927     db_retract0(CTXT);
01928     break;
01929   case DB_GET_CLAUSE:
01930     db_get_clause(CTXT);
01931     break;
01932   case DB_BUILD_PRREF:
01933     db_build_prref(CTXT);
01934     break;
01935   case DB_GET_PRREF:
01936     db_get_prref(CTXT);
01937     break;
01938   case DB_ABOLISH0:
01939     db_abolish0(CTXT);
01940     break;
01941   case DB_RECLAIM0:
01942     db_reclaim0(CTXT);
01943     break;
01944 
01945 /*----------------------------------------------------------------------*/
01946 
01947 #include "std_cases_xsb_i.h"
01948     
01949 #ifdef ORACLE
01950 #include "oracle_xsb_i.h"
01951 #endif
01952     
01953 #ifdef XSB_ODBC
01954 #include "odbc_xsb_i.h"
01955 #else
01956   case ODBC_EXEC_QUERY: {
01957     xsb_abort("[ODBC] XSB not compiled with ODBC support.\nRecompile using the option --with-odbc.\n");
01958   }
01959 #endif
01960 
01961 #ifdef XSB_INTERPROLOG
01962 #include "interprolog_xsb_i.h"
01963 #endif
01964     
01965 /*----------------------------------------------------------------------*/
01966     
01967   case TABLE_STATUS: {
01968     /*
01969      * Given a tabled goal, report on the following attributes:
01970      * 1) Predicate Type: Variant, Subsumptive, or Untabled
01971      * 2) Goal Type: Producer, Properly Subsumed Consumer, Has No
01972      *      Call Table Entry, or Undefined
01973      * 3) Answer Set Status: Complete, Incomplete, or Undefined.
01974      *
01975      * Valid combinations reported by this routine:
01976      * When the predicate is an untabled functor, then only one sequence
01977      *   is generated:  Untabled,Undefined,Undefined
01978      * Otherwise the following combinations are possible:
01979      *
01980      * GoalType    AnsSetStatus   Meaning
01981      * --------    ------------   -------
01982      * producer    complete       call exists; it is a completed producer.
01983      *             incomplete     call exists; it is an incomplete producer.
01984      *
01985      * subsumed    complete       call exists; it's properly subsumed by a
01986      *                              completed producer.
01987      *             incomplete     call exists; it's properly subsumed by an
01988      *                              incomplete producer.
01989      *
01990      * no_entry    undefined      is a completely new call, not subsumed by
01991      *                              any other -> if this were to be called
01992      *                              right now, it would be a producing call.
01993      *             complete       there is no entry for this call, but if it
01994      *                              were to be called right now, it would
01995      *                              consume from a completed producer.
01996      *                              (The call is properly subsumed.)
01997      *             incomplete     same as previous, except the subsuming
01998      *                              producer is incomplete.
01999      *
02000      * Notice that not only can these combinations describe the
02001      * characteristics of a subgoal in the table, but they are also
02002      * equipped to predict how a new goal would have been treated had it
02003      * really been called.
02004      */
02005     const int Arity = 4;
02006     const int regGoalHandle   = 1;   /* in:  either a term or a SF ptr */
02007     const int regPredType     = 2;   /* out: status (as INT) */
02008     const int regGoalType     = 3;   /* out: status (as INT) */
02009     const int regAnsSetStatus = 4;   /* out: status (as INT) */
02010 
02011     int pred_type, goal_type, answer_set_status;
02012     VariantSF goalSF, subsumerSF;
02013     Cell goalTerm;
02014 
02015     goalTerm = ptoc_tag(CTXTc regGoalHandle);
02016     if ( isref(goalTerm) ) {
02017       err_handle(CTXTc INSTANTIATION, regGoalHandle, BuiltinName(TABLE_STATUS),
02018                  Arity, "", goalTerm);
02019       break;
02020     }
02021     if ( is_encoded_addr(goalTerm) ) {
02022       goalSF = (VariantSF)decode_addr(goalTerm);
02023 #ifdef DEBUG_ASSERTIONS
02024   /* Need to change for MT: smVarSF can be private or shared
02025 |      if ( ! smIsValidStructRef(smVarSF,goalSF) &&
02026 |          ! smIsValidStructRef(smProdSF,goalSF) &&
02027 |          ! smIsValidStructRef(smConsSF,goalSF) )
02028 |       xsb_abort("Invalid Table Entry Handle\n\t Argument %d of %s/%d",
02029 |                 regGoalHandle, BuiltinName(TABLE_STATUS), Arity);
02030   */
02031 #endif
02032       if ( IsProperlySubsumed(goalSF) )
02033         subsumerSF = (VariantSF)conssf_producer(goalSF);
02034       else
02035         subsumerSF = goalSF;
02036       pred_type = TIF_EvalMethod(subg_tif_ptr(subsumerSF));
02037     }
02038     else {
02039       Psc psc;
02040       TIFptr tif;
02041 
02042       psc = term_psc(goalTerm);
02043       if ( IsNULL(psc) ) {
02044         err_handle(CTXTc TYPE, regGoalHandle, BuiltinName(TABLE_STATUS),
02045                    4, "Callable term", goalTerm);
02046         break;
02047       }
02048       tif = get_tip(CTXTc psc);
02049       if ( IsNULL(tif) ) {
02050         ctop_int(CTXTc regPredType, UNTABLED_PREDICATE);
02051         ctop_int(CTXTc regGoalType, UNDEFINED_CALL);
02052         ctop_int(CTXTc regAnsSetStatus, UNDEFINED_ANSWER_SET);
02053         return TRUE;
02054       }
02055       pred_type = TIF_EvalMethod(tif);
02056       if ( IsVariantPredicate(tif) )
02057         goalSF = subsumerSF = get_variant_sf(CTXTc goalTerm, tif, NULL);
02058       else {
02059         BTNptr root, leaf;
02060         TriePathType path_type;
02061 
02062         root = TIF_CallTrie(tif);
02063         if ( IsNonNULL(root) )
02064           leaf = subsumptive_trie_lookup(CTXTc root, get_arity(psc),
02065                                          clref_val(goalTerm) + 1,
02066                                          &path_type, NULL);
02067         else {
02068           leaf = NULL;
02069           path_type = NO_PATH;
02070         }
02071         if ( path_type == NO_PATH )
02072           goalSF = subsumerSF = NULL;
02073         else if ( path_type == VARIANT_PATH ) {
02074           goalSF = CallTrieLeaf_GetSF(leaf);
02075           if ( IsProperlySubsumed(goalSF) )
02076             subsumerSF = (VariantSF)conssf_producer(goalSF);
02077           else
02078             subsumerSF = goalSF;
02079         }
02080         else {
02081           goalSF = NULL;
02082           subsumerSF = CallTrieLeaf_GetSF(leaf);
02083           if ( IsProperlySubsumed(subsumerSF) )
02084             subsumerSF = (VariantSF)conssf_producer(subsumerSF);
02085         }
02086       }
02087     }
02088     /*
02089      * Now both goalSF and subsumerSF should be set for all cases.
02090      * Determine status values based on these pointers.
02091      */
02092 #ifndef SHARED_COMPL_TABLES
02093     if ( IsNonNULL(goalSF) ) {
02094 #else
02095     if ( IsNonNULL(goalSF) && !subg_grabbed(goalSF)) {
02096 #endif
02097       if ( goalSF == subsumerSF )
02098         goal_type = PRODUCER_CALL;
02099       else
02100         goal_type = SUBSUMED_CALL;
02101     }
02102     else
02103       goal_type = NO_CALL_ENTRY;
02104 
02105 #ifndef SHARED_COMPL_TABLES
02106     if ( IsNonNULL(subsumerSF) ) {
02107 #else
02108     if ( IsNonNULL(subsumerSF) && !subg_grabbed(subsumerSF)) {
02109 #endif
02110       if ( is_completed(subsumerSF) )
02111         answer_set_status = COMPLETED_ANSWER_SET;
02112       else
02113         answer_set_status = INCOMPLETE_ANSWER_SET;
02114     }
02115     else
02116       answer_set_status = UNDEFINED_ANSWER_SET;
02117 
02118     ctop_int(CTXTc regPredType, pred_type);
02119     ctop_int(CTXTc regGoalType, goal_type);
02120     ctop_int(CTXTc regAnsSetStatus, answer_set_status);
02121     return TRUE;
02122   }
02123 
02124   case ABOLISH_TABLE_PREDICATE: {
02125     const int Arity = 1;
02126     const int regTerm = 1;   /* in: tabled predicate as term */
02127     Cell term;
02128     Psc psc;
02129 
02130     term = ptoc_tag(CTXTc regTerm);
02131     if ( isref(term) ) {
02132       err_handle(CTXTc INSTANTIATION, regTerm,
02133                  BuiltinName(ABOLISH_TABLE_PREDICATE), Arity, "", term);
02134       break;
02135     }
02136     psc = term_psc(term);
02137     if ( IsNULL(psc) ) {
02138       xsb_domain_error(CTXTc "predicate_or_term_indicator",term,
02139                        "abolish_table_pred",1, 1) ;
02140       break;
02141     }
02142     if (abolish_table_predicate(CTXTc psc)) {
02143       return TRUE;
02144     }
02145   }
02146 
02147   case ABOLISH_TABLE_CALL: {
02148     
02149     return abolish_table_call(CTXTc (VariantSF) ptoc_int(CTXTc 1));
02150   }
02151 
02152   case ABOLISH_MODULE_TABLES: {
02153     char *module_name;
02154 
02155     module_name = ptoc_string(CTXTc 1);
02156     if (!strcmp(module_name,"usermod") || !strcmp(module_name,"global")) 
02157       return abolish_usermod_tables(CTXT);
02158     else 
02159       return abolish_module_tables(CTXTc module_name);
02160     break;
02161   }
02162   case TRIE_ASSERT:
02163     if (trie_assert(CTXT))
02164       return TRUE;
02165     else
02166       xsb_exit("Failure of trie_assert/1");
02167   case TRIE_RETRACT:
02168     if (trie_retract(CTXT))
02169       return TRUE;
02170     else
02171       xsb_exit("Failure of trie_retract/1");
02172 
02173   case TRIE_RETRACT_SAFE:
02174     return trie_retract_safe(CTXT);
02175 
02176   case TRIE_DELETE_RETURN: {
02177     const int Arity = 2;
02178     const int regTableEntry = 1;   /* in: subgoal frame ref */
02179     const int regReturnNode = 2;   /* in: answer trie node */
02180     VariantSF sf;
02181     BTNptr leaf;
02182     /*
02183      * The primary purpose of this builtin is for the support of HiLog
02184      * aggregation predicates, which are based upon variant tabling.
02185      * So we currently disallow its use on subsumptive predicates.
02186      */
02187     sf = ptoc_addr(regTableEntry);
02188 #ifdef DEBUG_ASSERTIONS
02189   /* Need to change for MT: smVarSF can be private or shared
02190 |    if ( smIsValidStructRef(smProdSF,sf) ||
02191 |        smIsValidStructRef(smConsSF,sf) )
02192 |      xsb_abort("Invalid Table Entry Handle: Subsumptive table entry"
02193 |               "\n\t Argument %d of %s/%d\n\t Answers for subsumptive"
02194 |               " subgoals may not be deleted",
02195 |               regTableEntry, BuiltinName(TRIE_DELETE_RETURN), Arity);
02196 |    if ( ! smIsValidStructRef(smVarSF,sf) )
02197 |      xsb_abort("Invalid Table Entry Handle\n\t Argument %d of %s/%d",
02198 |               regTableEntry, BuiltinName(TRIE_DELETE_RETURN), Arity);
02199   */
02200 #endif
02201     leaf = ptoc_addr(regReturnNode);
02202     SET_TRIE_ALLOCATION_TYPE_SF(sf); /* set to private/shared SM */
02203     if ( ! smIsValidStructRef(*smBTN,leaf) )
02204       xsb_abort("Invalid Return Handle\n\t Argument %d of %s/%d",
02205                 regReturnNode, BuiltinName(TRIE_DELETE_RETURN), Arity);
02206 
02207     if ( (! smIsAllocatedStruct(*smBTN,leaf)) ||
02208          (subg_ans_root_ptr(sf) != get_trie_root(leaf)) ||
02209          (! IsLeafNode(leaf)) )
02210       return FALSE;
02211 
02212     delete_return(CTXTc leaf,sf);
02213     break;
02214   }
02215 
02216   case TRIE_GET_RETURN: {
02217     const int Arity = 2;
02218     const int regTableEntry = 1;   /* in: subgoal frame ref */
02219     const int regRetTerm    = 2;   /* in/out: ret/n term to unify against
02220                                               answer substitutions */
02221     VariantSF sf;
02222     Cell retTerm;
02223 
02224     sf = ptoc_addr(regTableEntry);
02225 #ifdef DEBUG_ASSERTIONS
02226   /* Need to change for MT: smVarSF can be private or shared
02227 |    if ( ! smIsValidStructRef(smVarSF,sf) &&
02228 |        ! smIsValidStructRef(smProdSF,sf) &&
02229 |        ! smIsValidStructRef(smConsSF,sf) )
02230 |      xsb_abort("Invalid Table Entry Handle\n\t Argument %d of %s/%d",
02231 |               regTableEntry, BuiltinName(TRIE_GET_RETURN), Arity);
02232   */
02233 #endif
02234     retTerm = ptoc_tag(CTXTc regRetTerm);
02235     if ( isref(retTerm) ) {
02236       err_handle(CTXTc INSTANTIATION, regRetTerm, BuiltinName(TRIE_GET_RETURN),
02237                  Arity, "", retTerm);
02238       break;
02239     }
02240     pcreg = trie_get_returns(CTXTc sf, retTerm);
02241     break;
02242   }
02243 
02244   case TRIE_ASSERT_HDR_INFO: /* r1: 0 -> r2: +TrieNodeAddr, r3: -RootOfCall
02245                                 r1: 1 -> r2: +Clref, r3: -trieNodeAddr, 
02246                                              fail if Clref not for a trie. */
02247     switch (ptoc_int(CTXTc 1)) {
02248     case 0:  /* r1: 0 -> r2: +TrieNodeAddr, r3: -RootOfCall */
02249       ctop_int(CTXTc 3,(Integer)(((BTNptr)(ptoc_int(CTXTc 2)))->child));
02250       break;
02251     case 1: {
02252       BTNptr trienode = trie_asserted_trienode((CPtr)ptoc_int(CTXTc 2));
02253       if (trienode) ctop_int(CTXTc 3, (Integer)trienode);
02254       else return FALSE;
02255       break;
02256     }
02257     }
02258     break;
02259 
02260   case TRIE_UNIFY_CALL: /* r1: +call_term */
02261     pcreg = trie_get_calls(CTXT);
02262     break;
02263 
02264   case GET_LASTNODE_CS_RETSKEL: {
02265     const int regCallTerm  = 1;   /* in: call of a tabled predicate */
02266     const int regTrieLeaf  = 2;   /* out: a unifying trie term handle */
02267     const int regLeafChild = 3;   /* out: usually to get subgoal frame */
02268     const int regRetTerm   = 4;   /* out: term in ret/N form:
02269                                      Call Trie -> answer template
02270                                      Other Trie -> variable vector */
02271     ctop_int(CTXTc regTrieLeaf, (Integer)Last_Nod_Sav);
02272     ctop_int(CTXTc regLeafChild, (Integer)BTN_Child(Last_Nod_Sav));
02273     ctop_tag(CTXTc regRetTerm, get_lastnode_cs_retskel(CTXTc ptoc_tag(CTXTc regCallTerm)));
02274     return TRUE;
02275   }
02276 
02277   case TRIE_GET_CALL: {
02278     const int regCallTerm = 1;   /* in:  tabled call to look for */
02279     const int regSF       = 2;   /* out: corresponding subgoal frame */
02280     const int regRetTerm  = 3;   /* out: answer template in ret/N form */
02281 
02282     Cell ret;
02283     VariantSF sf;
02284 
02285     sf = get_call(CTXTc ptoc_tag(CTXTc regCallTerm), &ret);
02286     if ( IsNonNULL(sf) ) {
02287       ctop_int(CTXTc regSF, (Integer)sf);
02288       ctop_tag(CTXTc regRetTerm, ret);
02289       return TRUE;
02290     }
02291     else
02292       return FALSE;
02293   }
02294 
02295   case BREG_RETSKEL:
02296     breg_retskel(CTXT);
02297     break;
02298 
02299   case TRIMCORE:
02300     /*
02301      * In each case, check whether the initial size of the data area is
02302      * large enough to contain the currently used portion of the data area.
02303      */
02304     if (tcpstack.size != tcpstack.init_size)
02305       if ( (unsigned int)((tcpstack.high - (byte *)top_of_cpstack) +
02306                      ((byte *)top_of_trail - tcpstack.low))
02307            < tcpstack.init_size * K - OVERFLOW_MARGIN )
02308         tcpstack_realloc(CTXTc tcpstack.init_size);
02309 
02310     if (complstack.size != complstack.init_size)
02311       if ( (unsigned int)(complstack.high - (byte *)openreg)
02312            < complstack.init_size * K - OVERFLOW_MARGIN )
02313         complstack_realloc(CTXTc complstack.init_size);
02314 
02315     if (glstack.size != glstack.init_size)
02316       if ( (unsigned int)((glstack.high - (byte *)top_of_localstk) +
02317                           ((byte *)hreg - glstack.low))
02318            < glstack.init_size * K - OVERFLOW_MARGIN )
02319         glstack_realloc(CTXTc glstack.init_size,0);
02320 
02321     tstShrinkDynStacks(CTXT);
02322     break;
02323 
02324   case NEWTRIE:
02325     ctop_int(CTXTc 1,newtrie(CTXT));
02326     break;
02327   case TRIE_INTERN:
02328     trie_intern(CTXT);
02329     break;
02330   case TRIE_INTERNED:
02331     return(trie_interned(CTXT));
02332   case TRIE_DISPOSE:
02333     trie_dispose(CTXT);
02334     break;
02335   case TRIE_DISPOSE_NR:
02336     trie_dispose_nr(CTXT);
02337     break;
02338   case TRIE_UNDISPOSE:
02339     trie_undispose(CTXTc ptoc_int(CTXTc 1), (BTNptr) ptoc_int(CTXTc 2));
02340     break;
02341   case RECLAIM_UNINTERNED_NR:
02342     reclaim_uninterned_nr(CTXTc ptoc_int(CTXTc 1));
02343     break;
02344   case GLOBALVAR:
02345     ctop_tag(CTXTc 1, ((Cell)glstack.low));
02346     break;
02347 
02348   case STORAGE_BUILTIN: {
02349     STORAGE_HANDLE *storage_handle =
02350       storage_builtin(CTXTc ptoc_int(CTXTc 1),(Cell)ptoc_tag(CTXTc 2));
02351     if (storage_handle != NULL) {
02352       ctop_int(CTXTc 3, (Integer)storage_handle->handle);
02353       ctop_int(CTXTc 4, (Integer)storage_handle->snapshot_number);
02354       ctop_int(CTXTc 5, (Integer)storage_handle->changed);
02355     }
02356     break;
02357   }
02358 
02359   case BOTTOM_UP_UNIFY:
02360     return ( bottom_up_unify(CTXT) );
02361   case DELETE_TRIE:
02362     if (strcmp(ptoc_string(CTXTc 2),"intern") == 0){
02363       int tmpval = ptoc_int(CTXTc 1);
02364       delete_interned_trie(CTXTc tmpval);
02365     }
02366     else {
02367       xsb_abort("[DELETE_TRIE] Invalid use of this operation");
02368     }
02369     break;
02370 
02371     case SET_TABLED_EVAL: { /* reg 1=psc, reg 2=eval method to use */
02372     Psc psc;
02373     Cell term = ptoc_tag(CTXTc 1);
02374     int eval_meth = ptoc_int(CTXTc 2);
02375 
02376     if ( isref(term) ) {
02377       err_handle(CTXTc INSTANTIATION, 1, BuiltinName(SET_TABLED_EVAL),
02378                  2, "", term);
02379       break;
02380     }
02381     psc = term_psc(term);
02382     if ( IsNULL(psc) ) {
02383       err_handle(CTXTc TYPE, 1, BuiltinName(SET_TABLED_EVAL),
02384                  2, "Predicate specification", term);
02385       break;
02386     }      
02387     if ((eval_meth == VARIANT_EVAL_METHOD) && (get_tabled(psc) != T_TABLED_VAR)) {
02388       if (get_tabled(psc) == T_TABLED) set_tabled(psc,T_TABLED_VAR);
02389       else xsb_warn("Cannot change to variant tabling method for %s/%d",get_name(psc),get_arity(psc));
02390     } else if ((eval_meth == SUBSUMPTIVE_EVAL_METHOD) && (get_tabled(psc) != T_TABLED_SUB)) {
02391       if (get_tabled(psc) == T_TABLED) set_tabled(psc,T_TABLED_SUB);
02392       else xsb_warn("Cannot change to subsumptive tabling method for %s/%d",get_name(psc),get_arity(psc));
02393     }
02394 
02395     /***    tif = get_tip(CTXTc psc);
02396     if ( IsNULL(tif) ) {
02397       xsb_warn("Predicate %s/%d is not tabled", get_name(psc), get_arity(psc));
02398       return FALSE;
02399     }
02400     if ( IsNonNULL(TIF_CallTrie(tif)) ) {
02401       xsb_warn("Cannot change tabling method for tabled predicate %s/%d\n"
02402                "\t   Calls to %s/%d have already been issued\n",
02403                get_name(psc), get_arity(psc), get_name(psc), get_arity(psc));
02404       return FALSE;
02405     }
02406     TIF_EvalMethod(tif) = (TabledEvalMethod)ptoc_int(CTXTc regTEM); 
02407 ***/
02408     return TRUE;
02409   }
02410 
02411     case UNIFY_WITH_OCCURS_CHECK:
02412       return unify_with_occurs_check(CTXTc cell(reg+1),cell(reg+2));
02413 
02414   case XSB_PROFILE:
02415     {
02416       if (xsb_profiling_enabled) {
02417         int call_type = ptoc_int(CTXTc 1);
02418         if (call_type == 1) { /* turn profiling on */
02419           if (!profile_thread_started) {
02420             if (!startProfileThread()) {
02421               xsb_abort("[XSB_PROFILE] Profiling thread does not start");
02422             } else profile_thread_started = TRUE;
02423           }
02424           if_profiling = 1;
02425         } else if (call_type == 2) {
02426           if_profiling = 0;
02427         } else if (call_type == 3) {
02428           retrieve_prof_table();
02429         } else {
02430           xsb_abort("[XSB_PROFILE] Unknown profiling command");
02431         }
02432         return TRUE;
02433       } else return FALSE;
02434     }
02435 
02436   case XSB_BACKTRACE:
02437     switch (ptoc_int(CTXTc 1)) {
02438     case 1: 
02439       print_xsb_backtrace(CTXT);
02440       break;
02441     case 2: 
02442       return unify(CTXTc ptoc_tag(CTXTc 2),build_xsb_backtrace(CTXT));
02443       break;
02444     }
02445     break;
02446 
02447   /* TLS: useful for power function -- see eval.P */
02448   case XSB_POW: 
02449     ctop_float(CTXTc 3,pow(ptoc_int(CTXTc 1),ptoc_int(CTXTc 2))); 
02450     return TRUE ;
02451 
02452   case PRINT_LS: print_ls(CTXTc 1) ; return TRUE ;
02453   case PRINT_TR: print_tr(CTXTc 1) ; return TRUE ;
02454   case PRINT_HEAP: print_heap(CTXTc 0,2000,1) ; return TRUE ;
02455   case PRINT_CP: print_cp(CTXTc 1) ; return TRUE ;
02456   case PRINT_REGS: print_regs(CTXTc 10,1) ; return TRUE ;
02457   case PRINT_ALL_STACKS: print_all_stacks(CTXTc 10) ; return TRUE ;
02458   case EXP_HEAP: glstack_realloc(CTXTc glstack.size + 1,0) ; return TRUE ;
02459   case MARK_HEAP: {
02460     int tmpval;
02461     mark_heap(CTXTc ptoc_int(CTXTc 1),&tmpval);
02462     return TRUE;
02463   }
02464 
02465     /* TLS: changed && -> & */
02466   case GC_STUFF: {
02467     int gc = ptoc_int(CTXTc 1);
02468     int ret_val = 0;
02469     if (gc & GC_GC_STRINGS) {
02470       gc &= ~GC_GC_HEAP;
02471       ret_val |= gc_heap(CTXTc 2,TRUE);
02472     }
02473     if (gc & GC_GC_HEAP) ret_val |= gc_heap(CTXTc 2,FALSE);
02474     if (gc & GC_GC_CLAUSES) ret_val |= gc_dynamic(CTXT);
02475     if (gc & GC_GC_TABLED_PREDS) ret_val |= gc_tabled_preds(CTXT);
02476 
02477     ctop_int(CTXTc 2, ret_val);
02478     return TRUE;
02479   }
02480   case FLOAT_OP:
02481   {
02482     char * operator = ptoc_string(CTXTc 1);
02483     Float result;
02484     switch((*operator))
02485     {
02486     case '+':
02487     result = 
02488         (EXTRACT_FLOAT_FROM_16_24_24((ptoc_int(CTXTc 2)), (ptoc_int(CTXTc 3)), (ptoc_int(CTXTc 4))))
02489         +
02490         (EXTRACT_FLOAT_FROM_16_24_24((ptoc_int(CTXTc 5)), (ptoc_int(CTXTc 6)), (ptoc_int(CTXTc 7))));
02491         break;
02492     case '-':
02493     result = 
02494         (EXTRACT_FLOAT_FROM_16_24_24((ptoc_int(CTXTc 2)), (ptoc_int(CTXTc 3)), (ptoc_int(CTXTc 4))))
02495         -
02496         (EXTRACT_FLOAT_FROM_16_24_24((ptoc_int(CTXTc 5)), (ptoc_int(CTXTc 6)), (ptoc_int(CTXTc 7))));
02497         break;
02498     case '*':
02499     result = 
02500         (EXTRACT_FLOAT_FROM_16_24_24((ptoc_int(CTXTc 2)), (ptoc_int(CTXTc 3)), (ptoc_int(CTXTc 4))))
02501         *
02502         (EXTRACT_FLOAT_FROM_16_24_24((ptoc_int(CTXTc 5)), (ptoc_int(CTXTc 6)), (ptoc_int(CTXTc 7))));
02503         break;
02504     case '/':
02505     result = 
02506         (EXTRACT_FLOAT_FROM_16_24_24((ptoc_int(CTXTc 2)), (ptoc_int(CTXTc 3)), (ptoc_int(CTXTc 4))))
02507         /
02508         (EXTRACT_FLOAT_FROM_16_24_24((ptoc_int(CTXTc 5)), (ptoc_int(CTXTc 6)), (ptoc_int(CTXTc 7))));
02509         break;
02510     default:
02511         result = 0.0;
02512         xsb_abort("[float_op] unsupported operator: %s\n", operator);
02513         return FALSE;
02514     }
02515     ctop_int(CTXTc 8, ((ID_BOXED_FLOAT << BOX_ID_OFFSET ) | FLOAT_HIGH_16_BITS(result) ));
02516     ctop_int(CTXTc 9, (FLOAT_MIDDLE_24_BITS(result)));
02517     ctop_int(CTXTc 10, (FLOAT_LOW_24_BITS(result)));    
02518     return TRUE;
02519   }
02520 
02521     /* This is the builtin where people should put their private, experimental
02522        builtin code. SEE THE EXAMPLE IN private_builtin.c to UNDERSTAND HOW TO
02523        DO IT. Note: even though this is a single builtin, YOU CAN SIMULATE ANY
02524        NUMBER OF BUILTINS WITH IT.  */
02525        
02526   case PRIVATE_BUILTIN: 
02527   {
02528     //    private_builtin();
02529     return TRUE;
02530   }
02531   case SEGFAULT_HANDLER: { /* Set the desired segfault handler:
02532                               +Arg1:  none  - don't catch segfaults;
02533                                       warn  - warn and exit;
02534                                       catch - try to recover */
02535     char *type = ptoc_string(CTXTc 1);
02536     switch (*type) {
02537     case 'w': /* warn: Warn and wuit */
02538       xsb_default_segfault_handler = xsb_segfault_quitter;
02539       break;
02540     case 'n': /* none: Don't handle segfaults */
02541       xsb_default_segfault_handler = SIG_DFL;
02542       break;
02543     case 'c': /* catch: Try to recover from all segfaults */
02544       xsb_default_segfault_handler = xsb_segfault_catcher;
02545       break;
02546     default:
02547       xsb_warn("Request for unsupported type of segfault handling, %s", type);
02548       return TRUE;
02549     }
02550 #ifdef SIGBUS
02551     signal(SIGBUS, xsb_default_segfault_handler);
02552 #endif
02553     signal(SIGSEGV, xsb_default_segfault_handler);
02554     return TRUE;
02555   }
02556 
02557   case IS_CHARLIST: {
02558     prolog_term size_var;
02559     int size;
02560     xsbBool retcode;
02561     size_var = reg_term(CTXTc 2);
02562     if (! isref(size_var)) {
02563       xsb_abort("[IS_CHARLIST] Arg 2 must be a variable");
02564     }
02565     retcode = is_charlist(reg_term(CTXTc 1), &size);
02566     c2p_int(CTXTc size,size_var);
02567     return retcode;
02568   }
02569 
02570     case DYNAMIC_CODE_FUNCTION: {
02571       dynamic_code_function(CTXT);
02572       break;
02573     }
02574 
02575     case FINDALL_FREE: 
02576       findall_free(CTXTc ptoc_int(CTXTc 1));
02577       return TRUE;
02578       break;
02579     case FINDALL_INIT: return(findall_init(CTXT)) ;
02580     case FINDALL_ADD: return(findall_add(CTXT)) ;
02581     case FINDALL_GET_SOLS: return(findall_get_solutions(CTXT)) ;
02582 
02583 #ifdef HAVE_SOCKET
02584     case SOCKET_REQUEST: {
02585       xsbBool xsb_socket_request_return;
02586       SYS_MUTEX_LOCK( MUTEX_SOCKETS ) ;
02587       xsb_socket_request_return = xsb_socket_request(CTXT);
02588       SYS_MUTEX_UNLOCK( MUTEX_SOCKETS ) ;
02589       return xsb_socket_request_return;
02590     }
02591 #endif /* HAVE_SOCKET */            
02592 
02593 #ifdef WIN_NT
02594   case JAVA_INTERRUPT: 
02595     return( startInterruptThread( (SOCKET)ptoc_int(CTXTc 1) ) );
02596 #endif
02597 
02598   case FORCE_TRUTH_VALUE: { /* +R1: AnsLeafPtr; +R2: TruthValue */
02599     BTNptr as_leaf = (BTNptr)ptoc_addr(1);
02600     char *tmpstr = ptoc_string(CTXTc 2);
02601     if (!strcmp(tmpstr, "true"))
02602       force_answer_true(as_leaf);
02603     else if (!strcmp(tmpstr, "false"))
02604       force_answer_false(as_leaf);
02605     else xsb_abort("[FORCE_TRUTH_VALUE] Argument 2 has unknown truth value");
02606     break;
02607   }
02608 
02609   case PUT_ATTRIBUTES: { /* R1: -Var; R2: +List */
02610     Cell attv = ptoc_tag(CTXTc 1);
02611     Cell atts = ptoc_tag(CTXTc 2);
02612     if (isref(attv)) {          /* attv is a free var */
02613       if (!isnil(atts)) {
02614         bind_attv((CPtr)attv, hreg);
02615         bld_free(hreg); hreg++;
02616         bld_copy(hreg, atts); hreg++;
02617       }
02618     }
02619     else if (isattv(attv)) {    /* attv is already an attv */
02620       if (isnil(atts)) {        /* change it back to normal var */
02621         bind_ref((CPtr)dec_addr(attv), hreg);
02622         bld_free(hreg); hreg++;
02623       }
02624       else {                    /* update the atts (another copy) */
02625         bind_attv((CPtr)dec_addr(attv), hreg);
02626         bld_free(hreg); hreg++;
02627         bld_copy(hreg, atts); hreg++;
02628       }
02629     }
02630     else xsb_abort("[PUT_ATTRIBUTES] Argument 1 is nonvar");
02631     break;
02632   }
02633 
02634   case GET_ATTRIBUTES: { /* R1: +Var; R2: -List */
02635     Cell attv = ptoc_tag(CTXTc 1);
02636     if (isref(attv)) {          /* a free var */
02637         return FALSE;
02638     }
02639     else if (isattv(attv)) {
02640       CPtr list;
02641       list = (CPtr)dec_addr(attv) + 1;
02642       ctop_tag(CTXTc 2, cell(list));
02643     }
02644     else xsb_abort("[GET_ATTRIBUTES] Argument 1 is not an attributed variable");
02645     break;
02646   }
02647 
02648   case DELETE_ATTRIBUTES: { /* R1: -Var */
02649     Cell attv = ptoc_tag(CTXTc 1);
02650     if (isattv(attv)) {
02651       bind_ref((CPtr)dec_addr(attv), hreg);
02652       bld_free(hreg); hreg++;
02653     }
02654     break;
02655 
02656   }
02657 
02658   /*
02659    * attv_unify/1 is an internal builtin for binding an attv to a value
02660    * (it could be another attv or a nonvar term).  The users can call
02661    * this builtin in verify_attributes/2 to bind an attributed var
02662    * without triggering attv interrupt.
02663    */
02664   case ATTV_UNIFY: { /* R1: +Var; R2: +Value */
02665     Cell attv = ptoc_tag(CTXTc 1);
02666     if (isattv(attv)) {
02667       bind_copy((CPtr)dec_addr(attv), ptoc_tag(CTXTc 2));
02668     } else {
02669       return FALSE;
02670     }
02671     break;
02672   }
02673 
02674   case SET_SCOPE_MARKER: {
02675     if (set_scope_marker(CTXT)) return TRUE; else return FALSE;
02676     break;
02677   }
02678   case UNWIND_STACK: {
02679     if (unwind_stack(CTXT)) return TRUE; else return FALSE;
02680     break;
02681   }
02682   case CLEAN_UP_BLOCK: {
02683     if (clean_up_block(CTXT)) return TRUE; else return FALSE;
02684     break;
02685   }
02686 
02687   case THREAD_REQUEST: {
02688 
02689     return xsb_thread_request(CTXT) ;
02690   }
02691 
02692   case MT_RANDOM_REQUEST: {
02693     return mt_random_request(CTXT) ;
02694   }
02695 
02696   default:
02697     xsb_abort("Builtin #%d is not implemented", number);
02698     break;
02699 
02700   } /* switch */
02701 
02702   return TRUE; /* catch for every break from switch */
02703 }
02704 
02705 /* Prolog Profiling (NOT thread-safe) */
02706 
02707 ubi_btRoot TreeRoot;
02708 ubi_btRootPtr RootPtr = NULL;
02709 ubi_btNodePtr prof_table;
02710 ubi_btNodePtr prof_table_free = NULL;
02711 
02712 typedef struct psc_profile_count_struct {
02713   Psc psc;
02714   int prof_count;
02715 } psc_profile_count;
02716 
02717 /* could use a splay tree to store and quickly find these entries if
02718    this were to be too slow, or if we added returning to psc and so
02719    got more. */
02720 
02721 static psc_profile_count *psc_profile_count_table = NULL;
02722 static int psc_profile_count_max = 0;
02723 static int psc_profile_count_num = 0;
02724 #define initial_psc_profile_count_size 100
02725 
02726 void add_to_profile_count_table(Psc apsc, int count) {
02727   int i;
02728   if (psc_profile_count_num >= psc_profile_count_max) {
02729     if (psc_profile_count_table == NULL) {
02730       psc_profile_count_max = initial_psc_profile_count_size;
02731       psc_profile_count_table = (psc_profile_count *)
02732         mem_alloc(psc_profile_count_max*sizeof(psc_profile_count),PROFILE_SPACE);
02733     } else {
02734       psc_profile_count_max = 2*psc_profile_count_max;
02735       psc_profile_count_table = (psc_profile_count *)
02736         mem_realloc(psc_profile_count_table,
02737                     (psc_profile_count_max/2)*sizeof(psc_profile_count),
02738                     psc_profile_count_max*sizeof(psc_profile_count),PROFILE_SPACE);
02739     }
02740   }
02741   for (i=0; i<psc_profile_count_num; i++)
02742     if (psc_profile_count_table[i].psc == apsc) {
02743       psc_profile_count_table[i].prof_count += count;
02744       return;
02745     }
02746   psc_profile_count_table[psc_profile_count_num].psc = apsc;
02747   psc_profile_count_table[psc_profile_count_num].prof_count = count;
02748   psc_profile_count_num++;
02749 }
02750 
02751 int compareItemNode(ubi_btItemPtr itemPtr, ubi_btNodePtr nodePtr) {
02752   if (*itemPtr < nodePtr->code_begin) return -1;
02753   else if (*itemPtr == nodePtr->code_begin) return 0;
02754   else return 1;
02755 }
02756 
02757 void log_prog_ctr(CTXTdeclc byte *lpcreg) {
02758   ubi_btNodePtr uNodePtr;
02759 
02760   uNodePtr = ubi_sptLocate(RootPtr, &lpcreg, ubi_trLE);
02761   prof_total++;
02762   if (uNodePtr == NULL) prof_unk_count++;
02763   else if (lpcreg <= uNodePtr->code_end) {
02764     uNodePtr->i_count++;
02765   }
02766   else prof_unk_count++;
02767 }
02768 
02769 #define prof_tab_incr 10000
02770 
02771 void add_prog_seg(Psc psc, byte *code_addr, long code_len) {
02772   ubi_btNodePtr newNode;
02773 
02774   if (!RootPtr) RootPtr = ubi_btInitTree(&TreeRoot,compareItemNode,ubi_trOVERWRITE);
02775 
02776   if (prof_table_free != NULL) {
02777     newNode = prof_table_free;
02778     prof_table_free = prof_table_free->Link[0];
02779   } else if (prof_table_count >= prof_table_length) {
02780     /* printf("Allocating another Profile Table segment\n"); */
02781     prof_table = (ubi_btNodePtr)mem_alloc(prof_tab_incr*sizeof(ubi_btNode),PROFILE_SPACE);
02782     prof_table_length = prof_tab_incr;
02783     newNode = prof_table;
02784     prof_table_count = 1;
02785   } else {
02786     newNode = prof_table+prof_table_count;
02787     prof_table_count++;
02788   }
02789   newNode->code_begin = code_addr;
02790   newNode->code_end = code_addr+code_len;
02791   newNode->code_psc = psc;
02792   newNode->i_count = 0;
02793   ubi_sptInsert(RootPtr,newNode,&(newNode->code_begin),NULL);
02794   //  printf("Adding segment for: %s/%d\n",get_name(newNode->code_psc),get_arity(newNode->code_psc));
02795   total_prog_segments++;
02796 }
02797 
02798 void remove_prog_seg(byte *code_addr) {
02799   ubi_btNodePtr oldNodePtr;
02800 
02801   oldNodePtr = ubi_sptFind(RootPtr,&code_addr);
02802   if (oldNodePtr == NULL) fprintf(stdout,"Error: code to delete not found: %p\n", code_addr);
02803   else {
02804     //    printf("Removing segment for: %s/%d\n",get_name(oldNodePtr->code_psc),get_arity(oldNodePtr->code_psc));
02805     if (oldNodePtr->i_count != 0)
02806       add_to_profile_count_table(oldNodePtr->code_psc, oldNodePtr->i_count);
02807     ubi_sptRemove(RootPtr,oldNodePtr);
02808     oldNodePtr->Link[0] = prof_table_free;
02809     prof_table_free = oldNodePtr;
02810     total_prog_segments--;
02811   }
02812 }
02813 
02814 Psc p3psc = NULL;
02815 
02816 void retrieve_prof_table(CTXTdecl) { /* r2: +NodePtr, r3: -p(PSC,ModPSC,Cnt), r4: -NextNodePtr */
02817   ubi_btNodePtr uNodePtr;
02818   CPtr pscptrloc, modpscptrloc;
02819   Cell arg3;
02820   Integer i;
02821   int tmp;
02822   Psc apsc;
02823 
02824   i = ptoc_int(CTXTc 2);
02825   if (i == 0) { // fill table
02826     uNodePtr = ubi_btFirst(RootPtr->root);
02827     while (uNodePtr != NULL) {
02828       if (uNodePtr->i_count != 0) {
02829         add_to_profile_count_table(uNodePtr->code_psc,uNodePtr->i_count);
02830         uNodePtr->i_count = 0;
02831       }
02832       uNodePtr = ubi_btNext(uNodePtr);
02833     }
02834   }
02835 
02836   if (p3psc == NULL) p3psc = insert("p",3,(Psc)flags[CURRENT_MODULE],&tmp)->psc_ptr;
02837   arg3 = ptoc_tag(CTXTc 3);
02838   bind_cs((CPtr)arg3,hreg);
02839   new_heap_functor(hreg,p3psc);
02840   pscptrloc = hreg++;
02841   modpscptrloc = hreg++;
02842   if (i < psc_profile_count_num) {
02843     follow(hreg++) = makeint(psc_profile_count_table[i].prof_count);
02844     apsc = psc_profile_count_table[i].psc;
02845     bld_oint(pscptrloc,(Integer)(apsc));
02846     bld_oint(modpscptrloc,(Integer)(apsc->data));
02847     ctop_int(CTXTc 4,i+1);
02848   } else {
02849     follow(hreg++) = makeint(prof_unk_count);
02850     bld_int(pscptrloc,0);
02851     bld_int(modpscptrloc,0);
02852     psc_profile_count_num = 0; // clear table
02853     prof_total = 0;
02854     prof_unk_count = 0;
02855     ctop_int(CTXTc 4,0);
02856   }
02857 }
02858 
02859 /*----------------------------------------------------------------------*/
02860 /* backtrace printer DSW */
02861 Psc psc_from_code_addr(byte *code_addr) {
02862   ubi_btNodePtr uNodePtr;
02863 
02864   uNodePtr = ubi_sptLocate(RootPtr, &code_addr, ubi_trLE);
02865   if (uNodePtr == NULL) return NULL;
02866   if (code_addr <= uNodePtr->code_end) return uNodePtr->code_psc;
02867   return NULL;
02868 }
02869 
02870 #define MAX_BACKTRACE_LENGTH 50
02871 int print_xsb_backtrace(CTXTdecl) {
02872   Psc tmp_psc, called_psc;
02873   byte *tmp_cpreg;
02874   byte instruction;
02875   CPtr tmp_ereg, tmp_breg;
02876   long backtrace_length = 0;
02877   if (xsb_profiling_enabled) {
02878     // print forward continuation
02879     fprintf(stdout,"Forward Continuation...\n");
02880     tmp_psc = psc_from_code_addr(pcreg);
02881     if (tmp_psc) fprintf(stdout,"... %s/%d,  pc=%p\n",get_name(tmp_psc),get_arity(tmp_psc),pcreg);
02882     else fprintf(stdout,"...unknown/?,  pc=%p\n",pcreg);
02883     tmp_ereg = ereg;
02884     tmp_cpreg = cpreg;
02885     instruction = *(tmp_cpreg-2*sizeof(Cell));
02886     while (tmp_cpreg && (instruction == call || instruction == trymeorelse) && 
02887            (backtrace_length++ < MAX_BACKTRACE_LENGTH)) {
02888       if (instruction == call) {
02889         called_psc = *((Psc *)tmp_cpreg - 1);
02890         if (called_psc != tmp_psc) {
02891           fprintf(stdout,"..* %s/%d,  pc=%p\n",get_name(called_psc),get_arity(called_psc),get_ep(called_psc));
02892         }
02893       }
02894       tmp_psc = psc_from_code_addr(tmp_cpreg);
02895       if (tmp_psc) fprintf(stdout,"... %s/%d,  pc=%p\n",get_name(tmp_psc),get_arity(tmp_psc),tmp_cpreg);
02896       else fprintf(stdout,"... unknown/?,  pc=%p\n",tmp_cpreg);
02897       tmp_cpreg = *((byte **)tmp_ereg-1);
02898       tmp_ereg = *(CPtr *)tmp_ereg;
02899       instruction = *(tmp_cpreg-2*sizeof(Cell));
02900     }
02901 
02902     // print backward continuation
02903     fprintf(stdout,"Backward Continuation...\n");
02904     tmp_breg = breg;
02905     while (tmp_breg && tmp_breg != cp_prevbreg(tmp_breg)) {
02906       tmp_psc = psc_from_code_addr(cp_pcreg(tmp_breg));
02907       if (tmp_psc) fprintf(stdout,"... %s/%d,  pc=%p, hreg=%p\n",
02908                           get_name(tmp_psc),get_arity(tmp_psc),cp_pcreg(tmp_breg),cp_hreg(tmp_breg));
02909       else fprintf(stdout,"... unknown/?,  i=%x, pc=%p\n",*cp_pcreg(tmp_breg),cp_pcreg(tmp_breg));
02910       tmp_breg = cp_prevbreg(tmp_breg);
02911     }
02912   } else {
02913     fprintf(stdout,"Partial Forward Continuation...\n");
02914     tmp_ereg = ereg;
02915     tmp_cpreg = cpreg;
02916     instruction = *(tmp_cpreg-2*sizeof(Cell));
02917     while (tmp_cpreg && (instruction == call || instruction == trymeorelse) && 
02918            (backtrace_length++ < MAX_BACKTRACE_LENGTH)) {
02919       if (instruction == call) {
02920         called_psc = *((Psc *)tmp_cpreg - 1);
02921         fprintf(stdout,"... %s/%d\n",get_name(called_psc),get_arity(called_psc));
02922       }
02923       tmp_cpreg = *((byte **)tmp_ereg-1);
02924       tmp_ereg = *(CPtr *)tmp_ereg;
02925       instruction = *(tmp_cpreg-2*sizeof(Cell));
02926     }
02927   }
02928   return TRUE;
02929 }
02930 
02931 prolog_term build_xsb_backtrace(CTXTdecl) {
02932   Psc tmp_psc, called_psc;
02933   byte *tmp_cpreg;
02934   byte instruction;
02935   CPtr tmp_ereg, tmp_breg, forward, backward, threg;
02936   prolog_term backtrace;
02937 
02938   backtrace = makelist(hreg);
02939   forward = hreg++;
02940   backward = hreg++;
02941   if (xsb_profiling_enabled) {
02942     tmp_psc = psc_from_code_addr(pcreg);
02943     follow(forward) = makelist(hreg);
02944     threg = hreg++;
02945     forward = hreg++;
02946     bld_oint(threg,tmp_psc);
02947     tmp_ereg = ereg;
02948     tmp_cpreg = cpreg;
02949     instruction = *(tmp_cpreg-2*sizeof(Cell));
02950     while (tmp_cpreg && (instruction == call || instruction == trymeorelse)
02951            && (pb)top_of_localstk > (pb)top_of_heap + 96) {
02952       if (instruction == call) {
02953         called_psc = *((Psc *)tmp_cpreg - 1);
02954         if (called_psc != tmp_psc) {
02955           follow(forward) = makelist(hreg);
02956           threg = hreg++;
02957           forward = hreg++;
02958           bld_oint(threg,called_psc);
02959         }
02960       }
02961       tmp_psc = psc_from_code_addr(tmp_cpreg);
02962       follow(forward) = makelist(hreg);
02963       threg = hreg++;
02964       forward = hreg++;
02965       bld_oint(threg,tmp_psc);
02966       tmp_cpreg = *((byte **)tmp_ereg-1);
02967       tmp_ereg = *(CPtr *)tmp_ereg;
02968       instruction = *(tmp_cpreg-2*sizeof(Cell));
02969     }
02970     follow(forward) = makenil;
02971 
02972     tmp_breg = breg;
02973     while (tmp_breg && tmp_breg != cp_prevbreg(tmp_breg)
02974            && (pb)top_of_localstk > (pb)top_of_heap + 48) {
02975       tmp_psc = psc_from_code_addr(cp_pcreg(tmp_breg));
02976       follow(backward) = makelist(hreg);
02977       threg = hreg++;
02978       backward = hreg++;
02979       bld_oint(threg,tmp_psc);
02980       tmp_breg = cp_prevbreg(tmp_breg);
02981     }
02982     follow(backward) = makenil;
02983 
02984   } else {
02985     tmp_ereg = ereg;
02986     tmp_cpreg = cpreg;
02987     instruction = *(tmp_cpreg-2*sizeof(Cell));
02988     while (tmp_cpreg && (instruction == call || instruction == trymeorelse)
02989            && (pb)top_of_localstk > (pb)top_of_heap + 48) {
02990       if (instruction == call) {
02991         called_psc = *((Psc *)tmp_cpreg - 1);
02992         follow(forward) = makelist(hreg);
02993         threg = hreg++;
02994         forward = hreg++;
02995         bld_oint(threg,called_psc);
02996       }
02997       tmp_cpreg = *((byte **)tmp_ereg-1);
02998       tmp_ereg = *(CPtr *)tmp_ereg;
02999       instruction = *(tmp_cpreg-2*sizeof(Cell));
03000     }
03001     follow(forward) = makenil;
03002     follow(backward) = makenil;
03003   }
03004   return backtrace;
03005 }
03006 
03007 
03008 /*------------------------- end of builtin.c -----------------------------*/
03009 

Generated on Wed Jul 26 13:30:40 2006 for XSB by  doxygen 1.4.5