libicl.c

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

C
2,613
字号
    (void)memset(tmp, 0, tmpBufSz);
    snprintf(tmp, tmpBufSz, "%f", icl_Float(t));
    res = tmp;
  }
  else if (icl_IsStr(t)) {
    if(t->hadQuotes == 1) {
      res = strdup(icl_stQuoteForce(t->p));
    }
    else {
      res = strdup(icl_stQuote(t->p));
    }
  }
  else if(icl_IsDataQ(t)) {
    /* icldataq("") */
    res = (char*)malloc(icl_Len(t) + 1);
    res = memcpy(res, icl_DataQ(t), icl_Len(t));
    res[icl_Len(t)] = '\0';
  }
  else if (icl_IsStruct(t)) {
    int first = TRUE;
    ICLListType *args;

    /* Checks for struct that are operators */
    if (icl_stIsOperator(icl_Functor(t))>0) {
      args = icl_Arguments(t);
      /* Left operand */
      icl_stAppend(&res, icl_NewStringFromTerm(args->elt));
      /* Operator */
      icl_stAppend(&res, icl_Functor(t));
      /* Right operand */
      args = args->next;
      if (args) {
        icl_stAppend(&res, icl_NewStringFromTerm(args->elt));
      }
    }
    else {
      res = strdup(icl_Functor(t));
      args = icl_Arguments(t);
      icl_stAppend(&res, "(");
      while (args) {
        char *arg;
        arg = icl_NewStringFromTerm(args->elt);
        if (first) {
          first = FALSE;
        }
        else {
          icl_stAppend(&res, ",");
        }
        icl_stAppend(&res, arg);
        icl_stFree(arg);
        args = args->next;
      }
      icl_stAppend(&res, ")");
    }
  }
  else if (icl_IsList(t)) {
    int first = TRUE;
    ICLListType *args;
    args = icl_List(t);
    res = strdup("[");
    while (args) {
      char *arg;
      arg = icl_NewStringFromTerm(args->elt);
      if (first)
        first = FALSE;
      else icl_stAppend(&res, ",");
      icl_stAppend(&res, arg);
      icl_stFree(arg);
      args = args->next;
    }
    icl_stAppend(&res, "]");
  }
  else if (icl_IsGroup(t)) {
    int first = TRUE;
    ICLListType *args;
    char start;
    char *separator;

    icl_GetGroupChars(t, &start, &separator);
    args = icl_List(t);
    res = strdup("[");
    res[0] = start;
    while (args) {
      char *arg;
      arg = icl_NewStringFromTerm(args->elt);
      if (first)
        first = FALSE;
      else icl_stAppend(&res, separator);
      icl_stAppend(&res, arg);
      icl_stFree(arg);
      args = args->next;
    }
    icl_stAppend(&res, "]");
    if (start == '(')
      res[strlen(res)-1] = start + 1;  /* () */
    else
      res[strlen(res)-1] = start + 2;  /* {|} and [\] */

    icl_stFree(separator);
  }
  else {
    fprintf(stderr, "Unknown term type for icl_NewStringFromTerm: %i\n", t->iclType);
  }

  return (res);
}

/****************************************************************************
 * name:    pt
 * purpose: Debug
 ****************************************************************************/

EXPORT_MSCPP
char * EXPORT_BORLAND
pt(ICLTerm *t)
{
  return icl_NewStringFromTerm(t);
}

/**
 * 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.
 * @see icl_stFree
 */
EXPORT_MSCPP
char * EXPORT_BORLAND
icl_NewStringStructFromTerm(ICLTerm *t)
{
  int tmpBufSz = 0;
  char *res = NULL;
  char* tmp = NULL;

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

  if (icl_IsVar(t)) {
    tmpBufSz = snprintf(tmp, 0, "var(%s)", (char*)(t->p));
    ++tmpBufSz;
    tmp = (char*)malloc(tmpBufSz * sizeof(char));
    memset(tmp, 0, tmpBufSz);
    snprintf(tmp, tmpBufSz, "var(%s)", (char*)(t->p));
    res = tmp;
  }
  else if (icl_IsInt(t)) {
    tmpBufSz = snprintf(tmp, 0, "int(%lld)", icl_Int(t));
    ++tmpBufSz;
    tmp = (char*)malloc(tmpBufSz * sizeof(char));
    memset(tmp, 0, tmpBufSz);
    snprintf(tmp, tmpBufSz, "int(%lld)", icl_Int(t));
    res = tmp;
  }
  else if (icl_IsFloat(t)) {
    tmpBufSz = snprintf(tmp, 0, "float(%f)", icl_Float(t));
    ++tmpBufSz;
    tmp = (char*)malloc(tmpBufSz * sizeof(char));
    memset(tmp, 0, tmpBufSz);
    snprintf(tmp, tmpBufSz, "float(%f)", icl_Float(t));
    res = tmp;
  }
  else if (icl_IsStr(t)) {
    tmpBufSz = snprintf(tmp, 0, "str(%s)", icl_stQuote(t->p));
    ++tmpBufSz;
    tmp = (char*)malloc(tmpBufSz * sizeof(char));
    memset(tmp, 0, tmpBufSz);
    snprintf(tmp, tmpBufSz, "str(%s)", icl_stQuote(t->p));
    res = tmp;
  }
  else if (icl_IsStruct(t)) {
    int first = TRUE;
    ICLListType *args;
    tmpBufSz = snprintf(tmp, 0, "struct(%s,", icl_Functor(t));
    ++tmpBufSz;
    tmp = (char*)malloc(tmpBufSz * sizeof(char));
    memset(tmp, 0, tmpBufSz);
    snprintf(tmp, tmpBufSz, "struct(%s,", icl_Functor(t));
    res = tmp;
    args = icl_Arguments(t);
    icl_stAppend(&res, "(");
    while (args) {
      char *arg;
      arg = icl_NewStringStructFromTerm(args->elt);
      if (first) {
	first = FALSE;
      }
      else {
	icl_stAppend(&res, ",");
      }
      icl_stAppend(&res, arg);
      icl_stFree(arg);
      args = args->next;
    }
    icl_stAppend(&res, ")");
  }
  else if (icl_IsList(t)) {
    int first = TRUE;
    ICLListType *args;
    args = icl_List(t);
    res = strdup("list([");
    while (args) {
      char *arg;
      arg = icl_NewStringStructFromTerm(args->elt);
      if (first) {
	first = FALSE;
      }
      else {
	icl_stAppend(&res, ",");
      }
      icl_stAppend(&res, arg);
      icl_stFree(arg);
      args = args->next;
    }
    icl_stAppend(&res, "])");
  }
  else if (icl_IsGroup(t)) {
    int first = TRUE;
    ICLListType *args;
    char start;
    char *separator;

    icl_GetGroupChars(t, &start, &separator);
    args = icl_List(t);
    res = strdup("group([");
    while (args) {
      char *arg;
      arg = icl_NewStringStructFromTerm(args->elt);
      if (first) {
	first = FALSE;
      }
      else {
	icl_stAppend(&res, separator);
      }
      icl_stAppend(&res, arg);
      icl_stFree(arg);
      args = args->next;
    }
    icl_stAppend(&res, "])");
    if (start == '(') {
      res[strlen(res)-1] = start + 1;  /* () */
    }
    else {
      res[strlen(res)-1] = start + 2;  /* {|} and [\] */
    }

    icl_stFree(separator);
  }
  return (res);
}

enum CompoundType {
  compound_sentinel_type,
  compound_struct_type,
  compound_list_type,
  compound_group_type
}
;

struct CompoundInfo
{
  enum CompoundType cType;
  void* p;
  int numArgsExpected;
}
;

struct CompoundStructType
{
  char* functor;
  ICLListType* args;
}
;

struct CompoundListType
{
  ICLListType* args;
}
;

struct CompoundGroupType
{
  char startC;
  char* sep;
  ICLListType* args;
}
;

struct CompoundSentinelType
{
  ICLTerm* term;
}
;

static void icl_add_compound_argument(struct CompoundInfo* ci, ICLTerm* t)
{
  struct CompoundStructType* structCompound;
  struct CompoundListType* listCompound;
  struct CompoundGroupType* groupCompound;

  switch(ci->cType) {
  case compound_struct_type:
    structCompound = (struct CompoundStructType*)ci->p;
    if(!structCompound->args) {
      structCompound->args = icl_NewCons(t, NULL);
    }
    else {
      structCompound->args = icl_NewCons(t, structCompound->args);
    }
    ci->numArgsExpected--;
    break;
  case compound_list_type:
    listCompound = (struct CompoundListType*)ci->p;
    if(!listCompound->args) {
      listCompound->args = icl_NewCons(t, NULL);
    }
    else {
      listCompound->args = icl_NewCons(t, listCompound->args);
    }
    ci->numArgsExpected--;
    break;
  case compound_group_type:
    groupCompound = (struct CompoundGroupType*)ci->p;
    if(!groupCompound->args) {
      groupCompound->args = icl_NewCons(t, NULL);
    }
    else {
      groupCompound->args = icl_NewCons(t, groupCompound->args);
    }
    ci->numArgsExpected--;
    break;
  case compound_sentinel_type:
    ((struct CompoundSentinelType*)ci->p)->term = t;
    ci->numArgsExpected--;
    break;
  default:
    fprintf(stderr, "Unknown compound type\n");
    break;
  }
  if(ci->numArgsExpected < 0) {
    fprintf(stderr, "numArgsExpected < 0\n");
  }
}

/**
 * Creates a copy of the term, all in new memory.
 * Deref vars from binding list if available. Nonrecursive.
 */
EXPORT_MSCPP
ICLTerm *EXPORT_BORLAND
icl_copy_term_nonrec(ICLTerm* t, struct dyn_array* vars)
{
  struct dyn_array termStack;
  struct dyn_array compoundStack;
  ICLTerm* currTerm = NULL;
  struct CompoundInfo* currCompound;
  struct CompoundStructType* structCompound;
  struct CompoundListType* listCompound;
  struct CompoundGroupType* groupCompound;
  struct CompoundSentinelType sentinelCompound;
  struct CompoundInfo sentinelCI;

  if(t == NULL) {
    return NULL;
  }

  icl_init_dyn_array(&termStack);
  icl_append_dyn_array(&termStack, t);
  icl_init_dyn_array(&compoundStack);
  sentinelCI.p = &sentinelCompound;
  sentinelCI.cType = compound_sentinel_type;
  sentinelCI.numArgsExpected = 1;
  icl_append_dyn_array(&compoundStack, &sentinelCI);
  if(termStack.count == 0) {
    fprintf(stderr, "icl_copy_term_nonrec termStack count is 0!\n");
  }
  while(termStack.count != 0) {
    currTerm = (ICLTerm*)termStack.item[termStack.count - 1];
    termStack.item[termStack.count - 1] = NULL;
    termStack.count--;
    if(vars) {
      icl_deref(&currTerm, *vars);
    }

    if(icl_IsVar(currTerm)) {
      currTerm = icl_NewVar(icl_Str(currTerm));
    }
    else if(icl_IsInt(currTerm)) {
      currTerm = icl_NewInt(icl_Int(currTerm));
    }
    else if(icl_IsFloat(currTerm)) {
      currTerm = icl_NewFloat(icl_Float(currTerm));
    }
    else if(icl_IsStr(currTerm)) {
      currTerm = icl_NewStr(icl_Str(currTerm));
    }
    else if(icl_IsDataQ(currTerm)) {
      currTerm = icl_NewDataQ(icl_DataQ(currTerm), icl_Len(currTerm));
    }
    else if(icl_IsStruct(currTerm)) {
      /* Take the arguments of the struct, and put them into
       * the termStack, in the current order.  Note that this
       * means when we recreate the struct, we have to reverse
       * the order of the arguments!
       */
      struct CompoundInfo* ci = (struct CompoundInfo*)malloc(sizeof(struct CompoundInfo)) ;
      struct CompoundStructType* c = (struct CompoundStructType*)malloc(sizeof(struct CompoundStructType));
      ICLListType* args = icl_Arguments(currTerm);
      ci->p = c;
      ci->cType = compound_struct_type;
      ci->numArgsExpected = 0;
      c->functor = icl_Functor(currTerm);
      c->args = NULL;
      while(args) {
	ci->numArgsExpected++;
	icl_append_dyn_array(&termStack, args->elt);
	args = args->next;
      }
      icl_append_dyn_array(&compoundStack, ci);
      if(ci->numArgsExpected > 0) {
	continue;
      }
    }
    else if(icl_IsList(currTerm)) {
      struct CompoundInfo* ci = (struct CompoundInfo*)malloc(sizeof(struct CompoundInfo));
      struct CompoundListType* c = (struct CompoundListType*)malloc(sizeof(struct CompoundListType));
      ICLListType* args = icl_List(currTerm);
      ci->p = c;
      ci->cType = compound_list_type;
      ci->numArgsExpected = 0;
      c->args = NULL;
      while(args) {
	ci->numArgsExpected++;
	icl_append_dyn_array(&termStack, args->elt);
	args = args->next;
      }
      icl_append_dyn_array(&compoundStack, ci);
      if(ci->numArgsExpected > 0) {
	continue;
      }
    }
    else if(icl_IsGroup(currTerm)) {
      struct CompoundInfo* ci = (struct CompoundInfo*)malloc(sizeof(struct CompoundInfo));
      struct CompoundGroupType* c = (struct CompoundGroupType*)malloc(sizeof(struct CompoundGroupType));
      ICLListType* args = icl_List(currTerm);
      ci->p = c;
      ci->cType = compound_group_type;
      ci->numArgsExpected = 0;
      c->args = NULL;
      icl_GetGroupChars(currTerm, &(c->startC), &(c->sep));
      while(args) {
	ci->numArgsExpected++;
	icl_append_dyn_array(&termStack, args->elt);
	args = args->next;
      }
      icl_append_dyn_array(&compoundStack, ci);
      if(ci->numArgsExpected > 0) {
	continue;
      }
    }
    else if(currTerm == NULL) {
      currTerm = NULL;
    }
    else {
      char* s = icl_NewStringFromTerm(t);
      fprintf(stderr, "Unknown type in icl_copy_term_nonrec: [%s]\n", s);
      icl_stFree(s);
      currTerm = NULL;
    }

    /* currTerm == NULL or some term; add it to the current compound
       info structure
    */

    currCompound = (struct CompoundInfo*)compoundStack.item[compoundStack.count - 1];

    if(currCompound->numArgsExpected > 0) {
      icl_add_compound_argument(currCompound, currTerm);
    }

    while(currCompound->numArgsExpected == 0) {
      switch(currCompound->cType) {
      case compound_struct_type:
	structCompound = (struct CompoundStructType*)currCompound->p;
	currTerm = icl_NewStructFromList(structCompound->functor, icl_NewList(structCompound->args));
	free(structCompound);
	free(currCompound);
	structCompound = NULL;
	currCompound = NULL;
	break;
      case compound_list_type:
	listCompound = (struct CompoundListType*)currCompound->p;
	currTerm = icl_NewList(listCompound->args);
	free(listCompound);
	free(currCompound);
	listCompound = NULL;
	currCompound = NULL;
	break;
      case compound_group_type:
	groupCompound = (struct CompoundGroupType*)currCompound->p;
	currTerm = icl_NewGroup(groupCompound->startC, groupCompound->sep, groupCompound->args);
	free(groupCompound);
	free(currCompound);
	groupCompound = NULL;
	currCompound = NULL;
	break;
      case compound_sentinel_type:
	if(compoundStack.count != 1) {
	  fprintf(stderr, "icl_copy_term_nonrec got sentinel but nonempty compoundStack\n");
	}
	if(compoundStack.item != NULL) {
	  free(compoundStack.item);
	}
	if(termStack.item != NULL) {
	  free(termStack.item);
	}
	CHECK_LEAKS();
	return ((struct CompoundSentinelType*)(currCompound->p))->term;
	break;
      default:
	fprintf(stderr, "icl_copy_term_nonrec got unknown compound type\n");
	if(compoundStack.item != NULL) {
	  free(compoundStack.item);

⌨️ 快捷键说明

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