[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 /* t1asm 2 * 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 8 * file. 9 * 10 * Copyright (c) 1992 by I. Lee Hetherington, all rights reserved. 11 * 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 14 * intact. 15 * 16 * I. Lee Hetherington ([email protected]) 17 * 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 ([email protected]). 23 * 24 * Revision 1.1 92/05/22 11:48:46 ilh 25 * initial version 26 * 27 * Ported to Microsoft C/C++ Compiler and MS-DOS operating system by 28 * Kai-Uwe Herbing ([email protected]) 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. 32 * 33 */ 34 35 #ifndef lint 36 static char copyright[] = 37 "@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved."; 38 #ifdef _MSDOS 39 static char portnotice[] = 40 "@(#) Ported to MS-DOS by Kai-Uwe Herbing ([email protected])."; 41 #endif 42 #endif 43 44 /* Note: this is ANSI C. */ 45 46 #ifdef _MSDOS 47 #include <fcntl.h> 48 #include <getopt.h> 49 #include <io.h> 50 #endif 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <ctype.h> 55 #include <limits.h> 56 57 #ifdef WINDOWS 58 # ifdef STANDALONE 59 # define WINDOWS_FUNCTIONS 60 # include "windows.h" 61 # endif 62 #endif 63 64 /* int32 must be at least 32-bit and uint16 must be at least 16-bit */ 65 #if INT_MAX >= 0x7FFFFFFFUL 66 typedef int int32; 67 #else 68 typedef long int32; 69 #endif 70 #if USHRT_MAX >= 0xFFFFUL 71 typedef unsigned short uint16; 72 #else 73 typedef unsigned int uint16; 74 #endif 75 76 #define LINESIZE 256 77 78 #define MAXBLOCKLEN ((1L<<17)-6) 79 #define MINBLOCKLEN ((1L<<8)-6) 80 81 #define MARKER 128 82 #define ASCII 1 83 #define BINARY 2 84 #define DONE 3 85 86 typedef unsigned char byte; 87 88 /* must be visible from outside */ 89 FILE *ifp; 90 FILE *ofp; 91 92 /* flags */ 93 static int pfb = 0; 94 static int active = 0; 95 static int start_charstring = 0; 96 static int in_eexec = 0; 97 98 static char line[LINESIZE]; 99 100 /* lenIV and charstring start command */ 101 static int lenIV = 4; 102 static char cs_start[10]; 103 104 /* for charstring buffering */ 105 static byte charstring_buf[65535]; 106 static byte *charstring_bp; 107 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; 113 114 /* decryption stuff */ 115 static uint16 er, cr; 116 static uint16 c1 = 52845, c2 = 22719; 117 118 /* table of charstring commands */ 119 static struct command { 120 char *name; 121 int one, two; 122 } command_table[] = { 123 { "callothersubr", 12, 16 }, 124 { "callsubr", 10, -1 }, 125 { "closepath", 9, -1 }, 126 { "div", 12, 12 }, 127 { "dotsection", 12, 0 }, 128 { "endchar", 14, -1 }, 129 { "hlineto", 6, -1 }, 130 { "hmoveto", 22, -1 }, 131 { "hsbw", 13, -1 }, 132 { "hstem", 1, -1 }, 133 { "hstem3", 12, 2 }, 134 { "hvcurveto", 31, -1 }, 135 { "pop", 12, 17 }, 136 { "return", 11, -1 }, 137 { "rlineto", 5, -1 }, 138 { "rmoveto", 21, -1 }, 139 { "rrcurveto", 8, -1 }, 140 { "sbw", 12, 7 }, 141 { "seac", 12, 6 }, 142 { "setcurrentpoint", 12, 33 }, 143 { "vhcurveto", 30, -1 }, 144 { "vlineto", 7, -1 }, 145 { "vmoveto", 4, -1 }, 146 { "vstem", 3, -1 }, 147 { "vstem3", 12, 1 }, 148 }; /* alphabetical */ 149 150 /* Two separate encryption functions because eexec and charstring encryption 151 must proceed in parallel. */ 152 153 static byte eencrypt(byte plain) 154 { 155 byte cipher; 156 157 cipher = (byte) (plain ^ (er >> 8)); 158 er = (uint16) ((cipher + er) * c1 + c2); 159 return cipher; 160 } 161 162 static byte cencrypt(byte plain) 163 { 164 byte cipher; 165 166 cipher = (byte) (plain ^ (cr >> 8)); 167 cr = (uint16) ((cipher + cr) * c1 + c2); 168 return cipher; 169 } 170 171 /* This function flushes a buffered PFB block. */ 172 173 static void output_block() 174 { 175 int32 i; 176 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); 182 183 /* output block data */ 184 for (i = 0; i < blockpos; i++) 185 fputc(blockbuf[i], ofp); 186 187 /* mark block buffer empty and uninitialized */ 188 blockpos = -1; 189 } 190 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. */ 194 195 static void output_byte(byte b) 196 { 197 static char *hexchar = "0123456789ABCDEF"; 198 static int hexcol = 0; 199 200 if (pfb) { 201 /* PFB */ 202 if (blockpos < 0) { 203 fputc(MARKER, ofp); 204 fputc(blocktyp, ofp); 205 blockpos = 0; 206 } 207 blockbuf[blockpos++] = b; 208 if (blockpos == blocklen) 209 output_block(); 210 } else { 211 /* PFA */ 212 if (in_eexec) { 213 /* trim hexadecimal lines to 64 columns */ 214 if (hexcol >= 64) { 215 fputc('\n', ofp); 216 hexcol = 0; 217 } 218 fputc(hexchar[(b >> 4) & 0xf], ofp); 219 fputc(hexchar[b & 0xf], ofp); 220 hexcol += 2; 221 } else { 222 fputc(b, ofp); 223 } 224 } 225 } 226 227 /* This function outputs a byte through possible eexec encryption. */ 228 229 static void eexec_byte(byte b) 230 { 231 if (in_eexec) 232 output_byte(eencrypt(b)); 233 else 234 output_byte(b); 235 } 236 237 /* This function outputs a null-terminated string through possible eexec 238 encryption. */ 239 240 static void eexec_string(char *string) 241 { 242 while (*string) 243 eexec_byte((byte) *string++); 244 } 245 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. */ 249 250 static void eexec_start() 251 { 252 eexec_string(line); 253 if (pfb) { 254 output_block(); 255 blocktyp = BINARY; 256 } 257 258 in_eexec = 1; 259 er = 55665; 260 eexec_byte(0); 261 eexec_byte(0); 262 eexec_byte(0); 263 eexec_byte(0); 264 } 265 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. */ 269 270 static void eexec_end() 271 { 272 int i, j; 273 274 if (pfb) { 275 output_block(); 276 blocktyp = ASCII; 277 } else { 278 fputc('\n', ofp); 279 } 280 in_eexec = 0; 281 for (i = 0; i < 8; i++) { 282 for (j = 0; j < 64; j++) 283 eexec_byte('0'); 284 eexec_byte('\n'); 285 } 286 #if 0 287 eexec_string("cleartomark\n"); 288 #endif 289 } 290 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. */ 294 295 static void file_end() 296 { 297 if (pfb) { 298 output_block(); 299 fputc(MARKER, ofp); 300 fputc(DONE, ofp); 301 } 302 } 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. */ 308 309 static void t1asm_getline() 310 { 311 int c; 312 char *p = line; 313 int comment = 0; 314 315 start_charstring = 0; 316 while (p < line + LINESIZE) { 317 c = fgetc(ifp); 318 if (c == EOF) 319 break; 320 if (c == '%') 321 comment = 1; 322 if (active && !comment && c == '{') { 323 start_charstring = 1; 324 break; 325 } 326 *p++ = (char) c; 327 if (c == '\n') 328 break; 329 } 330 *p = '\0'; 331 } 332 333 /* This function is used by the binary search, bsearch(), for command names in 334 the command table. */ 335 336 static int command_compare(const void *key, const void *item) 337 { 338 return strcmp((char *) key, ((struct command *) item)->name); 339 } 340 341 /* This function returns 1 if the string is an integer and 0 otherwise. */ 342 343 static int is_integer(char *string) 344 { 345 if (isdigit(string[0]) || string[0] == '-' || string[0] == '+') { 346 while (*++string && isdigit(*string)) 347 ; /* deliberately empty */ 348 if (!*string) 349 return 1; 350 } 351 return 0; 352 } 353 354 /* This function initializes charstring encryption. Note that this is called 355 at the beginning of every charstring. */ 356 357 static void charstring_start() 358 { 359 int i; 360 361 charstring_bp = charstring_buf; 362 cr = 4330; 363 for (i = 0; i < lenIV; i++) 364 *charstring_bp++ = cencrypt((byte) 0); 365 } 366 367 /* This function encrypts and buffers a single byte of charstring data. */ 368 369 static void charstring_byte(int v) 370 { 371 byte b = (byte) (v & 0xff); 372 373 if (charstring_bp - charstring_buf > sizeof(charstring_buf)) { 374 fprintf(stderr, "error: charstring_buf full (%d bytes)\n", 375 sizeof(charstring_buf)); 376 exit(1); 377 } 378 *charstring_bp++ = cencrypt(b); 379 } 380 381 /* This function outputs buffered, encrypted charstring data through possible 382 eexec encryption. */ 383 384 static void charstring_end() 385 { 386 byte *bp; 387 388 sprintf(line, "%d ", charstring_bp - charstring_buf); 389 eexec_string(line); 390 sprintf(line, "%s ", cs_start); 391 eexec_string(line); 392 for (bp = charstring_buf; bp < charstring_bp; bp++) 393 eexec_byte(*bp); 394 } 395 396 /* This function generates the charstring representation of an integer. */ 397 398 static void charstring_int(int num) 399 { 400 int x; 401 402 if (num >= -107 && num <= 107) { 403 charstring_byte(num + 139); 404 } else if (num >= 108 && num <= 1131) { 405 x = num - 108; 406 charstring_byte(x / 256 + 247); 407 charstring_byte(x % 256); 408 } else if (num >= -1131 && num <= -108) { 409 x = abs(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); 418 } else { 419 fprintf(stderr, 420 "error: cannot format the integer %d, too large\n", num); 421 exit(1); 422 } 423 } 424 425 /* This function parses an entire charstring into integers and commands, 426 outputting bytes through the charstring buffer. */ 427 428 static void parse_charstring() 429 { 430 struct command *cp; 431 432 charstring_start(); 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 */ 438 continue; 439 } 440 if (line[0] == '}') 441 break; 442 if (is_integer(line)) { 443 charstring_int(atoi(line)); 444 } else { 445 cp = (struct command *) 446 bsearch((void *) line, (void *) command_table, 447 sizeof(command_table) / sizeof(struct command), 448 sizeof(struct command), 449 command_compare); 450 if (cp) { 451 charstring_byte(cp->one); 452 if (cp->two >= 0) 453 charstring_byte(cp->two); 454 } else { 455 fprintf(stderr, "error: cannot use `%s' in charstring\n",line); 456 exit(1); 457 } 458 } 459 } 460 charstring_end(); 461 } 462 463 static void usage() 464 { 465 fprintf(stderr, 466 "usage: t1asm [-b] [-l block-length] [input [output]]\n"); 467 fprintf(stderr, 468 "\n-b means output in PFB format, otherwise PFA format.\n"); 469 fprintf(stderr, 470 "The block length applies to the length of blocks in the\n"); 471 fprintf(stderr, 472 "PFB output file; the default is to use the largest possible.\n"); 473 exit(1); 474 } 475 476 static void print_banner() 477 { 478 static char rcs_revision[] = ""; /* removed RCS */ 479 static char revision[20]; 480 481 if (sscanf(rcs_revision, "$Revision: %19s", revision) != 1) 482 revision[0] = '\0'; 483 fprintf(stderr, "This is t1asm %s.\n", revision); 484 } 485 486 #ifdef STANDALONE 487 int main(int argc, char **argv) 488 { 489 char *p, *q, *r; 490 int c; 491 492 extern char *optarg; 493 extern int optind; 494 495 ifp = stdin; 496 ofp = stdout; 497 498 print_banner(); 499 500 /* interpret command line arguments using getopt */ 501 while ((c = getopt(argc, argv, "bl:")) != -1) 502 switch (c) { 503 case 'b': 504 pfb = 1; 505 break; 506 case 'l': 507 blocklen = atoi(optarg); 508 if (blocklen < MINBLOCKLEN) { 509 blocklen = MINBLOCKLEN; 510 fprintf(stderr, 511 "warning: using minimum block length of %d\n", 512 blocklen); 513 } else if (blocklen > MAXBLOCKLEN) { 514 blocklen = MAXBLOCKLEN; 515 fprintf(stderr, 516 "warning: using maximum block length of %d\n", 517 blocklen); 518 } 519 break; 520 default: 521 usage(); 522 break; 523 } 524 if (argc - optind > 2) 525 usage(); 526 527 /* possibly open input & output files */ 528 if (argc - optind >= 1) { 529 ifp = fopen(argv[optind], "r"); 530 if (!ifp) { 531 fprintf(stderr, "error: cannot open %s for reading\n", argv[1]); 532 exit(1); 533 } 534 } 535 if (argc - optind >= 2) { 536 ofp = fopen(argv[optind + 1], "w"); 537 if (!ofp) { 538 fprintf(stderr, "error: cannot open %s for writing\n", argv[2]); 539 exit(1); 540 } 541 } 542 543 #else 544 int runt1asm(int pfbflag) 545 { 546 char *p, *q, *r; 547 548 pfb = pfbflag; 549 #endif 550 551 #ifdef _MSDOS 552 /* If we are processing a PFB (binary) output */ 553 /* file, we must set its file mode to binary. */ 554 if (pfb) 555 _setmode(_fileno(ofp), _O_BINARY); 556 #endif 557 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. */ 562 563 while (!feof(ifp) && !ferror(ifp)) { 564 t1asm_getline(); 565 if (strcmp(line, "currentfile eexec\n") == 0) { 566 eexec_start(); 567 continue; 568 } else if (strstr(line, "/Subrs") && isspace(line[6])) { 569 active = 1; 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, '/'); 576 if (q) { 577 r = cs_start; 578 ++q; 579 while (!isspace(*q) && *q != '{') 580 *r++ = *q++; 581 *r = '\0'; 582 } 583 *p = 's'; /* repair line[] */ 584 } 585 /* output line data */ 586 eexec_string(line); 587 if ((p = strstr(line, "currentfile closefile"))) { 588 eexec_end(); 589 } 590 if (start_charstring) { 591 if (!cs_start[0]) { 592 fprintf(stderr, "error: couldn't find charstring start command\n"); 593 exit(1); 594 } 595 parse_charstring(); 596 } 597 } 598 file_end(); 599 600 fclose(ifp); 601 fclose(ofp); 602 603 return 0; 604 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:08:37 2014 | Cross-referenced by PHPXref 0.7.1 |