ibmfont.c (5358B)
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; 36 FILE *fp_out; 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 fp_in = stdin; 58 fp_out = stdout; 59 60 options(); 61 arguments(); 62 exit(x_stat); 63 64 } /* End of main */ 65 66 /*****************************************************************************/ 67 68 options() 69 70 { 71 72 int ch; 73 char *names = "DI"; 74 75 extern char *optarg; 76 extern int optind; 77 78 /* 79 * 80 * Command line options. 81 * 82 */ 83 84 while ( (ch = getopt(argc, argv, names)) != EOF ) { 85 switch ( ch ) { 86 case 'D': /* debug flag */ 87 debug = ON; 88 break; 89 90 case 'I': /* ignore FATAL errors */ 91 ignore = ON; 92 break; 93 94 case '?': /* don't understand the option */ 95 error(FATAL, ""); 96 break; 97 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 */ 103 104 argc -= optind; 105 argv += optind; 106 107 } /* End of options */ 108 109 /*****************************************************************************/ 110 111 arguments() 112 113 { 114 115 /* 116 * 117 * Everything esle is an input file. No arguments or '-' means stdin. 118 * 119 */ 120 121 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 */ 136 137 } /* End of arguments */ 138 139 /*****************************************************************************/ 140 141 conv() 142 143 { 144 145 int blocksize; 146 int blocktype; 147 int seg; 148 long ftell(); 149 150 /* 151 * 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, 154 * 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 159 * 160 */ 161 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; 177 178 case 2: 179 hexdata(blocksize); 180 break; 181 182 case 3: 183 return; 184 185 default: 186 error(FATAL, "unknown resource type %d", blocktype); 187 } /* End switch */ 188 } /* End while */ 189 190 } /* End of conv */ 191 192 /*****************************************************************************/ 193 194 asciitext(count) 195 196 int count; /* bytes left in the block */ 197 198 { 199 200 int ch; 201 int i = 0; 202 203 /* 204 * 205 * Handles type 1 (ie. ASCII text) blocks. Changing carriage returns to newlines 206 * is all I've done. 207 * 208 */ 209 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 */ 215 216 } /* End of asciitext */ 217 218 /*****************************************************************************/ 219 220 hexdata(count) 221 222 int count; /* bytes left in the block */ 223 224 { 225 226 int i; 227 int n; 228 229 /* 230 * 231 * Reads the next count bytes and converts each byte to hex. Also starts a new 232 * line every 80 hex characters. 233 * 234 */ 235 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 */ 241 242 } /* End of hexdata */ 243 244 /*****************************************************************************/ 245 246 getint() 247 248 { 249 250 int val; 251 252 /* 253 * 254 * Reads the next four bytes into an integer and returns the value to the caller. 255 * First two bytes are probably always 0. 256 * 257 */ 258 259 val = getc(fp_in); 260 val |= (getc(fp_in) << 8); 261 val |= (getc(fp_in) << 16); 262 val |= (getc(fp_in) << 24); 263 264 return(val); 265 266 } /* End of getint */ 267 268 /*****************************************************************************/ 269 270 error(kind, mesg, a1, a2, a3) 271 272 int kind; 273 char *mesg; 274 unsigned a1, a2, a3; 275 276 { 277 278 /* 279 * 280 * Print mesg and quit if kind is FATAL. 281 * 282 */ 283 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 */ 289 290 if ( kind == FATAL && ignore == OFF ) 291 exit(x_stat | 01); 292 293 } /* End of error */ 294 295 /*****************************************************************************/