home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ARM Club 3
/
TheARMClub_PDCD3.iso
/
hensa
/
utilities
/
b182_1
/
t1utils
/
c
/
unpost
< prev
Wrap
Text File
|
1994-02-25
|
7KB
|
333 lines
/* 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
*
*/
/* Note: this is ANSI C. */
#ifndef lint
static char rcsid[] =
"@(#) $Id: unpost.c,v 1.1 92/05/22 12:07:49 ilh Exp $";
static char copyright[] =
"@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.";
#endif
#include <stdio.h>
#include <stdlib.h>
/* 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 long read_three(FILE *fi)
{
long val;
val = read_one(fi);
val = (val << 8) + read_one(fi);
val = (val << 8) + read_one(fi);
return val;
}
static long read_four(FILE *fi)
{
long 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, long len)
{
fputc(len & 0xff, fo);
len >>= 8;
fputc(len & 0xff, fo);
len >>= 8;
fputc(len & 0xff, fo);
len >>= 8;
fputc(len & 0xff, fo);
}
static void reposition(FILE *fi, long absolute)
{
if (fseek(fi, absolute, 0) == -1) {
fprintf(stderr, "error: fseek failed to position %ld.\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, long offset, int binary)
{
enum PS_type { PS_ascii = 1, PS_binary = 2, PS_end = 5 };
static enum PS_type last_type = PS_ascii;
long 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, *fo;
long data_fork_size;
long res_offset, res_data_offset, res_map_offset, type_list_offset;
long 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();
}
/* open files */
if (argc - optind == 1) {
fi = fopen(argv[optind++], "r");
if (!fi) {
fprintf(stderr, "error: couldn't open `%s' for reading\n",
argv[--optind]);
exit(1);
}
fo = stdout;
} else if (argc - optind == 2) {
fi = fopen(argv[optind++], "r");
if (!fi) {
fprintf(stderr, "error: couldn't open `%s' for reading\n",
argv[--optind]);
exit(1);
}
fo = fopen(argv[optind++], "w");
if (!fo) {
fprintf(stderr, "error: couldn't open `%s' for writing\n",
argv[--optind]);
exit(1);
}
} else {
usage();
}
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 = ('P' << 24) + ('O' << 16) + ('S' << 8) + 'T';
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;
}
/*
* for Emacs...
* Local Variables:
* mode: C
* comment-column: 50
* fill-column: 79
* c-indent-level: 2
* c-continued-statement-offset: 2
* c-brace-offset: -2
* c-argdecl-indent: 2
* c-label-offset: -2
* End:
*/