psc_xsb.c

00001 /* File:      psc_xsb.c
00002 ** Author(s): Xu, Sagonas, Swift
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 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: psc_xsb.c,v 1.31 2006/04/10 13:06:25 dwarren Exp $
00023 ** 
00024 */
00025 
00026 
00027 #include "xsb_config.h"
00028 #include "xsb_debug.h"
00029 
00030 #include <stdio.h>
00031 #include <string.h>
00032 
00033 #include "auxlry.h"
00034 #include "cell_xsb.h"
00035 #include "error_xsb.h"
00036 #include "psc_xsb.h"
00037 #include "tries.h"
00038 #include "hash_xsb.h"
00039 #include "macro_xsb.h"
00040 #include "loader_xsb.h"
00041 #include "flags_xsb.h"
00042 #include "sig_xsb.h"
00043 #include "inst_xsb.h"
00044 #include "memory_xsb.h"
00045 #include "register.h"
00046 #include "thread_xsb.h"
00047 
00048 extern Psc synint_proc(Psc, int);
00049 
00050 /* === String Table manipulation ====================================== */
00051 
00052 /*
00053  * Looks up a string in the String Table.  If it is not found and the
00054  * insert flag is set, then inserts the string into the table.
00055  * If the string exists in the table, returns a pointer to the string
00056  * part of the corresponding table entry.
00057  *                      
00058  * String Table entries have the form:
00059  *           +--------------------------+
00060  *           | Ptr_to_Next | String ... |
00061  *           +--------------------------+
00062  */
00063 /* TLS: use of NOERROR mutexes is ok (12/05) but if we put in error
00064    checking in mem_xxxoc() functions, we'll need to adjust these
00065    mutexes. */
00066 
00067 #define CHAR_PTR_SIZE  sizeof(char *)
00068 
00069 char *string_find(char *str, int insert) {
00070 
00071   char **ptr, *str0;
00072 
00073   SYS_MUTEX_LOCK_NOERROR( MUTEX_STRING ) ;
00074   ptr = (char **)string_table.table + hash(str, 0, string_table.size);
00075   while (*ptr) {
00076     str0 = *ptr + CHAR_PTR_SIZE;
00077     if (strcmp(str, str0) == 0)
00078       goto exit_string_find;
00079     ptr = (char **)(*ptr);
00080   }
00081   
00082   if (insert) {
00083     str0 = (char *)mem_alloc(CHAR_PTR_SIZE + strlen(str) + 1,STRING_SPACE);
00084     *ptr = str0;
00085     *(char **)str0 = NULL;
00086     str0 = str0 + CHAR_PTR_SIZE;
00087     strcpy(str0, str);
00088     string_table_increment_and_check_for_overflow;
00089   }
00090   else
00091     str0 = NULL ;
00092 
00093 exit_string_find:
00094   SYS_MUTEX_UNLOCK_NOERROR( MUTEX_STRING ) ;
00095   return str0;
00096 }
00097 
00098 char *string_find_safe(char *str) {
00099 
00100   char *ptr, *str0;
00101 
00102   ptr = (char *)((Integer)(*(string_table.table + hash(str, 0, string_table.size))) & ~1);
00103   while (ptr) {
00104     str0 = ptr + CHAR_PTR_SIZE;
00105     if (strcmp(str, str0) == 0)
00106       return str0;
00107     ptr = (char *)(((Integer)(*(void **)ptr)) & ~1);
00108   }
00109   return NULL;
00110 }
00111 
00112 /* === PSC and PSC-PAIR structure creation/initialization =============== */
00113 
00114 /*
00115  *  Create a PSC record and initialize its fields.
00116  */
00117 static Psc make_psc_rec(char *name, char arity) {
00118   Psc temp;
00119   
00120   temp = (Psc)mem_alloc(sizeof(struct psc_rec),ATOM_SPACE);
00121   set_type(temp, 0);
00122   temp->env = 0;
00123   //  set_env(temp, 0);
00124   //  set_spy(temp, 0);
00125   //  set_shared(temp, 0);
00126   //  set_tabled(temp, 0);
00127   set_arity(temp, arity);
00128   set_data(temp, 0);
00129   set_ep(temp,(byte *)&(temp->load_inst));
00130   set_name(temp, string_find(name, 1));
00131   cell_opcode(&(temp->load_inst)) = load_pred;
00132   temp->this_psc = temp;
00133   return temp;
00134 }
00135 
00136 /*
00137  *  Create a PSC-PAIR record, set it to point to a PSC record, and place
00138  *  it at the head of a PSC-PAIR record chain.
00139  */
00140 static Pair make_psc_pair(Psc psc_ptr, Pair *link_ptr) {
00141 
00142   Pair new_pair;
00143   
00144   new_pair = (Pair)mem_alloc(sizeof(struct psc_pair),ATOM_SPACE);
00145   //  printf("new_psc_pair %d, prev %d\n",(int)new_pair, (int)*link_ptr);
00146   pair_psc(new_pair) = psc_ptr;         /* set 1st to point to psc_rec */
00147   pair_next(new_pair) = *link_ptr;      /* set 2nd to old head */
00148   *link_ptr = new_pair;                 /* new symbol is in the head! */
00149   return new_pair;
00150 }
00151 
00152 
00153 /* === get_tip: get the TIP from a PSC record ========================= */
00154 extern CPtr dynpredep_to_prortb(CTXTdeclc void *pred_ep);
00155 
00156 TIFptr *get_tip_or_tdisp(Psc temp)
00157 {
00158     CPtr temp1 ;
00159 
00160     switch (get_type(temp)) {
00161       case T_DYNA:
00162       case T_PRED:
00163         temp1 = (CPtr)get_ep(temp);
00164         if (temp1 != 0) {
00165           switch (*(pb)temp1) {
00166             case tabletry:
00167             case tabletrysingle:
00168               return (TIFptr *) (temp1+2) ;
00169             case test_heap:
00170               if (*(pb)(temp1+2) == tabletry ||
00171                   *(pb)(temp1+2) == tabletrysingle)
00172                 return (TIFptr *) (temp1+4) ;
00173               else return (TIFptr *)NULL;
00174               break;
00175             case switchon3bound:
00176             case switchonbound:
00177             case switchonterm:
00178               if (  *(pb) (temp1+3) == tabletry 
00179                 ||  *(pb) (temp1+3) == tabletrysingle) 
00180                 return (TIFptr *) (temp1+5) ;
00181               else return (TIFptr *) NULL;
00182             default:
00183               return (TIFptr *) NULL;
00184           }
00185         }
00186         else return (TIFptr *) NULL;
00187       default: 
00188         return (TIFptr *) NULL;
00189     }
00190 }
00191 
00192 /* get_tip takes a psc record and returns the tip (or null).  If
00193    multithreaded, it must go through the dispatch table to get the
00194    tip. 
00195 
00196 TLS: Added a few lines below to return NULL if the psc is non-tabled.
00197 Calling routines can then report the appropriate error.  */
00198 
00199 TIFptr get_tip(CTXTdeclc Psc psc) {
00200   TIFptr *tip = get_tip_or_tdisp(psc);
00201 #ifndef MULTI_THREAD
00202   return tip?(*tip):NULL;
00203 #else
00204   if (!tip) { /* get it out of dispatch table */
00205     CPtr temp1 = (CPtr) get_ep(psc);
00206     if ((get_type(psc) == T_DYNA) &&
00207         (*(pb)(temp1) ==  switchonthread)) {
00208       temp1 = dynpredep_to_prortb(CTXTc temp1);
00209       if (temp1 && (*(pb)temp1 == tabletrysingle)) 
00210         return *(TIFptr *)(temp1+2);
00211       else return (TIFptr) NULL;
00212     } else {
00213       if (get_tabled(psc)) {
00214         xsb_error("Internal Error in table dispatch\n");
00215       } else { return NULL; }
00216     }
00217   }
00218   if (TIF_EvalMethod(*tip) != DISPATCH_BLOCK) return *tip;
00219   /* *tip points to 3rd word in TDispBlk, so get addr of TDispBlk */
00220   { struct TDispBlk_t *tdispblk = (struct TDispBlk_t *) (*tip);
00221     TIFptr rtip = (TIFptr)((&(tdispblk->Thread0))[th->tid]);
00222     if (!rtip) {
00223       rtip = New_TIF(CTXTc psc);
00224       (&(tdispblk->Thread0))[th->tid] = rtip;
00225     }
00226     return rtip; 
00227   }
00228 #endif
00229 }
00230 
00231 /* === is_globalmod: Is a global module =============================== */
00232 
00233 static int is_globalmod(Psc mod_psc)
00234 {
00235 /* 
00236  * The modules considered global are the ones that have the value 1 in
00237  * their data field of the module's psc record.  The modules I
00238  * know that have this property are the modules "global" and "usermod".
00239  */
00240     if (mod_psc)
00241       return (((Cell)get_data(mod_psc) == USERMOD_PSC));
00243     else
00244       return 1;
00245 }
00246 
00247 
00248 /* === search: search in a given chain ================================ */
00249 
00250 /*
00251  *  Returns a pointer to the PSC-PAIR structure which points to the
00252  *  PSC record of the desired symbol.
00253  */
00254 static Pair search(int arity, char *name, Pair *search_ptr)
00255 {
00256     Psc psc_ptr;
00257     /*    Pair *init_search_ptr = search_ptr; */
00258     /*    Pair found_pair; */
00259 
00260     while (*search_ptr) {
00261       psc_ptr = (*search_ptr)->psc_ptr;
00262       if (strcmp(name, get_name(psc_ptr)) == 0
00263           && arity == get_arity(psc_ptr) )
00264         return (*search_ptr);
00265       else 
00266         search_ptr  = &((*search_ptr)->next);
00267     }
00268     return NULL;
00269 } /* search */
00270 
00271 
00272 /* === insert0: search/insert to a given chain ======================== */
00273 
00274 static Pair insert0(char *name, byte arity, Pair *search_ptr, int *is_new)
00275 {
00276     Pair pair;
00277     
00278     pair = search(arity, name, search_ptr);
00279     if (pair==NULL) {
00280       *is_new = 1;
00281       pair = make_psc_pair(make_psc_rec(name,arity), search_ptr);
00282     }
00283     else
00284       *is_new = 0;
00285     return pair;
00286 } /* insert0 */
00287 
00288 
00289 /* === insert: search/insert to a given module ======================== */
00290 
00291 Pair insert(char *name, byte arity, Psc mod_psc, int *is_new)
00292 {
00293     Pair *search_ptr, temp;
00294 
00295     SYS_MUTEX_LOCK_NOERROR( MUTEX_SYMBOL ) ;
00296 
00297     if (is_globalmod(mod_psc)) {
00298       search_ptr = (Pair *)(symbol_table.table +
00299                    hash(name, arity, symbol_table.size));
00300       temp = insert0(name, arity, search_ptr, is_new);
00301       if (*is_new)
00302         symbol_table_increment_and_check_for_overflow;
00303     }
00304     else {
00305       search_ptr = (Pair *)&(get_data(mod_psc));
00306       temp = insert0(name, arity, search_ptr, is_new);
00307     }
00308     SYS_MUTEX_UNLOCK_NOERROR( MUTEX_SYMBOL ) ;
00309     return temp ;
00310 } /* insert */
00311 
00312 
00313 /* === insert_module: search for/insert a given module ================ */
00314 
00315 Pair insert_module(int type, char *name)
00316 {
00317     Pair new_pair;
00318     int is_new;
00319 
00320     SYS_MUTEX_LOCK_NOERROR( MUTEX_SYMBOL ) ;
00321     new_pair = insert0(name, 0, (Pair *)&flags[MOD_LIST], &is_new);
00322     if (is_new) {
00323         set_type(new_pair->psc_ptr, type);
00324     } else {    /* set loading bit: T_MODU - loaded; 0 - unloaded */
00325       set_type(new_pair->psc_ptr, get_type(new_pair->psc_ptr) | type);
00326     }
00327     SYS_MUTEX_UNLOCK_NOERROR( MUTEX_SYMBOL ) ;
00328     return new_pair;
00329 } /* insert_module */
00330 
00331 
00332 /* === link_sym: link a symbol into a given module ==================== */
00333 
00334 /*
00335  *  Given a PSC record 'psc' for a particular symbol, check to see if
00336  *  that symbol already exists in the module 'mod_psc'.
00337  *  Does NOT exist => insert it and return a ptr to its PSC-PAIR record.
00338  *  DOES exist => check if the found PSC record is the same as 'psc'.
00339  *    YES => return a ptr to its PSC-PAIR record.
00340  *     NO => replace the old PSC record with 'psc'; return a ptr to the
00341  *           PSC-PAIR record.
00342  */
00343 
00344 Pair link_sym(Psc psc, Psc mod_psc)
00345 {
00346     Pair *search_ptr, found_pair;
00347     char *name, message[120];
00348     byte arity, global_flag, type;
00349 
00350     SYS_MUTEX_LOCK_NOERROR( MUTEX_SYMBOL ) ;
00351     name = get_name(psc);
00352     arity = get_arity(psc);
00353     if ( (global_flag = is_globalmod(mod_psc)) )
00354       search_ptr = (Pair *)symbol_table.table +
00355                    hash(name, arity, symbol_table.size);
00356     else
00357       search_ptr = (Pair *)&get_data(mod_psc);
00358     if ((found_pair = search(arity, name, search_ptr))) {
00359       if (pair_psc(found_pair) != psc) {
00360         /*
00361          *  Invalidate the old name!! It is no longer accessible
00362          *  through the global chain.
00363          */
00364         type = get_type(pair_psc(found_pair));
00365         if ( type != T_ORDI ) {
00366           if (type == T_DYNA || type == T_PRED) {
00367             Psc mod_psc = (Psc) get_data(pair_psc(found_pair));
00368             sprintf(message,
00369                     "%s/%d (type %d) had been defined in module: %s",
00370                     name, arity, type, mod_psc == 0 ? "usermod" : get_name(mod_psc));
00371           } else 
00372             sprintf(message,
00373                     "%s/%d (type %d) had been defined in another module!",
00374                     name, arity, type);
00375           xsb_warn(message);
00376         }
00377         pair_psc(found_pair) = psc;
00378       }
00379     }
00380     else {
00381       found_pair = make_psc_pair(psc, search_ptr);
00382       if (global_flag)
00383         symbol_table_increment_and_check_for_overflow;
00384     }
00385     SYS_MUTEX_UNLOCK_NOERROR( MUTEX_SYMBOL ) ;
00386     return found_pair;
00387 } /* link_sym */
00388 
00389 
00390 /*
00391  * Get the PSC for ret/n.  If it already exists, just return it.  Or
00392  * create one and save it in ret_psc[n].
00393  */
00394 Psc get_ret_psc(int n)
00395 {
00396   Pair temp;
00397   int new_indicator;
00398 
00399   if (!ret_psc[n]) {
00400     temp = (Pair) insert("ret", (byte) n, global_mod, &new_indicator);
00401     ret_psc[n] = pair_psc(temp);
00402   }
00403   return ret_psc[n];
00404 }
00405 
00406 
00407 /*
00408  * Get the PSC for intern/1, a generic functor for storing in the roots
00409  * of interned tries.
00410  */
00411 Psc get_intern_psc() {
00412 
00413   Pair intern_handle;
00414   int new_indicator;
00415 
00416   intern_handle = insert("intern", 1, global_mod, &new_indicator);
00417   return (pair_psc(intern_handle));
00418 }
00419 

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