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 + -
显示快捷键?