home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / t / t1utils1.zip / T1BINARY.C < prev    next >
C/C++ Source or Header  |  1992-06-12  |  7KB  |  278 lines

  1. /* t1binary
  2.  *
  3.  * This program takes an Adobe Type-1 font program in ASCII (PFA) format and
  4.  * converts it to binary (PFB) format.
  5.  *
  6.  * Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.
  7.  *
  8.  * Permission is hereby granted to use, modify, and distribute this program
  9.  * for any purpose provided this copyright notice and the one below remain
  10.  * intact.
  11.  *
  12.  * I. Lee Hetherington (ilh@lcs.mit.edu)
  13.  *
  14.  * $Log:        t1binary.c,v $
  15.  * Revision 1.1  92/05/22  11:58:17  ilh
  16.  * initial version
  17.  *
  18.  * Ported to Microsoft C/C++ Compiler and MS-DOS operating system by
  19.  * Kai-Uwe Herbing (herbing@netmbx.netmbx.de) on June 12, 1992. Code
  20.  * specific to the MS-DOS version is encapsulated with #ifdef _MSDOS
  21.  * ... #endif, where _MSDOS is an identifier, which is automatically
  22.  * defined, if you compile with the Microsoft C/C++ Compiler.
  23.  *
  24.  */
  25.  
  26. #ifndef lint
  27. static char rcsid[] =
  28.   "@(#) $Id: t1binary.c,v 1.1 92/05/22 11:58:17 ilh Exp Locker: ilh $";
  29. static char copyright[] =
  30.   "@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.";
  31. #ifdef _MSDOS
  32. static char portnotice[] =
  33.   "@(#) Ported to MS-DOS by Kai-Uwe Herbing (herbing@netmbx.netmbx.de).";
  34. #endif
  35. #endif
  36.  
  37. /* Note: this is ANSI C. */
  38.  
  39. #ifdef _MSDOS
  40.   #include <fcntl.h>
  41.   #include <getopt.h>
  42.   #include <io.h>
  43. #endif
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include <ctype.h>
  48. #include <limits.h>
  49.  
  50. /* int32 must be at least 32-bit */
  51. #if INT_MAX >= 0x7FFFFFFFUL
  52. typedef int int32;
  53. #else
  54. typedef long int32;
  55. #endif
  56.  
  57. #define LINESIZE 256
  58.  
  59. #define MAXBLOCKLEN ((1L<<17)-6)
  60. #define MINBLOCKLEN ((1L<<8)-6)
  61.  
  62. #define MARKER   128
  63. #define ASCII    1
  64. #define BINARY   2
  65. #define DONE     3
  66.  
  67. typedef unsigned char byte;
  68.  
  69. static FILE *ifp = stdin;
  70. static FILE *ofp = stdout;
  71. static char line[LINESIZE];
  72.  
  73. /* for PFB block buffering */
  74. static byte blockbuf[MAXBLOCKLEN];
  75. static int32 blocklen = MAXBLOCKLEN;
  76. static int32 blockpos = -1;
  77. static int blocktyp = ASCII;
  78.  
  79. /* This function flushes a buffered PFB block. */
  80.  
  81. static void output_block()
  82. {
  83.   int32 i;
  84.  
  85.   /* output four-byte block length */
  86.   fputc((int) (blockpos & 0xff), ofp);
  87.   fputc((int) ((blockpos >> 8) & 0xff), ofp);
  88.   fputc((int) ((blockpos >> 16) & 0xff), ofp);
  89.   fputc((int) ((blockpos >> 24) & 0xff), ofp);
  90.  
  91.   /* output block data */
  92.   for (i = 0; i < blockpos; i++)
  93.     fputc(blockbuf[i], ofp);
  94.  
  95.   /* mark block buffer empty and uninitialized */
  96.   blockpos =  -1;
  97. }
  98.  
  99. /* This function outputs a single byte.  If output is in PFB format then output
  100.    is buffered through blockbuf[].  If output is in PFA format, then output
  101.    will be hexadecimal if in_eexec is set, ASCII otherwise. */
  102.  
  103. static void output_byte(byte b)
  104. {
  105.   if (blockpos < 0) {
  106.     fputc(MARKER, ofp);
  107.     fputc(blocktyp, ofp);
  108.     blockpos = 0;
  109.   }
  110.   blockbuf[blockpos++] = b;
  111.   if (blockpos == blocklen)
  112.     output_block();
  113. }
  114.  
  115. /* This function outputs a null-terminated string through the PFB buffering. */
  116.  
  117. static void output_string(char *string)
  118. {
  119.   while (*string)
  120.     output_byte((byte) *string++);
  121. }
  122.  
  123. /* This function returns the value (0-15) of a single hex digit.  It returns
  124.    0 for an invalid hex digit. */
  125.  
  126. static int hexval(char c)
  127. {
  128.   if (c >= 'A' && c <= 'F')
  129.     return c - 'A' + 10;
  130.   else if (c >= 'a' && c <= 'f')
  131.     return c - 'a' + 10;
  132.   else if (c >= '0' && c <= '9')
  133.     return c - '0';
  134.   else
  135.     return 0;
  136. }
  137.  
  138. /* This function outputs the binary data associated with a string of
  139.    hexadecimal digits.  There must be an even number of digits. */
  140.  
  141. static void output_hex_string(char *string)
  142. {
  143.   while (string[0] && string[0] != '\n') {
  144.     if (!string[1]) {
  145.       fprintf(stderr, "error: only one hex digit\n");
  146.       exit(1);
  147.     }
  148.     output_byte((byte)((hexval(string[0]) << 4) + hexval(string[1])));
  149.     string += 2;
  150.   }
  151. }
  152.  
  153. /* This function returns 1 if the string contains all '0's. */
  154.  
  155. static int all_zeroes(char *string)
  156. {
  157.   while (*string == '0')
  158.     string++;
  159.   return *string == '\0' || *string == '\n';
  160. }
  161.  
  162. static void usage()
  163. {
  164.   fprintf(stderr,
  165.           "usage: t1binary [-l block-length] [input [output]]\n");
  166.   fprintf(stderr,
  167.           "The block length applies to the length of blocks in the\n");
  168.   fprintf(stderr,
  169.           "PFB output file; the default is to use the largest possible.\n");
  170.   exit(1);
  171. }
  172.  
  173. static void print_banner()
  174. {
  175.   static char rcs_revision[] = "$Revision: 1.1 $";
  176.   static char revision[20];
  177.  
  178.   if (sscanf(rcs_revision, "$Revision: %19s", revision) != 1)
  179.     revision[0] = '\0';
  180.   fprintf(stderr, "This is t1binary %s.\n", revision);
  181. }
  182.  
  183. int main(int argc, char **argv)
  184. {
  185.   int c;
  186.  
  187.   extern char *optarg;
  188.   extern int optind;
  189.   extern int getopt(int argc, char **argv, char *optstring);
  190.  
  191.   print_banner();
  192.  
  193.   /* interpret command line arguments using getopt */
  194.   while ((c = getopt(argc, argv, "l:")) != -1)
  195.     switch (c) {
  196.     case 'l':
  197.       blocklen = atoi(optarg);
  198.       if (blocklen < MINBLOCKLEN) {
  199.         blocklen = MINBLOCKLEN;
  200.         fprintf(stderr,
  201.                 "warning: using minimum block length of %d\n",
  202.                 blocklen);
  203.       } else if (blocklen > MAXBLOCKLEN) {
  204.         blocklen = MAXBLOCKLEN;
  205.         fprintf(stderr,
  206.                 "warning: using maximum block length of %d\n",
  207.                 blocklen);
  208.       }
  209.       break;
  210.     default:
  211.       usage();
  212.       break;
  213.     }
  214.   if (argc - optind > 2)
  215.     usage();
  216.  
  217.   /* possibly open input & output files */
  218.   if (argc - optind >= 1) {
  219.     ifp = fopen(argv[optind], "r");
  220.     if (!ifp) {
  221.       fprintf(stderr, "error: cannot open %s for reading\n",
  222.               argv[optind]);
  223.       exit(1);
  224.     }
  225.   }
  226.   if (argc - optind >= 2) {
  227.     ofp = fopen(argv[optind + 1], "w");
  228.     if (!ofp) {
  229.       fprintf(stderr, "error: cannot open %s for writing\n",
  230.               argv[optind + 1]);
  231.       exit(1);
  232.     }
  233.   }
  234.  
  235.   #ifdef _MSDOS
  236.     /* As we are processing a PFB (binary) output */
  237.     /* file, we must set its file mode to binary. */
  238.     _setmode(_fileno(ofp), _O_BINARY);
  239.   #endif
  240.  
  241.   /* peek at first byte to see if it is the PFB marker 0x80 */
  242.   c = fgetc(ifp);
  243.   if (c == MARKER) {
  244.     fprintf(stderr,
  245.             "error: input may already be binary (starts with 0x80)\n");
  246.     exit(1);
  247.   }
  248.   ungetc(c, ifp);
  249.  
  250.   /* Finally, we loop until no more input.  We need to look for `currentfile
  251.      eexec' to start eexec section (hex to binary conversion) and line of all
  252.      zeros to switch back to ASCII. */
  253.  
  254.   while (fgets(line, LINESIZE, ifp), !feof(ifp) && !ferror(ifp)) {
  255.     if (blocktyp == ASCII && strcmp(line, "currentfile eexec\n") == 0) {
  256.       output_string(line);
  257.       output_block();
  258.       blocktyp = BINARY;
  259.     } else if (blocktyp == BINARY && all_zeroes(line)) {
  260.       output_block();
  261.       blocktyp = ASCII;
  262.       output_string(line);
  263.     } else if (blocktyp == ASCII) {
  264.       output_string(line);
  265.     } else {
  266.       output_hex_string(line);
  267.     }
  268.   }
  269.   output_block();
  270.   fputc(MARKER, ofp);
  271.   fputc(DONE, ofp);
  272.  
  273.   fclose(ifp);
  274.   fclose(ofp);
  275.  
  276.   return 0;
  277. }
  278.