libicl.c

来自「SRI international 发布的OAA框架软件」· C语言 代码 · 共 2,613 行 · 第 1/5 页

C
2,613
字号
      if(hashedVal != NULL) {
	free((*term)->p);
	(*term)->p = strdup(hashedVal);
      }
      else {
	char tempName[10];
	sprintf(tempName, "_%d", rename_vars_index);
	rename_vars_index++;
	htinsert((char *)((*term)->p),strdup(tempName),knownVars);
	free((*term)->p);
	(*term)->p = strdup(tempName);
      }
    }
    else
      if (((*term)->iclType == icl_list_type) ||
          ((*term)->iclType == icl_group_type) ||
          ((*term)->iclType == icl_struct_type)) {
        l = icl_List(*term);

        while (l) {
          icl_rename_vars_termhelper(&l->elt, knownVars);
          l = l->next;
        }
      }
  }
}

/**
 * Renames all unique vars in a term to "_NUM" format.
 * Used by asserts to get around variable name collisions
 */
static
void icl_rename_vars_term(ICLTerm **term)
{
  hthash_table knownVars;
  htconstruct_table(&knownVars, 271);
  icl_rename_vars_termhelper(term, &knownVars);
#ifdef NORMAL_GC
  htfree_table(&knownVars,GC_debug_free);
#else
  htfree_table(&knownVars,free);
#endif
}


/*****************************************************************************
 * Trace and error messages
 *****************************************************************************/


/****************************************************************************
 * Structure construction routines
 ****************************************************************************/

struct compoundInfo_s
{
  char* preChild;
  size_t preChildLen;
  char* postChild;
  size_t postChildLen;
  char* preAllButFirst;
  size_t preAllButFirstLen;
  char* postAllButLast;
  size_t postAllButLastLen;
  char* postPend;
  size_t postPendLen;
  int numChildrenToDo;
  int originalNumChildren;
}
;
typedef struct compoundInfo_s compoundInfo_t;

compoundInfo_t* compoundInfo_new()
{
  compoundInfo_t* res = (compoundInfo_t*)malloc(sizeof(compoundInfo_t));
  memset(res, 0, sizeof(compoundInfo_t));
  return res;
}

int compoundInfo_finished(compoundInfo_t* ci)
{
  if(ci->numChildrenToDo == 0) {
    return TRUE;
  }
  else {
    return FALSE;
  }
}

void compoundInfo_setNumChildren(compoundInfo_t* ci, int n)
{
  ci->numChildrenToDo = n;
  ci->originalNumChildren = n;
}

int compoundInfo_getCurrentChildNum(compoundInfo_t* ci)
{
  return ci->originalNumChildren - ci->numChildrenToDo;
}

void compoundInfo_setPreAllButFirst(compoundInfo_t* ci, char* s, size_t len)
{
  ci->preAllButFirst = s;
  ci->preAllButFirstLen = len;
}

void compoundInfo_setPostAllButLast(compoundInfo_t* ci, char* s, size_t len)
{
  ci->postAllButLast = s;
  ci->postAllButLastLen = len;
}

void compoundInfo_setPreChild(compoundInfo_t* ci, char* s, size_t len)
{
  ci->preChild = s;
  ci->preChildLen = len;
}

void compoundInfo_setPostChild(compoundInfo_t* ci, char* s, size_t len)
{
  ci->postChild = s;
  ci->postChildLen = len;
}

void compoundInfo_setPostPend(compoundInfo_t* ci, char* s, size_t len)
{
  ci->postPend = s;
  ci->postPendLen = len;
}

char* compoundInfo_getPreChild(compoundInfo_t* ci, int i, size_t* len)
{
  if(ci->preAllButFirst != NULL) {
    if(i != 0) {
      *len = ci->preAllButFirstLen;
      return ci->preAllButFirst;
    }
    else {
      *len = 0;
      return NULL;
    }
  }
  else {
    *len = ci->preChildLen;
    return ci->preChild;
  }
}

char* compoundInfo_getPostChild(compoundInfo_t* ci, int i, size_t* len)
{
  if(ci->postAllButLast != NULL) {
    if(i != ci->originalNumChildren - 1) {
      *len = ci->postAllButLastLen;
      return ci->postAllButLast;
    }
    else {
      *len = 0;
      return NULL;
    }
  }
  else {
    *len = ci->postChildLen;
    return ci->postChild;
  }
}

char* compoundInfo_getPostPend(compoundInfo_t* ci, size_t* len)
{
  *len = ci->postPendLen;
  return ci->postPend;
}

void compoundInfo_childFinished(compoundInfo_t* ci)
{
  --(ci->numChildrenToDo);
}

/**
 * You must free termAsString when you are done with it.
 */
int icl_toWireString(ICLTerm* t, char** termAsString, size_t* termAsStringLen)
{
  GByteArray* bytes = g_byte_array_new();
  GPtrArray* compoundList = g_ptr_array_new();
  GPtrArray* workingList = g_ptr_array_new();
  ICLTerm* currentTerm = NULL;
  compoundInfo_t* sentinel;
  compoundInfo_t* ci;
  compoundInfo_t* currentCompound;
  char startChar;
  char* separator;
  int childNum;
  char* tmpData;
  size_t tmpLen;
  int numberLen;
  int isCompound;
  int numArgs;
  char* functor;
  int zeroLenCompound = FALSE;
  int compoundSize = 0;
  int i;
  unsigned int ui;

  /*
  {
    char* ds = icl_NewStringFromTerm(t);
    printf("icl_toWireString() working on %s\n", ds);
    icl_stFree(ds);
  }
  */

  g_ptr_array_add(workingList, t);

  sentinel = compoundInfo_new();
  sentinel->numChildrenToDo = 1;
  sentinel->originalNumChildren = 1;
  g_ptr_array_add(compoundList, sentinel);

  while((compoundList->len > 0) ||
        (workingList->len > 0)) {
    zeroLenCompound = FALSE;
    currentTerm = (ICLTerm*)g_ptr_array_index(workingList, workingList->len - 1);
    (void)g_ptr_array_remove_index(workingList, workingList->len - 1);
    currentCompound = (compoundInfo_t*)g_ptr_array_index(compoundList, compoundList->len - 1);
    childNum = compoundInfo_getCurrentChildNum(currentCompound);
    tmpData = compoundInfo_getPreChild(currentCompound, childNum, &tmpLen);
    if(tmpData != NULL) {
      g_byte_array_append(bytes, tmpData, tmpLen);
    }
    switch(currentTerm->iclType) {
    case icl_list_type:
      g_byte_array_append(bytes, "[", 1);
      numArgs = icl_NumTerms(currentTerm);
      ci = compoundInfo_new();
      compoundInfo_setPostPend(ci, "]", 1);
      compoundInfo_setNumChildren(ci, numArgs);
      compoundInfo_setPreAllButFirst(ci, ",", 1);
      g_ptr_array_add(compoundList, ci);
      isCompound = TRUE;
      break;
    case icl_group_type:
      icl_GetGroupChars(currentTerm, &startChar, &separator);
      icl_stFree(separator);
      g_byte_array_append(bytes, &startChar, 1);
      numArgs = icl_NumTerms(currentTerm);
      ci = compoundInfo_new();
      switch(startChar) {
      case '{':
        compoundInfo_setPostPend(ci, "}", 1);
      default:
        compoundInfo_setPostPend(ci, ")", 1);
      }
      compoundInfo_setNumChildren(ci, numArgs);
      compoundInfo_setPreAllButFirst(ci, ",", 1);
      g_ptr_array_add(compoundList, ci);
      isCompound = TRUE;
      break;
    case icl_struct_type:
      functor = icl_Functor(currentTerm);
      numArgs = icl_NumTerms(currentTerm);
      ci = compoundInfo_new();
      g_byte_array_append(bytes, functor, strlen(functor));
      g_byte_array_append(bytes, "(", 1);
      compoundInfo_setPostPend(ci, ")", 1);
      compoundInfo_setNumChildren(ci, numArgs);
      compoundInfo_setPreAllButFirst(ci, ",", 1);
      g_ptr_array_add(compoundList, ci);
      isCompound = TRUE;
      break;
    case icl_int_type:
    case icl_float_type:
    case icl_str_type:
    case icl_var_type:
    case icl_dataq_type:
      isCompound = FALSE;
      numArgs = 0;
      break;
    default:
      fprintf(stderr, "libicl.c icl_toWireString() unknown type [%i] in term at %p\n", currentTerm->iclType, currentTerm);
      return FALSE;
    }

    if(isCompound) {
      ICLTerm* toAdd;
      /*
      printf("Found compound with %i args; compoundList has %i elements\n", numArgs, compoundList->len);
      */
      if(numArgs > 0) {
        for(i = numArgs - 1; i >= 0; --i) {
          toAdd = icl_NthTerm(currentTerm, i + 1);
          g_ptr_array_add(workingList, toAdd);

          {
            char* ds = icl_NewStringFromTerm(toAdd);
            //printf("Added child [%s] at index %i to workingList; workingList length = %i\n", ds, i, workingList->len);
            icl_stFree(ds);
          }

        }
        continue;
      }
      else {
        zeroLenCompound = TRUE;
      }
    }

    compoundSize = compoundList->len;
    currentCompound = (compoundInfo_t*)g_ptr_array_index(compoundList, compoundList->len - 1);
    if(!zeroLenCompound) {
      switch(currentTerm->iclType) {
      case icl_int_type:
        numberLen = snprintf(NULL, 0, "%lld", *((gint64*)currentTerm->p));
        if(numberLen < 0) {
          numberLen = 128;
        }
        tmpData = (char*)malloc(numberLen + 1);
        numberLen = snprintf(tmpData, numberLen + 1, "%lld", *((gint64*)currentTerm->p));
        if(numberLen < 0) {
          numberLen = 128;
        }
        g_byte_array_append(bytes, tmpData, strlen(tmpData));
        /*
        printf("Wrote %i bytes for integer %s\n", numberLen, tmpData);
        */
        free(tmpData);
        break;
      case icl_float_type:
        numberLen = snprintf(NULL, 0, "%f", *((double*)currentTerm->p));
        if(numberLen < 0) {
          numberLen = 128;
        }
        tmpData = (char*)malloc(numberLen + 1);
        numberLen = snprintf(tmpData, numberLen + 1, "%f", *((double*)currentTerm->p));
        if(numberLen < 0) {
          numberLen = 128;
        }
        g_byte_array_append(bytes, tmpData, strlen(tmpData));
        /*
        printf("Wrote %i bytes for float %s\n", numberLen, tmpData);
        */
        free(tmpData);
        break;
      case icl_var_type:
        g_byte_array_append(bytes, (char*)currentTerm->p, strlen((char*)currentTerm->p));
        /*
        printf("Wrote %i bytes for var %s\n", strlen((char*)currentTerm->p), (char*)currentTerm->p);
        */
        break;
      case icl_str_type:
        if(currentTerm->hadQuotes == 1) {
          tmpData = icl_stQuoteForce((char*)currentTerm->p);
        }
        else {
          tmpData = icl_stQuote((char*)currentTerm->p);
        }
        g_byte_array_append(bytes, tmpData, strlen(tmpData));

        /* printf("Wrote %i bytes for str %s\n", strlen((char*)currentTerm->p), (char*)currentTerm->p); */

        /* don't free tmpData--I'd rather icl_stQuote returned new memory, but
         * that's not the way it is
         */
        break;
      case icl_dataq_type:
        tmpData = (char*)currentTerm->p;
        /* printf("Writing icl_dataq_type of length %i\n", currentTerm->len); */
        g_byte_array_append(bytes, "icldataq(\"", 10);
        for(ui = 0; ui < currentTerm->len; ++ui) {
          if(tmpData[ui] == '"') {
            g_byte_array_append(bytes, "\"\"", 2);
          }
          else {
            g_byte_array_append(bytes, &tmpData[ui], 1);
          }
        }
        g_byte_array_append(bytes, "\")", 2);
        break;
      default:
        fprintf(stderr, "libicl.c icl_toWireString() unknown non-compound type [%i] at %p\n", currentTerm->iclType, currentTerm);
        return FALSE;
      }
      tmpData = compoundInfo_getPostChild(currentCompound, compoundInfo_getCurrentChildNum(currentCompound), &tmpLen);
      if(tmpData != NULL) {
        g_byte_array_append(bytes, tmpData, tmpLen);
      }
      compoundInfo_childFinished(currentCompound);
      /*
      printf("Child finished for current compound\n");
      */
    }
    else {
      /* nothing */
    }

    while(compoundInfo_finished(currentCompound)) {
      tmpData = compoundInfo_getPostPend(currentCompound, &tmpLen);
      if(tmpData != NULL) {
        g_byte_array_append(bytes, tmpData, tmpLen);
        /*
        printf("Wrote %i bytes for postPend on compound %s\n", tmpLen, tmpData);
        */
      }
      (void)g_ptr_array_remove_index(compoundList, compoundList->len - 1);
      free(currentCompound);
      /*
      printf("Compound finished compoundList length = %i\n", compoundList->len);
      */
      if(compoundList->len == 0) {
#ifdef NORMAL_GC
        *termAsString = (char*)malloc(bytes->len);
        memcpy(*termAsString, bytes->data, bytes->len);
        *termAsStringLen = bytes->len;
        g_byte_array_free(bytes, FALSE);
        g_ptr_array_free(compoundList, TRUE);
        g_ptr_array_free(workingList, TRUE);
#else
        *termAsString = bytes->data;
        *termAsStringLen = bytes->len;
        g_byte_array_free(bytes, FALSE);
        g_ptr_array_free(compoundList, TRUE);
        g_ptr_array_free(workingList, TRUE);
#endif
        return TRUE;
      }
      currentCompound = (compoundInfo_t*)g_ptr_array_index(compoundList, compoundList->len - 1);
      tmpData = compoundInfo_getPostChild(currentCompound, compoundInfo_getCurrentChildNum(currentCompound), &tmpLen);
      if(tmpData != NULL) {
        g_byte_array_append(bytes, tmpData, tmpLen);
      }
      compoundInfo_childFinished(currentCompound);
      /*
      printf("Child finished for current compound (through adding another compound)\n");
      */
    }
  }
  fprintf(stderr, "libicl.c icl_toWireString() This should never be reached\n");
  g_byte_array_free(bytes, TRUE);
  g_ptr_array_free(compoundList, TRUE);
  g_ptr_array_free(workingList, TRUE);
  return FALSE;
}

/**
 * Create a new IclTerm from the given data.
 *
 * @param data the data representing the term.
 * @param len the length of the data. If data is a char*,
 * this does not include the ending '\0' character.
 */
EXPORT_MSCPP
ICLTerm* EXPORT_BORLAND
icl_NewTermFromData(char* data, size_t len)
{
  ICLTerm* res = parser_getTermFromString(data, len);
  CHECK_LEAKS();
  return res;
}

/**
 * Returns a pointer to a new structured Icl term given string
 * containing an ICL expression,
 * or NULL if a valid object could not be created.
 *
 * @deprecated Use icl_NewTermFromData() instead
 */
EXPORT_MSCPP
ICLTerm * EXPORT_BORLAND
icl_NewTermFromString(char* t)
{
  ICLTerm* res = NULL;
  if(t != NULL) {
    res = icl_NewTermFromData(t, strlen(t));
    CHECK_LEAKS();
    return res;
  }
  else {
    return NULL;
  }
}


/**
 * Creates a string representation from an ICL term.
 * The string value is created in a new space which should be
 * icl_stFree'd when finished using.
 */
EXPORT_MSCPP
char * EXPORT_BORLAND
icl_NewStringFromTerm(ICLTerm *t)
{
  char *res = NULL;
  char* tmp = NULL;
  int tmpBufSz = 0;


  if (t==NULL)
    return NULL;

  /* Make sure the term is OK */
  if (!icl_IsValid(t))
    return NULL;

  if (icl_IsVar(t)) {
    res = strdup(t->p);
  }
  else if (icl_IsInt(t)) {
    tmpBufSz = snprintf(tmp, 0, "%lld", icl_Int(t));
    if(tmpBufSz < 0) {
      tmpBufSz = 128;
    }
    ++tmpBufSz;
    tmp = (char*)malloc(tmpBufSz * sizeof(char));
    (void)memset(tmp, 0, tmpBufSz);
    snprintf(tmp, tmpBufSz, "%lld", icl_Int(t));
    res = tmp;
  }
  else if (icl_IsFloat(t)) {
    tmpBufSz = snprintf(tmp, 0, "%f", icl_Float(t));
    if(tmpBufSz < 0) {
      tmpBufSz = 128;
    }
    ++tmpBufSz;
    tmp = (char*)malloc(tmpBufSz * sizeof(char));

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?