home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
print
/
t1utils
/
unpost.c
< prev
next >
Wrap
Text File
|
1994-02-04
|
9KB
|
347 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
*
* 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;
}