aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/psres/PSres.c
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
committerReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
commitf4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch)
tree2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/lib/psres/PSres.c
parenta840692edc9c6d19cd7c057f68e39c7d95eb767d (diff)
downloadnx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository
Diffstat (limited to 'nx-X11/lib/psres/PSres.c')
-rw-r--r--nx-X11/lib/psres/PSres.c1661
1 files changed, 1661 insertions, 0 deletions
diff --git a/nx-X11/lib/psres/PSres.c b/nx-X11/lib/psres/PSres.c
new file mode 100644
index 000000000..b7fd4acba
--- /dev/null
+++ b/nx-X11/lib/psres/PSres.c
@@ -0,0 +1,1661 @@
+/*
+ * PSres.c
+ *
+ * (c) Copyright 1991-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+/* $XFree86: xc/lib/psres/PSres.c,v 1.4tsi Exp $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef XENVIRONMENT
+#include <X11/Xos.h>
+#else
+#include <string.h>
+#include <sys/types.h>
+#endif
+
+#define USE_POSIX
+
+#ifdef NeXT
+#undef USE_POSIX
+#endif /* NeXT */
+
+#ifdef USE_POSIX
+#include <dirent.h>
+#else
+#include <sys/dir.h>
+#endif
+
+#include <sys/stat.h>
+#include <DPS/PSres.h>
+
+#ifndef PSRES_NAME
+#define PSRES_NAME "PSres.upr"
+#endif /* PSRES_NAME */
+
+#ifndef PSRES_EXT
+#define PSRES_EXT ".upr"
+#endif /* PSRES_EXT */
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif /* SEEK_SET */
+
+/* MT is the right pointer type to pass to memcpy, MST the size type */
+#define MT void *
+#define MST size_t
+
+#define MAXLEN 256
+typedef int (*ReadContentsFunction)();
+
+char *PSResFontOutline = "FontOutline",
+ *PSResFontPrebuilt = "FontPrebuilt",
+ *PSResFontAFM = "FontAFM",
+ *PSResFontBDF = "FontBDF",
+ *PSResFontFamily = "FontFamily",
+ *PSResFontBDFSizes = "FontBDFSizes",
+ *PSResForm = "Form",
+ *PSResPattern = "Pattern",
+ *PSResEncoding = "Encoding",
+ *PSResProcSet = "ProcSet";
+
+typedef struct _ResourceNameStruct {
+ char *name;
+ char *file;
+} ResourceNameStruct, *ResourceName;
+
+typedef struct _ResourceTypeStruct {
+ char *type;
+ long fileOffset; /* -1 means not really in the file */
+ ResourceName names;
+ int nameCount;
+ int filled; /* Whether has all names or just already found names */
+ char *nameBuffer;
+ char **oldNameBuffers;
+ int oldNameCount;
+} ResourceTypeStruct, *ResourceType;
+
+typedef struct _ResourceDirectoryStruct {
+ char *directory;
+ ResourceType types;
+ int typeCount;
+ char *typeNameBuffer;
+ char *filePrefix;
+ long endOfHeader;
+ int exclusive;
+ struct _ResourceDirectoryStruct *next;
+} ResourceDirectoryStruct, *ResourceDirectory;
+
+typedef struct {
+ char *type;
+ char *name;
+} TypeName;
+
+typedef struct {
+ PSResourceEnumerator func;
+ char *type;
+ char *name;
+ char *private;
+ int done;
+} EnumeratorStruct;
+
+static ResourceDirectory resDir = NULL, lastResDir;
+static char *savedPathOverride = NULL, *savedDefaultPath = NULL;
+static PSResourceSavePolicy currentPolicy = PSSaveByType;
+static char **currentResourceTypes = NULL;
+static char *resourceTypeBuffer = NULL;
+static time_t lastModifiedTime;
+static char nullStr = '\0';
+
+/* Wrappers */
+
+static char *mymalloc(size)
+ int size;
+{
+ char *ret;
+
+#ifdef XENVIRONMENT
+#ifdef MALLOC_0_RETURNS_NULL
+ if (size < 1) size = 1;
+#endif
+#else
+ if (size < 1) size = 1; /* Better safe than sorry */
+#endif
+
+ ret = (char *) malloc((unsigned) size);
+ if (ret != NULL) return ret;
+ (void) fprintf(stderr, "malloc failed\n");
+ exit(1);
+ return NULL;
+}
+
+PSResMallocProc PSResMalloc = mymalloc;
+#define MALLOC (*PSResMalloc)
+
+static char *myrealloc(ptr, size)
+ char *ptr;
+ int size;
+{
+ char *ret;
+
+#ifdef XENVIRONMENT
+#ifdef MALLOC_0_RETURNS_NULL
+ if (size < 1) size = 1;
+#endif
+#else
+ if (size < 1) size = 1; /* Better safe than sorry */
+#endif
+
+ if (ptr == NULL) return MALLOC(size);
+#ifdef NO_VOID_STAR
+ ret = (char *) realloc(ptr, (unsigned) size);
+#else
+ ret = (char *) realloc((void *) ptr, (unsigned) size);
+#endif
+ if (ret != NULL) return ret;
+ (void) fprintf(stderr, "realloc failed\n");
+ exit(1);
+ return NULL;
+}
+
+PSResReallocProc PSResRealloc = myrealloc;
+#define REALLOC (*PSResRealloc)
+
+static void myfree(ptr)
+ char *ptr;
+{
+#ifdef NO_VOID_STAR
+ if (ptr != NULL) free(ptr);
+#else
+ if (ptr != NULL) free((void *) ptr);
+#endif
+}
+
+PSResFreeProc PSResFree = myfree;
+#define FREE (*PSResFree)
+
+#define NewString(str) ((char *) strcpy(MALLOC((int) (strlen(str)+1)),(str)))
+
+static void FileWarningHandler(file, extraInfo)
+ char *file;
+ char *extraInfo;
+{
+ fprintf(stderr,
+ "Syntax error found in PostScript resource file %s:\n %s\n",
+ file, extraInfo);
+}
+
+PSResFileWarningHandlerProc PSResFileWarningHandler = FileWarningHandler;
+
+/* Just like fgets, but strips trailing newline, eliminates trailing comments,
+ skips trailing white space, skips blank lines, and chops lines longer
+ than size */
+
+static char *myfgets(buf, size, f)
+ char *buf;
+ register int size;
+ FILE *f;
+{
+ register int ch;
+ register int count = 0;
+
+#define STRIP_BLANKS \
+ while (--count >= 0 && (buf[count] == ' ' || buf[count] == '\t')) \
+ buf[count] = '\0';
+#define RETURN_BUF \
+ if (buf[0] != '\0') return buf; \
+ else return myfgets(buf, size, f);
+
+ if (size == 0) return buf;
+ size--;
+
+ while (count < size) {
+ ch = getc(f);
+ if (ch == EOF) {
+ buf[count] = '\0';
+ STRIP_BLANKS;
+ return NULL;
+ }
+ if (ch == '\n') {
+ buf[count] = '\0';
+ STRIP_BLANKS;
+ RETURN_BUF;
+ }
+ if (ch == '%') { /* Comment */
+ if (count == 0 || buf[count-1] != '\\') {
+ buf[count] = '\0';
+ do {
+ ch = getc(f);
+ } while (ch != EOF && ch != '\n');
+ STRIP_BLANKS;
+ if (ch == EOF) return NULL;
+ else RETURN_BUF;
+ }
+ }
+
+ buf[count] = ch;
+ count++;
+ }
+
+ /* Overflow, flush */
+ buf[count] = '\0';
+ do {
+ ch = getc(f);
+ } while (ch != EOF && ch != '\n');
+ STRIP_BLANKS;
+ if (ch == EOF) return NULL;
+ else RETURN_BUF;
+#undef RETURN_BUF
+#undef STRIP_BLANKS
+}
+
+static int Dequote(buf, dontDequote)
+ char *buf;
+ char dontDequote;
+{
+ char *dst = buf, *src = buf;
+
+ while (*src != '\0') {
+ if (*src == '\\') {
+ src++;
+ if (*src == '\0') {
+ *dst = '\0';
+ return 1;
+ } else if (*src == dontDequote) *dst++ = '\\';
+ }
+ *dst++ = *src++;
+ }
+ *dst = '\0';
+ return 0;
+}
+
+/* Sep returns the first unquoted position of the break character. The
+ dontDequote character only applies after the break character. If the
+ separator character is doubled, doubleSep is set to 1 and only one
+ of the separators is installed */
+
+static int DequoteAndBreak(buf, sep, bchar, dontDequote, doubleSep)
+ char *buf;
+ char **sep;
+ char bchar;
+ char dontDequote;
+ int *doubleSep;
+{
+ char *dst = buf, *src = buf;
+
+ *doubleSep = 0;
+ *sep = NULL;
+
+ while (*src != '\0') {
+ if (*src == '\\') {
+ src++;
+ if (*src == '\0') {
+ *dst = '\0';
+ return 1;
+ } else if (*src == dontDequote && *sep != NULL) *dst++ = '\\';
+ } else if (*sep == NULL && *src == bchar) {
+ *sep = dst;
+ if (*(src+1) == bchar) {
+ src++;
+ *doubleSep = 1;
+ }
+ }
+ *dst++ = *src++;
+ }
+ *dst = '\0';
+ return 0;
+}
+
+static float ParseVersion(f, excl)
+ FILE *f;
+ int *excl;
+{
+ char inBuf[MAXLEN];
+ float version = 0.0;
+ int count;
+
+ if (myfgets(inBuf, MAXLEN, f) == NULL) return 0.0;
+
+ /* Compare against magic value */
+
+ count = sscanf(inBuf, "PS-Resources-Exclusive-%f", &version);
+ if (count == 1) {
+ *excl = 1;
+ return version;
+ }
+ count = sscanf(inBuf, "PS-Resources-%f", &version);
+ if (count == 1) {
+ *excl = 0;
+ return version;
+ }
+ return 0.0;
+}
+
+static int ParseResourceTypes(f, dir)
+ FILE *f;
+ ResourceDirectory dir;
+{
+ char inBuf[MAXLEN];
+ char typebuf[MAXLEN];
+ char *types = typebuf;
+ int buflen = MAXLEN, typelen = 0, len;
+ int count, i;
+ int continued = 0, precontinued = 0;
+
+ typebuf[0] = '\0';
+ count = 0;
+
+ while (1) {
+ if (myfgets(inBuf, MAXLEN, f) == NULL) {
+ if (types != typebuf) FREE((char *) types);
+ return 1;
+ }
+ if (strcmp(inBuf, ".") == 0) break;
+ precontinued = continued;
+ continued = Dequote(inBuf, '\0');
+
+ len = strlen(inBuf);
+ if (typelen + len + 1 > buflen) {
+ if (types == typebuf) {
+ types = (char *) MALLOC(2*MAXLEN);
+ (void) memcpy((MT) types, (MT) typebuf, (MST) typelen);
+ } else types = REALLOC(types, buflen+MAXLEN);
+ buflen += MAXLEN;
+ }
+
+ if (precontinued) typelen--; /* Write over previous \0 */
+ else count++;
+ (void) strncpy(&types[typelen], inBuf, len+1);
+ typelen += len+1;
+ }
+
+ dir->typeCount = count;
+ if (count == 0) dir->types = NULL;
+ else {
+ dir->types = (ResourceType)
+ MALLOC((int) (count * sizeof(ResourceTypeStruct)));
+ dir->typeNameBuffer = (char *) MALLOC(typelen);
+ (void) memcpy((MT) dir->typeNameBuffer, (MT) types, (MST) typelen);
+ }
+
+ len = 0;
+ for (i = 0; i < count; i++) {
+ dir->types[i].type = &(dir->typeNameBuffer[len]);
+ dir->types[i].fileOffset = 0;
+ dir->types[i].names = NULL;
+ dir->types[i].nameBuffer = NULL;
+ dir->types[i].filled = 0;
+ dir->types[i].oldNameBuffers = NULL;
+ dir->types[i].oldNameCount = 0;
+ dir->types[i].nameCount = 0;
+ len += strlen(dir->types[i].type) + 1;
+ }
+
+ if (types != typebuf) FREE((char *) types);
+ return 0;
+}
+
+static int ParseFilePrefix(f, dir, dirName)
+ FILE *f;
+ ResourceDirectory dir;
+ char *dirName;
+{
+ char inBuf[MAXLEN];
+ int continued;
+ int len;
+ long savePos;
+ char *prefix;
+
+ dir->filePrefix = NULL;
+
+ savePos = ftell(f);
+ if (myfgets(inBuf, MAXLEN, f) == NULL) return 1;
+
+ if (inBuf[0] != '/') {
+ if (fseek(f, savePos, SEEK_SET) == -1) return 1;
+ len = strlen(dirName);
+ dir->filePrefix = strcpy((char *) MALLOC(len+2), dirName);
+ dir->filePrefix[len] = '/';
+ dir->filePrefix[len+1] = '\0';
+ return 0;
+ }
+
+ continued = Dequote(inBuf, '\0');
+ prefix = inBuf+1;
+ len = strlen(prefix);
+ dir->filePrefix = (char *) strcpy((char *) MALLOC(len+2), prefix);
+ if (!continued) {
+ dir->filePrefix[len] = '/';
+ dir->filePrefix[len+1] = '\0';
+ return 0;
+ }
+
+ while (1) {
+ if (myfgets(inBuf, MAXLEN, f) == NULL) return 1;
+ continued = Dequote(inBuf, '\0');
+ len += strlen(inBuf);
+ dir->filePrefix = (char *) REALLOC(dir->filePrefix, len+2);
+ (void) strcat(dir->filePrefix, inBuf);
+ if (!continued) {
+ dir->filePrefix[len] = '/';
+ dir->filePrefix[len+1] = '\0';
+ return 0;
+ }
+ }
+}
+
+static ResourceDirectory ParseHeader(f, dirName, fileName)
+ FILE *f;
+ char *dirName, *fileName;
+{
+ ResourceDirectory dir;
+ float version;
+ int exclusive;
+
+ rewind(f);
+
+ version = ParseVersion(f, &exclusive);
+ if (version < 1.0) return NULL;
+
+ dir = (ResourceDirectory) MALLOC(sizeof(ResourceDirectoryStruct));
+ dir->directory = (char *) NewString(fileName);
+ dir->exclusive = exclusive;
+ dir->next = NULL;
+
+ if (ParseResourceTypes(f, dir)) {
+ FREE((char *) dir->directory);
+ FREE((char *) dir);
+ return NULL;
+ }
+
+ if (ParseFilePrefix(f, dir, dirName)) dir->endOfHeader = 0;
+ else dir->endOfHeader = ftell(f);
+
+ return dir;
+}
+
+/* Store away old name buffer so pointers to it do not become invalid */
+
+static void CacheOldNames(type)
+ ResourceType type;
+{
+ type->oldNameCount++;
+ type->oldNameBuffers = (char **) REALLOC((char *) type->oldNameBuffers,
+ type->oldNameCount);
+ type->oldNameBuffers[type->oldNameCount-1] = type->nameBuffer;
+ type->nameBuffer = NULL;
+}
+
+/* Verify that the name matches the name in the file */
+
+static int VerifyName(f, name)
+ FILE *f;
+ char *name;
+{
+ char inBuf[MAXLEN];
+ int continued = 0;
+ int len;
+ int start = 0;
+
+ while (1) {
+ if (myfgets(inBuf, MAXLEN, f) == NULL) return 1;
+ continued = Dequote(inBuf, '\0');
+ if (continued) {
+ len = strlen(inBuf);
+ if (strncmp(inBuf, &name[start], len) != 0) return 1;
+ start += len;
+ } else {
+ if (strcmp(inBuf, &name[start]) != 0) return 1;
+ else break;
+ }
+ }
+ return 0;
+}
+
+static int LookupResourceInList(type, name)
+ ResourceType type;
+ char *name;
+{
+ int i;
+
+ for (i = 0; i < type->nameCount; i++) {
+ if (strcmp(name, type->names[i].name) == 0) return 1;
+ }
+ return 0;
+}
+
+static int CheckInsertPrefix(type)
+ char *type;
+{
+ /* Insert the prefix unless one of these special values */
+
+ if (strcmp(type, PSResFontFamily) == 0 ||
+ strcmp(type, PSResFontBDFSizes) == 0 ||
+ strcmp(type, "FontAxes") == 0 ||
+ strcmp(type, "FontBlendMap") == 0 ||
+ strcmp(type, "FontBlendPositions") == 0 ||
+ strcmp(type, "mkpsresPrivate") == 0) return 0;
+ return 1;
+}
+
+/* Returns a line, including continuations. Memory must be copied before
+ calling this again. */
+
+static int linebuflen = 0;
+static char *inputline = NULL;
+
+static char *ReadFullLine(f)
+ FILE *f;
+{
+ char readbuf[MAXLEN];
+ int start = 0;
+ int len;
+
+ while (1) {
+ if (myfgets(readbuf, MAXLEN, f) == NULL) return NULL;
+ len = strlen(readbuf);
+ if (start + len + 1 > linebuflen) {
+ linebuflen += MAXLEN + 1;
+ inputline = REALLOC(inputline, linebuflen);
+ }
+ strncpy(inputline+start, readbuf, len+1);
+
+ if (inputline[start+len-1] != '\\') break;
+
+ start = start+len-1;
+ }
+ return inputline;
+}
+
+static void FreeLineBuf()
+{
+ if (inputline != NULL) FREE(inputline);
+ inputline = NULL;
+ linebuflen = 0;
+}
+
+/* Assumes being correctly positioned in the file */
+
+static int ReadResourceSection(f, dir, type, name)
+ FILE *f;
+ ResourceDirectory dir;
+ ResourceType type;
+ char *name; /* If NULL, enumerate */
+{
+#define GROW 1000
+ char *linein;
+ int start;
+ int len;
+ char namebuf[GROW];
+ char *names = namebuf;
+ int buflen = GROW, namelen = 0;
+ int i, count = 0;
+ char *sep;
+ int prefixLen;
+ int insertPrefix;
+ char dontDequote;
+ int doubleEquals;
+ int addingPrefix;
+ int newsize;
+
+ if (type->nameBuffer != NULL) CacheOldNames(type);
+
+ insertPrefix = CheckInsertPrefix(type->type);
+ if (insertPrefix) {
+ prefixLen = strlen(dir->filePrefix);
+ dontDequote = '\0';
+ } else {
+ prefixLen = 0;
+ dontDequote = ',';
+ }
+
+ while (1) {
+ start = namelen;
+
+ linein = ReadFullLine(f);
+ if (linein == NULL) {
+ if (names != namebuf) FREE((char *) names);
+ FreeLineBuf();
+ return 1;
+ }
+ if (strcmp(linein, ".") == 0) break;
+
+ sep = NULL;
+ (void) DequoteAndBreak(linein, &sep, '=', dontDequote, &doubleEquals);
+
+ /* If no separator, a bogus line */
+ if (sep == NULL) continue;
+
+ /* Next line is UNIX specific! */
+ addingPrefix = *(sep+1) != '/' && insertPrefix && !doubleEquals;
+
+ len = strlen(linein) + 1 + (addingPrefix ? prefixLen : 0);
+
+ if (namelen + len >= buflen) {
+ newsize = buflen + GROW;
+ if (namelen + len > newsize) newsize = namelen + len;
+
+ if (names == namebuf) {
+ names = (char *) MALLOC(newsize);
+ (void) memcpy((MT) names, (MT) namebuf, (MST) namelen);
+ } else names = REALLOC(names, newsize);
+ buflen = newsize;
+ }
+
+ *sep = '\0';
+ len = strlen(linein);
+ (void) strncpy(&names[namelen], linein, len+1);
+ namelen += len+1;
+
+ if (addingPrefix) {
+ (void) strncpy(&names[namelen], dir->filePrefix, prefixLen);
+ namelen += prefixLen;
+ }
+
+ len = strlen(sep+1);
+ (void) strncpy(&names[namelen], sep+1, len+1);
+ namelen += len+1;
+
+ if (name != NULL && strcmp(names, name) != 0) namelen = start;
+ else count++;
+ }
+
+ type->nameCount = count;
+ if (count == 0) type->names = NULL;
+ else {
+ type->names = (ResourceName)
+ MALLOC((int) (count * sizeof(ResourceNameStruct)));
+ type->nameBuffer = (char *) MALLOC(namelen);
+ (void) memcpy((MT) type->nameBuffer, (MT) names, (MST) namelen);
+ }
+
+ len = 0;
+ for (i = 0; i < count; i++) {
+ type->names[i].name = &(type->nameBuffer[len]);
+ len += strlen(type->names[i].name) + 1;
+ type->names[i].file = &(type->nameBuffer[len]);
+ len += strlen(type->names[i].file) + 1;
+ }
+
+ if (names != namebuf) FREE((char *) names);
+ if (name == NULL) type->filled = 1;
+ FreeLineBuf();
+ return 0;
+
+#undef GROW
+}
+
+/* Assumes being correctly positioned in the file */
+
+static int SkipResourceSection(f, dir, type, checkName)
+ FILE *f;
+ ResourceDirectory dir;
+ ResourceType type;
+ int checkName;
+{
+ char inBuf[MAXLEN];
+ int i;
+
+ /* If next type has offset, just go there */
+
+ for (i = 0; i < dir->typeCount && dir->types + i != type; i++) {}
+
+ if (dir->types + i == type) {
+ for (i++; i < dir->typeCount; i++) {
+ if (dir->types[i].fileOffset == -1) continue;
+ if (dir->types[i].fileOffset > 0) {
+ if (fseek(f, dir->types[i].fileOffset, SEEK_SET) != -1) {
+ return 0;
+ } else break;
+ }
+ }
+ }
+
+ if (checkName && VerifyName(f, type->type) != 0) return 1;
+
+ while (1) {
+ if (myfgets(inBuf, MAXLEN, f) == NULL) return 1;
+ if (strcmp(inBuf, ".") == 0) return 0;
+ }
+}
+
+/* Assumes being correctly positioned in the file */
+
+static int ParseResourceSection(f, dir, type, name, checkName)
+ FILE *f;
+ ResourceDirectory dir;
+ ResourceType type;
+ char *name; /* If NULL, enumerate */
+ int checkName;
+{
+ if (checkName && VerifyName(f, type->type) != 0) return 1;
+
+ if (type->filled || (name != NULL && LookupResourceInList(type, name))) {
+ return SkipResourceSection(f, dir, type, 0);
+ }
+
+ return ReadResourceSection(f, dir, type, name);
+}
+
+void FreePSResourceStorage(everything)
+ int everything;
+{
+ ResourceDirectory d;
+ ResourceType t;
+ int i, j;
+
+ if (resDir == NULL) return;
+
+ for (d = resDir; d != NULL; d = d->next) {
+ for (i = 0; i < d->typeCount; i++) {
+ t = d->types + i;
+ FREE(t->nameBuffer);
+ FREE((char *) t->names);
+ t->nameCount = 0;
+ for (j = 0; j < t->oldNameCount; j++) FREE(t->oldNameBuffers[j]);
+ if (t->oldNameBuffers != NULL) FREE((char *) t->oldNameBuffers);
+ t->oldNameCount = 0;
+ t->nameCount = 0;
+ t->filled = 0;
+ }
+ }
+
+ if (!everything) return;
+
+ while (resDir != NULL) {
+ d = resDir->next;
+ FREE(resDir->directory);
+ FREE((char *) resDir->types);
+ FREE(resDir->typeNameBuffer);
+ FREE(resDir->filePrefix);
+ FREE((char *) resDir);
+ resDir = d;
+ }
+ lastResDir = NULL;
+ FREE(savedPathOverride);
+ savedPathOverride = NULL;
+ FREE(savedDefaultPath);
+ savedDefaultPath = NULL;
+}
+
+static ResourceDirectory ReadAndStoreFile(dir, name, len, readFunc, data)
+ char *dir, *name;
+ int len;
+ ReadContentsFunction readFunc;
+ char *data;
+{
+ ResourceDirectory rd = NULL;
+ FILE *f;
+ char nameBuf[MAXLEN];
+ char *fullName = nameBuf;
+ int fullLen;
+
+ fullLen = len + strlen(name) + 1;
+ if (fullLen >= MAXLEN) fullName = MALLOC(fullLen+1);
+ (void) strcpy(fullName, dir);
+ fullName[len] = '/';
+ (void) strcpy(fullName+len+1, name);
+
+ f = fopen(fullName, "r");
+ if (f != NULL) {
+ rd = ParseHeader(f, dir, fullName);
+
+ if (rd != NULL) {
+ if (resDir == NULL) resDir = rd;
+ else lastResDir->next = rd;
+ lastResDir = rd;
+ if (readFunc != NULL) (*readFunc) (f, rd, data);
+ } else (*PSResFileWarningHandler)(fullName, "Malformed header");
+ (void) fclose(f);
+ }
+ if (fullName != nameBuf) FREE(fullName);
+ return rd;
+}
+
+static time_t ReadFilesInDirectory(dirName, readFunc, data)
+ char *dirName;
+ ReadContentsFunction readFunc;
+ char *data;
+{
+ DIR *dir;
+#ifdef USE_POSIX
+ struct dirent *d;
+#else
+ struct direct *d;
+#endif
+ ResourceDirectory rd;
+ int len = strlen(dirName);
+ static int extensionLen = 0;
+ struct stat buf;
+ int namelen;
+
+ if (extensionLen == 0) extensionLen = strlen(PSRES_EXT);
+ if (stat(dirName, &buf) != 0) buf.st_mtime = 0;
+
+ rd = ReadAndStoreFile(dirName, PSRES_NAME, len, readFunc, data);
+
+ if (rd != 0 && rd->exclusive) return buf.st_mtime;
+
+ dir = opendir(dirName);
+ if (dir == NULL) return buf.st_mtime;
+
+ while ((d = readdir(dir)) != NULL) {
+ namelen = strlen(d->d_name);
+ if (namelen < extensionLen) continue;
+
+ if (strcmp(d->d_name + (namelen - extensionLen), PSRES_EXT) == 0
+ && strcmp(d->d_name, PSRES_NAME) != 0) {
+ (void) ReadAndStoreFile(dirName, d->d_name, len, readFunc, data);
+ }
+ }
+ (void) closedir(dir);
+ return buf.st_mtime;
+}
+
+/* Returns nonzero if current paths different from saved ones */
+
+static int SetUpSavedPaths(pathOverride, defaultPath)
+ char *pathOverride;
+ char *defaultPath;
+{
+ if (pathOverride == NULL) pathOverride = &nullStr;
+ if (defaultPath == NULL) defaultPath = &nullStr;
+
+ if (savedPathOverride == NULL ||
+ strcmp(pathOverride, savedPathOverride) != 0 ||
+ strcmp(defaultPath, savedDefaultPath) != 0) {
+
+ FreePSResourceStorage(1);
+
+ savedPathOverride = NewString(pathOverride);
+ savedDefaultPath = NewString(defaultPath);
+
+ return 1;
+ }
+ return 0;
+}
+
+/* Like SetUpSavedPaths, but never affects saved state */
+
+static int CheckSavedPaths(pathOverride, defaultPath)
+ char *pathOverride;
+ char *defaultPath;
+{
+ if (pathOverride == NULL) pathOverride = &nullStr;
+ if (defaultPath == NULL) defaultPath = &nullStr;
+
+ if (savedPathOverride == NULL ||
+ strcmp(pathOverride, savedPathOverride) != 0 ||
+ strcmp(defaultPath, savedDefaultPath) != 0) return 1;
+ else return 0;
+}
+
+static time_t ReadFilesInPath(string, readFunc, data)
+ char *string;
+ ReadContentsFunction readFunc;
+ char *data;
+{
+ char *pathChar;
+ char pathBuf[MAXLEN];
+ char *path;
+ register char *dir;
+ int len;
+ register char ch;
+ time_t newTime, latestTime = 0;
+
+ pathChar = string;
+
+ if (*pathChar == ':') pathChar++;
+
+ len = strlen(pathChar);
+ if (len < MAXLEN) path = pathBuf;
+ else path = MALLOC(len+1);
+
+ do {
+ dir = path;
+ do {
+ while (*pathChar == '\\') {
+ pathChar++;
+ if (*pathChar != '\0') *dir++ = *pathChar++;
+ }
+
+ *dir++ = ch = *pathChar++;
+ } while (ch != '\0' && ch != ':');
+ if (ch == ':') *(dir-1) = '\0';
+
+ if (*path == '\0') {
+ if (ch == ':' && string != savedDefaultPath) {
+ newTime = ReadFilesInPath(savedDefaultPath, readFunc, data);
+ if (newTime > latestTime) latestTime = newTime;
+ }
+ } else {
+ newTime = ReadFilesInDirectory(path, readFunc, data);
+ if (newTime > latestTime) latestTime = newTime;
+ }
+ } while (ch == ':');
+ if (path != pathBuf) FREE(path);
+ return latestTime;
+}
+
+static time_t MaxTimeInPath(string)
+ char *string;
+{
+ char *pathChar;
+ char pathBuf[MAXLEN];
+ char *path;
+ register char *dir;
+ int len;
+ register char ch;
+ time_t latestTime = 0;
+ struct stat buf;
+
+ pathChar = string;
+
+ if (*pathChar == ':') pathChar++;
+
+ len = strlen(pathChar);
+ if (len < MAXLEN) path = pathBuf;
+ else path = MALLOC(len+1);
+
+ do {
+ dir = path;
+ do {
+ while (*pathChar == '\\') {
+ pathChar++;
+ if (*pathChar != '\0') *dir++ = *pathChar++;
+ }
+
+ *dir++ = ch = *pathChar++;
+ } while (ch != '\0' && ch != ':');
+ if (ch == ':') *(dir-1) = '\0';
+
+ if (*path == '\0') {
+ if (ch == ':' && string != savedDefaultPath) {
+ buf.st_mtime = MaxTimeInPath(savedDefaultPath);
+ if (buf.st_mtime > latestTime) latestTime = buf.st_mtime;
+ }
+ } else {
+ if (stat(path, &buf) != 0) buf.st_mtime = 0;
+ if (buf.st_mtime > latestTime) latestTime = buf.st_mtime;
+ }
+ } while (ch == ':');
+ if (path != pathBuf) FREE(path);
+ return latestTime;
+}
+
+static char *GetPath()
+{
+ static char defaultEnvironmentPath[] = "::";
+ static char *environmentPath = NULL;
+
+ if (savedPathOverride != NULL && *savedPathOverride != '\0') {
+ return savedPathOverride;
+ }
+
+ if (environmentPath == NULL) {
+ environmentPath = getenv("PSRESOURCEPATH");
+ if (environmentPath == NULL) environmentPath = defaultEnvironmentPath;
+ }
+
+ return environmentPath;
+}
+
+void SetPSResourcePolicy(policy, willList, resourceTypes)
+ PSResourceSavePolicy policy;
+ int willList;
+ char **resourceTypes;
+{
+ currentPolicy = policy;
+
+ if (currentResourceTypes != NULL) FREE((char *) currentResourceTypes);
+ if (resourceTypeBuffer != NULL) FREE((char *) resourceTypeBuffer);
+
+ if (resourceTypes == NULL) {
+ currentResourceTypes = NULL;
+ resourceTypeBuffer = NULL;
+ } else {
+ int i = 0, len = 0;
+ char **cp = resourceTypes;
+
+ while (*cp != NULL) {
+ i++;
+ len += strlen(*cp) + 1;
+ cp++;
+ }
+
+ currentResourceTypes =
+ (char **) MALLOC((int) ((i+1) * sizeof(char *)));
+ resourceTypeBuffer = MALLOC(len);
+
+ len = 0;
+ i = 0;
+ cp = resourceTypes;
+
+ while (*cp != NULL) {
+ (void) strcpy(resourceTypeBuffer+len, *cp);
+ currentResourceTypes[i++] = resourceTypeBuffer + len;
+ len += strlen(*cp) + 1;
+ cp++;
+ }
+ currentResourceTypes[i] = NULL;
+ }
+}
+
+int InSavedList(type)
+ char *type;
+{
+ char **cp = currentResourceTypes;;
+
+ if (cp == NULL) return 0;
+
+ while (*cp != NULL) {
+ if (strcmp(*cp++, type) == 0) return 1;
+ }
+ return 0;
+}
+
+/* ARGSUSED */
+static int ReadEverything(f, rd, data)
+ FILE *f;
+ ResourceDirectory rd;
+ char *data;
+{
+ int i;
+ ResourceType t;
+ long pos;
+
+ /* We're at the start of the resource section; read all of them */
+
+ for (i = 0; i < rd->typeCount; i++) {
+ t = &rd->types[i];
+
+ if (t->fileOffset == -1) continue; /* Not really there */
+
+ if (t->fileOffset != 0 && fseek(f, t->fileOffset, SEEK_SET) != -1) {
+ if (!t->filled) {
+ if (ParseResourceSection(f, rd, t, (char *) NULL, 1)) {
+ char buf[256];
+ sprintf(buf, "Trouble parsing resource type %s", t->type);
+ PSResFileWarningHandler(rd->directory, buf);
+ return 1;
+ }
+ } else {
+ if (SkipResourceSection(f, rd, t, 1)) {
+ char buf[256];
+ sprintf(buf, "Trouble parsing resource type %s", t->type);
+ PSResFileWarningHandler(rd->directory, buf);
+ return 1;
+ }
+ }
+ continue;
+ }
+
+ pos = ftell(f);
+ if (VerifyName(f, t->type) == 0) {
+ t->fileOffset = pos;
+ if (ParseResourceSection(f, rd, t, (char *) NULL, 0)) {
+ char buf[256];
+ sprintf(buf, "Trouble parsing resource type %s", t->type);
+ PSResFileWarningHandler(rd->directory, buf);
+ return 1;
+ }
+ } else {
+ /* No resources of this type; try the next type */
+ t->fileOffset = -1;
+ if (fseek(f, pos, SEEK_SET)) {
+ PSResFileWarningHandler(rd->directory,
+ "File changed during execution");
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int ReadType(f, rd, type)
+ FILE *f;
+ ResourceDirectory rd;
+ char *type;
+{
+ int i;
+ ResourceType t;
+ long pos;
+
+ /* We're at the start of the resource section; read the sections that
+ are in the cached type list or are the passed in type */
+
+ for (i = 0; i < rd->typeCount; i++) {
+ t = &rd->types[i];
+
+ if (t->fileOffset == -1) continue; /* Not really there */
+ if (t->fileOffset != 0 && fseek(f, t->fileOffset, SEEK_SET) != -1) {
+ if (!t->filled &&
+ (strcmp(t->type, type) == 0 || InSavedList(t->type))) {
+ if (ParseResourceSection(f, rd, t, (char *) NULL, 1)) {
+ char buf[256];
+ sprintf(buf, "Trouble parsing resource type %s", t->type);
+ PSResFileWarningHandler(rd->directory, buf);
+ return 1;
+ }
+ } else if (SkipResourceSection(f, rd, t, 1)) {
+ char buf[256];
+ sprintf(buf, "Trouble parsing resource type %s", t->type);
+ PSResFileWarningHandler(rd->directory, buf);
+ return 1;
+ }
+ continue;
+ }
+
+ pos = ftell(f);
+ if (VerifyName(f, t->type) == 0) {
+ t->fileOffset = pos;
+ if (strcmp(t->type, type) == 0 || InSavedList(t->type)) {
+ if (ParseResourceSection(f, rd, t, (char *) NULL, 0)){
+ char buf[256];
+ sprintf(buf, "Trouble parsing resource type %s", t->type);
+ PSResFileWarningHandler(rd->directory, buf);
+ return 1;
+ }
+ } else if (SkipResourceSection(f, rd, t, 0)) {
+ char buf[256];
+ sprintf(buf, "Trouble parsing resource type %s", t->type);
+ PSResFileWarningHandler(rd->directory, buf);
+ return 1;
+ }
+ } else {
+ /* No resources of this type; try the next type */
+ t->fileOffset = -1;
+ if (fseek(f, pos, SEEK_SET) == -1) {
+ PSResFileWarningHandler(rd->directory,
+ "File changed during execution");
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int ReadName(f, rd, data)
+ FILE *f;
+ ResourceDirectory rd;
+ char *data;
+{
+ TypeName *tn = (TypeName *) data;
+ int i;
+ ResourceType t;
+ long pos;
+
+ /* We're at the start of the resource section; read the name in the
+ section for the passed in type */
+
+ for (i = 0; i < rd->typeCount; i++) {
+ t = &rd->types[i];
+
+ if (t->fileOffset == -1) continue; /* Not really there */
+ if (t->fileOffset != 0 && fseek(f, t->fileOffset, SEEK_SET)) {
+ if (strcmp(t->type, tn->type) == 0) {
+ if (ParseResourceSection(f, rd, t, tn->name, 1)) {
+ char buf[256];
+ sprintf(buf, "Trouble parsing resource type %s", t->type);
+ PSResFileWarningHandler(rd->directory, buf);
+ return 1;
+ }
+ } else if (SkipResourceSection(f, rd, t, 1)) {
+ char buf[256];
+ sprintf(buf, "Trouble parsing resource type %s", t->type);
+ PSResFileWarningHandler(rd->directory, buf);
+ return 1;
+ }
+ continue;
+ }
+
+ pos = ftell(f);
+ if (VerifyName(f, t->type) == 0) {
+ t->fileOffset = pos;
+ if (fseek(f, pos, SEEK_SET) == -1) {
+ PSResFileWarningHandler(rd->directory,
+ "File changed during execution");
+ return 1;
+ }
+ if (strcmp(t->type, tn->type) == 0) {
+ if (ParseResourceSection(f, rd, t, tn->name, 0)) {
+ char buf[256];
+ sprintf(buf, "Trouble parsing resource type %s", t->type);
+ PSResFileWarningHandler(rd->directory, buf);
+ return 1;
+ }
+ } else if (SkipResourceSection(f, rd, t, 0)) {
+ char buf[256];
+ sprintf(buf, "Trouble parsing resource type %s", t->type);
+ PSResFileWarningHandler(rd->directory, buf);
+ return 1;
+ }
+ } else {
+ /* No resources of this type; try the next type */
+ t->fileOffset = -1;
+ if (fseek(f, pos, SEEK_SET) == -1) {
+ PSResFileWarningHandler(rd->directory,
+ "File changed during execution");
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static void ReadHeadersAndData(resourceType, resourceName)
+ char *resourceType;
+ char *resourceName;
+{
+ TypeName t;
+
+ switch (currentPolicy) {
+ case PSSaveEverything:
+ lastModifiedTime =
+ ReadFilesInPath(GetPath(), ReadEverything, (char *) NULL);
+ break;
+ case PSSaveByType:
+ lastModifiedTime =
+ ReadFilesInPath(GetPath(), ReadType, resourceType);
+ break;
+ case PSSaveReturnValues:
+ t.type = resourceType;
+ t.name = resourceName;
+ lastModifiedTime =
+ ReadFilesInPath(GetPath(), ReadName, (char *) &t);
+ break;
+ }
+}
+
+static void UpdateData(resourceType, resourceName)
+ char *resourceType;
+ char *resourceName;
+{
+ ResourceDirectory rd;
+ ResourceType rt;
+ int i;
+ FILE *f;
+ TypeName tn;
+
+ /* Make two passes; the first figures out if we're going to have to read
+ the file to service this request. If we are, open the file and read
+ in sections in the saved list (from SetPSResourcePolicy). If not
+ just saving return values, make sure we read in everything
+ in the section. */
+
+ for (rd = resDir; rd != NULL; rd = rd->next) {
+ f = NULL;
+ for (i = 0; i < rd->typeCount; i++) {
+ rt = rd->types + i;
+ if (rt->filled) continue;
+ if (strcmp(rt->type, resourceType) != 0) continue;
+
+ if (resourceName != NULL &&
+ LookupResourceInList(rt, resourceName)) continue;
+
+ f = fopen(rd->directory, "r");
+ break;
+ }
+ if (f == NULL) continue;
+
+ /* Nuts, have to read the file */
+
+ if (fseek(f, rd->endOfHeader, SEEK_SET) != -1) {
+ switch (currentPolicy) {
+ case PSSaveEverything:
+ (void) ReadEverything(f, rd, (char *) NULL);
+ break;
+ case PSSaveByType:
+ (void) ReadType(f, rd, resourceType);
+ break;
+ case PSSaveReturnValues:
+ tn.type = resourceType;
+ tn.name = resourceName;
+ (void) ReadName(f, rd, (char *) &tn);
+ break;
+ }
+ } else (*PSResFileWarningHandler)(rd->directory,
+ "File changed during execution");
+ (void) fclose(f);
+ }
+}
+
+static int FindData(resourceType, resourceName,
+ resourceNamesReturn, resourceFilesReturn)
+ char *resourceType;
+ char *resourceName;
+ char ***resourceNamesReturn;
+ char ***resourceFilesReturn;
+{
+ ResourceDirectory rd;
+ ResourceType rt;
+ int i, j, k;
+ int nameCount = 0;
+ char **names, **files;
+
+ /* Make two passes; first count, then set and return */
+
+ for (rd = resDir; rd != NULL; rd = rd->next) {
+ for (i = 0; i < rd->typeCount; i++) {
+ rt = rd->types + i;
+ if (strcmp(rt->type, resourceType) != 0) continue;
+ if (resourceName == NULL) nameCount += rt->nameCount;
+ else {
+ for (j = 0; j < rt->nameCount; j++) {
+ if (strcmp(rt->names[j].name, resourceName) == 0) {
+ nameCount++;
+ }
+ }
+ }
+ }
+ }
+
+ if (nameCount == 0) return 0;
+
+ names = (char **) MALLOC((int) (nameCount * sizeof(char *)));
+ files = (char **) MALLOC((int) (nameCount * sizeof(char *)));
+ k = 0;
+
+ for (rd = resDir; rd != NULL; rd = rd->next) {
+ for (i = 0; i < rd->typeCount; i++) {
+ rt = rd->types + i;
+ if (strcmp(rt->type, resourceType) != 0) continue;
+ for (j = 0; j < rt->nameCount; j++) {
+ if (resourceName == NULL ||
+ strcmp(rt->names[j].name, resourceName) == 0) {
+ names[k] = rt->names[j].name;
+ files[k++] = rt->names[j].file;
+ }
+ }
+ }
+ }
+
+ *resourceNamesReturn = names;
+ *resourceFilesReturn = files;
+ return nameCount;
+}
+
+extern int ListPSResourceFiles(psResourcePathOverride, defaultPath,
+ resourceType, resourceName,
+ resourceNamesReturn, resourceFilesReturn)
+ char *psResourcePathOverride;
+ char *defaultPath;
+ char *resourceType;
+ char *resourceName;
+ char ***resourceNamesReturn;
+ char ***resourceFilesReturn;
+{
+ if (SetUpSavedPaths(psResourcePathOverride, defaultPath)) {
+ ReadHeadersAndData(resourceType, resourceName);
+ } else UpdateData(resourceType, resourceName);
+ return FindData(resourceType, resourceName,
+ resourceNamesReturn, resourceFilesReturn);
+}
+
+int ListPSResourceTypes(pathOverride, defaultPath, typesReturn)
+ char *pathOverride;
+ char *defaultPath;
+ char ***typesReturn;
+{
+#define GROW 5
+#define START 15
+ int typeCount = 0, i, j, typeBufSize = 0;
+ ResourceDirectory d;
+ register char **types = NULL;
+ int sig;
+ int *sigs = NULL;
+ char *ch;
+
+ if (SetUpSavedPaths(pathOverride, defaultPath)) {
+ if (currentPolicy != PSSaveEverything) {
+ lastModifiedTime =
+ ReadFilesInPath(GetPath(), (ReadContentsFunction) NULL,
+ (char *) NULL);
+ } else lastModifiedTime =
+ ReadFilesInPath(GetPath(), ReadEverything, (char *) NULL);
+ }
+
+ for (d = resDir; d != NULL; d = d->next) {
+ for (i = 0; i < d->typeCount; i++) {
+ for (sig = 0, ch = d->types[i].type; *ch != '\0'; sig += *ch++) {}
+ for (j = 0; j < typeCount; j++) {
+ if (sig == sigs[j] &&
+ strcmp(types[j], d->types[i].type) == 0) break;
+ }
+ if (j >= typeCount) { /* Have to add */
+ if (typeCount >= typeBufSize) {
+ if (typeCount == 0) typeBufSize = START;
+ else typeBufSize += GROW;
+ types = (char **) REALLOC((char *) types,
+ typeBufSize * sizeof(char *));
+ sigs = (int *) REALLOC((char *) sigs,
+ typeBufSize * sizeof(int));
+ }
+ types[typeCount] = d->types[i].type;
+ sigs[typeCount++] = sig;
+ }
+ }
+ }
+
+ FREE((char *) sigs);
+ *typesReturn = types;
+ return typeCount;
+#undef START
+#undef GROW
+}
+
+/* Assumes being correctly positioned in the file */
+
+static int EnumerateResourceSection(f, dir, type, s, checkName)
+ FILE *f;
+ ResourceDirectory dir;
+ ResourceType type;
+ EnumeratorStruct *s;
+ int checkName;
+{
+#define GROW 1000
+ char *linein;
+ int len;
+ char namebuf[GROW];
+ char *names = namebuf;
+ int buflen = GROW, namelen = 0;
+ char *sep;
+ int prefixLen;
+ int insertPrefix;
+ char *file;
+ char dontDequote;
+ int doubleEquals;
+ int addingPrefix;
+
+ if (checkName && VerifyName(f, type->type) != 0) return 1;
+
+ insertPrefix = CheckInsertPrefix(type->type);
+ if (insertPrefix) {
+ prefixLen = strlen(dir->filePrefix);
+ dontDequote = '\0';
+ } else {
+ prefixLen = 0;
+ dontDequote = ',';
+ }
+
+ while (1) {
+ linein = ReadFullLine(f);
+ if (linein == NULL) {
+ if (names != namebuf) FREE((char *) names);
+ FreeLineBuf();
+ return 1;
+ }
+
+ if (strcmp(linein, ".") == 0) {
+ if (names != namebuf) FREE((char *) names);
+ FreeLineBuf();
+ return 0;
+ }
+
+ sep = NULL;
+ (void) DequoteAndBreak(linein, &sep, '=', dontDequote, &doubleEquals);
+
+ /* If no separator, a bogus line */
+ if (sep == NULL) continue;
+
+ /* Next line is UNIX specific! */
+ addingPrefix = *(sep+1) != '/' && insertPrefix && !doubleEquals;
+
+ len = strlen(linein) + (addingPrefix ? 0 : prefixLen) + 1;
+ if (len > buflen) {
+ if (names != namebuf) FREE((char *) names);
+ names = (char *) MALLOC(len);
+ }
+
+ *sep = '\0';
+ len = strlen(linein);
+ (void) strncpy(names, linein, len+1);
+
+ namelen = len+1;
+ file = &names[namelen];
+
+ if (addingPrefix) {
+ (void) strncpy(&names[namelen], dir->filePrefix, prefixLen);
+ namelen += prefixLen;
+ }
+
+ len = strlen(sep+1);
+ (void) strncpy(&names[namelen], sep+1, len+1);
+
+ if (s->name == NULL || strcmp(names, s->name) == 0) {
+ s->done = (*s->func) (s->type, names, file, s->private);
+ if (s->done) {
+ if (names != namebuf) FREE((char *) names);
+ FreeLineBuf();
+ return 0;
+ }
+ }
+ }
+#undef GROW
+}
+
+static int Enumerate(f, rd, data)
+ FILE *f;
+ ResourceDirectory rd;
+ char *data;
+{
+ EnumeratorStruct *s = (EnumeratorStruct *) data;
+ int i;
+ ResourceType t;
+ long pos;
+
+ if (s->done) return 0;
+
+ for (i = 0; i < rd->typeCount; i++) {
+ t = &rd->types[i];
+
+ if (t->fileOffset == -1) continue; /* Not really there */
+ if (t->fileOffset != 0 && fseek(f, t->fileOffset, SEEK_SET) != -1) {
+ if (strcmp(t->type, s->type) == 0) {
+ if (EnumerateResourceSection(f, rd, t, s, 1)) {
+ char buf[256];
+ sprintf(buf, "Trouble parsing resource type %s", t->type);
+ PSResFileWarningHandler(rd->directory, buf);
+ return 1;
+ }
+ if (s->done) return 0;;
+ } else if (SkipResourceSection(f, rd, t, 1)) {
+ char buf[256];
+ sprintf(buf, "Trouble parsing resource type %s", t->type);
+ PSResFileWarningHandler(rd->directory, buf);
+ return 1;
+ }
+ continue;
+ }
+
+ pos = ftell(f);
+ if (VerifyName(f, t->type) == 0) {
+ t->fileOffset = pos;
+ if (strcmp(t->type, s->type) == 0) {
+ if (EnumerateResourceSection(f, rd, t, s, 0)) return 1;
+ if (s->done) return 0;
+ } else if (SkipResourceSection(f, rd, t, 0)) return 1;
+ } else {
+ /* No resources of this type; try the next type */
+ t->fileOffset = -1;
+ if (fseek(f, pos, SEEK_SET) == -1) return 1;
+ }
+ }
+ return 0;
+}
+
+void EnumeratePSResourceFiles(pathOverride, defaultPath, resourceType,
+ resourceName, enumerator, private)
+ char *pathOverride;
+ char *defaultPath;
+ char *resourceType;
+ char *resourceName;
+ PSResourceEnumerator enumerator;
+ char *private;
+{
+ ResourceDirectory d;
+ FILE *f;
+ EnumeratorStruct s;
+
+ s.func = enumerator;
+ s.type = resourceType;
+ s.name = resourceName;
+ s.private = private;
+ s.done = 0;
+
+ if (SetUpSavedPaths(pathOverride, defaultPath)) {
+ lastModifiedTime =
+ ReadFilesInPath(GetPath(), Enumerate, (char *) &s);
+ return;
+ }
+
+ for (d = resDir; d != NULL && !s.done; d = d->next) {
+ f = fopen(d->directory, "r");
+ if (f == NULL) continue;
+ if (fseek(f, d->endOfHeader, SEEK_SET) != -1) {
+ (void) Enumerate(f, d, (char *) &s);
+ }
+ (void) fclose(f);
+ }
+}
+
+int CheckPSResourceTime(pathOverride, defaultPath)
+ char *pathOverride;
+ char *defaultPath;
+{
+ if (CheckSavedPaths(pathOverride, defaultPath)) return 1;
+ return MaxTimeInPath(GetPath()) > lastModifiedTime;
+}