summaryrefslogtreecommitdiff
path: root/src/common/filepart.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/filepart.c')
-rw-r--r--src/common/filepart.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/common/filepart.c b/src/common/filepart.c
new file mode 100644
index 0000000..ab8049a
--- /dev/null
+++ b/src/common/filepart.c
@@ -0,0 +1,218 @@
+/*
+ * This file contains pathfind(), fparse(), makename(), and smatch().
+ */
+#include "../h/gsupport.h"
+
+static char *pathelem (char *s, char *buf);
+static char *tryfile (char *buf, char *dir, char *name, char *extn);
+
+/*
+ * Define symbols for building file names.
+ * 1. Prefix: the characters that terminate a file name prefix
+ * 2. FileSep: the char to insert after a dir name, if any
+ * 3. DefPath: the default IPATH/LPATH
+ * 4. PathSep: allowable IPATH/LPATH separators
+ *
+ * All platforms use POSIX forms of file paths.
+ * MS Windows implementations canonize local forms before parsing.
+ */
+
+#define Prefix "/"
+#define FileSep '/'
+#define PathSep " :"
+#define DefPath ""
+
+/*
+ * pathfind(buf,path,name,extn) -- find file in path and return name.
+ *
+ * pathfind looks for a file on a path, begining with the current
+ * directory. Details vary by platform, but the general idea is
+ * that the file must be a readable simple text file. pathfind
+ * returns buf if it finds a file or NULL if not.
+ *
+ * buf[MaxPath] is a buffer in which to put the constructed file name.
+ * path is the IPATH or LPATH value, or NULL if unset.
+ * name is the file name.
+ * extn is the file extension (.icn or .u1) to be appended, or NULL if none.
+ */
+char *pathfind(buf, path, name, extn)
+char *buf, *path, *name, *extn;
+ {
+ char *s;
+ char pbuf[MaxPath];
+
+ if (tryfile(buf, (char *)NULL, name, extn)) /* try curr directory first */
+ return buf;
+ if (!path) /* if no path, use default */
+ path = DefPath;
+
+ #if CYGWIN
+ s = alloca(cygwin_win32_to_posix_path_list_buf_size(path));
+ cygwin_win32_to_posix_path_list(path, s);
+ #else /* CYGWIN */
+ s = path;
+ #endif /* CYGWIN */
+
+ while ((s = pathelem(s, pbuf)) != 0) /* for each path element */
+ if (tryfile(buf, pbuf, name, extn)) /* look for file */
+ return buf;
+ return NULL; /* return NULL if no file found */
+ }
+
+/*
+ * pathelem(s,buf) -- copy next path element from s to buf.
+ *
+ * Returns the updated pointer s.
+ */
+static char *pathelem(s, buf)
+char *s, *buf;
+ {
+ char c;
+
+ while ((c = *s) != '\0' && strchr(PathSep, c))
+ s++;
+ if (!*s)
+ return NULL;
+ while ((c = *s) != '\0' && !strchr(PathSep, c)) {
+ *buf++ = c;
+ s++;
+ }
+
+ #ifdef FileSep
+ /*
+ * We have to append a path separator here.
+ * Seems like makename should really be the one to do that.
+ */
+ if (!strchr(Prefix, buf[-1])) { /* if separator not already there */
+ *buf++ = FileSep;
+ }
+ #endif /* FileSep */
+
+ *buf = '\0';
+ return s;
+ }
+
+/*
+ * tryfile(buf, dir, name, extn) -- check to see if file is readable.
+ *
+ * The file name is constructed in buf from dir + name + extn.
+ * findfile returns buf if successful or NULL if not.
+ */
+static char *tryfile(buf, dir, name, extn)
+char *buf, *dir, *name, *extn;
+ {
+ FILE *f;
+ makename(buf, dir, name, extn);
+ if ((f = fopen(buf, "r")) != NULL) {
+ fclose(f);
+ return buf;
+ }
+ else
+ return NULL;
+ }
+
+/*
+ * fparse - break a file name down into component parts.
+ * Result is a pointer to a struct of static pointers good until the next call.
+ */
+struct fileparts *fparse(s)
+char *s;
+ {
+ static char buf[MaxPath+2];
+ static struct fileparts fp;
+ int n;
+ char *p, *q;
+
+ #if CYGWIN
+ char posix_s[_POSIX_PATH_MAX + 1];
+ cygwin_conv_to_posix_path(s, posix_s);
+ s = posix_s;
+ #endif /* CYGWIN */
+
+ q = s;
+ fp.ext = p = s + strlen(s);
+ while (--p >= s) {
+ if (*p == '.' && *fp.ext == '\0')
+ fp.ext = p;
+ else if (strchr(Prefix,*p)) {
+ q = p+1;
+ break;
+ }
+ }
+
+ fp.dir = buf;
+ n = q - s;
+ strncpy(fp.dir,s,n);
+ fp.dir[n] = '\0';
+ fp.name = buf + n + 1;
+ n = fp.ext - q;
+ strncpy(fp.name,q,n);
+ fp.name[n] = '\0';
+ p = fp.ext;
+ fp.ext = fp.name + n + 1;
+ strcpy(fp.ext, p);
+
+ return &fp;
+ }
+
+/*
+ * makename - make a file name, optionally substituting a new dir and/or ext
+ */
+char *makename(dest,d,name,e)
+char *dest, *d, *name, *e;
+ {
+ struct fileparts fp;
+ fp = *fparse(name);
+ if (d != NULL)
+ fp.dir = d;
+ if (e != NULL)
+ fp.ext = e;
+ sprintf(dest,"%s%s%s",fp.dir,fp.name,fp.ext);
+ return dest;
+ }
+
+/*
+ * smatch - case-insensitive string match - returns nonzero if they match
+ */
+int smatch(s,t)
+char *s, *t;
+ {
+ char a, b;
+ for (;;) {
+ while (*s == *t)
+ if (*s++ == '\0')
+ return 1;
+ else
+ t++;
+ a = *s++;
+ b = *t++;
+ if (isupper(a)) a = tolower(a);
+ if (isupper(b)) b = tolower(b);
+ if (a != b)
+ return 0;
+ }
+ }
+
+#if MSWIN
+
+FILE *pathOpen(fname, mode)
+ char *fname;
+ char *mode;
+ {
+ char buf[MaxPath];
+ int i;
+
+ for (i = 0; fname[i] != '\0'; i++) {
+ if (fname[i] == '/' || fname[i] == ':' || fname[i] == '\\') {
+ /* fname contains an explicit path */
+ return fopen(fname, mode);
+ }
+ }
+
+ if (!pathfind(buf, getenv("PATH"), fname, NULL))
+ return 0;
+
+ return fopen(buf, mode);
+ }
+
+#endif /* MSWIN */