home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2188 < prev    next >
Encoding:
Internet Message Format  |  1990-12-28  |  11.2 KB

  1. From: kevin@kosman.UUCP (Kevin O'Gorman)
  2. Newsgroups: comp.lang.postscript,comp.fonts,alt.sources
  3. Subject: Untype1.c program -- a pipeline, more portable version
  4. Message-ID: <1270@kosman.UUCP>
  5. Date: 3 Dec 90 23:59:16 GMT
  6.  
  7. A little while ago, Chris Sears (sears@dungeon.enet.dec.com) posted a
  8. set of programs to decode eexec-ed type 1 font programs.  I had some
  9. trouble with that version, especially on MSDOS, so I combined some stuff
  10. and made this version, which compiles on MSC 5.1 and 6.00A, as well as
  11. under gcc on my SYSV UNIX.  It should be reasonably portable, since
  12. the machines differ in word-size and endianness.  There are some SYSV-isms,
  13. but just in the names of include files, I think.  Also, see NEED_STRSTR.
  14.  
  15. This routine also can be used in a pipeline.  Specify - for the standard
  16. input.  Output is always on stdout.
  17.  
  18. I HAVE been having some trouble with it though -- the resulting
  19. PostScript seems always to get a VMERROR on my LaserWriter Plus, on any
  20. real font.  Ideas?  The result is informative anyway.
  21.  
  22. I tried sending this to Chris first, but email to the indicated address
  23. does not work.  Chris, thanks for the original.
  24.  
  25. This is a single source file, not in shar format.  Beware the trailing
  26. signature.
  27.  
  28. /*
  29.  * untype1.c -- decrypt an Adobe font file encrypted for eexec
  30.  *
  31.  * original by Chris B. Sears (sears@dungeon.enet.dec.com)
  32.  *
  33.  * Modified for portability by Kevin O'Gorman (kosman!kevin), because MSDOS
  34.  * had trouble with intermediate files that were mixed binary and text, and
  35.  * because it's really all one task. (3 Dec 1990)
  36.  *
  37.  * The original was distributed without a copyright notice, and no comment
  38.  * about the status.  I take that to place it in the public domain.  I
  39.  * (Kevin O'Gorman) specifically place my modifications in the public domain
  40.  * -- I assert no rights, and accept no responsibility.
  41.  *
  42.  * As a courtesy, I request that notices of authorship be kept honest and
  43.  * complete (and don't forget your own).
  44.  *
  45.  * usage:
  46.  *    untype1 [-s] inputfile
  47.  *
  48.  * The optional -s switch causes the output to be truncated at the first line
  49.  * containing the token "definefont".  This is useful in conjunction with the
  50.  * shell scripts distributed by Chris Sears.
  51.  *
  52.  * The font-related code assumes that the font is eexec encoded (they almost
  53.  * always are); the copying loop for stuff outside of eexec does not check
  54.  * for font-related things.  Further, the RD and -| tokens are hardwired in.
  55.  *
  56.  * Inputfile may be specified as "-".
  57.  *
  58.  * The decoded result is placed on the standard output.
  59.  *
  60.  * Current status: the results get VMerrors on my LaserWriter Plus, even if
  61.  * I setpacking to true.  The results are nevertheless very informative.
  62.  *
  63.  * Things to do:
  64.  *   1: directly turn a type1 into a type3 font.
  65.  *   2: draw the font characters large, with the hints and control points
  66.  *       made visible.
  67.  *   3: decode printer internal fonts (type 5).
  68.  *   4: strip ^D (from some postscript files) and ^Z (from MSDOS) characters.
  69.  */
  70.  
  71. #include <stdio.h>
  72. #include <string.h>
  73. #include <ctype.h>
  74. #define    SEEK_SET    0
  75.  
  76. #define TRUE                1
  77. #define FALSE                0
  78.  
  79. #define EEXEC_SKIP_BYTES    4
  80. #define MAX_ESCAPE        33
  81.  
  82. int lenIV = 4;            /* CharString salt length */
  83.  
  84. typedef struct {
  85.     char *command;
  86.     int value;
  87. } Command;
  88.  
  89. #define    BUFFERSIZE    4096
  90. static int    skip_salt = EEXEC_SKIP_BYTES + 1;
  91. static FILE    *in;
  92. static char    in_buff[BUFFERSIZE], out_buff[BUFFERSIZE];
  93. static int    in_size, in_ptr;
  94. static int    o, obase;
  95. static unsigned short int
  96.         cr, cc1, cc2, er, ec1, ec2;
  97. #define    ER    55665
  98. #define EC1    52845
  99. #define    EC2    22719
  100. #define CR    4330
  101. #define CC1    52845
  102. #define CC2    22719
  103. static int    count, csalt;
  104.  
  105. Command commands[] = {
  106.     { "notdefined_c0",    0 },
  107.     { "hstem",            1 },
  108.     { "notdefined_c2",    2 },
  109.     { "vstem",            3 },
  110.     { "vmoveto",        4 },
  111.     { "chars_rlineto",    5 },
  112.     { "hlineto",        6 },
  113.     { "vlineto",        7 },
  114.     { "rrcurveto",        8 },
  115.     { "chars_closepath",9 },
  116.     { "callsubr",        10 },
  117.     { "return",            11 },
  118.     { "escape",            12 },
  119.     { "hsbw",            13 },
  120.     { "endchar",        14 },
  121.     { "notdefined_c15",    15 },
  122.     { "notdefined_c16",    16 },
  123.     { "notdefined_c17",    17 },
  124.     { "notdefined_c18",    18 },
  125.     { "notdefined_c19",    19 },
  126.     { "notdefined_c20",    20 },
  127.     { "chars_rmoveto",    21 },
  128.     { "hmoveto",        22 },
  129.     { "notdefined_c23",    23 },
  130.     { "notdefined_c24",    24 },
  131.     { "notdefined_c25",    25 },
  132.     { "notdefined_c26",    26 },
  133.     { "notdefined_c27",    27 },
  134.     { "notdefined_c28",    28 },
  135.     { "notdefined_c29",    29 },
  136.     { "vhcurveto",        30 },
  137.     { "hvcurveto",        31 }
  138. };
  139.  
  140. Command escapes[] = {
  141.     { "dotsection",        0 },
  142.     { "vstem3",            1 },
  143.     { "hstem3",            2 },
  144.     { "notdefined_e3",    3 },
  145.     { "notdefined_e4",    4 },
  146.     { "notdefined_e5",    5 },
  147.     { "seac",            6 },
  148.     { "sbw",            7 },
  149.     { "notdefined_e8",    8 },
  150.     { "notdefined_e9",    9 },
  151.     { "notdefined_e10",    10 },
  152.     { "notdefined_e11",    11 },
  153.     { "chars_div",        12 },
  154.     { "notdefined_e13",    13 },
  155.     { "notdefined_e14",    14 },
  156.     { "notdefined_e15",    15 },
  157.     { "callothersubr",    16 },
  158.     { "chars_pop",        17 },
  159.     { "notdefined_e18",    18 },
  160.     { "notdefined_e19",    19 },
  161.     { "notdefined_e20",    20 },
  162.     { "notdefined_e21",    21 },
  163.     { "notdefined_e22",    22 },
  164.     { "notdefined_e23",    23 },
  165.     { "notdefined_e24",    24 },
  166.     { "notdefined_e25",    25 },
  167.     { "notdefined_e26",    26 },
  168.     { "notdefined_e27",    27 },
  169.     { "notdefined_e28",    28 },
  170.     { "notdefined_e29",    29 },
  171.     { "notdefined_e30",    30 },
  172.     { "notdefined_e31",    31 },
  173.     { "notdefined_e32",    32 },
  174.     { "setcurrentpoint",33 }
  175. };
  176.  
  177. unsigned char GetPlain()
  178. {
  179.     if (in_ptr >= in_size) {
  180.         if(fgets(in_buff, BUFSIZ, in) == NULL) {
  181.             fprintf(stderr,"Errror -- end of file.\n");
  182.             exit(1);
  183.         }
  184.         in_size = strlen(in_buff) - 1;
  185.         in_ptr = 0;
  186.     }
  187.     return in_buff[in_ptr++];
  188. }
  189.  
  190. unsigned int GetHexChar()
  191. {
  192.     unsigned int byte;
  193.  
  194.     /* skip whitespace */
  195.     do {
  196.         byte = GetPlain();
  197.     } while   ((byte == '\n') || (byte == ' ') || (byte == '\t')
  198.         || (byte == '\r') || (byte == '\f'));
  199.  
  200.     /* figure the digit */
  201.     if ( (byte >= '0') && (byte <= '9') ) return (byte - '0');
  202.     if ( (byte >= 'A') && (byte <= 'F') ) return (byte - 'A' + 10);
  203.     if ( (byte >= 'a') && (byte <= 'f') ) return (byte - 'a' + 10);
  204.  
  205.     /* anything else is an error */
  206.     fprintf(stderr, "Illegal hex digit.\n");
  207.     exit (1);
  208. }
  209.  
  210. unsigned char
  211. EDeCrypt()
  212. {
  213.     unsigned char ch1, ch2, plain, cipher;
  214.  
  215.     /*
  216.      * Decode cipher.
  217.      */
  218.     do {
  219.         ch1 = GetHexChar();
  220.         ch2 = GetHexChar();
  221.         cipher = (ch1 << 4) + ch2;
  222.  
  223.         plain = (cipher ^ (er >> 8));
  224.         er = (cipher + er) * ec1 + ec2;
  225.         if (skip_salt) skip_salt--;
  226.     } while (skip_salt);
  227.     
  228.     return plain;
  229. }
  230.  
  231. unsigned char
  232. CDeCrypt()
  233. {
  234.     unsigned char plain, cypher;
  235.     if (count <= 0) {
  236.         fprintf(stderr,"Reading too many bytes of charstring data.\n");
  237.         exit(1);
  238.     }
  239.     do {
  240.         cypher = EDeCrypt();
  241.         count--;
  242.         plain = (cypher ^ (cr >> 8));
  243.         cr = (cypher + cr) * cc1 + cc2;
  244.         if (csalt) csalt--;
  245.     } while (csalt);
  246.     
  247.     return plain;
  248. }
  249.  
  250. #ifdef    NEED_STRSTR
  251. char *
  252. strstr(char *string, char *target)
  253. {
  254.     int slen, tlen, i;
  255.     tlen = strlen(target);
  256.     slen = strlen(string);
  257.     for (i=0; i+tlen <= slen; i++) {
  258.         if (!strncmp(target, &string[i],tlen)) return (&string[i]);
  259.     }
  260.     return NULL;
  261. }
  262. #endif
  263.  
  264. void
  265. out_check()
  266. {
  267.     out_buff[o] = '\0';        /* terminate the string */
  268.                     /* mostly serves to help use CodeView */
  269.     if (o-obase > 78) {
  270.         int ptr;
  271.         unsigned char c;
  272.         
  273.         for (ptr=obase+78; ptr>obase; ptr--) {
  274.             c = out_buff[ptr];
  275.             if(c==' ' || c=='\t') break;
  276.         }
  277.         if (ptr-obase < 10) return;
  278.         for (; ptr>obase; ptr--) {
  279.             c = out_buff[ptr];
  280.             if (isalpha(c)) break;
  281.         }
  282.         if (ptr-obase < 10) return;
  283.         for (;; ptr++) {
  284.             c = out_buff[ptr];
  285.             if(c==' ' || c=='\t') break;
  286.         }
  287.         out_buff[ptr] = '\0';
  288.         fputs(out_buff, stdout);
  289.         strcpy(out_buff,"\n\t");
  290.         strcat(out_buff,&out_buff[ptr+1]);
  291.         o = strlen(out_buff);
  292.         obase = -6;
  293.     }
  294. }
  295.  
  296.  
  297. void
  298. main(argc, argv)
  299.     int argc;
  300.     char **argv;
  301. {
  302.     unsigned char plainchar;
  303.     char *count_pos;
  304.     int i;
  305.     int line_pos;
  306.     long value;
  307. #define    DATA_STATE    0
  308. #define    CHAR_STATE    1
  309. #define    CINZ_STATE    2
  310.     int state = DATA_STATE;
  311.     unsigned char byte;
  312.     
  313.     if ((argc != 2 && argc != 3)
  314.         || (argc == 3 && strcmp(argv[1],"-s"))) {
  315.         fprintf(stderr, "Usage: %s [-s] input\n", argv[0]);
  316.         exit(0);
  317.     }
  318.  
  319.     if (strcmp(argv[argc-1], "-")) {
  320.         if ((in = fopen(argv[argc-1], "r")) == NULL) {
  321.             fprintf(stderr,
  322.                 "%s: can't open %s\n", argv[0], argv[argc-1]);
  323.             exit(0);
  324.         }
  325.     } else {in = stdin;}
  326.  
  327.     /*
  328.      * Just copy to output until we see an eexec.
  329.      */
  330. COPYFILE:
  331.     while (1) {
  332.         if (fgets(in_buff, BUFSIZ, in) == NULL) goto fin;
  333.         if (strcmp(in_buff, "currentfile eexec\n") == 0)
  334.             break;
  335.         fprintf(stdout, "%s", in_buff);
  336.     }
  337.  
  338.     skip_salt = EEXEC_SKIP_BYTES + 1;
  339.     er = ER;
  340.     ec1 = EC1;
  341.     ec2 = EC2;
  342.  
  343.     for (in_ptr = 999, in_size = 0, o=0, obase=0;;) {
  344.         switch(state) {
  345.         case CINZ_STATE:
  346.         cr = CR;
  347.         cc1 = CC1;
  348.         cc2 = CC2;
  349.         csalt = lenIV + 1;
  350.         for (count_pos = &out_buff[o-5];
  351.             (count_pos >= out_buff) && (*count_pos != ' ');
  352.             count_pos--)
  353.                 ;
  354.  
  355.         /* This can be at the beginning of a line */
  356.         if (*count_pos == ' ')
  357.             count_pos++;
  358.  
  359.         count = atoi(count_pos);
  360.                 
  361.         /*
  362.          * Change "count RD" to "{"
  363.          */
  364.         o = count_pos - out_buff;
  365.         out_buff[o++] = '{';
  366.         out_buff[o] = '\0';
  367.  
  368.         state = CHAR_STATE;
  369.         
  370.         case CHAR_STATE:
  371.         for ( ; count > 0; i += 2) {
  372.             /*
  373.              * Translate the buffer.
  374.              */
  375.             byte = CDeCrypt();
  376.             if (byte == 11) {            /* return */
  377.                 o += sprintf(&out_buff[o], " %s",
  378.                     commands[byte].command);
  379.                 out_check();
  380.                 break;
  381.             } else if (byte == 12) {    /* escape */
  382.                 byte = CDeCrypt();
  383.                 if (byte > MAX_ESCAPE) {
  384.                     o += sprintf(&out_buff[o],
  385.                         " not_defined_e%d", byte);
  386.                     out_check();
  387.                 } else {
  388.                     o += sprintf(&out_buff[o], " %s",
  389.                         escapes[byte].command);
  390.                     out_check();
  391.                 }
  392.                 continue;
  393.             } else if (byte < 32) {
  394.                 o += sprintf(&out_buff[o], " %s",
  395.                     commands[byte].command);
  396.                 out_check();
  397.             }
  398.             if (byte >= 32) {
  399.                 if (byte <= 246) {
  400.                     o += sprintf(&out_buff[o], " %d",
  401.                         byte  - 139);
  402.                     out_check();
  403.                 } else if ((byte >= 247) && (byte <= 250)) {
  404.                     o += sprintf(&out_buff[o], " %d",
  405.                         (byte  - 247) * 256
  406.                         + CDeCrypt() + 108);
  407.                     out_check();
  408.                 }
  409.                 else if ((byte >= 251) && (byte <= 254)) {
  410.                     o += sprintf(&out_buff[o], " %d",
  411.                         -((int)byte  - 251) * 256
  412.                         - (int)CDeCrypt() - 108);
  413.                     out_check();
  414.                 }
  415.                 else if (byte == 255) {
  416.                     value = CDeCrypt();
  417.                     value <<= 8;
  418.                     value += CDeCrypt();
  419.                     value <<= 8;
  420.                     value += CDeCrypt();
  421.                     value <<= 8;
  422.                     value += CDeCrypt();
  423.                     o +=sprintf(&out_buff[o],
  424.     /* NOTE: long value */                    " %ld", value);
  425.                     out_check();
  426.                 }
  427.             }
  428.         }
  429.  
  430.         o += sprintf(&out_buff[o], " }");
  431.         out_check();
  432.         state = DATA_STATE;
  433.         
  434.     case DATA_STATE:
  435.         /*
  436.          * Decrypt a line of hex.
  437.          */
  438.             plainchar = EDeCrypt();
  439.  
  440.             out_buff[o++] = plainchar;
  441.             out_check();
  442.  
  443.             if ((o >=4) && !strncmp(" RD ", &out_buff[o-4], 4)) {
  444.             state = CINZ_STATE;
  445.             break;
  446.             }
  447.             if ((o >=4) && !strncmp(" -| ", &out_buff[o-4], 4)) {
  448.             state = CINZ_STATE;
  449.             break;
  450.             }
  451.             if (plainchar == '\n') {
  452.             if (argc==3 && strstr(out_buff,"definefont")) goto fin;
  453.             if (strncmp("/lenIV", out_buff, 6) == 0)
  454.                 lenIV = atoi(out_buff + 7);
  455.             if ((count_pos =
  456.                 strstr(out_buff,"currentfile closefile"))
  457.                 != NULL){
  458.                 strcpy(count_pos, "\n");
  459.                 fputs(out_buff, stdout);
  460.                 goto COPYFILE;
  461.             }
  462.             fputs(out_buff, stdout);
  463.             o = 0;
  464.             obase = 0;
  465.             }
  466.         } /* switch */
  467.     } /* for (reading file) */
  468.  
  469. fin:    fclose(in);
  470.  
  471.     exit(0);
  472. }
  473.  
  474. -- 
  475. Kevin O'Gorman ( kevin@kosman.UUCP, kevin%kosman.uucp@nrc.com )
  476. voice: 805-984-8042 Vital Computer Systems, 5115 Beachcomber, Oxnard, CA  93035
  477. Non-Disclaimer: my boss is me, and he stands behind everything I say.
  478.