3 * This program `assembles' Adobe Type-1 font programs in pseudo-PostScript
4 * form into either PFB or PFA format. The human readable/editable input is
5 * charstring- and eexec-encrypted as specified in the `Adobe Type 1 Font
6 * Format' version 1.1 (the `black book'). There is a companion program,
7 * t1disasm, which `disassembles' PFB and PFA files into a pseudo-PostScript
10 * Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.
12 * Permission is hereby granted to use, modify, and distribute this program
13 * for any purpose provided this copyright notice and the one below remain
16 * I. Lee Hetherington (ilh@lcs.mit.edu)
18 * Revision 1.2 92/05/22 11:54:45 ilh
19 * Fixed bug where integers larger than 32000 could not be encoded in
20 * charstrings. Now integer range is correct for four-byte
21 * twos-complement integers: -(1<<31) <= i <= (1<<31)-1. Bug detected by
22 * Piet Tutelaers (rcpt@urc.tue.nl).
24 * Revision 1.1 92/05/22 11:48:46 ilh
27 * Ported to Microsoft C/C++ Compiler and MS-DOS operating system by
28 * Kai-Uwe Herbing (herbing@netmbx.netmbx.de) on June 12, 1992. Code
29 * specific to the MS-DOS version is encapsulated with #ifdef _MSDOS
30 * ... #endif, where _MSDOS is an identifier, which is automatically
31 * defined, if you compile with the Microsoft C/C++ Compiler.
36 static char copyright[] =
37 "@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.";
39 static char portnotice[] =
40 "@(#) Ported to MS-DOS by Kai-Uwe Herbing (herbing@netmbx.netmbx.de).";
44 /* Note: this is ANSI C. */
59 # define WINDOWS_FUNCTIONS
60 # include "win_missing.h"
64 /* int32 must be at least 32-bit and uint16 must be at least 16-bit */
65 #if INT_MAX >= 0x7FFFFFFFUL
70 #if USHRT_MAX >= 0xFFFFUL
71 typedef unsigned short uint16;
73 typedef unsigned int uint16;
78 #define MAXBLOCKLEN ((1L<<17)-6)
79 #define MINBLOCKLEN ((1L<<8)-6)
86 typedef unsigned char byte;
88 /* must be visible from outside */
94 static int active = 0;
95 static int start_charstring = 0;
96 static int in_eexec = 0;
98 static char line[LINESIZE];
100 /* lenIV and charstring start command */
101 static int lenIV = 4;
102 static char cs_start[10];
104 /* for charstring buffering */
105 static byte charstring_buf[65535];
106 static byte *charstring_bp;
108 /* for PFB block buffering */
109 static byte blockbuf[MAXBLOCKLEN];
110 static int32 blocklen = MAXBLOCKLEN;
111 static int32 blockpos = -1;
112 static int blocktyp = ASCII;
114 /* decryption stuff */
115 static uint16 er, cr;
116 static uint16 c1 = 52845, c2 = 22719;
118 /* table of charstring commands */
119 static struct command {
122 } command_table[] = {
123 { "callothersubr", 12, 16 },
124 { "callsubr", 10, -1 },
125 { "closepath", 9, -1 },
127 { "dotsection", 12, 0 },
128 { "endchar", 14, -1 },
129 { "hlineto", 6, -1 },
130 { "hmoveto", 22, -1 },
134 { "hvcurveto", 31, -1 },
136 { "return", 11, -1 },
137 { "rlineto", 5, -1 },
138 { "rmoveto", 21, -1 },
139 { "rrcurveto", 8, -1 },
142 { "setcurrentpoint", 12, 33 },
143 { "vhcurveto", 30, -1 },
144 { "vlineto", 7, -1 },
145 { "vmoveto", 4, -1 },
148 }; /* alphabetical */
150 /* Two separate encryption functions because eexec and charstring encryption
151 must proceed in parallel. */
153 static byte eencrypt(byte plain)
157 cipher = (byte) (plain ^ (er >> 8));
158 er = (uint16) ((cipher + er) * c1 + c2);
162 static byte cencrypt(byte plain)
166 cipher = (byte) (plain ^ (cr >> 8));
167 cr = (uint16) ((cipher + cr) * c1 + c2);
171 /* This function flushes a buffered PFB block. */
173 static void output_block()
177 /* output four-byte block length */
178 fputc((int) (blockpos & 0xff), ofp);
179 fputc((int) ((blockpos >> 8) & 0xff), ofp);
180 fputc((int) ((blockpos >> 16) & 0xff), ofp);
181 fputc((int) ((blockpos >> 24) & 0xff), ofp);
183 /* output block data */
184 for (i = 0; i < blockpos; i++)
185 fputc(blockbuf[i], ofp);
187 /* mark block buffer empty and uninitialized */
191 /* This function outputs a single byte. If output is in PFB format then output
192 is buffered through blockbuf[]. If output is in PFA format, then output
193 will be hexadecimal if in_eexec is set, ASCII otherwise. */
195 static void output_byte(byte b)
197 static char *hexchar = "0123456789ABCDEF";
198 static int hexcol = 0;
204 fputc(blocktyp, ofp);
207 blockbuf[blockpos++] = b;
208 if (blockpos == blocklen)
213 /* trim hexadecimal lines to 64 columns */
218 fputc(hexchar[(b >> 4) & 0xf], ofp);
219 fputc(hexchar[b & 0xf], ofp);
227 /* This function outputs a byte through possible eexec encryption. */
229 static void eexec_byte(byte b)
232 output_byte(eencrypt(b));
237 /* This function outputs a null-terminated string through possible eexec
240 static void eexec_string(char *string)
243 eexec_byte((byte) *string++);
246 /* This function gets ready for the eexec-encrypted data. If output is in
247 PFB format then flush current ASCII block and get ready for binary block.
248 We start encryption with four random (zero) bytes. */
250 static void eexec_start()
266 /* This function wraps-up the eexec-encrypted data.
267 If output is in PFB format then this entails flushing binary block and
268 starting an ASCII block. */
270 static void eexec_end()
281 for (i = 0; i < 8; i++) {
282 for (j = 0; j < 64; j++)
287 eexec_string("cleartomark\n");
291 /* This function writes ASCII trailer.
292 If output is in PFB format then this entails flushing binary block and
293 starting an ASCII block. */
295 static void file_end()
303 /* This function returns an input line of characters. A line is terminated by
304 length (including terminating null) greater than LINESIZE, a newline \n, or
305 when active (looking for charstrings) by '{'. When terminated by a newline
306 the newline is put into line[]. When terminated by '{', the '{' is not put
307 into line[], and the flag start_charstring is set to 1. */
309 static void t1asm_getline()
315 start_charstring = 0;
316 while (p < line + LINESIZE) {
322 if (active && !comment && c == '{') {
323 start_charstring = 1;
333 /* This function is used by the binary search, bsearch(), for command names in
334 the command table. */
336 static int command_compare(const void *key, const void *item)
338 return strcmp((char *) key, ((struct command *) item)->name);
341 /* This function returns 1 if the string is an integer and 0 otherwise. */
343 static int is_integer(char *string)
345 if (isdigit(string[0]) || string[0] == '-' || string[0] == '+') {
346 while (*++string && isdigit(*string))
347 ; /* deliberately empty */
354 /* This function initializes charstring encryption. Note that this is called
355 at the beginning of every charstring. */
357 static void charstring_start()
361 charstring_bp = charstring_buf;
363 for (i = 0; i < lenIV; i++)
364 *charstring_bp++ = cencrypt((byte) 0);
367 /* This function encrypts and buffers a single byte of charstring data. */
369 static void charstring_byte(int v)
371 byte b = (byte) (v & 0xff);
373 if (charstring_bp - charstring_buf > sizeof(charstring_buf)) {
374 fprintf(stderr, "error: charstring_buf full (%d bytes)\n",
375 sizeof(charstring_buf));
378 *charstring_bp++ = cencrypt(b);
381 /* This function outputs buffered, encrypted charstring data through possible
384 static void charstring_end()
388 sprintf(line, "%d ", charstring_bp - charstring_buf);
390 sprintf(line, "%s ", cs_start);
392 for (bp = charstring_buf; bp < charstring_bp; bp++)
396 /* This function generates the charstring representation of an integer. */
398 static void charstring_int(int num)
402 if (num >= -107 && num <= 107) {
403 charstring_byte(num + 139);
404 } else if (num >= 108 && num <= 1131) {
406 charstring_byte(x / 256 + 247);
407 charstring_byte(x % 256);
408 } else if (num >= -1131 && num <= -108) {
410 charstring_byte(x / 256 + 251);
411 charstring_byte(x % 256);
412 } else if (num >= (-2147483647-1) && num <= 2147483647) {
413 charstring_byte(255);
414 charstring_byte(num >> 24);
415 charstring_byte(num >> 16);
416 charstring_byte(num >> 8);
417 charstring_byte(num);
420 "error: cannot format the integer %d, too large\n", num);
425 /* This function parses an entire charstring into integers and commands,
426 outputting bytes through the charstring buffer. */
428 static void parse_charstring()
433 while (fscanf(ifp, "%s", line) == 1) {
434 if (line[0] == '%') {
435 /* eat comment to end of line */
436 while (fgetc(ifp) != '\n' && !feof(ifp))
437 ; /* deliberately empty */
442 if (is_integer(line)) {
443 charstring_int(atoi(line));
445 cp = (struct command *)
446 bsearch((void *) line, (void *) command_table,
447 sizeof(command_table) / sizeof(struct command),
448 sizeof(struct command),
451 charstring_byte(cp->one);
453 charstring_byte(cp->two);
455 fprintf(stderr, "error: cannot use `%s' in charstring\n",line);
466 "usage: t1asm [-b] [-l block-length] [input [output]]\n");
468 "\n-b means output in PFB format, otherwise PFA format.\n");
470 "The block length applies to the length of blocks in the\n");
472 "PFB output file; the default is to use the largest possible.\n");
476 static void print_banner()
478 static char rcs_revision[] = ""; /* removed RCS */
479 static char revision[20];
481 if (sscanf(rcs_revision, "$Revision: %19s", revision) != 1)
483 fprintf(stderr, "This is t1asm %s.\n", revision);
487 int main(int argc, char **argv)
500 /* interpret command line arguments using getopt */
501 while ((c = getopt(argc, argv, "bl:")) != -1)
507 blocklen = atoi(optarg);
508 if (blocklen < MINBLOCKLEN) {
509 blocklen = MINBLOCKLEN;
511 "warning: using minimum block length of %d\n",
513 } else if (blocklen > MAXBLOCKLEN) {
514 blocklen = MAXBLOCKLEN;
516 "warning: using maximum block length of %d\n",
524 if (argc - optind > 2)
527 /* possibly open input & output files */
528 if (argc - optind >= 1) {
529 ifp = fopen(argv[optind], "r");
531 fprintf(stderr, "error: cannot open %s for reading\n", argv[1]);
535 if (argc - optind >= 2) {
536 ofp = fopen(argv[optind + 1], "w");
538 fprintf(stderr, "error: cannot open %s for writing\n", argv[2]);
544 int runt1asm(int pfbflag)
552 /* If we are processing a PFB (binary) output */
553 /* file, we must set its file mode to binary. */
555 _setmode(_fileno(ofp), _O_BINARY);
558 /* Finally, we loop until no more input. Some special things to look for
559 are the `currentfile eexec' line, the beginning of the `/Subrs'
560 definition, the definition of `/lenIV', and the definition of the
561 charstring start command which has `...string currentfile...' in it. */
563 while (!feof(ifp) && !ferror(ifp)) {
565 if (strcmp(line, "currentfile eexec\n") == 0) {
568 } else if (strstr(line, "/Subrs") && isspace(line[6])) {
570 } else if ((p = strstr(line, "/lenIV"))) {
571 sscanf(p, "%*s %d", &lenIV);
572 } else if ((p = strstr(line, "string currentfile"))) {
573 /* locate the name of the charstring start command */
574 *p = '\0'; /* damage line[] */
575 q = strrchr(line, '/');
579 while (!isspace(*q) && *q != '{')
583 *p = 's'; /* repair line[] */
585 /* output line data */
587 if ((p = strstr(line, "currentfile closefile"))) {
590 if (start_charstring) {
592 fprintf(stderr, "error: couldn't find charstring start command\n");