plan9port

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

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