302 lines · 5.6 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * * Program that converts IBM font files to a format that works on Unix systems. * Essentially all the information needed came from the Adobe paper "Supporting * Downloadable PostScript Fonts". To use the program type, * *	ibmfont font.ibm >font.unix * * where font.ibm is the font file, exactly as it came over from an IBM PC, * and font.unix is equivalent host resident font file usable on Unix systems. *  */ #include <stdio.h>#include <signal.h> #define OFF		0#define ON		1 #define NON_FATAL	0#define FATAL		1 #define FALSE		0#define TRUE		1 char	**argv;int	argc; char	*prog_name; int	x_stat;int	debug = OFF;int	ignore = OFF; FILE	*fp_in = stdin;FILE	*fp_out = stdout; /*****************************************************************************/ main(agc, agv)     int		agc;    char	*agv[]; { /* * * IBM PC to Unix font converter. * */     argc = agc;    argv = agv;    prog_name = argv[0];     options();    arguments();    exit(x_stat); }   /* End of main */ /*****************************************************************************/ options() {     int		ch;    char	*names = "DI";     extern char	*optarg;    extern int	optind; /* * * Command line options. * */     while ( (ch = getopt(argc, argv, names)) != EOF ) {	switch ( ch ) {	    case 'D':			/* debug flag */		    debug = ON;		    break; 	    case 'I':			/* ignore FATAL errors */		    ignore = ON;		    break; 	    case '?':			/* don't understand the option */		    error(FATAL, "");		    break; 	    default:			/* don't know what to do for ch */		    error(FATAL, "missing case for option %c\n", ch);		    break;	}   /* End switch */    }   /* End while */     argc -= optind;    argv += optind; }   /* End of options */ /*****************************************************************************/ arguments() { /* * * Everything esle is an input file. No arguments or '-' means stdin. * */      if ( argc < 1 )	conv();    else	while ( argc > 0 ) {	    if ( strcmp(*argv, "-") == 0 )		fp_in = stdin;	    else if ( (fp_in = fopen(*argv, "r")) == NULL )		error(FATAL, "can't open %s", *argv);	    conv();	    if ( fp_in != stdin )		fclose(fp_in);	    argc--;	    argv++;	}   /* End while */ }   /* End of arguments */ /*****************************************************************************/ conv() {     int		blocksize;    int		blocktype;    int		seg;    long	ftell(); /* * * Font files on the IBM PC are stored in a compressed binary format. Individual * segments in the file are preceeded by a header that looks like, * *		Byte 1:		128 *		Byte 2:		segment type (1=ASCII, 2=TOHEX, or 3=EOF) *		Bytes 3-6:	length of the segment *		Bytes 7 ...	data * */     while ( 1 ) {	seg = ftell(fp_in);	if ( getc(fp_in) != 128 )	    error(FATAL, "bad file format");	blocktype = getc(fp_in);	blocksize = getint(fp_in);	if ( debug == ON ) {	    fprintf(stderr, "blocktype = %d, blocksize = %d\n", blocktype, blocksize);	    fprintf(stderr, "start=0%o, end=0%o\n", seg, seg+blocksize+6);	    fprintf(stderr, "start=%d, end=%d\n", seg, seg+blocksize+6);	}   /* End if */	switch ( blocktype ) {	    case 1:		asciitext(blocksize);		break; 	    case 2:		hexdata(blocksize);		break; 	    case 3:		return; 	    default:		error(FATAL, "unknown resource type %d", blocktype);	}   /* End switch */    }	/* End while */ }   /* End of conv */ /*****************************************************************************/ asciitext(count)     int		count;			/* bytes left in the block */ {     int		ch;    int		i = 0; /* * * Handles type 1 (ie. ASCII text) blocks. Changing carriage returns to newlines * is all I've done. * */     for ( i = 0; i < count; i++ ) {	if ( (ch = getc(fp_in)) == '\r' )	    ch = '\n';	putc(ch, fp_out);    }	/* End for */	}   /* End of asciitext */ /*****************************************************************************/ hexdata(count)     int		count;			/* bytes left in the block */ {     int		i;    int		n; /* * * Reads the next count bytes and converts each byte to hex. Also starts a new * line every 80 hex characters. * */     for ( i = 0, n = 0; i < count; i++ ) {	fprintf(fp_out, "%.2X", getc(fp_in));	if ( (++n % 40) == 0 )	    putc('\n', fp_out);    }	/* End for */	}   /* End of hexdata */ /*****************************************************************************/ getint() {     int		val; /* * * Reads the next four bytes into an integer and returns the value to the caller. * First two bytes are probably always 0. * */     val = getc(fp_in);    val |= (getc(fp_in) << 8);    val |= (getc(fp_in) << 16);    val |= (getc(fp_in) << 24);     return(val); }   /* End of getint */  /*****************************************************************************/ error(kind, mesg, a1, a2, a3)     int		kind;    char	*mesg;    unsigned	a1, a2, a3; { /* * * Print mesg and quit if kind is FATAL. * */     if ( mesg != NULL && *mesg != '\0' ) {	fprintf(stderr, "%s: ", prog_name);	fprintf(stderr, mesg, a1, a2, a3);	putc('\n', stderr);    }	/* End if */     if ( kind == FATAL && ignore == OFF )	exit(x_stat | 01); }   /* End of error */ /*****************************************************************************/