xref: /plan9/sys/src/cmd/postscript/misc/macfont.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier /*
2*219b2ee8SDavid du Colombier  *
3*219b2ee8SDavid du Colombier  * Program that converts Macintosh font files to a format that works on Unix
4*219b2ee8SDavid du Colombier  * systems. Essentially all the information needed came from the Adobe paper
5*219b2ee8SDavid du Colombier  * "Supporting Downloadable PostScript Fonts". To use the program type,
6*219b2ee8SDavid du Colombier  *
7*219b2ee8SDavid du Colombier  *	macfont font.mac >font.unix
8*219b2ee8SDavid du Colombier  *
9*219b2ee8SDavid du Colombier  * where font.mac is the font file, exactly as it came over from a Macintosh,
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  * Macintosh 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  *
115*219b2ee8SDavid du Colombier  * Everything else is an input file. No arguments or '-' means stdin.
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 
145*219b2ee8SDavid du Colombier /*
146*219b2ee8SDavid du Colombier  *
147*219b2ee8SDavid du Colombier  * The first four bytes (in a block) are the block size, the fifth is the block
148*219b2ee8SDavid du Colombier  * type, and the sixth always appears to be NULL. Type 0 blocks are comments and
149*219b2ee8SDavid du Colombier  * are always skipped. Type 1 blocks are ASCII text, type 2 is binary data that
150*219b2ee8SDavid du Colombier  * should be converted to hex, while type 5 blocks represent the end of the font
151*219b2ee8SDavid du Colombier  * file. Commment block lengths appear to be from the first byte, while other
152*219b2ee8SDavid du Colombier  * lengths seem to be measured from block type byte (ie. the fifth byte). Type
153*219b2ee8SDavid du Colombier  * four blocks aren't used, while type 3 blocks mean an end of file indication
154*219b2ee8SDavid du Colombier  * should be sent to the printer. Haven't done anything with type 3 blocks.
155*219b2ee8SDavid du Colombier  *
156*219b2ee8SDavid du Colombier  */
157*219b2ee8SDavid du Colombier 
158*219b2ee8SDavid du Colombier     while ( 1 ) {
159*219b2ee8SDavid du Colombier 	blocksize = getint(fp_in);
160*219b2ee8SDavid du Colombier 	blocktype = getc(fp_in);
161*219b2ee8SDavid du Colombier 	getc(fp_in);
162*219b2ee8SDavid du Colombier 	if ( debug == ON )
163*219b2ee8SDavid du Colombier 	    fprintf(stderr, "blocktype = %d, blocksize = %d\n", blocktype, blocksize);
164*219b2ee8SDavid du Colombier 	switch ( blocktype ) {
165*219b2ee8SDavid du Colombier 	    case 0:			/* comment - skip blockcount bytes */
166*219b2ee8SDavid du Colombier 		fseek(fp_in, (long) blocksize - 6, 1);
167*219b2ee8SDavid du Colombier 		break;
168*219b2ee8SDavid du Colombier 
169*219b2ee8SDavid du Colombier 	    case 1:
170*219b2ee8SDavid du Colombier 		asciitext(blocksize - 2);
171*219b2ee8SDavid du Colombier 		break;
172*219b2ee8SDavid du Colombier 
173*219b2ee8SDavid du Colombier 	    case 2:
174*219b2ee8SDavid du Colombier 		hexdata(blocksize - 2);
175*219b2ee8SDavid du Colombier 		break;
176*219b2ee8SDavid du Colombier 
177*219b2ee8SDavid du Colombier 	    case 3:
178*219b2ee8SDavid du Colombier 	    case 4:
179*219b2ee8SDavid du Colombier 		error(FATAL, "resource type %d not implemented", blocktype);
180*219b2ee8SDavid du Colombier 		break;
181*219b2ee8SDavid du Colombier 
182*219b2ee8SDavid du Colombier 	    case 5:
183*219b2ee8SDavid du Colombier 		return;
184*219b2ee8SDavid du Colombier 
185*219b2ee8SDavid du Colombier 	    default:
186*219b2ee8SDavid du Colombier 		error(FATAL, "unknown resource type %d", blocktype);
187*219b2ee8SDavid du Colombier 	}   /* End switch */
188*219b2ee8SDavid du Colombier     }	/* End while */
189*219b2ee8SDavid du Colombier 
190*219b2ee8SDavid du Colombier }   /* End of conv */
191*219b2ee8SDavid du Colombier 
192*219b2ee8SDavid du Colombier /*****************************************************************************/
193*219b2ee8SDavid du Colombier 
asciitext(count)194*219b2ee8SDavid du Colombier asciitext(count)
195*219b2ee8SDavid du Colombier 
196*219b2ee8SDavid du Colombier     int		count;			/* bytes left in the block */
197*219b2ee8SDavid du Colombier 
198*219b2ee8SDavid du Colombier {
199*219b2ee8SDavid du Colombier 
200*219b2ee8SDavid du Colombier     int		ch;
201*219b2ee8SDavid du Colombier     int		i = 0;
202*219b2ee8SDavid du Colombier 
203*219b2ee8SDavid du Colombier /*
204*219b2ee8SDavid du Colombier  *
205*219b2ee8SDavid du Colombier  * Handles type 1 (ie. ASCII text) blocks. Changing carriage returns to newlines
206*219b2ee8SDavid du Colombier  * is all I've done.
207*219b2ee8SDavid du Colombier  *
208*219b2ee8SDavid du Colombier  */
209*219b2ee8SDavid du Colombier 
210*219b2ee8SDavid du Colombier     for ( i = 0; i < count; i++ ) {
211*219b2ee8SDavid du Colombier 	if ( (ch = getc(fp_in)) == '\r' )
212*219b2ee8SDavid du Colombier 	    ch = '\n';
213*219b2ee8SDavid du Colombier 	putc(ch, fp_out);
214*219b2ee8SDavid du Colombier     }	/* End for */
215*219b2ee8SDavid du Colombier 
216*219b2ee8SDavid du Colombier }   /* End of asciitext */
217*219b2ee8SDavid du Colombier 
218*219b2ee8SDavid du Colombier /*****************************************************************************/
219*219b2ee8SDavid du Colombier 
hexdata(count)220*219b2ee8SDavid du Colombier hexdata(count)
221*219b2ee8SDavid du Colombier 
222*219b2ee8SDavid du Colombier     int		count;			/* bytes left in the block */
223*219b2ee8SDavid du Colombier 
224*219b2ee8SDavid du Colombier {
225*219b2ee8SDavid du Colombier 
226*219b2ee8SDavid du Colombier     int		i;
227*219b2ee8SDavid du Colombier     int		n;
228*219b2ee8SDavid du Colombier 
229*219b2ee8SDavid du Colombier /*
230*219b2ee8SDavid du Colombier  *
231*219b2ee8SDavid du Colombier  * Reads the next count bytes and converts each byte to hex. Also starts a new
232*219b2ee8SDavid du Colombier  * line every 80 hex characters.
233*219b2ee8SDavid du Colombier  *
234*219b2ee8SDavid du Colombier  */
235*219b2ee8SDavid du Colombier 
236*219b2ee8SDavid du Colombier     for ( i = 0, n = 0; i < count; i++ ) {
237*219b2ee8SDavid du Colombier 	fprintf(fp_out, "%.2X", getc(fp_in));
238*219b2ee8SDavid du Colombier 	if ( (++n % 40) == 0 )
239*219b2ee8SDavid du Colombier 	    putc('\n', fp_out);
240*219b2ee8SDavid du Colombier     }	/* End for */
241*219b2ee8SDavid du Colombier 
242*219b2ee8SDavid du Colombier }   /* End of hexdata */
243*219b2ee8SDavid du Colombier 
244*219b2ee8SDavid du Colombier /*****************************************************************************/
245*219b2ee8SDavid du Colombier 
getint()246*219b2ee8SDavid du Colombier getint()
247*219b2ee8SDavid du Colombier 
248*219b2ee8SDavid du Colombier {
249*219b2ee8SDavid du Colombier 
250*219b2ee8SDavid du Colombier     int		val;
251*219b2ee8SDavid du Colombier     int		i;
252*219b2ee8SDavid du Colombier 
253*219b2ee8SDavid du Colombier /*
254*219b2ee8SDavid du Colombier  *
255*219b2ee8SDavid du Colombier  * Reads the next four bytes into an integer and returns the value to the caller.
256*219b2ee8SDavid du Colombier  * First two bytes are probably always 0.
257*219b2ee8SDavid du Colombier  *
258*219b2ee8SDavid du Colombier  */
259*219b2ee8SDavid du Colombier 
260*219b2ee8SDavid du Colombier     for ( i = 0, val = (getc(fp_in) & 0377); i < 3; i++ )
261*219b2ee8SDavid du Colombier 	val = (val << 8) | (getc(fp_in) & 0377);
262*219b2ee8SDavid du Colombier 
263*219b2ee8SDavid du Colombier     return(val);
264*219b2ee8SDavid du Colombier 
265*219b2ee8SDavid du Colombier }   /* End of getint */
266*219b2ee8SDavid du Colombier 
267*219b2ee8SDavid du Colombier /*****************************************************************************/
268*219b2ee8SDavid du Colombier 
error(kind,mesg,a1,a2,a3)269*219b2ee8SDavid du Colombier error(kind, mesg, a1, a2, a3)
270*219b2ee8SDavid du Colombier 
271*219b2ee8SDavid du Colombier 
272*219b2ee8SDavid du Colombier     int		kind;
273*219b2ee8SDavid du Colombier     char	*mesg;
274*219b2ee8SDavid du Colombier     unsigned	a1, a2, a3;
275*219b2ee8SDavid du Colombier 
276*219b2ee8SDavid du Colombier {
277*219b2ee8SDavid du Colombier 
278*219b2ee8SDavid du Colombier /*
279*219b2ee8SDavid du Colombier  *
280*219b2ee8SDavid du Colombier  * Print *mesg then quit if kind is FATAL.
281*219b2ee8SDavid du Colombier  *
282*219b2ee8SDavid du Colombier  */
283*219b2ee8SDavid du Colombier 
284*219b2ee8SDavid du Colombier     if ( mesg != NULL && *mesg != '\0' ) {
285*219b2ee8SDavid du Colombier 	fprintf(stderr, "%s: ", prog_name);
286*219b2ee8SDavid du Colombier 	fprintf(stderr, mesg, a1, a2, a3);
287*219b2ee8SDavid du Colombier 	putc('\n', stderr);
288*219b2ee8SDavid du Colombier     }	/* End if */
289*219b2ee8SDavid du Colombier 
290*219b2ee8SDavid du Colombier     if ( kind == FATAL && ignore == OFF )
291*219b2ee8SDavid du Colombier 	exit(x_stat | 01);
292*219b2ee8SDavid du Colombier 
293*219b2ee8SDavid du Colombier }   /* End of error */
294*219b2ee8SDavid du Colombier 
295*219b2ee8SDavid du Colombier /*****************************************************************************/
296*219b2ee8SDavid du Colombier 
297