824N/A/*
824N/A * makepsres.c
824N/A *
824N/A * (c) Copyright 1991, 1994 Adobe Systems Incorporated.
824N/A * All rights reserved.
824N/A *
824N/A * Permission to use, copy, modify, distribute, and sublicense this software
824N/A * and its documentation for any purpose and without fee is hereby granted,
824N/A * provided that the above copyright notices appear in all copies and that
824N/A * both those copyright notices and this permission notice appear in
824N/A * supporting documentation and that the name of Adobe Systems Incorporated
824N/A * not be used in advertising or publicity pertaining to distribution of the
824N/A * software without specific, written prior permission. No trademark license
824N/A * to use the Adobe trademarks is hereby granted. If the Adobe trademark
824N/A * "Display PostScript"(tm) is used to describe this software, its
824N/A * functionality or for any other purpose, such use shall be limited to a
824N/A * statement that this software works in conjunction with the Display
824N/A * PostScript system. Proper trademark attribution to reflect Adobe's
824N/A * ownership of the trademark shall be given whenever any such reference to
824N/A * the Display PostScript system is made.
824N/A *
824N/A * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
824N/A * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
824N/A * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
824N/A * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
824N/A * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
824N/A * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
824N/A * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
824N/A * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
824N/A * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
824N/A * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
824N/A *
824N/A * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
824N/A * Incorporated which may be registered in certain jurisdictions
824N/A *
824N/A * Author: Adobe Systems Incorporated
824N/A */
824N/A/* $XFree86: xc/programs/makepsres/makepsres.c,v 1.8tsi Exp $ */
824N/A
824N/A#include <stdio.h>
824N/A#include <stdlib.h>
824N/A#include <errno.h>
824N/A#include <ctype.h>
824N/A
824N/A#ifdef XENVIRONMENT
824N/A#include <X11/Xos.h>
824N/A#else
824N/A#include <string.h>
824N/A#include <sys/types.h>
824N/A#endif
824N/A
824N/A#include <sys/stat.h>
824N/A
824N/A#include <dirent.h>
824N/A
824N/A#ifndef S_ISDIR
824N/A#ifdef S_IFDIR
824N/A#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
824N/A#else
824N/A#define S_ISDIR(mode) (((mode) & _S_IFMT) == _S_IFDIR)
824N/A#endif /* S_IFDIR */
824N/A#endif /* S_ISDIR */
824N/A
824N/A#define true 1
824N/A#define false 0
824N/A
824N/A/* The max line length is really 256, but why make things that are hard
824N/A to read??? */
824N/A#define MAXLINELEN 79
824N/A
824N/A#ifndef DEBUG
824N/A#define DEBUG false
824N/A#endif
824N/A
824N/A#define QUOTE 042
824N/A
824N/A#define HASHSIZE 2048
824N/A
824N/A/* Command line information */
824N/A
824N/Achar **directories;
824N/Aint *directoryLen;
824N/Aint directoryCount;
824N/Aint recursive;
824N/Aint discard;
824N/Aint keep;
824N/Achar *outputFilename;
824N/Achar **inputFiles;
824N/Aint inputCount;
824N/Aint makeExclusive;
824N/Aint interactive;
824N/Aint strict;
824N/Aint noPrefix;
824N/Aint issueWarnings;
824N/Aint noBackup;
824N/Aint noSuffix;
824N/A
824N/Atypedef struct _t_Resource {
824N/A char *name;
824N/A char *file;
824N/A int noPrefix;
824N/A struct _t_Resource *next;
824N/A} Resource;
824N/A
824N/Atypedef struct _t_Duplicate {
824N/A char *name;
824N/A char *file1;
824N/A char *file2;
824N/A struct _t_Duplicate *next;
824N/A} Duplicate;
824N/A
824N/Atypedef struct _t_Category {
824N/A char *name;
824N/A Resource *list;
824N/A Resource **hash; /* Currently used only for mkpsresPrivate */
824N/A Duplicate *duplicates;
824N/A struct _t_Category *next;
824N/A} Category;
824N/A
824N/Achar *program;
824N/A
824N/A#if 0
824N/Aextern char *malloc(), *realloc();
824N/Aextern char *sys_errlist[];
824N/Aextern int errno;
824N/A#endif
824N/A
824N/A#define BUFFER_SIZE 1024
824N/Astatic char lineBuffer[BUFFER_SIZE];
824N/A
824N/ACategory *categories;
824N/A
824N/Astatic char *ckmalloc(int size, char *whynot)
824N/A{
824N/A char *result;
824N/A
824N/A if (size == 0) size = 1;
824N/A result = malloc(size);
824N/A if (result == NULL) {
824N/A fprintf(stderr, "%s: %s\n", program, whynot);
824N/A exit(1);
824N/A }
824N/A return result;
824N/A}
824N/A
824N/Astatic char *ckrealloc(char *ptr, int size, char *whynot)
824N/A{
824N/A char *result;
824N/A
824N/A if (size == 0) size = 1;
824N/A result = realloc(ptr, size);
824N/A if (result == NULL) {
824N/A fprintf(stderr, "%sf : %s\n", program, whynot);
824N/A exit(1);
824N/A }
824N/A return result;
824N/A}
824N/A
824N/Astatic char *ckcalloc(int count, int size, char *whynot)
824N/A{
824N/A char *result;
824N/A
824N/A if (size == 0) size = 1;
824N/A if (count == 0) count = 1;
824N/A result = (char *) calloc(count, size);
824N/A if (result == NULL) {
824N/A fprintf(stderr, "%s: %s\n", program, whynot);
824N/A exit(1);
824N/A }
824N/A return result;
824N/A}
824N/A
824N/A
824N/Astatic Category *AddCategory (name)
824N/A char *name;
824N/A{
824N/A Category *newCategory = (Category *) ckcalloc (1, sizeof (Category),
824N/A "Failed to allocate Category record.");
824N/A
824N/A newCategory->name = (char *) ckmalloc (strlen (name) + 1,
824N/A "Failed to allocate Category name.");
824N/A
824N/A strcpy (newCategory->name, name);
824N/A
824N/A if (categories == NULL) {
824N/A categories = newCategory;
824N/A } else {
824N/A /* Insert into alphabetical position */
824N/A Category *current,
824N/A *previous;
824N/A
824N/A current = previous = categories;
824N/A
824N/A while (current != NULL) {
824N/A if (strcmp (current->name, name) > 0) {
824N/A break;
824N/A } else {
824N/A previous = current;
824N/A current = current->next;
824N/A }
824N/A }
824N/A
824N/A if (current == NULL) {
824N/A newCategory->next = NULL;
824N/A previous->next = newCategory;
824N/A } else {
824N/A newCategory->next = current;
824N/A
824N/A if (current == categories) {
824N/A categories = newCategory;
824N/A } else {
824N/A previous->next = newCategory;
824N/A }
824N/A }
824N/A }
824N/A
824N/A return (newCategory);
824N/A}
824N/A
824N/A
824N/Astatic Category *FindCategory (name)
824N/A char *name;
824N/A{
824N/A Category *category = categories;
824N/A
824N/A while (category != NULL) {
824N/A if (strcmp (category->name, name) == 0)
824N/A break;
824N/A else
824N/A category = category->next;
824N/A }
824N/A
824N/A if (category == NULL)
824N/A category = AddCategory (name);
824N/A
824N/A return (category);
824N/A}
824N/A
824N/A
824N/Aint Hash(string)
824N/A char *string;
824N/A{
824N/A int hash = 0;
824N/A unsigned char *ch = (unsigned char *) string;
824N/A
824N/A while (1) {
824N/A if (*ch == '\0') return hash % HASHSIZE;
824N/A if (*(ch+1) == '\0') {
824N/A hash += *ch;
824N/A return hash % HASHSIZE;
824N/A }
824N/A hash += *ch++;
824N/A hash += (*ch++ << 8);
824N/A }
824N/A}
824N/A
824N/Astatic void AddHashedResource(resource, category)
824N/A Resource *resource;
824N/A Category *category;
824N/A{
824N/A Resource *current, *previous;
824N/A int comparison, hash;
824N/A
824N/A if (category->hash == NULL) {
824N/A category->hash = (Resource **) ckcalloc(HASHSIZE, sizeof(Resource *),
824N/A "Failed to allocate hash table.");
824N/A }
824N/A
824N/A hash = Hash(resource->file);
824N/A current = previous = category->hash[hash];
824N/A
824N/A while (current != NULL) {
824N/A comparison = strcmp (current->file, resource->file);
824N/A if (comparison > 0) break;
824N/A
824N/A if (comparison == 0 &&
824N/A strcmp(current->name, resource->name) != 0) break;
824N/A
824N/A previous = current;
824N/A current = current->next;
824N/A }
824N/A
824N/A if (category->hash[hash] == NULL) {
824N/A category->hash[hash] = resource;
824N/A resource->next = NULL;
824N/A
824N/A } else if (current == NULL) {
824N/A resource->next = NULL;
824N/A previous->next = resource;
824N/A
824N/A } else {
824N/A resource->next = current;
824N/A
824N/A if (current == category->hash[hash]) {
824N/A category->hash[hash] = resource;
824N/A } else {
824N/A previous->next = resource;
824N/A }
824N/A }
824N/A}
824N/A
824N/Avoid EnterDuplicateWarning(category, res1, res2)
824N/A Category *category;
824N/A Resource *res1, *res2;
824N/A{
824N/A Duplicate *dup, *previous, *current;
824N/A
824N/A if (!issueWarnings) return;
824N/A
824N/A dup = (Duplicate *) ckcalloc(1, sizeof(Duplicate),
824N/A "Failed to allocate Duplicate record.");
824N/A
824N/A dup->name = res1->name;
824N/A dup->file1 = res1->file;
824N/A dup->file2 = res2->file;
824N/A
824N/A current = previous = category->duplicates;
824N/A
824N/A while (current != NULL) {
824N/A if (strcmp (current->name, res1->name) >= 0) break;
824N/A previous = current;
824N/A current = current->next;
824N/A }
824N/A
824N/A if (category->duplicates == NULL) category->duplicates = dup;
824N/A else if (current == NULL) {
824N/A dup->next = NULL;
824N/A previous->next = dup;
824N/A } else {
824N/A dup->next = current;
824N/A
824N/A if (current == category->duplicates) category->duplicates = dup;
824N/A else previous->next = dup;
824N/A }
824N/A}
824N/A
824N/Astatic void AddResource (categoryName, resourceName, fileName, noPrefix)
824N/A char *resourceName;
824N/A char *categoryName;
824N/A char *fileName;
824N/A int noPrefix;
824N/A{
824N/A Category *category = FindCategory (categoryName);
824N/A Resource *resource,
824N/A *current,
824N/A *previous;
824N/A int comparison;
824N/A
824N/A resource = (Resource *) ckcalloc (1, sizeof (Resource),
824N/A "Failed to allocate Resource record.");
824N/A
824N/A resource->name = ckmalloc (strlen (resourceName) + 1,
824N/A "Failed to allocate Resource name.");
824N/A
824N/A strcpy (resource->name, resourceName);
824N/A
824N/A if (fileName[0] == '.' && fileName[1] == '/') fileName+=2;
824N/A
824N/A resource->file = ckmalloc (strlen (fileName) + 1,
824N/A "Failed to allocate Resource filename.");
824N/A
824N/A strcpy (resource->file, fileName);
824N/A
824N/A resource->noPrefix = noPrefix;
824N/A
824N/A if (strcmp(categoryName, "mkpsresPrivate") == 0) {
824N/A AddHashedResource(resource, category);
824N/A return;
824N/A }
824N/A
824N/A current = previous = category->list;
824N/A
824N/A while (current != NULL) {
824N/A comparison = strcmp (current->name, resourceName);
824N/A if (comparison > 0) break;
824N/A else if (comparison == 0) {
824N/A comparison = strcmp (current->file, fileName);
824N/A if (comparison > 0) {
824N/A if (strcmp(categoryName, "FontBDFSizes") != 0 &&
824N/A strcmp(categoryName, "FontFamily") != 0 &&
824N/A strcmp(categoryName, "mkpsresPrivate") != 0) {
824N/A EnterDuplicateWarning(category, current, resource);
824N/A }
824N/A break;
824N/A } else if (comparison == 0) { /* Same file */
824N/A free (resource->name);
824N/A free (resource->file);
824N/A free (resource);
824N/A return;
824N/A }
824N/A }
824N/A previous = current;
824N/A current = current->next;
824N/A }
824N/A
824N/A if (category->list == NULL) {
824N/A category->list = resource;
824N/A } else if (current == NULL) {
824N/A resource->next = NULL;
824N/A previous->next = resource;
824N/A } else {
824N/A resource->next = current;
824N/A
824N/A if (current == category->list) {
824N/A category->list = resource;
824N/A } else {
824N/A previous->next = resource;
824N/A }
824N/A }
824N/A}
824N/A
824N/Aint FindResource(categoryName, resourceName)
824N/A char *categoryName;
824N/A char *resourceName;
824N/A{
824N/A Category *category = FindCategory (categoryName);
824N/A Resource *resource;
824N/A int i;
824N/A
824N/A for (resource = category->list;
824N/A resource != NULL && strcmp(resource->name, resourceName) != 0;
824N/A resource = resource->next) {}
824N/A
824N/A if (resource != NULL) return true;
824N/A
824N/A if (category->hash == NULL) return false;
824N/A
824N/A for (i = 0; i < HASHSIZE; i++) {
824N/A for (resource = category->hash[i];
824N/A resource != NULL && strcmp(resource->name, resourceName) != 0;
824N/A resource = resource->next) {}
824N/A if (resource != NULL) return true;
824N/A }
824N/A
824N/A return false;
824N/A}
824N/A
824N/A
824N/Atypedef struct _t_UPRResource {
824N/A char *name;
824N/A char *file;
824N/A char *category;
824N/A int found;
824N/A int noPrefix;
824N/A struct _t_UPRResource *next;
824N/A} UPRResource;
824N/A
824N/AUPRResource *UPRresources[HASHSIZE];
824N/A
824N/A#if DEBUG
824N/Aint bucketCount[HASHSIZE];
824N/Aint totalHashed = 0;
824N/A#endif
824N/A
824N/Astatic void AddUPRResource (categoryName, resourceName, fileName, prefix,
824N/A noPrefix)
824N/A char *resourceName;
824N/A char *categoryName;
824N/A char *fileName;
824N/A char *prefix;
824N/A int noPrefix;
824N/A{
824N/A UPRResource *resource, *current, *previous;
824N/A int comparison, hash;
824N/A
824N/A if (noPrefix || prefix == NULL) {
824N/A prefix = "";
824N/A if (fileName[0] == '.' && fileName[1] == '/') fileName+=2;
824N/A } else {
824N/A prefix++; /* Skip over leading / */
824N/A if (prefix[0] == '.' && prefix[1] == '/') prefix += 2;
824N/A }
824N/A
824N/A resource = (UPRResource *) ckcalloc (1, sizeof (UPRResource),
824N/A "Failed to allocate Resource record.");
824N/A
824N/A resource->name = ckmalloc (strlen (resourceName) + 1,
824N/A "Failed to allocate Resource name.");
824N/A
824N/A strcpy (resource->name, resourceName);
824N/A
824N/A resource->file = ckmalloc (strlen (fileName) + strlen(prefix) + 2,
824N/A "Failed to allocate Resource filename.");
824N/A
824N/A if (prefix != NULL && prefix[0] != '\0') {
824N/A strcpy (resource->file, prefix);
824N/A strcat (resource->file, "/");
824N/A strcat (resource->file, fileName);
824N/A } else strcpy (resource->file, fileName);
824N/A
824N/A resource->category = ckmalloc (strlen (categoryName) + 1,
824N/A "Failed to allocate Resource name.");
824N/A
824N/A strcpy(resource->category, categoryName);
824N/A
824N/A resource->noPrefix = noPrefix;
824N/A resource->found = false;
824N/A
824N/A hash = Hash(resource->file);
824N/A current = previous = UPRresources[hash];
824N/A
824N/A while (current != NULL) {
824N/A comparison = strcmp (current->file, resource->file);
824N/A if (comparison > 0) break;
824N/A
824N/A if (comparison == 0) {
824N/A if (noPrefix) break;
824N/A
824N/A if (strcmp(current->name, resource->name) != 0 ||
824N/A strcmp(current->category, resource->category) != 0) { /* Same */
824N/A if (strcmp(current->category, "mkpsresPrivate") == 0 &&
824N/A strcmp(current->name, "NONRESOURCE") == 0) {
824N/A
824N/A /* Replace "NONRESOURCE" entry with resource one */
824N/A free(current->name);
824N/A current->name = resource->name;
824N/A free(current->category);
824N/A current->category = resource->category;
824N/A free(resource->file);
824N/A free (resource);
824N/A return;
824N/A }
824N/A fprintf(stderr,
824N/A "%s: Warning: file %s identified as different resources\n",
824N/A program, resource->file);
824N/A fprintf(stderr, " Using %s\n", current->category);
824N/A }
824N/A free (resource->name);
824N/A free (resource->file);
824N/A free (resource->category);
824N/A free (resource);
824N/A return;
824N/A }
824N/A previous = current;
824N/A current = current->next;
824N/A }
824N/A
824N/A if (UPRresources[hash] == NULL) {
824N/A UPRresources[hash] = resource;
824N/A resource->next = NULL;
824N/A
824N/A } else if (current == NULL) {
824N/A resource->next = NULL;
824N/A previous->next = resource;
824N/A } else {
824N/A resource->next = current;
824N/A
824N/A if (current == UPRresources[hash]) {
824N/A UPRresources[hash] = resource;
824N/A } else {
824N/A previous->next = resource;
824N/A }
824N/A }
824N/A#if DEBUG
824N/A totalHashed++;
824N/A bucketCount[hash]++;
824N/A#endif
824N/A}
824N/A
824N/A
824N/Avoid AddUPRResourceBDF(font, sizes)
824N/A char *font;
824N/A char *sizes;
824N/A{
824N/A char *ch = sizes;
824N/A char *buf;
824N/A
824N/A while (*ch != '\0') {
824N/A while (*ch != '\0' && *ch != ',') ch++;
824N/A if (*ch == ',') {
824N/A *ch = '\0';
824N/A if (*sizes != '\0') {
824N/A /* Stick in the font size to spread out the hash table */
824N/A
824N/A buf = ckmalloc(strlen(font) + strlen(sizes) + 2,
824N/A "Failed to allocate BDF string");
824N/A sprintf(buf, "%s,%s", font, sizes);
824N/A AddUPRResource("FontBDFSizes", font, buf, NULL, true);
824N/A free(buf);
824N/A }
824N/A sizes = ++ch;
824N/A }
824N/A }
824N/A}
824N/A
824N/Avoid AddUPRResourceFontFamily(family, faces)
824N/A char *family;
824N/A char *faces;
824N/A{
824N/A char *ch = faces, *chunk = faces;
824N/A char old;
824N/A
824N/A while (true) {
824N/A while (true) {
824N/A while (*ch != '\0' && *ch != ',') ch++;
824N/A if (*ch == '\0') return;
824N/A if (ch > faces && *(ch-1) == '\\') ch++;
824N/A else break;
824N/A }
824N/A /* Found the first , look for the second */
824N/A ch++;
824N/A while (true) {
824N/A while (*ch != '\0' && *ch != ',') ch++;
824N/A if (*ch == '\0') break;
824N/A if (*(ch-1) == '\\') ch++;
824N/A else break;
824N/A }
824N/A
824N/A old = *ch;
824N/A *ch = '\0';
824N/A AddUPRResource("FontFamily", family, chunk, NULL, true);
824N/A if (old == '\0') return;
824N/A chunk = ++ch;
824N/A }
824N/A}
824N/A
824N/Astatic int SkipWhiteSpace(file)
824N/A FILE *file;
824N/A{
824N/A int c;
824N/A
824N/A while (1) {
824N/A c = fgetc(file);
824N/A if (c == ' ' || c == '\t') continue;
824N/A if (c == EOF) return false;
824N/A ungetc(c, file);
824N/A return true;
824N/A }
824N/A}
824N/A
824N/A
824N/Astatic int ReadItem(file, buf, size)
824N/A FILE *file;
824N/A char *buf;
824N/A int size;
824N/A{
824N/A int c;
824N/A char closechar, openchar;
824N/A int count = 0, nesting = 0;;
824N/A
824N/A openchar = '\0';
824N/A
824N/A c = fgetc(file);
824N/A if (c == EOF) return false;
824N/A if (c == '(') {closechar = ')'; openchar = c;}
824N/A else if (c == '[') {closechar = ']'; openchar = c;}
824N/A else if (c == QUOTE) closechar = QUOTE;
824N/A else if (c == '/') closechar = '\0';
824N/A else {
824N/A closechar = '\0';
824N/A ungetc(c, file);
824N/A }
824N/A
824N/A while (count < size) {
824N/A c = fgetc(file);
824N/A if (openchar != '\0' && c == openchar) nesting++;
824N/A if (c == EOF) break;
824N/A if (c == closechar) {
824N/A if (nesting == 0) break;
824N/A else nesting--;
824N/A }
824N/A if (closechar == '\0' && strchr(" \t\n\r", c) != NULL) break;
824N/A buf[count++] = c;
824N/A }
824N/A
824N/A buf[count] = '\0';
824N/A return true;
824N/A}
824N/A
824N/Astatic char *FindKeyValue (file, key)
824N/A FILE *file;
824N/A char *key;
824N/A{
824N/A char lineKey[64];
824N/A char *result = NULL;
824N/A
824N/A while (true) {
824N/A if (fgets (lineBuffer, BUFFER_SIZE, file) == NULL)
824N/A break;
824N/A
824N/A sscanf (lineBuffer, "%63[%a-zA-Z]", lineKey);
824N/A if (strcmp (key, lineKey) == 0) {
824N/A result = strchr (lineBuffer, ' ');
824N/A if (result != NULL) {
824N/A result++;
824N/A break;
824N/A }
824N/A }
824N/A }
824N/A
824N/A return (result);
824N/A}
824N/A
824N/Astatic void StripName (name)
824N/A char *name;
824N/A{
824N/A char closeCharacter = '\0';
824N/A char *pointer;
824N/A
824N/A if (name[0] == '/') strcpy(name, name+1);
824N/A
824N/A while (true) {
824N/A if (name[0] == '(') closeCharacter = ')';
824N/A else if (name[0] == QUOTE) closeCharacter = QUOTE;
824N/A else break;
824N/A
824N/A pointer = strrchr (name, closeCharacter);
824N/A
824N/A if (pointer != NULL) {
824N/A *pointer = '\0';
824N/A strcpy (name, name + 1);
824N/A } else break; /* No close character */
824N/A }
824N/A
824N/A pointer = strrchr (name, '\r');
824N/A
824N/A if (pointer != NULL) *pointer = '\0';
824N/A else {
824N/A pointer = strrchr (name, '\n');
824N/A if (pointer != NULL) *pointer = '\0';
824N/A }
824N/A}
824N/A
824N/A
824N/Astatic char *bugFamilies[] = {
824N/A "Berkeley", "CaslonFiveForty", "CaslonThree", "GaramondThree",
824N/A "Music", "TimesTen", NULL
824N/A };
824N/A
824N/Astatic char *fixedFamilies[] = {
824N/A "ITC Berkeley Oldstyle", "Caslon 540", "Caslon 3", "Garamond 3",
824N/A "Sonata", "Times 10", NULL
824N/A};
824N/A
824N/Astatic char *missingFoundries[] = {
824N/A "Berthold ", "ITC ", "Linotype ", NULL
824N/A};
824N/A
824N/Astatic int missingFoundryLen[] = {
824N/A 9, 4, 9, 0
824N/A};
824N/A
824N/Astatic void MungeFontNames(name, family, fullname, weight,
824N/A familyReturn, fullnameReturn, faceReturn)
824N/A char *name, *family, *fullname, *weight;
824N/A char *familyReturn, *fullnameReturn, *faceReturn;
824N/A{
824N/A register char *src, *dst, prev;
824N/A char buf[256];
824N/A int digits = 0;
824N/A int i, diff;
824N/A
824N/A /* Copy the fullname into buf, enforcing one space between words.
824N/A Eliminate leading digits and spaces, ignore asterisks, if the
824N/A full name ends with 5 digits strip them, and replace periods that
824N/A aren't followed by a space with a space. If leading digits are
824N/A followed by " pt " skip that too. */
824N/A
824N/A dst = buf;
824N/A prev = ' ';
824N/A src = fullname;
824N/A while (isdigit(*src)) src++;
824N/A while (*src == ' ' || *src == '\t') src++;
824N/A if (strncmp(src, "pt ", 3) == 0) src += 3;
824N/A else if (strncmp(src, "pt. ", 4) == 0) src += 4;
824N/A
824N/A while (*src != '\0') {
824N/A if (*src == '*') {
824N/A src++;
824N/A continue;
824N/A }
824N/A
824N/A if (*src == '.') {
824N/A if (*(src+1) != ' ') {
824N/A prev = *dst++ = ' ';
824N/A } else prev = *dst++ = '.';
824N/A src++;
824N/A continue;
824N/A }
824N/A
824N/A if (isdigit(*src)) digits++;
824N/A else digits = 0;
824N/A
824N/A if (isupper(*src)) {
824N/A if (prev != ' ' && (islower(*(src+1)) || islower(prev))) {
824N/A *dst++ = ' ';
824N/A prev = *dst++ = *src++;
824N/A } else prev = *dst++ = *src++;
824N/A
824N/A } else if (*src == ' ' || *src == '\t') {
824N/A if (prev == ' ') {
824N/A src++;
824N/A continue;
824N/A }
824N/A prev = *dst++ = ' ';
824N/A src++;
824N/A
824N/A } else prev = *dst++ = *src++;
824N/A }
824N/A
824N/A if (digits == 5) {
824N/A dst -= 5;
824N/A }
824N/A if (dst > buf && *(dst-1) == ' ') dst--;
824N/A
824N/A *dst = '\0';
824N/A
824N/A if (strcmp(name, "FetteFraktur-Dfr") == 0) strcat(buf, " Black Dfr");
824N/A else if (strcmp(name, "Linotext-Dfr") == 0) strcat(buf, " Dfr");
824N/A
824N/A if (strncmp(fullname, "pt ", 3) == 0) {
824N/A src = buf + 2;
824N/A while (*++src != '\0') *(src-3) = *src;
824N/A *(src-3) = '\0';
824N/A }
824N/A
824N/A strcpy(fullnameReturn, buf);
824N/A
824N/A /* From here on fullname should not be used */
824N/A
824N/A /* Done with the full name; now onto the family */
824N/A
824N/A for (i = 0; bugFamilies[i] != NULL; i++) {
824N/A diff = strcmp(family, bugFamilies[i]);
824N/A if (diff < 0) break;
824N/A if (diff == 0) {
824N/A strcpy(familyReturn, fixedFamilies[i]);
824N/A goto FAMILY_DONE;
824N/A }
824N/A }
824N/A
824N/A /* Copy the family into buf, enforcing one space between words */
824N/A
824N/A dst = buf;
824N/A prev = ' ';
824N/A src = family;
824N/A
824N/A while (*src != '\0') {
824N/A if (isupper(*src)) {
824N/A if (prev != ' ' && (islower(*(src+1)) || islower(prev))) {
824N/A *dst++ = ' ';
824N/A prev = *dst++ = *src++;
824N/A } else prev = *dst++ = *src++;
824N/A
824N/A } else if (*src == ' ' || *src == '\t') {
824N/A if (prev == ' ') {
824N/A src++;
824N/A continue;
824N/A }
824N/A prev = *dst++ = ' ';
824N/A src++;
824N/A
824N/A } else prev = *dst++ = *src++;
824N/A }
824N/A
824N/A if (dst > buf && *(dst-1) == ' ') dst--;
824N/A *dst = '\0';
824N/A
824N/A /* Compensate for fonts with foundries in the full name but not the
824N/A family name by adding to the family name */
824N/A
824N/A for (i = 0; missingFoundries[i] != NULL; i++) {
824N/A diff = strncmp(fullnameReturn, missingFoundries[i],
824N/A missingFoundryLen[i]);
824N/A if (diff > 0) continue;
824N/A if (diff == 0 && strncmp(buf, missingFoundries[i],
824N/A missingFoundryLen[i] != 0)) {
824N/A while (dst >= buf) {
824N/A *(dst+missingFoundryLen[i]) = *dst;
824N/A dst--;
824N/A }
824N/A strncpy(buf, missingFoundries[i], missingFoundryLen[i]);
824N/A }
824N/A break;
824N/A }
824N/A
824N/A /* From here on dst no longer points to the end of the buffer */
824N/A
824N/A if (strncmp(fullnameReturn, "Helvetica Rounded ", 18) == 0) {
824N/A strcat(buf, " Rounded");
824N/A }
824N/A
824N/A strcpy(familyReturn, buf);
824N/A
824N/AFAMILY_DONE:
824N/A
824N/A /* From here on family should not be used */
824N/A
824N/A /* Now to find the face in all this */
824N/A
824N/A src = fullnameReturn;
824N/A dst = familyReturn;
824N/A while (*dst == *src && *dst != '\0') {
824N/A src++;
824N/A dst++;
824N/A }
824N/A if (*src == ' ') src++;
824N/A
824N/A if (*src == '\0') {
824N/A if (*weight != '\0') {
824N/A /* Handle Multiple Master fonts */
824N/A if (strcmp(weight, "All") == 0) src = "Roman";
824N/A else {
824N/A if (islower(weight[0])) weight[0] = toupper(weight[0]);
824N/A src = weight;
824N/A }
824N/A } else src = "Medium";
824N/A }
824N/A
824N/A strcpy(faceReturn, src);
824N/A}
824N/A
824N/A
824N/Avoid StripComments(buf)
824N/A char *buf;
824N/A{
824N/A register char *ch = buf;
824N/A
824N/A while (true) {
824N/A while (*ch != '%' && *ch != '\0') ch++;
824N/A if (*ch == '\0') break;
824N/A if (ch == buf || *(ch-1) != '\\') {
824N/A *ch = '\0';
824N/A break;
824N/A }
824N/A ch++;
824N/A }
824N/A
824N/A /* ch points to '\0' right now */
824N/A
824N/A if (ch == buf) return;
824N/A ch--;
824N/A
824N/A while (ch > buf && (*ch == ' ' || *ch == '\t' || *ch == '\n')) {
824N/A *ch = '\0';
824N/A ch--;
824N/A }
824N/A
824N/A if (ch == buf && (*ch == ' ' || *ch == '\t' || *ch == '\n')) *ch = '\0';
824N/A}
824N/A
824N/A/* Caller must free returned line */
824N/A
824N/Achar *GetWholeLine(file)
824N/A FILE *file;
824N/A{
824N/A char *line;
824N/A int len, oldlen;
824N/A
824N/A if (fgets (lineBuffer, BUFFER_SIZE, file) == NULL) return NULL;
824N/A
824N/A StripComments(lineBuffer);
824N/A
824N/A len = strlen(lineBuffer);
824N/A line = ckmalloc(len+1, "Failed to allocate input line.");
824N/A strcpy(line, lineBuffer);
824N/A
824N/A if (line[len-1] == '\\') { /* Continued... */
824N/A line[len-1] = '\0';
824N/A oldlen = len-1;
824N/A while (true) {
824N/A if (fgets(lineBuffer, BUFFER_SIZE, file) == NULL) {
824N/A return line;
824N/A }
824N/A
824N/A StripComments(lineBuffer);
824N/A if (lineBuffer[0] == '\0') return line;
824N/A
824N/A len = strlen(lineBuffer);
824N/A line = ckrealloc(line, oldlen+len+1,
824N/A "Failed to reallocate input line.");
824N/A strcat(line, lineBuffer);
824N/A
824N/A oldlen += len;
824N/A if (line[oldlen-1] != '\\') break;
824N/A line[oldlen-1] = '\0';
824N/A oldlen--;
824N/A }
824N/A }
824N/A return line;
824N/A}
824N/A
824N/Astatic void HandleUnopenableUPRFile(filename, err)
824N/A char *filename;
824N/A int err;
824N/A{
824N/A if (issueWarnings) {
824N/A fprintf (stderr, "%s: Could not open file %s (%s).\n",
824N/A program, filename, strerror(err));
824N/A }
824N/A
824N/A if (strict) exit(1);
824N/A}
824N/A
824N/A
824N/Avoid PreprocessResourceDirectory(fullname)
824N/A char *fullname;
824N/A{
824N/A char *category;
824N/A FILE *file;
824N/A char *line;
824N/A char *directoryPrefix = NULL;
824N/A int noPrefix;
824N/A
824N/A file = fopen (fullname, "r");
824N/A
824N/A if (file == NULL) {
824N/A HandleUnopenableUPRFile(fullname, errno);
824N/A return;
824N/A }
824N/A
824N/A /* Skip over list of categories */
824N/A
824N/A while (true) {
824N/A if (fgets (lineBuffer, BUFFER_SIZE, file) == NULL) return;
824N/A
824N/A if (lineBuffer[0] == '.') break;
824N/A }
824N/A
824N/A while (true) {
824N/A /* Process category */
824N/A
824N/A line = GetWholeLine(file);
824N/A if (line == NULL) {
824N/A if (directoryPrefix != NULL) free(directoryPrefix);
824N/A return;
824N/A }
824N/A
824N/A if (line[0] == '/') { /* Handle optional directory prefix */
824N/A directoryPrefix = line;
824N/A continue;
824N/A }
824N/A
824N/A category = line;
824N/A
824N/A while (true) {
824N/A char *resourceFile;
824N/A
824N/A line = GetWholeLine(file);
824N/A if (line == NULL) {
824N/A if (directoryPrefix != NULL) free(directoryPrefix);
824N/A free(category);
824N/A }
824N/A
824N/A if (line[0] == '.') {
824N/A free(category);
824N/A free(line);
824N/A break;
824N/A }
824N/A
824N/A resourceFile = line;
824N/A while (true) {
824N/A if ((resourceFile = strchr(resourceFile, '=')) != NULL) {
824N/A if (resourceFile != line && *(resourceFile-1) != '\\') {
824N/A *resourceFile++ = '\0';
824N/A noPrefix = (*resourceFile == '=');
824N/A if (noPrefix) resourceFile++;
824N/A if (strcmp(category, "FontBDFSizes") == 0) {
824N/A AddUPRResourceBDF(line, resourceFile);
824N/A } else if (strcmp(category, "FontFamily") == 0) {
824N/A AddUPRResourceFontFamily(line, resourceFile);
824N/A } else AddUPRResource (category, line,
824N/A resourceFile,
824N/A (noPrefix ? NULL :
824N/A directoryPrefix),
824N/A noPrefix);
824N/A break;
824N/A }
824N/A resourceFile++;
824N/A } else break; /* Bogus line */
824N/A }
824N/A free(line);
824N/A }
824N/A }
824N/A}
824N/A
824N/Astatic int SkipToCharacter (file, character)
824N/A FILE *file;
824N/A char character;
824N/A{
824N/A int c;
824N/A
824N/A while ((c = fgetc (file)) != EOF) {
824N/A if (c == character)
824N/A return (true);
824N/A }
824N/A
824N/A return (false);
824N/A}
824N/A
824N/Astatic int SkipToEitherCharacter (file, character1, character2, outchar)
824N/A FILE *file;
824N/A char character1, character2;
824N/A char *outchar;
824N/A{
824N/A register int c;
824N/A
824N/A while ((c = fgetc (file)) != EOF) {
824N/A if (c == character1 || c == character2) {
824N/A *outchar = c;
824N/A return (true);
824N/A }
824N/A }
824N/A
824N/A return (false);
824N/A}
824N/A
824N/A
824N/Astatic void ProcessFont (file, fileName)
824N/A FILE *file;
824N/A char *fileName;
824N/A{
824N/A char fontName[256], fontFamily[256], fontFullName[256], fontWeight[256];
824N/A char key[256], buf[513];
824N/A char familyReturn[256], fullnameReturn[256], faceReturn[256];
824N/A char blendDesignPositions[256], blendDesignMap[256], blendAxisTypes[256];
824N/A char out;
824N/A int found = 0;
824N/A
824N/A fontName[0] = fontFamily[0] = fontFullName[0] = fontWeight[0] = '\0';
824N/A blendDesignPositions[0] = blendDesignMap[0] = blendAxisTypes[0] = '\0';
824N/A
824N/A while (found != 0x7F && SkipToEitherCharacter (file, '/', 'e', &out)) {
824N/A /* If we encounter an eexec, skip the rest of the file */
824N/A if (out == 'e') {
824N/A if (fscanf (file, "%255s", key) != 1) continue;
824N/A if (strcmp(key, "exec") == 0) break;
824N/A continue;
824N/A }
824N/A
824N/A if (fscanf (file, "%255s", key) != 1) continue;
824N/A if (!SkipWhiteSpace(file)) break;
824N/A if (!ReadItem(file, buf, 256)) break;
824N/A
824N/A if ((found & 0x1) == 0 && strcmp(key, "FullName") == 0) {
824N/A strcpy(fontFullName, buf);
824N/A found |= 0x1;
824N/A continue;
824N/A }
824N/A if ((found & 0x2) == 0 && strcmp(key, "FamilyName") == 0) {
824N/A strcpy(fontFamily, buf);
824N/A found |= 0x2;
824N/A continue;
824N/A }
824N/A if ((found & 0x4) == 0 && strcmp(key, "Weight") == 0) {
824N/A strcpy(fontWeight, buf);
824N/A found |= 0x4;
824N/A continue;
824N/A }
824N/A if ((found & 0x8) == 0 && strcmp(key, "FontName") == 0) {
824N/A strcpy(fontName, buf);
824N/A found |= 0x8;
824N/A continue;
824N/A }
824N/A if ((found & 0x10) == 0 && strcmp(key, "BlendDesignPositions") == 0) {
824N/A strcpy(blendDesignPositions, buf);
824N/A found |= 0x10;
824N/A continue;
824N/A }
824N/A if ((found & 0x20) == 0 && strcmp(key, "BlendDesignMap") == 0) {
824N/A strcpy(blendDesignMap, buf);
824N/A found |= 0x20;
824N/A continue;
824N/A }
824N/A if ((found & 0x40) == 0 && strcmp(key, "BlendAxisTypes") == 0) {
824N/A strcpy(blendAxisTypes, buf);
824N/A found |= 0x40;
824N/A continue;
824N/A }
824N/A }
824N/A
824N/A if (fontName[0] != '\0') {
824N/A if (fontFullName[0] == '\0') {
824N/A if (fontFamily[0] != '\0') strcpy(fontFullName, fontFamily);
824N/A else strcpy(fontFullName, fontName);
824N/A }
824N/A if (fontFamily[0] == '\0') strcpy(fontFamily, fontFullName);
824N/A
824N/A MungeFontNames(fontName, fontFamily, fontFullName, fontWeight,
824N/A familyReturn, fullnameReturn, faceReturn);
824N/A#if DEBUG
824N/A printf("Found font %s\n", fontName);
824N/A printf("Munged to (%s) (%s)\n", familyReturn, faceReturn);
824N/A#endif
824N/A sprintf(buf, "%s,%s", faceReturn, fontName);
824N/A AddResource ("FontOutline", fontName, fileName, false);
824N/A AddResource("FontFamily", familyReturn, buf, true);
824N/A if (blendDesignPositions[0] != '\0' && blendDesignMap[0] != '\0' &&
824N/A blendAxisTypes[0] != '\0') {
824N/A#if DEBUG
824N/A printf("Font %s is multiple master\n", fontName);
824N/A#endif
824N/A AddResource("FontBlendPositions", fontName, blendDesignPositions, true);
824N/A AddResource("FontBlendMap", fontName, blendDesignMap, true);
824N/A AddResource("FontAxes", fontName, blendAxisTypes, true);
824N/A }
824N/A }
824N/A}
824N/A
824N/A
824N/Astatic void ProcessResource (file, fileName)
824N/A FILE *file;
824N/A char *fileName;
824N/A{
824N/A char resourceType[256];
824N/A char resourceName[256];
824N/A char *pointer;
824N/A
824N/A sscanf (lineBuffer, "%%!PS-Adobe-%*[0123456789.] Resource-%128s",
824N/A resourceType);
824N/A
824N/A StripName (resourceType);
824N/A
824N/A if (strcmp(resourceType, "Font") == 0) {
824N/A ProcessFont(file, fileName);
824N/A return;
824N/A }
824N/A
824N/A pointer = FindKeyValue (file, "%%BeginResource");
824N/A
824N/A if (pointer == NULL) return;
824N/A
824N/A sscanf (pointer, "%*256s%255s", resourceName);
824N/A StripName (resourceName);
824N/A
824N/A AddResource (resourceType, resourceName, fileName, false);
824N/A}
824N/A
824N/A
824N/Astatic void ProcessBDF (file, fileName)
824N/A FILE *file;
824N/A char *fileName;
824N/A{
824N/A char fontName[256];
824N/A char psFontName[256];
824N/A char key[256];
824N/A unsigned int found = 0;
824N/A char nameSize[300];
824N/A int resx, resy, size;
824N/A char sizebuf[50];
824N/A
824N/A fontName[0] = psFontName[0] = '\0';
824N/A resx = resy = size = 0;
824N/A
824N/A while (SkipToCharacter(file, '\n')) {
824N/A if (!SkipWhiteSpace(file)) break;
824N/A if (fscanf (file, "%255s", key) != 1) continue;
824N/A if (!SkipWhiteSpace(file)) break;
824N/A
824N/A if ((found & 1) == 0 && strcmp(key, "FONT") == 0) {
824N/A if (!ReadItem(file, fontName, 256)) break;
824N/A found |= 1;
824N/A continue;
824N/A }
824N/A if ((found & 2) == 0 && strcmp(key, "RESOLUTION_X") == 0) {
824N/A if (fscanf (file, "%d", &resx) != 1) break;
824N/A found |= 2;
824N/A continue;
824N/A }
824N/A if ((found & 4) == 0 && strcmp(key, "RESOLUTION_Y") == 0) {
824N/A if (fscanf (file, "%d", &resy) != 1) break;
824N/A found |= 4;
824N/A continue;
824N/A }
824N/A if ((found & 8) == 0 && strcmp(key, "_ADOBE_PSFONT") == 0) {
824N/A if (!ReadItem(file, psFontName, 256)) break;
824N/A found |= 8;
824N/A continue;
824N/A }
824N/A if ((found & 16) == 0 && strcmp(key, "SIZE") == 0) {
824N/A if (fscanf(file, "%d %d %d", &size, &resx, &resy) != 3) break;
824N/A found |= 16;
824N/A continue;
824N/A }
824N/A if ((found & 32) == 0 && strcmp(key, "POINT_SIZE") == 0) {
824N/A if (fscanf(file, "%d", &size) != 1) break;
824N/A size /= 10;
824N/A found |= 32;
824N/A }
824N/A if (strcmp(key, "ENDPROPERTIES") == 0) break;
824N/A if (strcmp(key, "STARTCHAR") == 0) break;
824N/A }
824N/A
824N/A if (psFontName[0] != '\0') strcpy(fontName, psFontName);
824N/A
824N/A if (size == 0 || fontName[0] == '\0') return;
824N/A if (resx == 0 || resy == 0) sprintf(sizebuf, "%d", size);
824N/A else sprintf(sizebuf, "%d-%d-%d", size, resx, resy);
824N/A
824N/A sprintf(nameSize, "%s%s", fontName, sizebuf);
824N/A
824N/A AddResource ("FontBDF", nameSize, fileName, false);
824N/A AddResource ("FontBDFSizes", fontName, sizebuf, true);
824N/A}
824N/A
824N/Astatic void ProcessAFM (file, fileName)
824N/A FILE *file;
824N/A char *fileName;
824N/A{
824N/A char fontName[256];
824N/A char *pointer;
824N/A char *extraCr;
824N/A
824N/A pointer = FindKeyValue (file, "FontName");
824N/A
824N/A if (pointer == NULL)
824N/A return;
824N/A
824N/A sscanf (pointer, "%255s", fontName);
824N/A
824N/A extraCr = strchr (fontName, '\r'); /* Handle DOS newlines */
824N/A
824N/A if (extraCr != NULL) *extraCr = '\0';
824N/A
824N/A AddResource ("FontAFM", fontName, fileName, false);
824N/A}
824N/A
824N/A/* ARGSUSED */
824N/Astatic void ProcessResourceDirectory (file, fileName)
824N/A FILE *file;
824N/A char *fileName;
824N/A{
824N/A}
824N/A
824N/Avoid MarkAsNonResource(filename)
824N/A char *filename;
824N/A{
824N/A AddResource("mkpsresPrivate", "NONRESOURCE", filename, false);
824N/A}
824N/A
824N/Achar *userCategories[] = {
824N/A "Encoding",
824N/A "File",
824N/A "FontAFM",
824N/A "FontBDF",
824N/A "FontOutline",
824N/A "FontPrebuilt",
824N/A "Form",
824N/A "Pattern",
824N/A "ProcSet",
824N/A NULL
824N/A};
824N/A
824N/Astatic void IdentifyFromUser(filename, file)
824N/A char *filename;
824N/A FILE *file;
824N/A{
824N/A int i, numCats, choice, size;
824N/A char buf[256], name[256];
824N/A static int stdinEOF = false;
824N/A
824N/A if (stdinEOF) return;
824N/A
824N/A if (file != NULL) rewind(file);
824N/A
824N/A while (1) {
824N/A printf("Please indentify the file\n");
824N/A printf(" 0 - Not a resource file\n");
824N/A i = 0;
824N/A while (userCategories[i] != NULL) {
824N/A printf(" %d - %s\n", i+1, userCategories[i]);
824N/A i++;
824N/A }
824N/A numCats = i;
824N/A printf(" %d - Other\n", numCats+1);
824N/A if (file != NULL) printf(" %d - Show some of file\n", numCats+2);
824N/A printf("> ");
824N/A fflush(stdout);
824N/A if (scanf("%d", &choice) != 1) {
824N/A stdinEOF = true;
824N/A return;
824N/A }
824N/A /* Skip the last of the number input line */
824N/A if (fgets(buf, 256, stdin) == NULL) {
824N/A stdinEOF = true;
824N/A return;
824N/A }
824N/A if (choice < 0 || (file != NULL && choice > numCats+2) ||
824N/A (file == NULL && choice > numCats+1)) {
824N/A printf("Invalid choice\n\n");
824N/A continue;
824N/A }
824N/A if (choice == numCats+2) {
824N/A printf("\n");
824N/A for (i = 0; i < 10; i++) {
824N/A if (fgets(buf, 256, file) != NULL) fputs(buf, stdout);
824N/A }
824N/A printf("\n");
824N/A continue;
824N/A }
824N/A if (choice == 0) {
824N/A MarkAsNonResource(filename);
824N/A return;
824N/A }
824N/A if (choice == numCats+1) {
824N/A printf("Please enter resource category: ");
824N/A fflush(stdout);
824N/A if (fgets(buf, 256, stdin) == NULL) {
824N/A stdinEOF = true;
824N/A return;
824N/A }
824N/A if (buf[0] == '\0') continue;
824N/A printf("Please enter resource name: ");
824N/A fflush(stdout);
824N/A if (fgets(name, 256, stdin) == NULL) {
824N/A stdinEOF = true;
824N/A return;
824N/A }
824N/A if (name[0] == '\0') continue;
824N/A StripName(buf);
824N/A StripName(name);
824N/A AddResource(buf, name, filename, false);
824N/A return;
824N/A }
824N/A if (strcmp(userCategories[choice-1], "FontBDF") == 0) {
824N/A printf("Please enter font name: ");
824N/A fflush(stdout);
824N/A if (fgets(name, 256, stdin) == NULL) {
824N/A stdinEOF = true;
824N/A return;
824N/A }
824N/A if (name[0] == '\0') continue;
824N/A StripName(name);
824N/A printf("Please enter font size: ");
824N/A fflush(stdout);
824N/A if (scanf("%d", &size) != 1) {
824N/A stdinEOF = true;
824N/A return;
824N/A }
824N/A /* Skip the last of the number input line */
824N/A if (fgets(buf, 256, stdin) == NULL) {
824N/A stdinEOF = true;
824N/A return;
824N/A }
824N/A if (size <= 0) continue;
824N/A sprintf(buf, "%d", size);
824N/A AddResource("FontBDFSizes", name, buf, false);
824N/A sprintf(buf, "%s%d", name, size);
824N/A AddResource("FontBDF", buf, filename, true);
824N/A return;
824N/A }
824N/A if (strcmp(userCategories[choice-1], "FontOutline") == 0) {
824N/A char family[256], face[256];
824N/A printf("Please enter font name: ");
824N/A fflush(stdout);
824N/A if (fgets(name, 256, stdin) == NULL) {
824N/A stdinEOF = true;
824N/A return;
824N/A }
824N/A if (name[0] == '\0') continue;
824N/A StripName(name);
824N/A printf("Please enter font family: ");
824N/A fflush(stdout);
824N/A if (fgets(family, 256, stdin) == NULL) {
824N/A stdinEOF = true;
824N/A return;
824N/A }
824N/A if (name[0] == '\0') continue;
824N/A StripName(family);
824N/A printf("Please enter font face: ");
824N/A fflush(stdout);
824N/A if (fgets(face, 256, stdin) == NULL) {
824N/A stdinEOF = true;
824N/A return;
824N/A }
824N/A if (name[0] == '\0') continue;
824N/A StripName(face);
824N/A AddResource("FontOutline", name, filename, true);
824N/A sprintf(buf, "%s,%s", face, name);
824N/A AddResource("FontFamily", family, buf, false);
824N/A return;
824N/A }
824N/A
824N/A printf("Please enter %s name: ", userCategories[choice-1]);
824N/A fflush(stdout);
824N/A if (fgets(name, 256, stdin) == NULL) {
824N/A stdinEOF = true;
824N/A return;
824N/A }
824N/A if (name[0] == '\0') continue;
824N/A StripName(name);
824N/A AddResource(userCategories[choice-1], name, filename, true);
824N/A return;
824N/A }
824N/A}
824N/A
824N/Aint IdentifyFromUPRList(filename)
824N/A char *filename;
824N/A{
824N/A UPRResource *resource = UPRresources[Hash(filename)];
824N/A
824N/A while (resource != NULL && strcmp(filename, resource->file) != 0) {
824N/A resource = resource->next;
824N/A }
824N/A if (resource == NULL) return false;
824N/A AddResource(resource->category, resource->name, resource->file,
824N/A resource->noPrefix);
824N/A return true;
824N/A}
824N/A
824N/Aint IdentifyFromFileSuffix(fileName)
824N/A char *fileName;
824N/A{
824N/A int len, len1;
824N/A char fontName[256];
824N/A register char *ch;
824N/A
824N/A /* The only files we can get anything useful from without looking inside
824N/A are AFM files and prebuilt files */
824N/A
824N/A len = strlen(fileName);
824N/A if (len < 5) return false;
824N/A if (strcmp(".afm", fileName + len - 4) == 0) {
824N/A len1 = 0;
824N/A for (ch = fileName+len-5; ch > fileName && *ch != '/'; ch--) len1++;
824N/A if (*ch == '/') ch++;
824N/A else len1++;
824N/A strcpy(fontName, ch);
824N/A fontName[len1] = '\0';
824N/A AddResource("FontAFM", fontName, fileName, false);
824N/A return true;
824N/A }
824N/A if (len < 6) return false;
824N/A if ((strcmp(".bepf", fileName + len - 5) == 0) ||
824N/A (strcmp(".lepf", fileName + len - 5) == 0)) {
824N/A len1 = 0;
824N/A for (ch = fileName+len-6; ch > fileName && *ch != '/'; ch--) len1++;
824N/A if (*ch == '/') ch++;
824N/A else len1++;
824N/A strcpy(fontName, ch);
824N/A fontName[len1] = '\0';
824N/A AddResource("FontPrebuilt", fontName, fileName, false);
824N/A return true;
824N/A }
824N/A return false;
824N/A}
824N/A
824N/Astatic void HandleUnopenableFile(filename, err)
824N/A char *filename;
824N/A int err;
824N/A{
824N/A if (IdentifyFromUPRList(filename)) return;
824N/A
824N/A if (!noSuffix && IdentifyFromFileSuffix(filename)) return;
824N/A
824N/A if (issueWarnings) {
824N/A fprintf (stderr, "%s: Could not open file %s (%s).\n",
824N/A program, filename, strerror(err));
824N/A }
824N/A
824N/A if (strict) exit(1);
824N/A
824N/A if (interactive) IdentifyFromUser(filename, (FILE *) NULL);
824N/A else MarkAsNonResource(filename);
824N/A}
824N/A
824N/A
824N/Astatic void HandleUnidentifiableFile(filename, file)
824N/A char *filename;
824N/A FILE *file;
824N/A{
824N/A if (IdentifyFromUPRList(filename)) return;
824N/A
824N/A if (!noSuffix && IdentifyFromFileSuffix(filename)) return;
824N/A
824N/A if (issueWarnings) {
824N/A fprintf (stderr, "%s: Could not identify file %s.\n",
824N/A program, filename);
824N/A }
824N/A
824N/A if (strict) exit(1);
824N/A
824N/A if (interactive) IdentifyFromUser(filename, file);
824N/A else MarkAsNonResource(filename);
824N/A}
824N/A
824N/A
824N/Atypedef struct {
824N/A char *key;
824N/A int keyLength;
824N/A char *key2;
824N/A int key2Length;
824N/A void (*proc)(/* FILE *file, char *fileName */);
824N/A} ResourceKey;
824N/A
824N/Astatic ResourceKey resourceTypes[] = {
824N/A {"%!PS-AdobeFont-", 15, NULL, 0, ProcessFont},
824N/A {"%!PS-Adobe-", 11, " Resource-", 10, ProcessResource},
824N/A {"STARTFONT", 9, NULL, 0, ProcessBDF},
824N/A {"StartFontMetrics", 16, NULL, 0, ProcessAFM},
824N/A {"PS-Resources-", 13, NULL, 0, ProcessResourceDirectory},
824N/A {NULL, 0, NULL}
824N/A};
824N/A
824N/Astatic void ProcessFile (fileName, filePath)
824N/A char *fileName;
824N/A char *filePath;
824N/A{
824N/A FILE *file;
824N/A ResourceKey *resourceType;
824N/A char version[10];
824N/A
824N/A if (fileName[0] == '.')
824N/A return;
824N/A
824N/A file = fopen (filePath, "r");
824N/A
824N/A if (file == NULL) {
824N/A HandleUnopenableFile(filePath, errno);
824N/A return;
824N/A }
824N/A
824N/A fgets (lineBuffer, BUFFER_SIZE, file);
824N/A
824N/A for (resourceType = resourceTypes; resourceType->key != NULL;
824N/A resourceType++) {
824N/A if (strncmp (resourceType->key, lineBuffer,
824N/A resourceType->keyLength) == 0) {
824N/A if (resourceType->key2 == NULL) {
824N/A (*resourceType->proc) (file, filePath);
824N/A break;
824N/A
824N/A } else {
824N/A if (sscanf(lineBuffer+resourceType->keyLength,
824N/A "%10[0123456789.]", version) != 1) continue;
824N/A
824N/A if (strncmp(resourceType->key2,
824N/A lineBuffer + resourceType->keyLength +
824N/A strlen(version),
824N/A resourceType->key2Length) == 0) {
824N/A (*resourceType->proc) (file, filePath);
824N/A break;
824N/A }
824N/A }
824N/A }
824N/A }
824N/A
824N/A if (resourceType->key == NULL) HandleUnidentifiableFile(filePath, file);
824N/A
824N/A fclose (file);
824N/A}
824N/A
824N/Astatic void ProcessUPRFile (fileName, filePath)
824N/A char *fileName;
824N/A char *filePath;
824N/A{
824N/A int len;
824N/A
824N/A if (fileName[0] == '.')
824N/A return;
824N/A
824N/A len = strlen(fileName);
824N/A if (len < 4) return;
824N/A if (strcmp(".upr", fileName + len - 4) != 0) return;
824N/A
824N/A PreprocessResourceDirectory(filePath);
824N/A}
824N/A
824N/A
824N/Astatic void ProcessDirectory (directoryName, top, fileFunction)
824N/A char *directoryName;
824N/A int top;
824N/A void (*fileFunction)();
824N/A{
824N/A DIR *directory;
824N/A struct dirent *directoryEntry;
824N/A struct stat status;
824N/A char *filePath, *fileName;
824N/A
824N/A#if DEBUG
824N/A fprintf (stderr, "Directory: %s\n", directoryName);
824N/A#endif
824N/A
824N/A directory = opendir (directoryName);
824N/A
824N/A if (directory == NULL) {
824N/A /* Treat top level failures to open differently from subdirectories */
824N/A if (top || issueWarnings) {
824N/A fprintf (stderr, "%s: Could not open directory %s (%s).\n",
824N/A program, directoryName, strerror(errno));
824N/A }
824N/A if (strict) exit(1);
824N/A return;
824N/A }
824N/A while ((directoryEntry = readdir (directory)) != NULL) {
824N/A fileName = directoryEntry->d_name;
824N/A if (fileName[0] == '.') continue;
824N/A filePath = ckmalloc (strlen (directoryName) + strlen (fileName) + 2,
824N/A "Failed to allocate file name string.");
824N/A sprintf (filePath, "%s/%s", directoryName, fileName);
824N/A if (stat(filePath, &status) == -1) {
824N/A if (issueWarnings) {
824N/A fprintf(stderr, "Couldn't get status of file %s (%s)\n",
824N/A filePath, strerror(errno));
824N/A }
824N/A if (strict) exit(1);
824N/A continue;
824N/A }
824N/A if (S_ISDIR(status.st_mode)) {
824N/A if (recursive) ProcessDirectory(filePath, false, fileFunction);
824N/A } else (*fileFunction) (fileName, filePath);
824N/A free (filePath);
824N/A }
824N/A
824N/A closedir (directory);
824N/A}
824N/A
824N/A
824N/Avoid GenerateEntriesFromUPRList()
824N/A{
824N/A Category *category;
824N/A Resource *resource;
824N/A UPRResource *upr;
824N/A int i, bucket;
824N/A
824N/A for (category = categories; category != NULL; category = category->next) {
824N/A if (strcmp(category->name, "FontBDFSizes") == 0 ||
824N/A strcmp(category->name, "FontFamily") == 0) {
824N/A continue;
824N/A }
824N/A
824N/A for (resource = category->list; resource != NULL;
824N/A resource = resource->next) {
824N/A for (upr = UPRresources[Hash(resource->file)];
824N/A upr != NULL && strcmp(upr->file, resource->file) < 0;
824N/A upr = upr->next) {}
824N/A if (upr != NULL) upr->found = true;
824N/A }
824N/A
824N/A if (category->hash != NULL) {
824N/A for (bucket = 0; bucket < HASHSIZE; bucket++) {
824N/A for (resource = category->hash[bucket]; resource != NULL;
824N/A resource = resource->next) {
824N/A for (upr = UPRresources[Hash(resource->file)];
824N/A upr != NULL && strcmp(upr->file, resource->file) < 0;
824N/A upr = upr->next) {}
824N/A if (upr != NULL) upr->found = true;
824N/A }
824N/A }
824N/A }
824N/A }
824N/A
824N/A for (bucket = 0; bucket < HASHSIZE; bucket++) {
824N/A for (upr = UPRresources[bucket]; upr != NULL; upr = upr->next) {
824N/A if (upr->found) continue;
824N/A
824N/A if (strcmp(upr->category, "FontBDFSizes") != 0 &&
824N/A strcmp(upr->category, "FontFamily") != 0) {
824N/A
824N/A if (!keep) {
824N/A /* If this file is in one of the input dirs, but wasn't
824N/A found, it must have been deleted since the previous run */
824N/A
824N/A for (i = 0; i < directoryCount; i++) {
824N/A if (strncmp(upr->file, directories[i],
824N/A directoryLen[i]) == 0 &&
824N/A upr->file[directoryLen[i]+1] == '/') goto NEXT_UPR;
824N/A }
824N/A }
824N/A AddResource(upr->category, upr->name, upr->file, upr->noPrefix);
824N/A }
824N/ANEXT_UPR: ;
824N/A }
824N/A }
824N/A
824N/A /* Now do BDFSizes and Families */
824N/A
824N/A for (bucket = 0; bucket < HASHSIZE; bucket++) {
824N/A for (upr = UPRresources[bucket]; upr != NULL; upr = upr->next) {
824N/A if (upr->found) continue;
824N/A
824N/A if (strcmp(upr->category, "FontBDFSizes") == 0) {
824N/A char *buf, *ch = upr->file;
824N/A
824N/A /* We know there's a comma since we put one in. Anything
824N/A before the comma is just there to make hashing work better */
824N/A
824N/A while (*ch != '\0') ch++;
824N/A while (ch >= upr->file && *ch != ',') ch--;
824N/A if (*ch == ',') ch++;
824N/A
824N/A buf = ckmalloc(strlen(upr->name) + strlen(ch) + 1,
824N/A "Failed to allocate BDF name\n");
824N/A strcpy(buf, upr->name);
824N/A strcat(buf, ch);
824N/A
824N/A if (FindResource("FontBDF", buf)) {
824N/A AddResource(upr->category, upr->name, ch, false);
824N/A }
824N/A free(buf);
824N/A
824N/A } else if (strcmp(upr->category, "FontFamily") == 0) {
824N/A char *ch = upr->file;
824N/A
824N/A while (true) {
824N/A while (*ch != '\0' && *ch != ',') ch++;
824N/A if (*ch == '\0') break;
824N/A if (ch > upr->file && *(ch-1) == '\\') ch++;
824N/A else break;
824N/A }
824N/A if (*ch == ',') {
824N/A ch++;
824N/A if (FindResource("FontOutline", ch)) {
824N/A AddResource(upr->category, upr->name, upr->file, false);
824N/A }
824N/A }
824N/A }
824N/A }
824N/A }
824N/A}
824N/A
824N/A
824N/Astatic char *ExtractDirectoryPrefix()
824N/A{
824N/A Category *category;
824N/A Resource *resource;
824N/A char *prefix = NULL;
824N/A char *ch1, *ch2;
824N/A int bucket;
824N/A
824N/A if (noPrefix) return NULL;
824N/A
824N/A category = categories;
824N/A
824N/A while (category != NULL) {
824N/A if (strcmp(category->name, "FontBDFSizes") == 0 ||
824N/A strcmp(category->name, "FontFamily") == 0 ||
824N/A strcmp(category->name, "FontBlendPositions") == 0 ||
824N/A strcmp(category->name, "FontBlendMap") == 0 ||
824N/A strcmp(category->name, "FontAxes") == 0) {
824N/A category = category->next;
824N/A continue;
824N/A }
824N/A resource = category->list;
824N/A
824N/A while (resource != NULL) {
824N/A if (resource->noPrefix) {
824N/A resource = resource->next;
824N/A continue;
824N/A }
824N/A if (prefix == NULL) {
824N/A prefix = ckmalloc(strlen(resource->file) + 1,
824N/A "Failed to allocate directory prefix");
824N/A strcpy(prefix, resource->file);
824N/A#if DEBUG
824N/A printf("New directory prefix: %s\n", prefix);
824N/A#endif
824N/A } else {
824N/A ch1 = prefix;
824N/A ch2 = resource->file;
824N/A while (*ch1 != '\0' && *ch2 != '\0' && *ch1 == *ch2) {
824N/A ch1++; ch2++;
824N/A }
824N/A#if DEBUG
824N/A if (*ch1 != '\0') {
824N/A *ch1 = '\0';
824N/A printf("New directory prefix: %s\n", prefix);
824N/A }
824N/A#endif
824N/A *ch1 = '\0';
824N/A }
824N/A resource = resource->next;
824N/A }
824N/A
824N/A if (category->hash != NULL) {
824N/A for (bucket = 0; bucket < HASHSIZE; bucket++) {
824N/A for (resource = category->hash[bucket]; resource != NULL;
824N/A resource = resource->next) {
824N/A
824N/A if (resource->noPrefix) continue;
824N/A
824N/A if (prefix == NULL) {
824N/A prefix = ckmalloc(strlen(resource->file) + 1,
824N/A "Failed to allocate directory prefix");
824N/A strcpy(prefix, resource->file);
824N/A#if DEBUG
824N/A printf("New directory prefix: %s\n", prefix);
824N/A#endif
824N/A } else {
824N/A ch1 = prefix;
824N/A ch2 = resource->file;
824N/A while (*ch1 != '\0' && *ch2 != '\0' && *ch1 == *ch2) {
824N/A ch1++; ch2++;
824N/A }
824N/A#if DEBUG
824N/A if (*ch1 != '\0') {
824N/A *ch1 = '\0';
824N/A printf("New directory prefix: %s\n", prefix);
824N/A }
824N/A#endif
824N/A *ch1 = '\0';
824N/A }
824N/A }
824N/A }
824N/A }
824N/A category = category->next;
824N/A }
824N/A if (prefix != NULL) {
824N/A ch1 = ch2 = prefix;
824N/A while (*ch1 != '\0') {
824N/A if (*ch1 == '/') ch2 = ch1;
824N/A ch1++;
824N/A }
824N/A *ch2 = '\0';
824N/A }
824N/A
824N/A /* Prefixes must be absolute path names */
824N/A if (prefix != NULL && prefix[0] != '/') prefix[0] = '\0';
824N/A return prefix;
824N/A}
824N/A
824N/A
824N/Astatic void OutputChar(file, c)
824N/A FILE *file;
824N/A char c;
824N/A{
824N/A static int len; /* Rely upon being 0 initially */
824N/A
824N/A if (c == '\n') len = 0;
824N/A else {
824N/A len++;
824N/A if (len == MAXLINELEN) {
824N/A fputs("\\\n", file);
824N/A len = 1;;
824N/A }
824N/A }
824N/A
824N/A putc(c, file);
824N/A}
824N/A
824N/Astatic void OutputString(file, s)
824N/A FILE *file;
824N/A char *s;
824N/A{
824N/A while (*s != '\0') OutputChar(file, *s++);
824N/A}
824N/A
824N/A
824N/Astatic void PrintResourceDirectory (directoryName, file)
824N/A char *directoryName;
824N/A FILE *file;
824N/A{
824N/A Category *category;
824N/A Resource *resource;
824N/A char *pname;
824N/A int prefixlen;
824N/A int bucket;
824N/A#define outs(s) OutputString(file, s)
824N/A#define outc(c) OutputChar(file, c)
824N/A
824N/A if (directoryName == NULL || *directoryName == '\0') prefixlen = 0;
824N/A else prefixlen = strlen(directoryName) + 1;
824N/A
824N/A if (makeExclusive) outs("PS-Resources-Exclusive-1.0\n");
824N/A else outs("PS-Resources-1.0\n");
824N/A
824N/A category = categories;
824N/A
824N/A while (category != NULL) {
824N/A outs(category->name);
824N/A outc('\n');
824N/A category = category->next;
824N/A }
824N/A
824N/A outs(".\n");
824N/A if (prefixlen > 1) {
824N/A outc('/');
824N/A outs(directoryName);
824N/A outc('\n');
824N/A }
824N/A
824N/A category = categories;
824N/A
824N/A while (category != NULL) {
824N/A resource = category->list;
824N/A outs(category->name);
824N/A outc('\n');
824N/A if (strcmp(category->name, "FontBDFSizes") != 0 &&
824N/A strcmp(category->name, "FontFamily") != 0) {
824N/A while (resource != NULL) {
824N/A outs(resource->name);
824N/A outc('=');
824N/A if (resource->noPrefix) {
824N/A outc('=');
824N/A outs(resource->file);
824N/A } else outs(resource->file+prefixlen);
824N/A outc('\n');
824N/A resource = resource->next;
824N/A }
824N/A } else {
824N/A while (resource != NULL) {
824N/A outs(resource->name);
824N/A outc('=');
824N/A outs(resource->file);
824N/A pname = resource->name;
824N/A resource = resource->next;
824N/A while (resource != NULL && strcmp(resource->name, pname) == 0) {
824N/A outc(',');
824N/A outs(resource->file);
824N/A resource = resource->next;
824N/A }
824N/A outc('\n');
824N/A }
824N/A }
824N/A if (category->hash != NULL) {
824N/A for (bucket = 0; bucket < HASHSIZE; bucket++) {
824N/A for (resource = category->hash[bucket]; resource != NULL;
824N/A resource = resource->next) {
824N/A outs(resource->name);
824N/A outc('=');
824N/A if (resource->noPrefix) {
824N/A outc('=');
824N/A outs(resource->file);
824N/A } else outs(resource->file+prefixlen);
824N/A outc('\n');
824N/A }
824N/A }
824N/A }
824N/A outs(".\n");
824N/A category = category->next;
824N/A }
824N/A#undef outs
824N/A#undef outc
824N/A}
824N/A
824N/A
824N/Avoid Usage()
824N/A{
824N/A fprintf(stderr,
824N/A "Usage: %s [-o outputfile] [-f inputfile]... [-dir directory]...\n",
824N/A program);
824N/A fprintf(stderr,
824N/A " [-e] [-i] [-nr] [-s] [-p] [-d] [-k] [-q] directory...\n");
824N/A exit(1);
824N/A}
824N/A
824N/Aint stdinDirectories = false;
824N/A
824N/Avoid ReadStdinDirectories()
824N/A{
824N/A char buf[256];
824N/A
824N/A if (stdinDirectories) {
824N/A fprintf(stderr, "%s: Can only read stdin as directory list once.\n",
824N/A program);
824N/A Usage();
824N/A }
824N/A
824N/A stdinDirectories = true;
824N/A
824N/A while (scanf("%255s", buf) == 1) {
824N/A directoryCount++;
824N/A directories = (char **) ckrealloc((char *) directories,
824N/A directoryCount * sizeof(char *),
824N/A "Failed to reallocate directory list.");
824N/A directories[directoryCount-1] = ckmalloc(strlen(buf)+1,
824N/A "Failed to allocate directory name.");
824N/A strcpy(directories[directoryCount-1], buf);
824N/A }
824N/A}
824N/A
824N/Avoid ProcessArglist(argc, argv)
824N/A int argc;
824N/A char *argv[];
824N/A{
824N/A int i = 1, j;
824N/A
824N/A if (argc > 0) {
824N/A program = strrchr(argv[0], '/');
824N/A if (program != NULL) program++;
824N/A else program = argv[0];
824N/A } else program = "makepsres";
824N/A
824N/A directories = (char **) ckmalloc(argc * sizeof(char *),
824N/A "Failed to allocate directory list.");
824N/A while (i < argc) {
824N/A if (strcmp(argv[i], "-help") == 0) Usage();
824N/A
824N/A else if (strcmp(argv[i], "-q") == 0) issueWarnings = false;
824N/A
824N/A else if (strcmp(argv[i], "-k") == 0) keep = true;
824N/A
824N/A else if (strcmp(argv[i], "-d") == 0) discard = true;
824N/A
824N/A else if (strcmp(argv[i], "-p") == 0) noPrefix = true;
824N/A
824N/A else if (strcmp(argv[i], "-s") == 0) strict = true;
824N/A
824N/A else if (strcmp(argv[i], "-nr") == 0) recursive = false;
824N/A
824N/A else if (strcmp(argv[i], "-nb") == 0) noBackup = true;
824N/A
824N/A else if (strcmp(argv[i], "-ns") == 0) noSuffix = true;
824N/A
824N/A else if (strcmp(argv[i], "-i") == 0) interactive = true;
824N/A
824N/A else if (strcmp(argv[i], "-e") == 0) makeExclusive = true;
824N/A
824N/A else if (strcmp(argv[i], "-f") == 0) {
824N/A i++;
824N/A if (i >= argc) Usage();
824N/A if (inputFiles == NULL) {
824N/A inputFiles = (char **) ckmalloc(argc * sizeof(char *),
824N/A "Failed to allocat input file list.");
824N/A }
824N/A inputFiles[inputCount++] = argv[i];
824N/A }
824N/A
824N/A else if (strcmp(argv[i], "-o") == 0) {
824N/A i++;
824N/A if (i >= argc) Usage();
824N/A outputFilename = argv[i];
824N/A }
824N/A
824N/A else if (strcmp(argv[i], "-dir") == 0) {
824N/A i++;
824N/A if (i >= argc) Usage();
824N/A directories[directoryCount++] = argv[i];
824N/A }
824N/A
824N/A else directories[directoryCount++] = argv[i];
824N/A
824N/A i++;
824N/A }
824N/A
824N/A if (directoryCount == 0) {
824N/A directoryCount = 1;
824N/A directories[0] = ".";
824N/A } else {
824N/A for (i = 0; i < directoryCount; i++) {
824N/A if (strcmp(directories[i], "-") == 0) ReadStdinDirectories();
824N/A }
824N/A }
824N/A
824N/A if (stdinDirectories) {
824N/A j = 0;
824N/A for (i = 0; i < directoryCount; i++) {
824N/A if (strcmp(directories[i], "-") != 0) {
824N/A directories[j] = directories[i];
824N/A j++;
824N/A }
824N/A }
824N/A directoryCount--;
824N/A }
824N/A
824N/A for (i = 0; i < inputCount; i++) {
824N/A if (strcmp(inputFiles[i], "-") == 0 && stdinDirectories) {
824N/A fprintf(stderr,
824N/A "%s: Cannot read stdin as both directory list and input file\n",
824N/A program);
824N/A Usage();
824N/A }
824N/A }
824N/A
824N/A#if DEBUG
824N/A printf("Input directory list:\n");
824N/A for (i = 0; i < directoryCount; i++) printf(" %s\n", directories[i]);
824N/A#endif
824N/A
824N/A directoryLen = (int *) ckmalloc(directoryCount * sizeof(int),
824N/A "Failed to allocate directory length list.");
824N/A
824N/A for (i = 0; i < directoryCount; i++) {
824N/A directoryLen[i] = strlen(directories[i]);
824N/A }
824N/A}
824N/A
824N/A
824N/Avoid CheckBackup(filename)
824N/A char *filename;
824N/A{
824N/A char *backupname;
824N/A
824N/A if (noBackup || strcmp(filename, "/dev/null") == 0) return;
824N/A
824N/A backupname = ckmalloc(strlen(filename)+2,
824N/A "Failed to allocate backup file name.'");
824N/A strcpy(backupname, filename);
824N/A strcat(backupname, "~");
824N/A
824N/A /* Effect "rename (filename, backupname)" in BSD/Sys-V independent way */
824N/A
824N/A (void) unlink (backupname); /* Ignore error */
824N/A
824N/A#ifndef __UNIXOS2__
824N/A if (link (filename, backupname) != 0) {
824N/A if (errno != ENOENT) {
824N/A fprintf(stderr, "%s: Could not back up output file %s\n",
824N/A program, filename);
824N/A fprintf(stderr, " and will not write over it (%s)\n",
824N/A strerror(errno));
824N/A exit(1);
824N/A }
824N/A } else (void) unlink(filename);
824N/A#else
824N/A if (rename(filename,backupname) != 0) {
824N/A fprintf(stderr, "%s: Could not back up output file %s\n",
824N/A program, filename);
824N/A fprintf(stderr, " and will not write over it (%s)\n",
824N/A strerror(errno));
824N/A exit(1);
824N/A }
824N/A#endif
824N/A free(backupname);
824N/A}
824N/A
824N/A
824N/Avoid IssueDuplicateWarnings()
824N/A{
824N/A int headerIssued = false;
824N/A Category *category;
824N/A Duplicate *dup;
824N/A
824N/A for (category = categories; category != NULL; category = category->next) {
824N/A if (category->duplicates == NULL) continue;
824N/A if (!headerIssued) {
824N/A headerIssued = true;
824N/A fprintf(stderr,
824N/A "%s: Warning: The output resource file contains the following\n",
824N/A program);
824N/A fprintf(stderr,
824N/A " duplicates. Edit them out if you wish.\n");
824N/A }
824N/A fprintf(stderr, "Category %s:\n", category->name);
824N/A for (dup = category->duplicates; dup != NULL; dup = dup->next) {
824N/A fprintf(stderr, " Resource: %s\n", dup->name);
824N/A fprintf(stderr, " First file: %s\n", dup->file1);
824N/A fprintf(stderr, " Second file: %s\n", dup->file2);
824N/A }
824N/A }
824N/A}
824N/A
824N/Aint
824N/Amain (argc, argv)
824N/A int argc;
824N/A char *argv[];
824N/A{
824N/A FILE *outputFile;
824N/A int i, len;
824N/A char *prefix;
824N/A
824N/A directories = NULL;
824N/A directoryCount = 0;
824N/A recursive = true;
824N/A discard = false;
824N/A keep = false;
824N/A outputFilename = NULL;
824N/A inputFiles = NULL;
824N/A inputCount = 0;
824N/A makeExclusive = false;
824N/A interactive = false;
824N/A strict = false;
824N/A noPrefix = false;
824N/A issueWarnings = true;
824N/A noBackup = false;
824N/A noSuffix = false;
824N/A
824N/A ProcessArglist(argc, argv);
824N/A
824N/A for (i = 0; i < inputCount; i++) {
824N/A PreprocessResourceDirectory(inputFiles[i]);
824N/A }
824N/A
824N/A /* Make two passes; the first time we just look for .upr files, and the
824N/A second time we look for everything. This gives us a better chance at
824N/A identifying files. */
824N/A
824N/A for (i = 0; i < directoryCount; i++) {
824N/A len = strlen (directories[i]);
824N/A if (directories[i][len - 1] == '/') directories[i][len - 1] = '\0';
824N/A
824N/A ProcessDirectory (directories[i], true, ProcessUPRFile);
824N/A }
824N/A
824N/A#if DEBUG
824N/A {
824N/A int i, biggestBucket, emptyCount;
824N/A static int count[11];
824N/A emptyCount = biggestBucket = 0;
824N/A for (i = 0; i < HASHSIZE; i++) {
824N/A if (bucketCount[i] == 0) emptyCount++;
824N/A if (bucketCount[i] > biggestBucket) biggestBucket = bucketCount[i];
824N/A }
824N/A if (biggestBucket != 0) {
824N/A for (i = 0; i < HASHSIZE; i++) {
824N/A count[bucketCount[i] * 10 / biggestBucket]++;
824N/A }
824N/A }
824N/A printf("Total UPR entries: %d\n", totalHashed);
824N/A printf("Buckets: %d\n", HASHSIZE);
824N/A printf("Longest bucket: %d\n", biggestBucket);
824N/A printf("Number of empty buckets: %d\n", emptyCount);
824N/A if (biggestBucket != 0) {
824N/A for (i = 0; i < 10; i++) {
824N/A printf("Number of buckets <= %d entries: %d\n",
824N/A biggestBucket*(i+1) / 10, count[i]);
824N/A }
824N/A }
824N/A }
824N/A#endif
824N/A
824N/A for (i = 0; i < directoryCount; i++) {
824N/A len = strlen (directories[i]);
824N/A if (directories[i][len - 1] == '/') directories[i][len - 1] = '\0';
824N/A
824N/A ProcessDirectory (directories[i], true, ProcessFile);
824N/A }
824N/A
824N/A if (outputFilename == NULL) outputFilename = "PSres.upr";
824N/A
824N/A if (strcmp(outputFilename, "-") == 0) outputFile = stdout;
824N/A else {
824N/A CheckBackup(outputFilename);
824N/A outputFile = fopen (outputFilename, "w");
824N/A }
824N/A
824N/A if (outputFile == NULL) {
824N/A fprintf (stderr,
824N/A "%s: Failed to open %s for writing: %s\n",
824N/A program, outputFilename, strerror(errno));
824N/A exit (1);
824N/A }
824N/A
824N/A if (!discard) GenerateEntriesFromUPRList();
824N/A
824N/A prefix = ExtractDirectoryPrefix();
824N/A PrintResourceDirectory (prefix, outputFile);
824N/A IssueDuplicateWarnings();
824N/A exit (0);
824N/A}