diff options
Diffstat (limited to 'Build/source/texk/dtl/dt2dv.c')
-rw-r--r-- | Build/source/texk/dtl/dt2dv.c | 2868 |
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 */ |