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 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 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 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 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 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 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 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 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