DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T c

⟦c6115752c⟧ TextFile

    Length: 9041 (0x2351)
    Types: TextFile
    Names: »checkw.c«

Derivation

└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
    └─⟦this⟧ »./DVIware/laser-setters/umd-dvi/misc/checkw.c« 
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« 
        └─⟦ca79c7339⟧ 
            └─⟦this⟧ »DVIware/laser-setters/mctex/misc/mf79/checkw.c« 

TextFile

#ifndef lint
static char rcsid[] = "$Header$";
#endif

/*
 * checkw -- check & fix the TFM widths in a PXL file
 *
 * Usage: checkw [-f] [-s] tfmfile pxlfile
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "../h/types.h"
#include "../h/fio.h"

char *ProgName;

struct tfmheader {
    int th_lf;			/* length of the file (words) */
    int th_lh;			/* length of the header data (words) */
    int th_bc;			/* smallest char code in font */
    int th_ec;			/* largest char code in font (inclusive) */
    int th_nw;			/* number of words in width table */
    int th_nh;			/* number of words in height table */
    int th_nd;			/* number of words in depth table */
    int th_ni;			/* number of words in ital. corr. table */
    int th_nl;			/* number of words in lig/kern table */
    int th_nk;			/* number of words in kern table */
    int th_ne;			/* number of words in extensible char table */
    int th_np;			/* number of font param words */
};

/*
 * The rest of the TFM file is composed of the following information,
 * all of which are 32 bit quantities:
 *
 * header:	array [0..lh-1] of stuff
 * char_info:	array [bc..ec] of char_info_word
 * width:	array [0..nw-1] of fix_word
 * height:	array [0..nh-1] of fix_word
 * depth:	array [0..nd-1] of fix_word
 * italic:	array [0..ni-1] of fix_word
 * lig_kern:	array [0..nl-1] of lig_kern_command
 * kern:	array [0..nk-1] of fix_word
 * exten:	array [0..ne-1] of extensible_recipie
 * param:	array [1..np] of fix_word
 *
 * We are interested only in the width information.  This can be
 * found by taking the first byte of each of the char_info_words
 * and using it as an index in the width table.  That is, the
 * width of character $n$ is width[char_info[$n$-$bc$].width_index].
 */

struct char_info_word {
    char width_index;
    char height_and_depth_index;
    char italic_index_and_tag;
    char remainder;
};

/*
 * A PXL file ends with 2068 bytes of information which includes the
 * TFM widths and some other stuff (some of which we don't need, some
 * of which we do; it's easiest to just read it all).
 */
#define PXBUFSIZE	2068

#define	PXL_ID		1001

#define PXIDOFF		2064		/* PXL_ID found here */
#define PXTFMOFF(n)	(((n) << 4) + 12)/* TFM width of char $n$ here */

int    FFlag;			/* -f => fix */
int    SFlag;			/* -s => silent */
int    QFlag;			/* -q => quiet (like -s if match) */
char  *tfname;			/* name of the TFM file */
FILE  *tf;			/* the TFM file */
char  *pxname;			/* name of the PXL file */
int    px;			/* we don't use stdio on the pxl file */
char   pxbuf[PXBUFSIZE];	/* the tail of the PXL file */
long   pxtailoff;		/* tells where pxbuf goes */
struct tfmheader th;		/* the TFM file's header information */
i32   *width;			/* the TFM width tables */
struct char_info_word *char_info;/* the TFM character info tables */

#define WIDTH(c) width[char_info[(c) - th.th_bc].width_index]

extern char *optarg;
extern int   optind;
extern int   errno;

char *malloc ();
long  lseek ();

/*
 * Exit stati.
 */
#define EX_OK		0	/* all is well in fontland */
#define EX_NOMATCH	1	/* didn't match, didn't update PXL file */
#define EX_OTHER	2	/* other error (invalid command, etc.) */

main (argc, argv)
register int argc;
register char **argv; {
    register int c;

    ProgName = argv[0];
    while ((c = getopt (argc, argv, "fqs")) != EOF) {
	switch (c) {
	    case 'f':
		FFlag++;
		break;
	    case 'q':
		QFlag++;
		break;
	    case 's':
		SFlag++;
		break;
	    case '?':
usage:
		error (EX_OTHER, 0, "usage: %s [-f] [-s] tfmfile pxlfile",
			ProgName);
		/*NOTREACHED*/
	}
    }
    if (argc - optind != 2)
	goto usage;
    tfname = argv[optind];
    pxname = argv[optind + 1];
    if ((tf = fopen (tfname, "r")) == NULL)
	error (EX_OTHER, errno, "can't open %s for reading", tfname);
    if ((px = open (pxname, FFlag ? 2 : 0)) < 0)
	error (EX_OTHER, errno, "can't open %s for %s", pxname,
		FFlag ? "update" : "reading");
    ReadPXLTail ();
    ReadTFMHeader ();
    if (th.th_ec < th.th_bc)
	error (EX_OTHER, 0, "\
Are you sure %s is a TFM file?  It contains no characters!", tfname);
    if (th.th_bc < 0 || th.th_ec > 127)
	error (EX_OTHER, 0, "\
I don't see how %s can correspond to your PXL file.\n\
(It has a first character entry of %d, and a last of %d.)",
		tfname, th.th_bc, th.th_ec);
    AllocateCharTable (th.th_ec - th.th_bc + 1);
    AllocateWidthTable (th.th_nw);
    SkipHeader ();
    ReadCharInfo (th.th_ec - th.th_bc + 1);
    ReadWidthTable (th.th_nw);
    if (WidthsMatch ()) {
	if (!SFlag && !QFlag)
	    printf ("%s: width tables for %s match %s\n", ProgName,
		    pxname, tfname);
	exit (EX_OK);
    }
    if (!FFlag) {
	if (!SFlag)
	    printf ("%s: width tables for %s and %s do not match\n", ProgName,
		    pxname, tfname);
	exit (EX_NOMATCH);
    }
    if (!SFlag)
	printf ("%s: width tables for %s and %s do not match; updating...\n",
		ProgName, pxname, tfname);
    FixPXLTail ();
    WritePXLTail ();
    if (!SFlag)
	printf ("%s: width tables in %s updated.\n", ProgName, pxname);
    exit (EX_OK);
}

/*
 * Called if the TFM file seems to be bogus.
 */
BadTFMFile () {
    error (EX_OTHER, 0, "unexpected EOF -- are you sure %s is a TFM file?",
	    tfname);
 /* NOTREACHED */
}

/*
 * Allocate n character info table entries.
 */
AllocateCharTable (n)
register int n; {
    char_info = (struct char_info_word *)
	    malloc ((unsigned) n * sizeof *char_info);
    if (char_info == 0)
	error (EX_OTHER, errno, "unable to allocate %d char table entries", n);
}

/*
 * Allocate n width table entries.
 */
AllocateWidthTable (n)
register int n; {
    width = (i32 *) malloc ((unsigned) n * sizeof *width);
    if (width == 0)
	error (EX_OTHER, errno,
		"unable to allocate %d width table entries", n);
}

/*
 * Read the TFM header.
 */
ReadTFMHeader () {
    register int *ip, i;

    for (ip = &th.th_lf; ip <= &th.th_np;) {
	i = UnSign16 (GetWord (tf));
	*ip++ = i;		/* ``cheating'' */
    }
 /* We could do something nice like make sure the actual file size and the
    reported size (tf.tf_lf * 4?) are the same... naaah. */
}

/*
 * Skip over the miscellaneous header info in the TFM file.
 */
SkipHeader () {
    (void) fseek (tf, (long) th.th_lh * sizeof (i32), 1);
}

/*
 * Read the character info table from the TFM file.  (We get all
 * of it, even though we're only going to use the width index.)
 */
ReadCharInfo (n)
register int n; {
    register struct char_info_word *ci;

    for (ci = char_info; --n >= 0; ci++) {
	ci -> width_index = getc (tf);
	ci -> height_and_depth_index = getc (tf);
	ci -> italic_index_and_tag = getc (tf);
	ci -> remainder = getc (tf);
    }
    if (feof (tf))
	BadTFMFile ();
}

/*
 * Read the width table from the TFM file.
 */
ReadWidthTable (n)
register int n; {
    register i32 *ip;

    for (ip = width; --n >= 0; ip++)
	fGetLong (tf, *ip);

    if (feof (tf))
	BadTFMFile ();
}

/*
 * Get a 32 bit quantity from the specified offset in the pxl buffer.
 */
i32
GetPXLong (off) {
    register char *p = pxbuf + off;
    register i32 rv;

    rv = UnSign8 (*p++) << 24;
    rv |= UnSign8 (*p++) << 16;
    rv |= UnSign8 (*p++) << 8;
    rv |= UnSign8 (*p);
    return rv;
}

/*
 * Put the specified value in the pxl buffer at the given offset.
 * N.B.: assuming 8 bit bytes (since val >> n might be signed).
 */
PutPXLong (off, val)
int off;
register i32 val; {
    register char *p = pxbuf + off;

    *p++ = val >> 24;
    *p++ = val >> 16;
    *p++ = val >> 8;
    *p = val;
}

/*
 * Read (and verify) the end part of the pxl file.
 */
ReadPXLTail () {
    struct stat st;

    if (fstat (px, &st))
	error (EX_OTHER, errno, "fstat(%s)", px, pxname);
    if (st.st_size & 3 || st.st_size < PXBUFSIZE)
	error (EX_OTHER, 0, "%s doesn't seem to be a pxl file", pxname);
    pxtailoff = st.st_size - PXBUFSIZE;
    if (lseek (px, pxtailoff, 0) != pxtailoff)
	error (EX_OTHER, errno, "lseek(%s) didn't return %ld", pxname,
		pxtailoff);
    if (read (px, pxbuf, PXBUFSIZE) != PXBUFSIZE)
	error (EX_OTHER, errno, "read(%s)", pxname);
    if (GetPXLong (PXIDOFF) != PXL_ID)
	error (EX_OTHER, 0, "%s doesn't seem to be a PXL file.",
		pxname);
}

/*
 * Write the end part of the PXL file back to the original PXL file.
 */
WritePXLTail () {
    if (lseek (px, pxtailoff, 0) != pxtailoff)
	error (EX_OTHER, errno, "lseek(%s) didn't return %ld", pxname,
		pxtailoff);
    if (write (px, pxbuf, PXBUFSIZE) != PXBUFSIZE)
	error (EX_OTHER, errno, "write(%s) failed---pxl file may be damaged",
		pxname);
}

/*
 * Compare the width values in the PXL tail buffer with those in the
 * TFM width tables.  Return 1 iff they all match.
 */
WidthsMatch () {
    register int i;

    for (i = th.th_bc; i <= th.th_ec; i++)
	if (GetPXLong (PXTFMOFF (i)) != WIDTH (i))
	    return 0;		/* a mismatch */
 /* perhaps we should make sure the rest are 0... oh well */
    return 1;
}

/*
 * Fix the width values in the PXL file tail buffer.
 */
FixPXLTail () {
    register int i;

    for (i = th.th_bc; i <= th.th_ec; i++)
	PutPXLong (PXTFMOFF (i), WIDTH (i));
}