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 ** author: I. Lee Hetherington (ilh@lcs.mit.edu)
20 static char sccsid
[] =
21 "@(#) t1asm.c 1.2 10:09:46 5/22/92";
22 static char copyright
[] =
23 "@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.";
26 /* Note: this is ANSI C. */
39 #define BANNER "This is t1asm 1.2.\n"
42 #define MAXBLOCKLEN ((1<<17)-6)
43 #define MINBLOCKLEN ((1<<8)-6)
50 typedef unsigned char byte
;
52 static FILE *ifp
= stdin
;
53 static FILE *ofp
= stdout
;
57 static int active
= 0;
58 static int start_charstring
= 0;
59 static int in_eexec
= 0;
61 static char line
[LINESIZE
+ 1];
63 /* lenIV and charstring start command */
65 static char cs_start
[10];
67 /* for charstring buffering */
68 static byte charstring_buf
[65535];
69 static byte
*charstring_bp
;
71 /* for PFB block buffering */
72 static byte blockbuf
[MAXBLOCKLEN
];
73 static int blocklen
= MAXBLOCKLEN
;
74 static int blockpos
= -1;
75 static int blocktyp
= ASCII
;
77 /* decryption stuff */
78 static unsigned short er
, cr
;
79 static unsigned short c1
= 52845, c2
= 22719;
81 /* table of charstring commands */
82 static struct command
{
86 { "callothersubr", 12, 16 },
87 { "callsubr", 10, -1 },
88 { "closepath", 9, -1 },
90 { "dotsection", 12, 0 },
91 { "endchar", 14, -1 },
94 { "hmoveto", 22, -1 },
98 { "hvcurveto", 31, -1 },
100 { "return", 11, -1 },
101 { "rlineto", 5, -1 },
102 { "rmoveto", 21, -1 },
103 { "rrcurveto", 8, -1 },
106 { "setcurrentpoint", 12, 33 },
107 { "vhcurveto", 30, -1 },
108 { "vlineto", 7, -1 },
109 { "vmoveto", 4, -1 },
112 }; /* alphabetical */
114 /* Two separate decryption functions because eexec and charstring decryption
115 must proceed in parallel. */
117 static byte
eencrypt(byte plain
)
121 cipher
= (plain
^ (er
>> 8));
122 er
= (cipher
+ er
) * c1
+ c2
;
126 static byte
cencrypt(byte plain
)
130 cipher
= (plain
^ (cr
>> 8));
131 cr
= (cipher
+ cr
) * c1
+ c2
;
135 /* This function flushes a buffered PFB block. */
137 static void output_block()
141 /* output four-byte block length */
142 fputc(blockpos
& 0xff, ofp
);
143 fputc((blockpos
>> 8) & 0xff, ofp
);
144 fputc((blockpos
>> 16) & 0xff, ofp
);
145 fputc((blockpos
>> 24) & 0xff, ofp
);
147 /* output block data */
148 for (i
= 0; i
< blockpos
; i
++)
149 fputc(blockbuf
[i
], ofp
);
151 /* mark block buffer empty and uninitialized */
155 /* This function outputs a single byte. If output is in PFB format then output
156 is buffered through blockbuf[]. If output is in PFA format, then output
157 will be hexadecimal if in_eexec is set, ASCII otherwise. */
159 static void output_byte(byte b
)
161 static char *hexchar
= "0123456789ABCDEF";
162 static int hexcol
= 0;
168 fputc(blocktyp
, ofp
);
171 blockbuf
[blockpos
++] = b
;
172 if (blockpos
== blocklen
)
177 /* trim hexadecimal lines to 64 columns */
182 fputc(hexchar
[(b
>> 4) & 0xf], ofp
);
183 fputc(hexchar
[b
& 0xf], ofp
);
191 /* This function outputs a byte through possible eexec encryption. */
193 static void eexec_byte(byte b
)
196 output_byte(eencrypt(b
));
201 /* This function outputs a null-terminated string through possible eexec
204 static void eexec_string(char *string
)
207 eexec_byte((byte
) *string
++);
210 /* This function gets ready for the eexec-encrypted data. If output is in
211 PFB format then flush current ASCII block and get ready for binary block.
212 We start encryption with four random (zero) bytes. */
214 static void eexec_start()
230 /* This function wraps-up the eexec-encrypted data and writes ASCII trailer.
231 If output is in PFB format then this entails flushing binary block and
232 starting an ASCII block. */
234 static void eexec_end()
245 for (i
= 0; i
< 7; i
++) {
246 for (j
= 0; j
< 64; j
++)
250 eexec_string("cleartomark\n");
258 /* This function returns an input line of characters. A line is terminated by
259 length (including terminating null) greater than LINESIZE, a newline \n, or
260 when active (looking for charstrings) by '{'. When terminated by a newline
261 the newline is put into line[]. When terminated by '{', the '{' is not put
262 into line[], and the flag start_charstring is set to 1. */
264 static void getline()
270 start_charstring
= 0;
271 while (p
< line
+ LINESIZE
) {
277 if (active
&& !comment
&& c
== '{') {
278 start_charstring
= 1;
288 /* This function is used by the binary search, bsearch(), for command names in
289 the command table. */
291 static int command_compare(const void *key
, const void *item
)
293 return strcmp((char *) key
, ((struct command
*) item
)->name
);
296 /* This function returns 1 if the string is an integer and 0 otherwise. */
298 static int is_integer(char *string
)
300 if (isdigit(string
[0]) || string
[0] == '-' || string
[0] == '+') {
301 while (*++string
&& isdigit(*string
))
302 ; /* deliberately empty */
309 /* This function initializes charstring encryption. Note that this is called
310 at the beginning of every charstring. */
312 static void charstring_start()
316 charstring_bp
= charstring_buf
;
318 for (i
= 0; i
< lenIV
; i
++)
319 *charstring_bp
++ = cencrypt((byte
) 0);
322 /* This function encrypts and buffers a single byte of charstring data. */
324 static void charstring_byte(v
)
327 byte b
= ((unsigned int)v
) & 0xff;
329 if (charstring_bp
- charstring_buf
> sizeof(charstring_buf
)) {
330 fprintf(stderr
, "error: charstring_buf full (%d bytes)\n",
331 sizeof(charstring_buf
));
334 *charstring_bp
++ = cencrypt(b
);
337 /* This function outputs buffered, encrypted charstring data through possible
340 static void charstring_end()
344 sprintf(line
, "%d %s ", charstring_bp
- charstring_buf
, cs_start
);
346 for (bp
= charstring_buf
; bp
< charstring_bp
; bp
++)
350 /* This function generates the charstring representation of an integer. */
352 static void charstring_int(int num
)
356 if (num
>= -107 && num
<= 107) {
357 charstring_byte(num
+ 139);
358 } else if (num
>= 108 && num
<= 1131) {
360 charstring_byte(x
/ 256 + 247);
361 charstring_byte(x
% 256);
362 } else if (num
>= -1131 && num
<= -108) {
364 charstring_byte(x
/ 256 + 251);
365 charstring_byte(x
% 256);
366 } else if (num
>= (-2147483647-1) && num
<= 2147483647) {
367 charstring_byte(255);
368 charstring_byte(num
>> 24);
369 charstring_byte(num
>> 16);
370 charstring_byte(num
>> 8);
371 charstring_byte(num
);
374 "error: cannot format the integer %d, too large\n", num
);
379 /* This function parses an entire charstring into integers and commands,
380 outputting bytes through the charstring buffer. */
382 static void parse_charstring()
387 while (fscanf(ifp
, "%s", line
) == 1) {
388 if (line
[0] == '%') {
389 /* eat comment to end of line */
390 while (fgetc(ifp
) != '\n' && !feof(ifp
))
391 ; /* deliberately empty */
396 if (is_integer(line
)) {
397 charstring_int(atoi(line
));
399 cp
= (struct command
*)
400 bsearch((void *) line
, (void *) command_table
,
401 sizeof(command_table
) / sizeof(struct command
),
402 sizeof(struct command
),
405 charstring_byte(cp
->one
);
407 charstring_byte(cp
->two
);
409 fprintf(stderr
, "error: cannot use `%s' in charstring\n", cp
->name
);
420 "usage: t1asm [-b] [-l block-length] [input [output]]\n");
422 "\n-b means output in PFB format, otherwise PFA format.\n");
424 "The block length applies to the length of blocks in the\n");
426 "PFB output file; the default is to use the largest possible.\n");
431 int main(int argc
, char **argv
)
438 extern int getopt(int argc
, char **argv
, char *optstring
);
440 fprintf(stderr
, "%s", BANNER
);
442 /* interpret command line arguments using getopt */
443 while ((c
= getopt(argc
, argv
, "bl:")) != -1)
449 blocklen
= atoi(optarg
);
450 if (blocklen
< MINBLOCKLEN
) {
451 blocklen
= MINBLOCKLEN
;
453 "warning: using minimum block length of %d\n",
455 } else if (blocklen
> MAXBLOCKLEN
) {
456 blocklen
= MAXBLOCKLEN
;
458 "warning: using maximum block length of %d\n",
466 if (argc
- optind
> 2)
469 /* possibly open input & output files */
470 if (argc
- optind
>= 1) {
471 ifp
= fopen(argv
[optind
], "r");
473 fprintf(stderr
, "error: cannot open %s for reading\n", argv
[1]);
477 if (argc
- optind
>= 2) {
478 ofp
= fopen(argv
[optind
+ 1], WB
);
480 fprintf(stderr
, "error: cannot open %s for writing\n", argv
[2]);
485 /* Finally, we loop until no more input. Some special things to look for
486 are the `currentfile eexec' line, the beginning of the `/Subrs'
487 definition, the definition of `/lenIV', and the definition of the
488 charstring start command which has `...string currentfile...' in it. */
490 while (!feof(ifp
) && !ferror(ifp
)) {
492 if (strcmp(line
, "currentfile eexec\n") == 0) {
495 } else if (strstr(line
, "/Subrs") && isspace(line
[6])) {
497 } else if ((p
= strstr(line
, "/lenIV"))) {
498 sscanf(p
, "%*s %d", &lenIV
);
499 } else if ((p
= strstr(line
, "string currentfile"))) {
500 /* locate the name of the charstring start command */
501 *p
= '\0'; /* damage line[] */
502 q
= strrchr(line
, '/');
506 while (!isspace(*q
) && *q
!= '{')
510 *p
= 's'; /* repair line[] */
512 /* output line data */
514 if (start_charstring
) {
516 fprintf(stderr
, "error: couldn't find charstring start command\n");