libutils.c

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

C
691
字号
#include <stdio.h>
#include <string.h>
//#include <malloc.h>

#ifndef _WINDOWS
#include <pwd.h>        /* used by expandFileName */
#endif

#include <stdarg.h>  	/* Variable length argument lists */
#include <stdlib.h>

#include "libutils.h"

/****************************************************************************
 * Global variables and forward declarations
 ****************************************************************************/

#define EXPORT_BORLAND

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

/* Exported by liboaa */
extern int oaa_argc;
extern char** oaa_argv;
#define SETUP_FILE_NAME "setup.pl"
/* Each line in a setup file should be less than this length: */
#define SETUP_FILE_BUFSIZ 1024

char *expand_filename(char* nm, char* startDir);

/****************************************************************************
 * name:    oaa_ResolveVariable
 * purpose:
 * remarks:
 * returns:
 ****************************************************************************/
EXPORT_MSCPP
int EXPORT_BORLAND
oaa_ResolveVariable(char* inVarName, ICLTerm **resolvedVar){
  int i = 1;
  int found = FALSE;

  ICLTerm* varNameAsIclStruct;
  ICLTerm* varNameAsIclStr;
  ICLTerm* resultOfUnification = NULL;
  ICLTerm* var;

  var = icl_NewVar("_");
  varNameAsIclStruct = icl_NewStruct(inVarName, 1, var);
  if(varNameAsIclStruct == NULL) {
    icl_Free(var);
  }
  CHECK_LEAKS();
  varNameAsIclStr = icl_NewStr(inVarName);
  CHECK_LEAKS();

  /* First looks at the command line */
  while ((i<oaa_argc) && !found) {
    ICLTerm* currentParamAsTerm = icl_NewStr(oaa_argv[i]);
    CHECK_LEAKS();

    /* Looks at the term as a struct */
    if (currentParamAsTerm && icl_IsStruct(currentParamAsTerm)) {
      CHECK_LEAKS();
      if (icl_Unify(currentParamAsTerm, varNameAsIclStruct, &resultOfUnification)) {
        CHECK_LEAKS();
        if (resolvedVar) {
          *resolvedVar = icl_CopyTerm(icl_NthTerm(resultOfUnification, 1));
          CHECK_LEAKS();          
        }
        found = TRUE;
      }
      icl_Free(resultOfUnification);
      CHECK_LEAKS();
    }

    /* Looks at the term as an icl str */
    if (currentParamAsTerm && icl_IsStr(currentParamAsTerm)) {
      if (icl_Unify(currentParamAsTerm, varNameAsIclStr, &resultOfUnification)) {
        /* The -oaa parameter does not take any parameters */
        if (strcmp(oaa_argv[i],"-oaa")==0) {
          if (resolvedVar)
            *resolvedVar = icl_CopyTerm(icl_NthTerm(resultOfUnification, 1));
        }
        else{
          if (resolvedVar)
            *resolvedVar = icl_NewTermFromString(oaa_argv[++i]);
        }
        found = TRUE;
      }
      icl_Free(resultOfUnification);
    }

    icl_Free(currentParamAsTerm);
    i++;
  }

  /*
     If not found within the arguments, looks in the setup.pl file.
     First in the current directory, then in the user's root directory
     on UNIX (LINUX) systems, or in c:\ on Windows based machines.
  */

  if (!found) {
    FILE *setup_file;
    char buf[SETUP_FILE_BUFSIZ];
#ifndef _WINDOWS /* --------------------------------------------------------- */
    char *filename;
    strcpy(buf, "./");
    strcat(buf, SETUP_FILE_NAME);
#else /* ----------------------------------------------------------------- */
    strcpy(buf, SETUP_FILE_NAME);
#endif  /* ---------------------------------------------------------------- */
    if ((setup_file = fopen(buf, "r")) == NULL) {
#ifdef _WINDOWS  /* ----------------------------------------------------- */
      strcpy(buf,"C:\\");
      strcat(buf, SETUP_FILE_NAME);
#else  /* ---------------------------------------------------------------- */
      strcpy(buf, "~/");
      strcat(buf, SETUP_FILE_NAME);
      filename = expand_filename(buf, NULL);
      strncpy(buf, filename, 512);
      icl_stFree(filename);
#endif  /* ---------------------------------------------------------------- */
      setup_file = fopen(buf, "r");
    }

    /* TBD: The following code could use some additional error-checking.
    ** Note that terms spanning multiple lines could cause problems. */
    if (setup_file != NULL) {
      while (!found && (fgets(buf, SETUP_FILE_BUFSIZ, setup_file) != NULL)){
        ICLTerm* currentLineAsTerm = NULL;

        if ((buf[0]!='%') && (strcmp(buf,"")!=0) && (strchr(buf,'.')!=0)) {
          int l = strlen(buf) - 1;
          /* Gets rid of the .\n */
          /* buf[strlen(buf)-2]=0; */
          while (buf[l] != '.') {
            buf[l--] = 0;
          }
          buf[l] = 0;

      	  currentLineAsTerm = icl_NewTermFromString(buf);
          if(currentLineAsTerm != NULL) {
            if(icl_Unify(currentLineAsTerm, varNameAsIclStruct, &resultOfUnification)) {
              *resolvedVar = icl_CopyTerm(icl_NthTerm(resultOfUnification, 1));
              found = TRUE;
              icl_Free(resultOfUnification);
              resultOfUnification = NULL;
            }
            icl_Free(currentLineAsTerm);
            currentLineAsTerm = NULL;
          }
        }
      }
      fclose(setup_file);
    }
  }

  CHECK_LEAKS();
  icl_Free(varNameAsIclStruct);
  CHECK_LEAKS();
  icl_Free(varNameAsIclStr);
  CHECK_LEAKS();

  return found;
}

/****************************************************************************
 * name:    filename_as_directory
 * purpose: concatenate a slash onto a filename if necessary
 * inputs:
 *    - char  *in: file to work on
 *    - char *out: result
 * remarks:
 *    Internal static command
 ****************************************************************************/
static char *
filename_as_directory (out, in)
     char *out, *in;
{
  int size = strlen (in) - 1;

  strcpy (out, in);

  /* For Unix syntax, Append a slash if necessary */
  if (out[size] != '/')
    strcat (out, "/");
  return out;
}

/**
 * Convert a filename to absolute, and canonicalize it.
 * Accepts "~", "~username", and all relative paths.
 * Filenames containing . or .. as components are simplified.
 * @param filename the filename to expand
 * @param startdir the directory to start with if filename is relative.
 *        If startdir is NULL or missing, the current working directory
 *        is used.
 * @return The expanded filename in a structure created by malloc.
 */
char *
expand_filename(char* nm, char* startDir) {

  register unsigned char *newdir, *p, *o;
  int tlen;
  unsigned char *target;
  int lose;

#ifndef _WINDOWS
  struct passwd *pw;
#endif

  /* If nm is absolute, flush ...// and detect /./ and /../.
     If no /./ or /../ we can return right away. */
  if (nm[0] == '/') {
    p = nm;
    lose = 0;
    while (*p){
      if (p[0] == '/' && p[1] == '/')
	nm = p + 1;
      if (p[0] == '/' && p[1] == '~')
	nm = p + 1, lose = 1;
      if (p[0] == '/' && p[1] == '.'
	  && (p[2] == '/' || p[2] == 0
	      || (p[2] == '.' && (p[3] == '/' || p[3] == 0))))
	lose = 1;
      p++;
    }
    if (!lose) {
      printf("expand_filename !lose\n");
      return strdup (nm);
    }
  }

  /* Now determine directory to start with and put it in NEWDIR.  */

  newdir = 0;

#ifndef _WINDOWS
  if (nm[0] == '~'){
    if (nm[1] == '/' || nm[1] == 0){
      /* Handle ~ on its own.  */
      newdir = (unsigned char *) getenv ("HOME");
    }
    else {
      /* Handle ~ followed by user name.  */
      unsigned char *user = nm + 1;

      /* Find end of name.  */
      unsigned char *ptr = (unsigned char *) strchr (user, '/');
      int len = ptr ? (int) (ptr - user) : (int) strlen (user);

      /* Copy the user name into temp storage.  */
      o = (unsigned char *) strdup(user);
      o[len] = 0;

      /* Look up the user name.  */
      pw = (struct passwd *) getpwnam (o);
      if (!pw) {
	printf("User \"%s\" is not known", o);
      }

      newdir = (unsigned char *) (pw->pw_dir);

      /* Discard the user name from NM.  */
      nm += len;
    }

    /* Discard the ~ from NM.  */
    nm++;

    if (newdir == 0) {
      newdir = (unsigned char *)"";
    }
  }
#endif

  if (nm[0] != '/' && !newdir){
    if (startDir[0] == 0)
      newdir = (unsigned char *)getenv("PWD");
    else
      newdir = startDir;
  }

  if (newdir != 0){
    /* Get rid of any slash at the end of newdir.  */
    int length = strlen (newdir);
    if (length > 1 && newdir[length - 1] == '/'){
      unsigned char *temp = (unsigned char *) strdup(newdir);
      temp[length - 1] = 0;
      newdir = temp;
    }
    tlen = length + 1;
  }
  else {
    tlen = 0;
  }

  /* Now concatenate the directory and name to new space in the stack frame */

  tlen += strlen (nm) + 1;
  target = (unsigned char *) malloc (tlen);
  *target = 0;

  if (newdir){
    if (nm[0] == 0 || nm[0] == '/') {
      strcpy (target, newdir);
    }
    else {
      filename_as_directory (target, newdir);
    }
  }

  strcat (target, nm);

  /* Now canonicalize by removing /. and /foo/.. if they appear */
  /* This could be done by using realpath(), but realpath only  */
  /* works if the file actually exists.        */

  p = target;
  o = target;

  while (*p){
    if (*p != '/'){
      *o++ = *p++;
    }
    else
      if (!strncmp (p, "//", 2)){
        o = target;
        p++;
      }
      else
        if (p[0] == '/' && p[1] == '.' &&
            (p[2] == '/' || p[2] == 0)){
          if (o == target && p[2] == '\0') {
            *o++ = *p;
          }
          p += 2;
        }
        else if (!strncmp (p, "/..", 3)
                 && o != target

⌨️ 快捷键说明

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