home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 700-799 / ff732.lha / pstools / t1utils / t1sourcecode / t1binary.c < prev    next >
C/C++ Source or Header  |  1992-09-26  |  6KB  |  250 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.  */
  19.  
  20. #ifndef lint
  21. static char rcsid[] =
  22.   "@(#) $Id: t1binary.c,v 1.1 92/05/22 11:58:17 ilh Exp $";
  23. static char copyright[] =
  24.   "@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.";
  25. #endif
  26.  
  27. /* Note: this is ANSI C. */
  28.  
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <ctype.h>
  33.  
  34. #define BANNER   "This is t1binary 1.1.\n"
  35. #define LINESIZE 256
  36.  
  37. #define MAXBLOCKLEN ((1<<17)-6)
  38. #define MINBLOCKLEN ((1<<8)-6)
  39.  
  40. #define MARKER   128
  41. #define ASCII    1
  42. #define BINARY   2
  43. #define DONE     3
  44.  
  45. typedef unsigned char byte;
  46.  
  47. static FILE *ifp = stdin;
  48. static FILE *ofp = stdout;
  49. static char line[LINESIZE];
  50.  
  51. /* for PFB block buffering */
  52. static byte blockbuf[MAXBLOCKLEN];
  53. static int blocklen = MAXBLOCKLEN;
  54. static int blockpos = -1;
  55. static int blocktyp = ASCII;
  56.  
  57. /* This function flushes a buffered PFB block. */
  58.  
  59. static void output_block()
  60. {
  61.   int i;
  62.  
  63.   /* output four-byte block length */
  64.   fputc(blockpos & 0xff, ofp);
  65.   fputc((blockpos >> 8) & 0xff, ofp);
  66.   fputc((blockpos >> 16) & 0xff, ofp);
  67.   fputc((blockpos >> 24) & 0xff, ofp);
  68.  
  69.   /* output block data */
  70.   for (i = 0; i < blockpos; i++)
  71.     fputc(blockbuf[i], ofp);
  72.  
  73.   /* mark block buffer empty and uninitialized */
  74.   blockpos =  -1;
  75. }
  76.  
  77. /* This function outputs a single byte.  If output is in PFB format then output
  78.    is buffered through blockbuf[].  If output is in PFA format, then output
  79.    will be hexadecimal if in_eexec is set, ASCII otherwise. */
  80.  
  81. static void output_byte(byte b)
  82. {
  83.   if (blockpos < 0) {
  84.     fputc(MARKER, ofp);
  85.     fputc(blocktyp, ofp);
  86.     blockpos = 0;
  87.   }
  88.   blockbuf[blockpos++] = b;
  89.   if (blockpos == blocklen)
  90.     output_block();
  91. }
  92.  
  93. /* This function outputs a null-terminated string through the PFB buffering. */
  94.  
  95. static void output_string(char *string)
  96. {
  97.   while (*string)
  98.     output_byte((byte) *string++);
  99. }
  100.  
  101. /* This function returns the value (0-15) of a single hex digit.  It returns
  102.    0 for an invalid hex digit. */
  103.  
  104. static int hexval(char c)
  105. {
  106.   if (c >= 'A' && c <= 'F')
  107.     return c - 'A' + 10;
  108.   else if (c >= 'a' && c <= 'f')
  109.     return c - 'a' + 10;
  110.   else if (c >= '0' && c <= '9')
  111.     return c - '0';
  112.   else
  113.     return 0;
  114. }
  115.  
  116. /* This function outputs the binary data associated with a string of
  117.    hexadecimal digits.  There must be an even number of digits. */
  118.  
  119. static void output_hex_string(char *string)
  120. {
  121.   while (string[0] && string[0] != '\n') {
  122.     if (!string[1]) {
  123.       fprintf(stderr, "error: only one hex digit\n");
  124.       exit(1);
  125.     }
  126.     output_byte((byte)((hexval(string[0]) << 4) + hexval(string[1])));
  127.     string += 2;
  128.   }
  129. }
  130.  
  131. /* This function returns 1 if the string contains all '0's. */
  132.  
  133. static int all_zeroes(char *string)
  134. {
  135.   while (*string == '0')
  136.     string++;
  137.   return *string == '\0' || *string == '\n';
  138. }
  139.  
  140. static void usage()
  141. {
  142.   fprintf(stderr,
  143.       "usage: t1binary [-l block-length] [input [output]]\n");
  144.   fprintf(stderr,
  145.       "The block length applies to the length of blocks in the\n");
  146.   fprintf(stderr,
  147.       "PFB output file; the default is to use the largest possible.\n");
  148.   exit(1);
  149. }
  150.  
  151. static void print_banner()
  152. {
  153.   static char rcs_revision[] = "$Revision: 1.1 $";
  154.   static char revision[20];
  155.  
  156.   if (sscanf(rcs_revision, "$Revision: %19s", revision) != 1)
  157.     revision[0] = '\0';
  158.   fprintf(stderr, "This is t1binary %s.\n", revision);
  159. }
  160.  
  161. int main(int argc, char **argv)
  162. {
  163.   int c;
  164.  
  165.   extern char *optarg;
  166.   extern int optind;
  167.   extern int getopt(int argc, char **argv, char *optstring);
  168.  
  169.   print_banner();
  170.  
  171.   /* interpret command line arguments using getopt */
  172.   while ((c = getopt(argc, argv, "l:")) != -1)
  173.     switch (c) {
  174.     case 'l':
  175.       blocklen = atoi(optarg);
  176.       if (blocklen < MINBLOCKLEN) {
  177.     blocklen = MINBLOCKLEN;
  178.     fprintf(stderr,
  179.         "warning: using minimum block length of %d\n",
  180.         blocklen);
  181.       } else if (blocklen > MAXBLOCKLEN) {
  182.     blocklen = MAXBLOCKLEN;
  183.     fprintf(stderr,
  184.         "warning: using maximum block length of %d\n",
  185.         blocklen);
  186.       }
  187.       break;
  188.     default:
  189.       usage();
  190.       break;
  191.     }
  192.   if (argc - optind > 2)
  193.     usage();
  194.  
  195.   /* possibly open input & output files */
  196.   if (argc - optind >= 1) {
  197.     ifp = fopen(argv[optind], "r");
  198.     if (!ifp) {
  199.       fprintf(stderr, "error: cannot open %s for reading\n",
  200.           argv[optind]);
  201.       exit(1);
  202.     }
  203.   }
  204.   if (argc - optind >= 2) {
  205.     ofp = fopen(argv[optind + 1], "w");
  206.     if (!ofp) {
  207.       fprintf(stderr, "error: cannot open %s for writing\n",
  208.           argv[optind + 1]);
  209.       exit(1);
  210.     }
  211.   }
  212.  
  213.   /* peek at first byte to see if it is the PFB marker 0x80 */
  214.   c = fgetc(ifp);
  215.   if (c == MARKER) {
  216.     fprintf(stderr,
  217.         "error: input may already be binary (starts with 0x80)\n");
  218.     exit(1);
  219.   }
  220.   ungetc(c, ifp);
  221.  
  222.   /* Finally, we loop until no more input.  We need to look for `currentfile
  223.      eexec' to start eexec section (hex to binary conversion) and line of all
  224.      zeros to switch back to ASCII. */
  225.  
  226.   while (fgets(line, LINESIZE, ifp), !feof(ifp) && !ferror(ifp)) {
  227.     if (blocktyp == ASCII && strcmp(line, "currentfile eexec\n") == 0) {
  228.       output_string(line);
  229.       output_block();
  230.       blocktyp = BINARY;
  231.     } else if (blocktyp == BINARY && all_zeroes(line)) {
  232.       output_block();
  233.       blocktyp = ASCII;
  234.       output_string(line);
  235.     } else if (blocktyp == ASCII) {
  236.       output_string(line);
  237.     } else {
  238.       output_hex_string(line);
  239.     }
  240.   }
  241.   output_block();
  242.   fputc(MARKER, ofp);
  243.   fputc(DONE, ofp);
  244.  
  245.   fclose(ifp);
  246.   fclose(ofp);
  247.  
  248.   return 0;
  249. }
  250.