plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

macfont.c (5672B)


      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;
     36 FILE	*fp_out;
     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     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  *
    118  * Everything else is an input file. No arguments or '-' means stdin.
    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 
    148 /*
    149  *
    150  * The first four bytes (in a block) are the block size, the fifth is the block
    151  * type, and the sixth always appears to be NULL. Type 0 blocks are comments and
    152  * are always skipped. Type 1 blocks are ASCII text, type 2 is binary data that
    153  * should be converted to hex, while type 5 blocks represent the end of the font
    154  * file. Commment block lengths appear to be from the first byte, while other
    155  * lengths seem to be measured from block type byte (ie. the fifth byte). Type
    156  * four blocks aren't used, while type 3 blocks mean an end of file indication
    157  * should be sent to the printer. Haven't done anything with type 3 blocks.
    158  *
    159  */
    160 
    161     while ( 1 ) {
    162 	blocksize = getint(fp_in);
    163 	blocktype = getc(fp_in);
    164 	getc(fp_in);
    165 	if ( debug == ON )
    166 	    fprintf(stderr, "blocktype = %d, blocksize = %d\n", blocktype, blocksize);
    167 	switch ( blocktype ) {
    168 	    case 0:			/* comment - skip blockcount bytes */
    169 		fseek(fp_in, (long) blocksize - 6, 1);
    170 		break;
    171 
    172 	    case 1:
    173 		asciitext(blocksize - 2);
    174 		break;
    175 
    176 	    case 2:
    177 		hexdata(blocksize - 2);
    178 		break;
    179 
    180 	    case 3:
    181 	    case 4:
    182 		error(FATAL, "resource type %d not implemented", blocktype);
    183 		break;
    184 
    185 	    case 5:
    186 		return;
    187 
    188 	    default:
    189 		error(FATAL, "unknown resource type %d", blocktype);
    190 	}   /* End switch */
    191     }	/* End while */
    192 
    193 }   /* End of conv */
    194 
    195 /*****************************************************************************/
    196 
    197 asciitext(count)
    198 
    199     int		count;			/* bytes left in the block */
    200 
    201 {
    202 
    203     int		ch;
    204     int		i = 0;
    205 
    206 /*
    207  *
    208  * Handles type 1 (ie. ASCII text) blocks. Changing carriage returns to newlines
    209  * is all I've done.
    210  *
    211  */
    212 
    213     for ( i = 0; i < count; i++ ) {
    214 	if ( (ch = getc(fp_in)) == '\r' )
    215 	    ch = '\n';
    216 	putc(ch, fp_out);
    217     }	/* End for */
    218 
    219 }   /* End of asciitext */
    220 
    221 /*****************************************************************************/
    222 
    223 hexdata(count)
    224 
    225     int		count;			/* bytes left in the block */
    226 
    227 {
    228 
    229     int		i;
    230     int		n;
    231 
    232 /*
    233  *
    234  * Reads the next count bytes and converts each byte to hex. Also starts a new
    235  * line every 80 hex characters.
    236  *
    237  */
    238 
    239     for ( i = 0, n = 0; i < count; i++ ) {
    240 	fprintf(fp_out, "%.2X", getc(fp_in));
    241 	if ( (++n % 40) == 0 )
    242 	    putc('\n', fp_out);
    243     }	/* End for */
    244 
    245 }   /* End of hexdata */
    246 
    247 /*****************************************************************************/
    248 
    249 getint()
    250 
    251 {
    252 
    253     int		val;
    254     int		i;
    255 
    256 /*
    257  *
    258  * Reads the next four bytes into an integer and returns the value to the caller.
    259  * First two bytes are probably always 0.
    260  *
    261  */
    262 
    263     for ( i = 0, val = (getc(fp_in) & 0377); i < 3; i++ )
    264 	val = (val << 8) | (getc(fp_in) & 0377);
    265 
    266     return(val);
    267 
    268 }   /* End of getint */
    269 
    270 /*****************************************************************************/
    271 
    272 error(kind, mesg, a1, a2, a3)
    273 
    274 
    275     int		kind;
    276     char	*mesg;
    277     unsigned	a1, a2, a3;
    278 
    279 {
    280 
    281 /*
    282  *
    283  * Print *mesg then quit if kind is FATAL.
    284  *
    285  */
    286 
    287     if ( mesg != NULL && *mesg != '\0' ) {
    288 	fprintf(stderr, "%s: ", prog_name);
    289 	fprintf(stderr, mesg, a1, a2, a3);
    290 	putc('\n', stderr);
    291     }	/* End if */
    292 
    293     if ( kind == FATAL && ignore == OFF )
    294 	exit(x_stat | 01);
    295 
    296 }   /* End of error */
    297 
    298 /*****************************************************************************/