home *** CD-ROM | disk | FTP | other *** search
- /* unpost
- *
- * This program converts Macintosh type-1 fonts stored in MacBinary (I or II)
- * format or raw resource fork to PFA and PFB formats.
- *
- * Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.
- *
- * Permission is hereby granted to use, modify, and distribute this program
- * for any purpose provided this copyright notice and the one below remain
- * intact.
- *
- * I. Lee Hetherington (ilh@lcs.mit.edu)
- *
- * $Log: unpost.c,v $
- * Revision 1.1 92/05/22 12:07:49 ilh
- * initial version
- *
- * Ported to Microsoft C/C++ Compiler and MS-DOS operating system by
- * Kai-Uwe Herbing (herbing@netmbx.netmbx.de) on June 12, 1992. Code
- * specific to the MS-DOS version is encapsulated with #ifdef _MSDOS
- * ... #endif, where _MSDOS is an identifier, which is automatically
- * defined, if you compile with the Microsoft C/C++ Compiler.
- *
- */
-
- /* Note: this is ANSI C. */
-
- #ifndef lint
- static char rcsid[] =
- "@(#) $Id: unpost.c,v 1.1 92/05/22 12:07:49 ilh Exp Locker: ilh $";
- static char copyright[] =
- "@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.";
- #ifdef _MSDOS
- static char portnotice[] =
- "@(#) Ported to MS-DOS by Kai-Uwe Herbing (herbing@netmbx.netmbx.de).";
- #endif
- #endif
-
- #ifdef _MSDOS
- #include <fcntl.h>
- #include <getopt.h>
- #include <io.h>
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <limits.h>
-
- /* int32 must be at least 32-bit */
- #if INT_MAX >= 0x7FFFFFFFUL
- typedef int int32;
- #else
- typedef long int32;
- #endif
-
- /* Some functions to read one, two, three, and four byte integers in 68000
- byte order (most significant byte first). */
-
- static int read_one(FILE *fi)
- {
- return fgetc(fi);
- }
-
- static int read_two(FILE *fi)
- {
- int val;
-
- val = read_one(fi);
- val = (val << 8) + read_one(fi);
-
- return val;
- }
-
- static int32 read_three(FILE *fi)
- {
- int32 val;
-
- val = read_one(fi);
- val = (val << 8) + read_one(fi);
- val = (val << 8) + read_one(fi);
-
- return val;
- }
-
- static int32 read_four(FILE *fi)
- {
- int32 val;
-
- val = read_one(fi);
- val = (val << 8) + read_one(fi);
- val = (val << 8) + read_one(fi);
- val = (val << 8) + read_one(fi);
-
- return val;
- }
-
- /* Function to write four byte length to PFB file: least significant byte
- first. */
-
- static void write_pfb_length(FILE *fo, int32 len)
- {
- fputc((int) (len & 0xff), fo);
- len >>= 8;
- fputc((int) (len & 0xff), fo);
- len >>= 8;
- fputc((int) (len & 0xff), fo);
- len >>= 8;
- fputc((int) (len & 0xff), fo);
- }
-
- static void reposition(FILE *fi, int32 absolute)
- {
- if (fseek(fi, absolute, 0) == -1) {
- fprintf(stderr, "error: fseek failed to position %d.\n", absolute);
- fprintf(stderr, " Is this file seekable?\n");
- exit(1);
- }
- }
-
- static int hex_column = 0; /* current column of hex */
- /* ASCII output */
-
- static void output_hex_byte(FILE *fo, int b)
- {
- static char *hex = "0123456789ABCDEF";
-
- if (hex_column > 62) { /* 64 column output */
- fputc('\n', fo);
- hex_column = 0;
- }
- fputc(hex[b >> 4], fo);
- fputc(hex[b & 0xf], fo);
- hex_column += 2;
- }
-
- /* Function to extract a particular POST resource. Offset points to the four
- byte length which is followed by the data. The first byte of the POST data
- specifies resource type: 1 for ASCII, 2 for binary, and 5 for end. The
- second byte is always zero. */
-
- static void extract_data(FILE *fi, FILE *fo, int32 offset, int binary)
- {
- enum PS_type { PS_ascii = 1, PS_binary = 2, PS_end = 5 };
- static enum PS_type last_type = PS_ascii;
- int32 len, save_offset = ftell(fi);
- int c;
-
- reposition(fi, offset);
- len = read_four(fi) - 2; /* subtract type field */
- switch ((enum PS_type)read_one(fi)) {
- case PS_ascii:
- (void) read_one(fi);
- if (binary) {
- fputc(128, fo);
- fputc(1, fo);
- write_pfb_length(fo, len);
- while (len--) {
- if ((c = read_one(fi)) == '\r') /* change \r to \n */
- c = '\n';
- fputc(c, fo);
- }
- } else {
- if (last_type == PS_binary)
- fputc('\n', fo);
- while (len--) {
- if ((c = read_one(fi)) == '\r') /* change \r to \n */
- c = '\n';
- fputc(c, fo);
- }
- }
- last_type = 1;
- break;
- case PS_binary:
- (void) read_one(fi);
- if (binary) {
- fputc(128, fo);
- fputc(2, fo);
- write_pfb_length(fo, len);
- while (len--)
- fputc(read_one(fi), fo);
- } else {
- if (last_type != 2)
- hex_column = 0;
- while (len--)
- output_hex_byte(fo, read_one(fi));
- last_type = 2;
- }
- break;
- case PS_end:
- (void) read_one(fi);
- if (binary) {
- fputc(128, fo);
- fputc(3, fo);
- }
- break;
- }
- reposition(fi, save_offset);
- }
-
- static void usage(void)
- {
- fprintf(stderr, "usage: unpost [-b] [-r] in-file [out-file]\n");
- exit(1);
- }
-
- static void print_banner()
- {
- static char rcs_revision[] = "$Revision: 1.1 $";
- static char revision[20];
-
- if (sscanf(rcs_revision, "$Revision: %19s", revision) != 1)
- revision[0] = '\0';
- fprintf(stderr, "This is unpost %s.\n", revision);
- }
-
- int main(int argc, char **argv)
- {
- FILE *fi;
- FILE *fo = stdout;
- int32 data_fork_size;
- int32 res_offset, res_data_offset, res_map_offset, type_list_offset;
- int32 post_type;
- int num_types, num_of_type, num_extracted = 0, binary = 0, raw = 0;
- int c;
- extern int optind;
- extern int getopt(int, char **, char*);
-
- print_banner();
-
- /* parse command line */
- while ((c = getopt(argc, argv, "br?")) != -1)
- switch(c) {
- case 'b':
- ++binary;
- break;
- case 'r':
- ++raw;
- break;
- default:
- usage();
- }
- if (argc - optind < 1 || argc - optind > 2)
- usage();
-
- /* open input file */
- #ifdef _MSDOS
- /* As we are processing an input file in Macintosh */
- /* format, we should avoid any kind of translation */
- /* and consequently open it in binary file mode. */
- fi = fopen(argv[optind], "rb");
- #else
- fi = fopen(argv[optind], "rb");
- #endif
- if (!fi) {
- fprintf(stderr, "error: cannot open %s for reading\n", argv[1]);
- exit(1);
- }
- /* possibly open output file */
- if (argc - optind == 2) {
- fo = fopen(argv[optind + 1], "wb");
- if (!fo) {
- fprintf(stderr, "error: cannot open %s for writing\n", argv[2]);
- exit(1);
- }
- }
-
- #ifdef _MSDOS
- /* If we are processing a PFB (binary) output */
- /* file, we must set its file mode to binary. */
- if (binary)
- _setmode(_fileno(fo), _O_BINARY);
- #endif
-
- if (raw) {
-
- /* raw resource file */
-
- res_offset = 0;
-
- } else {
-
- /* MacBinary (I or II) file */
-
- /* SHOULD CHECK INTEGRITY OF MACBINARY HEADER HERE TO VERIFY THAT WE
- REALLY HAVE A MACBINARY FILE. MACBINARY-II-STANDARD.TXT DESCRIBES
- AN APPROPRIATE VERIFICATION PROCEDURE. */
-
- /* read data and resource fork sizes in MacBinary header */
- reposition(fi, 83);
- data_fork_size = read_four(fi);
- (void) read_four(fi);
-
- /* round data_fork_size up to multiple of 128 */
- if (data_fork_size % 128)
- data_fork_size += 128 - data_fork_size % 128;
-
- res_offset = 128 + data_fork_size;
-
- }
-
- /* read offsets from resource fork header */
- reposition(fi, res_offset);
- res_data_offset = res_offset + read_four(fi);
- res_map_offset = res_offset + read_four(fi);
-
- /* read type list offset from resource map header */
- reposition(fi, res_map_offset + 24);
- type_list_offset = res_map_offset + read_two(fi);
-
- /* read type list */
- reposition(fi, type_list_offset);
- num_types = read_two(fi) + 1;
-
- /* find POST type */
- post_type = (int32) ('P' & 0xff) << 24;
- post_type |= (int32) ('O' & 0xff) << 16;
- post_type |= (int32) ('S' & 0xff) << 8;
- post_type |= (int32) ('T' & 0xff);
-
- while (num_types--) {
- if (read_four(fi) == post_type) {
- num_of_type = 1 + read_two(fi);
- reposition(fi, type_list_offset + read_two(fi));
- while (num_of_type--) {
- (void) read_two(fi); /* ID */
- (void) read_two(fi);
- (void) read_one(fi);
- extract_data(fi, fo, res_data_offset + read_three(fi), binary);
- ++num_extracted;
- (void) read_four(fi);
- }
- break;
- } else {
- (void) read_two(fi);
- (void) read_two(fi);
- }
- }
-
- fclose(fi);
- if (fo != stdout) {
- fclose(fo);
- fprintf(stderr, "Extracted %d POST resource%s.\n", num_extracted,
- (num_extracted == 1) ? "" : "s");
- }
-
- return 0;
- }