libicl.c

Go to the documentation of this file.
00001 /****************************************************************************
00002  *   File    : libicl.c
00003  *   Author  : Adam Cheyer
00004  *   Purpose : Contains C version of ICL constructor and accessor routines
00005  *   Updated : 5/21/97
00006  */
00007 /*
00008  * Copyright (C) 2006  SRI International
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00023  *
00024  * SRI International: 333 Ravenswood Ave, Menlo Park, CA 94025
00025  */
00026 
00027 #define EXPORT_BORLAND
00028 
00029 #ifdef IS_DLL
00030 #define EXPORT_MSCPP __declspec(dllexport)
00031 #else
00032 #define EXPORT_MSCPP
00033 #endif
00034 
00035 /****************************************************************************
00036  * RCS Header
00037  ****************************************************************************/
00038 #ifndef lint
00039 /*char *rcsid= "$Header: /home/zuma1/OAA/CVSRepository/oaa2/src/oaalib/c/src/libicl.c,v 1.52 2006/12/11 13:32:30 agno Exp $";*/
00040 #endif
00041 
00042 
00043 /****************************************************************************
00044  *Include files
00045  ****************************************************************************/
00046 
00047 #include <stdio.h>
00048 #include <stdlib.h>
00049 #include <string.h>
00050 //#include <malloc.h>
00051 #include <stdarg.h>   /* Variable length argument lists */
00052 #include <ctype.h>
00053 #include "libicl.h"
00054 #include "libutils.h"
00055 #include "libicl_private.h"
00056 #include "libicl_depr.h"
00057 #include "stdpccts.h"
00058 
00059 #ifdef _WINDOWS
00060 #include "oaa-windows.h"
00061 #endif
00062 
00063 /****************************************************************************
00064  * Global variables and definitions
00065  ****************************************************************************/
00066 
00067 extern char* ICLDATAQSTART;
00068 extern size_t ICLDATAQSTARTLEN;
00069 static int rename_vars_index;
00070 
00071 #ifndef STREQ
00072 #define STREQ(str1, str2) (strcmp((str1), (str2)) == 0)
00073 #endif
00074 
00075 #ifdef NORMAL_GC
00076 char* gc_strdup(char* s)
00077 {
00078   int i = strlen(s);
00079   char* p = (char*)malloc(i + 1);
00080   strcpy(p, s);
00081   p[i] = '\0';
00082   return p;
00083 }
00084 #endif
00085 
00086 /*****************************************************************************
00087  * Local utility routines for dynamic arrays (used for unification)
00088  *****************************************************************************/
00089 
00090 /****************************************************************************
00091  * Forward references for some static functions
00092  ****************************************************************************/
00093 static void icl_deref(ICLTerm **var, struct dyn_array var_bindings);
00094 static ICLListType *
00095 icl_copy_list_type(ICLListType *list, struct dyn_array *vars);
00096 
00097 EXTERN void printDebug(int level, char *str, ...);
00098 
00099 /****************************************************************************
00100  * More forward references
00101  ****************************************************************************/
00102 static void iclIncRef(ICLTerm* t);
00103 int iclDecRef(ICLTerm* t);
00104 static void icl_FreeTermMulti(ICLTerm *elt, int n, void* pc);
00105 
00106 /****************************************************************************
00107  * name:    iclIncRef
00108  * purpose: Increment the reference count of a term
00109  ****************************************************************************/
00110 static void iclIncRef(ICLTerm* t)
00111 {
00112   t->refCount++;
00113 }
00114 
00120 int iclDecRef(ICLTerm* t)
00121 {
00122   if(t != NULL) {
00123     t->refCount -= 1;
00124     return t->refCount;
00125   }
00126   return -1;
00127 }
00128 
00132 EXPORT_MSCPP
00133 void EXPORT_BORLAND icl_init_const_dyn_array(struct const_dyn_array *da)
00134 {
00135   (*da).allocated = 0;
00136   (*da).count = 0;
00137   (*da).item = NULL;
00138 }
00142 EXPORT_MSCPP
00143 void EXPORT_BORLAND icl_init_dyn_array(struct dyn_array *da)
00144 {
00145   (*da).allocated = 0;
00146   (*da).count = 0;
00147   (*da).item = NULL;
00148 }
00149 
00155 EXPORT_MSCPP
00156 int EXPORT_BORLAND
00157 icl_stIsVar(char *t)
00158 {
00159   return ((t != NULL) && ((*t == '_') || ((*t >= 'A') && (*t <= 'Z'))));
00160 }
00161 
00162 EXPORT_MSCPP
00163 int EXPORT_BORLAND
00164 icl_stIsOperation(char *t){
00165   return icl_stOperationArgs(t, NULL, NULL, NULL);
00166 }
00167 
00168 EXPORT_MSCPP
00169 int EXPORT_BORLAND
00170 icl_stIsIclDataQ(char* t, size_t len)
00171 {
00172   static size_t dataqMarkerLen = 0;
00173   if(dataqMarkerLen == 0) {
00174     dataqMarkerLen = strlen(ICLDATAQSTART);
00175   }
00176   if(len >= 9) {
00177     if(strncmp(t, ICLDATAQSTART, dataqMarkerLen) == 0) {
00178       return TRUE;
00179     }
00180   }
00181 
00182   return FALSE;
00183 }
00184 
00190 EXPORT_MSCPP
00191 int EXPORT_BORLAND
00192 icl_stIsInt(char *t)
00193 {
00194   char *p;
00195 
00196   strtol(t, &p, 10);
00197   return ((p != t) && (*p == '\0'));
00198 }
00199 
00200 
00206 EXPORT_MSCPP
00207 int EXPORT_BORLAND
00208 icl_stIsFloat(char *t)
00209 {
00210   char *p;
00211 
00212   strtod(t, &p);
00213   if (p == t)     /* strtod failed */
00214     return (FALSE);
00215 
00216   if (*p == '\0')   /* String contains only 1.0 */
00217     return (TRUE);
00218 
00219   if ((*p == 'E'))
00220     return (((*(p+1) == '+') ||
00221              (*(p+1) == '-')) &&
00222             (atoi(p+2) > 0));
00223   else return (FALSE);
00224 }
00225 
00232 EXPORT_MSCPP
00233 void EXPORT_BORLAND
00234 icl_stUndoubleQuotes(char *s)
00235 {
00236   char c;
00237   char cc;
00238   char* in_ptr;
00239   char* out_ptr;
00240 
00241   in_ptr = s;
00242   out_ptr = s;
00243 
00244   while ((c = *in_ptr++) != (char) NULL) {
00245     cc = *in_ptr;
00246     if (c == '\'' && cc == c) {
00247       *out_ptr++ = c;
00248       in_ptr++;
00249     } else {
00250       *out_ptr++ = c;
00251     }
00252   }
00253   *out_ptr++ = '\0';
00254 }
00255 
00267 EXPORT_MSCPP
00268 char * EXPORT_BORLAND
00269 icl_stFixQuotes(char *s)
00270 {
00271   icl_stRemoveQuotes(s);
00272   icl_stUndoubleQuotes(s);
00273   return s;
00274 }
00275 
00276 
00277 
00288 EXPORT_MSCPP
00289 char * EXPORT_BORLAND
00290 icl_stDoubleQuotes(char *s)
00291 {
00292   static char *out_str = 0;
00293   static int out_str_len = 0;
00294   char *in_ptr, *out_ptr;
00295   char c;
00296   int i = 0;
00297   int num = 0;
00298   int new_len;
00299 
00300   /* Count number of ' chars */
00301   while (i < (int)strlen(s)) {
00302     if (s[i] == '\'') {
00303       num++;
00304     }
00305     i++;
00306   }
00307 
00308   new_len = strlen(s) + num + 10;
00309 
00310   /* Reallocate space if necessary */
00311   if (out_str_len < new_len) {
00312     if (out_str) {
00313       icl_stFree(out_str);
00314     }
00315     out_str = malloc(new_len);
00316     out_str_len = new_len;
00317   }
00318 
00319   /* Copy string to new buffer, doubling ' char */
00320   in_ptr = s;
00321   out_ptr = out_str;
00322   while ((c = *in_ptr++) != 0) {
00323     if (c == '\'') {
00324       *out_ptr++ = c;
00325       *out_ptr++ = c;
00326     } else {
00327       *out_ptr++ = c;
00328     }
00329   }
00330   *out_ptr++ = (char) 0;
00331 
00332   return out_str;
00333 
00334 }
00335 
00336 
00346 EXPORT_MSCPP
00347 char * EXPORT_BORLAND
00348 icl_stQuoteForce(char *s)
00349 {
00350   static char *out_str = 0;
00351   static int out_str_len = 0;
00352 
00353   /* Code adapted from icl_DoubleQuotes */
00354   char *in_ptr, *out_ptr;
00355   char c;
00356   int i = 0;
00357   int num = 0;
00358   int new_len;
00359   
00360   /* Count number of ' chars */
00361   while (i < (int)strlen(s)) {
00362     if (s[i] == '\'') {
00363       num++;
00364     }
00365     i++;
00366   }
00367   
00368   new_len = strlen(s) + num + 10;
00369   
00370   /* Reallocate space if necessary */
00371   if (out_str_len < new_len) {
00372     if (out_str) {
00373       icl_stFree(out_str);
00374     }
00375     out_str = malloc(new_len);
00376     out_str_len = new_len;
00377   }
00378   
00379   /* Copy string to new buffer, doubling ' char, and wrapping in ' */
00380   in_ptr = s;
00381   out_ptr = out_str;
00382   *out_ptr++ = '\'';
00383   while ((c = *in_ptr++) != 0) {
00384     if (c == '\'') {
00385       *out_ptr++ = c;
00386       *out_ptr++ = c;
00387     } else {
00388       *out_ptr++ = c;
00389     }
00390   }
00391   *out_ptr++ = '\'';
00392   *out_ptr++ = (char) 0;
00393   
00394   return (out_str);
00395 }
00396 
00406 EXPORT_MSCPP
00407 char * EXPORT_BORLAND
00408 icl_stQuote(char *s)
00409 {
00410   static char *out_str = 0;
00411   static int out_str_len = 0;
00412 
00413   if (icl_stIsStr(s))
00414     return (s);
00415 
00416   /* Code adapted from icl_DoubleQuotes */
00417   else {
00418     char *in_ptr, *out_ptr;
00419     char c;
00420     int i = 0;
00421     int num = 0;
00422     int new_len;
00423 
00424     /* Count number of ' chars */
00425     while (i < (int)strlen(s)) {
00426       if (s[i] == '\'') {
00427         num++;
00428       }
00429       i++;
00430     }
00431 
00432     new_len = strlen(s) + num + 10;
00433 
00434     /* Reallocate space if necessary */
00435     if (out_str_len < new_len) {
00436       if (out_str) {
00437         icl_stFree(out_str);
00438       }
00439       out_str = malloc(new_len);
00440       out_str_len = new_len;
00441     }
00442 
00443     /* Copy string to new buffer, doubling ' char, and wrapping in ' */
00444     in_ptr = s;
00445     out_ptr = out_str;
00446     *out_ptr++ = '\'';
00447     while ((c = *in_ptr++) != 0) {
00448       if (c == '\'') {
00449         *out_ptr++ = c;
00450         *out_ptr++ = c;
00451       } else {
00452         *out_ptr++ = c;
00453       }
00454     }
00455     *out_ptr++ = '\'';
00456     *out_ptr++ = (char) 0;
00457 
00458     return (out_str);
00459   }
00460 }
00461 
00462 
00463 
00464 
00465 
00470 EXPORT_MSCPP
00471 void EXPORT_BORLAND
00472 icl_stTrim(char *s)
00473 {
00474   while (s && (*s) && (*s <= ' '))
00475     strcpy(s, &s[1]);
00476   while (s && (*s) && (s[strlen(s)-1] <= ' '))
00477     s[strlen(s)-1] = '\0';
00478 }
00479 
00480 
00481 
00491 EXPORT_MSCPP
00492 void EXPORT_BORLAND
00493 icl_stAppend(char **str1, char *str2)
00494 {
00495   char *p;
00496   int str2len = strlen(str2);
00497 
00498   if (!str2 || !*str2) return;
00499 
00500   if (*str1 == NULL) {
00501 
00502     *str1 = (char*)malloc(sizeof(char) * (str2len + 1));
00503     *str1 = strdup(str2);
00504     (*str1)[str2len] = '\0';
00505   }
00506   else {
00507     p = malloc(strlen(*str1) + strlen(str2)+1);
00508     strcpy(p, *str1);
00509     strcat(p, str2);
00510     icl_stFree(*str1);
00511     *str1 = p;
00512   }
00513 }
00514 
00515 
00516 
00517 
00518 
00519 static
00520 void icl_rename_vars_termhelper(ICLTerm **term, hthash_table *knownVars)
00521 {
00522   ICLListType *l;
00523   char *hashedVal = NULL;
00524 
00525   /* Validate incoming arguments */
00526   if (icl_IsValid(*term)) {
00527     if (icl_IsVar(*term)) {
00528       if((strncmp((*term)->p,"_",1) == 0) &&
00529          (strlen((*term)->p) == 1)) {
00530         char tempName[10];
00531         hashedVal = NULL;
00532         do {
00533           sprintf(tempName, "_%d", rename_vars_index++);
00534         }
00535         while((hashedVal = (char*)htlookup(tempName, knownVars)) != NULL);
00536         free((*term)->p);
00537         (*term)->p = strdup(tempName);
00538       }
00539       else {
00540         hashedVal = (char *)htlookup((char *)((*term)->p), knownVars);
00541       }
00542       if(hashedVal != NULL) {
00543         free((*term)->p);
00544         (*term)->p = strdup(hashedVal);
00545       }
00546       else {
00547         char tempName[10];
00548         sprintf(tempName, "_%d", rename_vars_index);
00549         rename_vars_index++;
00550         htinsert((char *)((*term)->p),strdup(tempName),knownVars);
00551         free((*term)->p);
00552         (*term)->p = strdup(tempName);
00553       }
00554     }
00555     else
00556       if (((*term)->iclType == icl_list_type) ||
00557           ((*term)->iclType == icl_group_type) ||
00558           ((*term)->iclType == icl_struct_type)) {
00559         l = icl_List(*term);
00560 
00561         while (l) {
00562           icl_rename_vars_termhelper(&l->elt, knownVars);
00563           l = l->next;
00564         }
00565       }
00566   }
00567 }
00568 
00573 static
00574 void icl_rename_vars_term(ICLTerm **term)
00575 {
00576   hthash_table knownVars;
00577   htconstruct_table(&knownVars, 271);
00578   icl_rename_vars_termhelper(term, &knownVars);
00579 #ifdef NORMAL_GC
00580   htfree_table(&knownVars,GC_debug_free);
00581 #else
00582   htfree_table(&knownVars,free);
00583 #endif
00584 }
00585 
00586 
00587 /*****************************************************************************
00588  * Trace and error messages
00589  *****************************************************************************/
00590 
00591 
00592 /****************************************************************************
00593  * Structure construction routines
00594  ****************************************************************************/
00595 
00596 struct compoundInfo_s
00597 {
00598   guint8* preChild;
00599   size_t preChildLen;
00600   guint8* postChild;
00601   size_t postChildLen;
00602   guint8* preAllButFirst;
00603   size_t preAllButFirstLen;
00604   guint8* postAllButLast;
00605   size_t postAllButLastLen;
00606   guint8* postPend;
00607   size_t postPendLen;
00608   int numChildrenToDo;
00609   int originalNumChildren;
00610 }
00611 ;
00612 typedef struct compoundInfo_s compoundInfo_t;
00613 
00614 compoundInfo_t* compoundInfo_new()
00615 {
00616   compoundInfo_t* res = (compoundInfo_t*)malloc(sizeof(compoundInfo_t));
00617   memset(res, 0, sizeof(compoundInfo_t));
00618   return res;
00619 }
00620 
00621 int compoundInfo_finished(compoundInfo_t* ci)
00622 {
00623   if(ci->numChildrenToDo == 0) {
00624     return TRUE;
00625   }
00626   else {
00627     return FALSE;
00628   }
00629 }
00630 
00631 void compoundInfo_setNumChildren(compoundInfo_t* ci, int n)
00632 {
00633   ci->numChildrenToDo = n;
00634   ci->originalNumChildren = n;
00635 }
00636 
00637 int compoundInfo_getCurrentChildNum(compoundInfo_t* ci)
00638 {
00639   return ci->originalNumChildren - ci->numChildrenToDo;
00640 }
00641 
00642 void compoundInfo_setPreAllButFirst(compoundInfo_t* ci, guint8* s, size_t len)
00643 {
00644   ci->preAllButFirst = s;
00645   ci->preAllButFirstLen = len;
00646 }
00647 
00648 void compoundInfo_setPostAllButLast(compoundInfo_t* ci, guint8* s, size_t len)
00649 {
00650   ci->postAllButLast = s;
00651   ci->postAllButLastLen = len;
00652 }
00653 
00654 void compoundInfo_setPreChild(compoundInfo_t* ci, guint8* s, size_t len)
00655 {
00656   ci->preChild = s;
00657   ci->preChildLen = len;
00658 }
00659 
00660 void compoundInfo_setPostChild(compoundInfo_t* ci, guint8* s, size_t len)
00661 {
00662   ci->postChild = s;
00663   ci->postChildLen = len;
00664 }
00665 
00666 void compoundInfo_setPostPend(compoundInfo_t* ci, guint8* s, size_t len)
00667 {
00668   ci->postPend = s;
00669   ci->postPendLen = len;
00670 }
00671 
00672 guint8* compoundInfo_getPreChild(compoundInfo_t* ci, int i, size_t* len)
00673 {
00674   if(ci->preAllButFirst != NULL) {
00675     if(i != 0) {
00676       *len = ci->preAllButFirstLen;
00677       return ci->preAllButFirst;
00678     }
00679     else {
00680       *len = 0;
00681       return NULL;
00682     }
00683   }
00684   else {
00685     *len = ci->preChildLen;
00686     return ci->preChild;
00687   }
00688 }
00689 
00690 guint8* compoundInfo_getPostChild(compoundInfo_t* ci, int i, size_t* len)
00691 {
00692   if(ci->postAllButLast != NULL) {
00693     if(i != ci->originalNumChildren - 1) {
00694       *len = ci->postAllButLastLen;
00695       return ci->postAllButLast;
00696     }
00697     else {
00698       *len = 0;
00699       return NULL;
00700     }
00701   }
00702   else {
00703     *len = ci->postChildLen;
00704     return ci->postChild;
00705   }
00706 }
00707 
00708 guint8* compoundInfo_getPostPend(compoundInfo_t* ci, size_t* len)
00709 {
00710   *len = ci->postPendLen;
00711   return ci->postPend;
00712 }
00713 
00714 void compoundInfo_childFinished(compoundInfo_t* ci)
00715 {
00716   --(ci->numChildrenToDo);
00717 }
00718 
00722 int icl_toWireString(ICLTerm* t, char** termAsString, size_t* termAsStringLen)
00723 {
00724   GByteArray* bytes = g_byte_array_new();
00725   GPtrArray* compoundList = g_ptr_array_new();
00726   GPtrArray* workingList = g_ptr_array_new();
00727   ICLTerm* currentTerm = NULL;
00728   compoundInfo_t* sentinel;
00729   compoundInfo_t* ci;
00730   compoundInfo_t* currentCompound;
00731   char startChar;
00732   char* separator;
00733   int childNum;
00734   guint8* tmpData;
00735   size_t tmpLen;
00736   int numberLen;
00737   int isCompound;
00738   int numArgs;
00739   char* functor;
00740   int zeroLenCompound = FALSE;
00741   int compoundSize = 0;
00742   int i;
00743   unsigned int ui;
00744 
00745   /*
00746   {
00747     char* ds = icl_NewStringFromTerm(t);
00748     printf("icl_toWireString() working on %s\n", ds);
00749     icl_stFree(ds);
00750   }
00751   */
00752 
00753   g_ptr_array_add(workingList, t);
00754 
00755   sentinel = compoundInfo_new();
00756   sentinel->numChildrenToDo = 1;
00757   sentinel->originalNumChildren = 1;
00758   g_ptr_array_add(compoundList, sentinel);
00759 
00760   while((compoundList->len > 0) ||
00761         (workingList->len > 0)) {
00762     zeroLenCompound = FALSE;
00763     currentTerm = (ICLTerm*)g_ptr_array_index(workingList, workingList->len - 1);
00764     (void)g_ptr_array_remove_index(workingList, workingList->len - 1);
00765     currentCompound = (compoundInfo_t*)g_ptr_array_index(compoundList, compoundList->len - 1);
00766     childNum = compoundInfo_getCurrentChildNum(currentCompound);
00767     tmpData = compoundInfo_getPreChild(currentCompound, childNum, &tmpLen);
00768     if(tmpData != NULL) {
00769       g_byte_array_append(bytes, tmpData, tmpLen);
00770     }
00771     switch(currentTerm->iclType) {
00772     case icl_list_type:
00773       g_byte_array_append(bytes, (guint8*)"[", 1);
00774       numArgs = icl_NumTerms(currentTerm);
00775       ci = compoundInfo_new();
00776       compoundInfo_setPostPend(ci, (guint8*)"]", 1);
00777       compoundInfo_setNumChildren(ci, numArgs);
00778       compoundInfo_setPreAllButFirst(ci, (guint8*)",", 1);
00779       g_ptr_array_add(compoundList, ci);
00780       isCompound = TRUE;
00781       break;
00782     case icl_group_type:
00783       icl_GetGroupChars(currentTerm, &startChar, &separator);
00784       icl_stFree(separator);
00785       g_byte_array_append(bytes, (guint8*)&startChar, 1);
00786       numArgs = icl_NumTerms(currentTerm);
00787       ci = compoundInfo_new();
00788       switch(startChar) {
00789       case '{':
00790         compoundInfo_setPostPend(ci, (guint8*)"}", 1);
00791       default:
00792         compoundInfo_setPostPend(ci, (guint8*)")", 1);
00793       }
00794       compoundInfo_setNumChildren(ci, numArgs);
00795       compoundInfo_setPreAllButFirst(ci, (guint8*)",", 1);
00796       g_ptr_array_add(compoundList, ci);
00797       isCompound = TRUE;
00798       break;
00799     case icl_struct_type:
00800       functor = icl_Functor(currentTerm);
00801       numArgs = icl_NumTerms(currentTerm);
00802       ci = compoundInfo_new();
00803       g_byte_array_append(bytes, (guint8*)functor, strlen(functor));
00804       g_byte_array_append(bytes, (guint8*)"(", 1);
00805       compoundInfo_setPostPend(ci, (guint8*)")", 1);
00806       compoundInfo_setNumChildren(ci, numArgs);
00807       compoundInfo_setPreAllButFirst(ci, (guint8*)",", 1);
00808       g_ptr_array_add(compoundList, ci);
00809       isCompound = TRUE;
00810       break;
00811     case icl_int_type:
00812     case icl_float_type:
00813     case icl_str_type:
00814     case icl_var_type:
00815     case icl_dataq_type:
00816       isCompound = FALSE;
00817       numArgs = 0;
00818       break;
00819     default:
00820       fprintf(stderr, "libicl.c icl_toWireString() unknown type [%i] in term at %p\n", currentTerm->iclType, currentTerm);
00821       return FALSE;
00822     }
00823 
00824     if(isCompound) {
00825       ICLTerm* toAdd;
00826       /*
00827       printf("Found compound with %i args; compoundList has %i elements\n", numArgs, compoundList->len);
00828       */
00829       if(numArgs > 0) {
00830         for(i = numArgs - 1; i >= 0; --i) {
00831           toAdd = icl_NthTerm(currentTerm, i + 1);
00832           g_ptr_array_add(workingList, toAdd);
00833 
00834           {
00835             char* ds = icl_NewStringFromTerm(toAdd);
00836             //printf("Added child [%s] at index %i to workingList; workingList length = %i\n", ds, i, workingList->len);
00837             icl_stFree(ds);
00838           }
00839 
00840         }
00841         continue;
00842       }
00843       else {
00844         zeroLenCompound = TRUE;
00845       }
00846     }
00847 
00848     compoundSize = compoundList->len;
00849     currentCompound = (compoundInfo_t*)g_ptr_array_index(compoundList, compoundList->len - 1);
00850     if(!zeroLenCompound) {
00851       switch(currentTerm->iclType) {
00852       case icl_int_type:
00853         numberLen = snprintf(NULL, 0, get64BitFormat(), *((gint64*)currentTerm->p));
00854         if(numberLen < 0) {
00855           numberLen = 128;
00856         }
00857         tmpData = (guint8*)malloc(numberLen + 1);
00858         numberLen = snprintf((char*)tmpData, numberLen + 1, get64BitFormat(), *((gint64*)currentTerm->p));
00859         if(numberLen < 0) {
00860           numberLen = 128;
00861         }
00862         g_byte_array_append(bytes, tmpData, strlen((char*)tmpData));
00863         /*
00864         printf("Wrote %i bytes for integer %s\n", numberLen, tmpData);
00865         */
00866         free(tmpData);
00867         break;
00868       case icl_float_type:
00869         numberLen = snprintf(NULL, 0, "%f", *((double*)currentTerm->p));
00870         if(numberLen < 0) {
00871           numberLen = 128;
00872         }
00873         tmpData = (guint8*)malloc(numberLen + 1);
00874         numberLen = snprintf((char*)tmpData, numberLen + 1, "%f", *((double*)currentTerm->p));
00875         if(numberLen < 0) {
00876           numberLen = 128;
00877         }
00878         g_byte_array_append(bytes, tmpData, strlen((char*)tmpData));
00879         /*
00880         printf("Wrote %i bytes for float %s\n", numberLen, tmpData);
00881         */
00882         free(tmpData);
00883         break;
00884       case icl_var_type:
00885         g_byte_array_append(bytes, (guint8*)currentTerm->p, strlen((char*)currentTerm->p));
00886         /*
00887         printf("Wrote %i bytes for var %s\n", strlen((char*)currentTerm->p), (char*)currentTerm->p);
00888         */
00889         break;
00890       case icl_str_type:
00891         if(currentTerm->needsQuotes == 1) {
00892           tmpData = (guint8*)icl_stQuoteForce((char*)currentTerm->p);
00893         }
00894         else {
00895           tmpData = (guint8*)currentTerm->p;
00896         }
00897         g_byte_array_append(bytes, tmpData, strlen((char*)tmpData));
00898 
00899         /* printf("Wrote %i bytes for str %s\n", strlen((char*)currentTerm->p), (char*)currentTerm->p); */
00900 
00901         /* don't free tmpData--I'd rather icl_stQuote returned new memory, but
00902          * that's not the way it is
00903          */
00904         break;
00905       case icl_dataq_type:
00906         tmpData = (guint8*)currentTerm->p;
00907         /* printf("Writing icl_dataq_type of length %i\n", currentTerm->len); */
00908         g_byte_array_append(bytes, (guint8*)"icldataq(\"", 10);
00909         for(ui = 0; ui < currentTerm->len; ++ui) {
00910           if(tmpData[ui] == '"') {
00911             g_byte_array_append(bytes, (guint8*)"\"\"", 2);
00912           }
00913           else {
00914             g_byte_array_append(bytes, &tmpData[ui], 1);
00915           }
00916         }
00917         g_byte_array_append(bytes, (guint8*)"\")", 2);
00918         break;
00919       default:
00920         fprintf(stderr, "libicl.c icl_toWireString() unknown non-compound type [%i] at %p\n", currentTerm->iclType, currentTerm);
00921         return FALSE;
00922       }
00923       tmpData = compoundInfo_getPostChild(currentCompound, compoundInfo_getCurrentChildNum(currentCompound), &tmpLen);
00924       if(tmpData != NULL) {
00925         g_byte_array_append(bytes, tmpData, tmpLen);
00926       }
00927       compoundInfo_childFinished(currentCompound);
00928       /*
00929       printf("Child finished for current compound\n");
00930       */
00931     }
00932     else {
00933       /* nothing */
00934     }
00935 
00936     while(compoundInfo_finished(currentCompound)) {
00937       tmpData = compoundInfo_getPostPend(currentCompound, &tmpLen);
00938       if(tmpData != NULL) {
00939         g_byte_array_append(bytes, tmpData, tmpLen);
00940         /*
00941         printf("Wrote %i bytes for postPend on compound %s\n", tmpLen, tmpData);
00942         */
00943       }
00944       (void)g_ptr_array_remove_index(compoundList, compoundList->len - 1);
00945       free(currentCompound);
00946       /*
00947       printf("Compound finished compoundList length = %i\n", compoundList->len);
00948       */
00949       if(compoundList->len == 0) {
00950 #ifdef NORMAL_GC
00951         *termAsString = (char*)malloc(bytes->len);
00952         memcpy(*termAsString, bytes->data, bytes->len);
00953         *termAsStringLen = bytes->len;
00954         g_byte_array_free(bytes, FALSE);
00955         g_ptr_array_free(compoundList, TRUE);
00956         g_ptr_array_free(workingList, TRUE);
00957 #else
00958         *termAsString = (char*)bytes->data;
00959         *termAsStringLen = bytes->len;
00960         g_byte_array_free(bytes, FALSE);
00961         g_ptr_array_free(compoundList, TRUE);
00962         g_ptr_array_free(workingList, TRUE);
00963 #endif
00964         return TRUE;
00965       }
00966       currentCompound = (compoundInfo_t*)g_ptr_array_index(compoundList, compoundList->len - 1);
00967       tmpData = compoundInfo_getPostChild(currentCompound, compoundInfo_getCurrentChildNum(currentCompound), &tmpLen);
00968       if(tmpData != NULL) {
00969         g_byte_array_append(bytes, tmpData, tmpLen);
00970       }
00971       compoundInfo_childFinished(currentCompound);
00972       /*
00973       printf("Child finished for current compound (through adding another compound)\n");
00974       */
00975     }
00976   }
00977   fprintf(stderr, "libicl.c icl_toWireString() This should never be reached\n");
00978   g_byte_array_free(bytes, TRUE);
00979   g_ptr_array_free(compoundList, TRUE);
00980   g_ptr_array_free(workingList, TRUE);
00981   return FALSE;
00982 }
00983 
00991 EXPORT_MSCPP
00992 ICLTerm* EXPORT_BORLAND
00993 icl_NewTermFromData(char* data, size_t len)
00994 {
00995   ICLTerm* res = parser_getTermFromString(data, len);
00996   CHECK_LEAKS();
00997   return res;
00998 }
00999 
01007 EXPORT_MSCPP
01008 ICLTerm * EXPORT_BORLAND
01009 icl_NewTermFromString(char* t)
01010 {
01011   ICLTerm* res = NULL;
01012   if(t != NULL) {
01013     res = icl_NewTermFromData(t, strlen(t));
01014     CHECK_LEAKS();
01015     return res;
01016   }
01017   else {
01018     return NULL;
01019   }
01020 }
01021 
01022 
01028 EXPORT_MSCPP
01029 char * EXPORT_BORLAND
01030 icl_NewStringFromTerm(ICLTerm const*t)
01031 {
01032   char *res = NULL;
01033   char* tmp = NULL;
01034   int tmpBufSz = 0;
01035 
01036 
01037   if (t==NULL)
01038     return NULL;
01039 
01040   /* Make sure the term is OK */
01041   if (!icl_IsValid(t))
01042     return NULL;
01043 
01044   if (icl_IsVar(t)) {
01045     res = strdup(t->p);
01046   }
01047   else if (icl_IsInt(t)) {
01048     tmpBufSz = snprintf(tmp, 0, get64BitFormat(), icl_Int(t));
01049     if(tmpBufSz < 0) {
01050       tmpBufSz = 128;
01051     }
01052     ++tmpBufSz;
01053     tmp = (char*)malloc(tmpBufSz * sizeof(char));
01054     (void)memset(tmp, 0, tmpBufSz);
01055     snprintf(tmp, tmpBufSz, get64BitFormat(), icl_Int(t));
01056     res = tmp;
01057   }
01058   else if (icl_IsFloat(t)) {
01059     tmpBufSz = snprintf(tmp, 0, "%f", icl_Float(t));
01060     if(tmpBufSz < 0) {
01061       tmpBufSz = 128;
01062     }
01063     ++tmpBufSz;
01064     tmp = (char*)malloc(tmpBufSz * sizeof(char));
01065     (void)memset(tmp, 0, tmpBufSz);
01066     snprintf(tmp, tmpBufSz, "%f", icl_Float(t));
01067     res = tmp;
01068   }
01069   else if (icl_IsStr(t)) {
01070     if(t->needsQuotes == 1) {
01071       res = strdup(icl_stQuoteForce(t->p));
01072     }
01073     else {
01074       res = strdup(t->p);
01075     }
01076   }
01077   else if(icl_IsDataQ(t)) {
01078     /* icldataq("") */
01079     res = (char*)malloc(icl_Len(t) + 1);
01080     res = memcpy(res, icl_DataQ(t), icl_Len(t));
01081     res[icl_Len(t)] = '\0';
01082   }
01083   else if (icl_IsStruct(t)) {
01084     int first = TRUE;
01085     ICLListType *args;
01086 
01087     /* Checks for struct that are operators */
01088     if (icl_stIsOperator(icl_Functor(t))>0) {
01089       args = icl_Arguments(t);
01090       /* Left operand */
01091       icl_stAppend(&res, icl_NewStringFromTerm(args->elt));
01092       /* Operator */
01093       icl_stAppend(&res, icl_Functor(t));
01094       /* Right operand */
01095       args = args->next;
01096       if (args) {
01097         icl_stAppend(&res, icl_NewStringFromTerm(args->elt));
01098       }
01099     }
01100     else {
01101       res = strdup(icl_Functor(t));
01102       args = icl_Arguments(t);
01103       icl_stAppend(&res, "(");
01104       while (args) {
01105         char *arg;
01106         arg = icl_NewStringFromTerm(args->elt);
01107         if (first) {
01108           first = FALSE;
01109         }
01110         else {
01111           icl_stAppend(&res, ",");
01112         }
01113         icl_stAppend(&res, arg);
01114         icl_stFree(arg);
01115         args = args->next;
01116       }
01117       icl_stAppend(&res, ")");
01118     }
01119   }
01120   else if (icl_IsList(t)) {
01121     int first = TRUE;
01122     ICLListType *args;
01123     args = icl_List(t);
01124     res = strdup("[");
01125     while (args) {
01126       char *arg;
01127       arg = icl_NewStringFromTerm(args->elt);
01128       if (first)
01129         first = FALSE;
01130       else icl_stAppend(&res, ",");
01131       icl_stAppend(&res, arg);
01132       icl_stFree(arg);
01133       args = args->next;
01134     }
01135     icl_stAppend(&res, "]");
01136   }
01137   else if (icl_IsGroup(t)) {
01138     int first = TRUE;
01139     ICLListType *args;
01140     char start;
01141     char *separator;
01142 
01143     icl_GetGroupChars(t, &start, &separator);
01144     args = icl_List(t);
01145     res = strdup("[");
01146     res[0] = start;
01147     while (args) {
01148       char *arg;
01149       arg = icl_NewStringFromTerm(args->elt);
01150       if (first)
01151         first = FALSE;
01152       else icl_stAppend(&res, separator);
01153       icl_stAppend(&res, arg);
01154       icl_stFree(arg);
01155       args = args->next;
01156     }
01157     icl_stAppend(&res, "]");
01158     if (start == '(')
01159       res[strlen(res)-1] = start + 1;  /* () */
01160     else
01161       res[strlen(res)-1] = start + 2;  /* {|} and [\] */
01162 
01163     icl_stFree(separator);
01164   }
01165   else {
01166     fprintf(stderr, "Unknown term type for icl_NewStringFromTerm: %i\n", t->iclType);
01167   }
01168 
01169   return (res);
01170 }
01171 
01172 EXPORT_MSCPP
01173 char* EXPORT_BORLAND
01174 icl_UnquotedStringFromStr(ICLTerm* t)
01175 {
01176   if(!icl_IsStr(t)) {
01177     return NULL;
01178   }
01179 
01180   return strdup(t->p);
01181 }
01182 
01183 EXPORT_MSCPP
01184 char* EXPORT_BORLAND
01185 icl_ForcedQuotedStringFromStr(ICLTerm* t)
01186 {
01187   if(!icl_IsStr(t)) {
01188     return NULL;
01189   }
01190 
01191   return strdup(icl_stQuoteForce(t->p));
01192 }
01193 
01194 EXPORT_MSCPP
01195 char* EXPORT_BORLAND
01196 icl_MinimallyQuotedStringFromStr(ICLTerm* t)
01197 {
01198   if(!icl_IsStr(t)) {
01199     return NULL;
01200   }
01201 
01202   return icl_NewStringFromTerm(t);
01203 }
01204 
01205 /****************************************************************************
01206  * name:    pt
01207  * purpose: Debug
01208  ****************************************************************************/
01209 
01210 EXPORT_MSCPP
01211 char * EXPORT_BORLAND
01212 pt(ICLTerm *t)
01213 {
01214   return icl_NewStringFromTerm(t);
01215 }
01216 
01223 EXPORT_MSCPP
01224 char * EXPORT_BORLAND
01225 icl_NewStringStructFromTerm(ICLTerm *t)
01226 {
01227   char* INT64FORMAT = get64BitFormatWrapped("int(", ")");
01228   int tmpBufSz = 0;
01229   char *res = NULL;
01230   char* tmp = NULL;
01231 
01232   /* Make sure the term is OK */
01233   if (!icl_IsValid(t)) {
01234     free(INT64FORMAT);
01235     return NULL;
01236   }
01237 
01238   if (icl_IsVar(t)) {
01239     tmpBufSz = snprintf(tmp, 0, "var(%s)", (char*)(t->p));
01240     ++tmpBufSz;
01241     tmp = (char*)malloc(tmpBufSz * sizeof(char));
01242     memset(tmp, 0, tmpBufSz);
01243     snprintf(tmp, tmpBufSz, "var(%s)", (char*)(t->p));
01244     res = tmp;
01245   }
01246   else if (icl_IsInt(t)) {
01247     tmpBufSz = snprintf(tmp, 0, INT64FORMAT, icl_Int(t));
01248     ++tmpBufSz;
01249     tmp = (char*)malloc(tmpBufSz * sizeof(char));
01250     memset(tmp, 0, tmpBufSz);
01251     snprintf(tmp, tmpBufSz, INT64FORMAT, icl_Int(t));
01252     res = tmp;
01253   }
01254   else if (icl_IsFloat(t)) {
01255     tmpBufSz = snprintf(tmp, 0, "float(%f)", icl_Float(t));
01256     ++tmpBufSz;
01257     tmp = (char*)malloc(tmpBufSz * sizeof(char));
01258     memset(tmp, 0, tmpBufSz);
01259     snprintf(tmp, tmpBufSz, "float(%f)", icl_Float(t));
01260     res = tmp;
01261   }
01262   else if (icl_IsStr(t)) {
01263     tmpBufSz = snprintf(tmp, 0, "str(%s)", icl_stQuote(t->p));
01264     ++tmpBufSz;
01265     tmp = (char*)malloc(tmpBufSz * sizeof(char));
01266     memset(tmp, 0, tmpBufSz);
01267     snprintf(tmp, tmpBufSz, "str(%s)", icl_stQuote(t->p));
01268     res = tmp;
01269   }
01270   else if (icl_IsStruct(t)) {
01271     int first = TRUE;
01272     ICLListType *args;
01273     tmpBufSz = snprintf(tmp, 0, "struct(%s,", icl_Functor(t));
01274     ++tmpBufSz;
01275     tmp = (char*)malloc(tmpBufSz * sizeof(char));
01276     memset(tmp, 0, tmpBufSz);
01277     snprintf(tmp, tmpBufSz, "struct(%s,", icl_Functor(t));
01278     res = tmp;
01279     args = icl_Arguments(t);
01280     icl_stAppend(&res, "(");
01281     while (args) {
01282       char *arg;
01283       arg = icl_NewStringStructFromTerm(args->elt);
01284       if (first) {
01285   first = FALSE;
01286       }
01287       else {
01288   icl_stAppend(&res, ",");
01289       }
01290       icl_stAppend(&res, arg);
01291       icl_stFree(arg);
01292       args = args->next;
01293     }
01294     icl_stAppend(&res, ")");
01295   }
01296   else if (icl_IsList(t)) {
01297     int first = TRUE;
01298     ICLListType *args;
01299     args = icl_List(t);
01300     res = strdup("list([");
01301     while (args) {
01302       char *arg;
01303       arg = icl_NewStringStructFromTerm(args->elt);
01304       if (first) {
01305   first = FALSE;
01306       }
01307       else {
01308   icl_stAppend(&res, ",");
01309       }
01310       icl_stAppend(&res, arg);
01311       icl_stFree(arg);
01312       args = args->next;
01313     }
01314     icl_stAppend(&res, "])");
01315   }
01316   else if (icl_IsGroup(t)) {
01317     int first = TRUE;
01318     ICLListType *args;
01319     char start;
01320     char *separator;
01321 
01322     icl_GetGroupChars(t, &start, &separator);
01323     args = icl_List(t);
01324     res = strdup("group([");
01325     while (args) {
01326       char *arg;
01327       arg = icl_NewStringStructFromTerm(args->elt);
01328       if (first) {
01329   first = FALSE;
01330       }
01331       else {
01332   icl_stAppend(&res, separator);
01333       }
01334       icl_stAppend(&res, arg);
01335       icl_stFree(arg);
01336       args = args->next;
01337     }
01338     icl_stAppend(&res, "])");
01339     if (start == '(') {
01340       res[strlen(res)-1] = start + 1;  /* () */
01341     }
01342     else {
01343       res[strlen(res)-1] = start + 2;  /* {|} and [\] */
01344     }
01345 
01346     icl_stFree(separator);
01347   }
01348   free(INT64FORMAT);
01349   return (res);
01350 }
01351 
01352 enum CompoundType {
01353   compound_sentinel_type,
01354   compound_struct_type,
01355   compound_list_type,
01356   compound_group_type
01357 }
01358 ;
01359 
01360 struct CompoundInfo
01361 {
01362   enum CompoundType cType;
01363   void* p;
01364   int numArgsExpected;
01365 }
01366 ;
01367 
01368 struct CompoundStructType
01369 {
01370   char* functor;
01371   ICLListType* args;
01372 }
01373 ;
01374 
01375 struct CompoundListType
01376 {
01377   ICLListType* args;
01378 }
01379 ;
01380 
01381 struct CompoundGroupType
01382 {
01383   char startC;
01384   char* sep;
01385   ICLListType* args;
01386 }
01387 ;
01388 
01389 struct CompoundSentinelType
01390 {
01391   ICLTerm* term;
01392 }
01393 ;
01394 
01395 static void icl_add_compound_argument(struct CompoundInfo* ci, ICLTerm* t)
01396 {
01397   struct CompoundStructType* structCompound;
01398   struct CompoundListType* listCompound;
01399   struct CompoundGroupType* groupCompound;
01400 
01401   switch(ci->cType) {
01402   case compound_struct_type:
01403     structCompound = (struct CompoundStructType*)ci->p;
01404     if(!structCompound->args) {
01405       structCompound->args = icl_NewCons(t, NULL);
01406     }
01407     else {
01408       structCompound->args = icl_NewCons(t, structCompound->args);
01409     }
01410     ci->numArgsExpected--;
01411     break;
01412   case compound_list_type:
01413     listCompound = (struct CompoundListType*)ci->p;
01414     if(!listCompound->args) {
01415       listCompound->args = icl_NewCons(t, NULL);
01416     }
01417     else {
01418       listCompound->args = icl_NewCons(t, listCompound->args);
01419     }
01420     ci->numArgsExpected--;
01421     break;
01422   case compound_group_type:
01423     groupCompound = (struct CompoundGroupType*)ci->p;
01424     if(!groupCompound->args) {
01425       groupCompound->args = icl_NewCons(t, NULL);
01426     }
01427     else {
01428       groupCompound->args = icl_NewCons(t, groupCompound->args);
01429     }
01430     ci->numArgsExpected--;
01431     break;
01432   case compound_sentinel_type:
01433     ((struct CompoundSentinelType*)ci->p)->term = t;
01434     ci->numArgsExpected--;
01435     break;
01436   default:
01437     fprintf(stderr, "Unknown compound type\n");
01438     break;
01439   }
01440   if(ci->numArgsExpected < 0) {
01441     fprintf(stderr, "numArgsExpected < 0\n");
01442   }
01443 }
01444 
01449 EXPORT_MSCPP
01450 ICLTerm *EXPORT_BORLAND
01451 icl_copy_term_nonrec(ICLTerm const* t, struct dyn_array* vars)
01452 {
01453   struct const_dyn_array termStack;
01454   struct dyn_array compoundStack;
01455   ICLTerm* currTerm = NULL;
01456   struct CompoundInfo* currCompound;
01457   struct CompoundStructType* structCompound;
01458   struct CompoundListType* listCompound;
01459   struct CompoundGroupType* groupCompound;
01460   struct CompoundSentinelType sentinelCompound;
01461   struct CompoundInfo sentinelCI;
01462 
01463   if(t == NULL) {
01464     return NULL;
01465   }
01466 
01467   icl_init_const_dyn_array(&termStack);
01468   icl_append_const_dyn_array(&termStack, t);
01469   icl_init_dyn_array(&compoundStack);
01470   sentinelCI.p = &sentinelCompound;
01471   sentinelCI.cType = compound_sentinel_type;
01472   sentinelCI.numArgsExpected = 1;
01473   icl_append_dyn_array(&compoundStack, &sentinelCI);
01474   if(termStack.count == 0) {
01475     fprintf(stderr, "icl_copy_term_nonrec termStack count is 0!\n");
01476   }
01477   while(termStack.count != 0) {
01478     currTerm = (ICLTerm*)termStack.item[termStack.count - 1];
01479     termStack.item[termStack.count - 1] = NULL;
01480     termStack.count--;
01481     if(vars) {
01482       icl_deref(&currTerm, *vars);
01483     }
01484 
01485     if(icl_IsVar(currTerm)) {
01486       currTerm = icl_NewVar(icl_Str(currTerm));
01487     }
01488     else if(icl_IsInt(currTerm)) {
01489       currTerm = icl_NewInt(icl_Int(currTerm));
01490     }
01491     else if(icl_IsFloat(currTerm)) {
01492       currTerm = icl_NewFloat(icl_Float(currTerm));
01493     }
01494     else if(icl_IsStr(currTerm)) {
01495       currTerm = icl_NewStr(icl_Str(currTerm));
01496     }
01497     else if(icl_IsDataQ(currTerm)) {
01498       currTerm = icl_NewDataQ(icl_DataQ(currTerm), icl_Len(currTerm));
01499     }
01500     else if(icl_IsStruct(currTerm)) {
01501       /* Take the arguments of the struct, and put them into
01502        * the termStack, in the current order.  Note that this
01503        * means when we recreate the struct, we have to reverse
01504        * the order of the arguments!
01505        */
01506       struct CompoundInfo* ci = (struct CompoundInfo*)malloc(sizeof(struct CompoundInfo)) ;
01507       struct CompoundStructType* c = (struct CompoundStructType*)malloc(sizeof(struct CompoundStructType));
01508       ICLListType* args = icl_Arguments(currTerm);
01509       ci->p = c;
01510       ci->cType = compound_struct_type;
01511       ci->numArgsExpected = 0;
01512       c->functor = icl_Functor(currTerm);
01513       c->args = NULL;
01514       while(args) {
01515   ci->numArgsExpected++;
01516   icl_append_const_dyn_array(&termStack, args->elt);
01517   args = args->next;
01518       }
01519       icl_append_dyn_array(&compoundStack, ci);
01520       if(ci->numArgsExpected > 0) {
01521   continue;
01522       }
01523     }
01524     else if(icl_IsList(currTerm)) {
01525       struct CompoundInfo* ci = (struct CompoundInfo*)malloc(sizeof(struct CompoundInfo));
01526       struct CompoundListType* c = (struct CompoundListType*)malloc(sizeof(struct CompoundListType));
01527       ICLListType* args = icl_List(currTerm);
01528       ci->p = c;
01529       ci->cType = compound_list_type;
01530       ci->numArgsExpected = 0;
01531       c->args = NULL;
01532       while(args) {
01533   ci->numArgsExpected++;
01534   icl_append_const_dyn_array(&termStack, args->elt);
01535   args = args->next;
01536       }
01537       icl_append_dyn_array(&compoundStack, ci);
01538       if(ci->numArgsExpected > 0) {
01539   continue;
01540       }
01541     }
01542     else if(icl_IsGroup(currTerm)) {
01543       struct CompoundInfo* ci = (struct CompoundInfo*)malloc(sizeof(struct CompoundInfo));
01544       struct CompoundGroupType* c = (struct CompoundGroupType*)malloc(sizeof(struct CompoundGroupType));
01545       ICLListType* args = icl_List(currTerm);
01546       ci->p = c;
01547       ci->cType = compound_group_type;
01548       ci->numArgsExpected = 0;
01549       c->args = NULL;
01550       icl_GetGroupChars(currTerm, &(c->startC), &(c->sep));
01551       while(args) {
01552   ci->numArgsExpected++;
01553   icl_append_const_dyn_array(&termStack, args->elt);
01554   args = args->next;
01555       }
01556       icl_append_dyn_array(&compoundStack, ci);
01557       if(ci->numArgsExpected > 0) {
01558   continue;
01559       }
01560     }
01561     else if(currTerm == NULL) {
01562       currTerm = NULL;
01563     }
01564     else {
01565       char* s = icl_NewStringFromTerm(t);
01566       fprintf(stderr, "Unknown type in icl_copy_term_nonrec: [%s]\n", s);
01567       icl_stFree(s);
01568       currTerm = NULL;
01569     }
01570 
01571     /* currTerm == NULL or some term; add it to the current compound
01572        info structure
01573     */
01574 
01575     currCompound = (struct CompoundInfo*)compoundStack.item[compoundStack.count - 1];
01576 
01577     if(currCompound->numArgsExpected > 0) {
01578       icl_add_compound_argument(currCompound, currTerm);
01579     }
01580 
01581     while(currCompound->numArgsExpected == 0) {
01582       switch(currCompound->cType) {
01583       case compound_struct_type:
01584   structCompound = (struct CompoundStructType*)currCompound->p;
01585   currTerm = icl_NewStructFromList(structCompound->functor, icl_NewList(structCompound->args));
01586   free(structCompound);
01587   free(currCompound);
01588   structCompound = NULL;
01589   currCompound = NULL;
01590   break;
01591       case compound_list_type:
01592   listCompound = (struct CompoundListType*)currCompound->p;
01593   currTerm = icl_NewList(listCompound->args);
01594   free(listCompound);
01595   free(currCompound);
01596   listCompound = NULL;
01597   currCompound = NULL;
01598   break;
01599       case compound_group_type:
01600   groupCompound = (struct CompoundGroupType*)currCompound->p;
01601   currTerm = icl_NewGroup(groupCompound->startC, groupCompound->sep, groupCompound->args);
01602   free(groupCompound);
01603   free(currCompound);
01604   groupCompound = NULL;
01605   currCompound = NULL;
01606   break;
01607       case compound_sentinel_type:
01608   if(compoundStack.count != 1) {
01609     fprintf(stderr, "icl_copy_term_nonrec got sentinel but nonempty compoundStack\n");
01610   }
01611   if(compoundStack.item != NULL) {
01612     free(compoundStack.item);
01613   }
01614   if(termStack.item != NULL) {
01615     free(termStack.item);
01616   }
01617   CHECK_LEAKS();
01618   return ((struct CompoundSentinelType*)(currCompound->p))->term;
01619   break;
01620       default:
01621   fprintf(stderr, "icl_copy_term_nonrec got unknown compound type\n");
01622   if(compoundStack.item != NULL) {
01623     free(compoundStack.item);
01624   }
01625   return NULL;
01626   break;
01627       }
01628       compoundStack.item[compoundStack.count - 1] = NULL;
01629       compoundStack.count--;
01630       currCompound = (struct CompoundInfo*)compoundStack.item[compoundStack.count - 1];
01631       icl_add_compound_argument(currCompound, currTerm);
01632     }
01633   }
01634   icl_WriteTerm(currTerm);
01635   printf("\n");
01636   fprintf(stderr, "icl_copy_term_nonrec unreachable\n");
01637   return NULL;
01638 }
01639 
01640 /****************************************************************************
01641  * name:    icl_copy_term
01642  * purpose: Creates a copy of the term, all in new memory.
01643  *      Dereferences variables from binding list if available
01644  ****************************************************************************/
01645 /*
01646   EXPORT_MSCPP
01647   ICLTerm *EXPORT_BORLAND
01648   icl_copy_term(ICLTerm *t, struct dyn_array *vars)
01649   {
01650   ICLTerm *res = NULL;
01651 
01652   if (vars) {
01653   icl_deref(&t, *vars);
01654   }
01655 
01656   if (icl_IsVar(t)) {
01657   res = icl_NewVar(icl_Str(t));
01658   }
01659   else if (icl_IsInt(t)) {
01660   res = icl_NewInt(icl_Int(t));
01661   }
01662   else if (icl_IsFloat(t)) {
01663   res = icl_NewFloat(icl_Float(t));
01664   }
01665   else if (icl_IsStr(t)) {
01666   res = icl_NewStr(icl_Str(t));
01667   }
01668   else if (icl_IsStruct(t)) {
01669   ICLTerm *argList = icl_NewList(icl_copy_list_type(icl_Arguments(t),vars));
01670   res = icl_NewStructFromList(icl_Functor(t), argList);
01671   }
01672   else if (icl_IsList(t)) {
01673   res = icl_NewList(icl_copy_list_type(icl_List(t),vars));
01674   }
01675   else if (icl_IsGroup(t)) {
01676   char startC, *sep = NULL;
01677   icl_GetGroupChars(t, &startC, &sep);
01678   res = icl_NewGroup(startC, sep, icl_copy_list_type(icl_List(t), vars));
01679   icl_stFree(sep);
01680   }
01681   else if (t == NULL) {
01682   return NULL;
01683   }
01684   else {
01685   fprintf(stderr, "Unknown type in icl_copy_term\n");
01686   }
01687 
01688   return (res);
01689   }
01690 */
01691 
01695 static
01696 ICLListType *
01697 icl_copy_list_type(ICLListType *list, struct dyn_array *vars)
01698 {
01699   ICLListType *res = NULL, *end = NULL;
01700 
01701   while (list) {
01702     if (!res) {
01703       ICLTerm* copy = icl_copy_term_nonrec(list->elt, vars);
01704       res = icl_NewCons(copy, NULL);
01705       end = res;
01706     }
01707     else {
01708       end->next = icl_NewCons(icl_copy_term_nonrec(list->elt, vars), NULL);
01709       end = end->next;
01710     }
01711     list = list->next;
01712   }
01713 
01714   return(res);
01715 }
01716 
01717 
01718 
01722 EXPORT_MSCPP
01723 ICLTerm * EXPORT_BORLAND
01724 icl_CopyTerm(ICLTerm const*t)
01725 {
01726   return (icl_copy_term(t, NULL));
01727 }
01728 
01729 
01733 EXPORT_MSCPP
01734 ICLListType * EXPORT_BORLAND
01735 icl_CopyListType(ICLListType *list)
01736 {
01737   return(icl_copy_list_type(list, NULL));
01738 }
01739 
01740 
01741 
01747 EXPORT_MSCPP
01748 ICLTerm * EXPORT_BORLAND
01749 icl_NewInt(gint64 i)
01750 {
01751   ICLTerm *res = malloc(sizeof(ICLTerm));
01752   gint64 *iptr = malloc(sizeof(gint64));
01753 
01754   *iptr = i;
01755   res->iclType = icl_int_type;
01756   res->p = iptr;
01757   res->magic_cookie = ICL_MAGIC_COOKIE;
01758   res->len = sizeof(gint64);
01759 
01760   res->refCount = 1;
01761   res->glibAlloc = 0;
01762   res->needsQuotes = 0;
01763   return (res);
01764 }
01765 
01766 
01772 EXPORT_MSCPP
01773 ICLTerm * EXPORT_BORLAND
01774 icl_NewFloat(double f)
01775 {
01776   ICLTerm *res = malloc(sizeof(ICLTerm));
01777   double *fptr = malloc(sizeof(double));
01778 
01779   *fptr = f;
01780   res->iclType = icl_float_type;
01781   res->p = fptr;
01782   res->magic_cookie = ICL_MAGIC_COOKIE;
01783   res->len = sizeof(double);
01784 
01785   res->refCount = 1;
01786   res->glibAlloc = 0;
01787   res->needsQuotes = 0;
01788   return (res);
01789 }
01790 
01797 static char* trimAndStrdup(char const* s)
01798 {
01799   char const* start;
01800   char const* end;
01801   char* result;
01802   for(start = s; (*start != '\0') && (!isgraph(*start) || isspace(*start)); ++start);
01803   for(end = s + strlen(s) - 1; (end != start) && (!isgraph(*end) || isspace(*end)); --end);
01804 
01805   result = (char*)malloc(end - start + 1 + 1);
01806   memcpy(result, start, end - start + 1);
01807   result[end - start + 1] = '\0';
01808   return result;
01809 }
01810 
01815 static char* trimInPlace(char* s)
01816 {
01817   char* start;
01818   char* end;
01819   for(start = s; (*start != '\0') && (!isgraph(*start) || isspace(*start)); ++start);
01820   for(end = s + strlen(s) - 1; (end != start) && (!isgraph(*end) || isspace(*end)); --end);
01821 
01822   memmove(s, start, (end - start + 1));
01823   s[end - start + 1] = '\0';
01824   
01825   return s;
01826 }
01827 
01831 EXPORT_MSCPP
01832 int EXPORT_BORLAND
01833 icl_stIsProperlyQuoted(char* s)
01834 {
01835   int quotesAllowed = 0;
01836   int originalLen = strlen(s);
01837   int i;
01838 
01839   if(*s == '\'') {
01840     if((originalLen > 1) && *(s + originalLen - 1) == '\'') {
01841       quotesAllowed = 1;
01842     }
01843     else {
01844       return FALSE;
01845     }
01846   }
01847 
01848   for(i = 1; i < originalLen - 1; ++i) {
01849     if(s[i] == '\'') {
01850       if(!quotesAllowed) {
01851         return FALSE;
01852       }
01853       if(((i + 1) < originalLen - 1) && (s[i + 1] == '\'')) {
01854         ++i;
01855         continue;
01856       }
01857       else {
01858         return FALSE;
01859       }
01860     }
01861   }
01862 
01863   return TRUE;
01864 }
01865 
01866 static char* unquoteHelper(char const* from, char* to)
01867 {
01868   size_t index;
01869   int negativeOffset;
01870   size_t len = strlen(from);
01871 
01872   if((--len > 0) && (from[0] == '\'')) {
01873     // result + len points to the last single quote
01874     for(index = 1, negativeOffset = 1;
01875         index < len;
01876         ++index) {
01877       to[index - negativeOffset] = from[index];
01878       if(from[index] == '\'') {
01879         // must be doubled
01880         ++index;
01881         ++negativeOffset;
01882       }
01883     }
01884     to[len - negativeOffset] = '\0';
01885   }
01886 
01887   return to;
01888 }
01889 
01904 static char* unquoteInPlace(char* s)
01905 {
01906   return unquoteHelper(s, s);
01907 }
01908 
01912 void icl_setStrFromProperlyQuoted(char* s, ICLTerm* res)
01913 {
01914   s = unquoteInPlace(s);
01915 
01916   if(s[0] != '\0') {
01917     ICLTerm* term = icl_NewTermFromString(s);
01918     res->p = s;
01919     if(!term) {
01920       res->needsQuotes = TRUE;
01921     }
01922     else if(!icl_IsStr(term)) {
01923       res->needsQuotes = TRUE;
01924     }
01925     else {
01926       res->needsQuotes = FALSE;
01927     }
01928     icl_Free(term);
01929   }
01930   else {
01931     res->p = s;
01932     res->needsQuotes = FALSE;
01933   }
01934 }
01935 
01939 static void setIclStrValueFromString(char* s, ICLTerm* res)
01940 {
01941   if(icl_stIsProperlyQuoted(s)) {
01942     icl_setStrFromProperlyQuoted(s, res);
01943   }
01944   else {
01945     res->needsQuotes = TRUE;
01946     res->p = s;
01947   }
01948   res->len = strlen(res->p);
01949 }
01950 
01956 EXPORT_MSCPP
01957 ICLTerm * EXPORT_BORLAND
01958 icl_NewStr(char const*s)
01959 {
01960   ICLTerm *res = NULL;
01961   char* stringCopy;
01962 
01963   if(s) {
01964     res = malloc(sizeof(ICLTerm));
01965     stringCopy = trimAndStrdup(s);
01966 
01967     res->iclType = icl_str_type;
01968     res->magic_cookie = ICL_MAGIC_COOKIE;
01969     res->refCount = 1;
01970     res->glibAlloc = 0;
01971 
01972     setIclStrValueFromString(stringCopy, res);
01973   }
01974 
01975   return (res);
01976 }
01977 
01983 ICLTerm*
01984 icl_NewStrNoCopy(char *s)
01985 {
01986   ICLTerm *res = NULL;
01987 
01988   if (s) {
01989     res = malloc(sizeof(ICLTerm));
01990     s = trimInPlace(s);
01991 
01992     res->iclType = icl_str_type;
01993     res->magic_cookie = ICL_MAGIC_COOKIE;
01994     res->refCount = 1;
01995     res->glibAlloc = 0;
01996 
01997     setIclStrValueFromString(s, res);
01998     res->len = strlen(s);
01999   }
02000 
02001   return (res);
02002 }
02003 
02009 EXPORT_MSCPP
02010 ICLTerm * EXPORT_BORLAND
02011 icl_NewVar(char *name)
02012 {
02013   ICLTerm *res = NULL;
02014 
02015   if (name && *name) {
02016     res = malloc(sizeof(ICLTerm));
02017 
02018     res->iclType = icl_var_type;
02019     res->p = strdup(name);
02020     res->magic_cookie = ICL_MAGIC_COOKIE;
02021     res->refCount = 1;
02022     res->glibAlloc = 0;
02023     res->needsQuotes = 0;
02024     res->len = strlen(name);
02025   }
02026 
02027   return (res);
02028 }
02029 
02030 ICLTerm *
02031 icl_NewVarNoCopy(char *name)
02032 {
02033   ICLTerm *res = NULL;
02034 
02035   if (name && *name) {
02036     res = malloc(sizeof(ICLTerm));
02037 
02038     res->iclType = icl_var_type;
02039     res->p = name;
02040     res->magic_cookie = ICL_MAGIC_COOKIE;
02041     res->refCount = 1;
02042     res->glibAlloc = 0;
02043     res->needsQuotes = 0;
02044     res->len = strlen(name);
02045   }
02046 
02047   return (res);
02048 }
02049 
02057 EXPORT_MSCPP
02058 ICLTerm * EXPORT_BORLAND
02059 icl_NewStructFromList(char const* functor, ICLTerm *args)
02060 {
02061   ICLTerm       *res = NULL;
02062   ICLStructType *st = NULL;
02063   ICLTerm* functorAsTerm = NULL;
02064 
02065   //fprintf(stderr, "ALA:%s:%s:%i functor = %s\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, functor);
02066     
02067   functorAsTerm = icl_NewStr(functor);
02068 
02069   if (icl_IsList(args) && functorAsTerm) {
02070 
02071     res = malloc(sizeof(ICLTerm));
02072     st = malloc(sizeof(ICLStructType));
02073 
02074     st->numArgs = icl_NumTerms(args);
02075     st->args = args;
02076     st->functor = functorAsTerm;
02077 
02078     res->iclType = icl_struct_type;
02079     res->p = st;
02080     res->magic_cookie = ICL_MAGIC_COOKIE;
02081     res->refCount = 1;
02082     res->glibAlloc = 0;
02083     res->needsQuotes = 0;
02084     res->len = sizeof(st);
02085   }
02086 
02087   return (res);
02088 }
02089 
02090 
02091 
02099 EXPORT_MSCPP
02100 ICLTerm * EXPORT_BORLAND
02101 icl_NewStruct(char const* functor, int arity, ...)
02102 {
02103   ICLTerm *arg,  *res = NULL;
02104 
02105   va_list ap; /* points to each unnamed arg in turn */
02106   int i=0;
02107 
02108   ICLTerm* functorAsTerm = icl_NewStr(functor);
02109 
02110   //fprintf(stderr, "ALA:%s:%s:%i functor = %s\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, functor);
02111 
02112   if (functorAsTerm) {
02113     ICLStructType *st = malloc(sizeof(ICLStructType));
02114     ICLTerm *args;
02115 
02116     res = malloc(sizeof(ICLTerm));
02117 
02118     args = icl_NewList(NULL);
02119 
02120     /* copy args into list */
02121     va_start(ap, arity);  /* point ap to first unnamed arg */
02122     for (i=0; i< arity;i++) {
02123       arg = va_arg(ap, ICLTerm*);
02124       if (arg) {
02125         icl_AddToList(args, arg, TRUE);
02126       }
02127     }
02128     va_end(ap);
02129 
02130     st->numArgs = arity;
02131     st->args = args;
02132     st->functor = functorAsTerm;
02133 
02134     res->iclType = icl_struct_type;
02135     res->p = st;
02136     res->magic_cookie = ICL_MAGIC_COOKIE;
02137     res->refCount = 1;
02138     res->glibAlloc = 0;
02139     res->needsQuotes = 0;
02140     res->len = sizeof(st);
02141   }
02142 
02143   return (res);
02144 }
02145 
02146 
02150 EXPORT_MSCPP
02151 ICLListType * EXPORT_BORLAND
02152 icl_NewCons(ICLTerm *elt, ICLListType *tail)
02153 {
02154   ICLListType *res = malloc(sizeof(ICLListType));
02155 
02156   res->elt = elt;
02157   res->next = tail;
02158   if(elt != NULL) {
02159     iclIncRef(elt);
02160   }
02161 
02162   return (res);
02163 }
02164 
02165 EXPORT_MSCPP
02166 ICLTerm* EXPORT_BORLAND
02167 icl_NewDataQ(void const* data, size_t dataLen)
02168 {
02169   ICLTerm* res = malloc(sizeof(ICLTerm));
02170   res->p = malloc(dataLen);
02171   if(dataLen > 0) {
02172     memcpy(res->p, data, dataLen);
02173   }
02174   else {
02175     res->p = NULL;
02176   }
02177   res->len = dataLen;
02178   res->iclType = icl_dataq_type;
02179   res->magic_cookie = ICL_MAGIC_COOKIE;
02180   res->refCount = 1;
02181   res->glibAlloc = 0;
02182   res->needsQuotes = 0;
02183 
02184   return res;
02185 }
02186 
02187 ICLTerm*
02188 icl_NewDataQNoCopy(void* data, size_t dataLen)
02189 {
02190   ICLTerm* res = malloc(sizeof(ICLTerm));
02191   res->p = data;
02192   res->len = dataLen;
02193   res->iclType = icl_dataq_type;
02194   res->magic_cookie = ICL_MAGIC_COOKIE;
02195   res->refCount = 1;
02196   res->glibAlloc = 0;
02197   res->needsQuotes = 0;
02198 
02199   return res;
02200 }
02201 
02210 EXPORT_MSCPP
02211 ICLTerm * EXPORT_BORLAND
02212 icl_NewGroup(char startC, char *separator, ICLListType *list)
02213 {
02214   ICLTerm *res = malloc(sizeof(ICLTerm));
02215   ICLGroupType *gp = malloc(sizeof(ICLGroupType));
02216 
02217   res->iclType = icl_group_type;
02218   gp->startChar = startC;
02219   gp->separator = strdup(separator);
02220   gp->list = list;
02221   res->p = gp;
02222   res->magic_cookie = ICL_MAGIC_COOKIE;
02223   res->refCount = 1;
02224   res->glibAlloc = 0;
02225   res->needsQuotes = 0;
02226   res->len = sizeof(gp);
02227 
02228   return (res);
02229 }
02230 
02237 EXPORT_MSCPP
02238 ICLTerm * EXPORT_BORLAND
02239 icl_NewList(ICLListType *list)
02240 {
02241   ICLTerm *res = malloc(sizeof(ICLTerm));
02242 
02243   res->iclType = icl_list_type;
02244   res->p = list;
02245   res->magic_cookie = ICL_MAGIC_COOKIE;
02246   res->refCount = 1;
02247   res->glibAlloc = 0;
02248   res->needsQuotes = 0;
02249   res->len = sizeof(list);
02250 
02251   return (res);
02252 }
02253 
02254 
02255 EXPORT_MSCPP
02256 void EXPORT_BORLAND
02257 icl_FreeTermSingle(ICLTerm *elt)
02258 {
02259   /* void* pc = current_text_addr(); */
02260   icl_FreeTermMulti(elt,0,0);
02261 }
02262 
02263 EXPORT_MSCPP
02264 void EXPORT_BORLAND
02265 icl_FreeTerm(ICLTerm *elt)
02266 {
02267   icl_FreeTermMulti(elt,0,0);
02268 }
02269 
02282 EXPORT_MSCPP
02283 void EXPORT_BORLAND
02284 icl_stFree(void *p) {
02285   if (p) {
02286 #ifdef NORMAL_GC
02287     GC_debug_free(p); p = 0;
02288 #else
02289   free(p); p = 0;
02290 #endif
02291   }
02292 }
02293 
02294 /****************************************************************************
02295  * name:    icl_FreeTermMulti
02296  * purpose: Frees all memory used by an object ptr
02297  * remarks: Use icl_Free() macro, which then sets the pointer to NIL
02298  ****************************************************************************/
02299 static void
02300 icl_FreeTermMulti(ICLTerm *elt, int n, void* pc)
02301 {
02302 #ifdef NORMAL_GC
02303   CHECK_LEAKS();
02304 #endif
02305   /*
02306     int decRes = 0;
02307     int i = 0;
02308     int max = (n > 10 ? 10 : n);
02309     CHECK_LEAKS();
02310 
02311     if(elt != NULL) {
02312     iclDecRef(elt);
02313     }
02314 
02315     for(i = 0; i < max; i++) {
02316     fprintf(stderr, "  ");
02317     }
02318     fprintf(stderr, "icl_FreeTerm on %x called from %x recursion %i\n",
02319     elt, pc, n);
02320 
02321     if(n > 100) {
02322     char* abort = 0;
02323     fprintf(stderr, "icl_FreeTerm suspicious recursion number; aborting\n");
02324     abort[0] = 1;
02325     }
02326 
02327     if(decRes < 0) {
02328     char* abort = 0;
02329     fprintf(stderr, "icl_FreeTerm duplicate free; aborting\n");
02330     abort[0] = 1;
02331     }
02332   */
02333 
02334   if (icl_IsValid(elt)) {
02335 
02336     if ((elt->iclType == icl_int_type) ||
02337         (elt->iclType == icl_float_type) ||
02338         (elt->iclType == icl_var_type) ||
02339         (elt->iclType == icl_str_type) ||
02340         (elt->iclType == icl_dataq_type)) {
02341       if(elt->glibAlloc == 1) {
02342         g_free(elt->p);
02343       }
02344       else {
02345         free(elt->p);   /* frees space allocated by pointer */
02346         elt->p = NULL;
02347       }
02348     }
02349     else
02350 
02351       if (elt->iclType == icl_struct_type) {
02352         ICLStructType *st = elt->p;
02353         icl_FreeTermMulti(st->functor, n + 1, pc);
02354         st->functor = NULL;
02355         icl_FreeTermMulti(st->args, n + 1, pc);
02356         free(elt->p);
02357         elt->p = NULL;
02358       }
02359       else
02360 
02361         if (elt->iclType == icl_list_type) {
02362           ICLListType *list = elt->p;
02363           ICLListType *next;
02364           while (list) {
02365       icl_FreeTermMulti(list->elt, n + 1, pc);
02366       next = list->next;
02367             memset(list, 0, sizeof(ICLListType));
02368       free(list);
02369       list = next;
02370           }
02371           elt->p = NULL;
02372         }
02373 
02374     if (elt->iclType == icl_group_type) {
02375       ICLGroupType *gp = elt->p;
02376       ICLListType *list = gp->list;
02377       ICLListType *next;
02378       free(gp->separator);
02379       gp->separator = NULL;
02380       while (list) {
02381         icl_FreeTermMulti(list->elt, n + 1, pc);
02382         next = list->next;
02383         list->next = NULL;
02384         memset(list, 0, sizeof(ICLListType));
02385         free(list);
02386         list = next;
02387       }
02388       free(gp);
02389       elt->p = NULL;
02390     }
02391 
02392     memset(elt, 0, sizeof(ICLTerm));
02393     elt->magic_cookie = 0xdeadbeef;
02394     elt->iclType = icl_no_type;
02395     free(elt);
02396 #ifdef NORMAL_GC
02397     CHECK_LEAKS();
02398 #endif
02399   }
02400 }
02401 
02402 #if 0
02403 
02404 /****************************************************************************
02405  * name:    icl_ReuseMem
02406  * purpose: A very simple form of garbage collection for ICLTerms.
02407  *    Often, a programmer wants to create a "temporary" ICL structure to
02408  *    pass to some procedure, such that the life of the structure needs only
02409  *    exist during that call.  icl_ReuseMem can be used for this purpose, to
02410  *    recover the memory for a temporary structure.
02411  * remarks:
02412  *    icl_ReuseMem keeps a static pointer of the last structure passed which
02413  *    it will free to make room for the next structure coming in.  Therefore,
02414  *    the "life expectancy" of a structure passed to icl_ReuseMem is only
02415  *    until the next call to this function.
02416  * warning:
02417  *    Do not use this function twice in the same call, since the second call
02418  *    will erase the value of the first (see above)
02419  *     ie. WRONG!!!
02420  *        do(icl_ReuseMem(icl_NewStr("a")), icl_ReuseMem(icl_NewStr("b")));
02421  ****************************************************************************/
02422 EXPORT_MSCPP
02423 ICLTerm * EXPORT_BORLAND
02424 icl_ReuseMem(ICLTerm *elt)
02425 {
02426   static ICLTerm *last = NULL;
02427 
02428   icl_Free(last);
02429   last = elt;
02430   return elt;
02431 }
02432 
02433 #endif
02434 
02435 
02436 /****************************************************************************
02437  * Structure testing routines
02438  ****************************************************************************/
02439 
02443 EXPORT_MSCPP
02444 int EXPORT_BORLAND
02445 icl_IsList(ICLTerm const*elt)
02446 {
02447   return (icl_IsValid(elt) && (elt->iclType == icl_list_type));
02448 }
02449 
02453 EXPORT_MSCPP
02454 int EXPORT_BORLAND
02455 icl_IsGroup(ICLTerm const*elt)
02456 {
02457   return (icl_IsValid(elt) && (elt->iclType == icl_group_type));
02458 }
02459 
02463 EXPORT_MSCPP
02464 int EXPORT_BORLAND
02465 icl_IsStruct(ICLTerm const*elt)
02466 {
02467   return (icl_IsValid(elt) && (elt->iclType == icl_struct_type));
02468 }
02469 
02470 
02474 EXPORT_MSCPP
02475 int EXPORT_BORLAND
02476 icl_IsStr(ICLTerm const*elt)
02477 {
02478   return (icl_IsValid(elt) && (elt->iclType == icl_str_type));
02479 }
02480 
02481 
02485 EXPORT_MSCPP
02486 int EXPORT_BORLAND
02487 icl_IsVar(ICLTerm const*elt)
02488 {
02489   return (icl_IsValid(elt) && (elt->iclType == icl_var_type));
02490 }
02491 
02492 
02496 EXPORT_MSCPP
02497 int EXPORT_BORLAND
02498 icl_IsInt(ICLTerm const*elt)
02499 {
02500   return (icl_IsValid(elt) && (elt->iclType == icl_int_type));
02501 }
02502 
02503 
02507 EXPORT_MSCPP
02508 int EXPORT_BORLAND
02509 icl_IsFloat(ICLTerm const*elt)
02510 {
02511   return (icl_IsValid(elt) && (elt->iclType == icl_float_type));
02512 }
02513 
02514 EXPORT_MSCPP
02515 int EXPORT_BORLAND
02516 icl_IsDataQ(ICLTerm const* elt)
02517 {
02518   return (icl_IsValid(elt) && (elt->iclType == icl_dataq_type));
02519 }
02520 
02521 
02525 EXPORT_MSCPP
02526 int EXPORT_BORLAND
02527 icl_IsValid(ICLTerm const*elt)
02528 {
02529   return (elt && (elt->magic_cookie == ICL_MAGIC_COOKIE));
02530 }
02531 
02532 /*****************************************************************************
02533  * name: icl_IsGround
02534  * purpose:
02535  *****************************************************************************/
02536 
02537 int icl_IsGround(ICLTerm const *term)
02538 {
02539   ICLListType *plist = (ICLListType *)NULL;
02540 
02541   if (! icl_IsValid(term))
02542     return FALSE;
02543 
02544   if(icl_IsVar(term))
02545     return FALSE;
02546 
02547   if(icl_IsStruct(term))
02548     plist = icl_Arguments(term);
02549   else if(icl_IsList(term))
02550     plist = icl_List(term);
02551 
02552   /* ??? check for any other complex types? */
02553 
02554   while(icl_ListHasMoreElements(plist)) {
02555     ICLTerm *el = icl_ListElement(plist);
02556 
02557     if(!icl_IsGround(el))
02558       return FALSE;
02559     plist = icl_ListNextElement(plist);
02560   }
02561   return TRUE;
02562 }
02563 
02571 EXPORT_MSCPP
02572 void* EXPORT_BORLAND
02573 icl_DataQ(ICLTerm const* elt)
02574 {
02575   if(icl_IsDataQ(elt)) {
02576     return elt->p;
02577   }
02578   else {
02579     return NULL;
02580   }
02581 }
02582 
02583 EXPORT_MSCPP
02584 size_t EXPORT_BORLAND
02585 icl_DataQLen(ICLTerm const* elt)
02586 {
02587   if(icl_IsDataQ(elt)) {
02588     return elt->len;
02589   }
02590   else {
02591     return 0;
02592   }
02593 }
02594 
02598 EXPORT_MSCPP
02599 size_t EXPORT_BORLAND
02600 icl_Len(ICLTerm const *elt)
02601 {
02602   if(icl_IsValid(elt)) {
02603     return elt->len;
02604   }
02605   else {
02606     return 0;
02607   }
02608 }
02609 
02614 EXPORT_MSCPP
02615 gint64 EXPORT_BORLAND
02616 icl_Int(ICLTerm const*elt)
02617 {
02618   gint64 *i;
02619 
02620   if (icl_IsInt(elt)) {
02621     i = elt->p;
02622     return (*i);
02623   }
02624   else return(0);
02625 }
02626 
02627 
02632 EXPORT_MSCPP
02633 double EXPORT_BORLAND
02634 icl_Float(ICLTerm const*elt)
02635 {
02636   double *f;
02637 
02638   if (icl_IsFloat(elt)) {
02639     f = elt->p;
02640     return (*f);
02641   }
02642   else return(0.0);
02643 }
02644 
02645 
02652 EXPORT_MSCPP
02653 char * EXPORT_BORLAND
02654 icl_Str(ICLTerm const*elt)
02655 {
02656   if (icl_IsStr(elt) || icl_IsVar(elt))
02657     return((char*)(elt->p));
02658   else
02659     if (icl_IsStruct(elt)) {
02660       ICLStructType *st = elt->p;
02661       return(icl_Str(st->functor));
02662     }
02663     else return(NULL);
02664 }
02665 
02672 EXPORT_MSCPP
02673 char* EXPORT_BORLAND
02674 icl_Functor(ICLTerm const*elt)
02675 {
02676   if (icl_IsStruct(elt)) {
02677     ICLStructType *st = elt->p;
02678     return(icl_Str(st->functor));
02679   }
02680   else {
02681     return(NULL);
02682   }
02683 }
02684 
02685 
02690 EXPORT_MSCPP
02691 ICLListType * EXPORT_BORLAND
02692 icl_Arguments(ICLTerm const *elt)
02693 {
02694   if (icl_IsStruct(elt)) {
02695     ICLStructType *st = elt->p;
02696     return(icl_List(st->args));
02697   }
02698   else return(NULL);
02699 }
02700 
02709 EXPORT_MSCPP
02710 int EXPORT_BORLAND
02711 icl_GetGroupChars(ICLTerm const*group, char *startC, char **sep)
02712 {
02713   if (icl_IsGroup(group)) {
02714     ICLGroupType *gt = group->p;
02715     *startC = gt->startChar;
02716     *sep = strdup(gt->separator);
02717     return(TRUE);
02718   }
02719   else return(FALSE);
02720 }
02721 
02722 
02728 EXPORT_MSCPP
02729 ICLListType * EXPORT_BORLAND
02730 icl_List(ICLTerm const*elt)
02731 {
02732   if (icl_IsList(elt)) {
02733     ICLListType *list = elt->p;
02734     return(list);
02735   }
02736   else
02737     if (icl_IsGroup(elt)) {
02738       ICLGroupType *gp = elt->p;
02739       ICLListType *list = gp->list;
02740       return(list);
02741     }
02742     else
02743       if (icl_IsStruct(elt)) {
02744         ICLStructType *st = elt->p;
02745         return(icl_List(st->args));
02746       }
02747       else return(NULL);
02748 }
02749 
02750 EXPORT_MSCPP
02751 ICLListType *  EXPORT_BORLAND icl_ListNext(ICLListType const* t)
02752 {
02753   return t->next;
02754 }
02755 
02756 EXPORT_MSCPP
02757 ICLTerm *  EXPORT_BORLAND icl_ListElt(ICLListType const* t)
02758 {
02759   return t->elt;
02760 }
02761 
02762 
02763 ICLListType* icl_copy_listtype(ICLListType* l)
02764 {
02765   ICLListType* newList = NULL;
02766   ICLListType* prev = NULL;
02767   while(l) {
02768     newList = (ICLListType*)malloc(sizeof(ICLListType));
02769     if(prev != NULL) {
02770       prev->next = newList;
02771     }
02772     newList->next = NULL;
02773     newList->elt = icl_CopyTerm(l->elt);
02774     l = l->next;
02775     prev = newList;
02776   }
02777   return newList;
02778 }
02779 
02785 EXPORT_MSCPP
02786 ICLListType * EXPORT_BORLAND
02787 icl_ListCopy(ICLTerm const*elt)
02788 {
02789   if (icl_IsList(elt)) {
02790     ICLListType *list = elt->p;
02791     return(icl_copy_listtype(list));
02792   }
02793   else
02794     if (icl_IsGroup(elt)) {
02795       ICLGroupType *gp = elt->p;
02796       ICLListType *list = gp->list;
02797       return(icl_copy_listtype(list));
02798     }
02799     else
02800       if (icl_IsStruct(elt)) {
02801         ICLStructType *st = elt->p;
02802         return(icl_copy_listtype(icl_List(st->args)));
02803       }
02804       else {
02805         return(NULL);
02806       }
02807 }
02808 
02809 
02810 /****************************************************************************
02811  * List manipulation
02812  ****************************************************************************/
02813 
02818 EXPORT_MSCPP
02819 int EXPORT_BORLAND
02820 icl_AddToList(ICLTerm *list, ICLTerm *elt, int atEnd)
02821 {
02822   if (icl_IsValid(elt) && (icl_IsList(list) || icl_IsGroup(list)) ) {
02823 
02824     /* Empty list */
02825     if (icl_IsList(list) && !list->p) {
02826       list->p = icl_NewCons(elt, NULL);
02827       return TRUE;
02828     }
02829     else {
02830       /* at beginning */
02831       if (!atEnd) {
02832   list->p = icl_NewCons(elt, list->p);
02833       }
02834       else {
02835   /* Group of one elt ??  */
02836   if (icl_IsGroup(list) && (!((ICLGroupType*)list->p)->list))
02837     ((ICLGroupType *)list->p)->list = icl_NewCons(elt, NULL);
02838 
02839   /* loop to end and add elt */
02840   else {
02841     ICLListType *p;
02842     p = icl_List(list);
02843     while (p->next)
02844       p = p->next;
02845     p->next = icl_NewCons(elt, NULL);
02846   }
02847       }
02848       return (TRUE);
02849     }
02850   }
02851   else {
02852     return (FALSE);
02853   }
02854 }
02855 
02860 EXPORT_MSCPP
02861 int EXPORT_BORLAND
02862 icl_ClearList(ICLTerm *list)
02863 {
02864   if ((icl_IsList(list) || icl_IsGroup(list)) ) {
02865     ICLListType *p;
02866     ICLListType *toBeDestroyed;
02867     ICLTerm* t;
02868 
02869     p = icl_List(list);
02870     while (p) {
02871       toBeDestroyed = p;
02872       p = p->next;
02873       t = toBeDestroyed->elt;
02874       icl_Free(t);
02875       icl_stFree(toBeDestroyed);
02876     }
02877     return (TRUE);
02878   }
02879   return FALSE;
02880 }
02881 
02886 EXPORT_MSCPP
02887 int EXPORT_BORLAND
02888 icl_SortList(ICLTerm *list, int (*user_function)(ICLTerm *Elt1, ICLTerm *Elt2))
02889 {
02890   (void)list;
02891   (void)user_function;
02892   return FALSE;
02893 }
02894 
02898 EXPORT_MSCPP
02899 int EXPORT_BORLAND
02900 icl_ListHasMoreElements(ICLListType const*l)
02901 {
02902   if((l != NULL) &&
02903      (l->elt != NULL)) {
02904     return TRUE;
02905   }
02906   return FALSE;
02907 }
02908 
02912 EXPORT_MSCPP
02913 ICLListType * EXPORT_BORLAND
02914 icl_ListNextElement(ICLListType const*l)
02915 {
02916   if(l)
02917     return l->next;
02918   else
02919     return NULL;
02920 }
02921 
02925 EXPORT_MSCPP
02926 ICLTerm * EXPORT_BORLAND
02927 icl_ListElement(ICLListType const*list)
02928 {
02929   return list->elt;
02930 }
02931 
02937 EXPORT_MSCPP
02938 int EXPORT_BORLAND
02939 icl_ListDelete(ICLTerm *list, ICLTerm *elem, ICLTerm **residue) {
02940   ICLListType *iterator;
02941   if(!icl_IsList(list))
02942     return FALSE;
02943   iterator = icl_List(list);
02944   *residue = icl_NewList(NULL);
02945   while(icl_ListHasMoreElements(iterator)) {
02946     ICLTerm *listel = icl_ListElement(iterator);
02947     if(!icl_Unify(listel, elem, NULL)) {
02948       icl_AddToList(*residue, icl_CopyTerm(listel), TRUE);
02949     }
02950     iterator = icl_ListNextElement(iterator);
02951   }
02952   return TRUE;
02953 }
02954 
02958 EXPORT_MSCPP
02959 int EXPORT_BORLAND
02960 icl_AppendCopy(ICLTerm *list1, ICLTerm const*list2) {
02961 
02962   if (list2==NULL)
02963     return FALSE;
02964 
02965   if(icl_IsList(list1) && icl_IsList(list2)) {
02966     ICLListType *l2 = icl_List(list2);
02967     while(icl_ListHasMoreElements(l2)) {
02968       icl_AddToList(list1, icl_CopyTerm(icl_ListElement(l2)), TRUE);
02969       l2 = icl_ListNextElement(l2);
02970     }
02971     return TRUE;
02972   }
02973   return FALSE;
02974 }
02975 
02979 EXPORT_MSCPP
02980 int EXPORT_BORLAND
02981 icl_Append(ICLTerm *list1, ICLTerm *list2) {
02982 
02983   /*
02984     char *debugString1 = icl_NewStringFromTerm(list1);
02985     char *debugString2 = icl_NewStringFromTerm(list2);
02986 
02987     printDebug(7, "List 1 %s\n", debugString1);
02988     printDebug(7, "List 2 %s\n", debugString2);
02989 
02990     icl_stFree(debugString1);
02991     icl_stFree(debugString2);
02992   */
02993   if (list2==NULL)
02994     return FALSE;
02995 
02996   if(icl_IsList(list1) && icl_IsList(list2)) {
02997     ICLListType *l2 = icl_List(list2);
02998     while(icl_ListHasMoreElements(l2)) {
02999       icl_AddToList(list1, icl_ListElement(l2), TRUE);
03000       l2 = icl_ListNextElement(l2);
03001     }
03002     return TRUE;
03003   }
03004   return FALSE;
03005 }
03006 
03012 EXPORT_MSCPP
03013 int EXPORT_BORLAND
03014 icl_Union(ICLTerm *list1, ICLTerm *list2, ICLTerm **dest)
03015 {
03016   ICLTerm* tmp;
03017   int res;
03018   if (list1 && list2 && icl_IsList(list1) && icl_IsList(list2)) {
03019     *dest = icl_CopyTerm(list1);
03020     tmp = *dest;
03021     res = icl_AppendCopy(*dest, list2);
03022     return TRUE;
03023   }
03024   return FALSE;
03025 }
03026 
03033 EXPORT_MSCPP
03034 int EXPORT_BORLAND
03035 icl_Arity(ICLTerm const*elt)
03036 {
03037   return icl_NumTerms(elt);
03038 }
03039 
03045 EXPORT_MSCPP
03046 int EXPORT_BORLAND
03047 icl_NumTerms(ICLTerm const*elt)
03048 {
03049   int len = 0;
03050 
03051   if (icl_IsList(elt) || icl_IsGroup(elt) || icl_IsStruct(elt)) {
03052 
03053     ICLListType *p;
03054 
03055     p = icl_List(elt);
03056     while (p) {
03057       p = p->next;
03058       ++len;
03059     }
03060   }
03061 
03062   return (len);
03063 }
03064 
03071 EXPORT_MSCPP
03072 int EXPORT_BORLAND
03073 icl_ListLen(ICLTerm const*elt){
03074   return icl_NumTerms(elt);
03075 }
03076 
03082 EXPORT_MSCPP
03083 ICLTerm * EXPORT_BORLAND icl_NthTerm(ICLTerm const*elt, int n)
03084 {
03085   ICLListType *p;
03086 
03087   if (icl_IsList(elt) || icl_IsStruct(elt) || icl_IsGroup(elt))
03088   {
03089     if(!icl_IsValid(elt)) {
03090       return NULL;
03091     }
03092 
03093     p = icl_List(elt);
03094   }
03095   else return (NULL);
03096 
03097   while (p && (n > 1)) {
03098     p = p->next;
03099     --n;
03100   }
03101   if (p)
03102     return (p->elt);
03103   else
03104     return (NULL);
03105 }
03106 
03112 EXPORT_MSCPP
03113 int EXPORT_BORLAND
03114 icl_NthTermAsInt(ICLTerm const*elt, int n, int *Value)
03115 {
03116   ICLTerm *v = icl_NthTerm(elt, n);
03117   if (v != NULL) {
03118     int tempInt = icl_Int(v);
03119     memcpy(Value, &tempInt, sizeof(int));
03120     return TRUE;
03121   }
03122   return FALSE;
03123 }
03124 
03136 EXPORT_MSCPP
03137 int EXPORT_BORLAND
03138 icl_ParamValue(char *func, ICLTerm *match, ICLTerm *paramlist, ICLTerm **value)
03139 {
03140   ICLListType *p;
03141   ICLTerm *test = (ICLTerm *)NULL;
03142   int found = FALSE;
03143 
03144 
03145   // only prepare the string if it will be used...
03146   if (DEBUG_LEVEL > 7) {
03147     char *debugString = icl_NewStringFromTerm(paramlist);
03148 
03149     printDebug(7, "icl_ParamValue : func %s\n", func);
03150     printDebug(7, "icl_ParamValue : paramlist %s\n", debugString);
03151     icl_stFree(debugString);
03152   }
03153 
03154   if (icl_IsList(paramlist) && func && *func && (icl_NumTerms(paramlist)>0)) {
03155     p = icl_List(paramlist);
03156   }
03157   else {
03158     return FALSE;
03159   }
03160 
03161   if (match) {
03162     test = icl_NewStruct(func, 1, icl_CopyTerm(match));
03163   }
03164   else {
03165     test = icl_NewStruct(func, 1, icl_NewVar("_"));
03166   }
03167 
03168   while(p && !found) {
03169 
03170     /* For debugging */
03171     // only prepare the strings if they will be used...
03172     if (DEBUG_LEVEL > 7) {
03173       char *s1, *s2;
03174 
03175       s1 = icl_NewStringStructFromTerm(test);
03176       s2 = icl_NewStringStructFromTerm(p->elt);
03177 
03178       printDebug(7, "icl_ParamValue : %s VS %s\n", s1, s2);
03179       icl_stFree(s1);
03180       icl_stFree(s2);
03181     }
03182     /* End for debugging */
03183 
03184     found = icl_Unify(test, p->elt, value);
03185     p = p->next;
03186   }
03187 
03188   // only prepare the string if it will be used...
03189   if (found && value && (DEBUG_LEVEL > 7)) {
03190     char *debugString = icl_NewStringFromTerm(*value);
03191 
03192     printDebug(7, "Found %s\n", debugString);
03193     icl_stFree(debugString);
03194   }
03195 
03196   icl_Free(test);
03197 
03198   return (found);
03199 }
03200 
03201 
03206 EXPORT_MSCPP
03207 gint64 EXPORT_BORLAND
03208 icl_ParamValueAsInt(char *func, ICLTerm *paramlist, gint64 *Value)
03209 {
03210   ICLTerm *v = NULL;
03211   int result = FALSE;
03212 
03213   if (Value && *Value &&
03214       icl_ParamValue(func, NULL, paramlist, &v)) {
03215     ICLTerm* temp_result = icl_NthTerm(v,1);
03216     if (icl_IsInt(temp_result)) {
03217       *Value = icl_Int(temp_result);
03218       result = TRUE;
03219     }
03220   }
03221   icl_Free(v);
03222   return result;
03223 }
03224 
03225 
03231 EXPORT_MSCPP
03232 int EXPORT_BORLAND
03233 icl_Member(ICLTerm const*elt, ICLTerm const*list, ICLTerm **res)
03234 {
03235   ICLListType *p;
03236   int found = FALSE;
03237 
03238   if (icl_IsList(list) && elt) {
03239     p = icl_List(list);
03240   }
03241   else {
03242     return FALSE;
03243   }
03244 
03245   while(p && !found) {
03246     found = icl_Unify(elt, p->elt, res);
03247     p = p->next;
03248   }
03249 
03250   return found;
03251 }
03252 
03253 
03254 /****************************************************************************
03255  * Unification
03256  ****************************************************************************/
03257 
03258 /****************************************************************************
03259  * name:    icl_bind_var
03260  * purpose: Stores a var/value pair in stringlist vars
03261  * inputs:
03262  *   - char *var: Variable name
03263  *   - char *value: Value
03264  *   - dyn_array vars: string list of var/value bindings
03265  * remarks:
03266  *   You can safely (and should!) free value after this, if necessary, as
03267  *   this function will copy it.
03268  ****************************************************************************/
03269 static
03270 void icl_bind_var(ICLTerm *var,
03271       ICLTerm *value,
03272       struct dyn_array *vars)
03273 {
03274   icl_append_dyn_array(vars, strdup(icl_Str(var)));
03275   icl_append_dyn_array(vars, icl_CopyTerm(value));
03276 }
03277 
03278 /****************************************************************************
03279  * name:    icl_deref
03280  * purpose: See if a variable can be resolved using existing variable bindings
03281  * inputs:
03282  *   - char *var: will return value if one can be found in var_bindings
03283  *   - char *var_bindings[]:
03284  *          A list stored with var/value in l[N]/l[N+1]
03285  ****************************************************************************/
03286 static
03287 void icl_deref(ICLTerm **var,
03288                struct dyn_array var_bindings)
03289 {
03290   int done = 0;
03291   int pos;
03292 
03293   do {
03294     if (!icl_IsVar(*var)) {
03295       return;
03296     }
03297 
03298     pos = icl_member_strlist(icl_Str(*var), var_bindings, 2, 0);
03299     if (pos >= 0) {
03300       *var = (ICLTerm *)var_bindings.item[pos+1];
03301     }
03302     else {
03303       done = 1;
03304     }
03305   } while (!done);
03306 
03307   return;
03308 }
03309 
03310 
03322 EXPORT_MSCPP
03323 int EXPORT_BORLAND icl_match_terms(ICLTerm *t1, ICLTerm *t2, struct dyn_array *vars)
03324 {
03325   int res;
03326   ICLListType *l1, *l2;
03327 
03328   /* Validate incoming arguments */
03329   if (!icl_IsValid(t1) || !icl_IsValid(t2)) {
03330     return FALSE;
03331   }
03332 
03333   if (vars) {
03334     icl_deref(&t1, *vars);
03335     icl_deref(&t2, *vars);
03336   }
03337 
03338   if (icl_IsVar(t1)) {
03339     /* Anonymous variable "_" never gets bound */
03340     if (vars) {
03341       /* && !STREQ(icl_Str(t1),"_") && !STREQ(icl_Str(t1),icl_Str(t2)))*/
03342       icl_bind_var(t1, t2, vars);
03343     }
03344     return TRUE;
03345   }
03346   else if (icl_IsVar(t2)) {
03347     /* Anonymous variable "_" never gets bound */
03348     if (vars) {
03349       /* && !STREQ(icl_Str(t2),"_") && !STREQ(icl_Str(t1),icl_Str(t2)))*/
03350       icl_bind_var(t2, t1, vars);
03351     }
03352     return TRUE;
03353   }
03354   else if (t1->iclType == t2->iclType) {
03355     /* Check that both are same types */
03356     if (t1->iclType == icl_float_type) {
03357       return (icl_Float(t1) == icl_Float(t2));
03358     }
03359     else if (t1->iclType == icl_int_type) {
03360       return (icl_Int(t1) == icl_Int(t2));
03361     }
03362     else if (t1->iclType == icl_str_type) {
03363       return (strcmp(icl_Str(t1), icl_Str(t2)) == 0);
03364     }
03365     else {
03366       if (t1->iclType == icl_struct_type) {
03367   if (strcmp(icl_Str(t1), icl_Str(t2)) != 0) {
03368     return FALSE;   /* check name, then fall through to args */
03369   }
03370       }
03371 
03372       if ((t1->iclType == icl_list_type) ||
03373     (t1->iclType == icl_group_type) ||
03374     (t1->iclType == icl_struct_type)) {
03375 
03376   l1 = icl_List(t1);
03377   l2 = icl_List(t2);
03378   res = TRUE;
03379 
03380   while (l1 && l2 && res) {
03381     res = icl_match_terms(l1->elt, l2->elt, vars);
03382     l1 = l1->next;
03383     l2 = l2->next;
03384   }
03385 
03386   return(!l1 && !l2 && res);
03387       }
03388       else {
03389   return FALSE;
03390       }
03391     }
03392   }
03393   else {
03394     /* t1 and t2 are not the same type */
03395     return FALSE;
03396   }
03397 }
03398 
03399 EXPORT_MSCPP
03400 int EXPORT_BORLAND icl_match_terms_DEBUG(ICLTerm *t1, ICLTerm *t2, struct dyn_array *vars)
03401 {
03402   int res;
03403   ICLListType *l1, *l2;
03404 
03405   printf("icl_match_terms_DEBUG\n");
03406 
03407   /* Validate incoming arguments */
03408   if (!icl_IsValid(t1) || !icl_IsValid(t2)) {
03409     printf("icl_match_terms_DEBUG One or the other is invalid\n");
03410     return FALSE;
03411   }
03412 
03413   if (vars) {
03414     icl_deref(&t1, *vars);
03415     icl_deref(&t2, *vars);
03416   }
03417 
03418   if (icl_IsVar(t1)) {
03419     /* Anonymous variable "_" never gets bound */
03420     if (vars) {
03421       /* && !STREQ(icl_Str(t1),"_") && !STREQ(icl_Str(t1),icl_Str(t2)))*/
03422       icl_bind_var(t1, t2, vars);
03423     }
03424     return TRUE;
03425   }
03426   else if (icl_IsVar(t2)) {
03427     /* Anonymous variable "_" never gets bound */
03428     if (vars) {
03429       /* && !STREQ(icl_Str(t2),"_") && !STREQ(icl_Str(t1),icl_Str(t2)))*/
03430       icl_bind_var(t2, t1, vars);
03431     }
03432     return TRUE;
03433   }
03434   else if (t1->iclType == t2->iclType) {
03435     /* Check that both are same types */
03436     if (t1->iclType == icl_float_type) {
03437       printf("icl_match_terms_DEBUG floats == %i\n", icl_Float(t1) == icl_Float(t2));
03438       return (icl_Float(t1) == icl_Float(t2));
03439     }
03440     else if (t1->iclType == icl_int_type) {
03441       printf("icl_match_terms_DEBUG ints == %i\n", icl_Int(t1) == icl_Int(t2));
03442       return (icl_Int(t1) == icl_Int(t2));
03443     }
03444     else if (t1->iclType == icl_str_type) {
03445       printf("icl_match_terms_DEBUG string types strcmp(%s,%s) = %i\n",
03446              icl_Str(t1), icl_Str(t2),
03447              strcmp(icl_Str(t1), icl_Str(t2)));
03448       return (strcmp(icl_Str(t1), icl_Str(t2)) == 0);
03449     }
03450     else {
03451       if (t1->iclType == icl_struct_type) {
03452   if (strcmp(icl_Str(t1), icl_Str(t2)) != 0) {
03453           printf("icl_match_terms_DEBUG mismatched struct names\n");
03454     return FALSE;   /* check name, then fall through to args */
03455   }
03456       }
03457 
03458       if ((t1->iclType == icl_list_type) ||
03459     (t1->iclType == icl_group_type) ||
03460     (t1->iclType == icl_struct_type)) {
03461 
03462   l1 = icl_List(t1);
03463   l2 = icl_List(t2);
03464   res = TRUE;
03465 
03466   while (l1 && l2 && res) {
03467     res = icl_match_terms_DEBUG(l1->elt, l2->elt, vars);
03468     l1 = l1->next;
03469     l2 = l2->next;
03470   }
03471 
03472   return(!l1 && !l2 && res);
03473       }
03474       else {
03475         printf("icl_match_terms_DEBUG bad type\n");
03476   return FALSE;
03477       }
03478     }
03479   }
03480   else {
03481     /* t1 and t2 are not the same type */
03482     printf("icl_match_terms_DEBUG different types: %i, %i\n", t1->iclType, t2->iclType);
03483     return FALSE;
03484   }
03485 }
03486 
03487 
03503 EXPORT_MSCPP
03504 int EXPORT_BORLAND icl_Unify(ICLTerm const*t1, ICLTerm const*t2, ICLTerm **answer)
03505 {
03506   struct dyn_array da;
03507   int result;
03508   int i;
03509 
03510   ICLTerm* renamed_t1 = icl_CopyTerm(t1);
03511   ICLTerm* renamed_t2 = icl_CopyTerm(t2);
03512   ICLTerm* toFree;
03513 
03514   da.count = 0;
03515   /* DEBUG */
03516   //printf("Unify t1 : %s\n", icl_NewStringFromTerm(t1));
03517   //printf("Unify t2 : %s\n", icl_NewStringFromTerm(t2));
03518 
03519   rename_vars_index=0;
03520   icl_rename_vars_term(&renamed_t1);
03521   icl_rename_vars_term(&renamed_t2);
03522 
03523   icl_init_dyn_array(&da);
03524 
03525   result = icl_match_terms(renamed_t1, renamed_t2, &da);
03526 
03527   if (result && answer) {
03528     CHECK_LEAKS();
03529     *answer = icl_copy_term(renamed_t1, &da);
03530     CHECK_LEAKS();
03531   }
03532 
03533   /* Free the dynamic array
03534    */
03535   for (i = 0; i < (da).count; i = i + 2) {
03536     free((da).item[i]);
03537     toFree = (ICLTerm*)(da.item[i + 1]);
03538     icl_Free(toFree);
03539   }
03540   free((da).item);
03541 
03542   icl_Free(renamed_t1);
03543   icl_Free(renamed_t2);
03544 
03545   CHECK_LEAKS();
03546   return result;
03547 }
03548 
03549 EXPORT_MSCPP
03550 int EXPORT_BORLAND icl_Unify_DEBUG(ICLTerm *t1, ICLTerm *t2, ICLTerm **answer)
03551 {
03552   struct dyn_array da;
03553   int result;
03554   int i;
03555 
03556   ICLTerm* renamed_t1 = icl_CopyTerm(t1);
03557   ICLTerm* renamed_t2 = icl_CopyTerm(t2);
03558   ICLTerm* toFree;
03559 
03560   /* DEBUG */
03561   //printf("Unify t1 : %s\n", icl_NewStringFromTerm(t1));
03562   //printf("Unify t2 : %s\n", icl_NewStringFromTerm(t2));
03563 
03564   rename_vars_index=0;
03565   icl_rename_vars_term(&renamed_t1);
03566   icl_rename_vars_term(&renamed_t2);
03567 
03568   icl_init_dyn_array(&da);
03569 
03570   result = icl_match_terms_DEBUG(renamed_t1, renamed_t2, &da);
03571   printf("result = %i\n", result);
03572 
03573   if (result && answer) {
03574     *answer = icl_copy_term(renamed_t1, &da);
03575   }
03576 
03577   /* Free the dynamic array
03578    */
03579   for (i = 0; i < (da).count; i = i + 2) {
03580     free((da).item[i]);
03581     toFree = (ICLTerm*)(da.item[i + 1]);
03582     icl_Free(toFree);
03583   }
03584   free((da).item);
03585 
03586   icl_Free(renamed_t1);
03587   icl_Free(renamed_t2);
03588 
03589   return result;
03590 }
03591 
03592 
03593 /****************************************************************************
03594  * Utility functions
03595  ****************************************************************************/
03596 
03601 EXPORT_MSCPP
03602 int    EXPORT_BORLAND
03603 icl_WriteTerm(ICLTerm *t)
03604 {
03605   if (icl_IsValid(t)) {
03606     char *s = icl_NewStringFromTerm(t);
03607     int res = (s != NULL);
03608 
03609     printf(s);
03610 
03611     icl_stFree(s);
03612     return res;
03613   }
03614   else return FALSE;
03615 }
03616 
03617 /****************************************************************************
03618  * Convenience functions for representing often-used terms
03619  ****************************************************************************/
03620 
03625 EXPORT_MSCPP
03626 ICLTerm * EXPORT_BORLAND
03627 icl_True()
03628 {
03629   static ICLTerm *icl_true = NULL;
03630 
03631   /* check to see if first time or somehow invalidated */
03632   if (!icl_IsValid(icl_true)) {
03633     icl_true = icl_NewStr("true");
03634     return icl_true;
03635   }
03636   else return icl_true;
03637 }
03638 
03639 EXPORT_MSCPP
03640 ICLTerm * EXPORT_BORLAND
03641 icl_False()
03642 {
03643   static ICLTerm *icl_false = NULL;
03644 
03645   /* check to see if first time or somehow invalidated */
03646   if (!icl_IsValid(icl_false)) {
03647     icl_false = icl_NewStr("false");
03648     return icl_false;
03649   }
03650   else return icl_false;
03651 }
03652 
03653 EXPORT_MSCPP
03654 ICLTerm * EXPORT_BORLAND
03655 icl_Empty()
03656 {
03657   static ICLTerm *icl_empty = NULL;
03658 
03659   /* check to see if first time or somehow invalidated */
03660   if (!icl_IsValid(icl_empty)) {
03661     icl_empty = icl_NewList(NULL);
03662     return icl_empty;
03663   }
03664   else {
03665     return icl_empty;
03666   }
03667 }
03668 
03669 EXPORT_MSCPP
03670 ICLTerm * EXPORT_BORLAND
03671 icl_Var()
03672 {
03673   static ICLTerm *icl_var = NULL;
03674 
03675   /* check to see if first time or somehow invalidated */
03676   if (icl_var && !icl_IsVar(icl_var)){
03677     icl_Free(icl_var);
03678     //icl_var = NULL;
03679   }
03680 
03681   if (!icl_IsValid(icl_var)) {
03682     icl_var = icl_NewVar("_");
03683     return icl_var;
03684   }
03685   else return icl_var;
03686 }
03687 
03688 
03689 /****************************************************************************
03690  * List management utility functions
03691  ****************************************************************************/
03692 
03696 int icl_list_has_more_elements(ICLListType *l)
03697 {
03698   if(l && (l->elt != NULL))
03699     return TRUE;
03700   return FALSE;
03701 }
03702 
03706 ICLListType *icl_list_next_element(ICLListType *l)
03707 {
03708   if(l)
03709     return l->next;
03710   else
03711     return NULL;
03712 }
03713 
03717 ICLTerm *icl_list_element(ICLListType *list)
03718 {
03719   return list->elt;
03720 }
03721 
03726 int icl_list_delete(ICLTerm *list, ICLTerm *elem, ICLTerm **residue)
03727 {
03728   ICLListType *iterator;
03729   if(!icl_IsList(list))
03730     return FALSE;
03731   iterator = icl_List(list);
03732   *residue = icl_NewList(NULL);
03733   while(icl_list_has_more_elements(iterator)) {
03734     ICLTerm *listel = icl_list_element(iterator);
03735     if(!icl_Unify(listel, elem, NULL)) {
03736       icl_AddToList(*residue, listel, TRUE);
03737     }
03738     iterator = icl_list_next_element(iterator);
03739   }
03740   return TRUE;
03741 }
03742 
03746 int icl_append_to_list(ICLTerm *list1, ICLTerm *list2, ICLTerm **list3)
03747 {
03748   ICLListType *l2;
03749 
03750   if (!icl_IsList(list2) || !icl_IsList(list1)) {
03751     return FALSE;
03752   }
03753 
03754   *list3 = icl_CopyTerm(list1);
03755   l2 = icl_List(list2);
03756 
03757   while(icl_ListHasMoreElements(l2)) {
03758     icl_AddToList(*list3, icl_CopyTerm(icl_ListElement(l2)), TRUE);
03759     l2 = icl_ListNextElement(l2);
03760   }
03761   return TRUE;
03762 }
03763 
03770 EXPORT_MSCPP
03771 ICLTerm* icl_GenerateSimpleUnifyingTerm(ICLTerm const*term)
03772 {
03773   ICLTerm* newTerm = NULL;
03774   int numTerms;
03775 
03776   if(!(icl_IsList(term) || icl_IsGroup(term) || icl_IsStruct(term))) {
03777     return icl_NewVar("_");
03778   }
03779 
03780   numTerms = icl_NumTerms(term);
03781 
03782   if(icl_IsStruct(term)) {
03783     char* functor = icl_Functor(term);
03784     ICLTerm* args = icl_NewList(NULL);
03785     {
03786       int i;
03787       for(i = 0; i < numTerms; ++i) {
03788         icl_AddToList(args, icl_NewVar("_"), TRUE);
03789       }
03790     }
03791     newTerm = icl_NewStructFromList(functor, args);
03792   }
03793   else {
03794     int i;
03795     newTerm = icl_CopyTerm(term);
03796     for(i = 0; i < numTerms; ++i) {
03797       icl_ReplaceElement(newTerm, i, icl_NewVar("_"), TRUE);
03798     }
03799   }
03800 
03801   return newTerm;
03802 }
03803 
03810 EXPORT_MSCPP
03811 int icl_ReplaceElement(ICLTerm* term, int index, ICLTerm* replacement, int freeReplaced)
03812 {
03813   if(!(icl_IsList(term) || icl_IsGroup(term) || icl_IsStruct(term))) {
03814     return FALSE;
03815   }
03816   else {
03817     ICLListType *p = icl_List(term);
03818     int i;
03819     for(i = 0; p && i < index; ++i) {
03820       p = p->next;
03821     }
03822     if(i != index) {
03823       return FALSE;
03824     }
03825     if(freeReplaced && p->elt) {
03826       icl_FreeTerm(p->elt);
03827     }
03828     p->elt = replacement;
03829 
03830     return TRUE;
03831   }
03832 }
03833 
03839 EXPORT_MSCPP
03840 int icl_ReplaceUnifying(ICLTerm* term, ICLTerm const* selector, ICLTerm const* replacement, int freeReplaced)
03841 {
03842   if(!(icl_IsList(term) || icl_IsGroup(term) || icl_IsStruct(term))) {
03843     return FALSE;
03844   }
03845   else {
03846     ICLListType *p;
03847     int numReplaced = 0;
03848     for(p = icl_List(term); p; p = p->next) {
03849       if(icl_Unify(p->elt, selector, NULL)) {
03850         if(freeReplaced) {
03851           icl_FreeTerm(p->elt);
03852         }
03853         p->elt = icl_CopyTerm(replacement);
03854         ++numReplaced;
03855       }
03856     }
03857     return numReplaced;
03858   }  
03859 }
03860 

Generated on Wed May 23 17:20:11 2007 using doxygen 1.5.2