summaryrefslogtreecommitdiff
path: root/Build/source/texk/dtl/dt2dv.c
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
committerKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
commit487ca4806cc046076293cf6cc5fbba0db282bac7 (patch)
tree847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/dtl/dt2dv.c
parenta3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff)
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dtl/dt2dv.c')
-rw-r--r--Build/source/texk/dtl/dt2dv.c2868
1 files changed, 2868 insertions, 0 deletions
diff --git a/Build/source/texk/dtl/dt2dv.c b/Build/source/texk/dtl/dt2dv.c
new file mode 100644
index 00000000000..4d45ad4f709
--- /dev/null
+++ b/Build/source/texk/dtl/dt2dv.c
@@ -0,0 +1,2868 @@
+/* dt2dv - convert human-readable "DTL" file to DVI format
+ - this is intended to invert dv2dt version 0.6.0
+ - version 0.6.1 - 14:38 GMT +11 Thu 9 March 1995
+ - Geoffrey Tobin G.Tobin@ee.latrobe.edu.au
+ - fixes: Michal Tomczak-Jaegermann ntomczak@vm.ucs.ualberta.ca
+ Nelson H. F. Beebe beebe@math.utah.edu
+ - Reference: "The DVI Driver Standard, Level 0",
+ by The TUG DVI Driver Standards Committee.
+ Appendix A, "Device-Independent File Format".
+*/
+
+/* unix version; read from stdin, write to stdout, by default. */
+
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef KPATHSEA
+#include <kpathsea/c-fopen.h>
+#endif
+
+#include "dtl.h"
+
+/* by default, read and write regular files */
+int rd_stdin = 0;
+int wr_stdout = 0;
+
+/* maximum number of characters in a DTL input line */
+#define MAXLINE 1024
+
+/* input line */
+typedef struct
+{
+ COUNT num; /* current line number */
+ size_t max; /* capacity of buf */
+ S4 wrote; /* number of characters written into buf */
+ size_t read; /* position in buf of next character to read from buf */
+ char * buf; /* line buffer */
+} Line;
+
+char linebuf[MAXLINE+1];
+
+Line dtl_line = {0, 0, 0, MAXLINE, linebuf};
+
+/* a DTL token either is:
+ a quoted string (admitting an escape character),
+ or BCOM (if that is a nonempty string),
+ or ECOM (if that is a nonempty string),
+ or a string _not_ including ECOM_CHAR or space.
+*/
+
+/* maximum expected length of a DTL token */
+#define MAXTOKLEN 255
+typedef char Token[MAXTOKLEN+1];
+
+typedef unsigned char Byte;
+typedef char Boolean;
+
+#ifndef true
+#define true 1
+#endif
+#ifndef false
+#define false 0
+#endif
+
+/* command prefixes */
+typedef struct
+{
+ Byte first_code;
+ char * name;
+ Boolean has_suffix;
+ Byte first_suffix, last_suffix;
+} CmdPrefix;
+
+CmdPrefix cmd_prefixes [] =
+{
+ {0, SETCHAR, true, 0, 127},
+ {128, SET, true, 1, 4},
+ {132, SETRULE, false, 0, 0},
+ {133, PUT, true, 1, 4},
+ {137, PUTRULE, false, 0, 0},
+ {138, NOP, false, 0, 0},
+ {139, BOP, false, 0, 0},
+ {140, EOP, false, 0, 0},
+ {141, PUSH, false, 0, 0},
+ {142, POP, false, 0, 0},
+ {143, RIGHT, true, 1, 4},
+ {147, W, true, 0, 4},
+ {152, X, true, 0, 4},
+ {157, DOWN, true, 1, 4},
+ {161, Y, true, 0, 4},
+ {166, Z, true, 0, 4},
+ {171, FONTNUM, true, 0, 63},
+ {235, FONT, true, 1, 4},
+ {239, SPECIAL, true, 1, 4},
+ {243, FONTDEF, true, 1, 4},
+ {247, PRE, false, 0, 0},
+ {248, POST, false, 0, 0},
+ {249, POSTPOST, false, 0, 0},
+ {250, OPCODE, true, 250, 255}
+};
+/* cmd_prefixes[] */
+
+/* Number of DVI commands, including those officially undefined */
+#define NCMDS 256
+
+/* table of command name (string) pointers */
+typedef char * CmdTable [NCMDS];
+
+/* initially all command name pointers are NULL */
+CmdTable cmd_table;
+
+/* operation's opcode, name, number of args, string of arguments. */
+typedef struct
+{
+ int code;
+ char * name;
+ int nargs;
+ char * args;
+} op_info;
+
+/* name of table, first opcode, last opcode, pointer to opcode info. */
+typedef struct
+{
+ char * name;
+ int first;
+ int last;
+ op_info * list;
+} op_table;
+
+/* Table for opcodes 128 to 170 inclusive. */
+
+op_info op_info_128_170 [] =
+{
+ {128, SET1, 1, "1"},
+ {129, SET2, 1, "2"},
+ {130, SET3, 1, "3"},
+ {131, SET4, 1, "-4"},
+ {132, SETRULE, 2, "-4 -4"},
+ {133, PUT1, 1, "1"},
+ {134, PUT2, 1, "2"},
+ {135, PUT3, 1, "3"},
+ {136, PUT4, 1, "-4"},
+ {137, PUTRULE, 2, "-4 -4"},
+ {138, NOP, 0, ""},
+ /* bop: not counting last argument, a signed address: */
+ {139, BOP, 10, "-4 -4 -4 -4 -4 -4 -4 -4 -4 -4"},
+ {140, EOP, 0, ""},
+ {141, PUSH, 0, ""},
+ {142, POP, 0, ""},
+ {143, RIGHT1, 1, "-1"},
+ {144, RIGHT2, 1, "-2"},
+ {145, RIGHT3, 1, "-3"},
+ {146, RIGHT4, 1, "-4"},
+ {147, W0, 0, ""},
+ {148, W1, 1, "-1"},
+ {149, W2, 1, "-2"},
+ {150, W3, 1, "-3"},
+ {151, W4, 1, "-4"},
+ {152, X0, 0, ""},
+ {153, X1, 1, "-1"},
+ {154, X2, 1, "-2"},
+ {155, X3, 1, "-3"},
+ {156, X4, 1, "-4"},
+ {157, DOWN1, 1, "-1"},
+ {158, DOWN2, 1, "-2"},
+ {159, DOWN3, 1, "-3"},
+ {160, DOWN4, 1, "-4"},
+ {161, Y0, 0, ""},
+ {162, Y1, 1, "-1"},
+ {163, Y2, 1, "-2"},
+ {164, Y3, 1, "-3"},
+ {165, Y4, 1, "-4"},
+ {166, Z0, 0, ""},
+ {167, Z1, 1, "-1"},
+ {168, Z2, 1, "-2"},
+ {169, Z3, 1, "-3"},
+ {170, Z4, 1, "-4"}
+};
+/* op_info op_info_128_170 [] */
+
+op_table op_128_170 = {"op_128_170", 128, 170, op_info_128_170};
+
+/* Table for fnt1 to fnt4 (opcodes 235 to 238) inclusive. */
+
+op_info fnt_n [] =
+{
+ {235, FONT1, 1, "1"},
+ {236, FONT2, 1, "2"},
+ {237, FONT3, 1, "3"},
+ {238, FONT4, 1, "-4"}
+};
+/* op_info fnt_n [] */
+
+op_table fnt = {FONT, 235, 238, fnt_n};
+
+
+/* Function prototypes */
+
+Void mem_viol ARGS((int sig));
+Void give_help (VOID);
+int parse ARGS((char * s));
+Void process ARGS((char * s));
+
+Void no_op (VOID);
+Void dtl_stdin (VOID);
+Void dvi_stdout (VOID);
+
+int open_dtl ARGS((char * dtl_file, FILE ** pdtl));
+int open_dvi ARGS((char * dvi_file, FILE ** pdvi));
+
+int dt2dv ARGS((FILE * dtl, FILE * dvi));
+
+Void * gmalloc ARGS((long int size));
+
+Void dinfo (VOID);
+Void dexit ARGS((int n));
+
+int cons_cmds ARGS((int nprefixes, CmdPrefix * prefix, CmdTable cmds));
+Void free_cmds ARGS((CmdTable cmd_table));
+
+int get_line ARGS((FILE * fp, Line * line, int max));
+int read_line_char ARGS((FILE * fp, int * ch));
+int read_char ARGS((FILE * fp, int * ch));
+int unread_char (VOID);
+int read_string_char ARGS((FILE * fp, int * ch));
+
+COUNT read_variety ARGS((FILE * dtl));
+COUNT read_token ARGS((FILE * dtl, char * token));
+COUNT skip_space ARGS((FILE * fp, int * ch));
+COUNT read_misc ARGS((FILE * fp, Token token));
+COUNT read_mes ARGS((FILE * fp, char * token));
+
+int find_command ARGS((char * command, int * opcode));
+int xfer_args ARGS((FILE * dtl, FILE * dvi, int opcode));
+
+int set_seq ARGS((FILE * dtl, FILE * dvi));
+
+int check_byte ARGS((int byte));
+int put_byte ARGS((int onebyte, FILE * dvi));
+
+U4 xfer_hex ARGS((int n, FILE * dtl, FILE * dvi));
+U4 xfer_oct ARGS((int n, FILE * dtl, FILE * dvi));
+U4 xfer_unsigned ARGS((int n, FILE * dtl, FILE * dvi));
+S4 xfer_signed ARGS((int n, FILE * dtl, FILE * dvi));
+
+int check_bmes ARGS((FILE * dtl));
+int check_emes ARGS((FILE * dtl));
+
+Void init_Lstring ARGS((Lstring * lsp, long int n));
+Void de_init_Lstring ARGS((Lstring * lsp));
+Lstring * alloc_Lstring ARGS((long int n));
+Void free_Lstring ARGS((Lstring * lstr));
+Void ls_putb ARGS((int ch, Lstring * lstr));
+
+S4 get_Lstring ARGS((FILE * dtl, Lstring * lstr));
+Void put_Lstring ARGS((const Lstring * lstr, FILE * dvi));
+U4 xfer_len_string ARGS((int n, FILE * dtl, FILE * dvi));
+
+U4 get_unsigned ARGS((FILE * dtl));
+S4 get_signed ARGS((FILE * dtl));
+
+int put_unsigned ARGS((int n, U4 unum, FILE * dvi));
+int put_signed ARGS((int n, S4 snum, FILE * dvi));
+
+S4 xfer_bop_address ARGS((FILE * dtl, FILE * dvi));
+S4 xfer_postamble_address ARGS((FILE * dtl, FILE * dvi));
+
+int put_table ARGS((op_table table, int opcode, FILE * dtl, FILE * dvi));
+
+U4 special ARGS((FILE * dtl, FILE * dvi, int n));
+int fontdef ARGS((FILE * dtl, FILE * dvi, int n));
+
+U4 preamble ARGS((FILE * dtl, FILE * dvi));
+int postamble ARGS((FILE * dtl, FILE * dvi));
+int post_post ARGS((FILE * dtl, FILE * dvi));
+
+
+typedef struct
+{
+ char * keyword; /* command line option keyword */
+ int * p_var; /* pointer to option variable */
+ char * desc; /* description of keyword and value */
+ Void (* p_fn) (VOID); /* pointer to function called when option is set */
+} Options;
+
+Options opts[] =
+{
+ {"-debug", &debug, "detailed debugging", no_op},
+ {"-group", &group, "each DTL command is in parentheses", no_op},
+ {"-si", &rd_stdin, "read all DTL commands from standard input", dtl_stdin},
+ {"-so", &wr_stdout, "write all DVI commands to standard output", dvi_stdout},
+ {NULL, NULL, NULL, NULL}
+};
+/* opts[] */
+
+char * progname = ""; /* intended for name of this program */
+int nfile = 0; /* number of filename arguments on the command line */
+
+#define PRINT_PROGNAME fprintf (stderr, "%s ", progname)
+
+/* Harbison & Steele (1991) warn that some C implementations */
+/* of free() do not treat NULL pointers correctly. */
+#define gfree(p) {if (p) free (p);}
+
+
+FILE * dtl_fp = NULL;
+FILE * dvi_fp = NULL;
+
+char * dtl_filename = "";
+char * dvi_filename = "";
+
+
+int
+main
+#ifdef STDC
+ (int argc, char * argv[])
+#else
+ (argc, argv)
+ int argc;
+ char * argv[];
+#endif
+{
+#ifndef WIN32
+ Void (*handler) ARGS((int)); /* Previous signal handler */
+#endif
+ int i;
+
+ progname = argv[0]; /* name of this program */
+
+ /* memory violation signal handler */
+ /* Not supported under Win32 */
+#ifndef WIN32
+ handler = (Void (*) ARGS((int))) signal (SIGSEGV, mem_viol);
+#endif
+
+#ifndef __DATE__
+#define __DATE__ ""
+#endif
+
+#ifndef __TIME__
+#define __TIME__ ""
+#endif
+
+#if STDC
+#define C_LEVEL ""
+#else /* NOT STDC */
+#define C_LEVEL "non-"
+#endif /* NOT STDC */
+
+ /* message about program and compiler */
+ /* NB: LTU EE's Sun/OS library is BSD, even though gcc 2.2.2 is ANSI */
+
+ fprintf (stderr, "\n");
+ fprintf (stderr,
+ "Program \"%s\" version %s compiled %s %s in %sstandard C.\n",
+ progname, VERSION, __DATE__, __TIME__, C_LEVEL);
+
+ /* interpret command line arguments */
+
+ nfile = 0;
+ dtl_fp = dvi_fp = NULL;
+ dtl_filename = dvi_filename = "";
+
+ for (i=1; i < argc; i++)
+ {
+ /* parse options, followed by any explicit filenames */
+ parse (argv[i]);
+ }
+
+ if (nfile != 2) /* not exactly two files specified, so give help */
+ give_help();
+ else
+ /* the real works */
+ dt2dv (dtl_fp, dvi_fp);
+
+ return 0; /* OK */
+}
+/* end main */
+
+#ifndef WIN32
+Void
+mem_viol
+#ifdef STDC
+ (int sig)
+#else
+ (sig)
+ int sig;
+#endif
+{
+ Void (* handler) ARGS((int));
+ handler = (Void (*) ARGS((int))) signal (SIGSEGV, mem_viol);
+ if (sig != SIGSEGV)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(mem_viol) : called with wrong signal!\n");
+ }
+ PRINT_PROGNAME;
+ fprintf (stderr, "(mem_viol) : RUNTIME MEMORY ERROR : memory violation, ");
+ fprintf (stderr, "dtl line >= ");
+ fprintf (stderr, WF, dtl_line.num);
+ fprintf (stderr, "\n");
+ dexit (1);
+}
+/* mem_viol */
+#endif
+
+Void
+give_help (VOID)
+{
+ int i;
+ char * keyword;
+ fprintf (stderr, "usage: ");
+ PRINT_PROGNAME;
+ fprintf (stderr, "[options] dtl_file dvi_file");
+ fprintf (stderr, "\n");
+ for (i=0; (keyword = opts[i].keyword) != NULL; i++)
+ {
+ fprintf (stderr, " ");
+ fprintf (stderr, "[%s]", keyword);
+ fprintf (stderr, " ");
+ fprintf (stderr, "%s", opts[i].desc);
+ fprintf (stderr, "\n");
+ }
+ fprintf (stderr, "Messages, like this one, go to stderr.\n");
+}
+/* give_help */
+
+
+Void no_op (VOID)
+/* do nothing */
+{
+}
+
+Void dtl_stdin (VOID)
+{
+ extern FILE * dtl_fp;
+ extern int nfile;
+
+ dtl_fp = stdin;
+ dtl_filename = "Standard Input";
+ ++ nfile;
+}
+
+Void dvi_stdout (VOID)
+{
+ extern FILE * dvi_fp;
+ extern int nfile;
+
+ /* ! Perilous to monitors! */
+ dvi_fp = stdout;
+ dvi_filename = "Standard Output";
+ ++ nfile;
+ if (!isatty(fileno(dvi_fp)))
+ SET_BINARY(fileno(dvi_fp));
+}
+
+
+int
+parse
+#ifdef STDC
+ (char * s)
+#else
+ (s)
+ char * s;
+#endif
+/* parse one command-line argument, `s' */
+{
+ int i;
+ char * keyword;
+ for (i=0; (keyword = opts[i].keyword) != NULL; i++)
+ {
+ if (strncmp (s, keyword, strlen (keyword)) == 0)
+ {
+ Void (*pfn) (VOID);
+ (*(opts[i].p_var)) = 1; /* turn option on */
+ if ((pfn = opts[i].p_fn) != NULL)
+ (*pfn) (); /* call option function */
+ return i;
+ }
+ }
+ /* reached here, so not an option: assume it's a filename */
+ process (s);
+ return i;
+}
+/* parse */
+
+
+int
+open_dtl
+#ifdef STDC
+ (char * dtl_file, FILE ** pdtl)
+#else
+ (dtl_file, pdtl)
+ char * dtl_file;
+ FILE ** pdtl;
+#endif
+/* I: dtl_file; I: pdtl; O: *pdtl. */
+{
+ extern char * dtl_filename;
+
+ dtl_filename = dtl_file;
+
+ if (dtl_filename == NULL)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(open_dtl) : INTERNAL ERROR : dtl file's name is NULL.\n");
+ dexit (1);
+ }
+
+ if (pdtl == NULL)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(open_dtl) : INTERNAL ERROR : address of dtl variable is NULL.\n");
+ dexit (1);
+ }
+
+ *pdtl = fopen (dtl_file, "r");
+
+ if (*pdtl == NULL)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(open_dtl) : DTL FILE ERROR : Cannot open \"%s\" for text reading.\n",
+ dtl_file);
+ dexit (1);
+ }
+
+ return 1; /* OK */
+}
+/* open_dtl */
+
+
+int
+open_dvi
+#ifdef STDC
+ (char * dvi_file, FILE ** pdvi)
+#else
+ (dvi_file, pdvi)
+ char * dvi_file;
+ FILE ** pdvi;
+#endif
+/* I: dvi_file; I: pdvi; O: *pdvi. */
+{
+ extern char * dvi_filename;
+
+ dvi_filename = dvi_file;
+
+ if (dvi_filename == NULL)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(open_dvi) : INTERNAL ERROR : dvi file's name is NULL.\n");
+ dexit (1);
+ }
+
+ if (pdvi == NULL)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(open_dvi) : INTERNAL ERROR : address of dvi variable is NULL.\n");
+ dexit (1);
+ }
+
+ *pdvi = fopen (dvi_file, "wb");
+
+ if (*pdvi == NULL)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(open_dvi) : DVI FILE ERROR : Cannot open \"%s\" for binary writing.\n",
+ dvi_file);
+ dexit (1);
+ }
+
+ return 1; /* OK */
+}
+/* open_dvi */
+
+
+Void
+process
+#ifdef STDC
+ (char * s)
+#else
+ (s)
+ char * s;
+#endif
+{
+ extern FILE * dtl_fp, * dvi_fp;
+ extern int nfile;
+ if (dtl_fp == NULL) /* first filename assumed to be DTL input */
+ {
+ open_dtl (s, &dtl_fp);
+ }
+ else if (dvi_fp == NULL) /* second filename assumed to be DVI output */
+ {
+ open_dvi (s, &dvi_fp);
+ }
+ else
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(process) : at most two filenames allowed.\n");
+ exit (1);
+ }
+ ++ nfile;
+}
+/* process */
+
+
+COUNT dtl_read = 0; /* bytes read from dtl file */
+COUNT dvi_written = 0; /* bytes written to dvi file */
+word_t last_bop_address = -1; /* byte address of last bop; first bop uses -1 */
+word_t postamble_address = -1; /* byte address of postamble */
+COUNT ncom = 0; /* commands successfully read and interpreted from dtl file */
+COUNT com_read = 0; /* bytes read in current (command and arguments), */
+ /* since and including the opening BCOM_CHAR, if any */
+
+
+int
+put_byte
+#ifdef STDC
+ (int byte, FILE * dvi)
+#else
+ (byte, dvi)
+ int byte;
+ FILE * dvi;
+#endif
+/* write byte into dvi file */
+{
+ check_byte (byte);
+/* if (fprintf (dvi, "%c", byte) != 1) */
+ if (fprintf (dvi, "%c", byte) < 0)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(put_byte) : DVI FILE ERROR (%s) : cannot write to dvi file.\n",
+ dtl_filename);
+ dexit (1);
+ }
+ ++ dvi_written;
+ return 1; /* OK */
+}
+/* put_byte */
+
+
+int
+dt2dv
+#ifdef STDC
+ (FILE * dtl, FILE * dvi)
+#else
+ (dtl, dvi)
+ FILE * dtl;
+ FILE * dvi;
+#endif
+{
+ int nprefixes = 0; /* number of prefixes in cmd_prefixes[] list. */
+ static Token dtl_cmd = ""; /* DTL command name */
+ COUNT nread = 0; /* number of bytes read by a function from dtl file. */
+
+ nprefixes = sizeof (cmd_prefixes) / sizeof (CmdPrefix);
+
+ /* Construct array of all NCMDS == 256 DTL commands */
+
+ (Void) cons_cmds (nprefixes, cmd_prefixes, cmd_table);
+
+ /* DTL commands have the form "[ ]*command arg ... arg[ ]*", */
+ /* possibly enclosed in a BCOM, ECOM pair, */
+ /* and are separated by optional whitespace, typically newlines. */
+ /* That is, each command and its arguments are parenthesised, */
+ /* with optional spaces after the BCOM and before the ECOM, if any. */
+
+ /* dt2dv is now at the very start of the DTL file */
+
+ dtl_line.num = 0;
+ dtl_read = 0;
+
+ /* The very first thing should be the "variety" signature */
+
+ nread = read_variety (dtl);
+
+ /* while not end of dtl file or reading error, */
+ /* read, interpret, and write commands */
+
+ while (!feof (dtl))
+ {
+ int opcode;
+
+ com_read = 0;
+
+ if (group)
+ {
+ /* BCOM check */
+ static Token token = ""; /* DTL token */
+ nread = read_token (dtl, token);
+ /* test for end of input, or reading error */
+ if (strlen (token) == 0)
+ {
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(dt2dv) : end of input, or reading error.\n");
+ }
+ break;
+ }
+ /* test whether this command begins correctly */
+ else if (strcmp (token, BCOM) != 0)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(dt2dv) : DTL FILE ERROR (%s) : ", dtl_filename);
+ fprintf (stderr, "command must begin with \"%s\", ", BCOM);
+ fprintf (stderr, "not `%c' (char %d).\n", token[0], token[0]);
+ dexit (1);
+ }
+ /* end BCOM check */
+ }
+
+ /* read the command name */
+ nread = read_token (dtl, dtl_cmd);
+ /* test for end of input, or reading error */
+ if (strlen (dtl_cmd) == 0)
+ {
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(dt2dv) : end of input, or reading error.\n");
+ }
+ break;
+ }
+ else
+ {
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(dt2dv) : command ");
+ fprintf (stderr, WF, ncom);
+ fprintf (stderr, " = \"%s\".\n", dtl_cmd);
+ }
+
+ /* find opcode for this command */
+ if (find_command (dtl_cmd, &opcode) == 1)
+ {
+ /* write the opcode, if we can */
+ put_byte (opcode, dvi);
+
+ /* treat the arguments, if any */
+ xfer_args (dtl, dvi, opcode);
+ }
+ else if (dtl_cmd[0] == BSEQ_CHAR)
+ {
+ /* sequence of font characters for SETCHAR */
+ set_seq (dtl, dvi);
+ }
+ else
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(dt2dv) : DTL FILE ERROR (%s) : unknown command \"%s\".\n",
+ dtl_filename, dtl_cmd);
+ dexit (1);
+ }
+ }
+
+ if (group)
+ {
+ /* seek ECOM after command's last argument and optional whitespace */
+ static Token token = ""; /* DTL token */
+ nread = read_token (dtl, token);
+ /* test for end of input, or reading error */
+ if (strlen (token) == 0)
+ {
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(dt2dv) : end of input, or reading error.\n");
+ }
+ break;
+ }
+ if (strcmp (token, ECOM) != 0)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(dt2dv) : DTL FILE ERROR (%s) : ", dtl_filename);
+ fprintf (stderr, "ECOM (\"%s\") expected, not `%c' (char %d).\n",
+ ECOM, token[0], token[0]);
+ dexit (1);
+ }
+ /* end ECOM check */
+ }
+
+ ++ ncom; /* one more command successfully read and interpreted */
+ }
+ /* end while */
+
+ PRINT_PROGNAME;
+ fprintf (stderr, "(dt2dv) :\n");
+ fprintf (stderr, "Read (from file \"%s\") ", dtl_filename);
+ fprintf (stderr, WF, dtl_read);
+ fprintf (stderr, " DTL bytes (");
+ fprintf (stderr, UF4, dtl_line.num);
+ fprintf (stderr, " lines);\n");
+ fprintf (stderr, "wrote (to file \"%s\") ", dvi_filename);
+ fprintf (stderr, WF, dvi_written);
+ fprintf (stderr, " DVI bytes;\n");
+ fprintf (stderr, "completely interpreted ");
+ fprintf (stderr, WF, ncom);
+ fprintf (stderr, " DVI command%s.\n", (ncom == 1 ? "" : "s"));
+ fprintf (stderr, "\n");
+
+ (Void) free_cmds (cmd_table);
+
+ return 1; /* OK */
+}
+/* dt2dv */
+
+
+Void *
+gmalloc
+#ifdef STDC
+ (long int size)
+#else
+ (size)
+ long int size;
+#endif
+{
+ Void * p = NULL;
+ if (size < 1)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(gmalloc) : INTERNAL ERROR : ");
+ fprintf (stderr,
+ "unreasonable request to malloc %ld bytes\n",
+ size);
+ dexit (1);
+ }
+ p = (Void *) malloc ((size_t) size);
+ if (p == NULL)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(gmalloc) : MEMORY ALLOCATION ERROR : ");
+ fprintf (stderr,
+ "operating system failed to malloc %ld bytes\n",
+ size);
+ dexit (1);
+ }
+ return (p);
+}
+/* gmalloc */
+
+
+Void
+dinfo (VOID)
+{
+ PRINT_PROGNAME;
+ fprintf (stderr, "(dinfo) : ");
+ fprintf (stderr, "Current DTL input line ");
+ fprintf (stderr, UF4, dtl_line.num);
+ fprintf (stderr, " :\n");
+ fprintf (stderr, "\"%s\"\n", dtl_line.buf);
+ fprintf (stderr, "Read ");
+ fprintf (stderr, WF, dtl_read);
+ fprintf (stderr, " DTL bytes (");
+ fprintf (stderr, WF, com_read);
+ fprintf (stderr, " in current command), wrote ");
+ fprintf (stderr, WF, dvi_written);
+ fprintf (stderr, " DVI bytes.\n");
+ fprintf (stderr, "Successfully interpreted ");
+ fprintf (stderr, WF, ncom);
+ fprintf (stderr, " DVI command%s.\n", (ncom == 1 ? "" : "s"));
+}
+/* dinfo */
+
+
+Void
+dexit
+#ifdef STDC
+ (int n)
+#else
+ (n)
+ int n;
+#endif
+{
+ dinfo();
+ PRINT_PROGNAME;
+ fprintf (stderr, "(dexit) : exiting with status %d.\n", n);
+ exit (n);
+}
+/* dexit */
+
+
+int
+cons_cmds
+#ifdef STDC
+ (int nprefixes, CmdPrefix * prefix, CmdTable cmds)
+#else
+ (nprefixes, prefix, cmds)
+ int nprefixes;
+ CmdPrefix * prefix;
+ CmdTable cmds;
+#endif
+{
+ int code; /* first opcode for a given command prefix */
+ int opcode; /* command's opcode */
+ int nsuffixes; /* number of commands with a given prefix */
+ int isuffix; /**** integer suffix, of at most three digits ****/
+ String suffix; /* suffix string generated from integer suffix */
+ size_t plen = 0; /* prefix length */
+ size_t slen; /* suffix length */
+ size_t clen; /* whole command name length */
+ int i, j; /* loop indices */
+
+ for (i=0; i < nprefixes; prefix++, i++)
+ {
+ code = prefix->first_code;
+ if (code < 0 || code > 255)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(cons_cmds) : INTERNAL ERROR : ");
+ fprintf (stderr,
+ "prefix listed internally with code = %d, must be 0 to 255\n",
+ code);
+ dexit (1);
+ }
+ if (prefix->has_suffix)
+ {
+ plen = strlen (prefix->name);
+ /**** Suffixes in DTL are Integers, in Sequence */
+ if (prefix->last_suffix < prefix->first_suffix)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(cons_cmds) : INTERNAL ERROR : ");
+ fprintf (stderr,
+ "prefix's last suffix %d < first suffix (%d)\n",
+ prefix->last_suffix, prefix->first_suffix);
+ dexit (1);
+ }
+ nsuffixes = prefix->last_suffix - prefix->first_suffix + 1;
+ opcode = prefix->first_code;
+ for (j=0; j < nsuffixes; j++, opcode++)
+ {
+ isuffix = prefix->first_suffix + j;
+ if (0 <= code && code <= 127) /* SETCHAR */
+ {
+ /* SETCHAR's suffix is written in uppercase hexadecimal */
+ sprintf (suffix, "%02X", isuffix);
+ }
+ else /* 128 <= code && code <= 255 */ /* other DTL commands */
+ {
+ /* other commands' suffices are written in decimal */
+ sprintf (suffix, "%d", isuffix);
+ }
+ slen = strlen (suffix);
+ clen = plen + slen;
+ cmds[opcode] = (char *) gmalloc (clen+1);
+ strcpy (cmds[opcode], prefix->name);
+ strcat (cmds[opcode], suffix);
+ }
+ }
+ else /* command name = prefix */
+ {
+ plen = strlen (prefix->name);
+ clen = plen;
+ opcode = prefix->first_code;
+ cmds[opcode] = (char *) gmalloc (clen+1);
+ strcpy (cmds[opcode], prefix->name);
+ }
+ }
+
+ return 1; /* OK */
+}
+/* cons_cmds */
+
+
+Void
+free_cmds
+#ifdef STDC
+ (CmdTable cmd_table)
+#else
+ (cmd_table)
+ CmdTable cmd_table;
+#endif
+{
+ int i;
+ for (i=0; i < NCMDS; i++)
+ gfree (cmd_table[i]);
+}
+/* free_cmds */
+
+
+int
+get_line
+#ifdef STDC
+ (FILE * fp, Line * line, int max)
+#else
+ (fp, line, max)
+ FILE * fp;
+ Line * line;
+ int max;
+#endif
+/* read a (Line *) line from fp, return length */
+/* adapted from K&R (second, alias ANSI C, edition, 1988), page 165 */
+{
+ if (fgets (line->buf, max, fp) == NULL)
+ return 0;
+ else
+ {
+ ++ line->num;
+ line->wrote = strlen (line->buf);
+ line->read = 0;
+ return 1;
+ }
+}
+/* get_line */
+
+
+int
+read_line_char
+#ifdef STDC
+ (FILE * fp, int * ch)
+#else
+ (fp, ch)
+ FILE * fp;
+ int * ch;
+#endif
+/* read one character from dtl_line if possible, */
+/* otherwise read another dtl_line from fp */
+/* return 1 if a character is read, 0 if at end of fp file */
+{
+ extern Line dtl_line;
+ if (dtl_line.wrote == 0 || dtl_line.read >= dtl_line.wrote)
+ {
+ int line_status;
+ /* refill line buffer */
+ line_status = get_line (fp, &dtl_line, MAXLINE);
+ if (line_status == 0)
+ {
+ /* at end of DTL file */
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(read_line_char) : end of DTL file\n");
+ dinfo();
+ }
+ return 0;
+ }
+ else
+ {
+ /* new DTL line was read */
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(read_line_char) : new DTL input line:\n");
+ fprintf (stderr, "\"%s\"\n", dtl_line.buf);
+ }
+ }
+ }
+ *ch = dtl_line.buf [dtl_line.read ++];
+ ++ dtl_read;
+ ++ com_read; /* count another DTL command character */
+ return 1;
+}
+/* read_line_char */
+
+
+int
+read_char
+#ifdef STDC
+ (FILE * fp, int * ch)
+#else
+ (fp, ch)
+ FILE * fp;
+ int * ch;
+#endif
+/* Read next character, if any, from file fp. */
+/* Write it into *ch. */
+/* If no character is read, then *ch value < 0. */
+/* Return 1 if OK, 0 if EOF or error. */
+{
+ int status = 1;
+ int c; /* in case ch points awry, we still have something in c. */
+
+ c = EOF;
+ if (read_line_char (fp, &c) == 0)
+ {
+ /* end of fp file, or error reading it */
+ status = 0;
+ }
+ else
+ {
+ if (c > 255)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(read_char) : character %d not in range 0 to 255\n",
+ c);
+ dinfo();
+ status = 0;
+ }
+ else if ( ! isprint (c) && ! isspace (c))
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(read_char) : character %d %s.\n",
+ c,
+ "not printable and not white space");
+ dinfo();
+ status = 0;
+ }
+ }
+ *ch = c;
+
+ return status;
+}
+/* read_char */
+
+
+COUNT
+read_variety
+#ifdef STDC
+ (FILE * dtl)
+#else
+ (dtl)
+ FILE * dtl;
+#endif
+/* read and check DTL variety signature */
+/* return number of DTL bytes written */
+/* DTL variety is _NEVER_ grouped by BCOM and ECOM. */
+/* Uniformity here enables the program easily to modify its behavior. */
+{
+ COUNT vread = 0; /* number of DTL bytes read by read_variety */
+ COUNT nread = 0; /* number of DTL bytes read by read_token */
+ static Token token = "";
+
+ /* read the DTL VARIETY keyword */
+ nread = read_token (dtl, token);
+ vread += nread;
+ /* test whether signature begins correctly */
+ if (strcmp (token, "variety") != 0)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(read_variety) : DTL FILE ERROR (%s) : ", dtl_filename);
+ fprintf (stderr, "DTL signature must begin with \"%s\", not \"%s\".\n",
+ "variety", token);
+ dexit (1);
+ }
+
+ /* read the DTL variety */
+ nread = read_token (dtl, token);
+ vread += nread;
+ /* test whether variety is correct */
+ if (strcmp (token, VARIETY) != 0)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(read_variety) : DTL FILE ERROR (%s) : ", dtl_filename);
+ fprintf (stderr, "DTL variety must be \"%s\", not \"%s\".\n",
+ VARIETY, token);
+ dexit (1);
+ }
+
+ PRINT_PROGNAME;
+ fprintf (stderr, "(read_variety) : DTL variety %s is OK.\n", VARIETY);
+
+ return vread; /* OK */
+}
+/* read_variety */
+
+
+COUNT
+skip_space
+#ifdef STDC
+ (FILE * fp, int * ch)
+#else
+ (fp, ch)
+ FILE * fp;
+ int * ch;
+#endif
+/* Skip whitespace characters in file fp. */
+/* Write in *ch the last character read from fp, */
+/* or < 0 if fp could not be read. */
+/* Return number of characters read from fp. */
+{
+ int c; /* character read (if any) */
+ COUNT count; /* number (0 or more) of whitespace characters read */
+ int nchar; /* number (0 or 1) of characters read by read_char */
+
+ /* loop ends at: end of fp file, or reading error, or not a white space */
+ for (count=0; ((nchar = read_char (fp, &c)) == 1 && isspace (c)); ++count)
+ {
+ /* otherwise, more white spaces to skip */
+ if (debug)
+ {
+ /* report when each DTL end of line is reached */
+ if (c == '\n')
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(skip_space) : ");
+ fprintf (stderr, "end of DTL line (at least) ");
+ fprintf (stderr, WF, dtl_line.num);
+ fprintf (stderr, "\n");
+ }
+ }
+ }
+
+ if (nchar == 0)
+ {
+ c = -1;
+ }
+
+ *ch = c; /* c will be < 0 if read_char could not read fp */
+ return (count + nchar);
+}
+/* skip_space */
+
+
+COUNT
+read_token
+#ifdef STDC
+ (FILE * dtl, char * token)
+#else
+ (dtl, token)
+ FILE * dtl;
+ char * token;
+#endif
+/* read next token from dtl file. */
+/* return number of DTL bytes read. */
+/* A token is one of:
+ a string from BMES_CHAR to the next unescaped EMES_CHAR, inclusive;
+ BCOM or ECOM, unless these are empty strings;
+ BSEQ or ESEQ;
+ any other sequence of non-whitespace characters.
+*/
+{
+ COUNT nread; /* number of DTL bytes read by read_token */
+ int ch; /* most recent character read */
+
+ nread = 0;
+
+ /* obtain first non-space character */
+ /* add to nread the number of characters read from dtl by skip_space */
+ nread += skip_space (dtl, &ch);
+
+ if (ch < 0)
+ {
+ /* end of dtl file */
+ /* write an empty token */
+ strcpy (token, "");
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(read_token) : end of dtl file.\n");
+ }
+ }
+ else if (group && ch == BCOM_CHAR)
+ {
+ strcpy (token, BCOM);
+ }
+ else if (group && ch == ECOM_CHAR)
+ {
+ strcpy (token, ECOM);
+ }
+ else
+ {
+ token[0] = ch;
+ token[1] = '\0';
+ if (ch == BMES_CHAR) /* string token; read until unescaped EMES_CHAR */
+ {
+ nread += read_mes (dtl, token+1);
+ }
+ else if (ch == BSEQ_CHAR || ch == ESEQ_CHAR)
+ {
+ /* token is complete */
+ }
+ else /* any other string not containing (ECOM_CHAR or) whitespace */
+ {
+ nread += read_misc (dtl, token+1);
+ }
+ }
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(read_token) : token = \"%s\"\n", token);
+ }
+
+ return (nread); /* number of bytes read from dtl file */
+}
+/* read_token */
+
+
+#define CHAR_OK 1
+#define CHAR_FAIL 0
+#define CHAR_EOS (-1)
+
+int
+read_string_char
+#ifdef STDC
+ (FILE * fp, int * ch)
+#else
+ (fp, ch)
+ FILE * fp;
+ int * ch;
+#endif
+{
+ int status = CHAR_OK; /* OK so far */
+ int c;
+
+ if (read_char (fp, &c) == 0)
+ status = CHAR_FAIL; /* fail */
+
+ if (c == EMES_CHAR) /* end-of-string char */
+ {
+ status = CHAR_EOS; /* end of string */
+ }
+ else if (c == ESC_CHAR) /* escape character */
+ {
+ /* accept the next character literally, even ESC_CHAR and EMES_CHAR */
+ if (read_char (fp, &c) == 0)
+ status = CHAR_FAIL; /* fail */
+ }
+
+ *ch = c;
+ return status;
+}
+/* read_string_char */
+
+
+COUNT
+read_misc
+#ifdef STDC
+ (FILE * fp, Token token)
+#else
+ (fp, token)
+ FILE * fp;
+ Token token;
+#endif
+{
+ int c;
+ int count;
+ /* loop ends at: end of fp file, or reading error, or a space */
+ for (count=0; count <= MAXTOKLEN; ++count)
+ {
+ if (read_char (fp, &c) == 0 || isspace (c))
+ break;
+ if (group && c == ECOM_CHAR)
+ {
+ (Void) unread_char ();
+ break;
+ }
+
+ token[count] = c;
+ }
+ token[count] = '\0';
+ return count;
+}
+/* read_misc */
+
+
+COUNT
+read_mes
+#ifdef STDC
+ (FILE * fp, char * token)
+#else
+ (fp, token)
+ FILE * fp;
+ char * token;
+#endif
+/* called **AFTER** a BMES_CHAR has been read */
+/* read file fp for characters up to next unescaped EMES_CHAR */
+/* this is called a "string token" */
+/* write string, including EMES_CHAR, into token[] */
+/* return number of characters read from fp */
+{
+ COUNT dtl_count; /* number of DTL characters read by read_mes from fp */
+ int more; /* flag more == 0 to terminate loop */
+ int escape; /* flag escape == 1 if previous character was ESC_CHAR */
+ int ch; /* current DTL character */
+
+ escape = 0;
+ more = 1;
+ dtl_count = 0;
+ while (more)
+ {
+ if (read_char (fp, &ch) == 0)
+ {
+ /* end of fp file, or reading error */
+ more = 0;
+ }
+ else /* error checking passed */
+ {
+ ++ dtl_count;
+ if (ch == EMES_CHAR && escape == 0) /* end of string */
+ {
+ /* include final EMES_CHAR */
+ * token ++ = ch;
+ more = 0;
+ }
+ else if (ch == ESC_CHAR && escape == 0)
+ {
+ /* next character is not end of string */
+ escape = 1;
+ }
+ else
+ {
+ /* store any other character, */
+ /* including escaped EMES_CHAR and ESC_CHAR*/
+ * token ++ = ch;
+ escape = 0;
+ }
+ }
+ }
+ * token = '\0';
+ return dtl_count;
+}
+/* read_mes */
+
+
+int
+unread_char (VOID)
+/* wind input back, to allow rereading of one character */
+/* return 1 if this works, 0 on error */
+{
+ extern Line dtl_line;
+ int status;
+ if (dtl_line.read > 0)
+ {
+ -- dtl_line.read; /* back up one character in dtl_line */
+ -- dtl_read; /* correct the count of DTL characters */
+ -- com_read; /* count another DTL command character */
+ status = 1; /* OK */
+ }
+ else /* current DTL line is empty */
+ {
+ status = 0; /* error */
+ }
+ return status;
+}
+/* unread_char */
+
+
+int
+find_command
+#ifdef STDC
+ (char * command, int * opcode)
+#else
+ (command, opcode)
+ char * command;
+ int * opcode;
+#endif
+{
+ int found;
+ int i;
+
+ found = 0;
+ for (i=0; i < NCMDS; i++)
+ {
+ if ((cmd_table[i] != 0) && (strcmp (command, cmd_table[i]) == 0))
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ *opcode = i;
+
+ return found;
+}
+/* find_command */
+
+
+int
+check_byte
+#ifdef STDC
+ (int byte)
+#else
+ (byte)
+ int byte;
+#endif
+{
+ if (byte < 0 || byte > 255)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(check_byte) : INTERNAL ERROR : ");
+ fprintf (stderr, "byte %d not in the range of 0 to 255.\n", byte);
+ dexit (1);
+ }
+ return 1; /* OK */
+}
+/* check_byte */
+
+
+int
+xfer_args
+#ifdef STDC
+ (FILE * dtl, FILE * dvi, int opcode)
+#else
+ (dtl, dvi, opcode)
+ FILE * dtl;
+ FILE * dvi;
+ int opcode;
+#endif
+{
+ int n;
+
+ if (opcode >= 0 && opcode <= 127)
+ ; /* SETCHAR uses no data */
+ else if (opcode >= 128 && opcode <= 170)
+ {
+ word_t this_bop_address = last_bop_address;
+
+ if (opcode == 139) /* BOP */
+ {
+ this_bop_address = dvi_written - 1;
+ }
+ put_table (op_128_170, opcode, dtl, dvi);
+ if (opcode == 139) /* BOP */
+ {
+ xfer_bop_address (dtl, dvi);
+ last_bop_address = this_bop_address;
+ }
+ }
+ else if (opcode >= 171 && opcode <= 234)
+ ; /* FONTNUM uses no data */
+ else if (opcode >= 235 && opcode <= 238)
+ put_table (fnt, opcode, dtl, dvi);
+ else if (opcode >= 239 && opcode <= 242)
+ {
+ n = opcode - 238;
+ special (dtl, dvi, n);
+ }
+ else if (opcode >= 243 && opcode <= 246)
+ {
+ n = opcode - 242;
+ fontdef (dtl, dvi, n);
+ }
+ else if (opcode == 247)
+ preamble (dtl, dvi);
+ else if (opcode == 248)
+ postamble (dtl, dvi);
+ else if (opcode == 249)
+ post_post (dtl, dvi);
+ else if (opcode >= 250 && opcode <= 255)
+ ; /* these, undefined, opcodes use no data */
+ else
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(xfer_args) : opcode %d not handled.\n",
+ opcode);
+ }
+
+ return 1; /* OK */
+}
+/* xfer_args */
+
+
+int
+set_seq
+#ifdef STDC
+ (FILE * dtl, FILE * dvi)
+#else
+ (dtl, dvi)
+ FILE * dtl;
+ FILE * dvi;
+#endif
+/* Called _after_ a BSEQ_CHAR command */
+/* Read bytes from dtl file, */
+/* writing corresponding SETCHAR or SET1 commands to DVI file, */
+/* _until_ unescaped ESEQ_CHAR is found */
+/* Return 1 if OK, 0 on error */
+/**** dt2dv assumes 8 bit characters, ****/
+/**** but some day one might change that. ****/
+{
+ int status = 1; /* status = 1 if OK, 0 if error */
+ int more; /* sequence of font characters continuing? */
+ int escape = 0; /* flag set if previous character was an escape */
+ int ch; /* character read from DTL file */
+ more = 1;
+ while (more)
+ {
+ /* ignore read_char status, to allow unprintable characters */
+ (Void) read_char (dtl, &ch);
+ /* but check for end of dtl file, or serious file reading error */
+ if (ch < 0)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(set_seq) : ");
+ fprintf (stderr, "end of dtl file, ");
+ fprintf (stderr, "or serious dtl file reading error\n");
+ dinfo();
+ more = 0;
+ status = 0; /* bad news */
+ }
+ else /* read dtl file, okay */
+ {
+ if (ch == ESC_CHAR && escape == 0) /* escape next character */
+ {
+ escape = 1;
+ }
+ else
+ {
+ if (ch == ESEQ_CHAR && escape == 0) /* end of sequence */
+ {
+ more = 0;
+ }
+ else if (ch <= 127) /* can use SETCHAR */
+ {
+ put_byte (ch, dvi);
+ }
+ else if (ch <= 255) /* can use SET1 */
+ {
+ put_byte (128, dvi); /* SET1 opcode */
+ put_unsigned (1, (U4) ch, dvi);
+ }
+ else
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(set_seq) : ");
+ fprintf (stderr,
+ "ERROR : DTL character %d is not in range 0 to 255\n",
+ ch);
+ dexit (1);
+ more = 0;
+ status = 0; /* Error, because dt2dv assumes 8 bit characters */
+ }
+ escape = 0; /* current ch is not an escape character */
+ }
+ }
+ }
+ return status;
+}
+/* set_seq */
+
+
+U4
+xfer_hex
+#ifdef STDC
+ (int n, FILE * dtl, FILE * dvi)
+#else
+ (n, dtl, dvi)
+ int n;
+ FILE * dtl;
+ FILE * dvi;
+#endif
+/* translate unsigned n-byte hexadecimal number from dtl to dvi file. */
+/* return value of hexadecimal number */
+{
+ U4 unum = 0; /* at most this space needed */
+ COUNT nread = 0; /* number of DTL bytes read by read_token */
+ int nconv = 0; /* number of arguments converted by sscanf */
+ static Token token = ""; /* DTL token */
+
+ if (n < 1 || n > 4)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(xfer_hex) : INTERNAL ERROR : asked for %d bytes. Must be 1 to 4.\n",
+ n);
+ dexit (1);
+ }
+
+ nread = read_token (dtl, token);
+
+ nconv = sscanf (token, XF4, &unum);
+
+ if (nconv < 1)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(xfer_hex) : DTL FILE ERROR (%s) : %s \"%s\".\n",
+ dtl_filename, "hexadecimal number expected, not", token);
+ dexit (1);
+ }
+
+ put_unsigned (n, unum, dvi);
+
+ return unum;
+}
+/* xfer_hex */
+
+
+U4
+xfer_oct
+#ifdef STDC
+ (int n, FILE * dtl, FILE * dvi)
+#else
+ (n, dtl, dvi)
+ int n;
+ FILE * dtl;
+ FILE * dvi;
+#endif
+/* translate unsigned n-byte octal number from dtl to dvi file. */
+/* return value of octal number */
+{
+ U4 unum = 0; /* at most this space needed */
+ COUNT nread = 0; /* number of DTL bytes read by read_token */
+ int nconv = 0; /* number of arguments converted by sscanf */
+ static Token token = ""; /* DTL token */
+
+ if (n < 1 || n > 4)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(xfer_oct) : INTERNAL ERROR : asked for %d bytes. Must be 1 to 4.\n",
+ n);
+ dexit (1);
+ }
+
+ nread = read_token (dtl, token);
+
+ nconv = sscanf (token, OF4, &unum);
+
+ if (nconv < 1)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(xfer_oct) : DTL FILE ERROR (%s) : %s \"%s\".\n",
+ dtl_filename, "octal number expected, not", token);
+ dexit (1);
+ }
+
+ put_unsigned (n, unum, dvi);
+
+ return unum;
+}
+/* xfer_oct */
+
+
+U4
+xfer_unsigned
+#ifdef STDC
+ (int n, FILE * dtl, FILE * dvi)
+#else
+ (n, dtl, dvi)
+ int n;
+ FILE * dtl;
+ FILE * dvi;
+#endif
+/* translate unsigned n-byte number from dtl to dvi file. */
+/* return value of unsigned number */
+{
+ U4 unum = 0; /* at most this space needed */
+
+ unum = get_unsigned (dtl);
+ put_unsigned (n, unum, dvi);
+
+ return unum;
+}
+/* xfer_unsigned */
+
+
+S4
+xfer_signed
+#ifdef STDC
+ (int n, FILE * dtl, FILE * dvi)
+#else
+ (n, dtl, dvi)
+ int n;
+ FILE * dtl;
+ FILE * dvi;
+#endif
+/* translate signed n-byte number from dtl to dvi file. */
+/* return value of signed number */
+{
+ S4 snum = 0;
+
+ snum = get_signed (dtl);
+ put_signed (n, snum, dvi);
+
+ return snum;
+}
+/* xfer_signed */
+
+
+U4
+get_unsigned
+#ifdef STDC
+ (FILE * dtl)
+#else
+ (dtl)
+ FILE * dtl;
+#endif
+/* read unsigned number from dtl file. */
+/* return value of unsigned number */
+{
+ U4 unum = 0; /* at most this space needed */
+ COUNT nread = 0; /* number of DTL bytes read by read_token */
+ int nconv = 0; /* number of arguments converted by sscanf */
+ static Token token = ""; /* DTL token */
+
+ nread = read_token (dtl, token);
+
+ nconv = sscanf (token, UF4, &unum);
+
+ if (nconv < 1)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(get_unsigned) : DTL FILE ERROR (%s) : %s \"%s\".\n",
+ dtl_filename, "unsigned number expected, not", token);
+ dexit (1);
+ }
+
+ return unum;
+}
+/* get_unsigned */
+
+
+S4
+get_signed
+#ifdef STDC
+ (FILE * dtl)
+#else
+ (dtl)
+ FILE * dtl;
+#endif
+/* read signed number from dtl file. */
+/* return value of signed number */
+{
+ S4 snum = 0;
+ COUNT nread = 0; /* number of DTL bytes read by read_token */
+ int nconv = 0; /* number of sscanf arguments converted and assigned */
+ static Token token = "";
+
+ nread = read_token (dtl, token);
+
+ nconv = sscanf (token, SF4, &snum);
+
+ if (nconv < 1)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(get_signed) : DTL FILE ERROR (%s) : %s \"%s\".\n",
+ dtl_filename, "signed number expected, not", token);
+ dexit (1);
+ }
+
+ return snum;
+}
+/* get_signed */
+
+
+int
+put_unsigned
+#ifdef STDC
+ (int n, U4 unum, FILE * dvi)
+#else
+ (n, unum, dvi)
+ int n;
+ U4 unum;
+ FILE * dvi;
+#endif
+/* put unsigned in-byte integer to dvi file */
+/* DVI format uses Big-endian storage of numbers: */
+/* most significant byte is first. */
+/* return number of bytes written. */
+{
+ Byte ubyte[4]; /* at most 4 bytes needed in DVI format */
+ int i;
+
+ if (n < 1 || n > 4)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(put_unsigned) : INTERNAL ERROR : asked for %d bytes. Must be 1 to 4.\n",
+ n);
+ dexit (1);
+ }
+
+ /* Big-endian storage. */
+ for (i = 0; i < n; i++)
+ {
+ ubyte[i] = (Byte) (unum % 256);
+ unum /= 256;
+ }
+ /* Reverse order for big-endian representation. */
+ for (i = n-1; i >= 0; i--)
+ {
+ put_byte ((int) ubyte[i], dvi);
+ }
+
+ return n;
+}
+/* put_unsigned */
+
+
+int
+put_signed
+#ifdef STDC
+ (int n, S4 snum, FILE * dvi)
+#else
+ (n, snum, dvi)
+ int n;
+ S4 snum;
+ FILE * dvi;
+#endif
+/* put signed in-byte integer to dvi file */
+/* DVI format uses 2's complement Big-endian storage of signed numbers: */
+/* most significant byte is first. */
+/* return number of bytes written. */
+{
+ /* Will this deal properly with the sign? */
+
+ if (n < 1 || n > 4)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(put_signed) : INTERNAL ERROR : asked for %d bytes. Must be 1 to 4.\n",
+ n);
+ dexit (1);
+ }
+
+ /* How do we ensure 2's complement representation? */
+ /* Here's a trick that I hope is portable, given ANSI C. */
+ /* See K&R (2nd edition), Appendix A6.2 "Integral Conversions". */
+
+ /* Convert snum to U4 data type */
+ put_unsigned (n, (U4) snum, dvi);
+
+ return n;
+}
+/* put_signed */
+
+
+int
+check_bmes
+#ifdef STDC
+ (FILE * dtl)
+#else
+ (dtl)
+ FILE * dtl;
+#endif
+/* check that a BMES_CHAR is the next non-whitespace character in dtl */
+{
+ int ch; /* next non-whitespace character in dtl */
+
+ /* `(Void)' because we ignore the number of spaces skipped */
+ (Void) skip_space (dtl, &ch);
+
+ if (ch < 0)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(check_bmes) : DTL FILE ERROR (%s) : ",
+ dtl_filename);
+ fprintf (stderr, "end of dtl file, or reading error\n");
+ dexit (1);
+ }
+
+ if (ch != BMES_CHAR)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(check_bmes) : DTL FILE ERROR (%s) : ",
+ dtl_filename);
+ fprintf (stderr, "BMES_CHAR (`%c') %s, not `%c' (char %d).\n",
+ BMES_CHAR, "expected before string", ch, ch);
+ dexit (1);
+ }
+
+ return 1; /* OK */
+}
+/* check_bmes */
+
+
+int
+check_emes
+#ifdef STDC
+ (FILE * dtl)
+#else
+ (dtl)
+ FILE * dtl;
+#endif
+/* check that an EMES_CHAR is the next character in dtl */
+{
+ int ch; /* dtl character */
+
+ if (read_char (dtl, &ch) == 0)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(check_emes) : DTL FILE ERROR (%s) : ",
+ dtl_filename);
+ fprintf (stderr, "end of dtl file, or reading error\n");
+ dexit (1);
+ }
+
+ if (ch != EMES_CHAR)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(check_emes) : DTL FILE ERROR (%s) : ",
+ dtl_filename);
+ fprintf (stderr, "EMES_CHAR (`%c') %s, not `%c' (char %d).\n",
+ EMES_CHAR, "expected to follow string", ch, ch);
+ dexit (1);
+ }
+
+ return 1; /* OK */
+}
+/* check_emes */
+
+
+/* Size typically used in this program for Lstring variables */
+#define LSIZE 1024
+
+
+Void
+init_Lstring
+#ifdef STDC
+ (Lstring * lsp, long int n)
+#else
+ (lsp, n)
+ Lstring * lsp;
+ long int n;
+#endif
+{
+ lsp->l = 0;
+ lsp->m = n;
+ lsp->s = (char *) gmalloc (n);
+}
+/* init_Lstring */
+
+
+Void
+de_init_Lstring
+#ifdef STDC
+ (Lstring * lsp)
+#else
+ (lsp)
+ Lstring * lsp;
+#endif
+{
+ lsp->l = 0;
+ lsp->m = 0;
+ free (lsp->s);
+ lsp->s = NULL; /* to be sure */
+}
+/* de_init_Lstring */
+
+
+Lstring *
+alloc_Lstring
+#ifdef STDC
+ (long int n)
+#else
+ (n)
+ long int n;
+#endif
+{
+ Lstring * lsp;
+ lsp = (Lstring *) gmalloc (sizeof (Lstring));
+ init_Lstring (lsp, n);
+ return (lsp);
+}
+/* alloc_Lstring */
+
+
+Void
+free_Lstring
+#ifdef STDC
+ (Lstring * lstr)
+#else
+ (lstr)
+ Lstring * lstr;
+#endif
+{
+ free (lstr->s);
+ free (lstr);
+}
+/* free_Lstring */
+
+
+Void
+ls_putb
+#ifdef STDC
+ (int ch, Lstring * lstr)
+#else
+ (ch, lstr)
+ int ch;
+ Lstring * lstr;
+#endif
+/* write byte ch into Lstring *lstr */
+{
+ if (lstr->l >= lstr->m)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(ls_putb) : ERROR : No more room in Lstring.\n");
+ dexit (1);
+ }
+ else
+ {
+ lstr->s [(lstr->l)++] = ch;
+ }
+}
+/* ls_putb */
+
+
+long int
+get_Lstring
+#ifdef STDC
+ (FILE * dtl, Lstring * lstr)
+#else
+ (dtl, lstr)
+ FILE * dtl;
+ Lstring * lstr;
+#endif
+/* get a string from dtl file, store as an Lstring in *lstr. */
+/* lstr must already be allocated and initialised. */
+/* return length of Lstring *lstr */
+{
+ U4 nch;
+ int char_status = CHAR_OK; /* OK so far */
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(get_Lstring) : entering get_Lstring.\n");
+ }
+
+ check_bmes (dtl);
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(get_Lstring) : string is: \"");
+ }
+
+ for (nch=0; ; nch++)
+ {
+ int ch;
+
+ char_status = read_string_char (dtl, &ch);
+
+ if (char_status == CHAR_FAIL)
+ {
+ /* end of dtl file, or reading error */
+ fprintf (stderr, "\n");
+ PRINT_PROGNAME;
+ fprintf (stderr, "(get_Lstring) : DTL FILE ERROR (%s) : ",
+ dtl_filename);
+ fprintf (stderr, "cannot read string[");
+ fprintf (stderr, UF4, nch);
+ fprintf (stderr, "] from dtl file.\n");
+ dexit (1);
+ }
+
+ if (debug)
+ {
+ fprintf (stderr, "%c", ch);
+ }
+
+ if (char_status == CHAR_EOS)
+ {
+ if (ch != EMES_CHAR)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(get_Lstring) : INTERNAL ERROR : ");
+ fprintf (stderr, "char_status = CHAR_FAIL,\n");
+ fprintf (stderr,
+ "but ch = %c (char %d) is not EMES_CHAR = %c (char %d)\n",
+ ch, ch, EMES_CHAR, EMES_CHAR);
+ dexit (1);
+ }
+ (Void) unread_char ();
+ break; /* end of string */
+ }
+ else if (char_status == CHAR_OK)
+ {
+ ls_putb (ch, lstr);
+ }
+ else
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(get_Lstring) : INTERNAL ERROR : ");
+ fprintf (stderr, "char_status = %d is unfamiliar!\n", char_status);
+ dexit (1);
+ }
+ }
+ /* end for */
+
+ if (debug)
+ {
+ fprintf (stderr, "\".\n");
+ }
+
+ check_emes (dtl);
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(get_Lstring) : leaving get_Lstring.\n");
+ }
+
+ return (lstr->l);
+}
+/* get_Lstring */
+
+
+Void
+put_Lstring
+#ifdef STDC
+ (const Lstring * lstr, FILE * dvi)
+#else
+ (str, dvi)
+ Lstring lstr;
+ FILE * dvi;
+#endif
+{
+ size_t fwret;
+ fwret = fwrite ((lstr->s), sizeof (char), (size_t) (lstr->l), dvi);
+
+ dvi_written += fwret;
+
+ if (fwret < lstr->l)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(put_Lstring) : DVI File ERROR : not all bytes written ");
+ fprintf (stderr, "(%ld of %ld).\n",
+ (long int) fwret, (long int) (lstr->l));
+ dexit (1);
+ }
+}
+/* put_Lstring */
+
+
+U4
+xfer_len_string
+#ifdef STDC
+ (int n, FILE * dtl, FILE * dvi)
+#else
+ (n, dtl, dvi)
+ int n;
+ FILE * dtl;
+ FILE * dvi;
+#endif
+/* transfer (length and) quoted string from dtl to dvi file, */
+/* return number of bytes written to dvi file. */
+{
+ U4 k, k2;
+ Lstring lstr;
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(xfer_len_string) : entering xfer_len_string.\n");
+ }
+
+ init_Lstring (&lstr, LSIZE);
+
+ /* k[n] : length of special string */
+
+ k = get_unsigned (dtl);
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(xfer_len_string) : string's nominal length k = ");
+ fprintf (stderr, UF4, k);
+ fprintf (stderr, " characters.\n");
+ }
+
+ k2 = get_Lstring (dtl, &lstr);
+
+ if (k2 != k)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(xfer_len_string) : WARNING : string length (");
+ fprintf (stderr, UF4, k);
+ fprintf (stderr, ") in DTL file is wrong\n");
+ fprintf (stderr, "Writing correct value (");
+ fprintf (stderr, UF4, k2);
+ fprintf (stderr, ") to DVI file\n");
+ }
+
+ put_unsigned (n, k2, dvi);
+
+ put_Lstring (&lstr, dvi);
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(xfer_len_string) : leaving xfer_len_string.\n");
+ }
+
+ de_init_Lstring (&lstr);
+
+ return (n + k2);
+}
+/* xfer_len_string */
+
+
+S4
+xfer_bop_address
+#ifdef STDC
+ (FILE * dtl, FILE * dvi)
+#else
+ (dtl, dvi)
+ FILE * dtl;
+ FILE * dvi;
+#endif
+/* translate signed 4-byte bop address from dtl to dvi file. */
+/* return value of bop address written to DVI file */
+{
+ S4 snum = 0; /* at most this space needed for byte address */
+ COUNT nread = 0; /* number of DTL bytes read by read_token */
+ int nconv = 0; /* number of arguments converted by sscanf */
+ static Token token = ""; /* DTL token */
+
+ nread += read_token (dtl, token);
+
+ nconv = sscanf (token, SF4, &snum);
+
+ if (nconv != 1)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(xfer_bop_address) : DTL FILE ERROR (%s) : ",
+ dtl_filename);
+ fprintf (stderr, "signed number expected, not \"%s\".\n", token);
+ dexit (1);
+ }
+
+ if (snum != last_bop_address)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(xfer_bop_address) : WARNING : byte address (");
+ fprintf (stderr, WF, snum);
+ fprintf (stderr, ")\n");
+ fprintf (stderr, "for previous bop in DTL file is wrong\n");
+ fprintf (stderr, "Writing correct value (");
+ fprintf (stderr, WF, last_bop_address);
+ fprintf (stderr, ") to DVI file\n");
+ }
+
+ put_signed (4, last_bop_address, dvi);
+
+ return last_bop_address;
+}
+/* xfer_bop_address */
+
+
+S4
+xfer_postamble_address
+#ifdef STDC
+ (FILE * dtl, FILE * dvi)
+#else
+ (dtl, dvi)
+ FILE * dtl;
+ FILE * dvi;
+#endif
+/* translate signed 4-byte postamble address from dtl to dvi file. */
+/* return value of postamble address written to DVI file */
+{
+ S4 snum = 0; /* at most this space needed for byte address */
+ COUNT nread = 0; /* number of DTL bytes read by read_token */
+ int nconv = 0; /* number of arguments converted by sscanf */
+ static Token token = ""; /* DTL token */
+
+ nread += read_token (dtl, token);
+
+ nconv = sscanf (token, SF4, &snum);
+
+ if (nconv != 1)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(xfer_postamble_address) : DTL FILE ERROR (%s) : ",
+ dtl_filename);
+ fprintf (stderr, "signed number expected, not \"%s\".\n", token);
+ dexit (1);
+ }
+
+ if (snum != postamble_address)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(xfer_postamble_address) : WARNING : byte address (");
+ fprintf (stderr, WF, snum);
+ fprintf (stderr, ")\n");
+ fprintf (stderr, "for postamble in DTL file is wrong\n");
+ fprintf (stderr, "Writing correct value (");
+ fprintf (stderr, WF, postamble_address);
+ fprintf (stderr, ") to DVI file\n");
+ }
+
+ put_signed (4, postamble_address, dvi);
+
+ return postamble_address;
+}
+/* xfer_postamble_address */
+
+
+int
+put_table
+#ifdef STDC
+ (op_table table, int opcode, FILE * dtl, FILE * dvi)
+#else
+ (table, opcode, dtl, dvi)
+ op_table table;
+ int opcode;
+ FILE * dtl;
+ FILE * dvi;
+#endif
+{
+ /* table: {char * name; int first, last; op_info * list; }; */
+ /* op_info: {int code; char * name; int nargs; char * args; }; */
+
+ op_info op; /* entry in table */
+ int i;
+ int pos; /* current position in string being scanned */
+ static String args = "";
+
+ /* Defensive programming. */
+ if (opcode < table.first || opcode > table.last)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(put_table) : DTL FILE (OR INTERNAL) ERROR : opcode %d ", opcode);
+ fprintf (stderr, "is outside table %s [ %d to %d ] !\n",
+ table.name, table.first, table.last);
+ dexit (1);
+ }
+
+ op = table.list [ opcode - table.first ];
+
+ /* More defensive programming. */
+ if (opcode != op.code)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(put_table) : INTERNAL ERROR : opcode %d for command \"%s\"",
+ opcode, op.name);
+ fprintf (stderr, " faulty in table \"%s\".\n", table.name);
+ dexit (1);
+ }
+
+ /* process all the arguments, according to size and sign */
+
+ strncpy (args, op.args, MAXSTRLEN);
+
+ pos = 0;
+ for (i=0; i < op.nargs; i++)
+ {
+ int argtype = 0;
+ int nscan = 0; /* number of bytes read by sscanf */
+ int nconv = 0; /* number of sscanf arguments converted & assigned */
+
+ /* sscanf() does NOT advance over its input: */
+ /* C strings lack internal state information, which C files have. */
+ /* On Sun/OS, sscanf calls ungetc on the string it reads, */
+ /* which therefore has to be writable. */
+
+ nconv = sscanf (args + pos, "%d%n", &argtype, &nscan);
+
+ if (nconv < 1 || nscan < 1)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr,
+ "(put_table) : INTERNAL ERROR : internal read of table %s failed!\n",
+ table.name);
+ dexit (1);
+ }
+
+ pos += nscan;
+
+ if (argtype < 0)
+ xfer_signed (-argtype, dtl, dvi);
+ else
+ xfer_unsigned (argtype, dtl, dvi);
+ }
+ /* end for */
+
+ return 1; /* OK */
+}
+/* put_table */
+
+
+/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+
+U4
+special
+#ifdef STDC
+ (FILE * dtl, FILE * dvi, int n)
+#else
+ (dtl, dvi, n)
+ FILE * dtl;
+ FILE * dvi;
+ int n;
+#endif
+/* read special (1 <= n <= 4 byte) data from dtl, and write in dvi */
+/* return number of bytes written */
+{
+ U4 nk;
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(special) : entering special.\n");
+ }
+
+ if (n < 1 || n > 4)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(special) : DTL FILE ERROR (%s) : special %d, ",
+ dtl_filename, n);
+ fprintf (stderr, "range is 1 to 4.\n");
+ dexit (1);
+ }
+
+ /* k[n] : length of special string */
+ /* x[k] : special string */
+ /* nk = n + k */
+ nk = xfer_len_string (n, dtl, dvi);
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(special) : leaving special.\n");
+ }
+
+ return (nk);
+}
+/* special */
+
+
+int
+fontdef
+#ifdef STDC
+ (FILE * dtl, FILE * dvi, int suffix)
+#else
+ (dtl, dvi, suffix)
+ FILE * dtl;
+ FILE * dvi;
+ int suffix;
+#endif
+/* read fontdef fnt_def1 .. fnt_def4 from dtl, and write in dvi */
+/* suffix is the fontdef suffix : 1 to 4 */
+/* return number of bytes written */
+{
+ U4 a, l, a2, l2;
+ U4 k;
+ Lstring lstr1, lstr2;
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(fontdef) : entering fontdef.\n");
+ }
+
+ if (suffix < 1 || suffix > 4)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(fontdef) : DTL FILE ERROR (%s) : ",
+ dtl_filename);
+ fprintf (stderr, "font def %d, but range is 1 to 4.\n", suffix);
+ dexit (1);
+ }
+
+ init_Lstring (&lstr1, LSIZE);
+ init_Lstring (&lstr2, LSIZE);
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(fontdef) : about to read font number.\n");
+ }
+
+ /* k[suffix] : font number */
+ if (suffix == 4)
+ k = xfer_signed (suffix, dtl, dvi);
+ else
+ k = xfer_unsigned (suffix, dtl, dvi);
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(fontdef) : font ");
+ fprintf (stderr, UF4, k);
+ fprintf (stderr, ".\n");
+ }
+
+#ifdef HEX_CHECKSUM
+ /* c[4] : (hexadecimal) checksum : I (gt) would prefer this */
+ xfer_hex (4, dtl, dvi);
+#else /* NOT HEX_CHECKSUM */
+ /* c[4] : checksum (octal, for comparison with tftopl's .pl file) */
+ xfer_oct (4, dtl, dvi);
+#endif
+
+ /* s[4] */
+ xfer_unsigned (4, dtl, dvi);
+
+ /* d[4] */
+ xfer_unsigned (4, dtl, dvi);
+
+ /* If DTL file's edited, a and l may be wrong. */
+
+ /* a[1] : length of font `area' (directory) portion of pathname string */
+ a = get_unsigned (dtl);
+
+ /* l[1] : length of font portion of pathname string */
+ l = get_unsigned (dtl);
+
+ /* n[a+l] : font pathname string <= area + font */
+
+ a2 = get_Lstring (dtl, &lstr1);
+
+ if (a2 != a)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(fontdef) : WARNING : font area string's length (");
+ fprintf (stderr, UF4, a);
+ fprintf (stderr, ") in DTL file is wrong\n");
+ fprintf (stderr, "Writing correct value (");
+ fprintf (stderr, UF4, a2);
+ fprintf (stderr, ") to DVI file\n");
+ }
+
+ put_unsigned (1, a2, dvi);
+
+ l2 = get_Lstring (dtl, &lstr2);
+
+ if (l2 != l)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(fontdef) : WARNING : font string's length (");
+ fprintf (stderr, UF4, l);
+ fprintf (stderr, ") in DTL file is wrong\n");
+ fprintf (stderr, "Writing correct value (");
+ fprintf (stderr, UF4, l2);
+ fprintf (stderr, ") to DVI file\n");
+ }
+
+ put_unsigned (1, l2, dvi);
+
+ put_Lstring (&lstr1, dvi);
+ put_Lstring (&lstr2, dvi);
+
+ de_init_Lstring (&lstr2);
+ de_init_Lstring (&lstr1);
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(fontdef) : leaving fontdef.\n");
+ }
+
+ return (suffix + 4*4 + 2*1 + a2 + l2);
+}
+/* fontdef */
+
+
+U4
+preamble
+#ifdef STDC
+ (FILE * dtl, FILE * dvi)
+#else
+ (dtl, dvi)
+ FILE * dtl;
+ FILE * dvi;
+#endif
+/* read preamble from dtl, and write in dvi */
+/* return number of bytes written */
+{
+ U4 k1;
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(preamble) : entering preamble.\n");
+ }
+
+ /* i[1] */
+ xfer_unsigned (1, dtl, dvi);
+
+ /* num[4] */
+ xfer_unsigned (4, dtl, dvi);
+
+ /* den[4] */
+ xfer_unsigned (4, dtl, dvi);
+
+ /* mag[4] */
+ xfer_unsigned (4, dtl, dvi);
+
+ /* k[1] : length of comment */
+ /* x[k] : comment string */
+ /* k1 = 1 + k */
+ k1 = xfer_len_string (1, dtl, dvi);
+
+ if (debug)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(preamble) : leaving preamble.\n");
+ }
+
+ return (1 + 3*4 + k1);
+}
+/* preamble */
+
+
+int
+postamble
+#ifdef STDC
+ (FILE * dtl, FILE * dvi)
+#else
+ (dtl, dvi)
+ FILE * dtl;
+ FILE * dvi;
+#endif
+/* read postamble from dtl, and write in dvi */
+/* return number of bytes written */
+{
+ postamble_address = dvi_written - 1;
+
+ /* p[4] : DVI address of previous bop command */
+ /* --- unsigned? --- or signed, as I assume? */
+ /* For, surely p should be -1 if the DVI file has NO bop? */
+ xfer_bop_address (dtl, dvi);
+
+ /* num[4] */
+ xfer_unsigned (4, dtl, dvi);
+
+ /* den[4] */
+ xfer_unsigned (4, dtl, dvi);
+
+ /* mag[4] */
+ xfer_unsigned (4, dtl, dvi);
+
+ /* l[4] */
+ xfer_unsigned (4, dtl, dvi);
+
+ /* u[4] */
+ xfer_unsigned (4, dtl, dvi);
+
+ /* s[2] */
+ xfer_unsigned (2, dtl, dvi);
+
+ /* t[2] */
+ xfer_unsigned (2, dtl, dvi);
+
+ return (6*4 + 2*2);
+}
+/* postamble */
+
+
+int
+post_post
+#ifdef STDC
+ (FILE * dtl, FILE * dvi)
+#else
+ (dtl, dvi)
+ FILE * dtl;
+ FILE * dvi;
+#endif
+/* read post_post from dtl, and write in dvi */
+/* return number of bytes written */
+{
+ /* hope I'm writing the "223" bytes in an 8-bit clean way */
+ int n223 = 0; /* number of "223" bytes in final padding */
+
+ /* q[4] : DVI address of post command */
+ /* --- unsigned? --- or signed, as I assume? */
+ /* what happens if there is NO postamble command? */
+ /* shouldn't q be -1 then? */
+
+ xfer_postamble_address (dtl, dvi);
+
+ /* i[1] : DVI identification byte = 2 */
+ xfer_unsigned (1, dtl, dvi);
+
+ for (n223 = 0; true; n223++)
+ {
+ COUNT nread = 0; /* number of DTL bytes read by read_token */
+ static Token token;
+
+ strcpy (token, "");
+
+ nread = read_token (dtl, token);
+
+ /* check whether end of dtl file */
+ if (nread == 0)
+ {
+ if (group)
+ {
+ /* dtl file shouldn't end before an ECOM */
+ PRINT_PROGNAME;
+ fprintf (stderr, "(post_post) : DTL FILE ERROR (%s) : ",
+ dtl_filename);
+ fprintf (stderr, "premature end of DTL file!\n");
+ fprintf (stderr,
+ "%d complete iterations of \"padding byte\" loop;\n", n223);
+ fprintf (stderr, "troublesome token = \"%s\"\n", token);
+ dexit (1);
+ }
+ /* leave the "223" loop */
+ break;
+ }
+ else if (strcmp (token, "223") == 0)
+ {
+ /* token is a "223" padding byte */
+ /* loop again */
+ }
+ else
+ {
+ /* read a non-empty token that wasn't "223" */
+ (Void) unread_char ();
+ if (group)
+ {
+ if (strcmp (token, ECOM) == 0)
+ {
+ /* end of DTL's post_post command */
+ }
+ else
+ {
+ /* error : expected end of post_post */
+ PRINT_PROGNAME;
+ fprintf (stderr, "(post_post) : DTL FILE ERROR (%s) : ",
+ dtl_filename);
+ fprintf (stderr, "token \"%s\" should be ECOM (\"%s\")\n",
+ token, ECOM);
+ dexit (1);
+ }
+ }
+ /* leave the "223" loop */
+ break;
+ }
+ }
+ /* end for */
+
+ if (n223 < 4)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(post_post) : DTL FILE ERROR (%s) : \n",
+ dtl_filename);
+ fprintf (stderr, "fewer than four `223' padding bytes.\n");
+ fprintf (stderr, "Will write at least four `223' padding bytes.\n");
+ }
+
+ /* check whether the DVI file size is a multiple of 4 bytes */
+ if ((dvi_written + n223) % 4 != 0)
+ {
+ PRINT_PROGNAME;
+ fprintf (stderr, "(post_post) : WARNING : \n");
+ fprintf (stderr, "DVI size ");
+ fprintf (stderr, WF, dvi_written);
+ fprintf (stderr, " (bytes) wouldn't be a multiple of 4 !\n");
+ fprintf (stderr,
+ "Will write (at least four) `223' padding bytes until it is.\n");
+ }
+
+ /* final padding of DVI file by "223" bytes to a multiple of 4 bytes, */
+ /* with at least 4 bytes */
+
+ for (n223 = 0; (n223 < 4) || (dvi_written % 4 != 0); n223++)
+ {
+ /* add a "223" padding byte */
+ put_byte (223, dvi);
+ }
+
+ return (4 + 1 + n223);
+}
+/* post_post */
+
+
+/* end of dt2dv.c */