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