subp.c

00001 /* File:      subp.c
00002 ** Author(s): Warren, Swift, Xu, Sagonas, Johnson
00003 ** Contact:   xsb-contact@cs.sunysb.edu
00004 ** 
00005 ** Copyright (C) The Research Foundation of SUNY, 1986, 1993-1998
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 Livallcense 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: subp.c,v 1.99 2006/07/14 16:49:36 tswift Exp $
00023 ** 
00024 */
00025 
00026 
00027 /* xsb_config.h must be the first #include.  Pls don't move it! */
00028 #include "xsb_config.h"
00029 #include "xsb_debug.h"
00030 
00031 
00032 #include "debugs/debug_attv.h"
00033 
00034 #include <stdio.h>
00035 #include <signal.h>
00036 #include <string.h>
00037 
00038 #ifdef WIN_NT
00039 #include <windows.h>
00040 #include <process.h>    /* _beginthread, _endthread */
00041 #include <winbase.h>
00042 #include <stddef.h>
00043 #include <stdlib.h>
00044 #include <winsock.h>
00045 #include <io.h>
00046 #include <string.h>
00047 #else
00048 #include <pthread.h>
00049 #include <sched.h>
00050 #include <unistd.h>
00051 #endif
00052 
00053 #include "auxlry.h"
00054 #include "cell_xsb.h"
00055 #include "debug_xsb.h"
00056 #include "error_xsb.h"
00057 #include "psc_xsb.h"
00058 
00059 #include "memory_xsb.h"
00060 #include "register.h"
00061 #include "heap_xsb.h"
00062 #include "deref.h"
00063 #include "flags_xsb.h"
00064 #include "binding.h"
00065 #include "trie_internals.h"
00066 #include "trassert.h"
00067 #include "choice.h"
00068 #include "token_xsb.h"
00069 #include "sig_xsb.h"
00070 #include "inst_xsb.h"
00071 #include "macro_xsb.h"
00072 #include "table_stats.h"
00073 #include "unify_xsb.h"
00074 #include "subp.h"
00075 #include "thread_xsb.h"
00076 #include "debug_xsb.h"
00077 #include "hash_xsb.h"
00078 #include "trace_xsb.h"
00079 
00080 /*======================================================================*/
00081 extern xsbBool quotes_are_needed(char *string);
00082 
00083 /*======================================================================*/
00084 
00085 #undef IFTHEN_FAILED
00086 #define IFTHEN_FAILED   return 0
00087 #undef IFTHEN_SUCCEED
00088 #define IFTHEN_SUCCEED  return 1
00089 
00090 double realtime_count_gl;
00091 
00092 #ifndef MULTI_THREAD
00093 extern int asynint_val; /* 0 - no interrupt (or being processed) */
00094 extern int asynint_code;        /* 0 means keyboard interrupt */
00095 #endif
00096 
00097 extern void print_mutex_use(void);
00098 
00099 extern void dis(xsbBool), debug_call(CTXTdeclc Psc);
00100 
00101 #ifdef LINUX
00102 static struct sigaction act, oact;
00103 #endif
00104 
00105 void (*xsb_default_segfault_handler)(int); /* where the previous value of the
00106                                              SIGSEGV/SIGBUS handler is saved */
00107 
00108 #ifndef MULTI_THREAD
00109 Cell attv_interrupts[20480][2];
00110 #endif
00111 
00112 /*
00113  * Put an attv interrupt into the interrupt chain. op1 is the related
00114  * attv, and op2 is the value (see verify_attributes/2).
00115  */
00116 
00117 void add_interrupt(CTXTdeclc Cell op1, Cell op2) {
00118   int num;
00119 
00120 #ifndef PRE_IMAGE_TRAIL
00121 #error "PRE_IMAGE_TRAIL has to be defined for add_interrupt() !"
00122 #else
00123 
00124   /*  printf("add_interrupt(");  
00125   dbg_printterm(0,stddbg,op1, 10);  
00126   printf(","); dbg_printterm(0,stddbg,op2, 10); printf(")\n");*/
00127 
00128   num = int_val(cell(interrupt_reg));
00130   push_pre_image_trail(&(attv_interrupts[num][0]), op1);
00131   attv_interrupts[num][0] = op1;
00132   push_pre_image_trail(&(attv_interrupts[num][1]), op2);
00133   attv_interrupts[num][1] = op2;
00134   num++;
00135   push_pre_image_trail(interrupt_reg, makeint(num));
00136   bld_int(interrupt_reg, num);
00137 
00138 #endif
00139 }
00140 
00141 
00142 /* Builds a list of interrupts on the heap.  As of 11/05, Called by
00143    the check_interrupt instruction; as well as synint_proc().  Both of
00144    these calls usually set reg1 to the chain, and call the handler */
00145 Cell build_interrupt_chain(CTXTdecl) {
00146   Cell head;
00147   CPtr tmp = &head;
00148   int num, i;
00149 
00150   num = int_val(cell(interrupt_reg));
00151   for (i = 0; i < num; i++) {
00152     bld_list(tmp, hreg);
00153     sreg = hreg + 2;
00154     bld_list(hreg, sreg); hreg++;
00155     if (i == (num - 1)) {
00156       bind_nil(hreg);
00157     }
00158     else
00159       tmp = hreg;
00160     bld_copy(sreg, attv_interrupts[i][0]); sreg++;
00161     bld_copy(sreg, attv_interrupts[i][1]); sreg++;
00162     hreg = sreg;
00163   }
00164 
00165 #ifndef PRE_IMAGE_TRAIL
00166 #error "PRE_IMAGE_TRAIL has to be defined for synint_proc() !"
00167 #else
00168   /* Reset the interrupt counter to 0 for further attv interrupts. */
00169   push_pre_image_trail(interrupt_reg, makeint(0));
00170 #endif
00171 
00172   bld_int(interrupt_reg, 0);
00173 
00174   return head;
00175 }
00176 
00177 /*======================================================================*/
00178 /*  Unification routines.                                               */
00179 /*======================================================================*/
00180 
00181 xsbBool unify(CTXTdeclc Cell rop1, Cell rop2)
00182 { /* begin unify */
00183   register Cell op1, op2;
00184 
00185   op1 = rop1; op2 = rop2;
00186 
00187 /*----------------------------------------*/
00188   unify_xsb(unify);
00189   /* unify_xsb.h already ends with this statement
00190      IFTHEN_SUCCEED;
00191   */
00192 /*----------------------------------------*/
00193 
00194 }  /* end of unify */
00195 
00196 /*======================================================================*/
00197 /*  Determining whether two terms are identical.                        */
00198 /*  (Used mostly by subsumptive trie lookup routines)                   */
00199 /*======================================================================*/
00200 
00201 xsbBool are_identical_terms(Cell term1, Cell term2) {
00202 
00203  begin_are_identical_terms:
00204   XSB_Deref(term1);
00205   XSB_Deref(term2);
00206   
00207   if ( term1 == term2 )
00208     return TRUE;
00209 
00210   if ( cell_tag(term1) != cell_tag(term2) )
00211     return FALSE;
00212 
00213   if ( cell_tag(term1) == XSB_STRUCT ) {
00214     CPtr cptr1 = clref_val(term1);
00215     CPtr cptr2 = clref_val(term2);
00216     Psc psc1 = (Psc)*cptr1;
00217     int i;
00218 
00219     if ( psc1 != (Psc)*cptr2 )
00220       return FALSE;
00221 
00222     for ( cptr1++, cptr2++, i = 0;  i < (int)get_arity(psc1)-1;  cptr1++, cptr2++, i++ )
00223       if ( ! are_identical_terms(*cptr1,*cptr2) ) 
00224         return FALSE;
00225     term1 = *cptr1; 
00226     term2 = *cptr2;
00227     goto begin_are_identical_terms;
00228   }
00229   else if ( cell_tag(term1) == XSB_LIST ) {
00230     CPtr cptr1 = clref_val(term1);
00231     CPtr cptr2 = clref_val(term2);
00232 
00233     if ( are_identical_terms(*cptr1, *cptr2) ) {
00234       term1 = *(cptr1 + 1); 
00235       term2 = *(cptr2 + 1);
00236       goto begin_are_identical_terms;
00237     } else return FALSE;
00238   }
00239   else return FALSE;
00240 }
00241 
00242 /*======================================================================*/
00243 /*  Print statistics and measurements.                                  */
00244 /*======================================================================*/
00245 
00246 /*
00247  * Called through builtins statistics/1 and statistics/0.
00248  * ( statistics :- statistics(1). )
00249  */
00250 void print_statistics(CTXTdeclc int amount) {
00251 
00252   switch (amount) {
00253 
00254   case 0:                   /* Reset Statistical Parameters */
00255 #ifndef MULTI_THREAD
00256     realtime_count_gl = real_time();
00257     perproc_reset_stat();       /* reset op-counts, starting time, and 'tds'
00258                                    struct variable (all 0's) */
00259     reset_stat_total();         /* reset 'ttt' struct variable (all 0's) */
00260     xsb_mesg("Statistics is reset.");
00261     break;
00262 #else
00263     realtime_count_gl = real_time();
00264     break;
00265 #endif
00266 
00267   case 1:                   /* Default use: Print Stack Usage and CPUtime: */
00268     perproc_stat();             /* move max usage into 'ttt' struct variable */
00269     total_stat(CTXTc real_time()-realtime_count_gl);   /* print */
00270     reset_stat_total();         /* reset 'ttt' struct variable (all 0's) */
00271     break;
00272 
00273   case 2:                   /* Print Detailed Table Usage */
00274 #ifndef MULTI_THREAD
00275     print_detailed_tablespace_stats(CTXT);
00276     break;
00277 #else
00278     fprintf(stdwarn,"statistics(2) not yet implemented for MT engine\n");
00279     break;
00280 #endif
00281 
00282   case 3:                   /* Print Detailed Table, Stack, and CPUtime */
00283 #ifndef MULTI_THREAD
00284     perproc_stat();
00285     total_stat(CTXTc real_time()-realtime_count_gl);
00286     reset_stat_total();
00287     print_detailed_tablespace_stats(CTXT);
00288     print_detailed_subsumption_stats();
00289     break;
00290 #else
00291     fprintf(stdwarn,"statistics(3) not yet implemented for MT engine\n");
00292     break;
00293 #endif
00294   case 4:                  /* mutex use (if PROFILE_MUTEXES is defined) */
00295     print_mutex_use();
00296     break;
00297   case 5:
00298     dis(0); 
00299     break;              /* output memory image - data only; for debugging */
00300   case 6:
00301     dis(1); 
00302     break;              /* output memory image - data + text; for debugging */
00303 #ifdef CP_DEBUG
00304   case 7:
00305     print_cp_backtrace();
00306     break;
00307 #endif
00308   case 8:              /* print symbol/string statistics */
00309     symbol_table_stats();
00310     string_table_stats();
00311     break;
00312   }
00313 }
00314 
00315 /*======================================================================*/
00316 /*======================================================================*/
00317 
00318 static void default_inthandler(int intcode)
00319 {
00320   char message[80];
00321 
00322   switch (intcode) {
00323   case MYSIG_UNDEF:
00324     xsb_exit("Undefined predicate; exiting by the default handler.");
00325     break;
00326   case MYSIG_KEYB:
00327     xsb_exit("Keyboard interrupt; exiting by the default handler.");
00328     break;
00329   case MYSIG_PSC:
00330     break;
00331   default:
00332     sprintf(message,
00333             "Unknown interrupt (%d) occured; exiting by the default handler", 
00334             intcode);
00335     xsb_exit(message);
00336     break;
00337   }
00338 }
00339 
00340 /*======================================================================*/
00341 /* builds the current call onto the heap and returns a pointer to it.   */
00342 /*======================================================================*/
00343 
00344 Pair build_call(CTXTdeclc Psc psc)
00345 {
00346   register Cell arg;
00347   register Pair callstr;
00348   register int i;
00349 
00350   callstr = (Pair)hreg; /* save addr of new structure rec */
00351   new_heap_functor(hreg, psc); /* set str psc ptr */
00352   for (i=1; i <= (int)get_arity(psc); i++) {
00353     arg = cell(reg+i);
00354     nbldval(arg);
00355   }
00356   return callstr;
00357 }
00358 
00359 /*======================================================================*/
00360 /* set interrupt code in reg 2 and return ep of interrupt handler.      */
00361 /* the returned value is normally assigned to pcreg, so this is like    */
00362 /* raising a trap.                                                      */
00363 /* Note that the interrupt handlers referred to by flags array values   */
00364 /* are set up on the Prolog side via set_inthandler/2                   */
00365 /*======================================================================*/
00366 
00367 Psc synint_proc(CTXTdeclc Psc psc, int intcode)
00368 {
00369   if (pflags[intcode+INT_HANDLERS_FLAGS_START]==(Cell)0) {
00370     /* default hard handler */
00371     default_inthandler(intcode);
00372     psc = 0;
00373   } else {                              /* call Prolog handler */
00374     switch (intcode) {
00375     case MYSIG_UNDEF:           /*  0 */
00376       SYS_MUTEX_LOCK( MUTEX_LOAD_UNDEF ) ;
00377     case MYSIG_KEYB:            /*  1 */
00378     case MYSIG_SPY:             /*  3 */
00379     case MYSIG_TRACE:           /*  4 */
00380     case THREADSIG_CANCEL:              /* f */
00381     case MYSIG_CLAUSE:          /* 16 */
00382       if (psc) bld_cs(reg+1, build_call(CTXTc psc));
00383       psc = (Psc)pflags[intcode+INT_HANDLERS_FLAGS_START];
00384       bld_int(reg+2, asynint_code);
00385       pcreg = get_ep(psc);
00386       break;
00387     case MYSIG_ATTV:            /*  8 */
00388       /* the old call must be built first */
00389       if (psc)
00390         bld_cs(reg+2, build_call(CTXTc psc));
00391       psc = (Psc)pflags[intcode+INT_HANDLERS_FLAGS_START];
00392       /*
00393        * Pass the interrupt chain to reg 1.  The counter of attv
00394        * interrupts (stored in *interrupt_reg) will be reset to 0 in
00395        * build_interrupt_chain()).
00396        */
00397       bld_copy(reg + 1, build_interrupt_chain(CTXT));
00398       /* bld_int(reg + 3, intcode); */  /* Not really needed */
00399       pcreg = get_ep(psc);
00400       break;
00401     default:
00402       xsb_abort("Unknown intcode in synint_proc()");
00403     } /* switch */
00404   }
00405   return psc;
00406 }
00407 
00408 void init_interrupt(void);
00409 
00410 /* TLS: 2/02 removed "inline static" modifiers so that this function
00411    can be called from interprolog_callback.c */
00412 void keyint_proc(int sig)
00413 {
00414 #ifdef MULTI_THREAD
00415   th_context *th = find_context(xsb_thread_self());
00416 #endif
00417 #ifndef LINUX
00418   init_interrupt();  /* reset interrupt, if using signal */
00419 #endif
00420   if (asynint_val & KEYINT_MARK) {
00421     xsb_abort("unhandled keyboard interrupt");
00422   } else {
00423     asynint_val |= KEYINT_MARK;
00424     asynint_code = 0;
00425   }
00426 }
00427 
00428 /* Called during XSB initialization -- could be in init_xsb.c, apart
00429    from funky use in keyint_proc() */
00430 
00431 void init_interrupt(void)
00432 {
00433 #if (defined(LINUX))
00434   act.sa_handler = keyint_proc;
00435   sigemptyset(&act.sa_mask); 
00436   act.sa_flags = 0;
00437   sigaction(SIGINT, &act, &oact);
00438 #else
00439   signal(SIGINT, keyint_proc); 
00440 #endif
00441 
00442 #if (defined(DEBUG_VERBOSE) || defined(DEBUG_VM) || defined(DEBUG_ASSERTIONS) || defined(DEBUG))
00443   /* Don't handle SIGSEGV/SIGBUS if configured with DEBUG */
00444   xsb_default_segfault_handler = SIG_DFL;
00445 #else 
00446   xsb_default_segfault_handler = xsb_segfault_quitter;
00447 #endif
00448 
00449 #ifdef SIGBUS
00450   signal(SIGBUS, xsb_default_segfault_handler);
00451 #endif
00452   signal(SIGSEGV, xsb_default_segfault_handler);
00453 }
00454 
00455 
00456 /*
00457  * Maintains max stack usage when "-s" option is given at startup.
00458  */
00459 void intercept(CTXTdeclc Psc psc) {
00460 
00461   if (pflags[CLAUSE_INT])
00462     synint_proc(CTXTc psc, MYSIG_CLAUSE);
00463   else if (flags[DEBUG_ON] && !flags[HIDE_STATE]) {
00464     if (get_spy(psc)) { /* spy'ed pred, interrupted */
00465       synint_proc(CTXTc psc, MYSIG_SPY);
00466       flags[HIDE_STATE]++; /* hide interrupt handler */
00467     }
00468     else if (flags[TRACE]) {
00469       synint_proc(CTXTc psc, MYSIG_TRACE);
00470       flags[HIDE_STATE]++; /* hide interrupt handler */
00471     }
00472   }
00473   if (flags[HITRACE])
00474     debug_call(CTXTc psc);
00475 
00476 #ifndef MULTI_THREAD
00477   if (flags[TRACE_STA]) {
00478     unsigned long  byte_size;
00479 
00480     byte_size = (top_of_heap - (CPtr)(glstack.low) + 1) * sizeof(Cell);
00481     if ( byte_size > tds.maxgstack_count )
00482       tds.maxgstack_count = byte_size;
00483 
00484     byte_size = ((CPtr)glstack.high - top_of_localstk) * sizeof(Cell);
00485     if ( byte_size > tds.maxlstack_count )
00486       tds.maxlstack_count = byte_size;
00487 
00488     byte_size = (top_of_trail - (CPtr *)tcpstack.low + 1) * sizeof(CPtr);
00489     if ( byte_size > tds.maxtrail_count )
00490       tds.maxtrail_count = byte_size;
00491 
00492     byte_size = ((CPtr)tcpstack.high - top_of_cpstack) * sizeof(Cell);
00493     if ( byte_size > tds.maxcpstack_count )
00494       tds.maxcpstack_count = byte_size;
00495 
00496     byte_size = ((CPtr)complstack.high - top_of_complstk) * sizeof(Cell);
00497     if ( byte_size > tds.maxopenstack_count )
00498       tds.maxopenstack_count = byte_size;
00499 
00500     if ((unsigned long)level_num > tds.maxlevel_num)
00501       tds.maxlevel_num = level_num;
00502   }
00503 #endif
00504 }
00505 
00506 /*======================================================================*/
00507 /* floating point conversions                                           */
00508 /*    The below 3 methods are to be used when floats and Cells are the  */
00509 /*    same size, in bytes, to convert between the two.                  */
00510 /*======================================================================*/
00511 
00512 /* lose some precision in conversions from 32 bit formats */
00513 
00514 #ifdef BITS64
00515 #define FLOAT_MASK 0xfffffffffffffff8
00516 #else
00517 #define FLOAT_MASK 0xfffffff8
00518 #endif
00519 
00520 
00521 inline float getfloatval(Cell w)
00522 {
00523     FloatConv converter;
00524     converter.i = w & FLOAT_MASK;
00525     return converter.f;
00526 }
00527 
00528 inline Cell makefloat(float f)
00529 {
00530     FloatConv converter;
00531     converter.f = f;
00532     return (Cell)(( converter.i & FLOAT_MASK ) | XSB_FLOAT);
00533 }
00534 
00535 inline int sign(Float num)
00536 {
00537   if (num==0.0) return 0;
00538   else if (num>0.0) return 1;
00539   else return -1;
00540 }
00541 
00542 /*======================================================================*/
00543 /* compare(V1, V2)                                                      */
00544 /*      compares two terms; returns zero if V1=V2, a positive value     */
00545 /*      if V1>V2 and a negative value if V1<V2.  Term comparison is     */
00546 /*      done according to the ISO standard total order of Prolog        */
00547 /*      terms which is as follows:                                      */
00548 /*                                                                      */
00549 /*          variables < floats < integers < atoms < compound terms      */
00550 /*                                                                      */
00551 /*      A list is compared as an ordinary compound term with arity      */
00552 /*      2 and functor '.'.                                              */
00553 /*                                                                      */
00554 /*      This function was rewritten from scratch by Kostis so that      */
00555 /*      it is independent of the relative order of tag encoding.        */
00556 /*      However, it should ONLY be used to compare terms that appear    */
00557 /*      in the above ordering list.                                     */
00558 /*======================================================================*/
00559 
00560 int compare(CTXTdeclc const void * v1, const void * v2)
00561 {
00562   int comp;
00563   CPtr cptr1, cptr2;
00564   Cell val1 = (Cell) v1 ;
00565   Cell val2 = (Cell) v2 ;
00566 
00567   XSB_Deref(val2);              /* val2 is not in register! */
00568   XSB_Deref(val1);              /* val1 is not in register! */
00569   if (val1 == val2) return 0;
00570   switch(cell_tag(val1)) {
00571   case XSB_FREE:
00572   case XSB_REF1:
00573     if (isattv(val2))
00574       return vptr(val1) - (CPtr)dec_addr(val2);
00575     else if (isnonvar(val2)) return -1;
00576     else { /* in case there exist local stack variables in the    */
00577            /* comparison, globalize them to guarantee that their  */
00578            /* order is retained as long as nobody "touches" them  */
00579            /* in the future -- without copying garbage collection */
00580       if ((top_of_localstk <= vptr(val1)) &&
00581           (vptr(val1) <= (CPtr)glstack.high-1)) {
00582         bld_free(hreg);
00583         bind_ref(vptr(val1), hreg);
00584         hreg++;
00585         val1 = follow(val1);    /* deref again */
00586       }
00587       if ((top_of_localstk <= vptr(val2)) &&
00588           (vptr(val2) <= (CPtr)glstack.high-1)) {
00589         bld_free(hreg);
00590         bind_ref(vptr(val2), hreg);
00591         hreg++;
00592         val2 = follow(val2);    /* deref again */
00593       }
00594       return vptr(val1) - vptr(val2);
00595     }
00596   case XSB_FLOAT:
00597     if (isref(val2) || isattv(val2)) return 1;
00598     else if (isofloat(val2)) 
00599       return sign(float_val(val1) - ofloat_val(val2));
00600     else return -1;
00601   case XSB_INT:
00602     if (isref(val2) || isofloat(val2) || isattv(val2)) return 1;
00603     else if (isinteger(val2)) 
00604       return int_val(val1) - int_val(val2);
00605     else if (isboxedinteger(val2))
00606       return int_val(val1) - boxedint_val(val2);
00607     else return -1;
00608   case XSB_STRING:
00609     if (isref(val2) || isofloat(val2) || isinteger(val2) || isattv(val2)) 
00610       return 1;
00611     else if (isstring(val2)) {
00612       return strcmp(string_val(val1), string_val(val2));
00613     }
00614     else return -1;
00615   case XSB_STRUCT:
00616     // below, first 2 if-checks test to see if this struct is actually a number representation,
00617     // (boxed float or boxed int) and if so, does what the number case would do, only with boxed_val
00618     // macros.
00619     if (isboxedinteger(val1)) {
00620       if (isref(val2) || isofloat(val2) || isattv(val2)) return 1;
00621       else if (isinteger(val2)) 
00622         return boxedint_val(val1) - int_val(val2);
00623       else if (isboxedinteger(val2))
00624         return boxedint_val(val1) - boxedint_val(val2);
00625       else return -1;
00626     } else if (isboxedfloat(val1)) {
00627         if (isref(val2) || isattv(val2)) return 1;
00628         else if (isofloat(val2)) 
00629           return sign(boxedfloat_val(val1) - ofloat_val(val2));
00630         else return -1;            
00631     } else if (cell_tag(val2) != XSB_STRUCT && cell_tag(val2) != XSB_LIST) return 1;
00632     else {
00633       int arity1, arity2;
00634       Psc ptr1 = get_str_psc(val1);
00635       Psc ptr2 = get_str_psc(val2);
00636 
00637       arity1 = get_arity(ptr1);
00638       if (islist(val2)) arity2 = 2; 
00639       else arity2 = get_arity(ptr2);
00640       if (arity1 != arity2) return arity1-arity2;
00641       if (islist(val2)) comp = strcmp(get_name(ptr1), ".");
00642       else comp = strcmp(get_name(ptr1), get_name(ptr2));
00643       if (comp || (arity1 == 0)) return comp;
00644       cptr1 = clref_val(val1);
00645       cptr2 = clref_val(val2);
00646       for (arity2 = 1; arity2 <= arity1; arity2++) {
00647         if (islist(val2))
00648           comp = compare(CTXTc (void*)cell(cptr1+arity2), (void*)cell(cptr2+arity2-1));  
00649         else
00650           comp = compare(CTXTc (void*)cell(cptr1+arity2), (void*)cell(cptr2+arity2));
00651         if (comp) break;
00652       }
00653       return comp;
00654     }
00655     break;
00656   case XSB_LIST:
00657     if (cell_tag(val2) != XSB_STRUCT && cell_tag(val2) != XSB_LIST) return 1;
00658     else if (isconstr(val2)) return -(compare(CTXTc (void*)val2, (void*)val1));
00659     else {      /* Here we are comparing two list structures. */
00660       cptr1 = clref_val(val1);
00661       cptr2 = clref_val(val2);
00662       comp = compare(CTXTc (void*)cell(cptr1), (void*)cell(cptr2));
00663       if (comp) return comp;
00664       return compare(CTXTc (void*)cell(cptr1+1), (void*)cell(cptr2+1));
00665     }
00666     break;
00667   case XSB_ATTV:
00668     if (isattv(val2))
00669       return (CPtr)dec_addr(val1) - (CPtr)dec_addr(val2);
00670     else if (isref(val2))
00671       return (CPtr)dec_addr(val1) - vptr(val2);
00672     else
00673       return -1;
00674   default:
00675     xsb_abort("Compare (unknown tag %ld); returning 0", cell_tag(val1));
00676     return 0;
00677   }
00678 }
00679 
00680 /*======================================================================*/
00681 /* key_compare(V1, V2)                                                  */
00682 /*      compares the keys of two terms of the form Key-Value; returns   */
00683 /*      zero if Key1=Key2, a positive value if Key1>Key2 and a negative */
00684 /*      value if Key1<Key2.  Term comparison is done according to the   */
00685 /*      standard total order of Prolog terms (see compare()).           */
00686 /*======================================================================*/
00687 
00688 int key_compare(CTXTdeclc const void * t1, const void * t2)
00689 {
00690   Cell term1 = (Cell) t1 ;
00691   Cell term2 = (Cell) t2 ;
00692 
00693   XSB_Deref(term1);             /* term1 is not in register! */
00694   XSB_Deref(term2);             /* term2 is not in register! */
00695   return compare(CTXTc (void*)cell(clref_val(term1)+1), (void*)cell(clref_val(term2)+1));
00696 }
00697 
00698 /*======================================================================*/
00699 /* print an atom as quoted.                                             */
00700 /* This, and the next few functions are used in file_puttoken.  I have  */
00701 /* no idea why we keep them here.                                       */
00702 /*======================================================================*/
00703 
00704 void print_aqatom(FILE *file, char *string) {
00705   int loc = 0;
00706 
00707   fprintf(file,"'");
00708   while (string[loc] != '\0') {
00709     if (string[loc] == '\'') fprintf(file,"'");
00710     fprintf(file,"%c",string[loc++]);
00711   }
00712   fprintf(file,"'");
00713 }
00714 
00715 /*======================================================================*/
00716 /* print an atom, quote it if necessary.                                */
00717 /*======================================================================*/
00718 
00719 void print_qatom(FILE *file, char *string)
00720 {
00721   if (quotes_are_needed(string)) print_aqatom(file, string);
00722   else fprintf(file, "%s", string);
00723 }
00724 
00725 /*======================================================================*/
00726 /* print a double quoted string, doubling internal double quotes        */
00727 /* if necessary.                                                        */
00728 /*======================================================================*/
00729 
00730 void print_dqatom(FILE *file, char *string)
00731 {
00732   int loc = 0;
00733 
00734   fprintf(file,"\"");
00735   while (string[loc] != '\0') {
00736     if (string[loc] == '"') fprintf(file,"\"");
00737     fprintf(file,"%c",string[loc++]);
00738   }
00739   fprintf(file,"\"");
00740 }
00741 
00742 /*======================================================================*/
00743 /* print an operator.                                                   */
00744 /*======================================================================*/
00745 
00746 void print_op(FILE *file, char *string, int pos)
00747 {
00748   char *s;
00749   int need_blank = 0;
00750 
00751   s = string;
00752   while (*s) { 
00753     if (intype(*s) != SIGN) { need_blank = 1; break;} 
00754     s++;
00755   }
00756   if (need_blank) {
00757     switch (pos) {
00758       case 1: print_qatom(file, string); putc(' ', file); break;
00759       case 2: putc(' ', file);
00760               print_qatom(file, string); putc(' ', file); break;
00761       case 3: putc(' ', file); print_qatom(file, string); break;
00762     }
00763   } else fprintf(file, "%s", string);
00764 }
00765 
00766 /* ----- The following is also called from the Prolog level ----------- */
00767 
00768 void remove_incomplete_tables_reset_freezes(CTXTdecl)
00769 {
00770     remove_incomplete_tables();
00771     reset_freeze_registers;
00772 }
00773 
00774 /* ----- C level exception handlers ----------------------------------- */
00775 
00776 /* SIGSEGV/SIGBUS handler that catches segfaults; used unless 
00777    configured with DEBUG */ 
00778 void xsb_segfault_catcher(int err)
00779 {
00780   char *tmp_message = xsb_segfault_message;
00781 #ifdef MULTI_THREAD
00782   xsb_exit(tmp_message);
00783 #else
00784   xsb_segfault_message = xsb_default_segfault_msg; /* restore default */
00785   printf("segfault!!\n");
00786   xsb_basic_abort(tmp_message);
00787 #endif
00788 }
00789 
00790 void xsb_segfault_quitter(int err)
00791 {
00792 #ifdef MULTI_THREAD
00793   th_context *th = find_context(xsb_thread_self());
00794 #endif
00795   print_xsb_backtrace(CTXT);
00796   xsb_exit(xsb_segfault_message);
00797 }
00798 
00799 #ifdef WIN_NT
00800 /* Our separate thread */
00801 void checkJavaInterrupt(void *info)
00802 {
00803   char ch;
00804   SOCKET intSocket = (SOCKET)info;
00805   xsb_dbgmsg((LOG_DEBUG, "Thread started on socket %ld",(int)intSocket));
00806   while(1){
00807     if (1!=recv(intSocket,&ch,1,0)) {
00808       xsb_warn("Problem handling interrupt from Java");
00809     }
00810     else 
00811       xsb_mesg("--- Java interrupt detected");
00812     /* Avoid those annoying lags? */
00813     fflush(stdout);
00814     fflush(stderr);
00815     fflush(stdmsg);
00816     fflush(stdwarn);
00817     fflush(stddbg);
00818     keyint_proc(SIGINT); /* Do XSB's "interrupt" thing */
00819   }
00820 }
00821 
00822 xsbBool startInterruptThread(SOCKET intSocket)
00823 {
00824   xsb_mesg("Beginning interrupt thread on socket %ld",(int)intSocket);
00825 #ifdef _MT
00826   _beginthread( checkJavaInterrupt, 0, (void*)intSocket );
00827 #endif
00828   return 1;
00829 }
00830 #endif
00831 
00832 
00833 extern long if_profiling;
00834 extern long prof_flag;
00835 
00836 void setProfileBit(void *place_holder) {
00837   long unhandled = 0;
00838 #ifdef MULTI_THREAD
00839   th_context *th = find_context(xsb_thread_self());
00840 #endif
00841   while (TRUE) {
00842     if (if_profiling) {
00843       if (asynint_val & PROFINT_MARK) {
00844         unhandled++;
00845         if (!(unhandled % 10)) printf("Unhandled profile ints: %ld\n",unhandled);
00846       }
00847       asynint_val |= PROFINT_MARK;
00848     }
00849 #ifdef WIN_NT
00850     Sleep(10);
00851 #else
00852     sleep(0.01);
00853 #endif
00854   }
00855 }
00856 
00857 xsbBool startProfileThread()
00858 {
00859 #ifdef WIN_NT
00860   HANDLE Thread;
00861   if (!if_profiling) {
00862     Thread = (HANDLE)_beginthread(setProfileBit,0,NULL);
00863     SetThreadPriority(Thread,THREAD_PRIORITY_HIGHEST/*_ABOVE_NORMAL*/);
00864   }
00865 #elif defined(SOLARIS)
00866   printf("Profiling not supported\n");
00867 #else
00868   pthread_t         a_thread;
00869   struct sched_param param;
00870 
00871   if (!if_profiling) {
00872     pthread_create(&a_thread, NULL, (void*)&setProfileBit, (void*)NULL);
00873     param.sched_priority = sched_get_priority_max(SCHED_OTHER);
00874     pthread_setschedparam(a_thread, SCHED_OTHER, &param);
00875 
00876     if_profiling = 1;
00877   }
00878 #endif
00879   return TRUE;
00880 }

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