1*219b2ee8SDavid du Colombier /*
2*219b2ee8SDavid du Colombier *
3*219b2ee8SDavid du Colombier * Program that converts IBM font files to a format that works on Unix systems.
4*219b2ee8SDavid du Colombier * Essentially all the information needed came from the Adobe paper "Supporting
5*219b2ee8SDavid du Colombier * Downloadable PostScript Fonts". To use the program type,
6*219b2ee8SDavid du Colombier *
7*219b2ee8SDavid du Colombier * ibmfont font.ibm >font.unix
8*219b2ee8SDavid du Colombier *
9*219b2ee8SDavid du Colombier * where font.ibm is the font file, exactly as it came over from an IBM PC,
10*219b2ee8SDavid du Colombier * and font.unix is equivalent host resident font file usable on Unix systems.
11*219b2ee8SDavid du Colombier *
12*219b2ee8SDavid du Colombier */
13*219b2ee8SDavid du Colombier
14*219b2ee8SDavid du Colombier #include <stdio.h>
15*219b2ee8SDavid du Colombier #include <signal.h>
16*219b2ee8SDavid du Colombier
17*219b2ee8SDavid du Colombier #define OFF 0
18*219b2ee8SDavid du Colombier #define ON 1
19*219b2ee8SDavid du Colombier
20*219b2ee8SDavid du Colombier #define NON_FATAL 0
21*219b2ee8SDavid du Colombier #define FATAL 1
22*219b2ee8SDavid du Colombier
23*219b2ee8SDavid du Colombier #define FALSE 0
24*219b2ee8SDavid du Colombier #define TRUE 1
25*219b2ee8SDavid du Colombier
26*219b2ee8SDavid du Colombier char **argv;
27*219b2ee8SDavid du Colombier int argc;
28*219b2ee8SDavid du Colombier
29*219b2ee8SDavid du Colombier char *prog_name;
30*219b2ee8SDavid du Colombier
31*219b2ee8SDavid du Colombier int x_stat;
32*219b2ee8SDavid du Colombier int debug = OFF;
33*219b2ee8SDavid du Colombier int ignore = OFF;
34*219b2ee8SDavid du Colombier
35*219b2ee8SDavid du Colombier FILE *fp_in = stdin;
36*219b2ee8SDavid du Colombier FILE *fp_out = stdout;
37*219b2ee8SDavid du Colombier
38*219b2ee8SDavid du Colombier /*****************************************************************************/
39*219b2ee8SDavid du Colombier
main(agc,agv)40*219b2ee8SDavid du Colombier main(agc, agv)
41*219b2ee8SDavid du Colombier
42*219b2ee8SDavid du Colombier int agc;
43*219b2ee8SDavid du Colombier char *agv[];
44*219b2ee8SDavid du Colombier
45*219b2ee8SDavid du Colombier {
46*219b2ee8SDavid du Colombier
47*219b2ee8SDavid du Colombier /*
48*219b2ee8SDavid du Colombier *
49*219b2ee8SDavid du Colombier * IBM PC to Unix font converter.
50*219b2ee8SDavid du Colombier *
51*219b2ee8SDavid du Colombier */
52*219b2ee8SDavid du Colombier
53*219b2ee8SDavid du Colombier argc = agc;
54*219b2ee8SDavid du Colombier argv = agv;
55*219b2ee8SDavid du Colombier prog_name = argv[0];
56*219b2ee8SDavid du Colombier
57*219b2ee8SDavid du Colombier options();
58*219b2ee8SDavid du Colombier arguments();
59*219b2ee8SDavid du Colombier exit(x_stat);
60*219b2ee8SDavid du Colombier
61*219b2ee8SDavid du Colombier } /* End of main */
62*219b2ee8SDavid du Colombier
63*219b2ee8SDavid du Colombier /*****************************************************************************/
64*219b2ee8SDavid du Colombier
options()65*219b2ee8SDavid du Colombier options()
66*219b2ee8SDavid du Colombier
67*219b2ee8SDavid du Colombier {
68*219b2ee8SDavid du Colombier
69*219b2ee8SDavid du Colombier int ch;
70*219b2ee8SDavid du Colombier char *names = "DI";
71*219b2ee8SDavid du Colombier
72*219b2ee8SDavid du Colombier extern char *optarg;
73*219b2ee8SDavid du Colombier extern int optind;
74*219b2ee8SDavid du Colombier
75*219b2ee8SDavid du Colombier /*
76*219b2ee8SDavid du Colombier *
77*219b2ee8SDavid du Colombier * Command line options.
78*219b2ee8SDavid du Colombier *
79*219b2ee8SDavid du Colombier */
80*219b2ee8SDavid du Colombier
81*219b2ee8SDavid du Colombier while ( (ch = getopt(argc, argv, names)) != EOF ) {
82*219b2ee8SDavid du Colombier switch ( ch ) {
83*219b2ee8SDavid du Colombier case 'D': /* debug flag */
84*219b2ee8SDavid du Colombier debug = ON;
85*219b2ee8SDavid du Colombier break;
86*219b2ee8SDavid du Colombier
87*219b2ee8SDavid du Colombier case 'I': /* ignore FATAL errors */
88*219b2ee8SDavid du Colombier ignore = ON;
89*219b2ee8SDavid du Colombier break;
90*219b2ee8SDavid du Colombier
91*219b2ee8SDavid du Colombier case '?': /* don't understand the option */
92*219b2ee8SDavid du Colombier error(FATAL, "");
93*219b2ee8SDavid du Colombier break;
94*219b2ee8SDavid du Colombier
95*219b2ee8SDavid du Colombier default: /* don't know what to do for ch */
96*219b2ee8SDavid du Colombier error(FATAL, "missing case for option %c\n", ch);
97*219b2ee8SDavid du Colombier break;
98*219b2ee8SDavid du Colombier } /* End switch */
99*219b2ee8SDavid du Colombier } /* End while */
100*219b2ee8SDavid du Colombier
101*219b2ee8SDavid du Colombier argc -= optind;
102*219b2ee8SDavid du Colombier argv += optind;
103*219b2ee8SDavid du Colombier
104*219b2ee8SDavid du Colombier } /* End of options */
105*219b2ee8SDavid du Colombier
106*219b2ee8SDavid du Colombier /*****************************************************************************/
107*219b2ee8SDavid du Colombier
arguments()108*219b2ee8SDavid du Colombier arguments()
109*219b2ee8SDavid du Colombier
110*219b2ee8SDavid du Colombier {
111*219b2ee8SDavid du Colombier
112*219b2ee8SDavid du Colombier /*
113*219b2ee8SDavid du Colombier *
114*219b2ee8SDavid du Colombier * Everything esle is an input file. No arguments or '-' means stdin.
115*219b2ee8SDavid du Colombier *
116*219b2ee8SDavid du Colombier */
117*219b2ee8SDavid du Colombier
118*219b2ee8SDavid du Colombier
119*219b2ee8SDavid du Colombier if ( argc < 1 )
120*219b2ee8SDavid du Colombier conv();
121*219b2ee8SDavid du Colombier else
122*219b2ee8SDavid du Colombier while ( argc > 0 ) {
123*219b2ee8SDavid du Colombier if ( strcmp(*argv, "-") == 0 )
124*219b2ee8SDavid du Colombier fp_in = stdin;
125*219b2ee8SDavid du Colombier else if ( (fp_in = fopen(*argv, "r")) == NULL )
126*219b2ee8SDavid du Colombier error(FATAL, "can't open %s", *argv);
127*219b2ee8SDavid du Colombier conv();
128*219b2ee8SDavid du Colombier if ( fp_in != stdin )
129*219b2ee8SDavid du Colombier fclose(fp_in);
130*219b2ee8SDavid du Colombier argc--;
131*219b2ee8SDavid du Colombier argv++;
132*219b2ee8SDavid du Colombier } /* End while */
133*219b2ee8SDavid du Colombier
134*219b2ee8SDavid du Colombier } /* End of arguments */
135*219b2ee8SDavid du Colombier
136*219b2ee8SDavid du Colombier /*****************************************************************************/
137*219b2ee8SDavid du Colombier
conv()138*219b2ee8SDavid du Colombier conv()
139*219b2ee8SDavid du Colombier
140*219b2ee8SDavid du Colombier {
141*219b2ee8SDavid du Colombier
142*219b2ee8SDavid du Colombier int blocksize;
143*219b2ee8SDavid du Colombier int blocktype;
144*219b2ee8SDavid du Colombier int seg;
145*219b2ee8SDavid du Colombier long ftell();
146*219b2ee8SDavid du Colombier
147*219b2ee8SDavid du Colombier /*
148*219b2ee8SDavid du Colombier *
149*219b2ee8SDavid du Colombier * Font files on the IBM PC are stored in a compressed binary format. Individual
150*219b2ee8SDavid du Colombier * segments in the file are preceeded by a header that looks like,
151*219b2ee8SDavid du Colombier *
152*219b2ee8SDavid du Colombier * Byte 1: 128
153*219b2ee8SDavid du Colombier * Byte 2: segment type (1=ASCII, 2=TOHEX, or 3=EOF)
154*219b2ee8SDavid du Colombier * Bytes 3-6: length of the segment
155*219b2ee8SDavid du Colombier * Bytes 7 ... data
156*219b2ee8SDavid du Colombier *
157*219b2ee8SDavid du Colombier */
158*219b2ee8SDavid du Colombier
159*219b2ee8SDavid du Colombier while ( 1 ) {
160*219b2ee8SDavid du Colombier seg = ftell(fp_in);
161*219b2ee8SDavid du Colombier if ( getc(fp_in) != 128 )
162*219b2ee8SDavid du Colombier error(FATAL, "bad file format");
163*219b2ee8SDavid du Colombier blocktype = getc(fp_in);
164*219b2ee8SDavid du Colombier blocksize = getint(fp_in);
165*219b2ee8SDavid du Colombier if ( debug == ON ) {
166*219b2ee8SDavid du Colombier fprintf(stderr, "blocktype = %d, blocksize = %d\n", blocktype, blocksize);
167*219b2ee8SDavid du Colombier fprintf(stderr, "start=0%o, end=0%o\n", seg, seg+blocksize+6);
168*219b2ee8SDavid du Colombier fprintf(stderr, "start=%d, end=%d\n", seg, seg+blocksize+6);
169*219b2ee8SDavid du Colombier } /* End if */
170*219b2ee8SDavid du Colombier switch ( blocktype ) {
171*219b2ee8SDavid du Colombier case 1:
172*219b2ee8SDavid du Colombier asciitext(blocksize);
173*219b2ee8SDavid du Colombier break;
174*219b2ee8SDavid du Colombier
175*219b2ee8SDavid du Colombier case 2:
176*219b2ee8SDavid du Colombier hexdata(blocksize);
177*219b2ee8SDavid du Colombier break;
178*219b2ee8SDavid du Colombier
179*219b2ee8SDavid du Colombier case 3:
180*219b2ee8SDavid du Colombier return;
181*219b2ee8SDavid du Colombier
182*219b2ee8SDavid du Colombier default:
183*219b2ee8SDavid du Colombier error(FATAL, "unknown resource type %d", blocktype);
184*219b2ee8SDavid du Colombier } /* End switch */
185*219b2ee8SDavid du Colombier } /* End while */
186*219b2ee8SDavid du Colombier
187*219b2ee8SDavid du Colombier } /* End of conv */
188*219b2ee8SDavid du Colombier
189*219b2ee8SDavid du Colombier /*****************************************************************************/
190*219b2ee8SDavid du Colombier
asciitext(count)191*219b2ee8SDavid du Colombier asciitext(count)
192*219b2ee8SDavid du Colombier
193*219b2ee8SDavid du Colombier int count; /* bytes left in the block */
194*219b2ee8SDavid du Colombier
195*219b2ee8SDavid du Colombier {
196*219b2ee8SDavid du Colombier
197*219b2ee8SDavid du Colombier int ch;
198*219b2ee8SDavid du Colombier int i = 0;
199*219b2ee8SDavid du Colombier
200*219b2ee8SDavid du Colombier /*
201*219b2ee8SDavid du Colombier *
202*219b2ee8SDavid du Colombier * Handles type 1 (ie. ASCII text) blocks. Changing carriage returns to newlines
203*219b2ee8SDavid du Colombier * is all I've done.
204*219b2ee8SDavid du Colombier *
205*219b2ee8SDavid du Colombier */
206*219b2ee8SDavid du Colombier
207*219b2ee8SDavid du Colombier for ( i = 0; i < count; i++ ) {
208*219b2ee8SDavid du Colombier if ( (ch = getc(fp_in)) == '\r' )
209*219b2ee8SDavid du Colombier ch = '\n';
210*219b2ee8SDavid du Colombier putc(ch, fp_out);
211*219b2ee8SDavid du Colombier } /* End for */
212*219b2ee8SDavid du Colombier
213*219b2ee8SDavid du Colombier } /* End of asciitext */
214*219b2ee8SDavid du Colombier
215*219b2ee8SDavid du Colombier /*****************************************************************************/
216*219b2ee8SDavid du Colombier
hexdata(count)217*219b2ee8SDavid du Colombier hexdata(count)
218*219b2ee8SDavid du Colombier
219*219b2ee8SDavid du Colombier int count; /* bytes left in the block */
220*219b2ee8SDavid du Colombier
221*219b2ee8SDavid du Colombier {
222*219b2ee8SDavid du Colombier
223*219b2ee8SDavid du Colombier int i;
224*219b2ee8SDavid du Colombier int n;
225*219b2ee8SDavid du Colombier
226*219b2ee8SDavid du Colombier /*
227*219b2ee8SDavid du Colombier *
228*219b2ee8SDavid du Colombier * Reads the next count bytes and converts each byte to hex. Also starts a new
229*219b2ee8SDavid du Colombier * line every 80 hex characters.
230*219b2ee8SDavid du Colombier *
231*219b2ee8SDavid du Colombier */
232*219b2ee8SDavid du Colombier
233*219b2ee8SDavid du Colombier for ( i = 0, n = 0; i < count; i++ ) {
234*219b2ee8SDavid du Colombier fprintf(fp_out, "%.2X", getc(fp_in));
235*219b2ee8SDavid du Colombier if ( (++n % 40) == 0 )
236*219b2ee8SDavid du Colombier putc('\n', fp_out);
237*219b2ee8SDavid du Colombier } /* End for */
238*219b2ee8SDavid du Colombier
239*219b2ee8SDavid du Colombier } /* End of hexdata */
240*219b2ee8SDavid du Colombier
241*219b2ee8SDavid du Colombier /*****************************************************************************/
242*219b2ee8SDavid du Colombier
getint()243*219b2ee8SDavid du Colombier getint()
244*219b2ee8SDavid du Colombier
245*219b2ee8SDavid du Colombier {
246*219b2ee8SDavid du Colombier
247*219b2ee8SDavid du Colombier int val;
248*219b2ee8SDavid du Colombier
249*219b2ee8SDavid du Colombier /*
250*219b2ee8SDavid du Colombier *
251*219b2ee8SDavid du Colombier * Reads the next four bytes into an integer and returns the value to the caller.
252*219b2ee8SDavid du Colombier * First two bytes are probably always 0.
253*219b2ee8SDavid du Colombier *
254*219b2ee8SDavid du Colombier */
255*219b2ee8SDavid du Colombier
256*219b2ee8SDavid du Colombier val = getc(fp_in);
257*219b2ee8SDavid du Colombier val |= (getc(fp_in) << 8);
258*219b2ee8SDavid du Colombier val |= (getc(fp_in) << 16);
259*219b2ee8SDavid du Colombier val |= (getc(fp_in) << 24);
260*219b2ee8SDavid du Colombier
261*219b2ee8SDavid du Colombier return(val);
262*219b2ee8SDavid du Colombier
263*219b2ee8SDavid du Colombier } /* End of getint */
264*219b2ee8SDavid du Colombier
265*219b2ee8SDavid du Colombier /*****************************************************************************/
266*219b2ee8SDavid du Colombier
error(kind,mesg,a1,a2,a3)267*219b2ee8SDavid du Colombier error(kind, mesg, a1, a2, a3)
268*219b2ee8SDavid du Colombier
269*219b2ee8SDavid du Colombier int kind;
270*219b2ee8SDavid du Colombier char *mesg;
271*219b2ee8SDavid du Colombier unsigned a1, a2, a3;
272*219b2ee8SDavid du Colombier
273*219b2ee8SDavid du Colombier {
274*219b2ee8SDavid du Colombier
275*219b2ee8SDavid du Colombier /*
276*219b2ee8SDavid du Colombier *
277*219b2ee8SDavid du Colombier * Print mesg and quit if kind is FATAL.
278*219b2ee8SDavid du Colombier *
279*219b2ee8SDavid du Colombier */
280*219b2ee8SDavid du Colombier
281*219b2ee8SDavid du Colombier if ( mesg != NULL && *mesg != '\0' ) {
282*219b2ee8SDavid du Colombier fprintf(stderr, "%s: ", prog_name);
283*219b2ee8SDavid du Colombier fprintf(stderr, mesg, a1, a2, a3);
284*219b2ee8SDavid du Colombier putc('\n', stderr);
285*219b2ee8SDavid du Colombier } /* End if */
286*219b2ee8SDavid du Colombier
287*219b2ee8SDavid du Colombier if ( kind == FATAL && ignore == OFF )
288*219b2ee8SDavid du Colombier exit(x_stat | 01);
289*219b2ee8SDavid du Colombier
290*219b2ee8SDavid du Colombier } /* End of error */
291*219b2ee8SDavid du Colombier
292*219b2ee8SDavid du Colombier /*****************************************************************************/
293*219b2ee8SDavid du Colombier
294