Main Page   Modules   Alphabetical List   Compound List   File List   Compound Members   File Members  

t1unmac.c

00001 /*  $Id: t1unmac.c,v 1.3 2000/11/30 02:25:10 dbryson Exp $ */
00002 
00003 /*
00004 **  Description:
00005 **  
00006 **    This file is part of libps
00007 **
00008 **
00009 **  Contact:
00010 **
00011 **      Mail:
00012 **
00013 **        Technology Associates, Inc.
00014 **        LIBPS Project
00015 **        1455 Deming Way #11
00016 **        Sparks, NV  89431
00017 **        USA
00018 **
00019 **      Email:
00020 **
00021 **        libps@techass.com
00022 **
00023 **      See our website at:
00024 **
00025 **        libps.sourceforge.net
00026 **
00027 */
00028 
00029 /* t1unmac/unpost
00030  *
00031  * This program converts Macintosh Type 1 fonts stored in MacBinary (I or II),
00032  * AppleSingle, AppleDouble, BinHex, or raw resource fork format to PFA and
00033  * PFB formats.
00034  *
00035  * Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.
00036  *
00037  * Permission is hereby granted to use, modify, and distribute this program
00038  * for any purpose provided this copyright notice and the one below remain
00039  * intact.
00040  *
00041  * I. Lee Hetherington (ilh@lcs.mit.edu)
00042  *
00043  * 1.5 and later versions contain changes by, and are maintained by,
00044  * Eddie Kohler <eddietwo@lcs.mit.edu>.
00045  *
00046  * New change log in `NEWS'. Old change log:
00047  *
00048  * Revision 1.2  92/06/23  10:57:33  ilh
00049  * MSDOS porting by Kai-Uwe Herbing (herbing@netmbx.netmbx.de)
00050  * incoporated.
00051  * 
00052  * Revision 1.1  92/05/22  12:07:49  ilh
00053  * initial version
00054  *
00055  * Ported to Microsoft C/C++ Compiler and MS-DOS operating system by
00056  * Kai-Uwe Herbing (herbing@netmbx.netmbx.de) on June 12, 1992. Code
00057  * specific to the MS-DOS version is encapsulated with #ifdef _MSDOS
00058  * ... #endif, where _MSDOS is an identifier, which is automatically
00059  * defined, if you compile with the Microsoft C/C++ Compiler.
00060  * */
00061 
00062 /* Note: this is ANSI C. */
00063 
00064 #ifdef HAVE_CONFIG_H
00065 # include <config.h>
00066 #endif
00067 #if defined(_MSDOS) || defined(_WIN32)
00068 # include <fcntl.h>
00069 # include <getopt.h>
00070 # include <io.h>
00071 #endif
00072 #include <stdio.h>
00073 #include <stdlib.h>
00074 #include <limits.h>
00075 #include <stdarg.h>
00076 #include <string.h>
00077 #include <errno.h>
00078 #include <ctype.h>
00079 #include "clp.h"
00080 #include "t1lib.h"
00081 
00082 /* int32 must be at least 32-bit */
00083 #if INT_MAX >= 0x7FFFFFFFUL
00084 typedef int int32;
00085 typedef unsigned int uint32;
00086 #else
00087 typedef long int32;
00088 typedef unsigned long uint32;
00089 #endif
00090 
00091 /* for PFB block buffering */
00092 void fatal_error(const char *message, ...);
00093 void error(const char *message, ...);
00094 
00095 
00096 /* Some functions to read one, two, three, and four byte integers in 68000
00097    byte order (most significant byte first). */
00098 
00099 static int
00100 read_one(FILE *fi)
00101 {
00102   return getc(fi);
00103 }
00104 
00105 static int
00106 read_two(FILE *fi)
00107 {
00108   int val;
00109 
00110   val = getc(fi);
00111   val = (val << 8) | getc(fi);
00112 
00113   return val;
00114 }
00115 
00116 static int32
00117 read_three(FILE *fi)
00118 {
00119   int32 val;
00120 
00121   val = getc(fi);
00122   val = (val << 8) | getc(fi);
00123   val = (val << 8) | getc(fi);
00124 
00125   return val;
00126 }
00127 
00128 static int32
00129 read_four(FILE *fi)
00130 {
00131   int32 val;
00132 
00133   val = getc(fi);
00134   val = (val << 8) | getc(fi);
00135   val = (val << 8) | getc(fi);
00136   val = (val << 8) | getc(fi);
00137 
00138   return val;
00139 }
00140 
00141 /* reposition a file with error messages */
00142 
00143 static void
00144 reposition(FILE *fi, int32 absolute)
00145 {
00146   if (fseek(fi, absolute, 0) == -1)
00147     fatal_error("can't seek to position %d\n\
00148    (The Mac file may be corrupted, or you may need the `-r' option.)",
00149                 absolute);
00150 }
00151 
00152 static int blocklen = -1;
00153 
00154 static int hex_column = 0;      /* current column of hex ASCII output */
00155 
00156 static void
00157 output_hex_byte(FILE *fo, int b)
00158 {
00159   static char *hex = "0123456789abcdef";
00160   
00161   if (hex_column >= blocklen) {
00162     putc('\n', fo);
00163     hex_column = 0;
00164   }
00165   putc(hex[b >> 4], fo);
00166   putc(hex[b & 0xf], fo);
00167   hex_column += 2;
00168 }
00169 
00170 /* Function to extract a particular POST resource.  Offset points to the four
00171    byte length which is followed by the data.  The first byte of the POST data
00172    specifies resource type: 1 for ASCII, 2 for binary, and 5 for end.  The
00173    second byte is always zero. */
00174 
00175 
00176 /* Function to write four byte length to PFB file: least significant byte
00177    first. */
00178 
00179 static int
00180 extract_data(FILE *fi, FILE *fo, struct pfb_writer *w, int32 offset, int pfb)
00181 {
00182   enum PS_type { PS_ascii = 1, PS_binary = 2, PS_end = 5 };
00183   static enum PS_type last_type = -1;
00184   static int skip_newline = 0;
00185   int32 len;
00186   int more = 1;
00187   int i, c;
00188 
00189   reposition(fi, offset);
00190   len = read_four(fi) - 2;      /* subtract type field */
00191 
00192   switch ((enum PS_type)read_one(fi)) {
00193     
00194    case PS_ascii: {
00195      (void) read_one(fi);
00196      if (last_type != PFB_ASCII && pfb) {
00197        pfb_writer_output_block(w);
00198        w->blocktyp = PFB_ASCII;
00199      }
00200      for (i = 0; i < len; i++) {
00201        c = read_one(fi);
00202        if (c == '\n' && skip_newline) {
00203          skip_newline = 0;
00204          continue;
00205        }
00206        if (c == '\r') {
00207          c = '\n';
00208          skip_newline = 1;
00209        } else
00210          skip_newline = 0;
00211        if (pfb)
00212          PFB_OUTPUT_BYTE(w, c);
00213        else
00214          putc(c, fo);
00215      }
00216      last_type = PFB_ASCII;
00217      break;
00218    }
00219    
00220    case PS_binary: {
00221      (void) read_one(fi);
00222      if (last_type != PFB_BINARY && pfb) {
00223        pfb_writer_output_block(w);
00224        w->blocktyp = PFB_BINARY;
00225      } else if (last_type != PFB_BINARY)
00226        hex_column = 0;
00227      if (pfb) {
00228        while (len--)
00229          PFB_OUTPUT_BYTE(w, read_one(fi));
00230      } else {
00231        while (len--)
00232          output_hex_byte(fo, read_one(fi));
00233      }
00234      last_type = PFB_BINARY;
00235      break;
00236    }
00237 
00238    case PS_end:
00239     more = 0;
00240     break;
00241     
00242   }
00243   
00244   return more;
00245 }
00246 
00247 
00248 /*****
00249  * Command line
00250  **/
00251 
00252 #define OUTPUT_OPT      301
00253 #define VERSION_OPT     302
00254 #define HELP_OPT        303
00255 #define PFB_OPT         304
00256 #define PFA_OPT         305
00257 #define MACBINARY_OPT   306
00258 #define RAW_OPT         307
00259 #define LINE_LEN_OPT    308
00260 #define APPLEDOUBLE_OPT 309
00261 #define BINHEX_OPT      310
00262 
00263 static Clp_Option options[] = {
00264   { "applesingle", 0, APPLEDOUBLE_OPT, 0, 0 },
00265   { "appledouble", 0, APPLEDOUBLE_OPT, 0, 0 },
00266   { "binhex", 0, BINHEX_OPT, 0, 0 },
00267   { "block-length", 0, LINE_LEN_OPT, Clp_ArgUnsigned, 0 },
00268   { "help", 0, HELP_OPT, 0, 0 },
00269   { "line-length", 'l', LINE_LEN_OPT, Clp_ArgUnsigned, 0 },
00270   { "macbinary", 0, MACBINARY_OPT, 0, 0 },
00271   { "output", 'o', OUTPUT_OPT, Clp_ArgString, 0 },
00272   { "pfa", 'a', PFA_OPT, 0, 0 },
00273   { "pfb", 'b', PFB_OPT, 0, 0 },
00274   { "raw", 'r', RAW_OPT, 0, 0 },
00275   { "version", 0, VERSION_OPT, 0, 0 },
00276 };
00277 static char *program_name;
00278 
00279 void
00280 fatal_error(const char *message, ...)
00281 {
00282   va_list val;
00283   va_start(val, message);
00284   fprintf(stderr, "%s: ", program_name);
00285   vfprintf(stderr, message, val);
00286   putc('\n', stderr);
00287   exit(1);
00288 }
00289 
00290 void
00291 error(const char *message, ...)
00292 {
00293   va_list val;
00294   va_start(val, message);
00295   fprintf(stderr, "%s: ", program_name);
00296   vfprintf(stderr, message, val);
00297   putc('\n', stderr);
00298 }
00299 
00300 void
00301 short_usage(void)
00302 {
00303   fprintf(stderr, "Usage: %s [OPTION]... INPUT [OUTPUT]\n\
00304 Try `%s --help' for more information.\n",
00305           program_name, program_name);
00306 }
00307 
00308 void
00309 usage(void)
00310 {
00311   printf("\
00312 `T1unmac' extracts a PostScript Type 1 font from a Macintosh font file. It can\n\
00313 read MacBinary, AppleSingle, AppleDouble, or BinHex files, or raw Macintosh\n\
00314 resource forks. The result is written to the standard output unless an OUTPUT\n\
00315 file is given.\n\
00316 \n\
00317 Usage: %s [OPTION]... INPUT [OUTPUT]\n\
00318 \n\
00319 Options:\n\
00320   -r, --raw                   Input is a raw Macintosh resource fork.\n\
00321       --macbinary             Input is in MacBinary format.\n\
00322       --applesingle           Input is in AppleSingle format.\n\
00323       --appledouble           Input is in AppleDouble format.\n\
00324       --binhex                Input is in BinHex format.\n\
00325   -a, --pfa                   Output font in ASCII (PFA) format.\n\
00326   -b, --pfb                   Output font in binary (PFB) format. This is\n\
00327                               the default.\n\
00328   -l, --block-length NUM      Set max block length for PFB output.\n\
00329   -l, --line-length NUM       Set max encrypted line length for PFA output.\n\
00330   -o, --output FILE           Write output to FILE.\n\
00331   -h, --help                  Print this message and exit.\n\
00332       --version               Print version number and warranty and exit.\n\
00333 \n\
00334 Report bugs to <eddietwo@lcs.mit.edu>.\n", program_name);
00335 }
00336 
00337 
00338 static const char *
00339 check_macbinary(FILE *ifp)
00340 {
00341   int i, j;
00342   char buf[124];
00343 
00344   /* check "version" bytes at offsets 0 and 74 */
00345   reposition(ifp, 0);
00346   if (read_one(ifp) != 0)
00347     return "bad version byte";
00348   reposition(ifp, 74);
00349   if (read_one(ifp) != 0)
00350     return "bad version byte";
00351   
00352 #if 0
00353   /* write out bullshit */
00354   {int t;
00355     reposition(ifp, 65);
00356     t = read_four(ifp);
00357     fprintf(stderr, "Type %c%c%c%c\n", (t>>24)&255, (t>>16)&255, (t>>8)&255, t&255);
00358     t = read_four(ifp);
00359     fprintf(stderr, "Creator %c%c%c%c\n", (t>>24)&255, (t>>16)&255, (t>>8)&255, t&255);
00360     t = read_one(ifp);
00361     fprintf(stderr, "Finder flags 1 %02x\n", t);
00362     read_one(ifp);
00363     t = read_two(ifp);
00364     fprintf(stderr, "horizpos %04x\n", t);
00365     t = read_two(ifp);
00366     fprintf(stderr, "vertpos %04x\n", t);
00367     t = read_two(ifp);
00368     fprintf(stderr, "folder id %d\n", t);
00369     t = read_one(ifp);
00370     fprintf(stderr, "protected? %x\n", t);
00371     t = read_one(ifp);
00372     t = read_four(ifp);
00373     fprintf(stderr, "data len %d\n", t);
00374     t = read_four(ifp);
00375     fprintf(stderr, "rsrc len %d\n", t);
00376     t = read_four(ifp);
00377     {
00378       struct tm *crap; 
00379       fprintf(stderr, "creation date %x\n", t);
00380       t -= 2082844800;
00381       fprintf(stderr, "   %s\n", ctime(&t));
00382       t = read_four(ifp);
00383       fprintf(stderr, "modification date %x\n", t);
00384       t -= 2082844800;
00385       fprintf(stderr, "   %s\n", ctime(&t));
00386       t = read_two(ifp);
00387     }
00388     fprintf(stderr, "getinfo len %d\n", t);
00389     t = read_one(ifp);
00390     fprintf(stderr, "finderflags 2 %02x\n", t);
00391     reposition(ifp, 116);
00392     t = read_four(ifp);
00393     fprintf(stderr, "total len %d\n", t);
00394     t = read_two(ifp);
00395     fprintf(stderr, "secondary header len %d\n", t);
00396     t = read_one(ifp);
00397     fprintf(stderr, "version %d\n", t);
00398     t = read_one(ifp);
00399     fprintf(stderr, "version %d\n", t);
00400   }
00401 #endif
00402 
00403   /* check file length */
00404   reposition(ifp, 1);
00405   i = read_one(ifp);
00406   if (i > 63)
00407     return "bad length";
00408   reposition(ifp, 83);
00409   i = read_four(ifp);
00410   j = read_four(ifp);
00411   if (i < 0 || j < 0 || i >= 0x800000 || j >= 0x800000)
00412     return "bad length";
00413 
00414   /* check CRC */
00415   reposition(ifp, 0);
00416   fread(buf, 1, 124, ifp);
00417   if (crcbuf(0, 124, buf) != read_two(ifp)) {
00418     reposition(ifp, 82);
00419     if (read_one(ifp) != 0)
00420       return "bad checksum";
00421   }
00422 
00423   return 0;
00424 }
00425 
00426 #define APPLESINGLE_MAGIC 0x00051600
00427 #define APPLEDOUBLE_MAGIC 0x00051607
00428 
00429 const char *
00430 check_appledouble(FILE *ifp)
00431 {
00432   int i;
00433   reposition(ifp, 0);
00434   i = read_four(ifp);
00435   if (i != APPLEDOUBLE_MAGIC && i != APPLESINGLE_MAGIC)
00436     return "bad magic number";
00437 
00438   return 0;
00439 }
00440 
00441 const char *
00442 translate_binhex(FILE *f, FILE *tmpf)
00443 {
00444   int i, c = 0, last_char, after_x90, bits, bitpos;
00445   unsigned char value_table[256];
00446 
00447   /* prepare value table */
00448   {
00449     const char *table = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
00450     for (i = 0; i < 256; i++)
00451       value_table[i] = 255;
00452     for (i = 0; *table; i++, table++)
00453       value_table[(unsigned char)*table] = i;
00454   }
00455   
00456   /* skip to comment */
00457   {
00458     const char *comment = "(This file must be converted with BinHex";
00459     while (!feof(f)) {
00460       const char *s;
00461       for (s = comment; *s; s++) {
00462         c = getc(f);
00463         if (c != *s)
00464           break;
00465       }
00466       /* skip to end of line */
00467       while (c >= 0 && c != '\n' && c != '\r')
00468         c = getc(f);
00469       /* stop if read comment */
00470       if (!*s)
00471         goto found_comment;
00472     }
00473     /* failed */
00474     return "no comment";
00475   }
00476 
00477  found_comment:
00478   /* skip spaces, look for ':' */
00479   for (c = ' '; isspace(c); c = getc(f)) ;
00480   if (c != ':')
00481     return "no file-start character";
00482 
00483   /* found ':', process until you find another ':' */
00484   last_char = -1;
00485   after_x90 = bits = 0;
00486   bitpos = 10;
00487   for (c = getc(f); c >= 0; c = getc(f))
00488     if (!isspace(c)) {
00489       /* add 6 bits to bits */
00490       if (value_table[c] == 255)
00491         break;
00492       bits |= (value_table[c] << bitpos);
00493       bitpos -= 6;
00494 
00495       /* output character(s) */
00496       if (bitpos <= 2) {
00497         int d = bits >> 8;
00498         bits = (bits << 8) & 0xFF00;
00499         bitpos += 8;
00500         if (after_x90) {
00501           /* handle compression */
00502           if (d == 0) {
00503             last_char = 0x90;
00504             putc(0x90, tmpf);
00505           } else
00506             for (i = 1; i < d; i++)
00507               putc(last_char, tmpf);
00508           after_x90 = 0;
00509         } else if (d == 0x90)
00510           after_x90 = 1;
00511         else {
00512           last_char = d;
00513           putc(d, tmpf);
00514         }
00515       }
00516     }
00517   
00518   if (c < 0)
00519     return "unexpected EOF";
00520   else if (c != ':')
00521     return "bad character";
00522 
00523   fflush(tmpf);
00524   return 0;
00525 }
00526 
00527 int
00528 check_binhex_crc(FILE *f, int offset, int length)
00529 {
00530   int crc = 0;
00531   char buf[2048];
00532   reposition(f, offset);
00533   while (length > 0) {
00534     int n = (length < 2048 ? length : 2048);
00535     fread(buf, 1, n, f);
00536     crc = hqx_crcbuf(crc, n, buf);
00537     length -= n;
00538   }
00539   return crc == 0;
00540 }
00541 
00542 const char *
00543 check_binhex(FILE *f)
00544 {
00545   int fname_len, data_len, rsrc_len, off;
00546   
00547   /* check lengths */
00548   reposition(f, 0);
00549   fname_len = read_one(f);
00550   if (fname_len < 1 || fname_len > 63)
00551     return "bad length";
00552   reposition(f, 1 + fname_len + 11);
00553   data_len = read_four(f);
00554   rsrc_len = read_four(f);
00555   if (data_len < 0 || rsrc_len < 0 || data_len >= 0x800000 || rsrc_len >= 0x800000)
00556     return "bad length";
00557 
00558   /* check version */
00559   reposition(f, 1 + fname_len);
00560   if (read_one(f) != 0)
00561     return "bad version";
00562 
00563   /* check CRC */
00564   off = 1 + fname_len + 21;
00565   if (!check_binhex_crc(f, 0, off))
00566     return "bad header CRC";
00567   if (!check_binhex_crc(f, off, data_len + 2))
00568     return "bad data CRC";
00569   if (!check_binhex_crc(f, off + data_len + 2, rsrc_len + 2))
00570     return "bad resource fork CRC";
00571 
00572   return 0;
00573 }
00574 
00575 int
00576 main(int argc, char **argv)
00577 {
00578   FILE *ifp = 0;
00579   FILE *ofp = 0;
00580   struct pfb_writer w;
00581   const char *ifp_name = "<stdin>";
00582   int32 res_offset, res_data_offset, res_map_offset, type_list_offset;
00583   int32 post_type;
00584   int num_types, num_extracted = 0, pfb = 1;
00585   int raw = 0, appledouble = 0, binhex = 0, macbinary = 0;
00586   
00587   Clp_Parser *clp =
00588     Clp_NewParser(argc, argv, sizeof(options) / sizeof(options[0]), options);
00589   program_name = (char *)Clp_ProgramName(clp);
00590   
00591   /* interpret command line arguments using CLP */
00592   while (1) {
00593     int opt = Clp_Next(clp);
00594     switch (opt) {
00595       
00596      case RAW_OPT:
00597       raw = 1;
00598       appledouble = binhex = macbinary = 0;
00599       break;
00600       
00601      case MACBINARY_OPT:
00602       macbinary = 1;
00603       raw = appledouble = binhex = 0;
00604       break;
00605 
00606      case APPLEDOUBLE_OPT:
00607       appledouble = 1;
00608       raw = binhex = macbinary = 0;
00609       break;
00610 
00611      case BINHEX_OPT:
00612       binhex = 1;
00613       raw = appledouble = macbinary = 0;
00614       break;
00615       
00616      output_file:
00617      case OUTPUT_OPT:
00618       if (ofp)
00619         fatal_error("output file already specified");
00620       if (strcmp(clp->arg, "-") == 0)
00621         ofp = stdout;
00622       else {
00623         ofp = fopen(clp->arg, "w");
00624         if (!ofp) fatal_error("%s: %s", clp->arg, strerror(errno));
00625       }
00626       break;
00627       
00628      case PFB_OPT:
00629       pfb = 1;
00630       break;
00631       
00632      case PFA_OPT:
00633       pfb = 0;
00634       break;
00635       
00636      case LINE_LEN_OPT:
00637       blocklen = clp->val.i;
00638       break;
00639       
00640      case HELP_OPT:
00641       usage();
00642       exit(0);
00643       break;
00644       
00645      case VERSION_OPT:
00646       printf("t1unmac (LCDF t1utils) %s\n", VERSION);
00647       printf("Copyright (C) 1992-2000 I. Lee Hetherington, Eddie Kohler et al.\n\
00648 This is free software; see the source for copying conditions.\n\
00649 There is NO warranty, not even for merchantability or fitness for a\n\
00650 particular purpose.\n");
00651       exit(0);
00652       break;
00653       
00654      case Clp_NotOption:
00655       if (ifp && ofp)
00656         fatal_error("too many arguments");
00657       else if (ifp)
00658         goto output_file;
00659       if (strcmp(clp->arg, "-") == 0)
00660         ifp = stdin;
00661       else {
00662         ifp_name = clp->arg;
00663         ifp = fopen(clp->arg, "rb");
00664         if (!ifp) fatal_error("%s: %s", clp->arg, strerror(errno));
00665       }
00666       break;
00667       
00668      case Clp_Done:
00669       goto done;
00670       
00671      case Clp_BadOption:
00672       short_usage();
00673       exit(1);
00674       break;
00675       
00676     }
00677   }
00678   
00679  done:
00680   if (!ifp) ifp = stdin;
00681   if (!ofp) ofp = stdout;
00682   
00683 #if defined(_MSDOS) || defined(_WIN32)
00684   _setmode(_fileno(ifp), _O_BINARY);
00685   /* If we are processing a PFB (binary) output */
00686   /* file, we must set its file mode to binary. */
00687   if (pfb)
00688     _setmode(_fileno(ofp), _O_BINARY);
00689 #endif
00690   
00691   if (pfb)
00692     init_pfb_writer(&w, blocklen, ofp);
00693   else {
00694     if (blocklen == -1)
00695       blocklen = 64;
00696     else if (blocklen < 4) {
00697       blocklen = 4;
00698       error("warning: line length raised to %d", blocklen);
00699     } else if (blocklen > 1024) {
00700       blocklen = 1024;
00701       error("warning: line length lowered to %d", blocklen);
00702     }
00703   }
00704 
00705   /* check for non-seekable input */
00706   if (fseek(ifp, 0, 0)) {
00707     char buf[2048];
00708     FILE *tmp = tmpfile();
00709     if (!tmp)
00710       fatal_error("cannot open temporary file: %s", strerror(errno));
00711     while (!feof(ifp)) {
00712       int i = fread(buf, 1, 2048, ifp);
00713       if (i > 0)
00714         fwrite(buf, 1, i, tmp);
00715     }
00716     if (ferror(ifp))
00717       fatal_error("%s: %s", ifp_name, strerror(errno));
00718     reposition(tmp, 0);
00719     fflush(tmp);
00720     if (ifp != stdin)
00721       fclose(ifp);
00722     ifp = tmp;
00723   }
00724   
00725   /* check for empty file */
00726   fseek(ifp, 0, 2);
00727   if (ftell(ifp) == 0)
00728     fatal_error("%s: empty file\n\
00729   (Try re-transferring the files using MacBinary format.)",
00730                 ifp_name);
00731   
00732   reposition(ifp, 0);
00733   if (!raw && !appledouble && !binhex && !macbinary) {
00734     /* check magic number, try to figure out what it is */
00735     int i, magic;
00736     magic = read_four(ifp);
00737     reposition(ifp, 0);
00738 
00739     if (magic == APPLESINGLE_MAGIC || magic == APPLEDOUBLE_MAGIC)
00740       appledouble = 1;
00741     else if ((magic & 0xFF000000) == 0)
00742       macbinary = 1;
00743     else {
00744       binhex = 1;
00745       for (i = 0; i < 4; i++, magic >>= 8)
00746         if (!isprint(magic & 0xFF) && !isspace(magic & 0xFF))
00747           /* not an ASCII character, assume not BinHex */
00748           binhex = 0;
00749     }
00750 
00751     if (!appledouble && !macbinary && !binhex)
00752       fatal_error("%s: unknown file type", ifp_name);
00753   }
00754   
00755   if (raw) {
00756     /* raw resource file */
00757     res_offset = 0;
00758     
00759   } else if (macbinary) {       /* MacBinary (I or II) file */
00760     const char *check;
00761     int32 data_fork_size;
00762 
00763     /* check integrity of file */
00764     check = check_macbinary(ifp);
00765     if (check)
00766       fatal_error("%s: not a MacBinary file (%s)", ifp_name, check);
00767     
00768     /* read data and resource fork sizes in MacBinary header */
00769     reposition(ifp, 83);
00770     data_fork_size = read_four(ifp);
00771     (void) read_four(ifp);
00772     
00773     /* round data_fork_size up to multiple of 128 */
00774     if (data_fork_size % 128)
00775       data_fork_size += 128 - data_fork_size % 128;
00776     
00777     res_offset = 128 + data_fork_size;
00778 
00779   } else if (appledouble) {     /* AppleDouble file */
00780     const char *check;
00781     const char *applewhat;
00782     int i, n;
00783 
00784     /* check integrity */
00785     check = check_appledouble(ifp);
00786     if (check)
00787       fatal_error("%s: not an AppleDouble file (%s)", ifp_name, check);
00788     reposition(ifp, 0);
00789     if (read_four(ifp) == APPLESINGLE_MAGIC)
00790       applewhat = "AppleSingle";
00791     else
00792       applewhat = "AppleDouble";
00793     
00794     /* find offset to resource and/or data fork */
00795     reposition(ifp, 24);
00796     n = read_two(ifp);
00797     res_offset = -1;
00798     for (i = 0; i < n; i++) {
00799       int type = read_four(ifp);
00800       if (type == 0)
00801         fatal_error("%s: bad %s file (bad entry descriptor)", ifp_name, applewhat);
00802       if (type == 2)            /* resource fork entry */
00803         res_offset = read_four(ifp);
00804       else
00805         (void) read_four(ifp);
00806       (void) read_four(ifp);
00807     }
00808     if (res_offset < 0)
00809       fatal_error("%s: bad %s file (no resource fork)", ifp_name, applewhat);
00810 
00811   } else if (binhex) {          /* BinHex file */
00812     const char *check;
00813     FILE *tmpf = tmpfile();
00814     if (!tmpf)
00815       fatal_error("cannot open temporary file: %s", strerror(errno));
00816 
00817     /* check integrity */
00818     check = translate_binhex(ifp, tmpf);
00819     if (check)
00820       fatal_error("%s: not a BinHex file (%s)", ifp_name, check);
00821     check = check_binhex(tmpf);
00822     if (check)
00823       fatal_error("%s: bad BinHex file (%s)", ifp_name, check);
00824 
00825     /* find resource offset */
00826     reposition(tmpf, 0);
00827     res_offset = read_one(tmpf);
00828     reposition(tmpf, 1 + res_offset + 11);
00829     res_offset += 22 + read_four(tmpf) + 2;
00830     if (ifp != stdin)
00831       fclose(ifp);
00832     ifp = tmpf;
00833     
00834   } else {
00835     fatal_error("%s: strange format", ifp_name);
00836     exit(1);
00837   }
00838   
00839   /* read offsets from resource fork header */
00840   reposition(ifp, res_offset);
00841   res_data_offset = res_offset + read_four(ifp);
00842   res_map_offset = res_offset + read_four(ifp);
00843   
00844   /* read type list offset from resource map header */
00845   reposition(ifp, res_map_offset + 24);
00846   type_list_offset = res_map_offset + read_two(ifp);
00847   
00848   /* read type list */
00849   reposition(ifp, type_list_offset);
00850   num_types = read_two(ifp) + 1;
00851   
00852   /* find POST type */
00853   post_type =  (int32)('P' & 0xff) << 24;
00854   post_type |= (int32)('O' & 0xff) << 16;
00855   post_type |= (int32)('S' & 0xff) << 8;
00856   post_type |= (int32)('T' & 0xff);
00857   
00858   while (num_types--) {
00859     if (read_four(ifp) == post_type) {
00860       int nrsrc = 1 + read_two(ifp);
00861       int list_offset = type_list_offset + read_two(ifp);
00862       int rsrc_pos = 0;
00863       int want_id = 501;
00864       int second_time = 1;
00865       reposition(ifp, list_offset);
00866       /* read resources sequentially, starting with ID 501, until we encounter
00867          an "end" resource or we can't find the next resource */
00868       while (rsrc_pos < nrsrc) {
00869         int offset = ftell(ifp);
00870         int id = read_two(ifp);
00871         if (id == want_id) {
00872           (void) read_two(ifp);
00873           (void) read_one(ifp);
00874           num_extracted++;
00875           if (!extract_data(ifp, ofp, &w, res_data_offset + read_three(ifp), pfb))
00876             break;
00877           second_time = 0;
00878           want_id++;
00879         }
00880         reposition(ifp, offset + 12);
00881         rsrc_pos++;
00882         if (rsrc_pos >= nrsrc && !second_time) {
00883           reposition(ifp, list_offset);
00884           rsrc_pos = 0;
00885         }
00886       }
00887       break;
00888     } else {
00889       (void) read_two(ifp);
00890       (void) read_two(ifp);
00891     }
00892   }
00893 
00894 #if 0
00895   system("/bin/rm -f /tmp/x.*");
00896   {
00897     FILE *f;
00898     int i;
00899     reposition(ifp, res_offset + 16);
00900     if ((f = fopen("/tmp/x.systemarea", "wb"))) {
00901       for (i = res_offset + 16; i < res_data_offset; i++) {
00902         putc(getc(ifp), f);
00903       }
00904       fclose(f);
00905     }
00906   }
00907   reposition(ifp, type_list_offset);
00908   num_types = read_two(ifp) + 1;
00909   while (num_types--) {
00910     int t = read_four(ifp);
00911     int num_of_type = 1 + read_two(ifp);
00912     int32 save_offset = ftell(ifp) + 2;
00913     reposition(ifp, type_list_offset + read_two(ifp));
00914     while (num_of_type--) {
00915       FILE *f;
00916       char buf[2048];
00917       int x, i, attrs;
00918       x = ftell(ifp);
00919       i = read_two(ifp);        /* ID */
00920       read_two(ifp);
00921       attrs = read_one(ifp);
00922       sprintf(buf, "/tmp/x.%c%c%c%c.%d", (t>>24)&255, (t>>16)&255, (t>>8)&255, t&255, i);
00923       fprintf(stderr, "%c%c%c%c.%d %d", (t>>24)&255, (t>>16)&255, (t>>8)&255, t&255, i, attrs);
00924       if ((f = fopen(buf, "wb"))) {
00925         int l;
00926         reposition(ifp, res_data_offset + read_three(ifp));
00927         l = read_four(ifp);
00928         fprintf(stderr, " %d\n", l);
00929         while (l > 0) {
00930           int n = (l < 2048 ? l : 2048);
00931           fread(buf, 1, n, ifp);
00932           fwrite(buf, 1, n, f);
00933           l -= n;
00934         }
00935         fclose(f);
00936       }
00937       reposition(ifp, x + 12);
00938     }
00939     reposition(ifp, save_offset);
00940   }
00941 #endif
00942 
00943   if (pfb)
00944     pfb_writer_end(&w);
00945   if (num_extracted == 0)
00946     error("%s: not a Type 1 font (no POST resources)", ifp_name);
00947   
00948   fclose(ifp);
00949   fclose(ofp);
00950   return 0;
00951 }

Generated at Mon Dec 11 22:46:28 2000 for Postscript Utility Library by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000