Blob


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 */
14 #include <stdio.h>
15 #include <signal.h>
17 #define OFF 0
18 #define ON 1
20 #define NON_FATAL 0
21 #define FATAL 1
23 #define FALSE 0
24 #define TRUE 1
26 char **argv;
27 int argc;
29 char *prog_name;
31 int x_stat;
32 int debug = OFF;
33 int ignore = OFF;
35 FILE *fp_in;
36 FILE *fp_out;
38 /*****************************************************************************/
40 main(agc, agv)
42 int agc;
43 char *agv[];
45 {
47 /*
48 *
49 * IBM PC to Unix font converter.
50 *
51 */
53 argc = agc;
54 argv = agv;
55 prog_name = argv[0];
57 fp_in = stdin;
58 fp_out = stdout;
60 options();
61 arguments();
62 exit(x_stat);
64 } /* End of main */
66 /*****************************************************************************/
68 options()
70 {
72 int ch;
73 char *names = "DI";
75 extern char *optarg;
76 extern int optind;
78 /*
79 *
80 * Command line options.
81 *
82 */
84 while ( (ch = getopt(argc, argv, names)) != EOF ) {
85 switch ( ch ) {
86 case 'D': /* debug flag */
87 debug = ON;
88 break;
90 case 'I': /* ignore FATAL errors */
91 ignore = ON;
92 break;
94 case '?': /* don't understand the option */
95 error(FATAL, "");
96 break;
98 default: /* don't know what to do for ch */
99 error(FATAL, "missing case for option %c\n", ch);
100 break;
101 } /* End switch */
102 } /* End while */
104 argc -= optind;
105 argv += optind;
107 } /* End of options */
109 /*****************************************************************************/
111 arguments()
115 /*
117 * Everything esle is an input file. No arguments or '-' means stdin.
119 */
122 if ( argc < 1 )
123 conv();
124 else
125 while ( argc > 0 ) {
126 if ( strcmp(*argv, "-") == 0 )
127 fp_in = stdin;
128 else if ( (fp_in = fopen(*argv, "r")) == NULL )
129 error(FATAL, "can't open %s", *argv);
130 conv();
131 if ( fp_in != stdin )
132 fclose(fp_in);
133 argc--;
134 argv++;
135 } /* End while */
137 } /* End of arguments */
139 /*****************************************************************************/
141 conv()
145 int blocksize;
146 int blocktype;
147 int seg;
148 long ftell();
150 /*
152 * Font files on the IBM PC are stored in a compressed binary format. Individual
153 * segments in the file are preceeded by a header that looks like,
155 * Byte 1: 128
156 * Byte 2: segment type (1=ASCII, 2=TOHEX, or 3=EOF)
157 * Bytes 3-6: length of the segment
158 * Bytes 7 ... data
160 */
162 while ( 1 ) {
163 seg = ftell(fp_in);
164 if ( getc(fp_in) != 128 )
165 error(FATAL, "bad file format");
166 blocktype = getc(fp_in);
167 blocksize = getint(fp_in);
168 if ( debug == ON ) {
169 fprintf(stderr, "blocktype = %d, blocksize = %d\n", blocktype, blocksize);
170 fprintf(stderr, "start=0%o, end=0%o\n", seg, seg+blocksize+6);
171 fprintf(stderr, "start=%d, end=%d\n", seg, seg+blocksize+6);
172 } /* End if */
173 switch ( blocktype ) {
174 case 1:
175 asciitext(blocksize);
176 break;
178 case 2:
179 hexdata(blocksize);
180 break;
182 case 3:
183 return;
185 default:
186 error(FATAL, "unknown resource type %d", blocktype);
187 } /* End switch */
188 } /* End while */
190 } /* End of conv */
192 /*****************************************************************************/
194 asciitext(count)
196 int count; /* bytes left in the block */
200 int ch;
201 int i = 0;
203 /*
205 * Handles type 1 (ie. ASCII text) blocks. Changing carriage returns to newlines
206 * is all I've done.
208 */
210 for ( i = 0; i < count; i++ ) {
211 if ( (ch = getc(fp_in)) == '\r' )
212 ch = '\n';
213 putc(ch, fp_out);
214 } /* End for */
216 } /* End of asciitext */
218 /*****************************************************************************/
220 hexdata(count)
222 int count; /* bytes left in the block */
226 int i;
227 int n;
229 /*
231 * Reads the next count bytes and converts each byte to hex. Also starts a new
232 * line every 80 hex characters.
234 */
236 for ( i = 0, n = 0; i < count; i++ ) {
237 fprintf(fp_out, "%.2X", getc(fp_in));
238 if ( (++n % 40) == 0 )
239 putc('\n', fp_out);
240 } /* End for */
242 } /* End of hexdata */
244 /*****************************************************************************/
246 getint()
250 int val;
252 /*
254 * Reads the next four bytes into an integer and returns the value to the caller.
255 * First two bytes are probably always 0.
257 */
259 val = getc(fp_in);
260 val |= (getc(fp_in) << 8);
261 val |= (getc(fp_in) << 16);
262 val |= (getc(fp_in) << 24);
264 return(val);
266 } /* End of getint */
268 /*****************************************************************************/
270 error(kind, mesg, a1, a2, a3)
272 int kind;
273 char *mesg;
274 unsigned a1, a2, a3;
278 /*
280 * Print mesg and quit if kind is FATAL.
282 */
284 if ( mesg != NULL && *mesg != '\0' ) {
285 fprintf(stderr, "%s: ", prog_name);
286 fprintf(stderr, mesg, a1, a2, a3);
287 putc('\n', stderr);
288 } /* End if */
290 if ( kind == FATAL && ignore == OFF )
291 exit(x_stat | 01);
293 } /* End of error */
295 /*****************************************************************************/