home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 12 Font / 12-Font.zip / FONTUTIL.ZIP / unpost.c < prev    next >
Text File  |  1992-07-06  |  9KB  |  347 lines

  1. /* unpost
  2.  *
  3.  * This program converts Macintosh type-1 fonts stored in MacBinary (I or II)
  4.  * format or raw resource fork to PFA and PFB formats.
  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:        unpost.c,v $
  15.  * Revision 1.1  92/05/22  12:07:49  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. /* Note: this is ANSI C. */
  27.  
  28. #ifndef lint
  29. static char rcsid[] =
  30.   "@(#) $Id: unpost.c,v 1.1 92/05/22 12:07:49 ilh Exp Locker: ilh $";
  31. static char copyright[] =
  32.   "@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.";
  33. #ifdef _MSDOS
  34. static char portnotice[] =
  35.   "@(#) Ported to MS-DOS by Kai-Uwe Herbing (herbing@netmbx.netmbx.de).";
  36. #endif
  37. #endif
  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 <limits.h>
  47.  
  48. /* int32 must be at least 32-bit */
  49. #if INT_MAX >= 0x7FFFFFFFUL
  50. typedef int int32;
  51. #else
  52. typedef long int32;
  53. #endif
  54.  
  55. /* Some functions to read one, two, three, and four byte integers in 68000
  56.    byte order (most significant byte first). */
  57.  
  58. static int read_one(FILE *fi)
  59. {
  60.   return fgetc(fi);
  61. }
  62.  
  63. static int read_two(FILE *fi)
  64. {
  65.   int val;
  66.  
  67.   val = read_one(fi);
  68.   val = (val << 8) + read_one(fi);
  69.  
  70.   return val;
  71. }
  72.  
  73. static int32 read_three(FILE *fi)
  74. {
  75.   int32 val;
  76.  
  77.   val = read_one(fi);
  78.   val = (val << 8) + read_one(fi);
  79.   val = (val << 8) + read_one(fi);
  80.  
  81.   return val;
  82. }
  83.  
  84. static int32 read_four(FILE *fi)
  85. {
  86.   int32 val;
  87.  
  88.   val = read_one(fi);
  89.   val = (val << 8) + read_one(fi);
  90.   val = (val << 8) + read_one(fi);
  91.   val = (val << 8) + read_one(fi);
  92.  
  93.   return val;
  94. }
  95.  
  96. /* Function to write four byte length to PFB file: least significant byte
  97.    first. */
  98.  
  99. static void write_pfb_length(FILE *fo, int32 len)
  100. {
  101.   fputc((int) (len & 0xff), fo);
  102.   len >>= 8;
  103.   fputc((int) (len & 0xff), fo);
  104.   len >>= 8;
  105.   fputc((int) (len & 0xff), fo);
  106.   len >>= 8;
  107.   fputc((int) (len & 0xff), fo);
  108. }
  109.  
  110. static void reposition(FILE *fi, int32 absolute)
  111. {
  112.   if (fseek(fi, absolute, 0) == -1) {
  113.     fprintf(stderr, "error: fseek failed to position %d.\n", absolute);
  114.     fprintf(stderr, "       Is this file seekable?\n");
  115.     exit(1);
  116.   }
  117. }
  118.  
  119. static int hex_column = 0;                        /* current column of hex */
  120.                                                   /* ASCII output */
  121.  
  122. static void output_hex_byte(FILE *fo, int b)
  123. {
  124.   static char *hex = "0123456789ABCDEF";
  125.  
  126.   if (hex_column > 62) {                          /* 64 column output */
  127.     fputc('\n', fo);
  128.     hex_column = 0;
  129.   }
  130.   fputc(hex[b >> 4], fo);
  131.   fputc(hex[b & 0xf], fo);
  132.   hex_column += 2;
  133. }
  134.  
  135. /* Function to extract a particular POST resource.  Offset points to the four
  136.    byte length which is followed by the data.  The first byte of the POST data
  137.    specifies resource type: 1 for ASCII, 2 for binary, and 5 for end.  The
  138.    second byte is always zero. */
  139.  
  140. static void extract_data(FILE *fi, FILE *fo, int32 offset, int binary)
  141. {
  142.   enum PS_type { PS_ascii = 1, PS_binary = 2, PS_end = 5 };
  143.   static enum PS_type last_type = PS_ascii;
  144.   int32 len, save_offset = ftell(fi);
  145.   int c;
  146.  
  147.   reposition(fi, offset);
  148.   len = read_four(fi) - 2;                        /* subtract type field */
  149.   switch ((enum PS_type)read_one(fi)) {
  150.   case PS_ascii:
  151.     (void) read_one(fi);
  152.     if (binary) {
  153.       fputc(128, fo);
  154.       fputc(1, fo);
  155.       write_pfb_length(fo, len);
  156.       while (len--) {
  157.         if ((c = read_one(fi)) == '\r')           /* change \r to \n */
  158.           c = '\n';
  159.         fputc(c, fo);
  160.       }
  161.     } else {
  162.       if (last_type == PS_binary)
  163.         fputc('\n', fo);
  164.       while (len--) {
  165.         if ((c = read_one(fi)) == '\r')           /* change \r to \n */
  166.           c = '\n';
  167.         fputc(c, fo);
  168.       }
  169.     }
  170.     last_type = 1;
  171.     break;
  172.   case PS_binary:
  173.     (void) read_one(fi);
  174.     if (binary) {
  175.       fputc(128, fo);
  176.       fputc(2, fo);
  177.       write_pfb_length(fo, len);
  178.       while (len--)
  179.         fputc(read_one(fi), fo);
  180.     } else {
  181.       if (last_type != 2)
  182.         hex_column = 0;
  183.       while (len--)
  184.         output_hex_byte(fo, read_one(fi));
  185.       last_type = 2;
  186.     }
  187.     break;
  188.   case PS_end:
  189.     (void) read_one(fi);
  190.     if (binary) {
  191.       fputc(128, fo);
  192.       fputc(3, fo);
  193.     }
  194.     break;
  195.   }
  196.   reposition(fi, save_offset);
  197. }
  198.  
  199. static void usage(void)
  200. {
  201.   fprintf(stderr, "usage: unpost [-b] [-r] in-file [out-file]\n");
  202.   exit(1);
  203. }
  204.  
  205. static void print_banner()
  206. {
  207.   static char rcs_revision[] = "$Revision: 1.1 $";
  208.   static char revision[20];
  209.  
  210.   if (sscanf(rcs_revision, "$Revision: %19s", revision) != 1)
  211.     revision[0] = '\0';
  212.   fprintf(stderr, "This is unpost %s.\n", revision);
  213. }
  214.  
  215. int main(int argc, char **argv)
  216. {
  217.   FILE *fi;
  218.   FILE *fo = stdout;
  219.   int32 data_fork_size;
  220.   int32 res_offset, res_data_offset, res_map_offset, type_list_offset;
  221.   int32 post_type;
  222.   int num_types, num_of_type, num_extracted = 0, binary = 0, raw = 0;
  223.   int c;
  224.   extern int optind;
  225.   extern int getopt(int, char **, char*);
  226.  
  227.   print_banner();
  228.  
  229.   /* parse command line */
  230.   while ((c = getopt(argc, argv, "br?")) != -1)
  231.     switch(c) {
  232.     case 'b':
  233.       ++binary;
  234.       break;
  235.     case 'r':
  236.       ++raw;
  237.       break;
  238.     default:
  239.       usage();
  240.     }
  241.   if (argc - optind < 1 || argc - optind > 2)
  242.     usage();
  243.  
  244.   /* open input file */
  245.   #ifdef _MSDOS
  246.     /* As we are processing an input file in Macintosh */
  247.     /* format, we should avoid any kind of translation */
  248.     /* and consequently open it in binary file mode.   */
  249.     fi = fopen(argv[optind], "rb");
  250.   #else
  251.     fi = fopen(argv[optind], "rb");
  252.   #endif
  253.   if (!fi) {
  254.     fprintf(stderr, "error: cannot open %s for reading\n", argv[1]);
  255.     exit(1);
  256.   }
  257.   /* possibly open output file */
  258.   if (argc - optind == 2) {
  259.     fo = fopen(argv[optind + 1], "wb");
  260.     if (!fo) {
  261.       fprintf(stderr, "error: cannot open %s for writing\n", argv[2]);
  262.       exit(1);
  263.     }
  264.   }
  265.  
  266.   #ifdef _MSDOS
  267.     /* If we are processing a PFB (binary) output */
  268.     /* file, we must set its file mode to binary. */
  269.     if (binary)
  270.       _setmode(_fileno(fo), _O_BINARY);
  271.   #endif
  272.  
  273.   if (raw) {
  274.  
  275.     /* raw resource file */
  276.  
  277.     res_offset = 0;
  278.  
  279.   } else {
  280.  
  281.     /* MacBinary (I or II) file */
  282.  
  283.     /* SHOULD CHECK INTEGRITY OF MACBINARY HEADER HERE TO VERIFY THAT WE
  284.        REALLY HAVE A MACBINARY FILE.  MACBINARY-II-STANDARD.TXT DESCRIBES
  285.        AN APPROPRIATE VERIFICATION PROCEDURE. */
  286.  
  287.     /* read data and resource fork sizes in MacBinary header */
  288.     reposition(fi, 83);
  289.     data_fork_size = read_four(fi);
  290.     (void) read_four(fi);
  291.  
  292.     /* round data_fork_size up to multiple of 128 */
  293.     if (data_fork_size % 128)
  294.       data_fork_size += 128 - data_fork_size % 128;
  295.  
  296.     res_offset = 128 + data_fork_size;
  297.  
  298.   }
  299.  
  300.   /* read offsets from resource fork header */
  301.   reposition(fi, res_offset);
  302.   res_data_offset = res_offset + read_four(fi);
  303.   res_map_offset = res_offset + read_four(fi);
  304.  
  305.   /* read type list offset from resource map header */
  306.   reposition(fi, res_map_offset + 24);
  307.   type_list_offset = res_map_offset + read_two(fi);
  308.  
  309.   /* read type list */
  310.   reposition(fi, type_list_offset);
  311.   num_types = read_two(fi) + 1;
  312.  
  313.   /* find POST type */
  314.   post_type =  (int32) ('P' & 0xff) << 24;
  315.   post_type |= (int32) ('O' & 0xff) << 16;
  316.   post_type |= (int32) ('S' & 0xff) << 8;
  317.   post_type |= (int32) ('T' & 0xff);
  318.  
  319.   while (num_types--) {
  320.     if (read_four(fi) == post_type) {
  321.       num_of_type = 1 + read_two(fi);
  322.       reposition(fi, type_list_offset + read_two(fi));
  323.       while (num_of_type--) {
  324.         (void) read_two(fi);                      /* ID */
  325.         (void) read_two(fi);
  326.         (void) read_one(fi);
  327.         extract_data(fi, fo, res_data_offset + read_three(fi), binary);
  328.         ++num_extracted;
  329.         (void) read_four(fi);
  330.       }
  331.       break;
  332.     } else {
  333.       (void) read_two(fi);
  334.       (void) read_two(fi);
  335.     }
  336.   }
  337.  
  338.   fclose(fi);
  339.   if (fo != stdout) {
  340.     fclose(fo);
  341.     fprintf(stderr, "Extracted %d POST resource%s.\n", num_extracted,
  342.             (num_extracted == 1) ? "" : "s");
  343.   }
  344.  
  345.   return 0;
  346. }
  347.