1 /* 2 * 3 * Program that converts Macintosh font files to a format that works on Unix 4 * systems. Essentially all the information needed came from the Adobe paper 5 * "Supporting Downloadable PostScript Fonts". To use the program type, 6 * 7 * macfont font.mac >font.unix 8 * 9 * where font.mac is the font file, exactly as it came over from a Macintosh, 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 * Macintosh 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 * 115 * Everything else is an input file. No arguments or '-' means stdin. 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 145 /* 146 * 147 * The first four bytes (in a block) are the block size, the fifth is the block 148 * type, and the sixth always appears to be NULL. Type 0 blocks are comments and 149 * are always skipped. Type 1 blocks are ASCII text, type 2 is binary data that 150 * should be converted to hex, while type 5 blocks represent the end of the font 151 * file. Commment block lengths appear to be from the first byte, while other 152 * lengths seem to be measured from block type byte (ie. the fifth byte). Type 153 * four blocks aren't used, while type 3 blocks mean an end of file indication 154 * should be sent to the printer. Haven't done anything with type 3 blocks. 155 * 156 */ 157 158 while ( 1 ) { 159 blocksize = getint(fp_in); 160 blocktype = getc(fp_in); 161 getc(fp_in); 162 if ( debug == ON ) 163 fprintf(stderr, "blocktype = %d, blocksize = %d\n", blocktype, blocksize); 164 switch ( blocktype ) { 165 case 0: /* comment - skip blockcount bytes */ 166 fseek(fp_in, (long) blocksize - 6, 1); 167 break; 168 169 case 1: 170 asciitext(blocksize - 2); 171 break; 172 173 case 2: 174 hexdata(blocksize - 2); 175 break; 176 177 case 3: 178 case 4: 179 error(FATAL, "resource type %d not implemented", blocktype); 180 break; 181 182 case 5: 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 int i; 252 253 /* 254 * 255 * Reads the next four bytes into an integer and returns the value to the caller. 256 * First two bytes are probably always 0. 257 * 258 */ 259 260 for ( i = 0, val = (getc(fp_in) & 0377); i < 3; i++ ) 261 val = (val << 8) | (getc(fp_in) & 0377); 262 263 return(val); 264 265 } /* End of getint */ 266 267 /*****************************************************************************/ 268 269 error(kind, mesg, a1, a2, a3) 270 271 272 int kind; 273 char *mesg; 274 unsigned a1, a2, a3; 275 276 { 277 278 /* 279 * 280 * Print *mesg then 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 /*****************************************************************************/ 296 297