libicl_private.c

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

C
1,108
字号
#include "stdpccts.h"
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "libicl_private.h"
#include "libicl_depr.h"
#include "libicl.h"

#ifdef _WINDOWS
#include "oaa-windows.h"
#endif

#define EXPORT_BORLAND 

#ifdef IS_DLL
#define EXPORT_MSCPP __declspec(dllexport)  
#else
#define EXPORT_MSCPP
#endif

#ifndef STREQ
#define STREQ(str1, str2) (strcmp((str1), (str2)) == 0)
#endif

char* ICLDATAQSTART = "icldataq(";
size_t ICLDATAQSTARTLEN = 9;
char last_separator = ',';

/*****************************************************************************
 * Operators representation
 *****************************************************************************/
SOperator operators[] = {
  { ":-", 1 },
  { ":", 1 },
  { "+", 2 },
  { "-", 2 },
  { "*", 3 },
  { "/", 3 },
  { "dummy", -1 }
};

ICLTerm*
icl_NewTermFromDataDebug(char* data, size_t len) 
{
  return parser_getTermFromStringDebug(data, len);
}

/**
 * Add a child to a compound term
 */
void icl_addChild(ICLTerm* compound, ICLTerm* child) 
{
  ICLListType* children = icl_List(compound);
  if(!(icl_IsList(compound) || 
       icl_IsGroup(compound) ||
       icl_IsStruct(compound))) {
    fprintf(stderr, "icl_addChild attempted to add a child to non-compound term\n");
    return;
  }

  if(children != NULL) {
    while(children->next != NULL) {
      children = children->next;
    }

    children->next = (ICLListType*)malloc(sizeof(ICLListType));
    children->next->elt = child;
    children->next->next = NULL;
  }
  else {
    if(icl_IsStruct(compound)) {
      ICLStructType* st = (ICLStructType*)compound->p;
      children = (ICLListType*)malloc(sizeof(ICLListType));
      children->elt = child;
      children->next = NULL;
      st->args = icl_NewList(children);
    }
    else if(icl_IsList(compound)) {
      ICLListType* lt = (ICLListType*)malloc(sizeof(ICLListType));
      compound->p = lt;
      lt->elt = child;
      lt->next = NULL;
    }
    else if(icl_IsGroup(compound)) {
      ICLGroupType* gt = (ICLGroupType*)compound->p;
      children = (ICLListType*)malloc(sizeof(ICLListType));
      children->elt = child;
      children->next = NULL;
      gt->list = children;
    }
  }
}

/****************************************************************************
 * name:    icl_stChunkTerm
 * purpose: takes a list of terms (comma separated) and returns the first (car)
 *          and rest (cdr) of the list.
 * inputs:
 *   - char *terms: a list of prolog terms
 * outputs:
 *   - char     *aterm: the first term in the list
 *   - char *restterms: the rest of the terms
 * remarks:
 *   - Terms may be nested arbitrarily deep (eg. a(b(c(d,1)), X).
 *   - aterm will return a new copy of the first argument, which should
 *     be free'd when finished using.  restterms will return a pointer
 *     into terms.
 *   - Term can correctly parse expression with embedded arguments using
 *     Japanese JIS7 format.  JIS7 is the Japanese encoding standard chosen
 *     for use with the OAA.  Three reasons for this choice:  1) it's the
 *     most popular standard on UNIX machines.  2) 7-bit encoding should
 *     be TCP/IP and modem friendly.  3) it's easy to parse: JIS7 embeds
 *     Japanese characters in a quotation-like wrapper, using ESC$B for the
 *     opening marker and ESC(B for the closing.
 * returns: 
 *     TRUE if a term was read, FALSE if a complete term could not be read.
 *     In the latter case, aterm and restterms returns "" as well--these
 *     still need to be freed
 ****************************************************************************/
EXPORT_MSCPP
int EXPORT_BORLAND icl_safeStTerm(char *terms,
                                  size_t len,
                                  char **aterm,
                                  size_t* atermLen,
                                  char **restterms,
                                  size_t* restTermsLen)
{
  size_t i;
  int n;
  int done = FALSE;
  int inquotes = FALSE;
  int inJIS7 = FALSE;
  int inData = FALSE;
  int parens = 0;
  int seen_something = FALSE;
  char* dataStart;
  *aterm = NULL;
  *restterms = NULL;

  if(len == 0) {
    *aterm = strdup("");
    *atermLen = 0;
    *restterms = strdup("");
    *restTermsLen = 0;
    return FALSE;
  }

  i = 0;
  while ((i < len) && !done) {
    /* Check for icldataq() struct */
    if(!inData) {
      if((i + ICLDATAQSTARTLEN < len) &&
         (strncmp(&terms[i], ICLDATAQSTART, ICLDATAQSTARTLEN) == 0)) {
        i += ICLDATAQSTARTLEN;
        dataStart = (char*)memchr(&terms[i],'"',len);
        if(dataStart == NULL) {
          *aterm = strdup("");
          *atermLen = 0;
          *restterms = strdup("");
          *restTermsLen = 0;
          return FALSE;
        }
        i += (dataStart - (char*)(&terms[i]));
        inData = TRUE;
      }
    }
    else {
      if((i < len) &&
         (terms[i] == '"')) {
        if((i + 1 < len) &&
           (terms[i + 1] == '"')) {
          // okay double quotes--still looking at data
          i += 2;
          continue;
        }
        else {
          // done the data--icldataq should now end with a paren, possibly
          // with white space, as well.
          ++i;
          while(i < len) {
            switch(terms[i]) {
            case ')':
              inData = FALSE;
              break;
            case ' ':
            case '\n':
            case '\t':
              break;
            default:
              *aterm = strdup("");
              *atermLen = 0;
              *restterms = strdup("");
              *restTermsLen = 0;
              return FALSE;
            }
            ++i;
            if(inData == FALSE) {
              break;
            }
          }
          continue;
        }
      }
    }

    /* Check for JIS7 Japanese Encoding markers */
    if(!inData) {
      if(!inJIS7) {
        if ((terms[i] == 27) && (terms[i+1] == '$') && (terms[i+2] == 'B')) {
          inJIS7 = TRUE;
        }
      }
      else {
        if ((terms[i] == 27) && (terms[i+1] == '(') && (terms[i+2] == 'B')) {
          inJIS7 = FALSE;
        }
      }
    }
  
    /* If we are not looking at Japanese characters, try to parse the 
       input. */
    if(!inData) {
      if (!inJIS7) {
        switch (terms[i]) {
        case '(':
        case '[':
        case '{':
          if (!inquotes)
            parens = parens + 1;
          break;
        case ')':
        case ']':
        case '}':
          if (!inquotes) {
            parens = parens - 1;
            if (parens == 0)
              done = TRUE;
          }
          break;
        case '\'':
          inquotes = !inquotes;
          break;
        case ',' :
          if ((parens == 0) && (inquotes == 0))
            done = TRUE;
          break;
        case ' ':
        case '\n':
        case '\t':
          if ((parens == 0) && (inquotes == 0) && seen_something)
            done = TRUE;
          break;
        default: seen_something = TRUE;
        }
      }
    }
    if(!done) {
      ++i;
    }
  } /* End while */

  if (!parens && !inquotes) {
    if (terms[i] == ',')
      n = i;
    else n = i+1;

    *aterm = malloc(n+1);
    strncpy(*aterm, terms, n);
    (*aterm)[n] = '\0';
    *atermLen = n;
    ++i;
    while ((terms[i] != 0) && ((terms[i] == ' ') || (terms[i] == ',')))
      ++i;
    *restterms = &terms[i];
    *restTermsLen = len - *atermLen;
    return TRUE;
  }
  else {
    *aterm = strdup("");
    *atermLen = 0;
    *restterms = strdup("");
    *restTermsLen = 0;
    return FALSE;
  } 
}
/****************************************************************************
 * name:    icl_stIsSeparator
 * purpose: Returns true if the beginning of next string is a separator
 ****************************************************************************/
int
icl_stIsSeparator(char *s) {

  return (s && ((*s == ',') || (*s == ';') || (*s == '|')));
}

char 
icl_stGetLastSeparator() {
  return last_separator;
}

/****************************************************************************
 * name:    icl_stHeadTailPtr
 * purpose: takes a comma-separated list of elements and returns a copy of 
 *	    the first element and a pointer to the rest of the list.
 * inputs:
 *   - char *terms: a list of terms
 * outputs:
 *   - char     *aterm: the first term in the list
 *   - char *restterms: the rest of the terms
 * remarks:
 *   - Terms may be nested arbitrarily deep (eg. a(b(c(d,1)), X).
 *   - aterm will return a new copy of the first argument, which should
 *     be free'd when finished using.  restterms will return a pointer
 *     into terms, which should NOT BE free'd.
 *   - Term can correctly parse expression with embedded arguments using
 *     Japanese JIS7 format.  JIS7 is the Japanese encoding standard chosen
 *     for use with the OAA.  Three reasons for this choice:  1) it's the
 *     most popular standard on UNIX machines.  2) 7-bit encoding should
 *     be TCP/IP and modem friendly.  3) it's easy to parse: JIS7 embeds
 *     Japanese characters in a quotation-like wrapper, using ESC$B for the
 *     opening marker and ESC(B for the closing.
 * returns: 
 *     TRUE if a term was read, FALSE if a complete term could not be read.
 *     In the latter case, aterm and restterms returns "" as well.
 ****************************************************************************/
EXPORT_MSCPP
int EXPORT_BORLAND 
icl_safeStHeadTailPtr(char *terms,
                      size_t len,
                      char **aterm,
                      size_t* atermLen,
                      char **restterms,
                      size_t* restTermsLen)
{
  size_t i;
  size_t n;
  int done = FALSE;
  int inquotes = FALSE;
  int inJIS7 = FALSE;
  int parens = 0;
  int seen_something = FALSE;
  int icldataqStart = -1;
  int inData = FALSE;
  /*
  char* buf = NULL;
  char* end = NULL;
  long rawLen = -1;
  long numQuotes = -1;
  */

  *aterm = NULL;
  *restterms = NULL;
  *atermLen = 0;
  *restTermsLen = 0;

  if(len == 0) {
    *aterm = strdup("");
    *atermLen = 0;
    *restterms = strdup("");
    *restTermsLen = 0;
    return FALSE;
  }

  i = 0;
  while ((i < len) && !done) {

    if(!inData && !inJIS7) {
      /* icldataq( */
      if((i + ICLDATAQSTARTLEN) < len) {
        if(strncmp(&(terms[i]), ICLDATAQSTART, ICLDATAQSTARTLEN) == 0) {

⌨️ 快捷键说明

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