home *** CD-ROM | disk | FTP | other *** search
- Subject: v11i072: Including PostScript figures in ditroff, Part01/05
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rs@uunet.UU.NET
-
- Submitted-by: trevor@linc.cis.upenn.edu (Trevor Darrell)
- Posting-number: Volume 11, Issue 72
- Archive-name: psfig/Part01
-
- This is "psfig," a package to include PostScript figures in ditroff. It
- was presented at the Phoenix Usenix and in Unix Review.
-
-
- system requirements:
- PostScript printer
- ditroff DWB version 2.0 or later
- transcript, with source for psdit
- **This may not be needed if you have transcript 3.0
-
- Please read the "system requirements" so I am not deluged with "but it
- doesn't work with my ditroff!" complaints.
-
- --tjd
-
- Trevor Darrell
-
- trevor@linc.cis.upenn.edu | trevor@grasp.cis.upenn.edu | (215) 898-5617
- Computer and Information Science
- University of Pennsylvania CIS dept. 200 S. 33rd st. Philadelphia, PA 19104
-
- -----------------------
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- #
- # Contents: trf/ trf/src/ trf/README trf/src/Makefile trf/src/cmds.c
- # trf/src/item.c trf/src/item.h trf/src/keywords.c trf/src/lineio.c
- # trf/src/macros.c trf/src/main.c trf/src/psfig.h trf/src/troff.c
-
- echo mkdir - trf
- mkdir trf
- chmod u=rwx,g=rx,o=rx trf
-
- echo x - trf/README
- sed 's/^@//' > "trf/README" <<'@//E*O*F trf/README//'
- This is the source and documentation to the psfig preprocessor for ditroff.
-
- All source code, documentation and related files are Copyright (C) 1987
- by Trevor Darrell. All rights reserved. This software may not be distributed
- on a for-profit basis in any way without express written permission of the
- author(s).
-
- ===========================================================================
-
- What you need to use psfig:
-
- + a ditroff (device-independent troff) that accepts the \X
- command for text pass-thru. ditroff from DWB 2.0 or
- greater will do.
-
- + source to psdit from the adobe transcript package
-
- + (optionally) source for ditroff to make some minor fixes.
-
- + of course, a postscript printer for the final result. Draft
- copies do not need a postscript device.
-
- ========================================================================
- What to do:
-
- 1. Compile the preprocessor:
- cd src; make psfig
- cp psfig /usr/local (or /usr/bin, &c...)
-
- 2. Next, install the patches to psdit and psdit.pro.
- ** Read patches/README for instructions on the psdit.c and psdit.pro patches.
-
- 3. Copy lib/psfig.tmac to the troff macro directory (/usr/lib/tmac).
-
- 4. Finally, if you are up to it and have ditroff source, apply
- the ditroff patch. (less critical) If you don't make the
- patch, figures may not center properly and figures won't
- work inside eqn. The centering problem can be alleviated
- by using "-f" with psfig.
-
- Give the test program a spin...
-
- % cd tst
- % make test.ps
-
- make a copy of the manaul...
-
- % cd doc
- % dopaper
-
- Note that the slew of warnings from psfig about `psfig.ps.?' on the first pass
- is no problem and should be ignored. (due to recursive figure processing...)
-
- @//E*O*F trf/README//
- chmod u=rw,g=r,o=r trf/README
-
- echo mkdir - trf/src
- mkdir trf/src
- chmod u=rwx,g=rx,o=rx trf/src
-
- echo x - trf/src/Makefile
- sed 's/^@//' > "trf/src/Makefile" <<'@//E*O*F trf/src/Makefile//'
- CFLAGS = -g
- OBJS = main.o lineio.o item.o troff.o cmds.o keywords.o macros.o
- SRCS = main.c lineio.c item.c troff.c cmds.c keywords.c macros.c
- HDRS = psfig.h item.h
-
- @.c.o:
- -rm -f $@
- cc -c $(CFLAGS) $<
-
- psfig : $(OBJS)
- -rm -f psfig
- cc ${CFLAGS} -o psfig $(OBJS)
-
- $(OBJS) : psfig.h
- item.o cmds.o keywords.o: item.h
-
- lint: $(SRCS) $(HDRS)
- lint $(SRCS)
-
- tidy:
- -rm -f *.BAK *.CKP a.out
- clean: tidy
- -rm -f *.o core '#'*
- @//E*O*F trf/src/Makefile//
- chmod u=rw,g=r,o=r trf/src/Makefile
-
- echo x - trf/src/cmds.c
- sed 's/^@//' > "trf/src/cmds.c" <<'@//E*O*F trf/src/cmds.c//'
- /***
- *** cmds.c --
- ***
- *** Handle parsing of commands for psfig.
- ***
- *** T.Darrell, 3/86.
- ***/
-
- # include "psfig.h"
- # include "item.h"
-
- int Draft = DraftDefault;
-
- int inLineFlag = 0; /* are we generating an in-line figure? */
-
- /*
- * dofigcmd()
- */
-
- dofigcmd()
- {
- int end = 0;
- int didsome = 0;
- int global = 0;
- static char cmdbuf[SMBUFSZ];
- static char bigbuf[BUFSIZ];
-
- while (!end) {
- switch (getItem(cmdbuf)) {
-
- case iEndOfInput:
- ++end;
- case iSeparator:
- break;
-
- case iDefine:
- switch (getItem(cmdbuf)) {
- case iEndOfInput:
- case iSeparator:
- error("empty define");
-
- case iWord:
- if (getString(bigbuf, sizeof(bigbuf))) {
- addMacro(cmdbuf, bigbuf);
- } else {
- deleteMacro(cmdbuf);
- }
- break;
-
- default:
- error("can't define a keyword");
- }
- break;
-
- case iDelim:
- switch (getItem(cmdbuf)) {
- case iEndOfInput:
- ++end;
- case iSeparator:
- delimSt = delimEnd = 0;
- break;
-
- case iWord:
- delimSt = cmdbuf[0];
- if (cmdbuf[1])
- delimEnd = cmdbuf[1];
- else
- delimEnd = delimSt;
- break;
- }
- break;
-
- case iSpace:
- switch(getItem(cmdbuf)) {
- case iWord:
- saveSpaceH(cmdbuf);
- didsome++;
- break;
- default:
- error("bad space command");
- }
- break;
-
- case iLiteral:
-
- if (!getString(bigbuf, sizeof(bigbuf)))
- break;
-
- for (;;) {
- switch (getItem(cmdbuf)) {
- case iLevel:
- if (getItem(cmdbuf) != iWord)
- error("bad level in literal");
- if (atoi(cmdbuf) < Draft) {
- ++didsome;
- emitLiteral(bigbuf);
- }
- continue;
-
- case iGlobal:
- ++global;
- emitLiteral("globalstart");
- continue;
-
- default:
- if (didsome) {
- unGetItem(cmdbuf);
- break;
- }
- if (inLineFlag) {
- if (InLineLevel < Draft) {
- emitLiteral(bigbuf);
- ++didsome;
- }
- } else {
- if (BrokenOutLevel < Draft) {
- emitLiteral(bigbuf);
- ++didsome;
- }
- }
-
- unGetItem(cmdbuf);
- break;
- }
- break;
- }
- if (global) {
- emitLiteral("globalend");
- global = 0;
- }
- break;
-
- case iFile:
- *bigbuf = 0;
- if (getItem(bigbuf) != iWord)
- error("bad file command");
-
- for (;;) {
- switch (getItem(cmdbuf)) {
- case iLevel:
- if (getItem(cmdbuf) != iWord)
- error("bad level in literal");
- if (atoi(cmdbuf) < Draft) {
- includeFile(abspath(bigbuf));
- ++didsome;
- }
- continue;
-
- case iGlobal:
- ++global;
- emitLiteral("globalstart");
- continue;
-
- default:
- if (inLineFlag) {
- if (InLineLevel < Draft) {
- includeFile(abspath(bigbuf));
- ++didsome;
- }
- } else {
- if (BrokenOutLevel < Draft) {
- includeFile(abspath(bigbuf));
- ++didsome;
- }
- }
- unGetItem(cmdbuf);
- break;
- }
- break;
- }
- if (global) {
- emitLiteral("globalend");
- global = 0;
- }
-
- break;
-
- case iFigure:
- includeFig();
- didsome++;
- break;
-
- case iWord:
- unGetItem(cmdbuf);
- includeFig();
- didsome++;
- break;
-
- default:
- error("unknown command");
- }
- }
-
- return didsome;
- }
-
-
- /*
- * includeFig:
- *
- * Appends the ditroff code needed to save space for figure specifed by the
- * 'file' command in cmd to dStr, and returns the new string.
- *
- * The ditroff commands leave the "pen" in the upper right hand corner.
- */
-
- static char path[SMBUFSZ], filenm[SMBUFSZ];
- static char x[SMBUFSZ], y[SMBUFSZ]; /* postscript size */
- static char rx[SMBUFSZ], ry[SMBUFSZ]; /* ditroff reserve size */
- int doClip;
- int nbox, draftlvl;
- int bflag; /* have bounds been set? */
- float bb_llx, bb_lly, bb_urx, bb_ury;
- char head[BUFSZ], foot[BUFSZ]; /* things to do before and
- * after the figure is inlcluded
- * (arguments, etc...)
- */
- char *
- includeFig()
- {
- float fx, fy;
-
- bflag = 0;
-
- parse();
-
- (void) strcpy(filenm, abspath(path));
-
- /*
- * If no size was specified, use size from file (in points).
- * If only a width was specified, calculate
- * height = fileheight * (width / filewidth).
- * If only a height, calculate
- * width = filewidth * (height / fileheight).
- */
-
- if (!bflag) {
- getFileBB(filenm, &bb_llx, &bb_lly, &bb_urx, &bb_ury);
- }
-
- fx = bb_urx - bb_llx;
- fy = bb_ury - bb_lly;
-
- if (!*x && !*y) {
- (void) sprintf(x, "%.2fp", fx);
- (void) sprintf(y, "%.2fp", fy);
- } else if (!*x) {
- (void) sprintf(x,"(%.2fp*%s/%.2fp)", fx, y, fy);
- } else if (!*y) {
- (void) sprintf(y,"(%.2fp*%s/%.2fp)", fy, x, fx);
- }
-
- /*
- * If reserve size was ommited, = figure size
- */
-
- if (*rx == 0)
- (void) strcpy(rx, x);
- if (*ry == 0)
- (void) strcpy(ry, y);
-
-
- if (draftlvl >= Draft) {
-
- if (!inLineFlag && strcmp(ry, "0")) {
- draftNote(path);
- makeBox(rx, ry);
- } else {
- if (strcmp(ry,"0"))
- saveSpaceV(ry, (inLineFlag ? UP : DOWN));
-
- saveSpaceH(rx);
- }
-
- } else {
-
- if (inLineFlag)
- moveUp(y);
-
- startfig(x, y, bb_llx, bb_lly, bb_urx, bb_ury);
- if (doClip) emitDoClip();
- fputs(head, stdout);
- includeFile(filenm);
- fputs(foot, stdout);
- endfig();
-
- /* Dont save space if == "0" */
- if (strcmp(ry, "0"))
- saveSpaceV(ry, (inLineFlag ? UP : DOWN));
- saveSpaceH(rx);
-
- if (inLineFlag)
- moveDown(y);
- }
- }
-
- /*
- * parse:
- *
- * parse file command.
- */
-
- parse()
- {
- int end = 0;
- int foundPath = 0;
- static char tmpbuf[SMBUFSZ];
- static char word[SMBUFSZ];
-
- /*
- * initialize all values to their defaults,
- * then fill them in as specifed on the cmd line.
- */
-
- strcpy(head, strcpy(foot, ""));
-
- if (inLineFlag)
- draftlvl = InLineLevel;
- else
- draftlvl = BrokenOutLevel;
- nbox = 0;
- doClip = 0;
-
- (void) strcpy(rx, strcpy(x, strcpy(y, "")));
-
- /*
- * If we are in-line, set default vert. reserve to nothing ("0")
- * otherwise, set default reserve to NULL, which signals
- * it should later be filled in with x,y.
- */
- if (inLineFlag)
- (void) strcpy(ry, "0");
- else
- (void) strcpy(ry, "");
-
- while (!end) {
- switch(getItem(word)) {
- case iHeight:
- if (getItem(y) != iWord)
- error("bad height");
- break;
- case iWidth:
- if (getItem(x) != iWord)
- error("bad width");
- break;
- case iReserve:
- if (getItem(rx) != iWord) {
- unGetItem(rx);
- (void) strcpy(rx, strcpy(ry, ""));
- break;
- }
- if (getItem(ry) != iWord)
- error("bad reserve");
- break;
- case iClip:
- ++doClip;
- break;
- case iLevel:
- if (getItem(tmpbuf) != iWord)
- error("bad level");
- draftlvl = atoi(tmpbuf);
- break;
- case iBounds:
- if (getItem(tmpbuf) != iWord)
- error("bad bounds");
- sscanf(tmpbuf, "%f", &bb_llx);
-
- if (getItem(tmpbuf) != iWord)
- error("bad bounds");
- sscanf(tmpbuf, "%f", &bb_lly);
-
- if (getItem(tmpbuf) != iWord)
- error("bad bounds");
- sscanf(tmpbuf, "%f", &bb_urx);
-
- if (getItem(tmpbuf) != iWord)
- error("bad bounds");
- sscanf(tmpbuf, "%f", &bb_ury);
- ++bflag;
- break;
- case iLeftBrace:
- parse_format();
- break;
- case iEndOfInput:
- case iSeparator:
- ++end;
- break;
- case iWord:
- if (!foundPath) {
- strcpy(path, word);
- ++foundPath;
- break;
- }
- /* flow through */
- default:
- unGetItem(word);
- ++end;
- break;
- }
- }
-
- /*
- * Make sure we have a file name.
- */
-
- if (!foundPath) {
- error("missing file name in figure command");
- }
- }
-
- parse_format() {
- static char word[SMBUFSZ];
- int pre = 1; /* true until `figure' is encountered */
-
- for (;;) switch (getItem(word)) {
-
- case iFile :
- if (getItem(word) != iWord)
- error("bad file command in format");
-
- sIncludeFile((pre ? head : foot), abspath(word),BUFSZ);
- break;
-
- case iLiteral :
- if (!getString(word, sizeof(word)))
- error("bad literal in format");
-
- sEmitLiteral((pre ? head : foot), word, BUFSZ);
- break;
-
- case iFigure :
- pre = 0;
- break;
-
- case iRightBrace:
- return;
-
- default :
- error("bad command in format");
- }
- }
- /* end of cmds.c */
- @//E*O*F trf/src/cmds.c//
- chmod u=r,g=r,o=r trf/src/cmds.c
-
- echo x - trf/src/item.c
- sed 's/^@//' > "trf/src/item.c" <<'@//E*O*F trf/src/item.c//'
- /***
- *** item.c --
- ***
- *** The item reading abstraction for psfig
- ***
- *** N.Batchelder, 3/8/86.
- ***/
-
- # include "item.h"
- # include "psfig.h"
-
- # define elif else if
- # define isWhite(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
-
- static int endofinput = 0; /* Have we hit the end? */
- static char cbuf[1000]; /* Where we do all processing */
- static char *cp; /* Our position in cbuf */
- static char *(*getmore)(); /* Our gimme gimme function */
-
- # define StartOffset 700 /* Where in cbuf to start filling. */
-
- /*
- * getCh:
- *
- * Read a character from our input. Returns 0 when no more.
- */
-
- static
- char
- getCh()
- {
- while (!endofinput) {
- if (*cp) {
- return *cp++;
- }
-
- if (!getmore) {
- endofinput++;
- } elif ((*getmore)(cp = cbuf + StartOffset) == NULL) {
- endofinput++;
- }
- }
-
- return 0;
- }
-
- /*
- * pushBackCh:
- *
- * Takes a character and pushes it back. Just like ungetc.
- */
-
- static
- pushBackCh(ch)
- char ch;
- {
- *--cp = ch;
- endofinput = 0;
- }
-
- /*
- * pushBackStr:
- *
- * Takes a string and pushes it back into our input so that it will be read
- * next time.
- */
-
- static
- pushBackStr(str)
- char *str;
- {
- register char *sp;
-
- /*
- * Find the end of the string.
- */
-
- for (sp = str; *sp; sp++)
- ;
-
- /*
- * Now write it into the buffer backwards from the current point.
- */
-
- while (--sp >= str) {
- *--cp = *sp;
- }
-
- if (cp < cbuf) {
- error("pushback overflow");
- }
-
- if (strlen(str)) {
- endofinput = 0;
- }
- }
-
- /*
- * setInput:
- *
- * Takes a string and a function, and installs them as the current working
- * text and the function to call to get more when that's used up.
- */
-
- void
- setInput(str, morefn)
- char *str;
- char *(*morefn)();
- {
- endofinput = 0;
- (void) strcpy(cbuf+StartOffset, str);
- cp = cbuf+StartOffset;
- getmore = morefn;
- }
-
- /*
- * getItem:
- *
- * Reads the next item (token) from the input and copies it to the buffer
- * provided to it. The return value is the type of the item (enum item).
- */
-
- static char lastitem[SMBUFSZ];
- static enum item lasttype;
- static int pusheditem = 0;
-
- enum item
- getItem(ibuf)
- char *ibuf;
- {
- char ch; /* Our latest character from getCh */
- char quote = 0; /* Our current quote char, if any */
- char *bp = ibuf; /* Fills up ibuf */
- enum item itype; /* What we eventually return */
- char *value; /* The value of a possible macro */
-
- if (pusheditem) {
- (void) strcpy(ibuf, lastitem);
- pusheditem = 0;
- return lasttype;
- }
-
- /*
- * First skip whitespace.
- */
-
- while ((ch = getCh()) && isWhite(ch))
- ;
-
- if (ch == 0) {
- return lasttype = iEndOfInput;
- }
-
- /*
- * Do we have a quote character in hand?
- */
-
- if (index(Quotes, ch)) {
- quote = ch;
- if (!(ch = getCh())) {
- return lasttype = iEndOfInput;
- }
- }
-
- /*
- * Loop around building up the item.
- */
-
- for (;;) {
- if (quote) {
- if (ch == quote) {
- break;
- }
- } elif (isWhite(ch)) {
- pushBackCh(ch);
- break;
- } elif (index(SelfDelim, ch)) {
- break;
- }
-
- *bp++ = ch;
-
- if (!(ch = getCh())) {
- break;
- }
-
- if (bp - ibuf > SMBUFSZ) {
- error("word overflow");
- }
- }
- *bp = '\0';
-
- if (index(SelfDelim, ch)) {
- if (bp == ibuf) {
- /* It was the first character read */
- switch (ch) {
- case Sep:
- return lasttype = iSeparator;
- case LBrace:
- return lasttype = iLeftBrace;
- case RBrace:
- return lasttype = iRightBrace;
- }
- } else {
- /* It terminated the item */
- pushBackCh(ch);
- }
- }
-
- /*
- * If the thing was quoted, then it is simply a generic word.
- */
-
- if (quote) {
- return iWord;
- }
-
- /*
- * Now we have a word in ibuf. We must check to see if it is a
- * keyword.
- */
-
- if (isKeyword(ibuf, &itype)) {
- return lasttype = itype;
- }
-
- /*
- * Is it a macro?
- */
-
- if (isMacro(ibuf, &value)) {
- pushBackStr(value);
- return getItem(ibuf);
- }
-
- /*
- * I guess it was just a generic word after all.
- */
-
- return lasttype = iWord;
- }
-
- /*
- * unGetItem:
- *
- * Takes the text of the last item and causes it to be returned next time.
- */
-
- unGetItem(ibuf)
- char *ibuf;
- {
- pusheditem++;
- (void) strcpy(lastitem, ibuf);
- }
-
- /*
- * getString:
- *
- * Reads a self-delimited string from the input, and returns it in the buffer
- * provided. Self-delimited means that the first non-white character is taken
- * to be the delimiter. No macro expansion is done, and quotes are like
- * anything else.
- * Returns 1 or 0 depending on whether there was a string or not. (A separator
- * or end of input can mean no string).
- */
-
- int
- getString(sbuf, len)
- char *sbuf;
- int len;
- {
- char ch; /* Our latest character from getCh */
- char delim; /* This string's delimiter */
- char *bp = sbuf; /* Fills up `sbuf' */
-
- /*
- * Skip whitespace.
- */
-
- while ((ch = getCh()) && isWhite(ch))
- ;
-
- if (ch == 0 || ch == Sep) {
- return 0;
- }
-
- delim = ch;
-
- do {
- ch = getCh();
- } while ((ch != delim) && (bp < sbuf + len) && (*bp++ = ch));
-
- if (bp == sbuf + len) error("buffer overflow");
-
- *bp = '\0';
- return 1;
- }
-
- /* end of item.c */
- @//E*O*F trf/src/item.c//
- chmod u=r,g=r,o=r trf/src/item.c
-
- echo x - trf/src/item.h
- sed 's/^@//' > "trf/src/item.h" <<'@//E*O*F trf/src/item.h//'
- /***
- *** item.h --
- ***
- *** Definitions for the item stuff for psfig.
- ***
- *** N.Batchelder, 3/8/86.
- ***/
-
- /*
- * These are the different types of items we can return.
- */
-
- enum item {
- iEndOfInput,
- iSeparator,
- iLeftBrace,
- iRightBrace,
- iFile,
- iFigure,
- iSpace,
- iDelim,
- iDefine,
- iLiteral,
- iWidth,
- iHeight,
- iReserve,
- iClip,
- iBox,
- iLevel,
- iBounds,
- iGlobal,
- iSafe,
- iWord,
- };
-
- /*
- * These are the characters that we recognize as special.
- */
-
- # define Quotes "\"'"
- # define SelfDelim "{};"
- # define Sep ';'
- # define LBrace '{'
- # define RBrace '}'
-
- enum item getItem();
-
- /* end of item.h */
- @//E*O*F trf/src/item.h//
- chmod u=r,g=r,o=r trf/src/item.h
-
- echo x - trf/src/keywords.c
- sed 's/^@//' > "trf/src/keywords.c" <<'@//E*O*F trf/src/keywords.c//'
- /***
- *** keywords.c --
- ***
- *** Keyword recognition function for psfig.
- ***
- *** N.Batchelder, 3/8/86.
- ***/
-
- # include "psfig.h"
- # include "item.h"
-
- static struct keypair {
- char *name;
- enum item itype;
- } keytable[] = {
- "figure", iFigure,
- "space", iSpace,
- "delim", iDelim,
- "define", iDefine,
- "literal", iLiteral,
- "file", iFile,
- "width", iWidth,
- "height", iHeight,
- "reserve", iReserve,
- "clip", iClip,
- "box", iBox,
- "level", iLevel,
- "bounds", iBounds,
- "global", iGlobal,
- "safe", iSafe,
- NULL, iEndOfInput,
- };
-
- /*
- * isKeyword:
- *
- * Takes the text of an item and returns whether or not it is a keyword.
- * If it is, then it fills in the exact item type in the pointed to enum item.
- */
-
- int
- isKeyword(buf, iptr)
- char *buf;
- enum item *iptr;
- {
- struct keypair *keyp;
-
- for (keyp = keytable; keyp->name; keyp++) {
- if (!strcmp(buf, keyp->name)) {
- /*
- * A match!
- */
-
- *iptr = keyp->itype;
- return 1;
- }
- }
-
- return 0;
- }
-
- /* end of keywords.c */
-
- @//E*O*F trf/src/keywords.c//
- chmod u=r,g=r,o=r trf/src/keywords.c
-
- echo x - trf/src/lineio.c
- sed 's/^@//' > "trf/src/lineio.c" <<'@//E*O*F trf/src/lineio.c//'
- /***
- *** lineio.c --
- ***
- *** Low level i/o for psfig.
- *** Provides the capability to get and unget lines.
- ***
- *** N.Batchelder, 3/8/86.
- ***/
-
- # include <stdio.h>
- # include "psfig.h"
-
- /*
- * This is non-NULL if a line was pushed back.
- */
-
- static char *ungotten = NULL;
-
- /*
- * getline:
- *
- * A lot like fgets, but will return the last line ungotten by ungetline if
- * there is one.
- */
-
- char *
- getline(buf, len, file)
- char *buf;
- int len;
- FILE *file;
- {
- if (ungotten) {
- (void) strcpy(buf, ungotten);
- ungotten = NULL;
- return buf;
- }
-
- linenumber++;
- return fgets(buf, len, file);
- }
-
- /*
- * ungetline:
- *
- * Takes the pointer passed to it and saves it to be returned by getline next
- * time.
- */
-
- ungetline(buf)
- char *buf;
- {
- if (ungotten) {
- error("Double ungetline!");
- }
- ungotten = buf;
- }
-
- /* end of lineio.c */
- @//E*O*F trf/src/lineio.c//
- chmod u=r,g=r,o=r trf/src/lineio.c
-
- echo x - trf/src/macros.c
- sed 's/^@//' > "trf/src/macros.c" <<'@//E*O*F trf/src/macros.c//'
- /***
- *** macros.c --
- ***
- *** The macro handling stuff for psfig.
- ***
- *** N.Batchelder, 3/8/86.
- ***/
-
- # include "psfig.h"
-
- # define MaxMacros 100
-
- /*
- * Our table of macros. The end is marked by a pointer (macp). Entries may
- * have NULL for their name (if they have been deleted).
- */
-
- struct mac {
- char *name;
- char *value;
- };
-
- static struct mac macros[MaxMacros];
- static struct mac *macp = macros;
-
- /*
- * isMacro:
- *
- * Look up a name. If it is a macro, point to the value through an argument,
- * and return 1. If it isn't, return 0.
- */
-
- int
- isMacro(nm, valp)
- char *nm;
- char **valp;
- {
- struct mac *mp;
-
- for (mp = macros; mp < macp; mp++) {
- if (!strcmp(nm, mp->name)) {
- *valp = mp->value;
- return 1;
- }
- }
-
- return 0;
- }
-
- /*
- * addMacro:
- *
- * Takes a name and a value and enters into the table.
- */
-
- addMacro(n, v)
- char *n;
- char *v;
- {
- char *strsave();
- struct mac *mp;
-
- if (macp >= macros+MaxMacros) {
- /*
- * Table is full. Attempt to compact it.
- */
-
- for (mp = macros; mp < macp; mp++) {
- if (mp->name == NULL) {
- mp->name = --macp->name;
- mp->value = macp->value;
- }
- }
-
- if (macp >= macros+MaxMacros) {
- error("macro table overflow");
- }
- }
-
- macp->name = strsave(n);
- macp->value = strsave(v);
- macp++;
- }
-
- /*
- * deleteMacro:
- *
- * Removes the given name from the table.
- */
-
- deleteMacro(nm)
- char *nm;
- {
- struct mac *mp;
-
- for (mp = macros; mp < macp; mp++) {
- if (!strcmp(nm, mp->name)) {
- mp->name = NULL;
- }
- }
- }
-
- /*
- * strsave:
- *
- * Stashes its argument away somewhere and returns a new pointer to it.
- */
-
- # define NSAVETAB 4096
-
- static char *savetab;
- static int saveleft;
-
- char *
- strsave(cp)
- register char *cp;
- {
- register int len;
-
- len = strlen(cp) + 1;
- if (len > saveleft) {
- saveleft = NSAVETAB;
- if (len > saveleft)
- saveleft = len;
- savetab = malloc((unsigned) saveleft);
- if (savetab == 0) {
- error("no more string memory");
- }
- }
- (void) strncpy(savetab, cp, len);
- cp = savetab;
- savetab += len;
- saveleft -= len;
-
- return cp;
- }
-
- /* end of macros.c */
- @//E*O*F trf/src/macros.c//
- chmod u=r,g=r,o=r trf/src/macros.c
-
- echo x - trf/src/main.c
- sed 's/^@//' > "trf/src/main.c" <<'@//E*O*F trf/src/main.c//'
- /***
- *** main.c --
- ***
- *** Central stuff for the psfig preprocessor.
- ***
- *** T.Darrell, 3/86.
- ***/
-
- # include "psfig.h"
-
- int linenumber = 0; /* line counter */
-
- char delimSt = 0,
- delimEnd = 0; /* delimeters */
-
- char *XFlush = NULL; /* The character to flush \X with */
-
- char *searchDirTable[MAXDIRS] = { "." };
- int dircnt = 0;
-
- char errbuf[SMBUFSZ]; /* temp buffer for error msg formatting */
-
- int psditfix = TRUE; /* use fix that compensates for the weird
- way psdit V2 draws lines (a point
- off here and there)
- "-t" option turns off this flag */
-
- int newbb = TRUE; /* search for bounding box comments the
- new way.
- "-b" option turns off this flag */
-
- /*
- * error:
- *
- * Print an error message, and leave.
- */
-
- error(s)
- char *s;
- {
- fprintf(stderr,"psfig: line %d: %s\n", linenumber, s);
- exit(1);
- }
- warn(s)
- char *s;
- {
- fprintf(stderr,"psfig: line %d: warning -- %s\n", linenumber, s);
- }
-
- /*
- * getaline:
- *
- * A function that we can pass to the lineio level to get more lines when
- * processing .F+ .F- commands. Claims that there is no more input when it
- * hits a .F-.
- */
-
- char *
- getaline(buf)
- char *buf;
- {
- if (getline(buf, BUFSZ, stdin) == NULL)
- return NULL;
-
- if (!strncmp(buf, FGEND, strlen(FGEND))) {
- ungetline(buf);
- return NULL;
- }
-
- return buf;
- }
-
- /*
- * main:
- *
- * The basic loop of the program is simply to read lines from the input, and
- * if thereare psfig commands to process, to process them. There are three
- * different ways to mark psfig commands:
- *
- * 1. Between .F+ and .F-
- * 2. Between delimiter characters
- * 3. The rest of a line that starts with .F=
- */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- char **argp;
-
- /*
- * Process arguments.
- */
-
- argc--;
- argp = argv+1;
-
- while ((*argp)[0] == '-' && argc--) {
- switch ((*argp)[1]) {
-
- case 'd': /* Specify draft level to run at */
- if ((*argp)[2] == '\0') {
- Draft = 0;
- break;
- }
- *argp += 2;
- Draft = atoi(*argp);
- break;
-
- case 'f': /* Ditroff bug: must flush before \X */
- XFlush = *argp + 2;
- if (strlen(XFlush) != 2) {
- XFlush = "ts";
- }
- break;
-
- case 't': /* disable compensation for psdit's line drawing */
- psditfix = FALSE;
- break;
-
- case 'b': /* use old bounding box comment search method */
- newbb = FALSE;
- break;
-
- case 'D': /* add directory to search list */
- if (++dircnt > MAXDIRS)
- error("too many search directories");
-
- searchDirTable[dircnt] = strsave((*argp)+2);
- break;
- default:
- error("bad flag");
- }
-
- argp++;
- }
-
- searchDirTable[dircnt + 1] = NULL;
-
- /*
- * If we are flushing \X with a character, make sure it doesn't get
- * printed.
- */
-
- if (XFlush != NULL) {
- printf(".tr \\(%s \n", XFlush);
- }
-
- /*
- * Now we process files. No arguments means standard input. Otherwise,
- * we just use the named files.
- */
-
- if (argc == 0) {
- doit();
- } else {
- while (argc-- > 0) {
- if (!freopen(*argp++, "r", stdin)) {
- perror("error opening input file");
- exit(1);
- } else {
- clearerr(stdin);
- doit();
- }
- }
- }
-
- exit(0);
- } /* main */
-
- doit() {
- char *ptr, *ptr1, *rest;
- char *getaline();
- static char buf[BUFSZ];
-
- while (getline(buf, sizeof(buf), stdin) != NULL) {
-
- if (!strncmp(buf, FGST, strlen(FGST))) {
- fputs(buf, stdout);
- *buf = 0;
- setInput(buf, getaline);
- if (dofigcmd()) {
- (void) fputc('\n', stdout);
- }
- (void) getline(buf, sizeof(buf), stdin);
- fputs(buf, stdout);
- continue;
- }
-
- ptr = rest = buf;
- while (delimSt && (ptr1 = index(ptr, delimSt))) {
- ptr = ptr1;
-
- *(ptr++) = '\0';
-
- fputs(rest, stdout);
-
- if (rest = index(ptr, delimEnd)) {
- *(rest++) = '\0';
- } else {
- error("Unbalanced delimiters");
- }
-
- ++inLineFlag;
- setInput(ptr, (char *(*)()) NULL);
- (void) dofigcmd();
- --inLineFlag;
- ptr = rest;
-
- }
- fputs(ptr, stdout);
- }
- }
-
- /*
- * getFileBB:
- *
- * Takes a file name and tries to find out what its bounding box is. If it
- * finds the info, it writes it into the four floats pointed to.
- */
-
- getFileBB(filenm, llx, lly, urx, ury)
- char *filenm;
- float *llx, *lly, *urx, *ury;
- {
- char *bbcomment = "%%BoundingBox:";
- char *atend = "(atend)";
- char *trailer = "%%Trailer";
- char *endcom = "%%EndComments";
- FILE *psfile;
- static char buf[BUFSZ];
- float tllx, tlly, turx, tury;
- int foundbb = FALSE;
- int intrailer = FALSE;
-
- if (!(psfile = fopen(filenm, "r"))) {
- (void) sprintf(errbuf, "error opening file `%s'", filenm);
- error(errbuf);
- }
-
- (void) fgets(buf, sizeof(buf), psfile);
- if (strncmp(buf, "%!", 2)) {
- (void) sprintf(errbuf, "`%s' not a postscript file", filenm);
- error(errbuf);
- }
-
-
-
- if (newbb)
- /*
- * Use full search for bb comment. Pays attention to
- * "%%EndComments", "(atend)", and "%%Trailer"
- */
-
- while (fgets(buf, sizeof(buf), psfile)) {
-
- /* If the first n chars of buf == %%BoundingBox: */
- if (!strncmp(buf, bbcomment, strlen(bbcomment))) {
- char *args = buf;
- args += strlen(bbcomment);
- while (*args == ' ') args++;
- if (!strncmp(args, atend, strlen(atend))) {
- /*
- * Scan for trailer section
- */
- intrailer = FALSE;
- while (fgets(buf, sizeof(buf), psfile))
- if (!strncmp(buf, trailer, strlen(trailer))) {
- intrailer = TRUE;
- break;
- }
- if (!intrailer) {
- sprintf(errbuf,
- "%%%%Trailer not found in %s", filenm);
- error(errbuf);
- break;
- }
- /*
- * Now that we've fouind the trailer
- * section, we can continue seaching from
- * the main while.
- */
- continue;
- }
-
- if (sscanf(args,"%f %f %f %f", &tllx, &tlly, &turx, &tury)
- == 4) {
- /*
- * We found a match, now if we are in the
- * header section we can leave straight away,
- * since the *first* bb comment is the
- * relevant one, but if we are in the trailer
- * we have to keep going, since the *last*
- * instance of a bb is the one we want to use.
- *
- * At least so says the Adobe book.
- */
- if (!intrailer) {
- *llx = tllx; *lly = tlly;
- *urx = turx; *ury = tury;
- foundbb = TRUE;
- fclose(psfile);
- return;
- } else {
- *llx = tllx; *lly = tlly;
- *urx = turx; *ury = tury;
- foundbb = TRUE;
- continue;
- }
-
- }
- (void) sprintf(errbuf,
- "malformed bounding box comment in %s", filenm);
- error(errbuf);
-
- } /* endif the first n chars match %%BoundingBox */
-
- /*
- * If the first two characters aren't %% or %!, or
- * if we reach %%EndComments, and we're not in the
- * trailer, then we're done.
- */
- if (intrailer) continue;
-
- if ((strncmp(buf, "%%", 2) && strncmp(buf, "%!", 2))
- || !strncmp(buf, endcom, strlen(endcom)))
- break;
- }
- else
- /*
- * Use old (simple) search for bb comment.
- */
-
- while (fgets(buf, sizeof(buf), psfile)) {
- if (sscanf(buf,"%%%%BoundingBox: %f %f %f %f",
- llx, lly, urx, ury) == 4) {
- fclose(psfile);
- return;
- }
- }
-
- if (foundbb) {
- fclose(psfile);
- return;
- }
-
- (void) sprintf(errbuf,"no bounding box found in %s",filenm);
- error(errbuf);
- }
-
- /*
- * abspath:
- *
- * Return the absolute expansion of a path, searching all the relevant
- * directories.
- */
-
- char *
- abspath(path)
- char *path;
- {
- static char pathbuf[SMBUFSZ];
- static char absbuf[SMBUFSZ];
- char **searchDir = searchDirTable;
-
- if (!*path) return path;
-
- if (*path != '/') {
- /*
- * path is relative, so attempt to locate file
- * in one of the search directories
- */
-
- do {
- strcpy(pathbuf, *searchDir);
- strcat(pathbuf, "/");
- strcat(pathbuf, path);
-
- if (access(pathbuf, F_OK) >= 0) {
- /*
- * Now that we know where the file is, we make
- * it absolute if necessary, and return it.
- */
-
- if (*pathbuf != '/') {
- getwd(absbuf);
- strcat(absbuf, "/");
- strcat(absbuf, pathbuf);
- return absbuf;
- } else {
- return pathbuf;
- }
- }
- } while (*(++searchDir));
-
- /*
- * the file was not found in any of the
- * search directories, so notify the user
- * and return the bare path
- */
-
- sprintf(errbuf, "`%s' not found in search directories", path);
- warn(errbuf);
- }
-
- return path;
- }
-
- /* end of main.c */
- @//E*O*F trf/src/main.c//
- chmod u=r,g=r,o=r trf/src/main.c
-
- echo x - trf/src/psfig.h
- sed 's/^@//' > "trf/src/psfig.h" <<'@//E*O*F trf/src/psfig.h//'
- /***
- *** psfig.h --
- ***
- *** Standard defines for psfig.
- ***
- *** T.Darrell, 3/86.
- ***/
-
- # include <stdio.h>
- # include <sys/file.h>
-
- # define TRUE 1
- # define FALSE 0
-
- # define UP 1
- # define DOWN 2
-
- # define MAXDIRS 12 /* max no. of search dirs */
-
- # define BUFSZ 1024
- # define SMBUFSZ 128
-
- # define FGST ".F+"
- # define FGEND ".F-"
-
- # define DraftDefault 100
- # define BrokenOutLevel 10
- # define InLineLevel 1
-
- # define endof(s) (s + strlen(s))
-
- extern Draft, linenumber, inLineFlag;
- extern psditfix;
- extern char delimSt, delimEnd;
- extern char *XFlush;
-
- extern char *Strcat(),
- *Strcpy(),
- *getline(),
- *includeFig(),
- *getLab(),
- *abspath(),
- *strsave();
-
- extern char *malloc(),
- *free(),
- *strcat(),
- *strcpy(),
- *strncpy(),
- *index();
-
- extern void pushBackItem(),
- setInput();
-
- /* end of psfig.h */
- @//E*O*F trf/src/psfig.h//
- chmod u=r,g=r,o=r trf/src/psfig.h
-
- echo x - trf/src/troff.c
- sed 's/^@//' > "trf/src/troff.c" <<'@//E*O*F trf/src/troff.c//'
- /***
- *** troff.c --
- ***
- *** Functions to output perverted Troff command strings for psfig.
- ***
- *** T.Darrell, 3/86.
- ***/
-
- # include "psfig.h"
-
- /*
- * Ditroff output format strings.
- */
-
- char saveSpaceDown_s[] = "\\x'%s'";
- char saveSpaceUp_s[] = "\\x'-(%s-\\n(.vu)'";
-
- saveSpaceV(y, sign)
- char *y;
- int sign;
- {
- if (sign == UP)
- printf(saveSpaceUp_s, y);
- else
- printf(saveSpaceDown_s, y);
- }
-
-
- char incl_file_s[] = "\\X'f%s'";
- includeFile(filenm)
- char *filenm; {
- printf(incl_file_s, filenm);
- }
-
- sIncludeFile(outbuf, filenm, len)
- int len;
- char *filenm; {
- sprintf(endof(outbuf), incl_file_s, filenm);
- if (strlen(outbuf) > len)
- error("buffer overflow");
- }
-
- char endfig_s[] = "\\X'pendFig'";
- endfig() {
- printf(endfig_s);
- }
-
- char startfig_s[] =
- "\\X'p\\w@\\h@%s@@'\\X'p\\w@\\h@%s@@'\\X'p%.2f'\\X'p%.2f'\\X'p%.2f'\\X'p%.2f'\\X'pstartFig'";
-
- startfig(x, y, llx, lly, urx, ury)
- char *x, *y;
- float llx, lly, urx, ury;
- {
- flushX();
- printf(startfig_s, x, y, llx, lly, urx, ury);
- }
-
- emitDoClip() {
- printf("\\X'pdoclip'");
- }
-
- flushX()
- {
- if (XFlush != NULL) {
- printf("\\z\\(%s", XFlush);
- }
- }
-
- char makeBoxDn_s_psditfix[] =
- "\\L'%s\\(br'\\v'+1p'\\l'%s\\(ul'\\v'-1p'\\L'-%s\\(br'\\v'+1p'\\l'-%s\\(ul'\\x'%s'\\v'-1p'";
- char makeBoxDn_s[] =
- "\\L'%s\\(br'\\l'%s\\(ul'\\L'-%s\\(br'\\l'-%s\\(ul'\\x'%s'";
-
- makeBox(x, y)
- char *x, *y;
- {
- if (psditfix)
- printf(makeBoxDn_s_psditfix, y, x, y, x, y);
- else
- printf(makeBoxDn_s, y, x, y, x, y);
-
- }
-
- char moveDown_s[] = "\\v'%s'";
-
- moveDown(y)
- char *y;
- {
- printf(moveDown_s, y);
- }
-
- char moveUp_s[] = "\\v'-%s'";
-
- moveUp(y)
- char *y;
- {
- printf(moveUp_s, y);
- }
-
- char draftNote_s[] = "\\v'1m'\\h'1n'%s\\h'-\\w'%s'u'\\h'-1n'\\v'-1m'";
-
- draftNote(filenm)
- char *filenm;
- {
- printf(draftNote_s, filenm, filenm);
- }
-
- char saveSpaceH_s[] = "\\h'%s'";
-
- saveSpaceH(x)
- char *x;
- {
- printf(saveSpaceH_s, x);
- }
-
- #define isWhite(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n')
-
- char literal_s[] = "\\X'p%s'";
- emitLiteral(text)
- char *text; {
- static char litbuf[BUFSZ];
-
- *litbuf = 0;
- sEmitLiteral(litbuf, text, sizeof(litbuf));
- fputs(litbuf, stdout);
- }
-
- sEmitLiteral(outbuf, text, len)
- int len;
- char *outbuf, *text; {
- char *ptr = text;
-
- /*
- * print each word of the literal (stuff separated by whitespace)
- * in a separate \X'p'
- */
-
- while (isWhite(*ptr)) ++ptr;
-
- /*
- * find delimiting character
- */
-
- while (*ptr) {
-
- /*
- * skip to next delimiting char.
- */
-
- for (text = ptr; *ptr && !isWhite(*ptr); ++ptr) ;
-
- /*
- * termainate string here, print this piece,
- * then repeat on the rest of the string.
- */
-
- if (!*ptr) {
- sprintf(endof(outbuf), literal_s, text);
- break;
- }
-
- *(ptr++) = 0;
- sprintf(endof(outbuf), literal_s, text);
-
- while (isWhite(*ptr)) ++ptr;
- }
-
- if (strlen(outbuf) > len)
- error("buffer overflow");
- }
-
-
- /* end of troff.c */
- @//E*O*F trf/src/troff.c//
- chmod u=r,g=r,o=r trf/src/troff.c
-
- echo Inspecting for damage in transit...
- temp=/tmp/shar$$; dtemp=/tmp/.shar$$
- trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
- cat > $temp <<\!!!
- 53 256 1687 README
- 23 69 421 Makefile
- 442 985 7906 cmds.c
- 299 876 4917 item.c
- 48 95 615 item.h
- 63 150 992 keywords.c
- 58 144 832 lineio.c
- 138 352 2043 macros.c
- 409 1239 8192 main.c
- 55 121 822 psfig.h
- 174 352 2825 troff.c
- 1762 4639 31252 total
- !!!
- wc trf/README trf/src/Makefile trf/src/cmds.c trf/src/item.c trf/src/item.h trf/src/keywords.c trf/src/lineio.c trf/src/macros.c trf/src/main.c trf/src/psfig.h trf/src/troff.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
- if [ -s $dtemp ]
- then echo "Ouch [diff of wc output]:" ; cat $dtemp
- else echo "No problems found."
- fi
- exit 0
-