diff options
author | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
commit | f4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch) | |
tree | 2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/lib/psres/PSres.c | |
parent | a840692edc9c6d19cd7c057f68e39c7d95eb767d (diff) | |
download | nx-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.c | 1661 |
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; +} |