1 /* dt2dv - convert human-readable "DTL" file to DVI format
2 - this is intended to invert dv2dt version 0.6.0
4 This file is public domain.
5 Originally written 1995, Geoffrey Tobin.
6 The author has expressed the hope that any modification will retain enough content to remain useful. He would also appreciate being acknowledged as the original author in the documentation.
7 This declaration added 2008/11/14 by Clea F. Rees with the permission of Geoffrey Tobin.
10 - Geoffrey Tobin G.Tobin@ee.latrobe.edu.au
11 - fixes: Michal Tomczak-Jaegermann ntomczak@vm.ucs.ualberta.ca
12 Nelson H. F. Beebe beebe@math.utah.edu
13 Angus Leeming leeming@lyx.org: Enable dt2dv to handle .dvi files
14 containing strings longer than 1024 chars.
15 Enrico Forestieri forenr@lyx.org: handle non-ASCII characters.
16 Juergen Spitzmueller spitz@lyx.org: fix compiler warnings
17 - Reference: "The DVI Driver Standard, Level 0",
18 by The TUG DVI Driver Standards Committee.
19 Appendix A, "Device-Independent File Format".
22 /* unix version; read from stdin, write to stdout, by default. */
33 /* by default, read and write regular files */
37 /* maximum number of characters in a DTL input line */
43 COUNT num; /* current line number */
44 size_t max; /* capacity of buf */
45 U4 wrote; /* number of characters written into buf */
46 size_t read; /* position in buf of next character to read from buf */
47 char * buf; /* line buffer */
50 char linebuf[MAXLINE+1];
52 Line dtl_line = {0, 0, 0, MAXLINE, linebuf};
54 /* a DTL token either is:
55 a quoted string (admitting an escape character),
56 or BCOM (if that is a nonempty string),
57 or ECOM (if that is a nonempty string),
58 or a string _not_ including ECOM_CHAR or space.
61 /* maximum expected length of a DTL token */
63 typedef char Token[MAXTOKLEN+1];
65 typedef unsigned char Byte;
71 /* command prefixes */
77 Byte first_suffix, last_suffix;
80 CmdPrefix cmd_prefixes [] =
82 {0, SETCHAR, true, 0, 127},
83 {128, SET, true, 1, 4},
84 {132, SETRULE, false, 0, 0},
85 {133, PUT, true, 1, 4},
86 {137, PUTRULE, false, 0, 0},
87 {138, NOP, false, 0, 0},
88 {139, BOP, false, 0, 0},
89 {140, EOP, false, 0, 0},
90 {141, PUSH, false, 0, 0},
91 {142, POP, false, 0, 0},
92 {143, RIGHT, true, 1, 4},
95 {157, DOWN, true, 1, 4},
98 {171, FONTNUM, true, 0, 63},
99 {235, FONT, true, 1, 4},
100 {239, SPECIAL, true, 1, 4},
101 {243, FONTDEF, true, 1, 4},
102 {247, PRE, false, 0, 0},
103 {248, POST, false, 0, 0},
104 {249, POSTPOST, false, 0, 0},
105 {250, OPCODE, true, 250, 255}
109 /* Number of DVI commands, including those officially undefined */
112 /* table of command name (string) pointers */
113 typedef char * CmdTable [NCMDS];
115 /* initially all command name pointers are NULL */
118 /* operation's opcode, name, number of args, string of arguments. */
127 /* name of table, first opcode, last opcode, pointer to opcode info. */
136 /* Table for opcodes 128 to 170 inclusive. */
138 op_info op_info_128_170 [] =
143 {131, SET4, 1, "-4"},
144 {132, SETRULE, 2, "-4 -4"},
148 {136, PUT4, 1, "-4"},
149 {137, PUTRULE, 2, "-4 -4"},
151 /* bop: not counting last argument, a signed address: */
152 {139, BOP, 10, "-4 -4 -4 -4 -4 -4 -4 -4 -4 -4"},
156 {143, RIGHT1, 1, "-1"},
157 {144, RIGHT2, 1, "-2"},
158 {145, RIGHT3, 1, "-3"},
159 {146, RIGHT4, 1, "-4"},
170 {157, DOWN1, 1, "-1"},
171 {158, DOWN2, 1, "-2"},
172 {159, DOWN3, 1, "-3"},
173 {160, DOWN4, 1, "-4"},
185 /* op_info op_info_128_170 [] */
187 op_table op_128_170 = {"op_128_170", 128, 170, op_info_128_170};
189 /* Table for fnt1 to fnt4 (opcodes 235 to 238) inclusive. */
193 {235, FONT1, 1, "1"},
194 {236, FONT2, 1, "2"},
195 {237, FONT3, 1, "3"},
196 {238, FONT4, 1, "-4"}
198 /* op_info fnt_n [] */
200 op_table fnt = {FONT, 235, 238, fnt_n};
203 /* Function prototypes */
205 Void mem_viol ARGS((int sig));
206 Void give_help (VOID);
207 int parse ARGS((char * s));
208 Void process ARGS((char * s));
211 Void dtl_stdin (VOID);
212 Void dvi_stdout (VOID);
214 int open_dtl ARGS((char * dtl_file, FILE ** pdtl));
215 int open_dvi ARGS((char * dvi_file, FILE ** pdvi));
217 int dt2dv ARGS((FILE * dtl, FILE * dvi));
219 Void * gmalloc ARGS((long int size));
222 Void dexit ARGS((int n));
224 int cons_cmds ARGS((int nprefixes, CmdPrefix * prefix, CmdTable cmds));
225 Void free_cmds ARGS((CmdTable cmd_table));
227 int get_line ARGS((FILE * fp, Line * line, int max));
228 int read_line_char ARGS((FILE * fp, int * ch));
229 int read_char ARGS((FILE * fp, int * ch));
230 int unread_char (VOID);
231 int read_string_char ARGS((FILE * fp, int * ch));
233 COUNT read_variety ARGS((FILE * dtl));
234 COUNT read_token ARGS((FILE * dtl, char * token));
235 COUNT skip_space ARGS((FILE * fp, int * ch));
236 COUNT read_misc ARGS((FILE * fp, Token token));
237 COUNT read_mes ARGS((FILE * fp, char * token));
239 int find_command ARGS((char * command, int * opcode));
240 int xfer_args ARGS((FILE * dtl, FILE * dvi, int opcode));
242 int set_seq ARGS((FILE * dtl, FILE * dvi));
244 int check_byte ARGS((int byte));
245 int put_byte ARGS((int onebyte, FILE * dvi));
247 U4 xfer_hex ARGS((int n, FILE * dtl, FILE * dvi));
248 U4 xfer_oct ARGS((int n, FILE * dtl, FILE * dvi));
249 U4 xfer_unsigned ARGS((int n, FILE * dtl, FILE * dvi));
250 S4 xfer_signed ARGS((int n, FILE * dtl, FILE * dvi));
252 int check_bmes ARGS((FILE * dtl));
253 int check_emes ARGS((FILE * dtl));
255 Void init_Lstring ARGS((Lstring * lsp, long int n));
256 Void de_init_Lstring ARGS((Lstring * lsp));
257 Lstring * alloc_Lstring ARGS((long int n));
258 Void free_Lstring ARGS((Lstring * lstr));
259 Void ls_putb ARGS((int ch, Lstring * lstr));
261 S4 get_Lstring ARGS((FILE * dtl, Lstring * lstr));
262 Void put_Lstring ARGS((const Lstring * lstr, FILE * dvi));
263 U4 xfer_len_string ARGS((int n, FILE * dtl, FILE * dvi));
265 U4 get_unsigned ARGS((FILE * dtl));
266 S4 get_signed ARGS((FILE * dtl));
268 int put_unsigned ARGS((int n, U4 unum, FILE * dvi));
269 int put_signed ARGS((int n, S4 snum, FILE * dvi));
271 S4 xfer_bop_address ARGS((FILE * dtl, FILE * dvi));
272 S4 xfer_postamble_address ARGS((FILE * dtl, FILE * dvi));
274 int put_table ARGS((op_table table, int opcode, FILE * dtl, FILE * dvi));
276 U4 special ARGS((FILE * dtl, FILE * dvi, int n));
277 int fontdef ARGS((FILE * dtl, FILE * dvi, int n));
279 U4 preamble ARGS((FILE * dtl, FILE * dvi));
280 int postamble ARGS((FILE * dtl, FILE * dvi));
281 int post_post ARGS((FILE * dtl, FILE * dvi));
286 char * keyword; /* command line option keyword */
287 int * p_var; /* pointer to option variable */
288 char * desc; /* description of keyword and value */
289 Void (* p_fn) (VOID); /* pointer to function called when option is set */
294 {"-debug", &debug, "detailed debugging", no_op},
295 {"-group", &group, "each DTL command is in parentheses", no_op},
296 {"-si", &rd_stdin, "read all DTL commands from standard input", dtl_stdin},
297 {"-so", &wr_stdout, "write all DVI commands to standard output", dvi_stdout},
298 {NULL, NULL, NULL, NULL}
302 char * progname = ""; /* intended for name of this program */
303 int nfile = 0; /* number of filename arguments on the command line */
305 #define PRINT_PROGNAME fprintf (stderr, "%s ", progname)
307 /* Harbison & Steele (1991) warn that some C implementations */
308 /* of free() do not treat NULL pointers correctly. */
309 #define gfree(p) {if (p) free (p);}
312 FILE * dtl_fp = NULL;
313 FILE * dvi_fp = NULL;
315 char * dtl_filename = "";
316 char * dvi_filename = "";
322 (int argc, char * argv[])
329 Void (*handler) ARGS((int)); /* Previous signal handler */
330 (void)handler;// avoid compiler warning [-Wunused-but-set-variable]
333 progname = argv[0]; /* name of this program */
335 /* memory violation signal handler */
337 handler = (Void (*) ARGS((int))) signal (SIGSEGV, mem_viol);
350 #define C_LEVEL "non-"
351 #endif /* NOT STDC */
353 /* message about program and compiler */
354 /* NB: LTU EE's Sun/OS library is BSD, even though gcc 2.2.2 is ANSI */
356 fprintf (stderr, "\n");
358 "Program \"%s\" version %s compiled %s %s in %sstandard C.\n",
359 progname, VERSION, __DATE__, __TIME__, C_LEVEL);
361 /* interpret command line arguments */
364 dtl_fp = dvi_fp = NULL;
365 dtl_filename = dvi_filename = "";
367 for (i=1; i < argc; i++)
369 /* parse options, followed by any explicit filenames */
373 if (nfile != 2) /* not exactly two files specified, so give help */
377 dt2dv (dtl_fp, dvi_fp);
393 Void (* handler) ARGS((int));
394 (void)handler;// avoid compiler warning [-Wunused-but-set-variable]
395 handler = (Void (*) ARGS((int))) signal (SIGSEGV, mem_viol);
400 "(mem_viol) : called with wrong signal!\n");
403 fprintf (stderr, "(mem_viol) : RUNTIME MEMORY ERROR : memory violation, ");
404 fprintf (stderr, "dtl line >= ");
405 fprintf (stderr, WF, dtl_line.num);
406 fprintf (stderr, "\n");
417 fprintf (stderr, "usage: ");
419 fprintf (stderr, "[options] dtl_file dvi_file");
420 fprintf (stderr, "\n");
421 for (i=0; (keyword = opts[i].keyword) != NULL; i++)
423 fprintf (stderr, " ");
424 fprintf (stderr, "[%s]", keyword);
425 fprintf (stderr, " ");
426 fprintf (stderr, "%s", opts[i].desc);
427 fprintf (stderr, "\n");
429 fprintf (stderr, "Messages, like this one, go to stderr.\n");
439 Void dtl_stdin (VOID)
441 extern FILE * dtl_fp;
445 dtl_filename = "Standard Input";
449 Void dvi_stdout (VOID)
451 extern FILE * dvi_fp;
454 /* ! Perilous to monitors! */
456 dvi_filename = "Standard Output";
469 /* parse one command-line argument, `s' */
473 for (i=0; (keyword = opts[i].keyword) != NULL; i++)
475 if (strncmp (s, keyword, strlen (keyword)) == 0)
478 (*(opts[i].p_var)) = 1; /* turn option on */
479 if ((pfn = opts[i].p_fn) != NULL)
480 (*pfn) (); /* call option function */
484 /* reached here, so not an option: assume it's a filename */
494 (char * dtl_file, FILE ** pdtl)
500 /* I: dtl_file; I: pdtl; O: *pdtl. */
502 extern char * dtl_filename;
504 dtl_filename = dtl_file;
506 if (dtl_filename == NULL)
510 "(open_dtl) : INTERNAL ERROR : dtl file's name is NULL.\n");
518 "(open_dtl) : INTERNAL ERROR : address of dtl variable is NULL.\n");
522 *pdtl = fopen (dtl_file, "r");
528 "(open_dtl) : DTL FILE ERROR : Cannot open \"%s\" for text reading.\n",
541 (char * dvi_file, FILE ** pdvi)
547 /* I: dvi_file; I: pdvi; O: *pdvi. */
549 extern char * dvi_filename;
551 dvi_filename = dvi_file;
553 if (dvi_filename == NULL)
557 "(open_dvi) : INTERNAL ERROR : dvi file's name is NULL.\n");
565 "(open_dvi) : INTERNAL ERROR : address of dvi variable is NULL.\n");
569 *pdvi = fopen (dvi_file, "wb");
575 "(open_dvi) : DVI FILE ERROR : Cannot open \"%s\" for binary writing.\n",
594 extern FILE * dtl_fp, * dvi_fp;
596 if (dtl_fp == NULL) /* first filename assumed to be DTL input */
598 open_dtl (s, &dtl_fp);
600 else if (dvi_fp == NULL) /* second filename assumed to be DVI output */
602 open_dvi (s, &dvi_fp);
607 fprintf (stderr, "(process) : at most two filenames allowed.\n");
615 COUNT dtl_read = 0; /* bytes read from dtl file */
616 COUNT dvi_written = 0; /* bytes written to dvi file */
617 word_t last_bop_address = -1; /* byte address of last bop; first bop uses -1 */
618 word_t postamble_address = -1; /* byte address of postamble */
619 COUNT ncom = 0; /* commands successfully read and interpreted from dtl file */
620 COUNT com_read = 0; /* bytes read in current (command and arguments), */
621 /* since and including the opening BCOM_CHAR, if any */
627 (int byte, FILE * dvi)
633 /* write byte into dvi file */
636 /* if (fprintf (dvi, "%c", byte) != 1) */
637 if (fprintf (dvi, "%c", byte) < 0)
641 "(put_byte) : DVI FILE ERROR (%s) : cannot write to dvi file.\n",
654 (FILE * dtl, FILE * dvi)
661 int nprefixes = 0; /* number of prefixes in cmd_prefixes[] list. */
662 static Token dtl_cmd = ""; /* DTL command name */
663 COUNT nread = 0; /* number of bytes read by a function from dtl file. */
664 (void)nread;// avoid compiler warning [-Wunused-but-set-variable]
666 nprefixes = sizeof (cmd_prefixes) / sizeof (CmdPrefix);
668 /* Construct array of all NCMDS == 256 DTL commands */
670 (Void) cons_cmds (nprefixes, cmd_prefixes, cmd_table);
672 /* DTL commands have the form "[ ]*command arg ... arg[ ]*", */
673 /* possibly enclosed in a BCOM, ECOM pair, */
674 /* and are separated by optional whitespace, typically newlines. */
675 /* That is, each command and its arguments are parenthesised, */
676 /* with optional spaces after the BCOM and before the ECOM, if any. */
678 /* dt2dv is now at the very start of the DTL file */
683 /* The very first thing should be the "variety" signature */
685 nread = read_variety (dtl);
687 /* while not end of dtl file or reading error, */
688 /* read, interpret, and write commands */
699 static Token token = ""; /* DTL token */
700 nread = read_token (dtl, token);
701 /* test for end of input, or reading error */
702 if (strlen (token) == 0)
707 fprintf (stderr, "(dt2dv) : end of input, or reading error.\n");
711 /* test whether this command begins correctly */
712 else if (strcmp (token, BCOM) != 0)
715 fprintf (stderr, "(dt2dv) : DTL FILE ERROR (%s) : ", dtl_filename);
716 fprintf (stderr, "command must begin with \"%s\", ", BCOM);
717 fprintf (stderr, "not `%c' (char %d).\n", token[0], token[0]);
723 /* read the command name */
724 nread = read_token (dtl, dtl_cmd);
725 /* test for end of input, or reading error */
726 if (strlen (dtl_cmd) == 0)
732 "(dt2dv) : end of input, or reading error.\n");
741 fprintf (stderr, "(dt2dv) : command ");
742 fprintf (stderr, WF, ncom);
743 fprintf (stderr, " = \"%s\".\n", dtl_cmd);
746 /* find opcode for this command */
747 if (find_command (dtl_cmd, &opcode) == 1)
749 /* write the opcode, if we can */
750 put_byte (opcode, dvi);
752 /* treat the arguments, if any */
753 xfer_args (dtl, dvi, opcode);
755 else if (dtl_cmd[0] == BSEQ_CHAR)
757 /* sequence of font characters for SETCHAR */
764 "(dt2dv) : DTL FILE ERROR (%s) : unknown command \"%s\".\n",
765 dtl_filename, dtl_cmd);
772 /* seek ECOM after command's last argument and optional whitespace */
773 static Token token = ""; /* DTL token */
774 nread = read_token (dtl, token);
775 /* test for end of input, or reading error */
776 if (strlen (token) == 0)
782 "(dt2dv) : end of input, or reading error.\n");
786 if (strcmp (token, ECOM) != 0)
789 fprintf (stderr, "(dt2dv) : DTL FILE ERROR (%s) : ", dtl_filename);
790 fprintf (stderr, "ECOM (\"%s\") expected, not `%c' (char %d).\n",
791 ECOM, token[0], token[0]);
797 ++ ncom; /* one more command successfully read and interpreted */
802 fprintf (stderr, "(dt2dv) :\n");
803 fprintf (stderr, "Read (from file \"%s\") ", dtl_filename);
804 fprintf (stderr, WF, dtl_read);
805 fprintf (stderr, " DTL bytes (");
806 fprintf (stderr, UF4, dtl_line.num);
807 fprintf (stderr, " lines);\n");
808 fprintf (stderr, "wrote (to file \"%s\") ", dvi_filename);
809 fprintf (stderr, WF, dvi_written);
810 fprintf (stderr, " DVI bytes;\n");
811 fprintf (stderr, "completely interpreted ");
812 fprintf (stderr, WF, ncom);
813 fprintf (stderr, " DVI command%s.\n", (ncom == 1 ? "" : "s"));
814 fprintf (stderr, "\n");
816 (Void) free_cmds (cmd_table);
836 fprintf (stderr, "(gmalloc) : INTERNAL ERROR : ");
838 "unreasonable request to malloc %ld bytes\n",
842 p = (Void *) malloc ((size_t) size);
846 fprintf (stderr, "(gmalloc) : MEMORY ALLOCATION ERROR : ");
848 "operating system failed to malloc %ld bytes\n",
861 fprintf (stderr, "(dinfo) : ");
862 fprintf (stderr, "Current DTL input line ");
863 fprintf (stderr, UF4, dtl_line.num);
864 fprintf (stderr, " :\n");
865 fprintf (stderr, "\"%s\"\n", dtl_line.buf);
866 fprintf (stderr, "Read ");
867 fprintf (stderr, WF, dtl_read);
868 fprintf (stderr, " DTL bytes (");
869 fprintf (stderr, WF, com_read);
870 fprintf (stderr, " in current command), wrote ");
871 fprintf (stderr, WF, dvi_written);
872 fprintf (stderr, " DVI bytes.\n");
873 fprintf (stderr, "Successfully interpreted ");
874 fprintf (stderr, WF, ncom);
875 fprintf (stderr, " DVI command%s.\n", (ncom == 1 ? "" : "s"));
891 fprintf (stderr, "(dexit) : exiting with status %d.\n", n);
900 (int nprefixes, CmdPrefix * prefix, CmdTable cmds)
902 (nprefixes, prefix, cmds)
908 int code; /* first opcode for a given command prefix */
909 int opcode; /* command's opcode */
910 int nsuffixes; /* number of commands with a given prefix */
911 int isuffix; /**** integer suffix, of at most three digits ****/
912 String suffix; /* suffix string generated from integer suffix */
913 size_t plen = 0; /* prefix length */
914 size_t slen; /* suffix length */
915 size_t clen; /* whole command name length */
916 int i, j; /* loop indices */
918 for (i=0; i < nprefixes; prefix++, i++)
920 code = prefix->first_code;
921 if (code < 0 || code > 255)
924 fprintf (stderr, "(cons_cmds) : INTERNAL ERROR : ");
926 "prefix listed internally with code = %d, must be 0 to 255\n",
930 if (prefix->has_suffix)
932 plen = strlen (prefix->name);
933 /**** Suffixes in DTL are Integers, in Sequence */
934 if (prefix->last_suffix < prefix->first_suffix)
937 fprintf (stderr, "(cons_cmds) : INTERNAL ERROR : ");
939 "prefix's last suffix %d < first suffix (%d)\n",
940 prefix->last_suffix, prefix->first_suffix);
943 nsuffixes = prefix->last_suffix - prefix->first_suffix + 1;
944 opcode = prefix->first_code;
945 for (j=0; j < nsuffixes; j++, opcode++)
947 isuffix = prefix->first_suffix + j;
948 if (0 <= code && code <= 127) /* SETCHAR */
950 /* SETCHAR's suffix is written in uppercase hexadecimal */
951 sprintf (suffix, "%02X", isuffix);
953 else /* 128 <= code && code <= 255 */ /* other DTL commands */
955 /* other commands' suffices are written in decimal */
956 sprintf (suffix, "%d", isuffix);
958 slen = strlen (suffix);
960 cmds[opcode] = (char *) gmalloc (clen+1);
961 strcpy (cmds[opcode], prefix->name);
962 strcat (cmds[opcode], suffix);
965 else /* command name = prefix */
967 plen = strlen (prefix->name);
969 opcode = prefix->first_code;
970 cmds[opcode] = (char *) gmalloc (clen+1);
971 strcpy (cmds[opcode], prefix->name);
990 for (i=0; i < NCMDS; i++)
991 gfree (cmd_table[i]);
999 (FILE * fp, Line * line, int max)
1006 /* read a (Line *) line from fp, return length */
1007 /* adapted from K&R (second, alias ANSI C, edition, 1988), page 165 */
1009 if (fgets (line->buf, max, fp) == NULL)
1014 line->wrote = strlen (line->buf);
1025 (FILE * fp, int * ch)
1031 /* read one character from dtl_line if possible, */
1032 /* otherwise read another dtl_line from fp */
1033 /* return 1 if a character is read, 0 if at end of fp file */
1035 extern Line dtl_line;
1036 if (dtl_line.wrote == 0 || dtl_line.read >= dtl_line.wrote)
1039 /* refill line buffer */
1040 line_status = get_line (fp, &dtl_line, MAXLINE);
1041 if (line_status == 0)
1043 /* at end of DTL file */
1047 fprintf (stderr, "(read_line_char) : end of DTL file\n");
1054 /* new DTL line was read */
1058 fprintf (stderr, "(read_line_char) : new DTL input line:\n");
1059 fprintf (stderr, "\"%s\"\n", dtl_line.buf);
1063 *ch = dtl_line.buf [dtl_line.read ++];
1065 ++ com_read; /* count another DTL command character */
1068 /* read_line_char */
1074 (FILE * fp, int * ch)
1080 /* Read next character, if any, from file fp. */
1081 /* Write it into *ch. */
1082 /* If no character is read, then *ch value < 0. */
1083 /* Return 1 if OK, 0 if EOF or error. */
1086 int c; /* in case ch points awry, we still have something in c. */
1089 if (read_line_char (fp, &c) == 0)
1091 /* end of fp file, or error reading it */
1100 "(read_char) : character %d not in range 0 to 255\n",
1105 else if ( ! isprint (c & 0x7f) && ! isspace (c))
1109 "(read_char) : character %d %s.\n",
1111 "not printable and not white space");
1131 /* read and check DTL variety signature */
1132 /* return number of DTL bytes written */
1133 /* DTL variety is _NEVER_ grouped by BCOM and ECOM. */
1134 /* Uniformity here enables the program easily to modify its behavior. */
1136 COUNT vread = 0; /* number of DTL bytes read by read_variety */
1137 COUNT nread = 0; /* number of DTL bytes read by read_token */
1138 static Token token = "";
1140 /* read the DTL VARIETY keyword */
1141 nread = read_token (dtl, token);
1143 /* test whether signature begins correctly */
1144 if (strcmp (token, "variety") != 0)
1147 fprintf (stderr, "(read_variety) : DTL FILE ERROR (%s) : ", dtl_filename);
1148 fprintf (stderr, "DTL signature must begin with \"%s\", not \"%s\".\n",
1153 /* read the DTL variety */
1154 nread = read_token (dtl, token);
1156 /* test whether variety is correct */
1157 if (strcmp (token, VARIETY) != 0)
1160 fprintf (stderr, "(read_variety) : DTL FILE ERROR (%s) : ", dtl_filename);
1161 fprintf (stderr, "DTL variety must be \"%s\", not \"%s\".\n",
1167 fprintf (stderr, "(read_variety) : DTL variety %s is OK.\n", VARIETY);
1169 return vread; /* OK */
1177 (FILE * fp, int * ch)
1183 /* Skip whitespace characters in file fp. */
1184 /* Write in *ch the last character read from fp, */
1185 /* or < 0 if fp could not be read. */
1186 /* Return number of characters read from fp. */
1188 int c; /* character read (if any) */
1189 COUNT count; /* number (0 or more) of whitespace characters read */
1190 int nchar; /* number (0 or 1) of characters read by read_char */
1192 /* loop ends at: end of fp file, or reading error, or not a white space */
1193 for (count=0; ((nchar = read_char (fp, &c)) == 1 && isspace (c)); ++count)
1195 /* otherwise, more white spaces to skip */
1198 /* report when each DTL end of line is reached */
1202 fprintf (stderr, "(skip_space) : ");
1203 fprintf (stderr, "end of DTL line (at least) ");
1204 fprintf (stderr, WF, dtl_line.num);
1205 fprintf (stderr, "\n");
1215 *ch = c; /* c will be < 0 if read_char could not read fp */
1216 return (count + nchar);
1224 (FILE * dtl, char * token)
1230 /* read next token from dtl file. */
1231 /* return number of DTL bytes read. */
1232 /* A token is one of:
1233 a string from BMES_CHAR to the next unescaped EMES_CHAR, inclusive;
1234 BCOM or ECOM, unless these are empty strings;
1236 any other sequence of non-whitespace characters.
1239 COUNT nread; /* number of DTL bytes read by read_token */
1240 int ch; /* most recent character read */
1244 /* obtain first non-space character */
1245 /* add to nread the number of characters read from dtl by skip_space */
1246 nread += skip_space (dtl, &ch);
1250 /* end of dtl file */
1251 /* write an empty token */
1256 fprintf (stderr, "(read_token) : end of dtl file.\n");
1259 else if (group && ch == BCOM_CHAR)
1261 strcpy (token, BCOM);
1263 else if (group && ch == ECOM_CHAR)
1265 strcpy (token, ECOM);
1271 if (ch == BMES_CHAR) /* string token; read until unescaped EMES_CHAR */
1273 nread += read_mes (dtl, token+1);
1275 else if (ch == BSEQ_CHAR || ch == ESEQ_CHAR)
1277 /* token is complete */
1279 else /* any other string not containing (ECOM_CHAR or) whitespace */
1281 nread += read_misc (dtl, token+1);
1288 fprintf (stderr, "(read_token) : token = \"%s\"\n", token);
1291 return (nread); /* number of bytes read from dtl file */
1298 #define CHAR_EOS (-1)
1303 (FILE * fp, int * ch)
1310 int status = CHAR_OK; /* OK so far */
1313 if (read_char (fp, &c) == 0)
1314 status = CHAR_FAIL; /* fail */
1316 if (c == EMES_CHAR) /* end-of-string char */
1318 status = CHAR_EOS; /* end of string */
1320 else if (c == ESC_CHAR) /* escape character */
1322 /* accept the next character literally, even ESC_CHAR and EMES_CHAR */
1323 if (read_char (fp, &c) == 0)
1324 status = CHAR_FAIL; /* fail */
1330 /* read_string_char */
1336 (FILE * fp, Token token)
1345 /* loop ends at: end of fp file, or reading error, or a space */
1346 for (count=0; count <= MAXTOKLEN; ++count)
1348 if (read_char (fp, &c) == 0 || isspace (c))
1350 if (group && c == ECOM_CHAR)
1352 (Void) unread_char ();
1358 token[count] = '\0';
1367 (FILE * fp, char * token)
1373 /* called **AFTER** a BMES_CHAR has been read */
1374 /* read file fp for characters up to next unescaped EMES_CHAR */
1375 /* this is called a "string token" */
1376 /* write string, including EMES_CHAR, into token[] */
1377 /* return number of characters read from fp */
1379 COUNT dtl_count; /* number of DTL characters read by read_mes from fp */
1380 int more; /* flag more == 0 to terminate loop */
1381 int escape; /* flag escape == 1 if previous character was ESC_CHAR */
1382 int ch; /* current DTL character */
1389 if (read_char (fp, &ch) == 0)
1391 /* end of fp file, or reading error */
1394 else /* error checking passed */
1397 if (ch == EMES_CHAR && escape == 0) /* end of string */
1399 /* include final EMES_CHAR */
1403 else if (ch == ESC_CHAR && escape == 0)
1405 /* next character is not end of string */
1410 /* store any other character, */
1411 /* including escaped EMES_CHAR and ESC_CHAR*/
1425 /* wind input back, to allow rereading of one character */
1426 /* return 1 if this works, 0 on error */
1428 extern Line dtl_line;
1430 if (dtl_line.read > 0)
1432 -- dtl_line.read; /* back up one character in dtl_line */
1433 -- dtl_read; /* correct the count of DTL characters */
1434 -- com_read; /* count another DTL command character */
1435 status = 1; /* OK */
1437 else /* current DTL line is empty */
1439 status = 0; /* error */
1449 (char * command, int * opcode)
1460 for (i=0; i < NCMDS; i++)
1462 if ((cmd_table[i] != 0) && (strcmp (command, cmd_table[i]) == 0))
1485 if (byte < 0 || byte > 255)
1488 fprintf (stderr, "(check_byte) : INTERNAL ERROR : ");
1489 fprintf (stderr, "byte %d not in the range of 0 to 255.\n", byte);
1500 (FILE * dtl, FILE * dvi, int opcode)
1510 if (opcode >= 0 && opcode <= 127)
1511 ; /* SETCHAR uses no data */
1512 else if (opcode >= 128 && opcode <= 170)
1514 word_t this_bop_address = last_bop_address;
1516 if (opcode == 139) /* BOP */
1518 this_bop_address = dvi_written - 1;
1520 put_table (op_128_170, opcode, dtl, dvi);
1521 if (opcode == 139) /* BOP */
1523 xfer_bop_address (dtl, dvi);
1524 last_bop_address = this_bop_address;
1527 else if (opcode >= 171 && opcode <= 234)
1528 ; /* FONTNUM uses no data */
1529 else if (opcode >= 235 && opcode <= 238)
1530 put_table (fnt, opcode, dtl, dvi);
1531 else if (opcode >= 239 && opcode <= 242)
1534 special (dtl, dvi, n);
1536 else if (opcode >= 243 && opcode <= 246)
1539 fontdef (dtl, dvi, n);
1541 else if (opcode == 247)
1542 preamble (dtl, dvi);
1543 else if (opcode == 248)
1544 postamble (dtl, dvi);
1545 else if (opcode == 249)
1546 post_post (dtl, dvi);
1547 else if (opcode >= 250 && opcode <= 255)
1548 ; /* these, undefined, opcodes use no data */
1553 "(xfer_args) : opcode %d not handled.\n",
1565 (FILE * dtl, FILE * dvi)
1571 /* Called _after_ a BSEQ_CHAR command */
1572 /* Read bytes from dtl file, */
1573 /* writing corresponding SETCHAR or SET1 commands to DVI file, */
1574 /* _until_ unescaped ESEQ_CHAR is found */
1575 /* Return 1 if OK, 0 on error */
1576 /**** dt2dv assumes 8 bit characters, ****/
1577 /**** but some day one might change that. ****/
1579 int status = 1; /* status = 1 if OK, 0 if error */
1580 int more; /* sequence of font characters continuing? */
1581 int escape = 0; /* flag set if previous character was an escape */
1582 int ch; /* character read from DTL file */
1586 /* ignore read_char status, to allow unprintable characters */
1587 (Void) read_char (dtl, &ch);
1588 /* but check for end of dtl file, or serious file reading error */
1592 fprintf (stderr, "(set_seq) : ");
1593 fprintf (stderr, "end of dtl file, ");
1594 fprintf (stderr, "or serious dtl file reading error\n");
1597 status = 0; /* bad news */
1599 else /* read dtl file, okay */
1601 if (ch == ESC_CHAR && escape == 0) /* escape next character */
1607 if (ch == ESEQ_CHAR && escape == 0) /* end of sequence */
1611 else if (ch <= 127) /* can use SETCHAR */
1615 else if (ch <= 255) /* can use SET1 */
1617 put_byte (128, dvi); /* SET1 opcode */
1618 put_unsigned (1, (U4) ch, dvi);
1623 fprintf (stderr, "(set_seq) : ");
1625 "ERROR : DTL character %d is not in range 0 to 255\n",
1629 status = 0; /* Error, because dt2dv assumes 8 bit characters */
1631 escape = 0; /* current ch is not an escape character */
1643 (int n, FILE * dtl, FILE * dvi)
1650 /* translate unsigned n-byte hexadecimal number from dtl to dvi file. */
1651 /* return value of hexadecimal number */
1653 U4 unum = 0; /* at most this space needed */
1654 COUNT nread = 0; /* number of DTL bytes read by read_token */
1655 (void)nread;// avoid compiler warning [-Wunused-but-set-variable]
1656 int nconv = 0; /* number of arguments converted by sscanf */
1657 static Token token = ""; /* DTL token */
1663 "(xfer_hex) : INTERNAL ERROR : asked for %d bytes. Must be 1 to 4.\n",
1668 nread = read_token (dtl, token);
1670 nconv = sscanf (token, XF4, &unum);
1675 fprintf (stderr, "(xfer_hex) : DTL FILE ERROR (%s) : %s \"%s\".\n",
1676 dtl_filename, "hexadecimal number expected, not", token);
1680 put_unsigned (n, unum, dvi);
1690 (int n, FILE * dtl, FILE * dvi)
1697 /* translate unsigned n-byte octal number from dtl to dvi file. */
1698 /* return value of octal number */
1700 U4 unum = 0; /* at most this space needed */
1701 COUNT nread = 0; /* number of DTL bytes read by read_token */
1702 (void)nread;// avoid compiler warning [-Wunused-but-set-variable]
1703 int nconv = 0; /* number of arguments converted by sscanf */
1704 static Token token = ""; /* DTL token */
1710 "(xfer_oct) : INTERNAL ERROR : asked for %d bytes. Must be 1 to 4.\n",
1715 nread = read_token (dtl, token);
1717 nconv = sscanf (token, OF4, &unum);
1722 fprintf (stderr, "(xfer_oct) : DTL FILE ERROR (%s) : %s \"%s\".\n",
1723 dtl_filename, "octal number expected, not", token);
1727 put_unsigned (n, unum, dvi);
1737 (int n, FILE * dtl, FILE * dvi)
1744 /* translate unsigned n-byte number from dtl to dvi file. */
1745 /* return value of unsigned number */
1747 U4 unum = 0; /* at most this space needed */
1749 unum = get_unsigned (dtl);
1750 put_unsigned (n, unum, dvi);
1760 (int n, FILE * dtl, FILE * dvi)
1767 /* translate signed n-byte number from dtl to dvi file. */
1768 /* return value of signed number */
1772 snum = get_signed (dtl);
1773 put_signed (n, snum, dvi);
1788 /* read unsigned number from dtl file. */
1789 /* return value of unsigned number */
1791 U4 unum = 0; /* at most this space needed */
1792 COUNT nread = 0; /* number of DTL bytes read by read_token */
1793 (void)nread;// avoid compiler warning [-Wunused-but-set-variable]
1794 int nconv = 0; /* number of arguments converted by sscanf */
1795 static Token token = ""; /* DTL token */
1797 nread = read_token (dtl, token);
1799 nconv = sscanf (token, UF4, &unum);
1804 fprintf (stderr, "(get_unsigned) : DTL FILE ERROR (%s) : %s \"%s\".\n",
1805 dtl_filename, "unsigned number expected, not", token);
1822 /* read signed number from dtl file. */
1823 /* return value of signed number */
1826 COUNT nread = 0; /* number of DTL bytes read by read_token */
1827 (void)nread;// avoid compiler warning [-Wunused-but-set-variable]
1828 int nconv = 0; /* number of sscanf arguments converted and assigned */
1829 static Token token = "";
1831 nread = read_token (dtl, token);
1833 nconv = sscanf (token, SF4, &snum);
1838 fprintf (stderr, "(get_signed) : DTL FILE ERROR (%s) : %s \"%s\".\n",
1839 dtl_filename, "signed number expected, not", token);
1851 (int n, U4 unum, FILE * dvi)
1858 /* put unsigned in-byte integer to dvi file */
1859 /* DVI format uses Big-endian storage of numbers: */
1860 /* most significant byte is first. */
1861 /* return number of bytes written. */
1863 Byte ubyte[4]; /* at most 4 bytes needed in DVI format */
1870 "(put_unsigned) : INTERNAL ERROR : asked for %d bytes. Must be 1 to 4.\n",
1875 /* Big-endian storage. */
1876 for (i = 0; i < n; i++)
1878 ubyte[i] = (Byte) (unum % 256);
1881 /* Reverse order for big-endian representation. */
1882 for (i = n-1; i >= 0; i--)
1884 put_byte ((int) ubyte[i], dvi);
1895 (int n, S4 snum, FILE * dvi)
1902 /* put signed in-byte integer to dvi file */
1903 /* DVI format uses 2's complement Big-endian storage of signed numbers: */
1904 /* most significant byte is first. */
1905 /* return number of bytes written. */
1907 /* Will this deal properly with the sign? */
1913 "(put_signed) : INTERNAL ERROR : asked for %d bytes. Must be 1 to 4.\n",
1918 /* How do we ensure 2's complement representation? */
1919 /* Here's a trick that I hope is portable, given ANSI C. */
1920 /* See K&R (2nd edition), Appendix A6.2 "Integral Conversions". */
1922 /* Convert snum to U4 data type */
1923 put_unsigned (n, (U4) snum, dvi);
1938 /* check that a BMES_CHAR is the next non-whitespace character in dtl */
1940 int ch; /* next non-whitespace character in dtl */
1942 /* `(Void)' because we ignore the number of spaces skipped */
1943 (Void) skip_space (dtl, &ch);
1948 fprintf (stderr, "(check_bmes) : DTL FILE ERROR (%s) : ",
1950 fprintf (stderr, "end of dtl file, or reading error\n");
1954 if (ch != BMES_CHAR)
1957 fprintf (stderr, "(check_bmes) : DTL FILE ERROR (%s) : ",
1959 fprintf (stderr, "BMES_CHAR (`%c') %s, not `%c' (char %d).\n",
1960 BMES_CHAR, "expected before string", ch, ch);
1977 /* check that an EMES_CHAR is the next character in dtl */
1979 int ch; /* dtl character */
1981 if (read_char (dtl, &ch) == 0)
1984 fprintf (stderr, "(check_emes) : DTL FILE ERROR (%s) : ",
1986 fprintf (stderr, "end of dtl file, or reading error\n");
1990 if (ch != EMES_CHAR)
1993 fprintf (stderr, "(check_emes) : DTL FILE ERROR (%s) : ",
1995 fprintf (stderr, "EMES_CHAR (`%c') %s, not `%c' (char %d).\n",
1996 EMES_CHAR, "expected to follow string", ch, ch);
2005 /* Size typically used in this program for Lstring variables */
2012 (Lstring * lsp, long int n)
2021 lsp->s = (char *) gmalloc (n);
2038 lsp->s = NULL; /* to be sure */
2040 /* de_init_Lstring */
2053 lsp = (Lstring *) gmalloc (sizeof (Lstring));
2054 init_Lstring (lsp, n);
2078 (int ch, Lstring * lstr)
2084 /* write byte ch into Lstring *lstr */
2086 if (lstr->l >= lstr->m)
2089 fprintf (stderr, "(ls_putb) : ERROR : No more room in Lstring.\n");
2094 lstr->s [(lstr->l)++] = ch;
2103 (FILE * dtl, Lstring * lstr)
2109 /* get a string from dtl file, store as an Lstring in *lstr. */
2110 /* lstr must already be allocated and initialised. */
2111 /* return length of Lstring *lstr */
2114 int char_status = CHAR_OK; /* OK so far */
2119 fprintf (stderr, "(get_Lstring) : entering get_Lstring.\n");
2128 "(get_Lstring) : string is: \"");
2131 for (nch=0; ; nch++)
2135 char_status = read_string_char (dtl, &ch);
2137 if (char_status == CHAR_FAIL)
2139 /* end of dtl file, or reading error */
2140 fprintf (stderr, "\n");
2142 fprintf (stderr, "(get_Lstring) : DTL FILE ERROR (%s) : ",
2144 fprintf (stderr, "cannot read string[");
2145 fprintf (stderr, UF4, nch);
2146 fprintf (stderr, "] from dtl file.\n");
2152 fprintf (stderr, "%c", ch);
2155 if (char_status == CHAR_EOS)
2157 if (ch != EMES_CHAR)
2160 fprintf (stderr, "(get_Lstring) : INTERNAL ERROR : ");
2161 fprintf (stderr, "char_status = CHAR_FAIL,\n");
2163 "but ch = %c (char %d) is not EMES_CHAR = %c (char %d)\n",
2164 ch, ch, EMES_CHAR, EMES_CHAR);
2167 (Void) unread_char ();
2168 break; /* end of string */
2170 else if (char_status == CHAR_OK)
2177 fprintf (stderr, "(get_Lstring) : INTERNAL ERROR : ");
2178 fprintf (stderr, "char_status = %d is unfamiliar!\n", char_status);
2186 fprintf (stderr, "\".\n");
2194 fprintf (stderr, "(get_Lstring) : leaving get_Lstring.\n");
2205 (const Lstring * lstr, FILE * dvi)
2213 fwret = fwrite ((lstr->s), sizeof (char), (size_t) (lstr->l), dvi);
2215 dvi_written += fwret;
2217 if ((long int) fwret < lstr->l)
2221 "(put_Lstring) : DVI File ERROR : not all bytes written ");
2222 fprintf (stderr, "(%ld of %ld).\n",
2223 (long int) fwret, (long int) (lstr->l));
2233 (int n, FILE * dtl, FILE * dvi)
2240 /* transfer (length and) quoted string from dtl to dvi file, */
2241 /* return number of bytes written to dvi file. */
2243 U4 k, k2, lstr_maxsize;
2249 fprintf (stderr, "(xfer_len_string) : entering xfer_len_string.\n");
2252 /* k[n] : length of special string */
2254 k = get_unsigned (dtl);
2256 lstr_maxsize = (k > LSIZE) ? k : LSIZE;
2257 init_Lstring (&lstr, lstr_maxsize);
2262 fprintf (stderr, "(xfer_len_string) : string's nominal length k = ");
2263 fprintf (stderr, UF4, k);
2264 fprintf (stderr, " characters.\n");
2267 k2 = get_Lstring (dtl, &lstr);
2272 fprintf (stderr, "(xfer_len_string) : WARNING : string length (");
2273 fprintf (stderr, UF4, k);
2274 fprintf (stderr, ") in DTL file is wrong\n");
2275 fprintf (stderr, "Writing correct value (");
2276 fprintf (stderr, UF4, k2);
2277 fprintf (stderr, ") to DVI file\n");
2280 put_unsigned (n, k2, dvi);
2282 put_Lstring (&lstr, dvi);
2287 fprintf (stderr, "(xfer_len_string) : leaving xfer_len_string.\n");
2290 de_init_Lstring (&lstr);
2294 /* xfer_len_string */
2300 (FILE * dtl, FILE * dvi)
2306 /* translate signed 4-byte bop address from dtl to dvi file. */
2307 /* return value of bop address written to DVI file */
2309 S4 snum = 0; /* at most this space needed for byte address */
2310 COUNT nread = 0; /* number of DTL bytes read by read_token */
2311 int nconv = 0; /* number of arguments converted by sscanf */
2312 static Token token = ""; /* DTL token */
2314 nread += read_token (dtl, token);
2316 nconv = sscanf (token, SF4, &snum);
2321 fprintf (stderr, "(xfer_bop_address) : DTL FILE ERROR (%s) : ",
2323 fprintf (stderr, "signed number expected, not \"%s\".\n", token);
2327 if (snum != last_bop_address)
2330 fprintf (stderr, "(xfer_bop_address) : WARNING : byte address (");
2331 fprintf (stderr, WF, snum);
2332 fprintf (stderr, ")\n");
2333 fprintf (stderr, "for previous bop in DTL file is wrong\n");
2334 fprintf (stderr, "Writing correct value (");
2335 fprintf (stderr, WF, last_bop_address);
2336 fprintf (stderr, ") to DVI file\n");
2339 put_signed (4, last_bop_address, dvi);
2341 return last_bop_address;
2343 /* xfer_bop_address */
2347 xfer_postamble_address
2349 (FILE * dtl, FILE * dvi)
2355 /* translate signed 4-byte postamble address from dtl to dvi file. */
2356 /* return value of postamble address written to DVI file */
2358 S4 snum = 0; /* at most this space needed for byte address */
2359 COUNT nread = 0; /* number of DTL bytes read by read_token */
2360 int nconv = 0; /* number of arguments converted by sscanf */
2361 static Token token = ""; /* DTL token */
2363 nread += read_token (dtl, token);
2365 nconv = sscanf (token, SF4, &snum);
2370 fprintf (stderr, "(xfer_postamble_address) : DTL FILE ERROR (%s) : ",
2372 fprintf (stderr, "signed number expected, not \"%s\".\n", token);
2376 if (snum != postamble_address)
2379 fprintf (stderr, "(xfer_postamble_address) : WARNING : byte address (");
2380 fprintf (stderr, WF, snum);
2381 fprintf (stderr, ")\n");
2382 fprintf (stderr, "for postamble in DTL file is wrong\n");
2383 fprintf (stderr, "Writing correct value (");
2384 fprintf (stderr, WF, postamble_address);
2385 fprintf (stderr, ") to DVI file\n");
2388 put_signed (4, postamble_address, dvi);
2390 return postamble_address;
2392 /* xfer_postamble_address */
2398 (op_table table, int opcode, FILE * dtl, FILE * dvi)
2400 (table, opcode, dtl, dvi)
2407 /* table: {char * name; int first, last; op_info * list; }; */
2408 /* op_info: {int code; char * name; int nargs; char * args; }; */
2410 op_info op; /* entry in table */
2412 int pos; /* current position in string being scanned */
2413 static String args = "";
2415 /* Defensive programming. */
2416 if (opcode < table.first || opcode > table.last)
2420 "(put_table) : DTL FILE (OR INTERNAL) ERROR : opcode %d ", opcode);
2421 fprintf (stderr, "is outside table %s [ %d to %d ] !\n",
2422 table.name, table.first, table.last);
2426 op = table.list [ opcode - table.first ];
2428 /* More defensive programming. */
2429 if (opcode != op.code)
2433 "(put_table) : INTERNAL ERROR : opcode %d for command \"%s\"",
2435 fprintf (stderr, " faulty in table \"%s\".\n", table.name);
2439 /* process all the arguments, according to size and sign */
2441 strncpy (args, op.args, MAXSTRLEN);
2444 for (i=0; i < op.nargs; i++)
2447 int nscan = 0; /* number of bytes read by sscanf */
2448 int nconv = 0; /* number of sscanf arguments converted & assigned */
2450 /* sscanf() does NOT advance over its input: */
2451 /* C strings lack internal state information, which C files have. */
2452 /* On Sun/OS, sscanf calls ungetc on the string it reads, */
2453 /* which therefore has to be writable. */
2455 nconv = sscanf (args + pos, "%d%n", &argtype, &nscan);
2457 if (nconv < 1 || nscan < 1)
2461 "(put_table) : INTERNAL ERROR : internal read of table %s failed!\n",
2469 xfer_signed (-argtype, dtl, dvi);
2471 xfer_unsigned (argtype, dtl, dvi);
2480 /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
2486 (FILE * dtl, FILE * dvi, int n)
2493 /* read special (1 <= n <= 4 byte) data from dtl, and write in dvi */
2494 /* return number of bytes written */
2501 fprintf (stderr, "(special) : entering special.\n");
2507 fprintf (stderr, "(special) : DTL FILE ERROR (%s) : special %d, ",
2509 fprintf (stderr, "range is 1 to 4.\n");
2513 /* k[n] : length of special string */
2514 /* x[k] : special string */
2516 nk = xfer_len_string (n, dtl, dvi);
2521 fprintf (stderr, "(special) : leaving special.\n");
2532 (FILE * dtl, FILE * dvi, int suffix)
2539 /* read fontdef fnt_def1 .. fnt_def4 from dtl, and write in dvi */
2540 /* suffix is the fontdef suffix : 1 to 4 */
2541 /* return number of bytes written */
2545 Lstring lstr1, lstr2;
2550 fprintf (stderr, "(fontdef) : entering fontdef.\n");
2553 if (suffix < 1 || suffix > 4)
2556 fprintf (stderr, "(fontdef) : DTL FILE ERROR (%s) : ",
2558 fprintf (stderr, "font def %d, but range is 1 to 4.\n", suffix);
2562 init_Lstring (&lstr1, LSIZE);
2563 init_Lstring (&lstr2, LSIZE);
2568 fprintf (stderr, "(fontdef) : about to read font number.\n");
2571 /* k[suffix] : font number */
2573 k = xfer_signed (suffix, dtl, dvi);
2575 k = xfer_unsigned (suffix, dtl, dvi);
2580 fprintf (stderr, "(fontdef) : font ");
2581 fprintf (stderr, UF4, k);
2582 fprintf (stderr, ".\n");
2586 /* c[4] : (hexadecimal) checksum : I (gt) would prefer this */
2587 xfer_hex (4, dtl, dvi);
2588 #else /*NOT HEX_CHECKSUM */
2589 /* c[4] : checksum (octal, for comparison with tftopl's .pl file) */
2590 xfer_oct (4, dtl, dvi);
2594 xfer_unsigned (4, dtl, dvi);
2597 xfer_unsigned (4, dtl, dvi);
2599 /* If DTL file's edited, a and l may be wrong. */
2601 /* a[1] : length of font `area' (directory) portion of pathname string */
2602 a = get_unsigned (dtl);
2604 /* l[1] : length of font portion of pathname string */
2605 l = get_unsigned (dtl);
2607 /* n[a+l] : font pathname string <= area + font */
2609 a2 = get_Lstring (dtl, &lstr1);
2614 fprintf (stderr, "(fontdef) : WARNING : font area string's length (");
2615 fprintf (stderr, UF4, a);
2616 fprintf (stderr, ") in DTL file is wrong\n");
2617 fprintf (stderr, "Writing correct value (");
2618 fprintf (stderr, UF4, a2);
2619 fprintf (stderr, ") to DVI file\n");
2622 put_unsigned (1, a2, dvi);
2624 l2 = get_Lstring (dtl, &lstr2);
2629 fprintf (stderr, "(fontdef) : WARNING : font string's length (");
2630 fprintf (stderr, UF4, l);
2631 fprintf (stderr, ") in DTL file is wrong\n");
2632 fprintf (stderr, "Writing correct value (");
2633 fprintf (stderr, UF4, l2);
2634 fprintf (stderr, ") to DVI file\n");
2637 put_unsigned (1, l2, dvi);
2639 put_Lstring (&lstr1, dvi);
2640 put_Lstring (&lstr2, dvi);
2642 de_init_Lstring (&lstr2);
2643 de_init_Lstring (&lstr1);
2648 fprintf (stderr, "(fontdef) : leaving fontdef.\n");
2651 return (suffix + 4*4 + 2*1 + a2 + l2);
2659 (FILE * dtl, FILE * dvi)
2665 /* read preamble from dtl, and write in dvi */
2666 /* return number of bytes written */
2673 fprintf (stderr, "(preamble) : entering preamble.\n");
2677 xfer_unsigned (1, dtl, dvi);
2680 xfer_unsigned (4, dtl, dvi);
2683 xfer_unsigned (4, dtl, dvi);
2686 xfer_unsigned (4, dtl, dvi);
2688 /* k[1] : length of comment */
2689 /* x[k] : comment string */
2691 k1 = xfer_len_string (1, dtl, dvi);
2696 fprintf (stderr, "(preamble) : leaving preamble.\n");
2699 return (1 + 3*4 + k1);
2707 (FILE * dtl, FILE * dvi)
2713 /* read postamble from dtl, and write in dvi */
2714 /* return number of bytes written */
2716 postamble_address = dvi_written - 1;
2718 /* p[4] : DVI address of previous bop command */
2719 /* --- unsigned? --- or signed, as I assume? */
2720 /* For, surely p should be -1 if the DVI file has NO bop? */
2721 xfer_bop_address (dtl, dvi);
2724 xfer_unsigned (4, dtl, dvi);
2727 xfer_unsigned (4, dtl, dvi);
2730 xfer_unsigned (4, dtl, dvi);
2733 xfer_unsigned (4, dtl, dvi);
2736 xfer_unsigned (4, dtl, dvi);
2739 xfer_unsigned (2, dtl, dvi);
2742 xfer_unsigned (2, dtl, dvi);
2752 (FILE * dtl, FILE * dvi)
2758 /* read post_post from dtl, and write in dvi */
2759 /* return number of bytes written */
2761 /* hope I'm writing the "223" bytes in an 8-bit clean way */
2762 int n223 = 0; /* number of "223" bytes in final padding */
2764 /* q[4] : DVI address of post command */
2765 /* --- unsigned? --- or signed, as I assume? */
2766 /* what happens if there is NO postamble command? */
2767 /* shouldn't q be -1 then? */
2769 xfer_postamble_address (dtl, dvi);
2771 /* i[1] : DVI identification byte = 2 */
2772 xfer_unsigned (1, dtl, dvi);
2774 for (n223 = 0; true; n223++)
2776 COUNT nread = 0; /* number of DTL bytes read by read_token */
2781 nread = read_token (dtl, token);
2783 /* check whether end of dtl file */
2788 /* dtl file shouldn't end before an ECOM */
2790 fprintf (stderr, "(post_post) : DTL FILE ERROR (%s) : ",
2792 fprintf (stderr, "premature end of DTL file!\n");
2794 "%d complete iterations of \"padding byte\" loop;\n", n223);
2795 fprintf (stderr, "troublesome token = \"%s\"\n", token);
2798 /* leave the "223" loop */
2801 else if (strcmp (token, "223") == 0)
2803 /* token is a "223" padding byte */
2808 /* read a non-empty token that wasn't "223" */
2809 (Void) unread_char ();
2812 if (strcmp (token, ECOM) == 0)
2814 /* end of DTL's post_post command */
2818 /* error : expected end of post_post */
2820 fprintf (stderr, "(post_post) : DTL FILE ERROR (%s) : ",
2822 fprintf (stderr, "token \"%s\" should be ECOM (\"%s\")\n",
2827 /* leave the "223" loop */
2836 fprintf (stderr, "(post_post) : DTL FILE ERROR (%s) : \n",
2838 fprintf (stderr, "fewer than four `223' padding bytes.\n");
2839 fprintf (stderr, "Will write at least four `223' padding bytes.\n");
2842 /* check whether the DVI file size is a multiple of 4 bytes */
2843 if ((dvi_written + n223) % 4 != 0)
2846 fprintf (stderr, "(post_post) : WARNING : \n");
2847 fprintf (stderr, "DVI size ");
2848 fprintf (stderr, WF, dvi_written);
2849 fprintf (stderr, " (bytes) wouldn't be a multiple of 4 !\n");
2851 "Will write (at least four) `223' padding bytes until it is.\n");
2854 /* final padding of DVI file by "223" bytes to a multiple of 4 bytes, */
2855 /* with at least 4 bytes */
2857 for (n223 = 0; (n223 < 4) || (dvi_written % 4 != 0); n223++)
2859 /* add a "223" padding byte */
2860 put_byte (223, dvi);
2863 return (4 + 1 + n223);
2868 /* end of dt2dv.c */