xref: /plan9/sys/src/cmd/postscript/misc/ibmfont.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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