summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/mpware/dmp_ffile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/mpware/dmp_ffile.c')
-rw-r--r--Build/source/texk/web2c/mpware/dmp_ffile.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/mpware/dmp_ffile.c b/Build/source/texk/web2c/mpware/dmp_ffile.c
new file mode 100644
index 00000000000..3a7f475f8f7
--- /dev/null
+++ b/Build/source/texk/web2c/mpware/dmp_ffile.c
@@ -0,0 +1,286 @@
+/* $Id: dmp_ffile.c,v 1.4 2005/08/24 10:54:02 taco Exp $
+ Public domain. */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "dmp.h"
+
+/* Where dmp looks for tex font metric files */
+#define TEXFONTS ".:/usr/lib/tex/fonts/tfm"
+
+/* Where dmp looks for troff font tables */
+#define TRFONTS "/usr/share/groff/current/font/devps"
+
+/* Where dmp looks for font map data and spec chars */
+#define MPPOOL ".:/usr/lib/mp"
+
+
+char *tfmpath = TEXFONTS; /* directories to search for TFM files */
+char *dbpath = MPPOOL; /* directories for font map data */
+char *charpath = MPPOOL; /* directories for spec chars */
+char *trpath = TRFONTS; /* search path for troff font data */
+
+/**************************************************************
+ Search Paths
+***************************************************************/
+
+#ifdef MS_DOS
+#define PATH_DELIM ';'
+#else
+#ifdef WIN32
+#define PATH_DELIM ';'
+#else
+#define PATH_DELIM ':'
+#endif
+#endif
+
+void fsearch_init(void)
+{
+ char *envpath;
+
+ if ((envpath = getenv("TEXFONTS")) != NULL)
+ tfmpath = envpath;
+ if ((envpath = getenv("MPPOOL")) != NULL) {
+ dbpath = envpath;
+ charpath = envpath;
+ }
+ if ((envpath = getenv("TRFONTS")) != NULL)
+ trpath = envpath;
+}
+
+
+FILE *fsearch(char *nam, char *ext, int path_type)
+{
+ FILE *f;
+ char *s, *p;
+ int dirlen;
+ char *path;
+ if (path_type == TEXFONTS_TYPE) {
+ path = tfmpath;
+ } else if (path_type == DB_TYPE) {
+ path = dbpath;
+ } else if (path_type == CHARLIB_TYPE) {
+ path = charpath;
+ /* somewhat sneaky trick to unify 'fsearch' API with
+ the smallest possible code impact */
+ ext = nam;
+ nam = "charlib/";
+ } else if (path_type == TRFONTS_TYPE) {
+ path = trpath;
+ }
+
+ if (nam[0]=='/') /* file name has absolute path */
+ path = NULL;
+ do {
+ s = &strpool[poolsize];
+ if (path!=NULL) {
+ while ((*path!=PATH_DELIM) && (*path!='\0'))
+ add_to_pool(*path++);
+ if (*path=='\0') path=NULL; else path++;
+ add_to_pool('/');
+ }
+ dirlen = &strpool[poolsize] - s;
+ for (p=nam; *p!='\0'; p++) add_to_pool(*p);
+ for (p=ext; *p!='\0'; p++) add_to_pool(*p);
+ add_to_pool('\0');
+ pathexpand(s, dirlen, &strpool[POOLMAX]-s);
+ f = fopen(s, "r");
+ poolsize = s - &strpool[0];
+ } while (f==NULL && path!=NULL);
+ if (f==NULL) quit("Cannot find ",nam,ext);
+ return f;
+}
+
+
+
+/**********************************************************
+ You might have to modify the following includes and defines.
+ They are supposed to declare opendir(), readdir(), closedir()
+ and define how to access the result of readdir().
+ **********************************************************/
+#ifdef BSD
+#include <sys/types.h>
+#include <sys/dir.h>
+#define DIRentry struct direct /* readdir() returns pointer to this */
+#define de_name d_name /* field in DIRentry for file name */
+
+#else
+/* This is for SYSV and _POSIX_SOURCE; I don't know about other systems
+ */
+#include <dirent.h>
+#define DIRentry struct dirent /* readdir() returns pointer to this */
+#define de_name d_name /* field in DIRentry for file name */
+#endif
+
+
+/**********************************************************
+ Nothing below here should need changing
+ **********************************************************/
+
+#include <stdio.h>
+
+#include <string.h>
+
+extern void exit();
+extern int access();
+
+
+#ifdef PEDEBUG
+/* The PEDEBUG flag is meant for seperate debugging of this file. Do not
+ set it when compiling MetaPost.
+*/
+int myaccess(nam, mode)
+{
+ int r;
+ r = access(nam, mode);
+ printf("can%s access %s\n", (r==0 ? "" : "not"), nam);
+ return r;
+}
+#else
+#define myaccess access
+#endif
+
+
+void move_str(dest, src) /* strcpy() for overlapping strings */
+ char *dest, *src;
+{
+ char *s, *d;
+ int n;
+
+ if (dest < src) {
+ while (*src != '\0')
+ *dest++ = *src++;
+ *dest = '\0';
+ } else {
+ n = strlen(src);
+ d = dest + n;
+ s = src + n;
+ *d = '\0';
+ while (s != src)
+ *--d = *--s;
+ }
+}
+
+
+/* Find the first "//" within the first dirlen characters of buf[], or return
+ * zero to indicate failure.
+ */
+char* find_dblslash(buf, dirlen)
+ char* buf;
+ int dirlen;
+{
+ char* p;
+ int k;
+
+ k = 0;
+ dirlen--;
+ while ((p = strchr(buf+k, '/')) != 0) {
+ if (p-buf >= dirlen)
+ return 0;
+ if (p[1]=='/')
+ return p;
+ k = 1 + p-buf;
+ }
+ return 0;
+}
+
+
+/* Pretend the string ends at endp and call opendir().
+ */
+DIR* pe_opendir(buf, endp)
+ char *buf, *endp;
+{
+ DIR* dirp;
+ char s;
+
+ s = *endp;
+ *endp = '\0';
+ dirp = opendir(buf);
+#ifdef PEDEBUG
+ printf("%s directory %s\n", (dirp==0 ? "cannot open" : "opening"), buf);
+#endif
+ *endp = s;
+ return dirp;
+}
+
+
+/* A file name begins at buf and has a slash at slash followed by a final
+ * component of length tail. Append one or more intermediate directories and
+ * then the final component so as to make an accessible path name. If this can
+ * be done, return the length of the path name; otherwise return something
+ * negative and leave buf set to a bad path name. On exit, *tailp is pointed
+ * to the tail string. Buffer overflow happens when the tail string would have
+ * to start at a position greater than lim.
+ * The algorithm is depth-first search with pruning based on the idea that
+ * directories contain files or subdirectories, but not both.
+ */
+int expand_dblslash(buf, slash, tail, lim, tailp)
+ char *buf, *slash, *lim;
+ int tail;
+ char** tailp;
+{
+ DIR* dirp;
+ DIRentry* de;
+ char *t, *tt; /* old and new positions of tail string */
+ char *ds;
+ int r;
+
+ t = slash + 1;
+ *tailp = t;
+ dirp = pe_opendir(buf, slash);
+ if (dirp==0)
+ return -2;
+ if (myaccess(buf, 04) == 0) {
+ closedir(dirp);
+ return (slash-buf) + 1 + tail;
+ }
+ while ((de = readdir(dirp)) != 0) {
+ ds = de->de_name;
+ if (ds[0]=='.' && (ds[1]==0 || ds[1]=='.' && ds[2]==0))
+ continue;
+ tt = slash + 2 + strlen(ds);
+ if (tt > lim) {
+ *slash = '\0';
+ fprintf(stderr,"> %s/%s/%s\n", buf, de->de_name, t);
+ fprintf(stderr,"! Fatal error: %s\n",
+ "// expansion makes path name too long");
+ exit(1);
+ }
+ move_str(tt, t);
+ strcpy(slash+1, ds);
+ tt[-1] = '/';
+ r = expand_dblslash(buf, tt-1, tail, lim, &t);
+ if (r != -1) {
+ *tailp = t;
+ closedir(dirp);
+ return (r<0) ? -1 : r;
+ }
+ }
+ closedir(dirp);
+ *tailp = t;
+ return -1;
+}
+
+
+
+/* Assume that buf points to an array of length at least bufsize that
+ * contains a path name. Modify the path name by expanding "//" if it occurs
+ * in the first dirlen characters. The expansions consist of zero or more
+ * intermediate directories. If the expansion fails, buf will contain an
+ * invalid path name.
+ */
+void pathexpand(buf, dirlen, bufsize)
+ char* buf; /* input path */
+ int dirlen; /* limit search to buf[0]..buf[dirlen-1] */
+ int bufsize; /* number of character in buf array */
+{
+ char *p;
+ int tail, junk;
+
+ if ((p = find_dblslash(buf, dirlen)) != 0) {
+ tail = strlen(p+1);
+ move_str(p, p+1);
+ expand_dblslash(buf, p, tail, buf+bufsize-tail-1, &junk);
+ }
+}