⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 t1asm.c

📁 字体缩放显示
💻 C
字号:
/* t1asm**** This program `assembles' Adobe Type-1 font programs in pseudo-PostScript** form into either PFB or PFA format.  The human readable/editable input is** charstring- and eexec-encrypted as specified in the `Adobe Type 1 Font** Format' version 1.1 (the `black book').  There is a companion program,** t1disasm, which `disassembles' PFB and PFA files into a pseudo-PostScript** file.**** Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.**** Permission is hereby granted to use, modify, and distribute this program** for any purpose provided this copyright notice and the one below remain** intact. **** author: I. Lee Hetherington (ilh@lcs.mit.edu)*/#ifndef lintstatic char sccsid[] =  "@(#) t1asm.c 1.2 10:09:46 5/22/92";static char copyright[] =  "@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.";#endif/* Note: this is ANSI C. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#ifdef MSDOS#define WB "wb"#else#define WB "w"#endif#define BANNER   "This is t1asm 1.2.\n"#define LINESIZE 256#define MAXBLOCKLEN ((1<<17)-6)#define MINBLOCKLEN ((1<<8)-6)#define MARKER   128#define ASCII    1#define BINARY   2#define DONE     3typedef unsigned char byte;static FILE *ifp;static FILE *ofp;/* flags */static int pfb = 0;static int active = 0;static int start_charstring = 0;static int in_eexec = 0;static char line[LINESIZE + 1];/* lenIV and charstring start command */static int lenIV = 4;static char cs_start[10];/* for charstring buffering */static byte charstring_buf[65535];static byte *charstring_bp;/* for PFB block buffering */static byte blockbuf[MAXBLOCKLEN];static int blocklen = MAXBLOCKLEN;static int blockpos = -1;static int blocktyp = ASCII;/* decryption stuff */static unsigned short er, cr;static unsigned short c1 = 52845, c2 = 22719;/* table of charstring commands */static struct command {  char *name;  int one, two;} command_table[] = {  { "callothersubr", 12, 16 },  { "callsubr", 10, -1 },  { "closepath", 9, -1 },  { "div", 12, 12 },  { "dotsection", 12, 0 },  { "endchar", 14, -1 },  { "escape", 12, -1 },  { "hlineto", 6, -1 },  { "hmoveto", 22, -1 },  { "hsbw", 13, -1 },  { "hstem", 1, -1 },  { "hstem3", 12, 2 },  { "hvcurveto", 31, -1 },  { "pop", 12, 17 },  { "return", 11, -1 },  { "rlineto", 5, -1 },  { "rmoveto", 21, -1 },  { "rrcurveto", 8, -1 },  { "sbw", 12, 7 },  { "seac", 12, 6 },  { "setcurrentpoint", 12, 33 },  { "vhcurveto", 30, -1 },  { "vlineto", 7, -1 },  { "vmoveto", 4, -1 },  { "vstem", 3, -1 },  { "vstem3", 12, 1 },};						  /* alphabetical *//* Two separate decryption functions because eexec and charstring decryption    must proceed in parallel. */static byte eencrypt(byte plain){  byte cipher;  cipher = (plain ^ (er >> 8));  er = (cipher + er) * c1 + c2;  return cipher;}static byte cencrypt(byte plain){  byte cipher;  cipher = (plain ^ (cr >> 8));  cr = (cipher + cr) * c1 + c2;  return cipher;}/* This function flushes a buffered PFB block. */static void output_block(){  int i;  /* output four-byte block length */  fputc(blockpos & 0xff, ofp);  fputc((blockpos >> 8) & 0xff, ofp);  fputc((blockpos >> 16) & 0xff, ofp);  fputc((blockpos >> 24) & 0xff, ofp);  /* output block data */  for (i = 0; i < blockpos; i++)    fputc(blockbuf[i], ofp);  /* mark block buffer empty and uninitialized */  blockpos =  -1;}/* This function outputs a single byte.  If output is in PFB format then output   is buffered through blockbuf[].  If output is in PFA format, then output   will be hexadecimal if in_eexec is set, ASCII otherwise. */static void output_byte(byte b){  static char *hexchar = "0123456789ABCDEF";  static int hexcol = 0;  if (pfb) {    /* PFB */    if (blockpos < 0) {      fputc(MARKER, ofp);      fputc(blocktyp, ofp);      blockpos = 0;    }    blockbuf[blockpos++] = b;    if (blockpos == blocklen)      output_block();  } else {    /* PFA */    if (in_eexec) {      /* trim hexadecimal lines to 64 columns */      if (hexcol >= 64) {	fputc('\n', ofp);	hexcol = 0;      }      fputc(hexchar[(b >> 4) & 0xf], ofp);      fputc(hexchar[b & 0xf], ofp);      hexcol += 2;    } else {      fputc(b, ofp);    }  }}/* This function outputs a byte through possible eexec encryption. */static void eexec_byte(byte b){  if (in_eexec)    output_byte(eencrypt(b));  else    output_byte(b);}/* This function outputs a null-terminated string through possible eexec   encryption. */static void eexec_string(char *string){  while (*string)    eexec_byte((byte) *string++);}/* This function gets ready for the eexec-encrypted data.  If output is in   PFB format then flush current ASCII block and get ready for binary block.   We start encryption with four random (zero) bytes. */static void eexec_start(){  eexec_string(line);  if (pfb) {    output_block();    blocktyp = BINARY;  }  in_eexec = 1;  er = 55665;  eexec_byte(0);  eexec_byte(0);  eexec_byte(0);  eexec_byte(0);}/* This function wraps-up the eexec-encrypted data and writes ASCII trailer.   If output is in PFB format then this entails flushing binary block and   starting an ASCII block. */static void eexec_end(){  int i, j;  if (pfb) {    output_block();    blocktyp = ASCII;  } else {    fputc('\n', ofp);  }  in_eexec = 0;  for (i = 0; i < 7; i++) {    for (j = 0; j < 64; j++)      eexec_byte('0');    eexec_byte('\n');  }  eexec_string("cleartomark\n");  if (pfb) {    output_block();    fputc(MARKER, ofp);    fputc(DONE, ofp);  }}/* This function returns an input line of characters.  A line is terminated by   length (including terminating null) greater than LINESIZE, a newline \n, or   when active (looking for charstrings) by '{'.  When terminated by a newline   the newline is put into line[].  When terminated by '{', the '{' is not put   into line[], and the flag start_charstring is set to 1. */static void getline(){  int c;  char *p = line;  int comment = 0;  start_charstring = 0;  while (p < line + LINESIZE) {    c = fgetc(ifp);    if (c == EOF)      break;    if (c == '%')      comment = 1;    if (active && !comment && c == '{') {      start_charstring = 1;      break;    }    *p++ = (char) c;    if (c == '\n')      break;  }  *p = '\0';}/* This function is used by the binary search, bsearch(), for command names in   the command table. */static int command_compare(const void *key, const void *item){  return strcmp((char *) key, ((struct command *) item)->name);}/* This function returns 1 if the string is an integer and 0 otherwise. */static int is_integer(char *string){  if (isdigit(string[0]) || string[0] == '-' || string[0] == '+') {    while (*++string && isdigit(*string))      ;						  /* deliberately empty */    if (!*string)      return 1;  }  return 0;}/* This function initializes charstring encryption.  Note that this is called   at the beginning of every charstring. */static void charstring_start(){  int i;  charstring_bp = charstring_buf;  cr = 4330;  for (i = 0; i < lenIV; i++)    *charstring_bp++ = cencrypt((byte) 0);}/* This function encrypts and buffers a single byte of charstring data. */static void charstring_byte(v)  int v;{  byte b = ((unsigned int)v) & 0xff;  if (charstring_bp - charstring_buf > sizeof(charstring_buf)) {    fprintf(stderr, "error: charstring_buf full (%d bytes)\n",	    sizeof(charstring_buf));    exit(1);  }  *charstring_bp++ = cencrypt(b);}/* This function outputs buffered, encrypted charstring data through possible   eexec encryption. */static void charstring_end(){  byte *bp;  sprintf(line, "%d %s ", charstring_bp - charstring_buf, cs_start);  eexec_string(line);  for (bp = charstring_buf; bp < charstring_bp; bp++)    eexec_byte(*bp);}/* This function generates the charstring representation of an integer. */static void charstring_int(int num){  int x;  if (num >= -107 && num <= 107) {    charstring_byte(num + 139);  } else if (num >= 108 && num <= 1131) {    x = num - 108;    charstring_byte(x / 256 + 247);    charstring_byte(x % 256);  } else if (num >= -1131 && num <= -108) {    x = abs(num) - 108;    charstring_byte(x / 256 + 251);    charstring_byte(x % 256);  } else if (num >= (-2147483647-1) && num <= 2147483647) {    charstring_byte(255);    charstring_byte(num >> 24);    charstring_byte(num >> 16);    charstring_byte(num >> 8);    charstring_byte(num);  } else {    fprintf(stderr,	    "error: cannot format the integer %d, too large\n", num);    exit(1);  }}/* This function parses an entire charstring into integers and commands,   outputting bytes through the charstring buffer. */static void parse_charstring(){  struct command *cp;  charstring_start();  while (fscanf(ifp, "%s", line) == 1) {    if (line[0] == '%') {      /* eat comment to end of line */      while (fgetc(ifp) != '\n' && !feof(ifp))	;					  /* deliberately empty */      continue;    }    if (line[0] == '}')      break;    if (is_integer(line)) {      charstring_int(atoi(line));    } else {      cp = (struct command *)	bsearch((void *) line, (void *) command_table,		sizeof(command_table) / sizeof(struct command),		sizeof(struct command),		command_compare);      if (cp) {	charstring_byte(cp->one);	if (cp->two >= 0)	  charstring_byte(cp->two);      } else {	fprintf(stderr, "error: cannot use `%s' in charstring\n", cp->name);	exit(1);      }    }  }  charstring_end();}static void usage(){  fprintf(stderr,	  "usage: t1asm [-b] [-l block-length] [input [output]]\n");  fprintf(stderr,	  "\n-b means output in PFB format, otherwise PFA format.\n");  fprintf(stderr,	  "The block length applies to the length of blocks in the\n");  fprintf(stderr,	  "PFB output file; the default is to use the largest possible.\n");  exit(1);}int main(int argc, char **argv){  char *p, *q, *r;  int c;  extern char *optarg;  extern int optind;  extern int getopt(int argc, char **argv, char *optstring);  ifp = stdin;  ofp = stdout;  fprintf(stderr, "%s", BANNER);  /* interpret command line arguments using getopt */  while ((c = getopt(argc, argv, "bl:")) != -1)    switch (c) {    case 'b':      pfb = 1;      break;    case 'l':      blocklen = atoi(optarg);      if (blocklen < MINBLOCKLEN) {	blocklen = MINBLOCKLEN;	fprintf(stderr,		"warning: using minimum block length of %d\n",		blocklen);      } else if (blocklen > MAXBLOCKLEN) {	blocklen = MAXBLOCKLEN;	fprintf(stderr,		"warning: using maximum block length of %d\n",		blocklen);      }      break;    default:      usage();      break;    }  if (argc - optind > 2)    usage();  /* possibly open input & output files */  if (argc - optind >= 1) {    ifp = fopen(argv[optind], "r");    if (!ifp) {      fprintf(stderr, "error: cannot open %s for reading\n", argv[1]);      exit(1);    }  }  if (argc - optind >= 2) {    ofp = fopen(argv[optind + 1], WB);    if (!ofp) {      fprintf(stderr, "error: cannot open %s for writing\n", argv[2]);      exit(1);    }  }  /* Finally, we loop until no more input.  Some special things to look for     are the `currentfile eexec' line, the beginning of the `/Subrs'     definition, the definition of `/lenIV', and the definition of the     charstring start command which has `...string currentfile...' in it. */  while (!feof(ifp) && !ferror(ifp)) {    getline();    if (strcmp(line, "currentfile eexec\n") == 0) {      eexec_start();      continue;    } else if (strstr(line, "/Subrs") && isspace(line[6])) {      active = 1;    } else if ((p = strstr(line, "/lenIV"))) {      sscanf(p, "%*s %d", &lenIV);    } else if ((p = strstr(line, "string currentfile"))) {      /* locate the name of the charstring start command */      *p = '\0';				  /* damage line[] */      q = strrchr(line, '/');      if (q) {	r = cs_start;	++q;	while (!isspace(*q) && *q != '{')	  *r++ = *q++;	*r = '\0';      }      *p = 's';					  /* repair line[] */    }    /* output line data */    eexec_string(line);    if (start_charstring) {      if (!cs_start[0]) {	fprintf(stderr, "error: couldn't find charstring start command\n");	exit(1);      }      parse_charstring();    }  }  eexec_end();  fclose(ifp);  fclose(ofp);  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -