4
* (c) Copyright 1991-1994 Adobe Systems Incorporated.
7
* Permission to use, copy, modify, distribute, and sublicense this software
8
* and its documentation for any purpose and without fee is hereby granted,
9
* provided that the above copyright notices appear in all copies and that
10
* both those copyright notices and this permission notice appear in
11
* supporting documentation and that the name of Adobe Systems Incorporated
12
* not be used in advertising or publicity pertaining to distribution of the
13
* software without specific, written prior permission. No trademark license
14
* to use the Adobe trademarks is hereby granted. If the Adobe trademark
15
* "Display PostScript"(tm) is used to describe this software, its
16
* functionality or for any other purpose, such use shall be limited to a
17
* statement that this software works in conjunction with the Display
18
* PostScript system. Proper trademark attribution to reflect Adobe's
19
* ownership of the trademark shall be given whenever any such reference to
20
* the Display PostScript system is made.
22
* ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
23
* ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
24
* ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
25
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26
* NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
27
* TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
28
* DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
29
* NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
30
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
31
* PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
33
* Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
34
* Incorporated which may be registered in certain jurisdictions
36
* Author: Adobe Systems Incorporated
38
/* $XFree86: xc/lib/psres/PSres.c,v 1.4 2001/10/28 03:32:46 tsi Exp $ */
47
#include <sys/types.h>
63
#include <DPS/PSres.h>
66
#define PSRES_NAME "PSres.upr"
67
#endif /* PSRES_NAME */
70
#define PSRES_EXT ".upr"
71
#endif /* PSRES_EXT */
77
/* MT is the right pointer type to pass to memcpy, MST the size type */
82
typedef int (*ReadContentsFunction)();
84
char *PSResFontOutline = "FontOutline",
85
*PSResFontPrebuilt = "FontPrebuilt",
86
*PSResFontAFM = "FontAFM",
87
*PSResFontBDF = "FontBDF",
88
*PSResFontFamily = "FontFamily",
89
*PSResFontBDFSizes = "FontBDFSizes",
91
*PSResPattern = "Pattern",
92
*PSResEncoding = "Encoding",
93
*PSResProcSet = "ProcSet";
95
typedef struct _ResourceNameStruct {
98
} ResourceNameStruct, *ResourceName;
100
typedef struct _ResourceTypeStruct {
102
long fileOffset; /* -1 means not really in the file */
105
int filled; /* Whether has all names or just already found names */
107
char **oldNameBuffers;
109
} ResourceTypeStruct, *ResourceType;
111
typedef struct _ResourceDirectoryStruct {
115
char *typeNameBuffer;
119
struct _ResourceDirectoryStruct *next;
120
} ResourceDirectoryStruct, *ResourceDirectory;
128
PSResourceEnumerator func;
135
static ResourceDirectory resDir = NULL, lastResDir;
136
static char *savedPathOverride = NULL, *savedDefaultPath = NULL;
137
static PSResourceSavePolicy currentPolicy = PSSaveByType;
138
static int currentWillList;
139
static char **currentResourceTypes = NULL;
140
static char *resourceTypeBuffer = NULL;
141
static time_t lastModifiedTime;
142
static char nullStr = '\0';
146
static char *mymalloc(size)
152
#ifdef MALLOC_0_RETURNS_NULL
153
if (size < 1) size = 1;
156
if (size < 1) size = 1; /* Better safe than sorry */
159
ret = (char *) malloc((unsigned) size);
160
if (ret != NULL) return ret;
161
(void) fprintf(stderr, "malloc failed\n");
166
PSResMallocProc PSResMalloc = mymalloc;
167
#define MALLOC (*PSResMalloc)
169
static char *myrealloc(ptr, size)
176
#ifdef MALLOC_0_RETURNS_NULL
177
if (size < 1) size = 1;
180
if (size < 1) size = 1; /* Better safe than sorry */
183
if (ptr == NULL) return MALLOC(size);
185
ret = (char *) realloc(ptr, (unsigned) size);
187
ret = (char *) realloc((void *) ptr, (unsigned) size);
189
if (ret != NULL) return ret;
190
(void) fprintf(stderr, "realloc failed\n");
195
PSResReallocProc PSResRealloc = myrealloc;
196
#define REALLOC (*PSResRealloc)
198
static void myfree(ptr)
202
if (ptr != NULL) free(ptr);
204
if (ptr != NULL) free((void *) ptr);
208
PSResFreeProc PSResFree = myfree;
209
#define FREE (*PSResFree)
211
#define NewString(str) ((char *) strcpy(MALLOC((int) (strlen(str)+1)),(str)))
213
static void FileWarningHandler(file, extraInfo)
218
"Syntax error found in PostScript resource file %s:\n %s\n",
222
PSResFileWarningHandlerProc PSResFileWarningHandler = FileWarningHandler;
224
/* Just like fgets, but strips trailing newline, eliminates trailing comments,
225
skips trailing white space, skips blank lines, and chops lines longer
228
static char *myfgets(buf, size, f)
234
register int count = 0;
236
#define STRIP_BLANKS \
237
while (--count >= 0 && (buf[count] == ' ' || buf[count] == '\t')) \
240
if (buf[0] != '\0') return buf; \
241
else return myfgets(buf, size, f);
243
if (size == 0) return buf;
246
while (count < size) {
258
if (ch == '%') { /* Comment */
259
if (count == 0 || buf[count-1] != '\\') {
263
} while (ch != EOF && ch != '\n');
265
if (ch == EOF) return NULL;
274
/* Overflow, flush */
278
} while (ch != EOF && ch != '\n');
280
if (ch == EOF) return NULL;
286
static int Dequote(buf, dontDequote)
290
char *dst = buf, *src = buf;
292
while (*src != '\0') {
298
} else if (*src == dontDequote) *dst++ = '\\';
306
/* Sep returns the first unquoted position of the break character. The
307
dontDequote character only applies after the break character. If the
308
separator character is doubled, doubleSep is set to 1 and only one
309
of the separators is installed */
311
static int DequoteAndBreak(buf, sep, bchar, dontDequote, doubleSep)
318
char *dst = buf, *src = buf;
323
while (*src != '\0') {
329
} else if (*src == dontDequote && *sep != NULL) *dst++ = '\\';
330
} else if (*sep == NULL && *src == bchar) {
332
if (*(src+1) == bchar) {
343
static float ParseVersion(f, excl)
351
if (myfgets(inBuf, MAXLEN, f) == NULL) return 0.0;
353
/* Compare against magic value */
355
count = sscanf(inBuf, "PS-Resources-Exclusive-%f", &version);
360
count = sscanf(inBuf, "PS-Resources-%f", &version);
368
static int ParseResourceTypes(f, dir)
370
ResourceDirectory dir;
373
char typebuf[MAXLEN];
374
char *types = typebuf;
375
int buflen = MAXLEN, typelen = 0, len;
377
int continued = 0, precontinued = 0;
383
if (myfgets(inBuf, MAXLEN, f) == NULL) {
384
if (types != typebuf) FREE((char *) types);
387
if (strcmp(inBuf, ".") == 0) break;
388
precontinued = continued;
389
continued = Dequote(inBuf, '\0');
392
if (typelen + len + 1 > buflen) {
393
if (types == typebuf) {
394
types = (char *) MALLOC(2*MAXLEN);
395
(void) memcpy((MT) types, (MT) typebuf, (MST) typelen);
396
} else types = REALLOC(types, buflen+MAXLEN);
400
if (precontinued) typelen--; /* Write over previous \0 */
402
(void) strncpy(&types[typelen], inBuf, len+1);
406
dir->typeCount = count;
407
if (count == 0) dir->types = NULL;
409
dir->types = (ResourceType)
410
MALLOC((int) (count * sizeof(ResourceTypeStruct)));
411
dir->typeNameBuffer = (char *) MALLOC(typelen);
412
(void) memcpy((MT) dir->typeNameBuffer, (MT) types, (MST) typelen);
416
for (i = 0; i < count; i++) {
417
dir->types[i].type = &(dir->typeNameBuffer[len]);
418
dir->types[i].fileOffset = 0;
419
dir->types[i].names = NULL;
420
dir->types[i].nameBuffer = NULL;
421
dir->types[i].filled = 0;
422
dir->types[i].oldNameBuffers = NULL;
423
dir->types[i].oldNameCount = 0;
424
dir->types[i].nameCount = 0;
425
len += strlen(dir->types[i].type) + 1;
428
if (types != typebuf) FREE((char *) types);
432
static int ParseFilePrefix(f, dir, dirName)
434
ResourceDirectory dir;
443
dir->filePrefix = NULL;
446
if (myfgets(inBuf, MAXLEN, f) == NULL) return 1;
448
if (inBuf[0] != '/') {
449
if (fseek(f, savePos, SEEK_SET) == -1) return 1;
450
len = strlen(dirName);
451
dir->filePrefix = strcpy((char *) MALLOC(len+2), dirName);
452
dir->filePrefix[len] = '/';
453
dir->filePrefix[len+1] = '\0';
457
continued = Dequote(inBuf, '\0');
459
len = strlen(prefix);
460
dir->filePrefix = (char *) strcpy((char *) MALLOC(len+2), prefix);
462
dir->filePrefix[len] = '/';
463
dir->filePrefix[len+1] = '\0';
468
if (myfgets(inBuf, MAXLEN, f) == NULL) return 1;
469
continued = Dequote(inBuf, '\0');
470
len += strlen(inBuf);
471
dir->filePrefix = (char *) REALLOC(dir->filePrefix, len+2);
472
(void) strcat(dir->filePrefix, inBuf);
474
dir->filePrefix[len] = '/';
475
dir->filePrefix[len+1] = '\0';
481
static ResourceDirectory ParseHeader(f, dirName, fileName)
483
char *dirName, *fileName;
485
ResourceDirectory dir;
491
version = ParseVersion(f, &exclusive);
492
if (version < 1.0) return NULL;
494
dir = (ResourceDirectory) MALLOC(sizeof(ResourceDirectoryStruct));
495
dir->directory = (char *) NewString(fileName);
496
dir->exclusive = exclusive;
499
if (ParseResourceTypes(f, dir)) {
500
FREE((char *) dir->directory);
505
if (ParseFilePrefix(f, dir, dirName)) dir->endOfHeader = 0;
506
else dir->endOfHeader = ftell(f);
511
/* Store away old name buffer so pointers to it do not become invalid */
513
static void CacheOldNames(type)
516
type->oldNameCount++;
517
type->oldNameBuffers = (char **) REALLOC((char *) type->oldNameBuffers,
519
type->oldNameBuffers[type->oldNameCount-1] = type->nameBuffer;
520
type->nameBuffer = NULL;
523
/* Verify that the name matches the name in the file */
525
static int VerifyName(f, name)
535
if (myfgets(inBuf, MAXLEN, f) == NULL) return 1;
536
continued = Dequote(inBuf, '\0');
539
if (strncmp(inBuf, &name[start], len) != 0) return 1;
542
if (strcmp(inBuf, &name[start]) != 0) return 1;
549
static int LookupResourceInList(type, name)
555
for (i = 0; i < type->nameCount; i++) {
556
if (strcmp(name, type->names[i].name) == 0) return 1;
561
static int CheckInsertPrefix(type)
564
/* Insert the prefix unless one of these special values */
566
if (strcmp(type, PSResFontFamily) == 0 ||
567
strcmp(type, PSResFontBDFSizes) == 0 ||
568
strcmp(type, "FontAxes") == 0 ||
569
strcmp(type, "FontBlendMap") == 0 ||
570
strcmp(type, "FontBlendPositions") == 0 ||
571
strcmp(type, "mkpsresPrivate") == 0) return 0;
575
/* Returns a line, including continuations. Memory must be copied before
576
calling this again. */
578
static int linebuflen = 0;
579
static char *inputline = NULL;
581
static char *ReadFullLine(f)
584
char readbuf[MAXLEN];
589
if (myfgets(readbuf, MAXLEN, f) == NULL) return NULL;
590
len = strlen(readbuf);
591
if (start + len + 1 > linebuflen) {
592
linebuflen += MAXLEN + 1;
593
inputline = REALLOC(inputline, linebuflen);
595
strncpy(inputline+start, readbuf, len+1);
597
if (inputline[start+len-1] != '\\') break;
604
static void FreeLineBuf()
606
if (inputline != NULL) FREE(inputline);
611
/* Assumes being correctly positioned in the file */
613
static int ReadResourceSection(f, dir, type, name)
615
ResourceDirectory dir;
617
char *name; /* If NULL, enumerate */
624
char *names = namebuf;
625
int buflen = GROW, namelen = 0;
635
if (type->nameBuffer != NULL) CacheOldNames(type);
637
insertPrefix = CheckInsertPrefix(type->type);
639
prefixLen = strlen(dir->filePrefix);
649
linein = ReadFullLine(f);
650
if (linein == NULL) {
651
if (names != namebuf) FREE((char *) names);
655
if (strcmp(linein, ".") == 0) break;
658
(void) DequoteAndBreak(linein, &sep, '=', dontDequote, &doubleEquals);
660
/* If no separator, a bogus line */
661
if (sep == NULL) continue;
663
/* Next line is UNIX specific! */
664
addingPrefix = *(sep+1) != '/' && insertPrefix && !doubleEquals;
666
len = strlen(linein) + 1 + (addingPrefix ? prefixLen : 0);
668
if (namelen + len >= buflen) {
669
newsize = buflen + GROW;
670
if (namelen + len > newsize) newsize = namelen + len;
672
if (names == namebuf) {
673
names = (char *) MALLOC(newsize);
674
(void) memcpy((MT) names, (MT) namebuf, (MST) namelen);
675
} else names = REALLOC(names, newsize);
680
len = strlen(linein);
681
(void) strncpy(&names[namelen], linein, len+1);
685
(void) strncpy(&names[namelen], dir->filePrefix, prefixLen);
686
namelen += prefixLen;
690
(void) strncpy(&names[namelen], sep+1, len+1);
693
if (name != NULL && strcmp(names, name) != 0) namelen = start;
697
type->nameCount = count;
698
if (count == 0) type->names = NULL;
700
type->names = (ResourceName)
701
MALLOC((int) (count * sizeof(ResourceNameStruct)));
702
type->nameBuffer = (char *) MALLOC(namelen);
703
(void) memcpy((MT) type->nameBuffer, (MT) names, (MST) namelen);
707
for (i = 0; i < count; i++) {
708
type->names[i].name = &(type->nameBuffer[len]);
709
len += strlen(type->names[i].name) + 1;
710
type->names[i].file = &(type->nameBuffer[len]);
711
len += strlen(type->names[i].file) + 1;
714
if (names != namebuf) FREE((char *) names);
715
if (name == NULL) type->filled = 1;
722
/* Assumes being correctly positioned in the file */
724
static int SkipResourceSection(f, dir, type, checkName)
726
ResourceDirectory dir;
733
/* If next type has offset, just go there */
735
for (i = 0; i < dir->typeCount && dir->types + i != type; i++) {}
737
if (dir->types + i == type) {
738
for (i++; i < dir->typeCount; i++) {
739
if (dir->types[i].fileOffset == -1) continue;
740
if (dir->types[i].fileOffset > 0) {
741
if (fseek(f, dir->types[i].fileOffset, SEEK_SET) != -1) {
748
if (checkName && VerifyName(f, type->type) != 0) return 1;
751
if (myfgets(inBuf, MAXLEN, f) == NULL) return 1;
752
if (strcmp(inBuf, ".") == 0) return 0;
756
/* Assumes being correctly positioned in the file */
758
static int ParseResourceSection(f, dir, type, name, checkName)
760
ResourceDirectory dir;
762
char *name; /* If NULL, enumerate */
765
if (checkName && VerifyName(f, type->type) != 0) return 1;
767
if (type->filled || (name != NULL && LookupResourceInList(type, name))) {
768
return SkipResourceSection(f, dir, type, 0);
771
return ReadResourceSection(f, dir, type, name);
774
void FreePSResourceStorage(everything)
781
if (resDir == NULL) return;
783
for (d = resDir; d != NULL; d = d->next) {
784
for (i = 0; i < d->typeCount; i++) {
787
FREE((char *) t->names);
789
for (j = 0; j < t->oldNameCount; j++) FREE(t->oldNameBuffers[j]);
790
if (t->oldNameBuffers != NULL) FREE((char *) t->oldNameBuffers);
797
if (!everything) return;
799
while (resDir != NULL) {
801
FREE(resDir->directory);
802
FREE((char *) resDir->types);
803
FREE(resDir->typeNameBuffer);
804
FREE(resDir->filePrefix);
805
FREE((char *) resDir);
809
FREE(savedPathOverride);
810
savedPathOverride = NULL;
811
FREE(savedDefaultPath);
812
savedDefaultPath = NULL;
815
static ResourceDirectory ReadAndStoreFile(dir, name, len, readFunc, data)
818
ReadContentsFunction readFunc;
821
ResourceDirectory rd = NULL;
823
char nameBuf[MAXLEN];
824
char *fullName = nameBuf;
827
fullLen = len + strlen(name) + 1;
828
if (fullLen >= MAXLEN) fullName = MALLOC(fullLen+1);
829
(void) strcpy(fullName, dir);
831
(void) strcpy(fullName+len+1, name);
833
f = fopen(fullName, "r");
835
rd = ParseHeader(f, dir, fullName);
838
if (resDir == NULL) resDir = rd;
839
else lastResDir->next = rd;
841
if (readFunc != NULL) (*readFunc) (f, rd, data);
842
} else (*PSResFileWarningHandler)(fullName, "Malformed header");
845
if (fullName != nameBuf) FREE(fullName);
849
static time_t ReadFilesInDirectory(dirName, readFunc, data)
851
ReadContentsFunction readFunc;
860
ResourceDirectory rd;
861
int len = strlen(dirName);
862
static int extensionLen = 0;
866
if (extensionLen == 0) extensionLen = strlen(PSRES_EXT);
867
if (stat(dirName, &buf) != 0) buf.st_mtime = 0;
869
rd = ReadAndStoreFile(dirName, PSRES_NAME, len, readFunc, data);
871
if (rd != 0 && rd->exclusive) return buf.st_mtime;
873
dir = opendir(dirName);
874
if (dir == NULL) return buf.st_mtime;
876
while ((d = readdir(dir)) != NULL) {
877
namelen = strlen(d->d_name);
878
if (namelen < extensionLen) continue;
880
if (strcmp(d->d_name + (namelen - extensionLen), PSRES_EXT) == 0
881
&& strcmp(d->d_name, PSRES_NAME) != 0) {
882
(void) ReadAndStoreFile(dirName, d->d_name, len, readFunc, data);
885
(void) closedir(dir);
889
/* Returns nonzero if current paths different from saved ones */
891
static int SetUpSavedPaths(pathOverride, defaultPath)
895
if (pathOverride == NULL) pathOverride = &nullStr;
896
if (defaultPath == NULL) defaultPath = &nullStr;
898
if (savedPathOverride == NULL ||
899
strcmp(pathOverride, savedPathOverride) != 0 ||
900
strcmp(defaultPath, savedDefaultPath) != 0) {
902
FreePSResourceStorage(1);
904
savedPathOverride = NewString(pathOverride);
905
savedDefaultPath = NewString(defaultPath);
912
/* Like SetUpSavedPaths, but never affects saved state */
914
static int CheckSavedPaths(pathOverride, defaultPath)
918
if (pathOverride == NULL) pathOverride = &nullStr;
919
if (defaultPath == NULL) defaultPath = &nullStr;
921
if (savedPathOverride == NULL ||
922
strcmp(pathOverride, savedPathOverride) != 0 ||
923
strcmp(defaultPath, savedDefaultPath) != 0) return 1;
927
static time_t ReadFilesInPath(string, readFunc, data)
929
ReadContentsFunction readFunc;
933
char pathBuf[MAXLEN];
938
time_t newTime, latestTime = 0;
942
if (*pathChar == ':') pathChar++;
944
len = strlen(pathChar);
945
if (len < MAXLEN) path = pathBuf;
946
else path = MALLOC(len+1);
951
while (*pathChar == '\\') {
953
if (*pathChar != '\0') *dir++ = *pathChar++;
956
*dir++ = ch = *pathChar++;
957
} while (ch != '\0' && ch != ':');
958
if (ch == ':') *(dir-1) = '\0';
961
if (ch == ':' && string != savedDefaultPath) {
962
newTime = ReadFilesInPath(savedDefaultPath, readFunc, data);
963
if (newTime > latestTime) latestTime = newTime;
966
newTime = ReadFilesInDirectory(path, readFunc, data);
967
if (newTime > latestTime) latestTime = newTime;
970
if (path != pathBuf) FREE(path);
974
static time_t MaxTimeInPath(string)
978
char pathBuf[MAXLEN];
983
time_t latestTime = 0;
988
if (*pathChar == ':') pathChar++;
990
len = strlen(pathChar);
991
if (len < MAXLEN) path = pathBuf;
992
else path = MALLOC(len+1);
997
while (*pathChar == '\\') {
999
if (*pathChar != '\0') *dir++ = *pathChar++;
1002
*dir++ = ch = *pathChar++;
1003
} while (ch != '\0' && ch != ':');
1004
if (ch == ':') *(dir-1) = '\0';
1006
if (*path == '\0') {
1007
if (ch == ':' && string != savedDefaultPath) {
1008
buf.st_mtime = MaxTimeInPath(savedDefaultPath);
1009
if (buf.st_mtime > latestTime) latestTime = buf.st_mtime;
1012
if (stat(path, &buf) != 0) buf.st_mtime = 0;
1013
if (buf.st_mtime > latestTime) latestTime = buf.st_mtime;
1015
} while (ch == ':');
1016
if (path != pathBuf) FREE(path);
1020
static char *GetPath()
1022
static char defaultEnvironmentPath[] = "::";
1023
static char *environmentPath = NULL;
1025
if (savedPathOverride != NULL && *savedPathOverride != '\0') {
1026
return savedPathOverride;
1029
if (environmentPath == NULL) {
1030
environmentPath = getenv("PSRESOURCEPATH");
1031
if (environmentPath == NULL) environmentPath = defaultEnvironmentPath;
1034
return environmentPath;
1037
void SetPSResourcePolicy(policy, willList, resourceTypes)
1038
PSResourceSavePolicy policy;
1040
char **resourceTypes;
1042
currentPolicy = policy;
1043
currentWillList = willList;
1045
if (currentResourceTypes != NULL) FREE((char *) currentResourceTypes);
1046
if (resourceTypeBuffer != NULL) FREE((char *) resourceTypeBuffer);
1048
if (resourceTypes == NULL) {
1049
currentResourceTypes = NULL;
1050
resourceTypeBuffer = NULL;
1053
char **cp = resourceTypes;
1055
while (*cp != NULL) {
1057
len += strlen(*cp) + 1;
1061
currentResourceTypes =
1062
(char **) MALLOC((int) ((i+1) * sizeof(char *)));
1063
resourceTypeBuffer = MALLOC(len);
1069
while (*cp != NULL) {
1070
(void) strcpy(resourceTypeBuffer+len, *cp);
1071
currentResourceTypes[i++] = resourceTypeBuffer + len;
1072
len += strlen(*cp) + 1;
1075
currentResourceTypes[i] = NULL;
1079
int InSavedList(type)
1082
char **cp = currentResourceTypes;;
1084
if (cp == NULL) return 0;
1086
while (*cp != NULL) {
1087
if (strcmp(*cp++, type) == 0) return 1;
1093
static int ReadEverything(f, rd, data)
1095
ResourceDirectory rd;
1102
/* We're at the start of the resource section; read all of them */
1104
for (i = 0; i < rd->typeCount; i++) {
1107
if (t->fileOffset == -1) continue; /* Not really there */
1109
if (t->fileOffset != 0 && fseek(f, t->fileOffset, SEEK_SET) != -1) {
1111
if (ParseResourceSection(f, rd, t, (char *) NULL, 1)) {
1113
sprintf(buf, "Trouble parsing resource type %s", t->type);
1114
PSResFileWarningHandler(rd->directory, buf);
1118
if (SkipResourceSection(f, rd, t, 1)) {
1120
sprintf(buf, "Trouble parsing resource type %s", t->type);
1121
PSResFileWarningHandler(rd->directory, buf);
1129
if (VerifyName(f, t->type) == 0) {
1130
t->fileOffset = pos;
1131
if (ParseResourceSection(f, rd, t, (char *) NULL, 0)) {
1133
sprintf(buf, "Trouble parsing resource type %s", t->type);
1134
PSResFileWarningHandler(rd->directory, buf);
1138
/* No resources of this type; try the next type */
1140
if (fseek(f, pos, SEEK_SET)) {
1141
PSResFileWarningHandler(rd->directory,
1142
"File changed during execution");
1150
static int ReadType(f, rd, type)
1152
ResourceDirectory rd;
1159
/* We're at the start of the resource section; read the sections that
1160
are in the cached type list or are the passed in type */
1162
for (i = 0; i < rd->typeCount; i++) {
1165
if (t->fileOffset == -1) continue; /* Not really there */
1166
if (t->fileOffset != 0 && fseek(f, t->fileOffset, SEEK_SET) != -1) {
1168
(strcmp(t->type, type) == 0 || InSavedList(t->type))) {
1169
if (ParseResourceSection(f, rd, t, (char *) NULL, 1)) {
1171
sprintf(buf, "Trouble parsing resource type %s", t->type);
1172
PSResFileWarningHandler(rd->directory, buf);
1175
} else if (SkipResourceSection(f, rd, t, 1)) {
1177
sprintf(buf, "Trouble parsing resource type %s", t->type);
1178
PSResFileWarningHandler(rd->directory, buf);
1185
if (VerifyName(f, t->type) == 0) {
1186
t->fileOffset = pos;
1187
if (strcmp(t->type, type) == 0 || InSavedList(t->type)) {
1188
if (ParseResourceSection(f, rd, t, (char *) NULL, 0)){
1190
sprintf(buf, "Trouble parsing resource type %s", t->type);
1191
PSResFileWarningHandler(rd->directory, buf);
1194
} else if (SkipResourceSection(f, rd, t, 0)) {
1196
sprintf(buf, "Trouble parsing resource type %s", t->type);
1197
PSResFileWarningHandler(rd->directory, buf);
1201
/* No resources of this type; try the next type */
1203
if (fseek(f, pos, SEEK_SET) == -1) {
1204
PSResFileWarningHandler(rd->directory,
1205
"File changed during execution");
1213
static int ReadName(f, rd, data)
1215
ResourceDirectory rd;
1218
TypeName *tn = (TypeName *) data;
1223
/* We're at the start of the resource section; read the name in the
1224
section for the passed in type */
1226
for (i = 0; i < rd->typeCount; i++) {
1229
if (t->fileOffset == -1) continue; /* Not really there */
1230
if (t->fileOffset != 0 && fseek(f, t->fileOffset, SEEK_SET)) {
1231
if (strcmp(t->type, tn->type) == 0) {
1232
if (ParseResourceSection(f, rd, t, tn->name, 1)) {
1234
sprintf(buf, "Trouble parsing resource type %s", t->type);
1235
PSResFileWarningHandler(rd->directory, buf);
1238
} else if (SkipResourceSection(f, rd, t, 1)) {
1240
sprintf(buf, "Trouble parsing resource type %s", t->type);
1241
PSResFileWarningHandler(rd->directory, buf);
1248
if (VerifyName(f, t->type) == 0) {
1249
t->fileOffset = pos;
1250
if (fseek(f, pos, SEEK_SET) == -1) {
1251
PSResFileWarningHandler(rd->directory,
1252
"File changed during execution");
1255
if (strcmp(t->type, tn->type) == 0) {
1256
if (ParseResourceSection(f, rd, t, tn->name, 0)) {
1258
sprintf(buf, "Trouble parsing resource type %s", t->type);
1259
PSResFileWarningHandler(rd->directory, buf);
1262
} else if (SkipResourceSection(f, rd, t, 0)) {
1264
sprintf(buf, "Trouble parsing resource type %s", t->type);
1265
PSResFileWarningHandler(rd->directory, buf);
1269
/* No resources of this type; try the next type */
1271
if (fseek(f, pos, SEEK_SET) == -1) {
1272
PSResFileWarningHandler(rd->directory,
1273
"File changed during execution");
1281
static void ReadHeadersAndData(resourceType, resourceName)
1287
switch (currentPolicy) {
1288
case PSSaveEverything:
1290
ReadFilesInPath(GetPath(), ReadEverything, (char *) NULL);
1294
ReadFilesInPath(GetPath(), ReadType, resourceType);
1296
case PSSaveReturnValues:
1297
t.type = resourceType;
1298
t.name = resourceName;
1300
ReadFilesInPath(GetPath(), ReadName, (char *) &t);
1305
static void UpdateData(resourceType, resourceName)
1309
ResourceDirectory rd;
1315
/* Make two passes; the first figures out if we're going to have to read
1316
the file to service this request. If we are, open the file and read
1317
in sections in the saved list (from SetPSResourcePolicy). If not
1318
just saving return values, make sure we read in everything
1321
for (rd = resDir; rd != NULL; rd = rd->next) {
1323
for (i = 0; i < rd->typeCount; i++) {
1325
if (rt->filled) continue;
1326
if (strcmp(rt->type, resourceType) != 0) continue;
1328
if (resourceName != NULL &&
1329
LookupResourceInList(rt, resourceName)) continue;
1331
f = fopen(rd->directory, "r");
1334
if (f == NULL) continue;
1336
/* Nuts, have to read the file */
1338
if (fseek(f, rd->endOfHeader, SEEK_SET) != -1) {
1339
switch (currentPolicy) {
1340
case PSSaveEverything:
1341
(void) ReadEverything(f, rd, (char *) NULL);
1344
(void) ReadType(f, rd, resourceType);
1346
case PSSaveReturnValues:
1347
tn.type = resourceType;
1348
tn.name = resourceName;
1349
(void) ReadName(f, rd, (char *) &tn);
1352
} else (*PSResFileWarningHandler)(rd->directory,
1353
"File changed during execution");
1358
static int FindData(resourceType, resourceName,
1359
resourceNamesReturn, resourceFilesReturn)
1362
char ***resourceNamesReturn;
1363
char ***resourceFilesReturn;
1365
ResourceDirectory rd;
1369
char **names, **files;
1371
/* Make two passes; first count, then set and return */
1373
for (rd = resDir; rd != NULL; rd = rd->next) {
1374
for (i = 0; i < rd->typeCount; i++) {
1376
if (strcmp(rt->type, resourceType) != 0) continue;
1377
if (resourceName == NULL) nameCount += rt->nameCount;
1379
for (j = 0; j < rt->nameCount; j++) {
1380
if (strcmp(rt->names[j].name, resourceName) == 0) {
1388
if (nameCount == 0) return 0;
1390
names = (char **) MALLOC((int) (nameCount * sizeof(char *)));
1391
files = (char **) MALLOC((int) (nameCount * sizeof(char *)));
1394
for (rd = resDir; rd != NULL; rd = rd->next) {
1395
for (i = 0; i < rd->typeCount; i++) {
1397
if (strcmp(rt->type, resourceType) != 0) continue;
1398
for (j = 0; j < rt->nameCount; j++) {
1399
if (resourceName == NULL ||
1400
strcmp(rt->names[j].name, resourceName) == 0) {
1401
names[k] = rt->names[j].name;
1402
files[k++] = rt->names[j].file;
1408
*resourceNamesReturn = names;
1409
*resourceFilesReturn = files;
1413
extern int ListPSResourceFiles(psResourcePathOverride, defaultPath,
1414
resourceType, resourceName,
1415
resourceNamesReturn, resourceFilesReturn)
1416
char *psResourcePathOverride;
1420
char ***resourceNamesReturn;
1421
char ***resourceFilesReturn;
1423
if (SetUpSavedPaths(psResourcePathOverride, defaultPath)) {
1424
ReadHeadersAndData(resourceType, resourceName);
1425
} else UpdateData(resourceType, resourceName);
1426
return FindData(resourceType, resourceName,
1427
resourceNamesReturn, resourceFilesReturn);
1430
int ListPSResourceTypes(pathOverride, defaultPath, typesReturn)
1433
char ***typesReturn;
1437
int typeCount = 0, i, j, typeBufSize = 0;
1438
ResourceDirectory d;
1439
register char **types = NULL;
1444
if (SetUpSavedPaths(pathOverride, defaultPath)) {
1445
if (currentPolicy != PSSaveEverything) {
1447
ReadFilesInPath(GetPath(), (ReadContentsFunction) NULL,
1449
} else lastModifiedTime =
1450
ReadFilesInPath(GetPath(), ReadEverything, (char *) NULL);
1453
for (d = resDir; d != NULL; d = d->next) {
1454
for (i = 0; i < d->typeCount; i++) {
1455
for (sig = 0, ch = d->types[i].type; *ch != '\0'; sig += *ch++) {}
1456
for (j = 0; j < typeCount; j++) {
1457
if (sig == sigs[j] &&
1458
strcmp(types[j], d->types[i].type) == 0) break;
1460
if (j >= typeCount) { /* Have to add */
1461
if (typeCount >= typeBufSize) {
1462
if (typeCount == 0) typeBufSize = START;
1463
else typeBufSize += GROW;
1464
types = (char **) REALLOC((char *) types,
1465
typeBufSize * sizeof(char *));
1466
sigs = (int *) REALLOC((char *) sigs,
1467
typeBufSize * sizeof(int));
1469
types[typeCount] = d->types[i].type;
1470
sigs[typeCount++] = sig;
1475
FREE((char *) sigs);
1476
*typesReturn = types;
1482
/* Assumes being correctly positioned in the file */
1484
static int EnumerateResourceSection(f, dir, type, s, checkName)
1486
ResourceDirectory dir;
1488
EnumeratorStruct *s;
1495
char *names = namebuf;
1496
int buflen = GROW, namelen = 0;
1505
if (checkName && VerifyName(f, type->type) != 0) return 1;
1507
insertPrefix = CheckInsertPrefix(type->type);
1509
prefixLen = strlen(dir->filePrefix);
1517
linein = ReadFullLine(f);
1518
if (linein == NULL) {
1519
if (names != namebuf) FREE((char *) names);
1524
if (strcmp(linein, ".") == 0) {
1525
if (names != namebuf) FREE((char *) names);
1531
(void) DequoteAndBreak(linein, &sep, '=', dontDequote, &doubleEquals);
1533
/* If no separator, a bogus line */
1534
if (sep == NULL) continue;
1536
/* Next line is UNIX specific! */
1537
addingPrefix = *(sep+1) != '/' && insertPrefix && !doubleEquals;
1539
len = strlen(linein) + (addingPrefix ? 0 : prefixLen) + 1;
1541
if (names != namebuf) FREE((char *) names);
1542
names = (char *) MALLOC(len);
1546
len = strlen(linein);
1547
(void) strncpy(names, linein, len+1);
1550
file = &names[namelen];
1553
(void) strncpy(&names[namelen], dir->filePrefix, prefixLen);
1554
namelen += prefixLen;
1557
len = strlen(sep+1);
1558
(void) strncpy(&names[namelen], sep+1, len+1);
1560
if (s->name == NULL || strcmp(names, s->name) == 0) {
1561
s->done = (*s->func) (s->type, names, file, s->private);
1563
if (names != namebuf) FREE((char *) names);
1572
static int Enumerate(f, rd, data)
1574
ResourceDirectory rd;
1577
EnumeratorStruct *s = (EnumeratorStruct *) data;
1582
if (s->done) return 0;
1584
for (i = 0; i < rd->typeCount; i++) {
1587
if (t->fileOffset == -1) continue; /* Not really there */
1588
if (t->fileOffset != 0 && fseek(f, t->fileOffset, SEEK_SET) != -1) {
1589
if (strcmp(t->type, s->type) == 0) {
1590
if (EnumerateResourceSection(f, rd, t, s, 1)) {
1592
sprintf(buf, "Trouble parsing resource type %s", t->type);
1593
PSResFileWarningHandler(rd->directory, buf);
1596
if (s->done) return 0;;
1597
} else if (SkipResourceSection(f, rd, t, 1)) {
1599
sprintf(buf, "Trouble parsing resource type %s", t->type);
1600
PSResFileWarningHandler(rd->directory, buf);
1607
if (VerifyName(f, t->type) == 0) {
1608
t->fileOffset = pos;
1609
if (strcmp(t->type, s->type) == 0) {
1610
if (EnumerateResourceSection(f, rd, t, s, 0)) return 1;
1611
if (s->done) return 0;
1612
} else if (SkipResourceSection(f, rd, t, 0)) return 1;
1614
/* No resources of this type; try the next type */
1616
if (fseek(f, pos, SEEK_SET) == -1) return 1;
1622
void EnumeratePSResourceFiles(pathOverride, defaultPath, resourceType,
1623
resourceName, enumerator, private)
1628
PSResourceEnumerator enumerator;
1631
ResourceDirectory d;
1635
s.func = enumerator;
1636
s.type = resourceType;
1637
s.name = resourceName;
1638
s.private = private;
1641
if (SetUpSavedPaths(pathOverride, defaultPath)) {
1643
ReadFilesInPath(GetPath(), Enumerate, (char *) &s);
1647
for (d = resDir; d != NULL && !s.done; d = d->next) {
1648
f = fopen(d->directory, "r");
1649
if (f == NULL) continue;
1650
if (fseek(f, d->endOfHeader, SEEK_SET) != -1) {
1651
(void) Enumerate(f, d, (char *) &s);
1657
int CheckPSResourceTime(pathOverride, defaultPath)
1661
if (CheckSavedPaths(pathOverride, defaultPath)) return 1;
1662
return MaxTimeInPath(GetPath()) > lastModifiedTime;