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 #include "xsb_config.h"
00027 #include "xsb_debug.h"
00028
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include <stdlib.h>
00032 #if !defined(WIN_NT) || defined(CYGWIN)
00033 #include <unistd.h>
00034 #endif
00035 #include <errno.h>
00036
00037 #include "auxlry.h"
00038 #include "cell_xsb.h"
00039 #include "memory_xsb.h"
00040 #include "register.h"
00041 #include "psc_xsb.h"
00042 #include "flags_xsb.h"
00043 #include "deref.h"
00044 #include "heap_xsb.h"
00045 #include "binding.h"
00046 #include "tries.h"
00047 #include "choice.h"
00048 #include "subp.h"
00049 #include "emuloop.h"
00050 #include "cinterf.h"
00051 #include "error_xsb.h"
00052 #include "orient_xsb.h"
00053 #include "loader_xsb.h"
00054 #include "context.h"
00055
00056
00057
00058
00059
00060 #define PRINTABLE_OR_ESCAPED_CHAR(Ch) \
00061 ((Ch >= (int)' ' && Ch <= (int)'~') || (Ch >= (int)'\a' && Ch <= (int)'\r'))
00062
00063
00064 extern char *expand_filename(char *);
00065 extern void xsb_sprint_variable(CTXTdeclc char *sptr, CPtr var);
00066
00067
00068 char *p_charlist_to_c_string(CTXTdeclc prolog_term term, VarString *buf,
00069 char *in_func, char *where);
00070 void c_string_to_p_charlist(CTXTdeclc char *name, prolog_term list,
00071 int regs_to_protect, char *in_func, char *where);
00072
00073
00074
00075
00076
00077 DllExport xsbBool call_conv is_var(prolog_term term)
00078 {
00079 Cell t = (Cell)term;
00080 XSB_Deref(t);
00081 return isref(t);
00082 }
00083
00084 DllExport xsbBool call_conv is_int(prolog_term term)
00085 {
00086 Cell t = (Cell)term;
00087 XSB_Deref(t);
00088 return (isinteger(t) | isboxedinteger(t));
00089 }
00090
00091 DllExport xsbBool call_conv is_float(prolog_term term)
00092 {
00093 Cell t = (Cell)term;
00094 XSB_Deref(t);
00095 return isofloat(t);
00096 }
00097
00098 DllExport xsbBool call_conv is_string(prolog_term term)
00099 {
00100 Cell t = (Cell)term;
00101 XSB_Deref(t);
00102 return isstring(t);
00103 }
00104
00105 DllExport xsbBool call_conv is_atom(prolog_term term)
00106 {
00107 Cell t = (Cell)term;
00108 XSB_Deref(t);
00109 return isatom(t);
00110 }
00111
00112 DllExport xsbBool call_conv is_list(prolog_term term)
00113 {
00114 Cell t = (Cell)term;
00115 XSB_Deref(t);
00116 return islist(t);
00117 }
00118
00119 DllExport xsbBool call_conv is_nil(prolog_term term)
00120 {
00121 Cell t = (Cell)term;
00122 XSB_Deref(t);
00123 return isnil(t);
00124 }
00125
00126 DllExport xsbBool call_conv is_functor(prolog_term term)
00127 {
00128 Cell t = (Cell)term;
00129 XSB_Deref(t);
00130 return isconstr(t);
00131 }
00132
00133 DllExport xsbBool call_conv is_attv(prolog_term term)
00134 {
00135 Cell t = (Cell)term;
00136 XSB_Deref(t);
00137 return isattv(t);
00138 }
00139
00140 DllExport prolog_term call_conv reg_term(CTXTdeclc reg_num regnum)
00141 {
00142 register Cell addr;
00143
00144 addr = cell(reg+regnum);
00145 XSB_Deref(addr);
00146 return (prolog_term)addr;
00147 }
00148
00149 DllExport xsbBool call_conv c2p_int(CTXTdeclc Integer val, prolog_term var)
00150 {
00151 Cell v = (Cell)var;
00152 if (is_var(v)) {
00153 bind_oint(vptr(v), val);
00154 return TRUE;
00155 } else {
00156 xsb_warn("[C2P_INT] Argument 2 must be a variable");
00157 return FALSE;
00158 }
00159 }
00160
00161 DllExport xsbBool call_conv c2p_float(CTXTdeclc double val, prolog_term var)
00162 {
00163 Cell v = (Cell)var;
00164 if (is_var(v)) {
00165 bind_boxedfloat(vptr(v), (Float)(val));
00166 return TRUE;
00167 } else {
00168 xsb_warn("[C2P_FLOAT] Argument 2 must be a variable");
00169 return FALSE;
00170 }
00171 }
00172
00173 DllExport xsbBool call_conv c2p_string(CTXTdeclc char *val, prolog_term var)
00174 {
00175 Cell v = (Cell)var;
00176 if (is_var(v)) {
00177 bind_string(vptr(v), (char *)string_find(val, 1));
00178 return TRUE;
00179 } else {
00180 xsb_warn("[C2P_STRING] Argument 2 must be a variable");
00181 return FALSE;
00182 }
00183 }
00184
00185 DllExport xsbBool call_conv c2p_list(CTXTdeclc prolog_term var)
00186 {
00187 Cell v = (Cell)var;
00188 if (is_var(v)) {
00189 sreg = hreg;
00190 new_heap_free(hreg);
00191 new_heap_free(hreg);
00192 bind_list(vptr(v), sreg);
00193 return TRUE;
00194 } else {
00195 xsb_warn("[C2P_LIST] Argument must be a variable");
00196 return FALSE;
00197 }
00198 }
00199
00200 DllExport xsbBool call_conv c2p_nil(CTXTdeclc prolog_term var)
00201 {
00202 Cell v = (Cell)var;
00203 if (is_var(v)) {
00204 bind_nil(vptr(v));
00205 return TRUE;
00206 } else {
00207 xsb_warn("[C2P_NIL] Argument must be a variable");
00208 return FALSE;
00209 }
00210 }
00211
00212 DllExport void call_conv c2p_setfree(prolog_term var)
00213 {
00214 CPtr v = (CPtr)var;
00215 bld_free(v);
00216 }
00217
00218
00219 DllExport void call_conv ensure_heap_space(CTXTdeclc int space, int regcnt) {
00220 check_glstack_overflow(regcnt,pcreg,space);
00221 }
00222
00223 DllExport xsbBool call_conv c2p_functor(CTXTdeclc char *functor, int arity,
00224 prolog_term var)
00225 {
00226 Cell v = (Cell)var;
00227 Pair sym;
00228 int i;
00229 if (is_var(v)) {
00230 sym = (Pair)insert(functor, (byte)arity, (Psc)flags[CURRENT_MODULE], &i);
00231 sreg = hreg;
00232 hreg += arity + 1;
00233 bind_cs(vptr(v), sreg);
00234 new_heap_functor(sreg, sym->psc_ptr);
00235 for (i=0; i<arity; sreg++,i++) { bld_free(sreg); }
00236 return TRUE;
00237 } else {
00238 xsb_warn("[C2P_FUNCTOR] Argument 3 must be a variable");
00239 return FALSE;
00240 }
00241 }
00242
00243 DllExport Integer call_conv p2c_int(prolog_term term)
00244 {
00245 Cell t = (Cell)term;
00246 return oint_val(t);
00247 }
00248
00249 DllExport double call_conv p2c_float(prolog_term term)
00250 {
00251 Cell t = (Cell)term;
00252 return (double)(ofloat_val(t));
00253 }
00254
00255 DllExport char* call_conv p2c_string(prolog_term term)
00256 {
00257 Cell t = (Cell)term;
00258 return string_val(t);
00259 }
00260
00261 DllExport char* call_conv p2c_functor(prolog_term term)
00262 {
00263 Cell t = (Cell)term;
00264 return get_name(get_str_psc(t));
00265 }
00266
00267 DllExport int call_conv p2c_arity(prolog_term term)
00268 {
00269 Cell t = (Cell)term;
00270 return get_arity(get_str_psc(t));
00271 }
00272
00273 DllExport prolog_term call_conv p2p_arg(prolog_term term, int argno)
00274 {
00275 Cell t = (Cell)term;
00276 XSB_Deref(t);
00277 t = cell(clref_val(t)+argno);
00278 XSB_Deref(t);
00279 return (prolog_term)t;
00280 }
00281
00282 DllExport prolog_term call_conv p2p_car(prolog_term term)
00283 {
00284 Cell t = (Cell)term;
00285 XSB_Deref(t);
00286 t = cell(clref_val(t));
00287 XSB_Deref(t);
00288 return (prolog_term)t;
00289 }
00290
00291 DllExport prolog_term call_conv p2p_cdr(prolog_term term)
00292 {
00293 Cell t = (Cell)term;
00294 XSB_Deref(t);
00295 t = cell(clref_val(t)+1);
00296 XSB_Deref(t);
00297 return (prolog_term)t;
00298 }
00299
00300 DllExport prolog_term call_conv p2p_new(CTXTdecl)
00301 {
00302 CPtr t = hreg;
00303 new_heap_free(hreg);
00304 return (prolog_term)(cell(t));
00305 }
00306
00307 DllExport xsbBool call_conv p2p_unify(CTXTdeclc prolog_term term1, prolog_term term2)
00308 {
00309 return unify(CTXTc term1, term2);
00310 }
00311
00312 DllExport prolog_term call_conv p2p_deref(prolog_term term)
00313 {
00314 Cell t = (Cell)term;
00315 XSB_Deref(t);
00316 return (prolog_term)t;
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 char *p_charlist_to_c_string(CTXTdeclc prolog_term term, VarString *buf,
00332 char *in_func, char *where)
00333 {
00334 Integer head_val;
00335 char head_char[1];
00336 int escape_mode=FALSE;
00337 prolog_term list = term, list_head;
00338
00339 if (!is_list(list) && !is_nil(list)) {
00340 xsb_abort("[%s] %s is not a list of characters", in_func, where);
00341 }
00342
00343 XSB_StrSet(buf, "");
00344
00345 while (is_list(list)) {
00346 if (is_nil(list)) break;
00347 list_head = p2p_car(list);
00348 if (!is_int(list_head)) {
00349 xsb_abort("[%s] A Prolog string (a character list) expected, %s",
00350 in_func, where);
00351 }
00352 head_val = int_val(list_head);
00353 if (! PRINTABLE_OR_ESCAPED_CHAR(head_val) ) {
00354 xsb_abort("[%s] A Prolog string (a character list) expected, %s",
00355 in_func, where);
00356 }
00357
00358 *head_char = (char) head_val;
00359
00360 if (escape_mode)
00361 switch (*head_char) {
00362 case 'a':
00363 XSB_StrAppendBlk(buf, "\a", 1);
00364 break;
00365 case 'b':
00366 XSB_StrAppendBlk(buf, "\b", 1);
00367 break;
00368 case 'f':
00369 XSB_StrAppendBlk(buf, "\f", 1);
00370 break;
00371 case 'n':
00372 XSB_StrAppendBlk(buf, "\n", 1);
00373 break;
00374 case 'r':
00375 XSB_StrAppendBlk(buf, "\r", 1);
00376 break;
00377 case 't':
00378 XSB_StrAppendBlk(buf, "\t", 1);
00379 break;
00380 case 'v':
00381 XSB_StrAppendBlk(buf, "\v", 1);
00382 break;
00383 default:
00384 XSB_StrAppendBlk(buf, head_char, 1);
00385 }
00386 else
00387 XSB_StrAppendBlk(buf, head_char, 1);
00388
00389 if (*head_char == '\\' && !escape_mode) {
00390 escape_mode = TRUE;
00391 buf->length--;
00392 }
00393 else {
00394 escape_mode = FALSE;
00395 }
00396 list = p2p_cdr(list);
00397 }
00398
00399 XSB_StrNullTerminate(buf);
00400
00401 return (buf->string);
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 void c_string_to_p_charlist(CTXTdeclc char *name, prolog_term list,
00413 int regs_to_protect, char *in_func, char *where)
00414 {
00415 Cell new_list;
00416 CPtr top = 0;
00417 int len=strlen(name), i;
00418
00419 if (isnonvar(list)) {
00420 xsb_abort("[%s] A variable expected, %s", in_func, where);
00421 }
00422 if (len == 0) {
00423 bind_nil((CPtr)(list));
00424 } else {
00425 check_glstack_overflow(regs_to_protect, pcreg, 2*len*sizeof(Cell));
00426 new_list = makelist(hreg);
00427 for (i = 0; i < len; i++) {
00428 follow(hreg++) = makeint(*(unsigned char *)name);
00429 name++;
00430 top = hreg++;
00431 follow(top) = makelist(hreg);
00432 } follow(top) = makenil;
00433 unify(CTXTc list, new_list);
00434 }
00435 }
00436
00437
00438
00439
00440
00441
00442
00443
00444 DllExport xsbBool call_conv is_charlist(prolog_term term, int *size)
00445 {
00446 int escape_mode=FALSE, head_char;
00447 prolog_term list, head;
00448
00449 list = term;
00450 *size = 0;
00451
00452
00453 if(is_nil(list))
00454 return TRUE;
00455
00456 if (!is_list(list))
00457 return FALSE;
00458
00459 while (is_list(list)) {
00460 if (is_nil(list)) break;
00461
00462 head = p2p_car(list);
00463 if (!is_int(head))
00464 return FALSE;
00465
00466 head_char = (char) int_val(head);
00467
00468 if (! PRINTABLE_OR_ESCAPED_CHAR(head_char) )
00469 return FALSE;
00470
00471 if (escape_mode)
00472 switch (head_char) {
00473 case 'a':
00474 case 'b':
00475 case 'f':
00476 case 'n':
00477 case 'r':
00478 case 't':
00479 case 'v':
00480 (*size)++;
00481 escape_mode=FALSE;
00482 break;
00483 default:
00484 (*size) += 2;
00485 }
00486 else
00487 if (head_char == '\\')
00488 escape_mode = TRUE;
00489 else
00490 (*size)++;
00491 list = p2p_cdr(list);
00492 }
00493 return TRUE;
00494 }
00495
00496
00497
00498
00499
00500 DllExport char *call_conv p2c_chars(CTXTdeclc prolog_term term, char *buf, int bsize)
00501 {
00502 XSB_StrDefine(bufvar);
00503
00504 p_charlist_to_c_string(CTXTc term, &bufvar, "p2c_chars", "list -> char*");
00505
00506 if (strlen(bufvar.string) > (size_t) bsize) {
00507 xsb_abort("Buffer overflow in p2c_chars");
00508 }
00509
00510 return strcpy(buf,bufvar.string);
00511 }
00512
00513 DllExport void call_conv c2p_chars(CTXTdeclc char *str, int regs_to_protect, prolog_term term)
00514 {
00515 c_string_to_p_charlist(CTXTc str,term,regs_to_protect,"c2p_chars", "char* -> list");
00516 }
00517
00518
00519
00520
00521
00522
00523
00524 #include "setjmp_xsb.h"
00525
00526 static char *c_dataptr_rest;
00527
00528 #ifndef MULTI_THREAD
00529 static jmp_buf cinterf_env;
00530 #endif
00531
00532
00533
00534
00535
00536
00537 static void cppc_error(CTXTdeclc int num)
00538 {
00539 longjmp(cinterf_env, num);
00540 }
00541
00542
00543
00544
00545
00546
00547 static char *skip_subfmt(CTXTdeclc char *ptr, char quote)
00548 {
00549 while (*ptr) {
00550 if (*ptr == quote) return ++ptr;
00551 else if (*ptr == '[') ptr = skip_subfmt(CTXTc ++ptr, ']');
00552 else if (*ptr == '(') ptr = skip_subfmt(CTXTc ++ptr, ')');
00553 else ptr++;
00554 }
00555 cppc_error(CTXTc 6);
00556 return ptr;
00557 }
00558
00559
00560
00561
00562
00563
00564
00565 static int count_arity(CTXTdeclc char *ptr, int quote)
00566 {
00567 int arity = 0;
00568
00569 while (*ptr && arity <= MAX_ARITY) {
00570 if (*ptr == quote) return arity;
00571 else if (*ptr == '%') {
00572 if (*(++ptr)!='*') arity++;
00573 } else if (*ptr == '[') ptr = skip_subfmt(CTXTc ++ptr, ']');
00574 else if (*ptr == '(') ptr = skip_subfmt(CTXTc ++ptr, ')');
00575 else ptr++;
00576 }
00577 cppc_error(CTXTc 5);
00578 return -1;
00579 }
00580
00581
00582
00583
00584
00585
00586
00587
00588 static int count_fields(CTXTdeclc char *ptr, int quote)
00589 {
00590 int fields = 0;
00591
00592 while (*ptr && fields <= MAX_ARITY) {
00593 if (*ptr == quote) return fields;
00594 else if (*ptr == '%') { fields++; ptr++; }
00595 else if (*ptr == '[') ptr = skip_subfmt(CTXTc ++ptr, ']');
00596 else if (*ptr == '(') ptr = skip_subfmt(CTXTc ++ptr, ')');
00597 else ptr++;
00598 }
00599 cppc_error(CTXTc 5);
00600 return -1;
00601 }
00602
00603
00604
00605
00606
00607
00608
00609 static int count_csize(CTXTdeclc char *ptr, int quote)
00610 {
00611 int size = 0;
00612
00613 while (*ptr) {
00614 if (*ptr == quote) return size;
00615 else if (*ptr == '%') {
00616 if (*(++ptr)=='*') ptr++;
00617 switch (*ptr) {
00618 case 'f': size += sizeof(float); ptr++; break;
00619 case 'd': size += sizeof(double); ptr++; break;
00620 case 'i': size += sizeof(int); ptr++; break;
00621 case 'c': size += 1; ptr++; break;
00622 case 's': size += sizeof(char *); ptr++; break;
00623 case 'z': ptr++; size += 4 * (*ptr-'0'); ptr++; break;
00624 case 't': size += sizeof(int *);
00625 ptr += 2;
00626 skip_subfmt(CTXTc ptr, ')');
00627 break;
00628 case 'l': size += sizeof(int *);
00629 ptr += 2;
00630 skip_subfmt(CTXTc ptr, ')');
00631 break;
00632 case '[':
00633 size += count_csize(CTXTc ++ptr, ']');
00634 skip_subfmt(CTXTc ptr, ']');
00635 break;
00636 case '0':
00637 case '1':
00638 case '2':
00639 case '3':
00640 case '4':
00641 case '5':
00642 case '6':
00643 case '7':
00644 case '8':
00645 case '9':
00646 size += sizeof(int *); ptr++; break;
00647 default: cppc_error(CTXTc 7); break;
00648 }
00649 }
00650 }
00651 cppc_error(CTXTc 8);
00652 return -1;
00653 }
00654
00655
00656
00657
00658
00659
00660 static char *ctop_term0(CTXTdeclc char *ptr, char *c_dataptr, char **subformat,
00661 prolog_term variable, int ignore)
00662 {
00663 char ch;
00664 int fmtnum;
00665 char *cdptr2;
00666 int argno, fields, i;
00667 int ignore1;
00668
00669 if (*ptr++!= '%') cppc_error(CTXTc 1);
00670 ch = *ptr++;
00671 if (ch=='*') ch = *ptr++;
00672 switch (ch) {
00673 case 'i':
00674
00675 if (!ignore) c2p_int(CTXTc *((int *)(c_dataptr)), variable);
00676 c_dataptr_rest = c_dataptr + sizeof(int);
00677 break;
00678
00679 case 'c':
00680
00681 if (!ignore) c2p_int(CTXTc (int)(*(char *)(c_dataptr)), variable);
00682 c_dataptr_rest = c_dataptr + 1;
00683 break;
00684
00685 case 's':
00686
00687 if (!ignore) c2p_string(CTXTc *(char **)(c_dataptr), variable);
00688 c_dataptr_rest = c_dataptr + sizeof(char*);
00689 break;
00690
00691 case 'z':
00692
00693 if (!ignore) c2p_string(CTXTc c_dataptr, variable);
00694 ch = *ptr++;
00695 c_dataptr_rest = c_dataptr + (ch -'0')*4;
00696 break;
00697
00698 case 'f':
00699
00700 if (!ignore) c2p_float(CTXTc (double)(*((float *)(c_dataptr))), variable);
00701 c_dataptr_rest = c_dataptr + sizeof(float);
00702 break;
00703
00704 case 'd':
00705
00706 if (!ignore) c2p_float(CTXTc *((double *)(c_dataptr)), variable);
00707 c_dataptr_rest = c_dataptr + sizeof(double);
00708 break;
00709
00710 case '[':
00711
00712 fields = count_fields(CTXTc ptr, ']');
00713 if (!ignore) {
00714 argno = count_arity(CTXTc ptr, ']');
00715 if (!is_functor(variable)) c2p_functor(CTXTc "c2p", argno, variable);
00716 }
00717 argno = 0;
00718 for (i = 1; i <= fields; i++) {
00719 if (*(ptr+1)=='*') ignore1 = 1;
00720 else { ignore1 = ignore; argno++; }
00721 ptr = ctop_term0(CTXTc ptr,c_dataptr,subformat,p2p_arg(variable,argno),ignore1);
00722 c_dataptr = c_dataptr_rest;
00723 }
00724 ptr = skip_subfmt(CTXTc ptr, ']');
00725 break;
00726
00727 case 't':
00728
00729 if (!ignore) {
00730 if (*(char **)(c_dataptr)) {
00731 fmtnum = (int)(*ptr-'0');
00732 subformat[fmtnum] = ptr-2;
00733 ptr++;
00734 if (*(ptr++) !='(') cppc_error(CTXTc 2);
00735 argno = count_arity(CTXTc ptr, ')');
00736 fields = count_fields(CTXTc ptr, ')');
00737 if (!is_functor(variable)) c2p_functor(CTXTc "c2p", argno, variable);
00738 cdptr2 = * (char **)(c_dataptr);
00739 argno = 0;
00740 for (i = 1; i <= fields; i++) {
00741 if (*(ptr+1)=='*') ignore = 1;
00742 else { ignore = 0; argno++; }
00743 ptr = ctop_term0(CTXTc ptr,cdptr2,subformat,p2p_arg(variable,argno),ignore);
00744 cdptr2 = c_dataptr_rest;
00745 }
00746 } else c2p_nil(CTXTc variable);
00747 }
00748 ptr = skip_subfmt(CTXTc ptr, ')');
00749 c_dataptr_rest = c_dataptr + 4;
00750 break;
00751
00752 case 'l':
00753 if (!ignore) {
00754 if (*(char **)(c_dataptr)) {
00755 fmtnum = (int)(*ptr-'0');
00756 subformat[fmtnum] = ptr-2;
00757 ptr++;
00758 if (*(ptr++) != '(') cppc_error(CTXTc 3);
00759 argno = count_arity(CTXTc ptr, ')');
00760 fields = count_fields(CTXTc ptr, ')');
00761 if (!is_list(variable)) c2p_list(CTXTc variable);
00762 cdptr2 = * (char **)(c_dataptr);
00763 argno = 0;
00764 for (i = 1; i <= fields; i++) {
00765 if (*(ptr+1)=='*') ignore = 1;
00766 else { ignore = 0; argno++; }
00767 if (argno==1)
00768 ptr = ctop_term0(CTXTc ptr,cdptr2,subformat,p2p_car(variable),ignore);
00769 else if (argno==2)
00770 ptr = ctop_term0(CTXTc ptr,cdptr2,subformat,p2p_cdr(variable),ignore);
00771 else if (argno==0)
00772 ptr = ctop_term0(CTXTc ptr,cdptr2,subformat,p2p_car(variable),ignore);
00773
00774 else cppc_error(CTXTc 30);
00775 cdptr2 = c_dataptr_rest;
00776 }
00777 } else c2p_nil(CTXTc variable);
00778 }
00779 ptr = skip_subfmt(CTXTc ptr, ')');
00780 c_dataptr_rest = c_dataptr + 4;
00781 break;
00782
00783 case '0':
00784 case '1':
00785 case '2':
00786 case '3':
00787 case '4':
00788 case '5':
00789 case '6':
00790 case '7':
00791 case '8':
00792 case '9':
00793
00794 if (!ignore) {
00795 if (*(char **)(c_dataptr)) {
00796 ctop_term0(CTXTc subformat[ch-'0'], c_dataptr, subformat,variable, 0);
00797 } else c2p_nil(CTXTc variable);
00798 }
00799 c_dataptr_rest = c_dataptr + 4;
00800 break;
00801
00802 default: cppc_error(CTXTc 4);
00803 }
00804 return ptr;
00805 }
00806
00807
00808
00809
00810
00811
00812 static char *ptoc_term0(CTXTdeclc char *ptr, char *c_dataptr, char **subformat,
00813 prolog_term variable, int ignore)
00814 {
00815 char ch;
00816 int fmtnum;
00817 char *cdptr2;
00818 int argno, fields, i, size;
00819 int ignore1;
00820
00821 if (*ptr++!= '%') cppc_error(CTXTc 9);
00822 ch = *ptr++;
00823 if (ch=='*') ch = *ptr++;
00824 switch (ch) {
00825 case 'i':
00826
00827 if (!ignore) {
00828 if (is_int(variable)) *((int *)(c_dataptr)) = p2c_int(variable);
00829 else cppc_error(CTXTc 10);
00830 }
00831 c_dataptr_rest = c_dataptr + sizeof(int);
00832 break;
00833
00834 case 'c':
00835
00836 if (!ignore) {
00837 if (is_int(variable)) *((char *)(c_dataptr)) =
00838 (char)p2c_int(variable);
00839 else cppc_error(CTXTc 11);
00840 }
00841 c_dataptr_rest = c_dataptr + 1;
00842 break;
00843
00844 case 's':
00845
00846 if (!ignore) {
00847 if (is_string(variable)) *((char **)(c_dataptr)) =
00848 p2c_string(variable);
00849 else cppc_error(CTXTc 12);
00850 }
00851 c_dataptr_rest = c_dataptr + 4;
00852 break;
00853
00854 case 'z':
00855
00856 ch = *ptr++;
00857 size = 4 * (ch - '0');
00858 if (!ignore) {
00859 if (is_string(variable))
00860 strncpy(c_dataptr, p2c_string(variable), size);
00861 else cppc_error(CTXTc 12);
00862 }
00863 c_dataptr_rest = c_dataptr + size;
00864 break;
00865
00866 case 'f':
00867
00868 if (!ignore) {
00869 if (is_float(variable))
00870 *((float *)(c_dataptr)) = (float)p2c_float(variable);
00871 else cppc_error(CTXTc 13);
00872 }
00873 c_dataptr_rest = c_dataptr + sizeof(float);
00874 break;
00875
00876 case 'd':
00877
00878 if (!ignore) {
00879 if (is_float(variable)) *((double *)(c_dataptr)) =
00880 p2c_float(variable);
00881 else cppc_error(CTXTc 14);
00882 }
00883 c_dataptr_rest = c_dataptr + sizeof(double);
00884 break;
00885
00886 case '[':
00887
00888 fields = count_fields(CTXTc ptr, ']');
00889 argno = 0;
00890 for (i = 1; i <= fields; i++) {
00891 if (*(ptr+1)=='*') ignore1 = 1;
00892 else { ignore1 = ignore; argno++; }
00893 ptr = ptoc_term0(CTXTc ptr, c_dataptr,subformat,p2p_arg(variable,argno),ignore1);
00894 c_dataptr = c_dataptr_rest;
00895 }
00896 ptr = skip_subfmt(CTXTc ptr, ']');
00897 break;
00898
00899 case 't':
00900
00901 if (!ignore) {
00902 fmtnum = (int)(*ptr-'0');
00903 subformat[fmtnum] = ptr-2;
00904 ptr++;
00905 if (*(ptr++) != '(') cppc_error(CTXTc 15);
00906 fields = count_fields(CTXTc ptr, ')');
00907 size = count_csize(CTXTc ptr, ')');
00908 cdptr2 = (char *)mem_alloc(size,OTHER_SPACE);
00909 *((char **)c_dataptr) = cdptr2;
00910 argno = 0;
00911 for (i = 1; i <= fields; i++) {
00912 if (*(ptr+1)=='*') ignore = 1;
00913 else { ignore = 0; argno++; }
00914 ptr = ptoc_term0(CTXTc ptr,cdptr2,subformat,p2p_arg(variable,argno),ignore);
00915 cdptr2 = c_dataptr_rest;
00916 }
00917 }
00918 ptr = skip_subfmt(CTXTc ptr, ')');
00919 c_dataptr_rest = c_dataptr + 4;
00920 break;
00921
00922 case 'l':
00923 if (!ignore) {
00924 fmtnum = (int)(*ptr-'0');
00925 subformat[fmtnum] = ptr-2;
00926 ptr++;
00927 if (*(ptr++)!='(') cppc_error(CTXTc 16);
00928 fields = count_fields(CTXTc ptr, ')');
00929 size = count_csize(CTXTc ptr, ')');
00930 cdptr2 = (char *)mem_alloc(size,OTHER_SPACE);
00931 *((char **)c_dataptr) = cdptr2;
00932 argno = 0;
00933 for (i = 1; i <= fields; i++) {
00934 if (*(ptr+1)=='*') ignore = 1;
00935 else { ignore = 0; argno++; }
00936 if (argno==1)
00937 ptr = ptoc_term0(CTXTc ptr,cdptr2,subformat,p2p_car(variable),ignore);
00938 else if (argno==2)
00939 ptr = ptoc_term0(CTXTc ptr,cdptr2,subformat,p2p_cdr(variable),ignore);
00940 else cppc_error(CTXTc 31);
00941 cdptr2 = c_dataptr_rest;
00942 }
00943 }
00944 ptr = skip_subfmt(CTXTc ptr, ')');
00945 c_dataptr_rest = c_dataptr + 4;
00946 break;
00947
00948 case '0':
00949 case '1':
00950 case '2':
00951 case '3':
00952 case '4':
00953 case '5':
00954 case '6':
00955 case '7':
00956 case '8':
00957 case '9':
00958
00959 if (!ignore) {
00960 if (!is_nil(variable)) {
00961 ptoc_term0(CTXTc subformat[ch-'0'], c_dataptr, subformat, variable, 0);
00962 } else *(int *)(c_dataptr) = 0;
00963 }
00964 c_dataptr_rest = c_dataptr + 4;
00965 break;
00966
00967 default: cppc_error(CTXTc 17);
00968 }
00969 return ptr;
00970 }
00971
00972
00973
00974
00975
00976
00977 int ctop_term(CTXTdeclc char *fmt, char *c_dataptr, reg_num regnum)
00978 {
00979 prolog_term variable;
00980 int my_errno;
00981 char *subformat[10];
00982
00983 variable = reg_term(CTXTc regnum);
00984 if ((my_errno = setjmp(cinterf_env))) return my_errno;
00985 ctop_term0(CTXTc fmt, c_dataptr, subformat, variable, 0);
00986 return 0;
00987 }
00988
00989
00990
00991
00992
00993
00994 int ptoc_term(CTXTdeclc char *fmt, char *c_dataptr, reg_num regnum)
00995 {
00996 prolog_term variable;
00997 int my_errno;
00998 char *subformat[10];
00999
01000 variable = reg_term(CTXTc regnum);
01001 if ((my_errno = setjmp(cinterf_env))) return my_errno;
01002 ptoc_term0(CTXTc fmt, c_dataptr, subformat, variable, 0);
01003 return 0;
01004 }
01005
01006
01007
01008
01009
01010
01011 int c2p_term(CTXTdeclc char *fmt, char *c_dataptr, prolog_term variable)
01012 {
01013 int my_errno;
01014 char *subformat[10];
01015
01016 if ((my_errno = setjmp(cinterf_env))) return my_errno;
01017 ctop_term0(CTXTc fmt, c_dataptr, subformat, variable, 0);
01018 return 0;
01019 }
01020
01021
01022
01023
01024
01025
01026 int p2c_term(CTXTdeclc char *fmt, char *c_dataptr, prolog_term variable)
01027 {
01028 int my_errno;
01029 char *subformat[10];
01030
01031 if ((my_errno = setjmp(cinterf_env))) return my_errno;
01032 ptoc_term0(CTXTc fmt, c_dataptr, subformat, variable, 0);
01033 return 0;
01034 }
01035
01036 int mustquote(char *atom)
01037 {
01038 int i;
01039
01040 if (!(atom[0] >= 'a' && atom[0] <= 'z')) return TRUE;
01041 for (i=1; atom[i] != '\0'; i++) {
01042 if (!((atom[i] >= 'a' && atom[i] <= 'z') ||
01043 (atom[i] >= 'A' && atom[i] <= 'Z') ||
01044 (atom[i] == '_') ||
01045 (atom[i] >= '0' && atom[i] <= '9')
01046 )) return TRUE;
01047 }
01048 return FALSE;
01049 }
01050
01051
01052 void printpstring(char *atom, int toplevel, VarString *straddr)
01053 {
01054 int i;
01055
01056 if (toplevel || !mustquote(atom)) {
01057 XSB_StrAppend(straddr,atom);
01058 } else {
01059 XSB_StrAppendBlk(straddr, "'", 1);
01060 for (i = 0; atom[i] != '\0'; i++) {
01061 XSB_StrAppendBlk(straddr, atom+i, 1);
01062 if (atom[i] == '\'')
01063
01064 XSB_StrAppendBlk(straddr, "'", 1);
01065 }
01066 XSB_StrAppend(straddr, "'");
01067 }
01068 }
01069
01070
01071 int clenpterm(prolog_term term)
01072 {
01073 int i, clen;
01074
01075 if (is_var(term)) return 11;
01076 else if (is_int(term)) return 12;
01077 else if (is_float(term)) return 12;
01078 else if (is_nil(term)) return 2;
01079 else if (is_string(term)) return strlen(p2c_string(term))+5;
01080 else if (is_list(term)) {
01081 clen = 1;
01082 clen += clenpterm(p2p_car(term)) + 1;
01083 while (is_list(term)) {
01084 clen += clenpterm(p2p_car(term)) + 1;
01085 term = p2p_cdr(term);
01086 }
01087 if (!is_nil(term)) {
01088 clen += clenpterm(term) + 1;
01089 }
01090 return clen+1;
01091 } else if (is_functor(term)) {
01092 clen = strlen(p2c_functor(term))+5;
01093 if (p2c_arity(term) > 0) {
01094 clen += clenpterm(p2p_arg(term,1)) + 1;
01095 for (i = 2; i <= p2c_arity(term); i++) {
01096 clen += clenpterm(p2p_arg(term,i)) + 1;
01097 }
01098 return clen + 1;
01099 } else return clen;
01100 } else {
01101 xsb_warn("Unrecognized prolog term type");
01102 return 0;
01103 }
01104 }
01105
01106 char tempstring[MAXBUFSIZE];
01107
01108
01109
01110
01111
01112
01113 DllExport void call_conv print_pterm(CTXTdeclc prolog_term term, int toplevel,
01114 VarString *straddr)
01115 {
01116 int i;
01117
01118 if (is_var(term)) {
01119 xsb_sprint_variable(CTXTc tempstring, (CPtr) term);
01120 XSB_StrAppend(straddr,tempstring);
01121 } else if (is_attv(term)) {
01122 xsb_sprint_variable(CTXTc tempstring, (CPtr) dec_addr(term));
01123 XSB_StrAppend(straddr,tempstring);
01124 } else if (is_int(term)) {
01125 sprintf(tempstring,"%d", (int) p2c_int(term));
01126 XSB_StrAppend(straddr,tempstring);
01127 } else if (is_float(term)) {
01128 sprintf(tempstring,"%f", (float) p2c_float(term));
01129 XSB_StrAppend(straddr,tempstring);
01130 } else if (is_nil(term)) {
01131 XSB_StrAppend(straddr,"[]");
01132 } else if (is_string(term)) {
01133 printpstring(p2c_string(term),toplevel,straddr);
01134 } else if (is_list(term)) {
01135 XSB_StrAppend(straddr, "[");
01136 print_pterm(CTXTc p2p_car(term),FALSE,straddr);
01137 term = p2p_cdr(term);
01138 while (is_list(term)) {
01139 XSB_StrAppend(straddr, ",");
01140 print_pterm(CTXTc p2p_car(term),FALSE,straddr);
01141 term = p2p_cdr(term);
01142 }
01143 if (!is_nil(term)) {
01144 XSB_StrAppend(straddr, "|");
01145 print_pterm(CTXTc term,FALSE,straddr);
01146 }
01147 XSB_StrAppend(straddr, "]");
01148 } else if (is_functor(term)) {
01149 printpstring(p2c_functor(term),FALSE,straddr);
01150 if (p2c_arity(term) > 0) {
01151 XSB_StrAppend(straddr, "(");
01152 print_pterm(CTXTc p2p_arg(term,1),FALSE,straddr);
01153 for (i = 2; i <= p2c_arity(term); i++) {
01154 XSB_StrAppend(straddr, ",");
01155 print_pterm(CTXTc p2p_arg(term,i),FALSE,straddr);
01156 }
01157 XSB_StrAppend(straddr, ")");
01158 }
01159 } else xsb_warn("[PRINT_PTERM] Unrecognized prolog term type");
01160 }
01161
01162
01163
01164
01165
01166
01167 int xsb_answer_string(CTXTdeclc VarString *ans, char *sep)
01168 {
01169 int i;
01170
01171 if (!is_string(reg_term(CTXTc 2))) {
01172 for (i=1; i<p2c_arity(reg_term(CTXTc 2)); i++) {
01173 print_pterm(CTXTc p2p_arg(reg_term(CTXTc 2),i),TRUE,ans);
01174 XSB_StrAppend(ans,sep);
01175 }
01176 print_pterm(CTXTc p2p_arg(reg_term(CTXTc 2),p2c_arity(reg_term(CTXTc 2))),TRUE,ans);
01177 }
01178 return 0;
01179 }
01180
01181
01182 static long lastWarningStart = 0L;
01183 static inline void updateWarningStart(void)
01184 {
01185 if(flags[STDERR_BUFFERED])
01186 lastWarningStart = ftell(stderr);
01187 }
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203 static int xsb_initted_gl = 0;
01204 static int xsb_inquery_gl = 0;
01205
01206 DllExport int call_conv xsb_init(CTXTdeclc int argc, char *argv[])
01207 {
01208 int rc = 1;
01209 char executable1[MAXPATHLEN];
01210 char *expfilename;
01211
01212 updateWarningStart();
01213 if (!xsb_initted_gl)
01214 {
01215
01216
01217 sprintf(executable1, "%s%cconfig%c%s%cbin%cxsb",
01218 argv[0], SLASH, SLASH, FULL_CONFIG_NAME, SLASH, SLASH);
01219 expfilename = expand_filename(executable1);
01220 strcpy(executable_path_gl, expfilename);
01221 mem_dealloc(expfilename,MAXPATHLEN,OTHER_SPACE);
01222
01223 if (0 == (rc = xsb(CTXTc 0,argc,argv)))
01224 {
01225 if (0 == (rc = xsb(CTXTc 1,0,0)))
01226 xsb_initted_gl = 1;
01227 }
01228 }
01229 return(rc);
01230 }
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242 DllExport int call_conv xsb_init_string(CTXTdeclc char *cmdline_param) {
01243 int i = 0, argc = 0;
01244 char **argv, delim;
01245 char cmdline[2*MAXPATHLEN+1];
01246
01247 updateWarningStart();
01248
01249
01250
01251
01252 if (strlen(cmdline_param) > 2*MAXPATHLEN) {
01253 xsb_warn("**************************************************************************");
01254 xsb_warn("[XSB_INIT_STRING] %18s...: command used to call XSB server is too long",
01255 cmdline_param);
01256 xsb_warn("**************************************************************************");
01257 exit(1);
01258 }
01259 strncpy(cmdline, cmdline_param, 2*MAXPATHLEN - 1);
01260 argv = (char **) mem_alloc(20*sizeof(char *),OTHER_SPACE);
01261
01262 while (cmdline[i] == ' ') i++;
01263 while (cmdline[i] != '\0') {
01264 if ((cmdline[i] == '"') || (cmdline[i] == '\'')) {
01265 delim = cmdline[i];
01266 i++;
01267 } else delim = ' ';
01268 argv[argc] = &(cmdline[i]);
01269 argc++;
01270 if (argc >= 19) {argc--; break;}
01271 while ((cmdline[i] != delim) && (cmdline[i] != '\0')) i++;
01272 if (cmdline[i] == '\0') break;
01273 cmdline[i] = '\0';
01274 i++;
01275 while (cmdline[i] == ' ') i++;
01276 }
01277 argv[argc] = 0;
01278 return xsb_init(CTXTc argc,argv);
01279 }
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292 DllExport int call_conv xsb_command(CTXTdecl)
01293 {
01294 if (xsb_inquery_gl) return(2);
01295 updateWarningStart();
01296 c2p_int(CTXTc 0,reg_term(CTXTc 3));
01297 xsb(CTXTc 1,0,0);
01298 if (is_var(reg_term(CTXTc 1))) return(1);
01299 c2p_int(CTXTc 1,reg_term(CTXTc 3));
01300 xsb(CTXTc 1,0,0);
01301 if (is_var(reg_term(CTXTc 1))) return(0);
01302 (void) xsb_close_query(CTXT);
01303 return(2);
01304 }
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316 DllExport int call_conv xsb_command_string(CTXTdeclc char *goal)
01317 {
01318 if (xsb_inquery_gl) return(2);
01319 updateWarningStart();
01320 c2p_string(CTXTc goal,reg_term(CTXTc 1));
01321 c2p_int(CTXTc 2,reg_term(CTXTc 3));
01322 xsb(CTXTc 1,0,0);
01323 if (is_var(reg_term(CTXTc 1))) return(1);
01324 c2p_int(CTXTc 1,reg_term(CTXTc 3));
01325 xsb(CTXTc 1,0,0);
01326 if (is_var(reg_term(CTXTc 1))) return(0);
01327 (void) xsb_close_query(CTXT);
01328 return(2);
01329 }
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345 DllExport int call_conv xsb_query(CTXTdecl)
01346 {
01347 if (xsb_inquery_gl) return(2);
01348 updateWarningStart();
01349 c2p_int(CTXTc 0,reg_term(CTXTc 3));
01350 xsb(CTXTc 1,0,0);
01351 if (is_var(reg_term(CTXTc 1))) return(1);
01352 xsb_inquery_gl = 1;
01353 return(0);
01354 }
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372 DllExport int call_conv xsb_query_string(CTXTdeclc char *goal)
01373 {
01374 if (xsb_inquery_gl) return(2);
01375 updateWarningStart();
01376 c2p_chars(CTXTc goal,2,reg_term(CTXTc 1));
01377 c2p_int(CTXTc 2,reg_term(CTXTc 3));
01378 xsb(CTXTc 1,0,0);
01379 if (is_var(reg_term(CTXTc 1))) return(1);
01380 xsb_inquery_gl = 1;
01381 return(0);
01382 }
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393 int call_conv xsb_query_string_string(CTXTdeclc char *goal,
01394 VarString *ans, char *sep)
01395 {
01396 int rc;
01397
01398 rc = xsb_query_string(CTXTc goal);
01399 if (rc > 0) return rc;
01400 return xsb_answer_string(CTXTc ans,sep);
01401 }
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413 #ifndef MULTI_THREAD
01414 static XSB_StrDefine(last_answer_lc);
01415 #define last_answer (&last_answer_lc)
01416 #endif
01417
01418 int call_conv xsb_query_string_string_b(CTXTdeclc
01419 char *goal, char *buff, int buflen, int *anslen, char *sep)
01420 {
01421 int rc;
01422
01423 XSB_StrSet(last_answer,"");
01424 rc = xsb_query_string_string(CTXTc goal,last_answer,sep);
01425 if (rc > 0) return rc;
01426 *anslen = last_answer->length;
01427 XSB_StrNullTerminate(last_answer);
01428 if (last_answer->length < buflen) {
01429 strcpy(buff,last_answer->string);
01430 return rc;
01431 } else return(3);
01432 }
01433
01434
01435
01436
01437
01438
01439 DllExport int call_conv
01440 xsb_get_last_answer_string(CTXTdeclc char *buff, int buflen, int *anslen) {
01441
01442 *anslen = last_answer->length;
01443 if (last_answer->length < buflen) {
01444 strcpy(buff,last_answer->string);
01445 return 0;
01446 } else
01447 return(3);
01448 }
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465 DllExport int call_conv xsb_next(CTXTdecl)
01466 {
01467 if (!xsb_inquery_gl) return(2);
01468 updateWarningStart();
01469 c2p_int(CTXTc 0,reg_term(CTXTc 3));
01470 xsb(CTXTc 1,0,0);
01471 if (is_var(reg_term(CTXTc 1))) {
01472 xsb_inquery_gl = 0;
01473 return(1);
01474 } else return(0);
01475 }
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485 DllExport int call_conv xsb_next_string(CTXTdeclc VarString *ans, char *sep)
01486 {
01487 int rc = xsb_next(CTXT);
01488 if (rc > 0) return rc;
01489 return xsb_answer_string(CTXTc ans,sep);
01490 }
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503 DllExport int call_conv xsb_next_string_b(CTXTdeclc
01504 char *buff, int buflen, int *anslen, char *sep)
01505 {
01506 int rc;
01507
01508 XSB_StrSet(last_answer,"");
01509 rc = xsb_next_string(CTXTc last_answer,sep);
01510 if (rc > 0) return rc;
01511 *anslen = last_answer->length;
01512 XSB_StrNullTerminate(last_answer);
01513 if (last_answer->length < buflen) {
01514 strcpy(buff,last_answer->string);
01515 return rc;
01516 } else return(3);
01517 }
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529 DllExport int call_conv xsb_close_query(CTXTdecl)
01530 {
01531 updateWarningStart();
01532 if (!xsb_inquery_gl) return(2);
01533 c2p_int(CTXTc 1,reg_term(CTXTc 3));
01534 xsb(CTXTc 1,0,0);
01535 if (is_var(reg_term(CTXTc 1))) {
01536 xsb_inquery_gl = 0;
01537 return(0);
01538 } else return(2);
01539 }
01540
01541
01542
01543
01544
01545
01546
01547
01548 DllExport int call_conv xsb_close(CTXTdecl)
01549 {
01550 updateWarningStart();
01551 if (xsb_initted_gl) return(0);
01552 else return(1);
01553 }
01554
01555 #if defined(WIN_NT)
01556
01557
01558
01559
01560
01561
01562 #include <io.h>
01563 #include <Basetsd.h>
01564 #if !defined(CYGWIN)
01565 typedef SSIZE_T ssize_t;
01566 #endif
01567 static inline ssize_t pread(int fd, void *buf, size_t count, long offset)
01568 {
01569 if (-1 == lseek(fd,offset,SEEK_SET))
01570 return(-1);
01571 return(read(fd,buf,count));
01572 }
01573 #else
01574
01575
01576
01577
01578
01579 #include <unistd.h>
01580 #endif
01581
01582
01583
01584
01585
01586
01587 DllExport int call_conv xsb_get_last_error_string(char *buff, int buflen, int *anslen)
01588 {
01589 int rc = 2;
01590 ssize_t bytesRead = 1;
01591 ssize_t totalBytesRead = 0;
01592
01593 if(!flags[STDERR_BUFFERED])
01594 xsb_warn("[xsb_get_last_error_string] This feature must be activated with the -q option");
01595 else
01596 {
01597 rc = 1;
01598 errno = 0;
01599 *anslen = (int)(ftell(stderr) - lastWarningStart);
01600 if((0 == errno) && (-1 < *anslen))
01601 {
01602 if (*anslen >= buflen)
01603 rc = 3;
01604 else
01605 {
01606 while ((totalBytesRead < *anslen) && (0 < bytesRead) && !ferror(stderr))
01607 {
01608 bytesRead = pread(fileno(stderr),&buff[totalBytesRead],(*anslen - totalBytesRead),(lastWarningStart + totalBytesRead));
01609 totalBytesRead += bytesRead;
01610 }
01611 if (!ferror(stderr))
01612 {
01613 rc = 0;
01614 if (-1 == bytesRead)
01615 *anslen = totalBytesRead + 1;
01616 else
01617 *anslen = totalBytesRead;
01618 buff[*anslen] = 0x00;
01619 }
01620 }
01621 }
01622 }
01623 return(rc);
01624 }