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