|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T c
Length: 9041 (0x2351)
Types: TextFile
Names: »checkw.c«
└─⟦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«
#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));
}