summaryrefslogtreecommitdiff
path: root/dviware/crudetype/version3/w2c-ext.c
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/crudetype/version3/w2c-ext.c')
-rw-r--r--dviware/crudetype/version3/w2c-ext.c628
1 files changed, 628 insertions, 0 deletions
diff --git a/dviware/crudetype/version3/w2c-ext.c b/dviware/crudetype/version3/w2c-ext.c
new file mode 100644
index 0000000000..1936da74ad
--- /dev/null
+++ b/dviware/crudetype/version3/w2c-ext.c
@@ -0,0 +1,628 @@
+/* External procedures for these programs. */
+
+/* This includes <stdio.h> and "site.h". */
+#include "w2c-ext.h"
+
+extern unsigned char xord[], xchr[];
+
+/* These help to deal with Pascal vs. C strings. */
+void make_c_string (), make_pascal_string ();
+void end_with_null (), end_with_space ();
+
+
+/* Round R to the nearest whole number. */
+integer zround (r)
+ double r;
+{
+ return r >= 0.0 ? (r + 0.5) : (r - 0.5);
+}
+
+
+/* Memory operations: variants of malloc(3) and realloc(3) that just
+ give up the ghost when they fail. It is a very bad practice to call
+ system procs & not check for errors.
+*/
+
+extern char *malloc (), *realloc ();
+
+char *xmalloc (size)
+ unsigned size;
+{
+ char *mem = malloc (size);
+
+ if (mem == NULL)
+ {
+ fprintf (stderr, "! Cannot allocate %u bytes.\n", size);
+ exit (10);
+ }
+
+ return mem;
+}
+
+
+char * xrealloc (ptr, size)
+ char *ptr;
+ unsigned size;
+{
+ char *mem = realloc (ptr, size);
+
+ if (mem == NULL)
+ {
+ fprintf (stderr, "! Cannot reallocate %u bytes at %x.\n", size, ptr);
+ exit (10);
+ }
+
+ return mem;
+}
+
+
+/* String operations. */
+
+/* Deal with C and Pascal strings. */
+
+/* Change the Pascal string P_STRING into a C string; i.e., make it
+ start after the leading character Pascal puts in, and terminate it
+ with a null. We also have to convert from the internal character set
+ (ASCII) to the external character set, if we're running on a
+ non-ASCII system.
+*/
+void make_c_string (p_string)
+ char **p_string;
+{
+ (*p_string)++;
+ end_with_null (*p_string);
+}
+
+
+/* Replace the first space we come to with a null.
+*/
+void end_with_null (s)
+ char *s;
+{
+ for ( ; *s != ' '; s++)
+#ifdef NONASCII
+ *s = xchr[*s]
+#endif
+ ;
+ *s = '\0';
+}
+
+
+/* Change the C string C_STRING into a Pascal string; i.e., make it
+ start one character before it does now (so C_STRING had better have
+ been a Pascal string originally), and terminate with a space. We
+ also convert back from the external character set to the internal
+ character set (ASCII), if we're running on a non-ASCII system.
+*/
+void make_pascal_string (c_string)
+ char **c_string;
+{
+ end_with_space (*c_string);
+ (*c_string)--;
+}
+
+/* Replace the first null we come to with a space.
+*/
+void end_with_space (s)
+ char *s;
+{
+ for ( ; *s != '\0' ; s++)
+#ifdef NONASCII
+ *s = xchr[*s]
+#endif
+ ;
+
+ *s = ' ';
+}
+
+
+/* Change the suffix of BASE (a Pascal string) to be SUFFIX (another
+ Pascal string). We have to change them to C strings to do the work,
+ then convert them back to Pascal strings.
+*/
+void makesuffix (base, suffix)
+ char *base;
+ char *suffix;
+{
+ char *last_dot, *last_slash;
+ make_c_string (&base);
+
+ last_dot = rindex (base, '.');
+ last_slash = rindex (base, '/');
+
+ if (last_dot == NULL || last_dot < last_slash) /* Add the suffix? */
+ {
+ make_c_string (&suffix);
+ strcat (base, suffix);
+ make_pascal_string (&suffix);
+ }
+
+ make_pascal_string (&base);
+}
+
+
+/* Insert the string INSERTION into TARGET before the index WHERE. We
+ assume that TARGET is large enough to hold the result.
+*/
+static void insert_string (target, where, insertion)
+ char target[];
+ int where;
+ char *insertion;
+{
+ int i;
+ unsigned insertion_length = strlen (insertion);
+ unsigned target_length = strlen (target);
+
+ for (i = target_length; i >= where; i--)
+ target[i + insertion_length] = target[i];
+
+ strncpy (target + where, insertion, insertion_length);
+}
+
+
+
+/* Path searching. */
+
+#define NUMBER_OF_PATHS 11
+
+static char *path[NUMBER_OF_PATHS];
+static char *env_var_names[NUMBER_OF_PATHS]
+ = { "BIBINPUTS", "GFFONTS", "MFBASES", "MFINPUTS", "MFPOOL",
+ "PKFONTS", "TEXFORMATS", "TEXINPUTS", "TEXPOOL",
+ "TEXFONTS", "VFFONTS"
+ };
+
+#define READ_ACCESS 4 /* Used in access(2) call. */
+
+/* What separates elements of the path variables. */
+#ifdef MS_DOS
+#define PATH_DELIMITER ';'
+#else
+#define PATH_DELIMITER ':'
+#endif
+
+/* We will need some system include files to deal with directories. */
+#ifdef SEARCH_SUBDIRECTORIES
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef SYSV
+#include <dirent.h>
+typedef struct dirent *directory_entry_type;
+#else
+#include <sys/dir.h>
+typedef struct direct *directory_entry_type;
+#endif /* not SYSV */
+
+/* Declare getcwd(3). */
+extern char *getcwd ();
+extern int errno;
+#endif /* SEARCH_SUBDIRECTORIES */
+
+
+/* Subroutines. */
+static void next_component ();
+int is_dir ();
+
+/* Says where NAME is ok to open for reading. */
+#define READABLE_FILE(name) access (name, READ_ACCESS) == 0 && !is_dir (name)
+
+
+/* This routine initializes `path[PATH_INDEX]'. If the environment
+ variable `env_var_names[PATH_INDEX]' is not set, we simply use
+ DEFAULT_VALUE. Otherwise, we use the value of the environment
+ variable, and then replace any ``extra'' colons with DEFAULT_VALUE.
+
+ For example, if DEFAULT_VALUE is `foo', and the environment variable
+ value is `:bar::baz:', the final result will be
+ `foo:bar:foo:baz:foo'. (Of course, it is pointless to have more than
+ one extra `:' in practice, but the point is that it can be anywhere.)
+
+ If subdirectory searching has been compiled (by defining
+ SEARCH_SUBDIRECTORIES), and SUBDIR_FLAG so indicates, we look at each
+ directory in the path and add all subdirectories we find to the end
+ of the path. This is somewhat less efficient when we are looking for
+ only one file, and the file would be found early in the path, but is
+ far more efficient when we look up many files using the same path. */
+
+/* Values for SUBDIR_FLAG. */
+#define SUBDIR_NO_CHECK 0
+#define SUBDIR_ALWAYS_CHECK 1
+#define SUBDIR_CHECK_IF_NOT_DEFAULT 2
+
+static void
+do_path (path_index, default_value, subdir_flag)
+ unsigned path_index;
+ char *default_value;
+ int subdir_flag;
+{
+ char *temp;
+ char *the_path;
+
+ temp = getenv (env_var_names[path_index]);
+ if (temp == NULL)
+ /* This doesn't actually assign into the array, but it doesn't
+ matter. */
+ the_path = default_value;
+ else
+ { /* Replace extra `:'s with the system default. */
+ the_path = xmalloc (strlen (temp) + 1);
+ strcpy (the_path, temp);
+
+ if (*the_path == PATH_DELIMITER)
+ {
+ the_path = xrealloc (the_path, strlen (the_path)
+ + strlen (default_value) + 1);
+ insert_string (the_path, 0, default_value);
+ }
+ if (*(the_path + strlen (the_path) - 1) == PATH_DELIMITER)
+ {
+ the_path = xrealloc (the_path, strlen (the_path)
+ + strlen (default_value) + 1);
+ strcat (the_path, default_value);
+ }
+ while ((temp = index (temp, PATH_DELIMITER)) != NULL)
+ {
+ temp++;
+ if (*temp == PATH_DELIMITER)
+ {
+ the_path = xrealloc (the_path, strlen (the_path)
+ + strlen (default_value) + 1);
+ insert_string (the_path, temp - the_path, default_value);
+ temp++;
+ }
+ }
+ }
+
+ /* Assign to the final resting place. */
+ path[path_index] = xmalloc (strlen (the_path) + 1);
+ strcpy (path[path_index], the_path);
+
+#ifdef SEARCH_SUBDIRECTORIES
+ /* At this point, `path[path_index]' is the colon-separated list of
+ directories to search. We want to add all the subdirectories
+ directly below each of those directories. */
+ if (subdir_flag == SUBDIR_ALWAYS_CHECK
+ || (subdir_flag == SUBDIR_CHECK_IF_NOT_DEFAULT
+ && the_path != default_value))
+ {
+ DIR *dir;
+ directory_entry_type e;
+ char dirname[FILENAMESIZE];
+
+ /* 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), even though it is slow
+ and prone to hang in networked installations. */
+ char *cwd = getcwd (NULL, FILENAMESIZE + 2);
+ if (cwd == NULL)
+ {
+ perror ("getcwd");
+ exit (errno);
+ }
+
+ temp = xmalloc (strlen (path[path_index]) + 1);
+ strcpy (temp, path[path_index]);
+
+ do
+ {
+ next_component (dirname, &temp);
+
+ /* All the `::'s should be gone by now, but we may as well make
+ sure `opendir' 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)
+ {
+ unsigned len = strlen (path[path_index]);
+ char potential[FILENAMESIZE];
+ strcpy (potential, dirname);
+ strcat (potential, "/");
+ strcat (potential, e->d_name);
+
+ path[path_index] = xrealloc (path[path_index],
+ len + strlen (potential) + 2);
+
+ len = strlen (path[path_index]);
+ *(path[path_index] + len) = PATH_DELIMITER;
+ *(path[path_index] + len + 1) = 0;
+ strcat (path[path_index], potential);
+ }
+ }
+ 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 (*temp != 0);
+ }
+#endif
+}
+
+
+/* This sets up the paths, by either copying from an environment variable
+ or using the default path, which is defined as a preprocessor symbol
+ (with the same name as the environment variable) in `site.h'. The
+ parameter PATH_BITS is a logical or of the paths we need to set.
+*/
+extern void
+setpaths (path_bits)
+ int path_bits;
+{
+ /* We must assign to the TFM file path before doing any of the other
+ font paths, since it is used as a default. */
+ if (path_bits
+ & (TFMFILEPATHBIT | GFFILEPATHBIT | PKFILEPATHBIT | VFFILEPATHBIT))
+ do_path (TFMFILEPATH, TEXFONTS, SUBDIR_ALWAYS_CHECK);
+
+ if (path_bits & BIBINPUTPATHBIT)
+ do_path (BIBINPUTPATH, BIBINPUTS, SUBDIR_NO_CHECK);
+
+ if (path_bits & GFFILEPATHBIT)
+ do_path (GFFILEPATH, path[TFMFILEPATH], SUBDIR_CHECK_IF_NOT_DEFAULT);
+
+ if (path_bits & MFBASEPATHBIT)
+ do_path (MFBASEPATH, MFBASES, SUBDIR_NO_CHECK);
+
+ if (path_bits & MFINPUTPATHBIT)
+ do_path (MFINPUTPATH, MFINPUTS, SUBDIR_ALWAYS_CHECK);
+
+ if (path_bits & MFPOOLPATHBIT)
+ do_path (MFPOOLPATH, MFPOOL, SUBDIR_NO_CHECK);
+
+ if (path_bits & PKFILEPATHBIT)
+ do_path (PKFILEPATH, path[TFMFILEPATH], SUBDIR_CHECK_IF_NOT_DEFAULT);
+
+ if (path_bits & TEXFORMATPATHBIT)
+ do_path (TEXFORMATPATH, TEXFORMATS, SUBDIR_NO_CHECK);
+
+ if (path_bits & TEXINPUTPATHBIT)
+ do_path (TEXINPUTPATH, TEXINPUTS, SUBDIR_ALWAYS_CHECK);
+
+ if (path_bits & TEXPOOLPATHBIT)
+ do_path (TEXPOOLPATH, TEXPOOL, SUBDIR_NO_CHECK);
+
+ if (path_bits & VFFILEPATHBIT)
+ do_path (VFFILEPATH, path[TFMFILEPATH], SUBDIR_CHECK_IF_NOT_DEFAULT);
+}
+
+
+/* Look for NAME, a Pascal string, in a colon-separated list of
+ directories. The path to use is given (indirectly) by PATH_INDEX.
+ If the search is successful, leave the full pathname in NAME (which
+ therefore must have enough room for such a pathname), padded with
+ blanks. Otherwise, or if NAME is an absolute or relative pathname,
+ just leave it alone.
+*/
+boolean
+testreadaccess (name, path_index)
+ char *name;
+ int path_index;
+{
+ char potential[FILENAMESIZE];
+ int ok = 0;
+ char *the_path = path[path_index];
+ char *saved_path = the_path;
+
+ make_c_string (&name);
+
+ if (*name == '/' || *name == '~'
+ || (*name == '.' && *(name + 1) == '/')
+ || (*name == '.' && *(name + 1) == '.' && *(name + 2) == '/'))
+ ok = READABLE_FILE (name);
+ else
+ {
+ do
+ {
+ next_component (potential, &the_path);
+
+ if (*potential != 0)
+ {
+ strcat (potential, "/");
+ strcat (potential, name);
+ ok = READABLE_FILE (potential);
+ }
+ }
+ while (!ok && *the_path != 0);
+
+ /* If we found it, leave the answer in NAME. */
+ if (ok)
+ strcpy (name, potential);
+ }
+
+ make_pascal_string (&name);
+
+ return ok;
+}
+
+
+/* Return, in NAME, the next component of PATH, i.e., the characters up
+ to the next PATH_DELIMITER.
+*/
+static void next_component (name, path)
+ char name[];
+ char **path;
+{
+ unsigned count = 0;
+
+ while (**path != 0 && **path != PATH_DELIMITER)
+ {
+ name[count++] = **path;
+ (*path)++; /* Move further along, even between calls. */
+ }
+
+ name[count] = 0;
+ if (**path == PATH_DELIMITER)
+ (*path)++; /* Move past the delimiter. */
+}
+
+
+
+/* Return true if FN is a directory or a symlink to a directory,
+ false if not.
+*/
+int
+is_dir (fn)
+ char *fn;
+{
+ struct stat stats;
+
+ return stat (fn, &stats) == 0 && (stats.st_mode & S_IFMT) == S_IFDIR;
+}
+
+
+
+/* File operations. */
+
+/* Open a file; don't return if any error occurs. NAME is a Pascal
+ string, but is changed to a C string and not changed back.
+ RMD: I do want it changed back
+*/
+FILE * checked_fopen (name, mode)
+ char *name;
+ char *mode;
+{
+ FILE *result;
+ char *cp;
+
+ make_c_string (&name);
+
+ result = fopen (name, mode);
+ if (result != NULL) {
+ make_pascal_string (&name);
+ return result;}
+
+ perror (name);
+ exit (1);
+ /*NOTREACHED*/
+}
+
+
+/* Return true if we're at the end of FILE, else false. This implements
+ Pascal's `eof' builtin.
+*/
+boolean test_eof (file)
+ text file;
+{
+ register int c;
+ FILE *ff ;
+ /* Maybe we're already at the end? */
+ ff = *file ;
+ if (feof( ff))
+ return true;
+
+ if ((c = getc (*file)) == EOF)
+ return true;
+
+ /* Whoops, we weren't at the end. Back up. */
+ (void) ungetc (c, *file);
+
+ return false;
+}
+
+
+/* Return true on end-of-line in FILE or at the end of FILE, else false.
+*/
+
+boolean eoln (file)
+ text file;
+{
+ register int c;
+
+ if (feof (*file))
+ return true;
+
+ c = getc (*file);
+
+ if (c != EOF)
+ (void) ungetc (c, *file);
+
+ return c == '\n' || c == EOF;
+}
+
+
+/* Print real number R in the Pascal format N:M on the file F.
+RMD: these procs not used; I made web2c generate proper write statements.
+*/
+void fprintreal (f, r, n, m)
+ text f;
+ double r;
+ int n, m;
+{
+ char fmt[50]; /* Surely enough, since N and M won't be more than 25
+ digits each! */
+
+ (void) sprintf (fmt, "%%%d.%dlf", n, m);
+ (void) fprintf (*f, fmt, r);
+}
+
+
+/* Print S, a Pascal string, on the file F. It starts at index 1 and is
+ terminated by a space.
+*/
+static void fprint_pascal_string (s, f)
+ char *s;
+ FILE *f;
+{
+ s++;
+ while (*s != ' ') putc (*s++, f);
+}
+
+/* Print S, a Pascal string, on stdout.
+*/
+void printpascalstring (s)
+ char *s;
+{
+ fprint_pascal_string (s, stdout);
+}
+
+/* Ditto, for stderr.
+*/
+void errprintpascalstring (s)
+ char *s;
+{
+ fprint_pascal_string (s, stderr);
+}
+
+/* Read an integer from the file F, reading past the subsequent end of
+ line.
+*/
+integer inputint (f)
+ text f;
+{
+ char buffer[50]; /* Long enough for anything reasonable. */
+
+ return
+ fgets (buffer, sizeof (buffer), *f)
+ ? atoi (buffer)
+ : 0;
+}
+
+/* Read three integers from stdin.
+*/
+void zinput3ints (a,b,c)
+ integer *a, *b, *c;
+{
+ while (scanf ("%ld %ld %ld\n", a, b, c) != 3)
+ (void) fprintf (stderr, "Please enter three integers.\n");
+}
+
+