Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!uunet!crdgw1!montnaro From: montnaro@sprite.crd.ge.com (Skip Montanaro) Newsgroups: alt.sources Subject: dviselect (Part 6 of 6) Message-ID:Date: 13 Nov 89 21:24:56 GMT Sender: news@crdgw1.crd.ge.com Reply-To: (Skip Montanaro) Organization: GE Corporate Research & Development, Schenectady, NY Lines: 1584 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh lib/Makefile <<'END_OF_lib/Makefile' X# X# Copyright (c) 1987 University of Maryland Department of Computer Science. X# All rights reserved. Permission to copy for any purpose is hereby granted X# so long as this copyright notice remains intact. X# X# Makefile for ctex/lib (C-TeX library routines) X# X# $Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/Makefile,v 1.6 89/02/13 14:31:29 grunwald Exp Locker: grunwald $ X# XDESTDIR= X# Alas, -R makes ALL initialised variables read-only, and we cannot X# use it on font files; hence, FCFLAGS. XCC=cc XCFLAGS= -O -I../h XFCFLAGS=-O -I../h X X# 4.1BSD Vax: X#ASSRC= bcopy.s bzero.s X#ASOBJ= bcopy.o bzero.o X#MISCC= getopt.c X#MISCO= getopt.o X X# 4.2BSD Vax: X#ASSRC= X#ASOBJ= X#MISCC= getopt.c X#MISCO= getopt.o X X# 4.2BSD Sun: X#ASSRC= X#ASOBJ= X#MISCC= X#MISCO= X X# 4.2BSD Pyramid: X#ASSRC= X#ASOBJ= X#MISCC= getopt.c X#MISCO= getopt.o X X# 4.3BSD Vax: XASSRC= XASOBJ= XMISCC= XMISCO= X# all XCSRC= conv.c dviclass.c error.c findpost.c fio.c font.c font_subr.c \ X gfclass.c gripes.c magfactor.c rotate.c scaletfm.c scanpost.c \ X search.c seek.c split.c strsave.c tfm.c ${MISCC} XCOBJ= conv.o dviclass.o error.o findpost.o fio.o font.o font_subr.o \ X gfclass.o gripes.o magfactor.o rotate.o scaletfm.o scanpost.o \ X search.o seek.o split.o strsave.o tfm.o ${MISCO} XFSRC= gffont.c pkfont.c pxlfont.c tfmfont.c XFOBJ= gffont.o pkfont.o pxlfont.o tfmfont.o X XOBJS= ${COBJ} ${ASOBJ} ${FOBJ} X Xall: lib.a X Xlib.a: ${OBJS} X ar cr lib.a ${OBJS} X ranlib lib.a X Xsrc: $(CSRC) $(FSRC) X @echo Done X X# no installation is necessary; this entry is just for standardisation Xinstall: X Xclean: X rm -f *.o lib.a X X#pxl.o: X# ${CC} ${CFLAGS} -c -DPXLPATH=\"${PXLPATH}\" pxl.c X X# font.o needs to know where to find the font description file Xfont.o: X ${CC} ${CFLAGS} -c -DFONTDESC=\"${FONTDESC}\" font.c X X# special rules for font objects X${FOBJ}: X ${CC} ${FCFLAGS} -c $*.c X X# DO NOT DELETE THIS LINE -- make depend uses it X# DEPENDENCIES MUST END AT END OF FILE X# IF YOU PUT STUFF HERE IT WILL GO AWAY X# see make depend above X# DO NOT DELETE THIS LINE -- make depend depends on it. X Xconv.o: ../h/types.h ../h/conv.h Xdviclass.o: ../h/dviclass.h Xerror.o: /usr/include/stdio.h /usr/include/varargs.h Xfindpost.o: /usr/include/stdio.h ../h/types.h ../h/dvicodes.h ../h/fio.h Xfio.o: /usr/include/stdio.h ../h/types.h ../h/fio.h Xfont.o: /usr/include/stdio.h /usr/include/errno.h /usr/include/sys/errno.h Xfont.o: ../h/types.h ../h/conv.h ../h/font.h Xfont_subr.o: ../h/font.h Xgetopt.o: /usr/include/stdio.h Xgfclass.o: ../h/gfclass.h Xgffont.o: /usr/include/stdio.h /usr/include/sys/types.h Xgffont.o: /usr/include/sys/stat.h ../h/types.h Xgffont.o: ../h/font.h ../h/gfcodes.h ../h/gfclass.h ../h/num.h Xgripes.o: /usr/include/stdio.h ../h/types.h Xpkfont.o: /usr/include/stdio.h /usr/include/sys/types.h Xpkfont.o: /usr/include/sys/stat.h ../h/types.h Xpkfont.o: ../h/font.h ../h/num.h Xpxlfont.o: /usr/include/stdio.h /usr/include/sys/types.h Xpxlfont.o: /usr/include/sys/stat.h Xpxlfont.o: /usr/include/errno.h /usr/include/sys/errno.h ../h/types.h Xpxlfont.o: ../h/font.h ../h/fio.h Xrotate.o: ../h/font.h Xscaletfm.o: ../h/types.h ../h/font.h Xscanpost.o: /usr/include/stdio.h ../h/types.h ../h/dvicodes.h ../h/fio.h Xscanpost.o: ../h/postamble.h Xsearch.o: ../h/types.h ../h/search.h Xseek.o: /usr/include/stdio.h /usr/include/sys/param.h Xseek.o: /usr/include/sys/signal.h Xseek.o: /usr/include/sys/types.h Xseek.o: /usr/include/sys/file.h Xseek.o: /usr/include/sys/stat.h Xsplit.o: /usr/include/ctype.h Xtfm.o: /usr/include/stdio.h ../h/types.h ../h/fio.h ../h/tfm.h Xtfmfont.o: /usr/include/stdio.h /usr/include/sys/types.h Xtfmfont.o: /usr/include/sys/stat.h ../h/types.h Xtfmfont.o: ../h/conv.h ../h/font.h ../h/tfm.h END_OF_lib/Makefile if test 3637 -ne `wc -c lib/rotate.c <<'END_OF_lib/rotate.c' X/* X * Copyright (c) 1987 University of Maryland Department of Computer Science. X * All rights reserved. Permission to copy for any purpose is hereby granted X * so long as this copyright notice remains intact. X */ X X#ifndef lint Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/rotate.c,v 1.4 89/02/13 14:31:18 grunwald Exp Locker: grunwald $"; X#endif X X/* X * Routines to generate rotated bitmaps given unrotated inputs. X * X * The rotated bitmap is indistinguishable from the unrotated one (aside X * from being rotated of course!). X */ X X#include "font.h" X Xextern int errno; X Xchar *malloc(); X Xstatic RotateClockwise(); X X/* X * Rounding, but by powers of two only. X */ X#define ROUND(n,r) (((n) + ((r) - 1)) & ~((r) - 1)) X X/* X * Set the rotation of glyph g to r. X */ XSetRotation(g, r) X register struct glyph *g; X int r; X{ X X if (r < ROT_NORM || r > ROT_RIGHT) X error(1, 0, "bad rotation value %d", r); X X /* X * The null glyph is trivial to rotate by any amount. X * X * Note that this assumes that any raster has been obtained X * BEFORE calling SetRotation()! X */ X if (g->g_raster == NULL) { X g->g_rotation = r; X return; X } X X /* X * This is hardly efficient, but it *is* expedient.... X */ X while (g->g_rotation != r) { X RotateClockwise(g); X g->g_rotation = (g->g_rotation - 1) & 3; X } X} X X/* X * Rotation by 1/4 turn clockwise (from ROT_NORM to ROT_RIGHT, e.g.). X */ Xstatic XRotateClockwise(glyph) X struct glyph *glyph; X{ X register char *nrast; /* new raster */ X register char *orast; /* old raster */ X register int oheight; /* old raster height, new raster width */ X register int owidth; /* old raster width, new raster height */ X unsigned int size; /* size of new raster (in bytes) */ X int nplus; /* offset between rows in nrast */ X X /* X * First, get a new raster. X */ X { X register struct glyph *g = glyph; X register int t; X X oheight = g->g_height; X owidth = g->g_width; X X /* X * Offset is (new width) rounded to bytes. X */ X nplus = ROUND(oheight, 8) >> 3; X X /* X * Size of new raster is (new height) * (new rounded width, X * in bytes). X */ X size = nplus * owidth; X if ((nrast = malloc(size)) == NULL) X error(1, errno, "out of memory"); X bzero(nrast, size); X X /* X * New y origin is old x origin; new x origin is old height X * minus old y origin - 1. X */ X t = g->g_yorigin; X g->g_yorigin = g->g_xorigin; X g->g_xorigin = oheight - t - 1; X X /* While we are at it, exchange height & width... */ X g->g_height = owidth; X g->g_width = oheight; X X /* and grab a pointer to the old raster. */ X orast = g->g_raster; X } X X /* X * Now copy bits from the old raster to the new one. The mapping X * function is X * X * for i in [0..height) X * for j in [0..width) X * new[j, height-i-1] = old[i, j] X * X * Thus i maps to height-i-1 and (since we have to do our own 2 X * dimensional array indexing) j to nplus*j. We call the mapped X * variables mapi and mapj, and, since we scan sequentially through X * the old raster, can discard the original i and j. X */ X { X register int mapj, c, k, mapi; X X mapi = oheight; X owidth *= nplus; X while (--mapi >= 0) { X k = 7; X for (mapj = 0; mapj < owidth; mapj += nplus) { X if (++k == 8) /* get another byte */ X c = *orast++, k = 0; X if (c & 0x80) /* old[i,j] was set */ X nrast[mapj + (mapi >> 3)] |= X 1 << (7 - (mapi & 7)); X c <<= 1; X } X } X } X X /* X * Finally, free the storage associated with the original raster. X */ X free(glyph->g_raster); glyph->g_raster = 0; X glyph->g_raster = nrast; X} END_OF_lib/rotate.c if test 3519 -ne `wc -c lib/scaletfm.c <<'END_OF_lib/scaletfm.c' X/* X * Copyright (c) 1987 University of Maryland Department of Computer Science. X * All rights reserved. Permission to copy for any purpose is hereby granted X * so long as this copyright notice remains intact. X */ X X#ifndef lint Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/scaletfm.c,v 1.3 89/02/13 14:31:19 grunwald Exp Locker: grunwald $"; X#endif X X#include "types.h" X#include "font.h" X X/* X * From DVITYPE.WEB: X * X * ``The most important part of in_TFM is the width computation, which X * involvles multiplying the relative widths in the TFM file by the scaling X * factor in the DVI file. This fixed-point multiplication must be done with X * precisely the same accuracy by all DVI-reading programs, in order to X * validate the assumptions made by DVI-writing programs like \TeX 82. X * X * Let us therefore summarize what needs to be done. Each width in a TFM X * file appears as a four-byte quantity called a fix_word. A fix_word whose X * respective bytes are (a,b,c,d) represents the number X * X * {{ b * 2^{-4} + c * 2^{-12} + d * 2^{-20}, if a = 0; X * x = {{ X * {{ -16 + b * 2^{-4} + c * 2^{-12} + d * 2^{-20}, if a = 255. X * X * (No other choices of a are allowed, since the magnitude of a TFM dimension X * must be less than 16.) We want to multiply this quantity by the integer X * z, which is known to be less than 2^{27}. Let \alpha = 16z. If z < X * 2^{23}, the individual multiplications b * z, c * z, d * z cannot X * overflow; otherwise we will divide z by 2, 4, 8, or 16, to obtain a X * multiplier less than 2^{23}, and we can compensate for this later. If z X * has thereby been replaced by z' = z/2^e, let \beta = 2^{4-e}; we shall X * compute X * X * \lfloor (b + c * 2^{-8} + d * 2^{-16})z' / \beta \rfloor X * X * if a = 0, or the same quantity minus \alpha if a = 255. This calculation X * must be done exactly, for the reasons stated above; the following program X * does the job in a system-independent way, assuming that arithmetic is X * exact on numbers less than 2^{31} in magnitude.'' X */ X X/* X * Scale the single TFM width t by z. X */ Xi32 XScaleOneWidth(t, z) X register i32 t, z; X{ X register i32 alpha, log2beta; X X /* First compute \alpha, \beta, and z': */ X alpha = 16 * z; X log2beta = 4; X while (z >= (1 << 23)) { X z >>= 1; X log2beta--; X } X X /* The four values 'a', 'b', 'c', and 'd' are fields within t: */ X#define a (UnSign8(t >> 24)) X#define b (UnSign8(t >> 16)) X#define c (UnSign8(t >> 8)) X#define d (UnSign8(t)) X if (t) { X t = (((((d * z) >> 8) + c * z) >> 8) + b * z) >> log2beta; X if (a) { X if (a != 255) X error(0, 0, "bad TFM width! [ScaleOneWidth]"); X t -= alpha; X } X } X return (t); X} X X/* X * Scale a set of glyphs [l..h) in font f according to f->f_dvimag. X */ XScaleGlyphs(f, l, h) X register struct font *f; X int l, h; X{ X register int i; X register i32 t, z, alpha, log2beta; X X z = f->f_dvimag; X alpha = 16 * z; X log2beta = 4; X while (z >= (1 << 23)) { X z >>= 1; X log2beta--; X } X X for (i = l; i < h; i++) { X if ((t = f->f_gly[i]->g_tfmwidth) == 0) X continue; X t = (((((d * z) >> 8) + c * z) >> 8) + b * z) >> log2beta; X if (a) { X if (a != 255) X error(0, 0, "\"%s\", glyph %d: bad TFM width", X f->f_path, i); X t -= alpha; X } X f->f_gly[i]->g_tfmwidth = t; X } X} END_OF_lib/scaletfm.c if test 3302 -ne `wc -c lib/scanpost.c <<'END_OF_lib/scanpost.c' X/* X * Copyright (c) 1987 University of Maryland Department of Computer Science. X * All rights reserved. Permission to copy for any purpose is hereby granted X * so long as this copyright notice remains intact. X */ X X#ifndef lint Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/scanpost.c,v 1.3 89/02/13 14:31:20 grunwald Exp Locker: grunwald $"; X#endif X X/* X * ScanPostAmble - read a DVI postamble. X */ X X#include X#include "types.h" X#include "dvicodes.h" X#include "fio.h" X#include "postamble.h" X XScanPostAmble(f, headerfunc, fontfunc) X register FILE *f; X int (*headerfunc)(); X register int (*fontfunc)(); X{ X register int n; X register char *s; X char name[512]; X X if (FindPostAmble(f)) { X GripeCannotFindPostamble(); X return(1); X } X if (GetByte(f) != Sign8(DVI_POST)) { X GripeMissingOp("POST"); X return(1); X } X X /* Read the postamble info stuff. */ X { X struct PostAmbleInfo pai; X register struct PostAmbleInfo *p = &pai; X X p->pai_PrevPagePointer = GetLong(f); X p->pai_Numerator = GetLong(f); X p->pai_Denominator = GetLong(f); X p->pai_DVIMag = GetLong(f); X p->pai_TallestPageHeight = GetLong(f); X p->pai_WidestPageWidth = GetLong(f); X p->pai_DVIStackSize = GetWord(f); X p->pai_NumberOfPages = GetWord(f); X X (*headerfunc)(p); X } X X /* Now read all the font definitions. */ X { X struct PostAmbleFont paf; X register struct PostAmbleFont *p = &paf; X X for (;;) { X switch (UnSign8(getc(f))) { X X case DVI_FNTDEF1: X p->paf_DVIFontIndex = UnSign8(getc(f)); X break; X X case DVI_FNTDEF2: X p->paf_DVIFontIndex = UnSign16(GetWord(f)); X break; X X case DVI_FNTDEF3: X p->paf_DVIFontIndex = UnSign24(Get3Byte(f)); X break; X X case DVI_FNTDEF4: X p->paf_DVIFontIndex = GetLong(f); X break; X X case DVI_POSTPOST: X return(0); X X default: X GripeMissingOp("POSTPOST"); X return(1); X /*NOTREACHED*/ X } X p->paf_DVIChecksum = GetLong(f); X p->paf_DVIMag = GetLong(f); X p->paf_DVIDesignSize = GetLong(f); X p->paf_n1 = UnSign8(getc(f)); X p->paf_n2 = UnSign8(getc(f)); X p->paf_name = name; /* never trust people not to X clobber it */ X n = p->paf_n1 + p->paf_n2; X s = name; X while (--n >= 0) X *s++ = GetByte(f); X *s = 0; X (*fontfunc)(p); X } X } X} END_OF_lib/scanpost.c if test 2244 -ne `wc -c lib/search.c <<'END_OF_lib/search.c' X/* X * Copyright (c) 1987 University of Maryland Department of Computer Science. X * All rights reserved. Permission to copy for any purpose is hereby granted X * so long as this copyright notice remains intact. X */ X X#ifndef lint Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/search.c,v 1.4 89/02/13 14:31:21 grunwald Exp Locker: grunwald $"; X#endif X X/* X * Key search routines (for a 32 bit key) X * X * SCreate initializes the search control area. X * X * SSearch returns the address of the data area (if found or created) X * or a null pointer (if not). The last argument controls the disposition X * in various cases, and is a ``value-result'' parameter. X * X * SEnumerate calls the given function on each data object within the X * search table. Note that no ordering is specified (though currently X * it runs in increasing-key-value sequence). X */ X X#include "types.h" X#include "search.h" X X#if vax || mc68000 || ns32000 || pyr X#define HARD_ALIGNMENT 4 X#else X#define HARD_ALIGNMENT 16 /* should suffice for most everyone */ X#endif X Xstatic int DOffset; /* part of alignment code */ X Xchar *malloc(), *realloc(); X Xstruct search * XSCreate(dsize) X register unsigned int dsize; X{ X register struct search *s; X X if ((s = (struct search *) malloc(sizeof *s)) == 0) X return (0); X X if (DOffset == 0) { X#ifndef HARD_ALIGNMENT X DOffset = sizeof(i32); X#else X DOffset = (sizeof(i32) + HARD_ALIGNMENT - 1) & X ~(HARD_ALIGNMENT - 1); X#endif X } X dsize += DOffset; /* tack on space for keys */ X X#ifdef HARD_ALIGNMENT X /* X * For machines with strict alignment constraints, it may be X * necessary to align the data at a multiple of some positive power X * of two. In general, it would suffice to make dsize a power of X * two, but this could be very space-wasteful, so instead we align it X * to HARD_ALIGNMENT. 64 bit machines might ``#define HARD_ALIGNMENT X * 8'', for example. N.B.: we assume that HARD_ALIGNMENT is a power X * of two. X */ X X dsize = (dsize + HARD_ALIGNMENT - 1) & ~(HARD_ALIGNMENT - 1); X#endif X X s->s_dsize = dsize; /* save data object size */ X s->s_space = 10; /* initially, room for 10 objects */ X s->s_n = 0; /* and none in the table */ X if ((s->s_data = malloc(s->s_space * dsize)) == 0) { X free((char *) s); (char *) s = 0; X return (0); X } X return (s); X} X X/* X * We actually use a binary search right now - this may change. X */ Xchar * XSSearch(s, key, disp) X register struct search *s; X register i32 key; X int *disp; X{ X register char *keyaddr; X int itemstomove; X X *disp &= S_CREATE | S_EXCL; /* clear return codes */ X if (s->s_n) { /* look for the key */ X register int h, l, m; X X h = s->s_n - 1; X l = 0; X while (l <= h) { X m = (l + h) >> 1; X keyaddr = s->s_data + m * s->s_dsize; X if (*(i32 *) keyaddr > key) X h = m - 1; X else if (*(i32 *) keyaddr < key) X l = m + 1; X else { /* found it, now what? */ X if (*disp & S_EXCL) { X *disp |= S_COLL; X return (0); /* collision */ X } X *disp |= S_FOUND; X return (keyaddr + DOffset); X } X } X keyaddr = s->s_data + l * s->s_dsize; X } else X keyaddr = s->s_data; X X /* keyaddr is now where the key should have been found, if anywhere */ X if ((*disp & S_CREATE) == 0) X return (0); /* not found */ X X /* avoid using realloc so as to retain old data if out of memory */ X if (s->s_space <= 0) { /* must expand; double it */ X register char *new; X X if ((new = malloc((s->s_n << 1) * s->s_dsize)) == 0) { X *disp |= S_ERROR; /* no space */ X return (0); X } X keyaddr = (keyaddr - s->s_data) + new; /* relocate */ X bcopy(s->s_data, new, s->s_n * s->s_dsize); X free(s->s_data); s->s_data = 0; X s->s_data = new; X s->s_space = s->s_n; X } X /* now move any keyed data that is beyond keyaddr down */ X itemstomove = s->s_n - (keyaddr - s->s_data) / s->s_dsize; X if (itemstomove) { X#ifndef USE_BCOPY /* often bcopy doesn't handle overlap */ X register char *from, *to; X X from = s->s_data + s->s_n * s->s_dsize; X to = from + s->s_dsize; X while (from > keyaddr) X *--to = *--from; X#else X bcopy(keyaddr + s->s_dsize, keyaddr + (s->s_dsize << 1), X itemstomove * s->s_dsize); X#endif X } X *disp |= S_NEW; X s->s_n++; X s->s_space--; X *(i32 *) keyaddr = key; X keyaddr += DOffset; /* now actually dataaddr */ X /* the bzero is just a frill... */ X bzero(keyaddr, s->s_dsize - DOffset); X return (keyaddr); X} X X/* X * Call function `f' for each element in the search table `s'. X */ XSEnumerate(s, f) X register struct search *s; X register int (*f)(); X{ X register int n; X register char *p; X X n = s->s_n; X p = s->s_data; X while (--n >= 0) { X (*f)(p + DOffset, *(i32 *) p); X p += s->s_dsize; X } X} END_OF_lib/search.c if test 4599 -ne `wc -c lib/seek.c <<'END_OF_lib/seek.c' X/* X * Copyright (c) 1987 University of Maryland Department of Computer Science. X * All rights reserved. Permission to copy for any purpose is hereby granted X * so long as this copyright notice remains intact. X */ X X#ifndef lint Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/seek.c,v 1.3 89/02/13 14:31:23 grunwald Exp Locker: grunwald $"; X#endif X X/* X * Seekable is a predicate which returns true iff a Unix fd is seekable. X * X * MakeSeekable forces an input stdio file to be seekable, by copying to X * a temporary file if necessary. X */ X X#include X#ifdef sys5 X#include X#include X#else X#include X#endif X#include X#include X Xlong lseek(); Xchar *getenv(); X Xint XSeekable(fd) X int fd; X{ X X return (lseek(fd, 0L, 1) >= 0 && !isatty(fd)); X} X X/* X * We use the despicable trick of unlinking an open temporary file. X * The alternatives are too painful. If it becomes necessary to X * do this another way, however, here is a method suggested by Fred X * Blonder: fork, and have the parent wait for the child to exit. X * (The parent must avoid being killed during this phase.) When X * the child exits, the parent should then remove the temporary file, X * then exit with the same status, or send itself the same signal. X */ Xint XMakeSeekable(f) X register FILE *f; X{ X register int tf, n; X int mypid, tries, blksize; X char *tmpdir; X#ifdef MAXBSIZE X char buf[MAXBSIZE]; X struct stat st; X#else X char buf[BUFSIZ]; X#endif X X if (Seekable(fileno(f))) X return (0); X X if ((tmpdir = getenv("TMPDIR")) == 0) X tmpdir = "/tmp"; X X /* compose a suitable temporary file name, and get an r/w descriptor */ X mypid = getpid(); X n = 0; X tries = 0; X do { X sprintf(buf, "%s/#%d.%d", tmpdir, mypid, n++); X (void) unlink(buf); X#ifdef O_CREAT /* have three-argument open syscall */ X tries++; X tf = open(buf, O_RDWR | O_CREAT | O_EXCL, 0666); X#else X if (access(buf, 0) == 0) { X /* X * Skip existing files. Note that tf might X * not be set yet. X */ X tf = -1; X continue; X } X tries++; X tf = creat(buf, 0666); X if (tf >= 0) { X (void) close(tf); X tf = open(buf, 2); X if (tf < 0) X (void) unlink(buf); X } X#endif X } while (tf < 0 && tries < 20); X if (tf < 0) /* probably unrecoverable user error */ X return (-1); X X (void) unlink(buf); X X /* copy from input file to temp file */ X#ifdef MAXBSIZE X if (fstat(tf, &st)) /* how can this ever fail? */ X blksize = MAXBSIZE; X else X blksize = MIN(MAXBSIZE, st.st_blksize); X#else X blksize = BUFSIZ; X#endif X while ((n = fread(buf, 1, blksize, f)) > 0) { X if (write(tf, buf, n) != n) { X (void) close(tf); X return (-1); X } X } X /* ferror() is broken in Ultrix 1.2; hence the && */ X if (ferror(f) && !feof(f)) { X (void) close(tf); X return (-1); X } X X /* X * Now switch f to point at the temp file. Since we hit EOF, there X * is nothing in f's stdio buffers, so we can play a dirty trick: X */ X clearerr(f); X if (dup2(tf, fileno(f))) { X (void) close(tf); X return (-1); X } X (void) close(tf); X return (0); X} END_OF_lib/seek.c if test 3044 -ne `wc -c lib/split.c <<'END_OF_lib/split.c' X/* X * Copyright (c) 1987 University of Maryland Department of Computer Science. X * All rights reserved. Permission to copy for any purpose is hereby granted X * so long as this copyright notice remains intact. X */ X X#ifndef lint Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/split.c,v 1.3 89/02/13 14:31:24 grunwald Exp Locker: grunwald $"; X#endif X X#include X X/* X * Split a line into an array of words. This is destructive of X * the original line; the word pointers point to places within X * that line. X * X * Return the number of words made, or -1 for overflow. X */ X X/* X * The lexical states are much like `sh's, except that we also do X * C-style backslash-escapes. X */ Xenum lexstate { X S_BLANK, /* outside a word */ X S_WORD, /* inside a word, no quoting */ X S_SQUOTE, /* inside a single quote */ X S_DQUOTE, /* inside a double quote */ X S_BKSL0, /* last char was \ */ X S_BKSL1, /* last chars were \, [0-7] */ X S_BKSL2 /* last chars were \, [0-7][0-7] */ X}; X Xint Xsplit(s, w, nw) X register char *s, **w; X int nw; X{ X register int c; X register char *canon = s; X register int wleft = nw; X enum lexstate state, prebkstate; X X /* X * Start out in the `blank' state (outside a word). Handle X * quotes and things. Backslashes are handled by saving the X * `pre-backslash' state, doing the backslash, and restoring X * that state at the end of the backslash sequence. X */ X state = S_BLANK; X while ((c = *s++) != 0) { Xreswitch: X switch (state) { X X /* X * Blanks: spaces stay in blank state; anything X * else starts a word. However, quotes may put X * us into quote states, rather than word states. X */ X case S_BLANK: X if (isspace(c)) X continue; X if (--wleft < 0) X return (-1); X *w++ = canon; X state = S_WORD; X /* FALLTHROUGH */ X X /* X * In a word. Spaces take us out (and end the X * current word). Quotes, however, put us into X * quote states. X */ X case S_WORD: X if (isspace(c)) { X *canon++ = 0; X state = S_BLANK; X break; X } X if (c == '\'') { X state = S_SQUOTE; X break; X } X if (c == '"') { X state = S_DQUOTE; X break; X } X if (c == '\\') { X prebkstate = S_WORD; X state = S_BKSL0; X break; X } X *canon++ = c; X break; X X /* X * Inside a single quote, the only special character X * is another single quote. This matches the Bourne X * shell quoting convention exactly. X */ X case S_SQUOTE: X if (c == '\'') X state = S_WORD; X else X *canon++ = c; X break; X X /* X * Inside a double quote, double quotes get us out, X * but backslashes must be interpreted. X */ X case S_DQUOTE: X if (c == '\\') { X prebkstate = S_DQUOTE; X state = S_BKSL0; X } else if (c == '"') X state = S_WORD; X else X *canon++ = c; X break; X X /* X * If we are handling a backslash, we will either X * restore the state, or go to BKSL1 state. In X * the latter case, do not advance the canonicalisation X * pointer, since we might have more octal digits X * to insert. X */ X case S_BKSL0: X state = prebkstate; /* probably */ X switch (c) { X X case 'b': X *canon++ = '\b'; X break; X X case 'f': X *canon++ = '\f'; X break; X X case 'n': X *canon++ = '\n'; X break; X X case 'r': X *canon++ = '\r'; X break; X X case 't': X *canon++ = '\t'; X break; X X case '0': case '1': case '2': case '3': X case '4': case '5': case '6': case '7': X *canon = c - '0'; X state = S_BKSL1; X break; X X default: X *canon++ = c; X break; X } X break; X X X /* X * In BKSL1, we have seen backslash and one octal X * digit. There may be more (in which case just X * count them on in), or there might be something X * that requires we restore the state and try again. X */ X case S_BKSL1: X switch (c) { X X case '0': case '1': case '2': case '3': X case '4': case '5': case '6': case '7': X *canon <<= 3; X *canon |= c - '0'; X state = S_BKSL2; X break; X X default: X canon++; X state = prebkstate; X goto reswitch; X } X break; X X /* X * BKSL2 is like BKSL1, except that it cannot X * help but restore the original state, since X * there are no four-character octal sequences. X */ X case S_BKSL2: X state = prebkstate; /* assuredly */ X switch (c) { X X case '0': case '1': case '2': case '3': X case '4': case '5': case '6': case '7': X *canon <<= 3; X *canon++ |= c - '0'; X break; X X default: X canon++; X goto reswitch; X } X break; X } X } X#ifdef notdef X if (state != S_WORD && state != S_BLANK) X error(0, 0, "warning: unclosed quote"); X#endif X if (state != S_BLANK) X *canon = 0; X return (nw - wleft); X} END_OF_lib/split.c if test 4603 -ne `wc -c lib/strsave.c <<'END_OF_lib/strsave.c' X/* X * Copyright (c) 1987 University of Maryland Department of Computer Science. X * All rights reserved. Permission to copy for any purpose is hereby granted X * so long as this copyright notice remains intact. X */ X X/* X * Save a string in managed memory. X */ X Xchar *malloc(), *realloc(); Xextern int errno; X Xchar * Xstrsave(s) X register char *s; X{ X register int l = strlen(s) + 1; X register char *p = malloc((unsigned) l); X X if (p == 0) X error(1, errno, "no room for %d bytes of string", l); X bcopy(s, p, l); X return (p); X} END_OF_lib/strsave.c if test 522 -ne `wc -c lib/tfm.c <<'END_OF_lib/tfm.c' X/* X * Copyright (c) 1987 University of Maryland Department of Computer Science. X * All rights reserved. Permission to copy for any purpose is hereby granted X * so long as this copyright notice remains intact. X */ X X#ifndef lint Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/tfm.c,v 1.4 89/02/13 14:31:26 grunwald Exp Locker: grunwald $"; X#endif X X/* X * TFM file reading routines. X * X * TODO: X * finish X */ X X#include X#include "types.h" X#include "fio.h" X#include "tfm.h" X Xchar *malloc(); X X#define ALLOC(n, type) ((type *) malloc((unsigned) ((n) * sizeof (type)))) X Xstatic trd_header(); Xstatic trd_ci(); Xstatic trd_fix(); X Xint Xreadtfmfile(f, t, stopafterwidth) X register FILE *f; X register struct tfmdata *t; X int stopafterwidth; /* ??? */ X{ X i32 nc; X X if (trd_header(f, &t->t_hdr)) X return (-1); X nc = t->t_hdr.th_ec - t->t_hdr.th_bc + 1; X X t->t_ci = NULL; X t->t_width = NULL; X t->t_height = NULL; X t->t_depth = NULL; X X (void) fseek(f, t->t_hdr.th_lh * 4L, 1); /* XXX */ X X if ((t->t_ci = ALLOC(nc, struct char_info_word)) == NULL || X trd_ci(f, nc, t->t_ci) || X (t->t_width = ALLOC(t->t_hdr.th_nw, i32)) == NULL || X trd_fix(f, t->t_hdr.th_nw, t->t_width)) X goto bad; X if (stopafterwidth) X return (0); X if ((t->t_height = ALLOC(t->t_hdr.th_nh, i32)) == NULL || X trd_fix(f, t->t_hdr.th_nh, t->t_height) || X (t->t_depth = ALLOC(t->t_hdr.th_nd, i32)) == NULL || X trd_fix(f, t->t_hdr.th_nd, t->t_depth)) X goto bad; X return (0); X X bad: X if (t->t_ci != NULL) { X free((char *) t->t_ci); (char *) t->t_ci = 0; X } X if (t->t_width != NULL) { X free((char *) t->t_width); (char *) t->t_width = 0; X } X if (t->t_height != NULL) { X free((char *) t->t_height); (char *) t->t_height = 0; X } X if (t->t_depth != NULL) { X free((char *) t->t_depth); (char *) t->t_depth = 0; X } X return (-1); X } X Xstatic int Xtrd_header(f, th) X register FILE *f; X register struct tfmheader *th; X{ X register i32 *p; X X for (p = &th->th_lf; p <= &th->th_np; p++) X fGetWord(f, *p); X if (feof(f)) X return (-1); X return (0); X} X Xstatic int Xtrd_ci(f, nc, ci) X register FILE *f; X register int nc; X register struct char_info_word *ci; X{ X X while (--nc >= 0) { X ci->ci_width = fgetbyte(f); X ci->ci_h_d = fgetbyte(f); X ci->ci_i_t = fgetbyte(f); X ci->ci_remainder = fgetbyte(f); X ci++; X } X if (feof(f)) X return (-1); X return (0); X} X Xstatic int Xtrd_fix(f, nf, p) X register FILE *f; X register int nf; X register i32 *p; X{ X X while (--nf >= 0) { X fGetLong(f, *p); X p++; X } X if (feof(f)) X return (-1); X return (0); X} END_OF_lib/tfm.c if test 2549 -ne `wc -c lib/tfmfont.c <<'END_OF_lib/tfmfont.c' X/* X * Copyright (c) 1987 University of Maryland Department of Computer Science. X * All rights reserved. Permission to copy for any purpose is hereby granted X * so long as this copyright notice remains intact. X */ X X#ifndef lint Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/tfmfont.c,v 1.5 89/02/13 14:31:27 grunwald Exp Locker: grunwald $"; X#endif X X#include X#include X#include X#include "types.h" X#include "conv.h" X#include "font.h" X#include "tfm.h" X X/* X * TFM font operations. This defines three fonts: X * X * box - prints as little square boxes, outlining what TeX X * thinks is the character. X * blank - prints as entirely blank. X * invis - prints as entirely blank. X * X * The first two also complain that no font is available in the X * requested size; these are intended to be used as a last resort X * so that users can always print DVI files. You should configure X * in exactly one of box or blank. X * X * TODO: X * base box edge widths on Conversion.c_dpi X */ X Xstatic box_read(); Xstatic blank_read(); Xstatic invis_read(); Xstatic do_read(); Xstatic tfm_getgly(); Xstatic tfm_rasterise(); Xstatic tfm_freefont(); X X /* magnifications are unused in tfm fonts */ Xstruct fontops boxops = /* `boxtops'? Is this a cereal driver? */ X { "box", 0.0, box_read, tfm_getgly, tfm_rasterise, tfm_freefont }; Xstruct fontops blankops = X { "blank", 0.0, blank_read, tfm_getgly, tfm_rasterise, tfm_freefont }; Xstruct fontops invisops = X { "invis", 0.0, invis_read, tfm_getgly, tfm_rasterise, tfm_freefont }; X X/* X * Local info. X */ X Xstruct tfm_details { X int tfm_edge; /* box edge widths, in pixels */ X struct conversion tfm_conv; /* conv. from scaled pts to pixels */ X struct tfmdata tfm_data; /* the TFM file data */ X}; X X/* X * Get the tfm_details from font f. X */ X#define ftotfm(f) ((struct tfm_details *) (f)->f_details) X Xextern int errno; Xchar *malloc(); X X/* X * Read a Box font. X */ Xstatic int Xbox_read(f) X struct font *f; X{ X X return (do_read(f, 0, 1)); X} X X/* X * Read a Blank font. X */ Xstatic int Xblank_read(f) X struct font *f; X{ X X return (do_read(f, 1, 1)); X} X X/* X * Read an Invisible font. X */ Xstatic int Xinvis_read(f) X struct font *f; X{ X X return (do_read(f, 1, 0)); X} X X/* X * Read a TFM font. It is blank if `blank'; complain if `complain'. X */ Xstatic int Xdo_read(f, blank, complain) X register struct font *f; X int blank, complain; X{ X register struct tfm_details *tfm; X FILE *fd; X X if ((fd = fopen(f->f_path, "r")) == 0) X return (-1); X if ((tfm = (struct tfm_details *) malloc(sizeof (*tfm))) == NULL) X goto fail; X if (readtfmfile(fd, &tfm->tfm_data, blank)) X goto fail; X if (blank) X tfm->tfm_edge = 0; X else { X extern Conv Conversion; X X tfm->tfm_edge = 2; /* XXX should be based on dpi */ X tfm->tfm_conv = Conversion; X tfm->tfm_conv.c_fromsp *= DMagFactor(f->f_scaled); X /* XXX !data abstraction */ X } X if (FontHasGlyphs(f, tfm->tfm_data.t_hdr.th_bc, X tfm->tfm_data.t_hdr.th_ec + 1)) X goto fail; X f->f_details = (char *) tfm; X (void) fclose(fd); X if (complain) X error(0, 0, "Warning: no font for %s", Font_TeXName(f)); X return (0); X Xfail: X (void) fclose(fd); X if (tfm != NULL) { X free((char *) tfm); (char *) tfm = 0; X } X return (-1); X} X X/* X * Obtain the specified range of glyphs. X */ Xstatic int Xtfm_getgly(f, l, h) X register struct font *f; X int l; X register int h; X{ X register struct tfm_details *tfm = ftotfm(f); X register struct glyph *g; X register int i; X register struct char_info_word *ci; X#define t (&tfm->tfm_data) X i32 ScaleOneWidth(); X X#define ftop(fix) cfromSP(&tfm->tfm_conv, ScaleOneWidth(fix, f->f_dvimag)) X X for (i = l; i < h; i++) { X ci = &t->t_ci[i - t->t_hdr.th_bc]; X /* zero widths mark invalid characters */ X if (ci->ci_width == 0) X continue; X g = f->f_gly[i]; X g->g_flags = GF_VALID; X g->g_tfmwidth = t->t_width[UnSign8(ci->ci_width)]; X if (tfm->tfm_edge != 0) { X g->g_xorigin = 0; X g->g_yorigin = ftop(t->t_height[T_CI_H(ci)]); X g->g_width = ftop(g->g_tfmwidth); X g->g_height = g->g_yorigin + X ftop(t->t_depth[T_CI_D(ci)]); X } X } X return (0); X#undef t X} X X/* X * Obtain rasters for the specified glyphs. X * X * IGNORES tfm->tfm_edge: 2 HARDCODED FOR NOW X */ Xstatic int Xtfm_rasterise(f, l, h) X struct font *f; X int l, h; X{ X register struct glyph *g; X register char *p; X register int w, j, i; X struct tfm_details *tfm = ftotfm(f); X#define EDGE 2 X X if (tfm->tfm_edge == 0) X return; Xif (tfm->tfm_edge != 2) panic("tfm_rasterise"); X for (i = l; i < h; i++) { X g = f->f_gly[i]; X if ((g->g_flags & GF_VALID) == 0 || !HASRASTER(g)) X continue; X w = (g->g_width + 7) >> 3; X p = malloc((unsigned) (g->g_height * w)); X if (p == NULL) X return (-1); X g->g_raster = p; X g->g_rotation = ROT_NORM; X if (g->g_width < 2 * EDGE) { X w = 2 * EDGE - g->g_width; X for (j = g->g_height; --j >= 0;) X *p++ = 0xf0 << w; X } else { X bzero(p, g->g_height * w); X for (j = 0; j < g->g_height;) { X if (j < EDGE || j >= g->g_height - EDGE) { X register int k = w; X X while (--k > 0) X *p++ = 0xff; X *p++ = 0xff << ((8 - g->g_width) & 7); X j++; X continue; X } X /* the following depends on EDGE==2 */ X *p = 0xc0; X p += w - ((g->g_width & 7) == 1 ? 2 : 1); X *p++ |= 0xc0 >> ((g->g_width - EDGE) & 7); X if ((g->g_width & 7) == 1) X *p++ = 0x80; X /* end dependencies */ X if (++j == EDGE && g->g_height >= 2 * EDGE) { X register int n = g->g_height - EDGE; X X p += (n - j) * w; X j = n; X } X } X } X } X return (0); X} X X/* X * Discard the font details. X */ Xstatic Xtfm_freefont(f) X struct font *f; X{ X X free(f->f_details); f->f_details = 0; X} END_OF_lib/tfmfont.c if test 5607 -ne `wc -c