home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
700-799
/
ff732.lha
/
pstools
/
t1utils
/
t1sourcecode
/
t1binary.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-26
|
6KB
|
250 lines
/* t1binary
*
* This program takes an Adobe Type-1 font program in ASCII (PFA) format and
* converts it to binary (PFB) format.
*
* 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: t1binary.c,v $
* Revision 1.1 92/05/22 11:58:17 ilh
* initial version
*
*/
#ifndef lint
static char rcsid[] =
"@(#) $Id: t1binary.c,v 1.1 92/05/22 11:58:17 ilh Exp $";
static char copyright[] =
"@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.";
#endif
/* Note: this is ANSI C. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define BANNER "This is t1binary 1.1.\n"
#define LINESIZE 256
#define MAXBLOCKLEN ((1<<17)-6)
#define MINBLOCKLEN ((1<<8)-6)
#define MARKER 128
#define ASCII 1
#define BINARY 2
#define DONE 3
typedef unsigned char byte;
static FILE *ifp = stdin;
static FILE *ofp = stdout;
static char line[LINESIZE];
/* for PFB block buffering */
static byte blockbuf[MAXBLOCKLEN];
static int blocklen = MAXBLOCKLEN;
static int blockpos = -1;
static int blocktyp = ASCII;
/* This function flushes a buffered PFB block. */
static void output_block()
{
int i;
/* output four-byte block length */
fputc(blockpos & 0xff, ofp);
fputc((blockpos >> 8) & 0xff, ofp);
fputc((blockpos >> 16) & 0xff, ofp);
fputc((blockpos >> 24) & 0xff, ofp);
/* output block data */
for (i = 0; i < blockpos; i++)
fputc(blockbuf[i], ofp);
/* mark block buffer empty and uninitialized */
blockpos = -1;
}
/* This function outputs a single byte. If output is in PFB format then output
is buffered through blockbuf[]. If output is in PFA format, then output
will be hexadecimal if in_eexec is set, ASCII otherwise. */
static void output_byte(byte b)
{
if (blockpos < 0) {
fputc(MARKER, ofp);
fputc(blocktyp, ofp);
blockpos = 0;
}
blockbuf[blockpos++] = b;
if (blockpos == blocklen)
output_block();
}
/* This function outputs a null-terminated string through the PFB buffering. */
static void output_string(char *string)
{
while (*string)
output_byte((byte) *string++);
}
/* This function returns the value (0-15) of a single hex digit. It returns
0 for an invalid hex digit. */
static int hexval(char c)
{
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
else if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
else if (c >= '0' && c <= '9')
return c - '0';
else
return 0;
}
/* This function outputs the binary data associated with a string of
hexadecimal digits. There must be an even number of digits. */
static void output_hex_string(char *string)
{
while (string[0] && string[0] != '\n') {
if (!string[1]) {
fprintf(stderr, "error: only one hex digit\n");
exit(1);
}
output_byte((byte)((hexval(string[0]) << 4) + hexval(string[1])));
string += 2;
}
}
/* This function returns 1 if the string contains all '0's. */
static int all_zeroes(char *string)
{
while (*string == '0')
string++;
return *string == '\0' || *string == '\n';
}
static void usage()
{
fprintf(stderr,
"usage: t1binary [-l block-length] [input [output]]\n");
fprintf(stderr,
"The block length applies to the length of blocks in the\n");
fprintf(stderr,
"PFB output file; the default is to use the largest possible.\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 t1binary %s.\n", revision);
}
int main(int argc, char **argv)
{
int c;
extern char *optarg;
extern int optind;
extern int getopt(int argc, char **argv, char *optstring);
print_banner();
/* interpret command line arguments using getopt */
while ((c = getopt(argc, argv, "l:")) != -1)
switch (c) {
case 'l':
blocklen = atoi(optarg);
if (blocklen < MINBLOCKLEN) {
blocklen = MINBLOCKLEN;
fprintf(stderr,
"warning: using minimum block length of %d\n",
blocklen);
} else if (blocklen > MAXBLOCKLEN) {
blocklen = MAXBLOCKLEN;
fprintf(stderr,
"warning: using maximum block length of %d\n",
blocklen);
}
break;
default:
usage();
break;
}
if (argc - optind > 2)
usage();
/* possibly open input & output files */
if (argc - optind >= 1) {
ifp = fopen(argv[optind], "r");
if (!ifp) {
fprintf(stderr, "error: cannot open %s for reading\n",
argv[optind]);
exit(1);
}
}
if (argc - optind >= 2) {
ofp = fopen(argv[optind + 1], "w");
if (!ofp) {
fprintf(stderr, "error: cannot open %s for writing\n",
argv[optind + 1]);
exit(1);
}
}
/* peek at first byte to see if it is the PFB marker 0x80 */
c = fgetc(ifp);
if (c == MARKER) {
fprintf(stderr,
"error: input may already be binary (starts with 0x80)\n");
exit(1);
}
ungetc(c, ifp);
/* Finally, we loop until no more input. We need to look for `currentfile
eexec' to start eexec section (hex to binary conversion) and line of all
zeros to switch back to ASCII. */
while (fgets(line, LINESIZE, ifp), !feof(ifp) && !ferror(ifp)) {
if (blocktyp == ASCII && strcmp(line, "currentfile eexec\n") == 0) {
output_string(line);
output_block();
blocktyp = BINARY;
} else if (blocktyp == BINARY && all_zeroes(line)) {
output_block();
blocktyp = ASCII;
output_string(line);
} else if (blocktyp == ASCII) {
output_string(line);
} else {
output_hex_string(line);
}
}
output_block();
fputc(MARKER, ofp);
fputc(DONE, ofp);
fclose(ifp);
fclose(ofp);
return 0;
}