00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "xsb_config.h"
00029 #include "builtin.h"
00030 #include "sp_unify_xsb_i.h"
00031
00032
00033 static xsbBool atom_to_list(CTXTdeclc int call_type);
00034 static xsbBool number_to_list(CTXTdeclc int call_type);
00035
00036
00037
00038 inline static xsbBool functor_builtin(CTXTdecl)
00039 {
00040
00041 int new_indicator, arity, value, disp;
00042 Psc psc;
00043 char *name;
00044 Cell functor, term;
00045 Pair sym;
00046
00047 term = ptoc_tag(CTXTc 1);
00048 if (isnonvar(term)) {
00049 if (isconstr(term) && !isboxedfloat(term) && !isboxedinteger(term)) {
00050 psc = get_str_psc(term);
00051 name = get_name(psc);
00052 arity = get_arity(psc);
00053 return (atom_unify(CTXTc makestring(name), ptoc_tag(CTXTc 2)) &&
00054 int_unify(CTXTc makeint(arity), ptoc_tag(CTXTc 3)));
00055 } else if (islist(term))
00056 return (atom_unify(CTXTc makestring(list_dot_string), ptoc_tag(CTXTc 2)) &&
00057 int_unify(CTXTc makeint(2), ptoc_tag(CTXTc 3)));
00058 else return (unify(CTXTc term, ptoc_tag(CTXTc 2)) &&
00059 int_unify(CTXTc makeint(0), ptoc_tag(CTXTc 3)));
00060 } else {
00061 functor = ptoc_tag(CTXTc 2);
00062 if (isstring(functor) || isinteger(functor) || isofloat(functor) ||
00063 isboxedinteger(functor) ||
00064 (isconstr(term) && get_arity(get_str_psc(term)) == 0)) {
00065 arity = ptoc_tag(CTXTc 3);
00066
00067 if (arity_integer(arity) && !isnumber(functor)) {
00068 value = int_val(arity);
00069 if (value == 0) return unify(CTXTc functor, term);
00070 else {
00071 if (value == 2 && isstring(functor)
00072 && string_val(functor) == list_dot_string) {
00073
00074 bind_list((CPtr)term, hreg);
00075 new_heap_free(hreg);
00076 new_heap_free(hreg);
00077 } else {
00078
00079 sym = (Pair)insert(string_val(functor), (char)value,
00080 (Psc)flags[CURRENT_MODULE],
00081 &new_indicator);
00082 sreg = hreg;
00083 hreg += value+1;
00084 bind_cs((CPtr)term, sreg);
00085 new_heap_functor(sreg, sym->psc_ptr);
00086 for (disp=0; disp<value; disp++) {
00087 new_heap_free(sreg);
00088 }
00089 }
00090 return TRUE;
00091 }
00092
00093 } else {
00094 if (isnumber(functor))
00095 return (unify(CTXTc term, functor) &&
00096 int_unify(CTXTc makeint(0), arity));
00097 else {
00098 if (isnonvar(arity)) {
00099 if (isinteger(arity))
00100 err_handle(CTXTc RANGE, 3, "functor", 3,
00101 "integer in the range 0..255", arity);
00102 else
00103 xsb_type_error(CTXTc "integer",arity,"functor",3,3);
00104
00105 }
00106 else err(INSTANTIATION, 3, "functor", 3);
00107 }
00108 }
00109 }
00110 else {
00111 if (isnonvar(functor))
00112 xsb_type_error(CTXTc "atom",functor,"functor",3,2);
00113 else err(INSTANTIATION, 2, "functor", 3);
00114 }
00115 }
00116 return TRUE;
00117 }
00118
00119
00120 inline static xsbBool arg_builtin(CTXTdecl)
00121 {
00122
00123 Cell index;
00124 Cell term;
00125 int disp;
00126
00127 index = ptoc_tag(CTXTc 1);
00128 if (isinteger(index)) {
00129 if ((disp = int_val(index)) > 0) {
00130 term = ptoc_tag(CTXTc 2);
00131 if (isnonvar(term)) {
00132 if (isconstr(term) && !isboxedinteger(term) && !isboxedfloat(term)) {
00133 if (disp <= (int)get_arity(get_str_psc(term))) {
00134 return unify(CTXTc (Cell)(clref_val(term)+disp),
00135 ptoc_tag(CTXTc 3));
00136 }
00137 else return FALSE;
00138 } else if (islist(term) && (disp==1 || disp==2)) {
00139 return unify(CTXTc (Cell)(clref_val(term)+disp-1),
00140 ptoc_tag(CTXTc 3));
00141 } else return FALSE;
00142 } else err(INSTANTIATION, 2, "arg", 3);
00143 } else return FALSE;
00144 } else {
00145 if (isnonvar(index)) xsb_type_error(CTXTc "integer",index,"arg",3,1);
00146 else err(INSTANTIATION, 1, "arg", 3);
00147 }
00148 return TRUE;
00149 }
00150
00151
00152 inline static xsbBool univ_builtin(CTXTdecl)
00153 {
00154
00155 int i, arity;
00156 int new_indicator;
00157 char *name;
00158 Cell list, new_list, term;
00159 CPtr head, top = 0;
00160 Pair sym;
00161
00162 term = ptoc_tag(CTXTc 1);
00163 list = ptoc_tag(CTXTc 2);
00164 if (isnonvar(term)) {
00165 new_list = makelist(hreg);
00166 if (isatomic(term) || isboxedinteger(term)) { follow(hreg++) = term; top = hreg++; }
00167 else if (isconstr(term) && (arity = (get_arity(get_str_psc(term))))) {
00168 follow(hreg++) = makestring(get_name(get_str_psc(term)));
00169 top = hreg++;
00170 for (i = 1 ; i <= arity ; i++) {
00171 follow(top) = makelist(hreg); top = hreg++;
00172 follow(top) = (Cell)(clref_val(term)+i); top = hreg++;
00173 }
00174 }
00175 else {
00176 follow(hreg++) = makestring(list_dot_string);
00177 top = hreg++;
00178 follow(top) = makelist(hreg); top = hreg++;
00179 follow(top) = (Cell)(clref_val(term)); top = hreg++;
00180 follow(top) = makelist(hreg); top = hreg++;
00181 follow(top) = (Cell)(clref_val(term)+1); top = hreg++;
00182 }
00183 follow(top) = makenil;
00184 return unify(CTXTc list, new_list);
00185 } else {
00186 if (islist(list)) {
00187 head = clref_val(list);
00188 XSB_Deref(cell(head));
00189 if (isatom(cell(head))) {
00190 if (isnil(cell(head+1))) {
00191 bind_copy((CPtr)term, cell(head));
00192 return TRUE;
00193 } else {
00194 xsbBool list_construction = FALSE;
00195 name = string_val(cell(head));
00196 if (!strcmp(name, ".")) {
00197 list = cell(head+1); XSB_Deref(list);
00198 if (islist(list)) {
00199 list = cell(clref_val(list)+1); XSB_Deref(list);
00200 if (islist(list)) {
00201 list = cell(clref_val(list)+1); XSB_Deref(list);
00202 if (isnil(list)) list_construction = TRUE;
00203 }
00204 }
00205 }
00206 if (list_construction) {
00207 bind_list((CPtr)term, hreg);
00208 list = cell(head+1);
00209 XSB_Deref(list);
00210 bld_copy(hreg, cell(clref_val(list))); hreg++;
00211 list = cell(clref_val(list)+1);
00212 XSB_Deref(list);
00213 bld_copy(hreg, cell(clref_val(list))); hreg++;
00214 } else {
00215 sreg = hreg;
00216 bind_cs((CPtr)term, sreg); hreg = sreg; sreg++;
00217 for (arity = 0, list = cell(head+1); ;
00218 arity++, list = cell(clref_val(list)+1)) {
00219 XSB_Deref(list);
00220 if (!islist(list)) break;
00221 bld_copy(sreg, cell(clref_val(list))); sreg++;
00222 }
00223 if (isnil(list) && arity <= MAX_ARITY) {
00224
00225 sym = (Pair)insert(name, (char)arity,
00226 (Psc)flags[CURRENT_MODULE],
00227 &new_indicator);
00228 new_heap_functor(hreg, sym->psc_ptr);
00229 hreg = sreg+1;
00230 } else {
00231 hreg = hreg-1;
00232 if (arity > MAX_ARITY)
00233 xsb_abort("[In =..] Attempt to construct a functor with arity %d > %d",
00234 arity, MAX_ARITY);
00235 else xsb_type_error(CTXTc "list",list,"=..",2,2);
00236 return FALSE;
00237 }
00238 }
00239 } return TRUE;
00240 }
00241 if ((isnumber(cell(head)) || isboxedinteger(cell(head))) && isnil(cell(head+1))) {
00242 bind_copy((CPtr)term, cell(head));
00243 return TRUE;
00244 }
00245 else
00246 {
00247 xsb_type_error(CTXTc "list",list,"=..",2,2);
00248 return(FALSE);
00249 }
00250 }
00251 if (isnonvar(list))
00252 xsb_type_error(CTXTc "list",list,"=..",2,2);
00253 else err(INSTANTIATION, 2, "=..", 2);
00254 }
00255 return TRUE;
00256 }
00257
00258
00259 inline static xsbBool hilog_arg(CTXTdecl)
00260 {
00261
00262 Cell index, term;
00263 int disp;
00264
00265 index = ptoc_tag(CTXTc 1);
00266 if (isinteger(index)) {
00267 if ((disp = int_val(index)) > 0) {
00268 term = ptoc_tag(CTXTc 2);
00269 if (isnonvar(term)) {
00270 if (isconstr(term)) {
00271 if (hilog_cs(term)) disp++;
00272 if (disp <= (int)get_arity(get_str_psc(term))) {
00273 return unify(CTXTc (Cell)(clref_val(term)+disp),
00274 ptoc_tag(CTXTc 3));
00275 } return FALSE;
00276 } else if (islist(term) && (disp==1 || disp==2)) {
00277 return unify(CTXTc (Cell)(clref_val(term)+disp-1),
00278 ptoc_tag(CTXTc 3));
00279 } else return FALSE;
00280 } else err(INSTANTIATION, 2, "hilog_arg", 3);
00281 } else return FALSE;
00282 } else {
00283 if (isnonvar(index))
00284 xsb_type_error(CTXTc "integer",index,"hilog_arg",3,1);
00285 else err(INSTANTIATION, 1, "hilog_arg", 3);
00286 }
00287 return TRUE;
00288 }
00289
00290 #define INITIAL_NAMELEN 256
00291
00292 inline static xsbBool atom_to_list(CTXTdeclc int call_type)
00293 {
00294
00295 int i, len;
00296 long c;
00297 char *atomname, *atomnamelast;
00298 static char *atomnameaddr = NULL;
00299 static int atomnamelen;
00300 char tmpstr[2], *tmpstr_interned;
00301 Cell heap_addr, term, term2;
00302 Cell list, new_list;
00303 CPtr top = 0;
00304 char *call_name = (call_type == ATOM_CODES ? "atom_codes" : "atom_chars");
00305 char *elt_type = (call_type == ATOM_CODES ? "ASCII code" : "character atom");
00306
00307 SYS_MUTEX_LOCK(MUTEX_ATOM_BUF);
00308
00309 term = ptoc_tag(CTXTc 1);
00310 list = ptoc_tag(CTXTc 2);
00311 if (!isnonvar(term)) {
00312 atomnameaddr = (char *)mem_alloc(INITIAL_NAMELEN,LEAK_SPACE);
00313 atomnamelen = INITIAL_NAMELEN;
00314
00315 atomname = atomnameaddr;
00316 atomnamelast = atomnameaddr + (atomnamelen - 1);
00317 term2 = list;
00318 do {
00319 XSB_Deref(term2);
00320 if (isnil(term2)) {
00321 *atomname++ = '\0';
00322 break;
00323 }
00324 if (islist(term2)) {
00325 heap_addr = cell(clref_val(term2)); XSB_Deref(heap_addr);
00326 if (((call_type==ATOM_CODES) && !isinteger(heap_addr))
00327 || ((call_type==ATOM_CHARS) && !isstring(heap_addr))) {
00328 if (isnonvar(heap_addr)) {
00329 xsb_type_error(CTXTc elt_type,list,call_name,2,2);
00330 }
00331 else err(INSTANTIATION, 2, call_name, 2);
00332 SYS_MUTEX_UNLOCK(MUTEX_ATOM_BUF);
00333 return FALSE;
00334 }
00335 if (isinteger(heap_addr))
00336 c = int_val(heap_addr);
00337 else
00338 c = *string_val(heap_addr);
00339
00340 if (c < 0 || c > 255) {
00341 err_handle(CTXTc RANGE, 2, call_name, 2, "ASCII code", heap_addr);
00342 SYS_MUTEX_UNLOCK(MUTEX_ATOM_BUF);
00343 return FALSE;
00344 }
00345 if (atomname >= atomnamelast) {
00346 atomnameaddr = (char *)mem_realloc(atomnameaddr,atomnamelen,(atomnamelen << 1),LEAK_SPACE);
00347 atomname = atomnameaddr + (atomnamelen - 1);
00348 atomnamelen = atomnamelen << 1;
00349 atomnamelast = atomnameaddr + (atomnamelen - 1);
00350
00351 }
00352 *atomname++ = (char)c;
00353 term2 = cell(clref_val(term2)+1);
00354 } else {
00355 if (isref(term2)) err(INSTANTIATION, 2, call_name, 2);
00356 else xsb_type_error(CTXTc "list",term2,call_name,2,2);
00357 SYS_MUTEX_UNLOCK(MUTEX_ATOM_BUF);
00358 return FALSE;
00359 }
00360 } while (1);
00361 bind_string((CPtr)(term), (char *)string_find((char *)atomnameaddr, 1));
00362 mem_dealloc(atomnameaddr,atomnamelen,LEAK_SPACE);
00363 SYS_MUTEX_UNLOCK(MUTEX_ATOM_BUF);
00364 return TRUE;
00365 } else {
00366 if (isstring(term)) {
00367 atomname = string_val(term);
00368 len = strlen(atomname);
00369 if (len == 0) {
00370 if (!isnonvar(list)) {
00371 bind_nil((CPtr)(list));
00372 SYS_MUTEX_UNLOCK(MUTEX_ATOM_BUF);
00373 return TRUE;
00374 }
00375 else
00376 { SYS_MUTEX_UNLOCK(MUTEX_ATOM_BUF);
00377 return isnil(list);
00378 }
00379 } else {
00380
00381 check_glstack_overflow(2, pcreg, 2*len*sizeof(Cell)) ;
00382 list = ptoc_tag(CTXTc 2);
00383
00384 new_list = makelist(hreg);
00385 for (i = 0; i < len; i++) {
00386 if (call_type==ATOM_CODES)
00387 follow(hreg++) = makeint(*(unsigned char *)atomname);
00388 else {
00389 tmpstr[0]=*atomname;
00390 tmpstr[1]='\0';
00391 tmpstr_interned=string_find(tmpstr,1);
00392 follow(hreg++) = makestring(tmpstr_interned);
00393 }
00394 atomname++;
00395 top = hreg++;
00396 follow(top) = makelist(hreg);
00397 }
00398 follow(top) = makenil;
00399 SYS_MUTEX_UNLOCK(MUTEX_ATOM_BUF);
00400 return unify(CTXTc list, new_list);
00401 }
00402 } else xsb_type_error(CTXTc "atom",term,call_name,2,1);
00403 }
00404 SYS_MUTEX_UNLOCK(MUTEX_ATOM_BUF);
00405 return TRUE;
00406 }
00407
00408 inline static xsbBool number_to_list(CTXTdeclc int call_type)
00409 {
00410 int i, tmpval;
00411 long c;
00412 char tmpstr[2], *tmpstr_interned;
00413 char str[256];
00414 int StringLoc = 0;
00415 Cell heap_addr, term, term2;
00416 Cell list, new_list;
00417 char hack_char;
00418 CPtr top = 0;
00419 char *call_name =
00420 (call_type == NUMBER_CODES ?
00421 "number_codes" : (call_type == NUMBER_DIGITS?
00422 "number_digits" : "number_chars"));
00423 char *elt_type =
00424 (call_type == NUMBER_CODES ?
00425 "integer" : (call_type == NUMBER_DIGITS? "digit" : "digit atom"));
00426
00427
00428 term = ptoc_tag(CTXTc 1);
00429 list = ptoc_tag(CTXTc 2);
00430 if (!isnonvar(term)) {
00431 term2 = list;
00432 do {
00433 XSB_Deref(term2);
00434 if (isnil(term2)) {
00435 str[StringLoc++] = '\0';
00436 break;
00437 }
00438 if (islist(term2)) {
00439 heap_addr = cell(clref_val(term2)); XSB_Deref(heap_addr);
00440 if (((call_type==NUMBER_CODES) && (!isinteger(heap_addr)))
00441 || ((call_type==NUMBER_CHARS) && !isstring(heap_addr))
00442 || ((call_type==NUMBER_DIGITS)
00443 && !isstring(heap_addr)
00444 && !isinteger(heap_addr))) {
00445 if (isnonvar(heap_addr))
00446 xsb_type_error(CTXTc elt_type,list,call_name,2,2);
00447 else err(INSTANTIATION, 2, call_name, 2);
00448 return FALSE;
00449 }
00450 if (call_type==NUMBER_CODES)
00451 c = int_val(heap_addr);
00452 else if ((call_type==NUMBER_DIGITS) && (isinteger(heap_addr))) {
00453 tmpval = int_val(heap_addr);
00454 if ((tmpval < 0) || (tmpval > 9)) {
00455 xsb_type_error(CTXTc elt_type,list,call_name,2,2);
00456 }
00457 c = (long) '0' + int_val(heap_addr);
00458 } else if (isstring(heap_addr))
00459 c = *string_val(heap_addr);
00460 else {
00461 xsb_type_error(CTXTc "integer, digit, or atom",list,call_name,2,2);
00462 }
00463
00464 if (c < 0 || c > 255) {
00465 err_handle(CTXTc RANGE, 2, call_name, 2, "ASCII code", heap_addr);
00466 return FALSE;
00467 }
00468 if (StringLoc > 200) return FALSE;
00469 str[StringLoc++] = (char)c;
00470 term2 = cell(clref_val(term2)+1);
00471 } else {
00472 if (isref(term2))
00473 err(INSTANTIATION, 2, call_name, 2);
00474 else
00475 xsb_type_error(CTXTc "list",term2,call_name,2,2);
00476 return FALSE;
00477 }
00478 } while (1);
00479
00480 if (sscanf(str, "%ld%c", &c, &hack_char) == 1) {
00481 bind_int((CPtr)(term), c);
00482 } else {
00483 Float float_temp;
00484
00485
00486 #ifndef FAST_FLOATS
00487 if (sscanf(str, "%lf%c", &float_temp, &hack_char) == 1)
00488 #else
00489 if (sscanf(str, "%f%c", &float_temp, &hack_char) == 1)
00490 #endif
00491 {
00492 bind_boxedfloat((CPtr)(term), float_temp);
00493 }
00494 else return FALSE;
00495 }
00496 } else {
00497 if (isinteger(term)) {
00498 sprintf(str, "%ld", (long)int_val(term));
00499 } else {
00500 if (isofloat(term)) {
00501 sprintf(str, "%e", ofloat_val(term));
00502 } else {
00503 if (isboxedinteger(term)) {
00504 sprintf(str,"%ld",(long)boxedint_val(term));
00505 } else {
00506 xsb_type_error(CTXTc "number",term,call_name,2,1);
00507 }
00508 }
00509 }
00510 new_list = makelist(hreg);
00511 for (i=0; str[i] != '\0'; i++) {
00512 if (call_type==NUMBER_CODES)
00513 follow(hreg++) = makeint((unsigned char)str[i]);
00514 else if (call_type==NUMBER_CHARS) {
00515 tmpstr[0] = str[i];
00516 tmpstr[1] = '\0';
00517 tmpstr_interned=string_find(tmpstr,1);
00518 follow(hreg++) = makestring(tmpstr_interned);
00519 } else {
00520 tmpval = str[i] - '0';
00521 if (0 <= tmpval && tmpval < 10)
00522 follow(hreg++) = makeint((unsigned char)str[i] - '0');
00523 else {
00524 tmpstr[0] = str[i];
00525 tmpstr[1] = '\0';
00526 tmpstr_interned=string_find(tmpstr,1);
00527 follow(hreg++) = makestring(tmpstr_interned);
00528 }
00529 }
00530 top = hreg++;
00531 follow(top) = makelist(hreg);
00532 } follow(top) = makenil;
00533 return unify(CTXTc list, new_list);
00534 }
00535 return TRUE;
00536 }
00537
00538 #ifdef MULTI_THREAD
00539
00540
00541
00542
00543
00544
00545
00546 typedef int (*compfptr)(CTXTdeclc const void *, const void *) ;
00547
00548 #define INSERT_SORT 8
00549
00550 #define QSORT_SWAP(a,b) { Cell t = *a ; *a = *b ; *b = t ; }
00551
00552 #define QSORT_LESS(A,B) ((*qsort_cmp)((CTXT),(A),(B)) < 0)
00553
00554 void qsort0(CTXTdeclc compfptr qsort_cmp, CPtr low, CPtr high )
00555 {
00556
00557
00558
00559 if ( high - low >= INSERT_SORT )
00560 {
00561 Cell pivot ;
00562 CPtr l, r ;
00563 CPtr mid = low + ( high - low ) / 2 ;
00564
00565 if ( QSORT_LESS(mid,low) )
00566 QSORT_SWAP( mid, low )
00567 if ( QSORT_LESS(high,mid) )
00568 { QSORT_SWAP( high, mid )
00569 if ( QSORT_LESS(mid,low) )
00570 QSORT_SWAP( mid, low )
00571 }
00572 pivot = *mid ;
00573
00574 l = low + 1 ;
00575 r = high - 1 ;
00576 do
00577 { while( QSORT_LESS(l, &pivot) ) l++ ;
00578 while( QSORT_LESS(&pivot, r) ) r-- ;
00579
00580 if( l < r )
00581 { QSORT_SWAP( l, r )
00582 l++; r--;
00583 }
00584 else if( l == r )
00585 { l++; r--;
00586 }
00587 } while( l <= r ) ;
00588 qsort0(CTXTc qsort_cmp, low, r) ;
00589 qsort0(CTXTc qsort_cmp, l, high) ;
00590 }
00591 else if( low < high )
00592 { CPtr p, min = low, r ;
00593
00594
00595 for( p = low + 1 ; p <= high ; p++ )
00596 if( QSORT_LESS( p, min ) )
00597 min = p ;
00598 if( low != min )
00599 QSORT_SWAP( low, min ) ;
00600
00601 for( r = low + 2 ; r <= high ; r++ )
00602 { Cell new_el = *r ;
00603
00604 for( p = r ; QSORT_LESS( &new_el, p-1 ) ; p-- )
00605 *p = *(p-1) ;
00606 *p = new_el ;
00607 }
00608 }
00609 }
00610
00611 void mt_qsort(th_context *th, CPtr v, int len, unsigned int sz, compfptr comp)
00612 {
00613 qsort0( th, comp, v, v + len - 1 ) ;
00614 }
00615 #endif
00616
00617 inline static xsbBool sort(CTXTdecl)
00618 {
00619
00620 int i, len;
00621 Cell *cell_tbl;
00622 Cell heap_addr, term, term2;
00623 Cell list, new_list;
00624 CPtr top = 0;
00625
00626 list = ptoc_tag(CTXTc 1);
00627 term2 = list; len = 0;
00628 do {
00629 XSB_Deref(term2);
00630 if (isnil(term2)) break;
00631 if (islist(term2)) {
00632 len++; term2 = cell(clref_val(term2)+1);
00633 } else {
00634 if (isref(term2)) err(INSTANTIATION, 1, "sort", 2);
00635 else xsb_type_error(CTXTc "list",list,"sort",2,1);
00636 }
00637 } while(1);
00638 check_glstack_overflow(3, pcreg, (2*len)*sizeof(Cell)) ;
00639 list = ptoc_tag(CTXTc 1);
00640 if (len > 0) {
00641 term2 = list;
00642 cell_tbl = (Cell *)mem_alloc((len * sizeof(Cell)),LEAK_SPACE);
00643 if (!cell_tbl)
00644 xsb_abort("Cannot allocate temporary memory for sort/2");
00645 for (i=0 ; i < len ; ++i) {
00646 XSB_Deref(term2);
00647 heap_addr = cell(clref_val(term2)); XSB_Deref(heap_addr);
00648 cell_tbl[i] = heap_addr;
00649 term2 = cell(clref_val(term2)+1);
00650 }
00651 #ifndef MULTI_THREAD
00652 qsort(cell_tbl, len, sizeof(Cell), compare);
00653 #else
00654 mt_qsort(CTXTc cell_tbl, len, sizeof(Cell), compare);
00655 #endif
00656 new_list = makelist(hreg);
00657 follow(hreg++) = cell_tbl[0]; top = hreg++;
00658 follow(top) = makelist(hreg);
00659 for (i=1 ; i < len ; i++) {
00660 if (compare(CTXTc (void*)cell_tbl[i], (void*)cell_tbl[i-1])) {
00661 follow(hreg++) = cell_tbl[i];
00662 top = hreg++;
00663 follow(top) = makelist(hreg);
00664 }
00665 } follow(top) = makenil;
00666 mem_dealloc(cell_tbl,len * sizeof(Cell),LEAK_SPACE);
00667 term = ptoc_tag(CTXTc 2);
00668 return unify(CTXTc new_list, term);
00669 }
00670 term = ptoc_tag(CTXTc 2);
00671 return unify(CTXTc list, term);
00672 }
00673
00674 inline static xsbBool keysort(CTXTdecl)
00675 {
00676
00677
00678 int i, len;
00679 Cell heap_addr, term, term2;
00680 Cell list, new_list;
00681 Cell *cell_tbl;
00682 CPtr top = 0;
00683
00684 list = ptoc_tag(CTXTc 1);
00685 term2 = list; len = 0;
00686 do {
00687 XSB_Deref(term2);
00688 if (isnil(term2)) break;
00689 if (islist(term2)) {
00690 heap_addr = cell(clref_val(term2)); XSB_Deref(heap_addr);
00691 if (isconstr(heap_addr) &&
00692 get_arity(get_str_psc(heap_addr)) == 2 &&
00693 !strcmp(get_name(get_str_psc(heap_addr)), "-")) {
00694 len++; term2 = cell(clref_val(term2)+1);
00695 } else {
00696 xsb_type_error(CTXTc "pair of the form Key-Value", (Cell)NULL,"keysort",2,1);
00697 }
00698 } else {
00699 if (isref(term2)) err(INSTANTIATION, 1, "keysort", 2);
00700 else err_handle(CTXTc TYPE, 1, "keysort", 2, "list", list);
00701 return FALSE;
00702 }
00703 } while(1);
00704 check_glstack_overflow(3, pcreg, (2*len)*sizeof(Cell)) ;
00705 list = ptoc_tag(CTXTc 1);
00706 term = ptoc_tag(CTXTc 2);
00707 if (len > 0) {
00708 term2 = list;
00709 cell_tbl = (Cell *)mem_alloc(len * sizeof(Cell),LEAK_SPACE);
00710 if (!cell_tbl)
00711 xsb_abort("Cannot allocate temporary memory for keysort/2");
00712 for (i=0 ; i < len ; ++i) {
00713 XSB_Deref(term2);
00714 heap_addr = cell(clref_val(term2)); XSB_Deref(heap_addr);
00715 cell_tbl[i] = heap_addr;
00716 term2 = cell(clref_val(term2)+1);
00717 }
00718 #ifndef MULTI_THREAD
00719 qsort(cell_tbl, len, sizeof(Cell), key_compare);
00720 #else
00721 mt_qsort(CTXTc cell_tbl, len, sizeof(Cell), key_compare);
00722 #endif
00723 new_list = makelist(hreg);
00724 for (i=0 ; i < len ; i++) {
00725 follow(hreg++) = cell_tbl[i];
00726 top = hreg++;
00727 follow(top) = makelist(hreg);
00728 } follow(top) = makenil;
00729 mem_dealloc(cell_tbl,len * sizeof(Cell),LEAK_SPACE);
00730 return unify(CTXTc new_list, term);
00731 }
00732 return unify(CTXTc list, term);
00733 }
00734
00735 #ifndef MULTI_THREAD
00736 struct sort_par_spec par_spec;
00737 #endif
00738
00739 int par_key_compare(CTXTdeclc const void * t1, const void * t2) {
00740 long ipar, cmp, ind1, ind2;
00741 Cell term1 = (Cell) t1 ;
00742 Cell term2 = (Cell) t2 ;
00743
00744 XSB_Deref(term1);
00745 XSB_Deref(term2);
00746 if (par_spec.sort_num_pars > 0) {
00747 ipar = 0;
00748 while (ipar < par_spec.sort_num_pars) {
00749 ind1 = ind2 = par_spec.sort_par_ind[ipar];
00750 if (islist(term1)) ind1--;
00751 if (islist(term2)) ind2--;
00752 cmp = compare(CTXTc (void*)cell(clref_val(term1)+ind1),
00753 (void*)cell(clref_val(term2)+ind2));
00754 if (cmp) {
00755 if (par_spec.sort_par_dir[ipar]) return cmp;
00756 else return -cmp;
00757 } else ipar++;
00758 }
00759 return 0;
00760 } else if (par_spec.sort_num_pars == 0) {
00761 return compare(CTXTc (void*)term1, (void*)term2);
00762 } else
00763 return -compare(CTXTc (void*)term1, (void*)term2);
00764 }
00765
00766 inline static xsbBool parsort(CTXTdecl)
00767 {
00768
00769
00770
00771
00772 int i, len;
00773 int max_ind = 0, elim_dupls;
00774 Cell heap_addr, term, term2, tmp_ind;
00775 Cell list, new_list;
00776 Cell *cell_tbl;
00777 CPtr top = 0;
00778 char ermsg[50];
00779
00780 elim_dupls = ptoc_int(CTXTc 3);
00781
00782 list = ptoc_tag(CTXTc 2);
00783 term2 = list; par_spec.sort_num_pars = 0;
00784
00785 XSB_Deref(term2);
00786 if (isstring(term2) && !strcmp(string_val(term2),"asc")) par_spec.sort_num_pars = 0;
00787 else if (isstring(term2) && !strcmp(string_val(term2),"desc")) par_spec.sort_num_pars = -1;
00788 else
00789 while (TRUE) {
00790 if (isnil(term2)) break;
00791 if (islist(term2)) {
00792 heap_addr = cell(clref_val(term2)); XSB_Deref(heap_addr);
00793 if (isconstr(heap_addr) &&
00794 get_arity(get_str_psc(heap_addr)) == 1 &&
00795 !strcmp(get_name(get_str_psc(heap_addr)),"asc")) {
00796 par_spec.sort_par_dir[par_spec.sort_num_pars] = 1;
00797 } else if (isconstr(heap_addr) &&
00798 get_arity(get_str_psc(heap_addr)) == 1 &&
00799 !strcmp(get_name(get_str_psc(heap_addr)),"desc")) {
00800 par_spec.sort_par_dir[par_spec.sort_num_pars] = 0;
00801 } else xsb_type_error(CTXTc "asc/1 or desc/1 term",heap_addr,"parsort",4,2);
00802 tmp_ind = cell(clref_val(heap_addr)+1); XSB_Deref(tmp_ind);
00803 if (!isinteger(tmp_ind)) xsb_type_error(CTXTc "integer arg for asc/1 or desc/1",tmp_ind,"parsort",4,2);
00804 i = int_val(tmp_ind);
00805
00806 if (i < 1 || i > 255) err_handle(CTXTc TYPE,2,"parsort",4,"arity-sized integer",tmp_ind);
00807 par_spec.sort_par_ind[par_spec.sort_num_pars] = i;
00808 if (i > max_ind) max_ind = i;
00809 par_spec.sort_num_pars++;
00810 term2 = cell(clref_val(term2)+1);
00811 XSB_Deref(term2);
00812 } else xsb_type_error(CTXTc "list",list,"parsort",4,2);
00813 }
00814
00815 list = ptoc_tag(CTXTc 1);
00816 term2 = list; len = 0;
00817 do {
00818 XSB_Deref(term2);
00819 if (isnil(term2)) break;
00820 if (islist(term2)) {
00821 heap_addr = cell(clref_val(term2)); XSB_Deref(heap_addr);
00822 if (par_spec.sort_num_pars <= 0 ||
00823 (isconstr(heap_addr) && (get_arity(get_str_psc(heap_addr)) >= max_ind)) ||
00824 (islist(heap_addr) && max_ind <=2)) {
00825 len++; term2 = cell(clref_val(term2)+1);
00826 } else {
00827 sprintf(ermsg,"Term with arity at least %d", max_ind);
00828 err_handle(CTXTc TYPE, 1, "parsort", 4, ermsg, (Cell)heap_addr);
00829 return FALSE;
00830 }
00831 } else {
00832 if (isref(term2)) err(INSTANTIATION, 1, "parsort", 4);
00833 else err_handle(CTXTc TYPE, 1, "parsort", 4, "list", list);
00834 return FALSE;
00835 }
00836 } while(1);
00837
00838 check_glstack_overflow(4, pcreg, (2*len)*sizeof(Cell)) ;
00839 list = ptoc_tag(CTXTc 1);
00840 term = ptoc_tag(CTXTc 4);
00841 if (len > 0) {
00842 term2 = list;
00843 cell_tbl = (Cell *)mem_alloc(len * sizeof(Cell),LEAK_SPACE);
00844 if (!cell_tbl)
00845 xsb_abort("Cannot allocate temporary memory for parsort/4");
00846 for (i=0 ; i < len ; ++i) {
00847 XSB_Deref(term2);
00848 heap_addr = cell(clref_val(term2)); XSB_Deref(heap_addr);
00849 cell_tbl[i] = heap_addr;
00850 term2 = cell(clref_val(term2)+1);
00851 }
00852 #ifndef MULTI_THREAD
00853 qsort(cell_tbl, len, sizeof(Cell), par_key_compare);
00854 #else
00855 mt_qsort(CTXTc cell_tbl, len, sizeof(Cell), par_key_compare);
00856 #endif
00857 new_list = makelist(hreg);
00858 if (elim_dupls) {
00859 follow(hreg++) = cell_tbl[0]; top = hreg++;
00860 follow(top) = makelist(hreg);
00861 for (i=1 ; i < len ; i++) {
00862 if (compare(CTXTc (void*)cell_tbl[i], (void*)cell_tbl[i-1])) {
00863 follow(hreg++) = cell_tbl[i];
00864 top = hreg++;
00865 follow(top) = makelist(hreg);
00866 }
00867 }
00868 } else {
00869 for (i=0 ; i < len ; i++) {
00870 follow(hreg++) = cell_tbl[i];
00871 top = hreg++;
00872 follow(top) = makelist(hreg);
00873 }
00874 }
00875 follow(top) = makenil;
00876 mem_dealloc(cell_tbl,len * sizeof(Cell),LEAK_SPACE);
00877 return unify(CTXTc new_list, term);
00878 }
00879 return unify(CTXTc list, term);
00880 }
00881
00882
00883 static inline xsbBool not_occurs_in(Cell Var, Cell Term) {
00884 XSB_Deref(Term);
00885
00886 switch (cell_tag(Term)) {
00887 case XSB_ATTV:
00888 case XSB_REF:
00889 case XSB_REF1: {
00890 if (Var == Term) return FALSE; else return TRUE;
00891 }
00892 case XSB_INT:
00893 case XSB_STRING:
00894 case XSB_FLOAT: {
00895 return TRUE;
00896 }
00897 case XSB_LIST: {
00898 return (not_occurs_in(Var,Term +1)
00899 & not_occurs_in(Var, Term + 2));
00900 }
00901 case XSB_STRUCT: {
00902 xsbBool Res = TRUE;
00903 int i;
00904 CPtr arg;
00905
00906 for (i = 1; i <= get_arity(get_str_psc(Term)); i++) {
00907 arg = clref_val(Term) + i;
00908
00909 Res = Res & not_occurs_in(Var,(Cell) (clref_val(Term) +i));
00910
00911 }
00912 return Res;
00913 }
00914 }
00915 return TRUE;
00916 }
00917
00918 xsbBool unify_with_occurs_check(CTXTdeclc Cell Term1, Cell Term2) {
00919
00920 xsbBool Res = TRUE;
00921
00922 XSB_Deref(Term1);
00923 XSB_Deref(Term2);
00924 switch (cell_tag(Term1)) {
00925 case XSB_ATTV:
00926 case XSB_REF:
00927 case XSB_REF1: {
00928 if (isnonvar(Term2)) {
00929 if (not_occurs_in(Term1,Term2))
00930 return unify(CTXTc Term1,Term2);
00931 else return FALSE;
00932 } else
00933 return (int) unify(CTXTc Term1,Term2);
00934 }
00935 case XSB_INT:
00936 case XSB_STRING:
00937 case XSB_FLOAT:
00938 return unify(CTXTc Term1,Term2);
00939 case XSB_LIST:
00940 case XSB_STRUCT: {
00941
00942
00943 switch (cell_tag(Term2)) {
00944 case XSB_ATTV:
00945 case XSB_REF:
00946 case XSB_REF1:
00947 if (not_occurs_in(Term2,Term1))
00948 return unify(CTXTc Term1,Term2);
00949 else return FALSE;
00950 case XSB_LIST:
00951 case XSB_STRUCT: {
00952 int i;
00953 int arity = get_arity(get_str_psc(Term1));
00954 if (arity == get_arity(get_str_psc(Term2))) {
00955 for (i = 1; i <= arity; i++) {
00956
00957 Res = Res & unify_with_occurs_check(CTXTc (Cell) (clref_val(Term1) + i),
00958 (Cell) (clref_val(Term2) + i));
00959
00960 }
00961 return Res;
00962 }
00963 else return FALSE;
00964 }
00965 }
00966
00967
00968
00969 }
00970 }
00971 return TRUE;
00972 }
00973