summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipsk/resident.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipsk/resident.c')
-rw-r--r--Build/source/texk/dvipsk/resident.c1216
1 files changed, 1216 insertions, 0 deletions
diff --git a/Build/source/texk/dvipsk/resident.c b/Build/source/texk/dvipsk/resident.c
new file mode 100644
index 00000000000..8a9a04fc972
--- /dev/null
+++ b/Build/source/texk/dvipsk/resident.c
@@ -0,0 +1,1216 @@
+/* For use with emTeX set FONTPATH to "TEXTFM"
+ */
+#ifndef FONTPATH
+#define FONTPATH "TEXFONTS"
+#endif
+
+/*
+ * This code reads in and handles the defaults for the program from the
+ * file config.sw. This entire file is a bit kludgy, sorry.
+ */
+#include "dvips.h" /* The copyright notice in that file is included too! */
+#include "paths.h"
+#ifdef KPATHSEA
+#include <kpathsea/c-ctype.h>
+#include <kpathsea/c-pathch.h>
+#include <kpathsea/c-stat.h>
+#include <kpathsea/pathsearch.h>
+#include <kpathsea/tex-file.h>
+#include <kpathsea/variable.h>
+#endif
+/*
+ * This is the structure definition for resident fonts. We use
+ * a small and simple hash table to handle these. We don't need
+ * a big hash table.
+ */
+struct resfont *reshash[RESHASHPRIME];
+/*
+ * The external declarations:
+ */
+#include "protos.h"
+
+/*
+ * To maintain a list of document fonts, we use the following
+ * pointer.
+ */
+struct header_list *ps_fonts_used;
+/*
+ * Our hash routine.
+ */
+unsigned int
+hash(char *s)
+{
+ unsigned int h = 12;
+
+ while (*s != 0)
+ h = (h + h + (unsigned char)(*s++)) % RESHASHPRIME;
+ return(h);
+}
+/*
+ * Reverse the hash chains.
+ */
+void
+revpslists(void) {
+ register int i;
+ for (i=0; i<RESHASHPRIME; i++)
+ reshash[i] = (struct resfont *)revlist(reshash[i]);
+}
+/*
+ * cleanres() marks all resident fonts as not being yet sent, except
+ * those marked with 2 meaning they were downloaded as part of the
+ * main prolog (not section prolog).
+ */
+void
+cleanres(void) {
+ register int i;
+ register struct resfont *p;
+ for (i=0; i<RESHASHPRIME; i++)
+ for (p=reshash[i]; p; p=p->next)
+ if (p->sent == 1)
+ p->sent = 0;
+}
+/*
+ * The routine that looks up a font name.
+ */
+struct resfont *
+lookup(char *name)
+{
+ struct resfont *p;
+
+ for (p=reshash[hash(name)]; p!=NULL; p=p->next)
+ if (strcmp(p->Keyname, name)==0)
+ return(p);
+ return(NULL);
+}
+
+struct resfont *
+findPSname(char *name)
+{
+ register int i;
+ register struct resfont *p;
+ for (i=0; i<RESHASHPRIME; i++)
+ for (p=reshash[i]; p; p=p->next) {
+ if (strcmp(p->PSname, name)==0)
+ return p;
+ }
+ return NULL;
+}
+
+/*
+ * This routine adds an entry.
+ */
+static void
+add_entry(char *TeXname, char *PSname, char *Fontfile,
+ char *Vectfile, char *specinfo, char *downloadinfo)
+{
+ struct resfont *p;
+ int h;
+ if (PSname == NULL)
+ PSname = TeXname;
+ p = (struct resfont *)mymalloc((integer)sizeof(struct resfont));
+ p->Keyname = TeXname;
+ p->PSname = PSname;
+ p->Fontfile = Fontfile;
+ p->Vectfile = Vectfile;
+ p->TeXname = TeXname;
+ p->specialinstructions = specinfo;
+ if (downloadinfo && *downloadinfo)
+ p->downloadheader = downloadinfo;
+ else
+ p->downloadheader = 0;
+ h = hash(TeXname);
+ p->next = reshash[h];
+ p->sent = 0;
+ reshash[h] = p;
+}
+/*
+ * Now our residentfont routine. Returns the number of characters in
+ * this font, based on the TFM file.
+ */
+int
+residentfont(register fontdesctype *curfnt)
+{
+ int i;
+ struct resfont *p;
+
+/*
+ * First we determine if we can find this font in the resident list.
+ */
+ if (*curfnt->area)
+ return 0; /* resident fonts never have a nonstandard font area */
+ if ((p=lookup(curfnt->name))==NULL)
+ return 0;
+/*
+ * This is not yet the correct way to do things, but it is useful as it
+ * is so we leave it in. The problem: if resident Times-Roman is
+ * re-encoded, then it will be downloaded as bitmaps; this is not
+ * right. The solution will be to introduce two types of `<'
+ * directives, one that downloads fonts and one that downloads
+ * short headers that are innocuous.
+ */
+ if (p->Fontfile && downloadpspk) {
+#ifdef DEBUG
+ if (dd(D_FONTS))
+ fprintf_str(stderr,"Using PK font %s for <%s>.\n",
+ curfnt->name, p->PSname);
+#endif /* DEBUG */
+ return 0;
+ }
+/*
+ * We clear out some pointers:
+ */
+#ifdef DEBUG
+ if (dd(D_FONTS))
+ fprintf_str(stderr,"Font %s <%s> is resident.\n",
+ curfnt->name, p->PSname);
+#endif /* DEBUG */
+ curfnt->resfont = p;
+ curfnt->name = p->TeXname;
+ for (i=0; i<256; i++) {
+ curfnt->chardesc[i].TFMwidth = 0;
+ curfnt->chardesc[i].packptr = NULL;
+ curfnt->chardesc[i].pixelwidth = 0;
+ curfnt->chardesc[i].flags = 0;
+ curfnt->chardesc[i].flags2 = 0;
+ }
+ add_name(p->PSname, &ps_fonts_used);
+/*
+ * We include the font here. But we only should need to include the
+ * font if we have a stupid spooler; smart spoolers should be able
+ * to supply it automatically.
+ */
+ if (p->downloadheader) {
+ char *cp = p->downloadheader;
+ char *q;
+
+ infont = p->PSname;
+ while (1) {
+ q = cp;
+ while (*cp && *cp != ' ')
+ cp++;
+ if (*cp) {
+ *cp = 0;
+ add_header(q);
+ *cp++ = ' ';
+ } else {
+/* if (strstr(q,".pfa")||strstr(q,".pfb")||
+ strstr(q,".PFA")||strstr(q,".PFB"))
+ break;
+ else */ {
+ add_header(q);
+ break;
+ }
+ }
+ infont = 0;
+ }
+ infont = 0;
+ }
+ i = tfmload(curfnt);
+ if (i < 0)
+ i = 1;
+ usesPSfonts = 1;
+ return(i);
+}
+#define INLINE_SIZE (2000)
+static char was_inline[INLINE_SIZE];
+static unsigned c_lineno;
+static void
+bad_config(const char *err)
+{
+ fprintf_str(stderr, "%s:%d:", realnameoffile, c_lineno);
+ error (err);
+ fprintf_str(stderr, " (%s)\n", was_inline);
+}
+
+#ifndef KPATHSEA
+/*
+ * Get environment variables! These override entries in ./config.h.
+ * We substitute everything of the form ::, ^: or :$ with default,
+ * so a user can easily build on to the existing paths.
+ */
+static char *
+getpath(char *who, char *what)
+{
+ if (who) {
+ register char *pp, *qq;
+ int lastsep = 1;
+
+ for (pp=nextstring, qq=who; *qq;) {
+ if (*qq == PATHSEP) {
+ if (lastsep) {
+ strcpy(pp, what);
+ pp = pp + strlen(pp);
+ }
+ lastsep = 1;
+ } else
+ lastsep = 0;
+ *pp++ = *qq++;
+ }
+ if (lastsep) {
+ strcpy(pp, what);
+ pp = pp + strlen(pp);
+ }
+ *pp = 0;
+ qq = nextstring;
+ nextstring = pp + 1;
+ return qq;
+ } else
+ return what;
+}
+#endif
+/*
+ * We use this function so we can support strings delimited by
+ * double quotes with spaces in them. We also accept strings
+ * with spaces in them, but kill off any spaces at the end.
+ */
+static char *
+configstring(char *s, int nullok)
+{
+ char tstr[INLINE_SIZE];
+ char *p = tstr;
+
+ while (*s && *s <= ' ')
+ s++;
+ if (*s == '"') {
+ s++;
+ while (*s != 10 && *s != 0 && *s != '"' && p < tstr+290)
+ *p++ = *s++;
+ } else {
+ while (*s && p < tstr+290)
+ *p++ = *s++;
+ while (*(p-1) <= ' ' && p > tstr)
+ p--;
+ }
+ *p = 0;
+ if (p == tstr && ! nullok)
+ bad_config("bad string");
+ return newstring(tstr);
+}
+#ifdef KPATHSEA
+/* We use this in `getdefaults' to modify the kpathsea structure for the
+ paths we read. See kpathsea/tex-file.[ch]. */
+#define SET_CLIENT_PATH(filefmt, val) \
+ kpse_format_info[filefmt].client_path = xstrdup (val)
+#endif
+/*
+ * Now we have the getdefaults routine.
+ */
+const char *psmapfile = PSMAPFILE;
+Boolean
+getdefaults(const char *s)
+{
+ FILE *deffile;
+ char PSname[INLINE_SIZE];
+ register char *p;
+ integer hsiz, vsiz;
+#ifndef KPATHSEA
+ char *d = configpath;
+ int i, j;
+#endif
+ int canaddtopaper = 0;
+
+ if (printer == NULL) {
+ if (s) {
+ strcpy(PSname, s);
+ } else {
+#ifdef KPATHSEA
+ char *dvipsrc = kpse_var_value ("DVIPSRC");
+#ifdef WIN32
+ if (dvipsrc && *dvipsrc) {
+ /* $DVIPSRC was set by user */
+ strcpy(PSname, dvipsrc);
+ }
+ else
+ /* No env var, looking into some kind of standard path. */
+ if (SearchPath(".;%HOME%;c:\\", ".dvipsrc", NULL,
+ INLINE_SIZE, PSname,
+ &dvipsrc) == 0) {
+ /* search failed, we must put something into PSname. */
+ dvipsrc = kpse_var_expand(DVIPSRC);
+ if (dvipsrc) {
+ strcpy(PSname, dvipsrc);
+ free(dvipsrc);
+ }
+ /* Else SearchPath has filled PSname with something */
+ }
+ /* remove any redundant path separators. Many configurations
+ can show up: c:\/.dvipsrc and so on ... */
+ {
+ char *p, *q;
+ for (p = q = PSname; *p && (p - PSname < INLINE_SIZE);
+ p++, q++) {
+ if (IS_DIR_SEP(*p)) {
+ *q = DIR_SEP; p++; q++;
+ while (*p && IS_DIR_SEP(*p)) p++;
+ }
+ else if (IS_KANJI(p)) {
+ *q++ = *p++;
+ }
+ *q = *p;
+ }
+ *q = '\0';
+ }
+#else
+ if(!dvipsrc) dvipsrc = kpse_var_expand(DVIPSRC);
+ strcpy(PSname, dvipsrc ? dvipsrc : "~/.dvipsrc");
+ if(dvipsrc) free(dvipsrc);
+#endif /* WIN32 */
+
+#else /* ! KPATHSEA */
+#ifndef VMCMS /* IBM: VM/CMS - don't have home directory on VMCMS */
+#ifndef MVSXA
+ d = "~";
+#endif
+#endif /* IBM: VM/CMS */
+ strcpy(PSname, DVIPSRC);
+#endif /* KPATHSEA */
+ }
+ } else {
+#if defined(MSDOS) || defined(OS2)
+ strcpy(PSname, printer);
+ strcat(PSname, ".cfg");
+#else
+ strcpy(PSname, "config.");
+ strcat(PSname, printer);
+#endif
+ }
+#ifdef KPATHSEA
+ if ((deffile=search(configpath,PSname,READ))!=NULL) {
+#else
+ if ((deffile=search(d,PSname,READ))!=NULL) {
+#endif
+ if (dvips_debug_flag && !quiet) {
+ if (strlen(realnameoffile) + prettycolumn > STDOUTSIZE) {
+ fprintf(stderr, "\n");
+ prettycolumn = 0;
+ }
+ fprintf_str(stderr, "{%s}", realnameoffile);
+ prettycolumn += strlen(realnameoffile) + 2;
+ }
+#ifdef DEBUG
+ if (dd (D_CONFIG)) {
+ fprintf_str(stderr, "Reading dvips config file `%s':\n", realnameoffile);
+ }
+#endif
+ c_lineno = 0;
+ while (fgets(was_inline, INLINE_SIZE, deffile)!=NULL) {
+ c_lineno++;
+#ifdef DEBUG
+ if (dd (D_CONFIG)) {
+ fprintf_str(stderr, "%s:%d:%s", realnameoffile, c_lineno, was_inline);
+ }
+#endif
+/*
+ * We need to get rid of the newline.
+ */
+ for (p=was_inline; *p; p++);
+ while (p > was_inline && (*(p-1) == '\n' || *(p-1) == '\r')) {
+ *--p = '\0';
+ }
+ if (was_inline[0] != '@')
+ canaddtopaper = 0;
+ switch (was_inline[0]) {
+/*
+ * Handling paper size information:
+ *
+ * If line is empty, then we clear out the paper size information
+ * we have so far.
+ *
+ * If it is `@+', then we add to the current paper size info.
+ *
+ * If it is `name hsize vsize', then we start a new definition.
+ */
+case '@' :
+ p = was_inline + 1;
+ while (*p && *p <= ' ') p++;
+ if (*p == 0) {
+ papsizes = 0; /* throw away memory */
+ } else if (*p == '+') {
+ if (canaddtopaper == 0)
+ error(
+ " @+ in config files must immediately following a @ lines");
+ else {
+ *(nextstring-1) = '\n';/* IBM: VM/CMS - changed 10 to "\n" */
+ p++;
+ while (*p && *p == ' ') p++;
+ strcpy(nextstring, p);
+ nextstring += strlen(p) + 1;
+ }
+ } else {
+ struct papsiz *ps;
+ char *q;
+
+ ps = (struct papsiz *)mymalloc((integer)sizeof(struct papsiz));
+ ps->next = papsizes;
+ papsizes = ps;
+ q = p;
+ while (*p && *p > ' ')
+ p++;
+ *p++ = 0;
+ ps->name = newstring(q);
+ while (*p && *p <= ' ') p++;
+ handlepapersize(p, &hsiz, &vsiz);
+ ps->xsize = hsiz;
+ ps->ysize = vsiz;
+ ps->specdat = newstring("");
+ canaddtopaper = 1;
+ }
+ break;
+case 'a' :
+ dopprescan = (was_inline[1] != '0');
+ break;
+case 'b':
+ if (strncmp(was_inline, "bitmapfontenc", 13) == 0) {
+ char *p = was_inline + 13 ;
+ while (*p && *p <= ' ')
+ p++ ;
+ if (strncmp(p, "off", 3) == 0) {
+ bitmapencopt(0) ; // disable bitmap font enc feature
+ } else if (strncmp(p, "on", 2) == 0) {
+ bitmapencopt(1) ; // try to include bitmap font encs
+ } else if (strncmp(p, "strict", 6) == 0) {
+ bitmapencopt(2) ; // issue warnings for missing encs
+ } else {
+ error(
+ "! bitmapfontenc config file option only supports on, off, and strict") ;
+ }
+ break ;
+ }
+#ifdef SHORTINT
+ if (sscanf(was_inline+1, "%ld", &pagecopies) != 1)
+ bad_config("missing pagecopies to b");
+#else
+ if (sscanf(was_inline+1, "%d", &pagecopies) != 1)
+ bad_config("missing pagecopies to b");
+#endif
+ if (pagecopies < 1 || pagecopies > 1000)
+ bad_config("pagecopies not between 1 and 1000");
+ break;
+case 'm' :
+#ifdef SHORTINT
+ if (sscanf(was_inline+1, "%ld", &swmem) != 1)
+ bad_config("missing swmem to m");
+#else /* ~SHORTINT */
+ if (sscanf(was_inline+1, "%d", &swmem) != 1)
+ bad_config("missing swmem to m");
+#endif /* ~SHORTINT */
+ if (swmem > 0) {
+ swmem += fontmem; /* grab headers we've seen already */
+ } else {
+ swmem = INT_MAX; /* if value <=0, max it out */
+ }
+ break;
+case 'M' :
+ /* If the user specified a -mode, don't replace it. */
+ if (!mfmode_option)
+ mfmode = configstring(was_inline+1, 0);
+ mflandmode = 0;
+ {
+ char *pp;
+ for (pp=mfmode; pp && *pp>' '; pp++);
+ if (pp && *pp == ' ') {
+ *pp++ = 0;
+ while (*pp && *pp <= ' ')
+ pp++;
+ if (*pp)
+ mflandmode = pp;
+ }
+ }
+ break;
+case 'o' :
+ if (!oname_option) {
+ struct stat st_buf;
+ char *tmp_oname;
+ tmp_oname = configstring(was_inline+1, 1);
+ if ((*tmp_oname && tmp_oname[strlen(tmp_oname)-1] == ':')
+ || (stat(tmp_oname, &st_buf) == 0 && S_ISCHR(st_buf.st_mode))) {
+ sendcontrolD = 1; /* if we send to a device, *we* are spooler */
+#if defined(MSDOS) || defined(OS2)
+ tmp_oname[strlen(tmp_oname)-1] = 0;
+#endif
+ }
+ oname = tmp_oname;
+ }
+ break;
+case 'F' :
+ sendcontrolD = (was_inline[1] != '0');
+ break;
+case 'O' :
+ p = was_inline + 1;
+ handlepapersize(p, &hoff, &voff);
+ break;
+#ifdef FONTLIB
+case 'L' :
+ {
+ char tempname[INLINE_SIZE];
+ if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config("missing arg to L");
+ else {
+ flipath = getpath(fliparse(PSname,tempname), flipath);
+ fliname = newstring(tempname);
+ }
+ }
+ break;
+#endif
+case 'T' :
+ if (sscanf(was_inline+1, "%s", PSname) != 1)
+ bad_config("missing arg to T");
+ else
+#ifdef KPATHSEA
+ SET_CLIENT_PATH (kpse_tfm_format, PSname);
+#else
+ tfmpath = getpath(PSname, tfmpath);
+#endif
+ break;
+case 'P' :
+ if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config("missing arg to P");
+ else
+#ifdef KPATHSEA
+ SET_CLIENT_PATH (kpse_pk_format, PSname);
+#else
+ pkpath = getpath(PSname, pkpath);
+#endif
+ break;
+case 'p' :
+ p = was_inline + 1;
+ while (*p && *p <= ' ')
+ p++;
+ if (*p == '+') {
+ if (sscanf(p+1, "%s", PSname) != 1)
+ bad_config("missing arg to p");
+ getpsinfo(PSname);
+ } else {
+ psmapfile = configstring(was_inline+1, 0);
+ }
+ break;
+case 'v' : case 'V' :
+ if (sscanf(was_inline+1, "%s", PSname) != 1)
+ bad_config("missing arg to V");
+ else
+#ifdef KPATHSEA
+ SET_CLIENT_PATH (kpse_vf_format, PSname);
+#else
+ vfpath = getpath(PSname, vfpath);
+#endif
+ break;
+case 'S' :
+ if (sscanf(was_inline+1, "%s", PSname) != 1)
+ bad_config("missing arg to S");
+ else
+#ifdef KPATHSEA
+ SET_CLIENT_PATH (kpse_pict_format, PSname);
+#else
+ figpath = getpath(PSname, figpath);
+#endif
+ break;
+case 's':
+ safetyenclose = 1;
+ break;
+case 'H' :
+ if (sscanf(was_inline+1, "%s", PSname) != 1)
+ bad_config("missing arg to H");
+ else
+#ifdef KPATHSEA
+ SET_CLIENT_PATH (headerpath, PSname);
+#else
+ headerpath = getpath(PSname, headerpath);
+#endif
+ break;
+case '%': case ' ' : case '*' : case '#' : case ';' :
+case '=' : case 0 : case '\n' :
+ break;
+case 'r' :
+ reverse = (was_inline[1] != '0');
+ break;
+/*
+ * This case is for last resort font scaling; I hate this, but enough
+ * people have in no uncertain terms demanded it that I'll go ahead and
+ * add it.
+ *
+ * This line must have numbers on it, resolutions, to search for the
+ * font as a last resort, and then the font will be scaled. These
+ * resolutions should be in increasing order.
+ *
+ * For most machines, just `300' is sufficient here; on the NeXT,
+ * `300 400' may be more appropriate.
+ */
+case 'R':
+#ifndef KPATHSEA
+ i = 0;
+ p = was_inline + 1;
+ while (*p) {
+ while (*p && *p <= ' ')
+ p++;
+ if ('0' <= *p && *p <= '9') {
+ j = 0;
+ while ('0' <= *p && *p <= '9')
+ j = 10 * j + (*p++ - '0');
+ if (i > 0)
+ if (lastresortsizes[i-1] > j) {
+ bad_config("last resort sizes (R) must be sorted");
+ }
+ lastresortsizes[i++] = j;
+ } else {
+ if (*p == 0)
+ break;
+ bad_config("only numbers expected on `R' line");
+ }
+ }
+ lastresortsizes[i] = 32000;
+#else /* KPATHSEA */
+ for (p = was_inline + 1; *p; p++) {
+ if (isblank ((unsigned char)*p)) {
+ *p = ':';
+ }
+ }
+ kpse_fallback_resolutions_string = xstrdup (was_inline + 1);
+#endif
+ break;
+case 'D' :
+ if (sscanf(was_inline+1, "%d", &actualdpi) != 1)
+ bad_config("missing arg to D");
+ if (actualdpi < 10 || actualdpi > 10000)
+ bad_config("dpi must be between 10 and 10000");
+ vactualdpi = actualdpi;
+ break;
+/*
+ * Execute a command. This can be dangerous, but can also be very useful.
+ */
+case 'E' :
+#ifdef SECURE
+ error("dvips was compiled with SECURE, which disables E in config");
+#else
+ if (secure) {
+ error("E in config is disabled. To enable E, set z0 before E");
+ break;
+ }
+ system(was_inline+1);
+#endif
+ break;
+case 'K':
+ removecomments = (was_inline[1] != '0');
+ break;
+case 'L':
+ lastpsizwins = (was_inline[1] != '0');
+ break;
+case 'U':
+ nosmallchars = (was_inline[1] != '0');
+ break;
+case 'W':
+ for (p=was_inline+1; *p && *p <= ' '; p++);
+ if (*p)
+ warningmsg = newstring(p);
+ else
+ warningmsg = 0;
+ break;
+case 'X' :
+ if (sscanf(was_inline+1, "%d", &actualdpi) != 1)
+ bad_config("missing numeric arg to X");
+ if (actualdpi < 10 || actualdpi > 10000)
+ bad_config("X arg must be between 10 and 10000");
+ break;
+case 'Y' :
+ if (sscanf(was_inline+1, "%d", &vactualdpi) != 1)
+ bad_config("missing numeric arg to Y");
+ if (vactualdpi < 10 || vactualdpi > 10000)
+ bad_config("Y arg must be between 10 and 10000");
+ break;
+case 'x': case 'y':
+ if (sscanf(was_inline+1, "%lg", &mag) != 1)
+ bad_config("missing arg to x or y");
+ overridemag = (was_inline[0] == 'x') ? 1 : -1;
+ break;
+case 'e' :
+ if (sscanf(was_inline+1, "%d", &maxdrift) != 1)
+ bad_config("missing arg to e");
+ if (maxdrift < 0) bad_config("bad argument to e");
+ vmaxdrift = maxdrift;
+ break;
+case 'z' :
+ if (secure_option && secure && was_inline[1] == '0') {
+ fprintf_str(stderr,
+ "warning: %s: z0 directive ignored since -R1 given\n",
+ realnameoffile); /* Never happen */
+ } else {
+ if (was_inline[1] == '0') {
+ secure = 0;
+ } else if (was_inline[1] == '2') {
+ secure = 2;
+ } else {
+ secure = 1;
+ }
+ }
+ break;
+case 'q' : case 'Q' :
+ quiet = (was_inline[1] != '0');
+ break;
+case 'f' :
+ filter = (was_inline[1] != '0');
+ if (filter)
+ oname = "";
+ /* noenv has already been tested, so no point in setting. */
+ sendcontrolD = 0;
+ break;
+#ifdef SHIFTLOWCHARS
+case 'G':
+ shiftlowchars = (was_inline[1] != '0');
+ break;
+#endif
+case 'h' :
+ if (sscanf(was_inline+1, "%s", PSname) != 1)
+ bad_config("missing arg to h");
+ else add_header(PSname);
+ break;
+case 'i' :
+ if (sscanf(was_inline+1, "%d", &maxsecsize) != 1)
+ maxsecsize = 0;
+ sepfiles = 1;
+ break;
+case 'I':
+ noenv = (was_inline[1] != '0');
+ break;
+case 'N' :
+ disablecomments = (was_inline[1] != '0');
+ break;
+case 'Z' :
+ compressed = (was_inline[1] != '0');
+ break;
+case 'j':
+ partialdownload = (was_inline[1] != '0');
+ break;
+case 't' :
+ if (sscanf(was_inline+1, "%s", PSname) != 1)
+ bad_config("missing arg to t");
+ else {
+ if (strcmp(PSname, "landscape") == 0) {
+ if (hpapersize || vpapersize)
+ error(
+ "both landscape and papersize specified; ignoring landscape");
+ else
+ landscape = 1;
+ } else
+ paperfmt = newstring(PSname);
+ }
+ break;
+case 'c' :
+ if (sscanf(was_inline+1, "%s", PSname) != 1)
+ bad_config("missing arg to c");
+ else
+ getdefaults(PSname);
+ break;
+default:
+ bad_config("strange line");
+ }
+ }
+ fclose(deffile);
+ } else {
+ if (printer)
+ {
+ char msg[1000];
+ snprintf (msg, sizeof(msg), "warning: no config file for `%s'",
+ printer);
+ error(msg);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*
+* If a character pointer is passed in, use that name; else, use the
+* default (possibly set) name, psfonts.map.
+*/
+void
+getpsinfo(const char *name)
+{
+ FILE *deffile;
+ register char *p;
+ char *specinfo, *downloadinfo;
+ char downbuf[500];
+ char specbuf[500];
+ int slen;
+
+ if (name == 0)
+ name = psmapfile;
+ if ((deffile=search(mappath, name, READ))!=NULL) {
+ if (dvips_debug_flag && !quiet) {
+ if (strlen(realnameoffile) + prettycolumn > STDOUTSIZE) {
+ fprintf(stderr, "\n");
+ prettycolumn = 0;
+ }
+ fprintf_str(stderr, "{%s}", realnameoffile);
+ prettycolumn += strlen(realnameoffile) + 2;
+ }
+ while (fgets(was_inline, INLINE_SIZE, deffile)!=NULL) {
+ p = was_inline;
+ if (*p > ' ' && *p != '*' && *p != '#' && *p != ';' && *p != '%') {
+ char *TeXname = NULL;
+ char *PSname = NULL;
+ char *Fontfile = NULL;
+ char *Vectfile = NULL;
+ char *hdr_name = NULL;
+ boolean nopartial_p = false;
+ boolean encoding_p = false;
+ specinfo = NULL;
+ downloadinfo = NULL;
+ downbuf[0] = 0;
+ specbuf[0] = 0;
+ while (*p) {
+ encoding_p = false;
+ while (*p && *p <= ' ')
+ p++;
+ if (*p) {
+ if (*p == '"') { /* PostScript instructions? */
+ if (specinfo) {
+ strcat(specbuf, specinfo);
+ strcat(specbuf, " ");
+ }
+ specinfo = p + 1;
+
+ } else if (*p == '<') { /* Header to download? */
+ /* If had previous downloadinfo, save it. */
+ if (downloadinfo) {
+ strcat(downbuf, downloadinfo);
+ strcat(downbuf, " ");
+ downloadinfo = NULL;
+ }
+ if (p[1] == '<') { /* << means always full download */
+ p++;
+ nopartial_p = true;
+ } else if (p[1] == '[') { /* <[ means an encoding */
+ p++;
+ encoding_p = true;
+ }
+ p++;
+ /* skip whitespace after < */
+ while (*p && *p <= ' ')
+ p++;
+
+ /* save start of header name */
+ hdr_name = p;
+
+ } else if (TeXname) /* second regular word on line? */
+ PSname = p;
+
+ else /* first regular word? */
+ TeXname = p;
+
+ if (*p == '"') {
+ p++; /* find end of "..." word */
+ while (*p != '"' && *p)
+ p++;
+ } else
+ while (*p > ' ') /* find end of anything else */
+ p++;
+ if (*p)
+ *p++ = 0;
+
+ /* If we had a header we were downloading, figure
+ out what to do; couldn't do this above since we
+ want to check the suffix. */
+ if (hdr_name) {
+ const char *suffix = find_suffix (hdr_name);
+ if (encoding_p || STREQ (suffix, "enc")) {
+ /* (SPQR) if it is a reencoding, pass on to
+ FontPart, and download as usual */
+ Vectfile = downloadinfo = hdr_name;
+ } else if (nopartial_p) {
+ downloadinfo = hdr_name;
+ } else if (FILESTRCASEEQ (suffix, "pfa")
+ || FILESTRCASEEQ (suffix, "pfb")
+ || STREQ (suffix, "PFA")
+ || STREQ (suffix, "PFB")) {
+ Fontfile = hdr_name;
+ } else {
+ downloadinfo = hdr_name;
+ }
+ }
+ }
+ }
+ if (specinfo)
+ strcat(specbuf, specinfo);
+ if (downloadinfo)
+ strcat(downbuf, downloadinfo);
+ slen = strlen(downbuf) - 1;
+ if (slen > 0 && downbuf[slen] == ' ') {
+ downbuf[slen] = 0;
+ }
+ if (TeXname) {
+ TeXname = newstring(TeXname);
+ PSname = newstring(PSname);
+ Fontfile = newstring(Fontfile);
+ Vectfile = newstring(Vectfile);
+ specinfo = newstring(specbuf);
+ downloadinfo = newstring(downbuf);
+ add_entry(TeXname, PSname, Fontfile, Vectfile,
+ specinfo, downloadinfo);
+ }
+ }
+ }
+ fclose(deffile);
+ }
+ checkstrings();
+}
+#ifndef KPATHSEA
+/*
+ * Get environment variables! These override entries in ./config.h.
+ * We substitute everything of the form ::, ^: or :$ with default,
+ * so a user can easily build on to the existing paths.
+ */
+static char *
+getenvup(char *who, char *what)
+{
+ return getpath(getenv(who), what);
+}
+#endif
+#if !defined(KPATHSEA) && defined(SEARCH_SUBDIRECTORIES)
+static char *concat3();
+#endif
+void
+checkenv(int which)
+{
+#ifndef KPATHSEA
+ if (which) {
+ tfmpath = getenvup(FONTPATH, tfmpath);
+ vfpath = getenvup("VFFONTS", vfpath);
+ pictpath = getenvup("TEXPICTS", pictpath);
+ figpath = getenvup("TEXINPUTS", figpath);
+ headerpath = getenvup("DVIPSHEADERS", headerpath);
+ if (getenv("TEXPKS"))
+ pkpath = getenvup("TEXPKS", pkpath);
+ else if (getenv("TEXPACKED"))
+ pkpath = getenvup("TEXPACKED", pkpath);
+ else if (getenv("PKFONTS"))
+ pkpath = getenvup("PKFONTS", pkpath);
+#ifdef SEARCH_SUBDIRECTORIES
+ else if (getenv(FONTPATH))
+ pkpath = getenvup(FONTPATH, pkpath);
+ if (getenv ("TEXFONTS_SUBDIR"))
+ fontsubdirpath = getenvup ("TEXFONTS_SUBDIR", fontsubdirpath);
+ {
+ char pathsep[2];
+ char *do_subdir_path();
+ char *dirs = do_subdir_path (fontsubdirpath);
+ /* If the paths were in dynamic storage before, that memory is
+ wasted now. */
+ pathsep[0] = PATHSEP;
+ pathsep[1] = '\0';
+ tfmpath = concat3 (tfmpath, pathsep, dirs);
+ pkpath = concat3 (pkpath, pathsep, dirs);
+ }
+#endif
+ } else
+ configpath = getenvup("TEXCONFIG", configpath);
+#endif
+}
+
+#if !defined(KPATHSEA) && defined(SEARCH_SUBDIRECTORIES)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#ifdef SYSV
+#include <dirent.h>
+typedef struct dirent *directory_entry_type;
+#else
+#include <sys/dir.h>
+typedef struct direct *directory_entry_type;
+#endif
+
+/* Declare the routine to get the current working directory. */
+
+#ifndef HAVE_GETCWD
+extern char *getwd ();
+#define getcwd(b, len) ((b) ? getwd (b) : getwd (xmalloc (len)))
+#else
+#ifdef ANSI
+extern char *getcwd (char *, int);
+#else
+extern char *getcwd ();
+#endif /* not ANSI */
+#endif /* not HAVE_GETWD */
+
+#if defined(SYSV) || defined(VMS) || defined(MSDOS) || defined(OS2) || defined(ATARIST)
+#define MAXPATHLEN (256)
+#else /* ~SYSV */
+#include <sys/param.h> /* for MAXPATHLEN */
+#endif
+
+extern void exit();
+extern int chdir();
+
+/* Memory operations: variants of malloc(3) and realloc(3) that just
+ give up the ghost when they fail. */
+
+char *
+xmalloc(unsigned size)
+{
+ char *mem = malloc (size);
+
+ if (mem == NULL)
+ {
+ fprintf (stderr, "! Cannot allocate %u bytes.\n", size);
+ exit (10);
+ }
+
+ return mem;
+}
+
+
+char *
+xrealloc(char *ptr, unsigned size)
+{
+ char *mem = realloc (ptr, size);
+
+ if (mem == NULL)
+ {
+ fprintf (stderr, "! Cannot reallocate %u bytes at %x.\n", size, (int)ptr);
+ exit (10);
+ }
+
+ return mem;
+}
+
+
+/* Return, in NAME, the next component of PATH, i.e., the characters up
+ to the next PATHSEP. */
+
+static void
+next_component(char *name, char **path)
+{
+ unsigned count = 0;
+
+ while (**path != 0 && **path != PATHSEP)
+ {
+ name[count++] = **path;
+ (*path)++; /* Move further along, even between calls. */
+ }
+
+ name[count] = 0;
+ if (**path == PATHSEP)
+ (*path)++; /* Move past the delimiter. */
+}
+
+
+#ifndef _POSIX_SOURCE
+#ifndef S_ISDIR
+#define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
+#endif
+#endif
+
+/* Return true if FN is a directory or a symlink to a directory,
+ false if not. */
+
+int
+is_dir(char *fn)
+{
+ struct stat stats;
+
+ return stat (fn, &stats) == 0 && S_ISDIR (stats.st_mode);
+}
+
+
+static char *
+concat3(char *s1, char *s2, char *s3)
+{
+ char *r = xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
+ strcpy (r, s1);
+ strcat (r, s2);
+ strcat (r, s3);
+ return r;
+}
+
+
+/* DIR_LIST is the default list of directories (colon-separated) to
+ search. We want to add all the subdirectories directly below each of
+ the directories in the path.
+
+ We return the list of directories found. */
+
+char *
+do_subdir_path(char *dir_list)
+{
+ char *cwd;
+ unsigned len;
+ char *result = xmalloc ((unsigned)1);
+ char *temp = dir_list;
+ char dirsep[2];
+
+ dirsep[0] = DIRSEP;
+ dirsep[1] = '\0';
+
+ /* Make a copy in writable memory. */
+ dir_list = xmalloc (strlen (temp) + 1);
+ strcpy (dir_list, temp);
+
+ *result = 0;
+
+ /* Unfortunately, we can't look in the environment for the current
+ directory, because if we are running under a program (let's say
+ Emacs), the PWD variable might have been set by Emacs' parent
+ to the current directory at the time Emacs was invoked. This
+ is not necessarily the same directory the user expects to be
+ in. So, we must always call getcwd(3) or getwd(3), even though
+ they are slow and prone to hang in networked installations. */
+ cwd = getcwd (NULL, MAXPATHLEN + 2);
+ if (cwd == NULL)
+ {
+ perror ("getcwd");
+ exit (errno);
+ }
+
+ do
+ {
+ DIR *dir;
+ directory_entry_type e;
+ char dirname[MAXPATHLEN];
+
+ next_component (dirname, &dir_list);
+
+ /* All the `::'s should be gone by now, but we may as well make
+ sure `chdir' doesn't crash. */
+ if (*dirname == 0) continue;
+
+ /* By changing directories, we save a bunch of string
+ concatenations (and make the pathnames the kernel looks up
+ shorter). */
+ if (chdir (dirname) != 0) continue;
+
+ dir = opendir (".");
+ if (dir == NULL) continue;
+
+ while ((e = readdir (dir)) != NULL)
+ {
+ if (is_dir (e->d_name) && strcmp (e->d_name, ".") != 0
+ && strcmp (e->d_name, "..") != 0)
+ {
+ char *found = concat3 (dirname, dirsep, e->d_name);
+
+ result = xrealloc (result, strlen (result) + strlen (found) + 2);
+
+ len = strlen (result);
+ if (len > 0)
+ {
+ result[len] = PATHSEP;
+ result[len + 1] = 0;
+ }
+ strcat (result, found);
+ free (found);
+ }
+ }
+ closedir (dir);
+
+ /* Change back to the current directory, in case the path
+ contains relative directory names. */
+ if (chdir (cwd) != 0)
+ {
+ perror (cwd);
+ exit (errno);
+ }
+ }
+ while (*dir_list != 0);
+
+ return result;
+}
+#endif /* SEARCH_SUBDIRECTORIES */