Path: utzoo!utgpu!water!watmath!clyde!rutgers!husc6!bu-cs!madd From: madd@bu-cs.BU.EDU (Jim Frost) Newsgroups: comp.sys.ibm.pc Subject: proff (roff like formatter) part 1 of 3 Message-ID: <19779@bu-cs.BU.EDU> Date: 8 Feb 88 21:20:20 GMT Reply-To: madd@.UUCP (Jim Frost) Organization: Boston University Distributed Systems Group Lines: 2005 The following is part 1 of 3 of "proff" a roff-like text formatter that is somewhat more portable than most others. While it wasn't designed especially for IBM PC's, it should be portable enough to compile and run with virtually no changes. I haven't tried to do this so I could be wrong. I used this for quite some time; it works fine. A ms-like macro package is included, along with notes describing the package and the differences between it and the troff ms macro package. I'm posting this here in response to the multitude of responses that I got when I mentioned that I had this. It is in shar format. If you cannot accept shar format, please get in touch with me and I'll email you an ARC file. Enjoy, jim frost madd@bu-it.bu.edu -- cut here -- #! /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 Makefile <<'END_OF_Makefile' XCFLAGS=-O XOBJS= proff.o proff01.o proff02.o lookup.o pinit.o putwrd.o\ X pxlex.o pxxparse.o dostuff2.o eval.o stack.o map.o X X#S=-s Xproff: $(OBJS) X cc $(CFLAGS) $S -o proff $(OBJS) X X$(OBJS): lextab.h lextab.d X Xlextab.h lextab.d: proffsym.new ltb X ltb proffsym.new lextab X Xltb: ltb.o look.o X cc $S -o ltb ltb.o look.o Xclean: X rm proff *.o Xarch: X ./archc Makefile *.c *.h proffsym.new >proff.arc END_OF_Makefile if test 393 -ne `wc -c NOTE <<'END_OF_NOTE' XArticle 1438 of net.sources: XRelay-Version: version B 2.10.1 6/24/83; site bu-cs.UUCP XPosting-Version: version B 2.10.2 9/5/84; site yetti.UUCP XPath: bu-cs!harvard!talcott!panda!genrad!decvax!decwrl!amdcad!amd!pesnta!lsuc!mnetor!yetti!oz XFrom: oz@yetti.UUCP (Ozan Yigit) XNewsgroups: net.sources XSubject: notes on PROFF - Portable ROFF XMessage-ID: <305@yetti.UUCP> XDate: Wed, 15-Jan-86 10:25:59 EST XDate-Received: Fri, 17-Jan-86 02:33:23 EST XReply-To: oz@yetti.UUCP (Ozan Yigit) XOrganization: York University Computer Science XLines: 47 XKeywords: PROFF, ROFF, formatting X XSome notes on PROFF: X X There is a naming clash in PROFF, which is a easy X to fix, and if you ever want to use it under UN*X, X [now why would you ever want to do such a thing ??] X it MUST be fixed: PROFF uses an internal routine X called brk, to introduce line break. This clashes with X unix brk. Even if the loader did not throw up, you can X never be sure things will be ok. The name is used X in about three places throughout the source. X X There are some compiler warnings. May or may not be X serious, depending on the system. X X The routine that converts numbers to roman numerals X should be replaced with something simpler. X X Performance improvements: This thing could be speeded X up by 20%, by diddling the code carefully, and getting X rid of ratfor-to-c-conversion remnants. X X Bolding should be done a la RUNOFF: X write a line X carriage return X overprint line X This would mean a major overhaul of the routines that X handle line preperation for output. May well worth it. X X Macros should include some sort of conditional. That would X make it much more powerful. X X A temporary I/O a la m4 divert/undivert would be really X handy. After using the formatter for about year-and-a-half, X that is what most users found to be a necessity. This would X also facilititate, with some further diddling, some sort X of footnote mechanism. X X If you want to hack it seriously, please contact me for X further notes/ideas etc. Some commented-out entries X in proffsym.new indicates couple of things I had in mind. X XOz X-- XUsenet: [decvax|allegra|linus|ihnp4]!utzoo!yetti!oz XBitnet: oz@[yusol|yuyetti] X In the beginning, there was Word all right, except X it wasn't fixed number of bits. X X END_OF_NOTE if test 2245 -ne `wc -c READ_ME <<'END_OF_READ_ME' XProff - A portable formatter X XThis is the first distribution of PROFF, a formatter based Xon software tools ROFF. It is mainly a C re-write of ROFF, X(now known as FORMAT), with some expansions. It is mainly Xintended for non-UN*X systems, CP/M, MS-DOS and the like. X XProff was originally written for The Faculty of Administrative XStudies, York University, to supplement their microcomputer Xenvironment. As of this release, the formatter is in the Xcontrol of The Faculty of Administrative Studies. X XThere is no man page for proff, for it was never intended Xfor UN*X systems. There is, however two comprehensive Xdocuments to answer all questions. X XThe C code for PROFF is quite warped, and should be approached Xcarefully. [Ok..Ok.. it is all my fault.. too much midnight Xoil..] It is reasonably customazible, by changing proffsym.new. XThis file is processed by ltb, a static hash table generator. XThis approach is most useful to change the operator keywords, Xcreate aliases, and it also bypassess the initialization Xoverhead. [see the makefile for the right output file names Xfor ltb] X XPROFF is not copyrighted, at least for this release. Future Xreleases may contain York University copyright. X XPlease send me all updates, bugfixes and other tidbits, Xso that future releases may be coordinated smoothly. X Xenjoy. X oz X bitnet: oz@yuyetti X oz@yusol X usenet: {ihnp4|decvax|allegra|linus}!utzoo!yetti!oz X phonet: (416) 667 3976 X END_OF_READ_ME if test 1426 -ne `wc -c debug.h <<'END_OF_debug.h' X X X X/* X#define DEBUG X#define PROFILE X*/ X X#ifdef PROFILE X#define dprintf(str) printf((str)); X#else X#define dprintf(str) X#endif X END_OF_debug.h if test 126 -ne `wc -c defs.h <<'END_OF_defs.h' X X/* X * defs.h X * X * #define rainbow - rainbow CP/M-86 version X * #define vms - vms version (predefined by VAX11C compiler) X * #define unix - unix version X */ X X/* X * Synonyms for ASCII control characters X * X */ X X#define BACKSPACE 8 X#define BEL 7 X#define BELL 7 X#define BLANK 32 X#define CARRIAGE_RETURN 13 X#define NEWLINE 10 X#define RUBOUT 127 X#define TAB 9 X X/* X * misc. definitions X * X */ X X#define EOS 0 X#define HUGE 30000 X#define NO 0 X#define OK 0 X#define YES 1 X#define FALSE 0 X#define TRUE 1 X#define FILENAMESIZE 50 X#define MAXCHARS 20 X#define MAXLINE 256 X#define MAXTOK 80 X#define ARB MAXLINE X X#define MAXCARD MAXLINE-1 X#define MAXNAME FILENAMESIZE X X#define NCHARS 33 X#define MAXOFILES 12 X X#define ARGFLAG '$' X#define INSIZE MAXLINE X#define MAXOUT 2*MAXLINE X#define MAXDEF 200 X#define NFILES MAXOFILES-4 X#define PAGENUM '#' X#define CURRENTDATE '%' X#define ESCAPE '@' X#define VESCAPE '$' X#define PAGEJECT 12 /* 12 is ASCII formfeed (control-L) */ X#define PAGEWIDTH 65 X#define PAGELEN 62 X#define BUFSIZE 512 /* push back buffer */ X/* X * lexical analyser values X * X * include lexical analyser return constants X * generated by ltb. X * X */ X#include "lextab.d" /* expended format & roff & runoff */ X X#define UNKNOWN 999 X#define MACRO 0 X#define NEGATED -1 X#define LEFT 1 X#define CENTER 2 X#define RIGHT 3 X X/* X * structure definition for contents linked list X * X */ X Xstruct clist { /* list struct for contents */ X char level; X char *str; X int page; X struct clist *nextc; X}; X X#undef putchar X#define putchar(c) putc((c),poutput); X END_OF_defs.h if test 1580 -ne `wc -c dostuff2.c <<'END_OF_dostuff2.c' X X X X X#include X#include X#include "proff.h" X#include "debug.h" X X/* X * dodef - define a command macro (".de xx" is in buf.) X * X */ Xdodef(buf,fd) Xchar buf[]; Xint fd; X{ X char name[MAXNAME],defn[MAXDEF]; X int i,junk; X X dprintf("dodef "); X i = 0; X junk = getwrd(buf, &i, name); X i = getwrd(buf, &i, name); /* get the name */ X if (i == 0) X error("missing name in command def."); X i = 0; X while (ngetln(buf,fd) != NULL) { X if (buf[0] == cchar && buf[1] == 'e' && X buf[2] == 'n' && !isalnum(buf[3])) X break; X junk = addstr(buf, defn, &i, MAXDEF); X } X if (addset(EOS, defn, &i, MAXDEF) == NO) X error("definition too long.\n"); X if (install(name, defn, macrotab) == NULL) X fprintf(stderr,"no room for new definition.\n"); X#ifdef DEBUG X printf("dodef: %s (name) %s (defn)\n",name,defn); X#endif X} X X/* X * doesc - expand escapes in buf X * X */ Xdoesc(buf, tbuf, size) Xchar buf[]; Xchar tbuf[]; Xint size; X{ X int i,j; X X dprintf("doesc "); X j = 0; X for (i = 0; buf[i] != EOS && j < size-1; i++) X /* X * clean up generic escapes along the way. X */ X if (buf[i] == genesc) X tbuf[j++] = buf[++i]; X X else if (buf[i] != ESCAPE) { X tbuf[j] = buf[i]; X j++; X } X else if (buf[i+1] == 'n' && X (buf[i+2] >= 'a' && buf[i+2] <= 'z')) { X j += itoc(nr[buf[i+2] - 'a'], X &tbuf[j], size - j - 1); X i += 2; X } X else { X tbuf[j] = buf[i]; X j++; X } X tbuf[j] = EOS; X strcpy(buf, tbuf); X} X X/* X * dovar - expand variables in buf X * X */ Xdovar(tbuf, buf) Xchar *buf; Xchar *tbuf; X{ X register char *c, *p, t; X struct hashlist *xp; X X while (*buf != '\0') { X if (*buf == genesc) { X *tbuf++ = *buf++; X *tbuf++ = *buf; X } X else if (*buf != VESCAPE) X *tbuf++ = *buf; X else { X buf++; /* skip the ESCAPE */ X if (*buf == '{') X buf++; X p = buf; /* save the beginning address of variable */ X while (isalnum(*buf)) X buf++; X t = *buf; /* save the character*/ X *buf = '\0'; /* hack a null there */ X if ((xp = lookup(p,gentab)) != NULL) { X c = xp->def; /* point to def */ X while (*c != '\0') X *tbuf++ = *c++; X } X if (*(p-1) != '{') X *tbuf++ = t; X else if (t != '}') X fprintf(stderr, "missing \"}\" in %s\n",p); X } X buf++; X } X *tbuf = '\0'; X} X X X/* X * dotabs - expand tabs in buf X * X */ Xdotabs(buf,tbuf,size) Xchar buf[]; Xchar tbuf[]; Xint size; X{ X int i,j; X dprintf("dotabs "); X X j = 0; X for (i = 0; buf[i] != EOS && j < size - 1; i++) X if (buf[i] == '\t') X while (j < size - 1) { X tbuf[j] = ' '; X j++; X if (tabs[j] == YES || j > INSIZE) X break; X } X else { X tbuf[j] = buf[i]; X j++; X } X tbuf[j] = EOS; X strcpy(buf, tbuf); X} X X/* X * docline - produce a "contents" line. X * X */ Xdocline(str,width,cline,page) Xchar *str; Xint width; Xchar *cline; Xint page; X{ X int i; X X for (i = 0; i < width - 6 && cline[i] != '\0'; i++) X str[i] = cline[i]; X while (i < width - 6) X str[i++] = '.'; X sprintf(str+i,"%5d\n",page); X} X END_OF_dostuff2.c if test 2884 -ne `wc -c eval.c <<'END_OF_eval.c' X X X#include X#include X#include "proff.h" X#include "debug.h" X X X/* X * eval - evaluate defined command (push back definition) X * X */ Xeval(buf,defn) Xchar buf[]; Xchar defn[]; X{ X register int j,k; X int i; X int argptr[10]; X X for (i = 0; i < 10 ; i++) X argptr[i] = 0; X X buf[0] = '\0'; /* buf[0] is cchar */ X dprintf(defn); X dprintf("eval "); X i = 1; X argptr[0] = 1; /* first parm is macro name */ X while (buf[i] != ' ' && buf[i] != '\t' && X buf[i] != '\n' && buf[i] != '\0') X i++; X buf[i++] = '\0'; /* EOS terminate */ X /* X * start scanning remaining macro parameters. X * delimiters are blanks or commas. Any string X * enclosed with double quotes are accepted as X * parameters as well X * X */ X for (j = 1; j < 10; j++) { X skipbl(buf, &i); X if (buf[i] == '\n' || buf[i] == '\0') X break; X argptr[j] = i; X while (buf[i] != ' ' && buf[i] != '\t' && X buf[i] != ',' && buf[i] != '\n' && buf[i] != '\0') X i++; X buf[i] = '\0'; X i++; X } X for (k = strlen(defn) - 1; k >= 0; k--) X if (defn[k-1] != ARGFLAG) X putbak(defn[k]); X else { X if (defn[k] < '0' || defn[k] > '9') X putbak(defn[k]); X else { X i = defn[k] - '0'; X i = argptr[i]; X pbstr(&buf[i]); X k--; /* skip over $ */ X } X } X if (k = 0) /* do the last character */ X putbak(defn[k]); X} X END_OF_eval.c if test 1298 -ne `wc -c lextab.d <<'END_OF_lextab.d' X#define DBO 5 X#define EBO 7 X#define NAP 101 X#define NPA 13 X#define GET 95 X#define PGI 11 X#define M1 45 X#define M2 47 X#define M3 49 X#define ELT 109 X#define M4 51 X#define LEX 89 X#define SAV 85 X#define CC 19 X#define BD 3 X#define SET 93 X#define EC 27 X#define CE 21 X#define DE 25 X#define EF 29 X#define HE 37 X#define EH 31 X#define LTR 107 X#define CL 103 X#define FI 33 X#define IG 91 X#define AP 99 X#define BP 9 X#define PC 105 X#define NE 53 X#define OE 63 X#define NF 55 X#define BR 15 X#define RST 87 X#define OF 65 X#define FO 35 X#define BS 17 X#define OH 67 X#define IN 39 X#define NJ 57 X#define CU 23 X#define PL 69 X#define TI 81 X#define PN 97 X#define RM 73 X#define PO 71 X#define LS 43 X#define JU 41 X#define NR 59 X#define UL 83 X#define SO 75 X#define SP 77 X#define OU 61 X#define ST 79 X#define WR 111 X#define RESET 1 END_OF_lextab.d if test 856 -ne `wc -c lextab.h <<'END_OF_lextab.h' X#ifndef STRUC_DEFINED X X/* lextab.h */ X Xstruct _lex_h { char *__s; X int __v; X int __f; X struct _lex_h *__l; X}; X X#define STRUC_DEFINED X#endif Xstruct X_lex_h __ce = { "ce", X 21, 0,NULL }; Xstruct X_lex_h __ec = { "ec", X 27, 0,&__ce }; Xstruct X_lex_h __de = { "de", X 25, 0,NULL }; Xstruct X_lex_h __f = { "f", X 33, 1,NULL }; Xstruct X_lex_h __ef = { "ef", X 29, 0,NULL }; Xstruct X_lex_h __nojustify = { "nojustify", X 57, 0,&__ef }; Xstruct X_lex_h __eh = { "eh", X 31, 0,NULL }; Xstruct X_lex_h __he = { "he", X 37, 0,&__eh }; Xstruct X_lex_h __j = { "j", X 41, 1,NULL }; Xstruct X_lex_h __fi = { "fi", X 33, 0,NULL }; Xstruct X_lex_h __na = { "na", X 99, 0,&__fi }; Xstruct X_lex_h __cl = { "cl", X 103, 0,&__na }; Xstruct X_lex_h __ig = { "ig", X 91, 0,NULL }; Xstruct X_lex_h __dbo = { "dbo", X 5, 1,NULL }; Xstruct X_lex_h __pa = { "pa", X 11, 1,&__dbo }; Xstruct X_lex_h __ap = { "ap", X 99, 1,&__pa }; Xstruct X_lex_h __el = { "el", X 109, 1,&__ap }; Xstruct X_lex_h __ebo = { "ebo", X 7, 1,NULL }; Xstruct X_lex_h __bp = { "bp", X 9, 0,&__ebo }; Xstruct X_lex_h __ne = { "ne", X 53, 0,NULL }; Xstruct X_lex_h __pc = { "pc", X 105, 0,&__ne }; Xstruct X_lex_h __br = { "br", X 15, 1,NULL }; Xstruct X_lex_h __need = { "need", X 53, 0,&__br }; Xstruct X_lex_h __nf = { "nf", X 55, 1,&__need }; Xstruct X_lex_h __oe = { "oe", X 63, 0,&__nf }; Xstruct X_lex_h __noautoparagraph = { "noautoparagraph", X 101, 1,&__oe }; Xstruct X_lex_h __page = { "page", X 9, 1,NULL }; Xstruct X_lex_h __bs = { "bs", X 17, 0,&__page }; Xstruct X_lex_h __cchar = { "cchar", X 19, 0,&__bs }; Xstruct X_lex_h __fo = { "fo", X 35, 0,&__cchar }; Xstruct X_lex_h __of = { "of", X 65, 0,&__fo }; Xstruct X_lex_h __pg = { "pg", X 9, 1,NULL }; Xstruct X_lex_h __echar = { "echar", X 27, 0,&__pg }; Xstruct X_lex_h __in = { "in", X 39, 0,&__echar }; Xstruct X_lex_h __oh = { "oh", X 67, 0,&__in }; Xstruct X_lex_h __s = { "s", X 77, 1,&__oh }; Xstruct X_lex_h __cu = { "cu", X 23, 0,NULL }; Xstruct X_lex_h __nj = { "nj", X 57, 1,&__cu }; Xstruct X_lex_h __bold = { "bold", X 3, 0,NULL }; Xstruct X_lex_h __break = { "break", X 15, 1,&__bold }; Xstruct X_lex_h __header = { "header", X 37, 0,&__break }; Xstruct X_lex_h __lm = { "lm", X 39, 1,&__header }; Xstruct X_lex_h __define = { "define", X 25, 0,NULL }; Xstruct X_lex_h __nap = { "nap", X 101, 1,&__define }; Xstruct X_lex_h __pl = { "pl", X 69, 0,NULL }; Xstruct X_lex_h __get = { "get", X 95, 0,&__pl }; Xstruct X_lex_h __ti = { "ti", X 81, 0,NULL }; Xstruct X_lex_h __vg = { "vg", X 95, 0,&__ti }; Xstruct X_lex_h __np = { "np", X 13, 0,NULL }; Xstruct X_lex_h __pn = { "pn", X 97, 0,&__np }; Xstruct X_lex_h __fill = { "fill", X 33, 1,NULL }; Xstruct X_lex_h __ju = { "ju", X 41, 0,&__fill }; Xstruct X_lex_h __ls = { "ls", X 43, 0,&__ju }; Xstruct X_lex_h __po = { "po", X 71, 0,&__ls }; Xstruct X_lex_h __rm = { "rm", X 73, 1,&__po }; Xstruct X_lex_h __nr = { "nr", X 59, 0,NULL }; Xstruct X_lex_h __lt = { "lt", X 107, 1,&__nr }; Xstruct X_lex_h __ul = { "ul", X 83, 0,NULL }; Xstruct X_lex_h __spc = { "spc", X 43, 1,NULL }; Xstruct X_lex_h __so = { "so", X 75, 0,&__spc }; Xstruct X_lex_h __ps = { "ps", X 69, 1,NULL }; Xstruct X_lex_h __sp = { "sp", X 77, 0,&__ps }; Xstruct X_lex_h __left = { "left", X 81, 1,&__sp }; Xstruct X_lex_h __tp = { "tp", X 53, 1,NULL }; Xstruct X_lex_h __ou = { "ou", X 61, 0,&__tp }; Xstruct X_lex_h __req = { "req", X 75, 1,&__ou }; Xstruct X_lex_h __lx = { "lx", X 89, 0,&__req }; Xstruct X_lex_h __rs = { "rs", X 87, 0,NULL }; Xstruct X_lex_h __lex = { "lex", X 89, 0,&__rs }; Xstruct X_lex_h __paging = { "paging", X 11, 1,NULL }; Xstruct X_lex_h __st = { "st", X 79, 0,NULL }; Xstruct X_lex_h __save = { "save", X 85, 0,&__st }; Xstruct X_lex_h __set = { "set", X 93, 0,NULL }; Xstruct X_lex_h __sv = { "sv", X 85, 0,NULL }; Xstruct X_lex_h __vs = { "vs", X 93, 0,&__sv }; Xstruct X_lex_h __wr = { "wr", X 111, 0,&__vs }; Xstruct X_lex_h __skip = { "skip", X 77, 1,NULL }; Xstruct X_lex_h __include = { "include", X 75, 0,NULL }; Xstruct X_lex_h __center = { "center", X 21, 0,NULL }; Xstruct X_lex_h __spacing = { "spacing", X 43, 1,&__center }; Xstruct X_lex_h __nofill = { "nofill", X 55, 0,NULL }; Xstruct X_lex_h __ignore = { "ignore", X 91, 0,&__nofill }; Xstruct X_lex_h __reset = { "reset", X 1, 0,NULL }; Xstruct X_lex_h __offset = { "offset", X 71, 0,&__reset }; Xstruct X_lex_h __literal = { "literal", X 107, 1,NULL }; Xstruct X_lex_h __enablebolding = { "enablebolding", X 7, 1,NULL }; Xstruct X_lex_h __nopaging = { "nopaging", X 13, 1,NULL }; Xstruct X_lex_h __footer = { "footer", X 35, 0,NULL }; Xstruct X_lex_h __outend = { "outend", X 63, 0,&__footer }; Xstruct X_lex_h __write = { "write", X 111, 0,&__outend }; Xstruct X_lex_h __pagesize = { "pagesize", X 69, 1,NULL }; Xstruct X_lex_h __source = { "source", X 75, 0,NULL }; Xstruct X_lex_h __m1 = { "m1", X 45, 0,NULL }; Xstruct X_lex_h __disablebolding = { "disablebolding", X 5, 1,NULL }; Xstruct X_lex_h __m2 = { "m2", X 47, 0,&__disablebolding }; Xstruct X_lex_h __m3 = { "m3", X 49, 0,NULL }; Xstruct X_lex_h __contline = { "contline", X 103, 0,&__m3 }; Xstruct X_lex_h __endliteral = { "endliteral", X 109, 1,&__contline }; Xstruct X_lex_h __m4 = { "m4", X 51, 0,NULL }; Xstruct X_lex_h __testpage = { "testpage", X 53, 1,&__m4 }; Xstruct X_lex_h __pagenumber = { "pagenumber", X 97, 0,NULL }; Xstruct X_lex_h __leftmargin = { "leftmargin", X 39, 1,NULL }; Xstruct X_lex_h __require = { "require", X 75, 1,&__leftmargin }; Xstruct X_lex_h __skipto = { "skipto", X 79, 0,NULL }; Xstruct X_lex_h __underline = { "underline", X 83, 0,&__skipto }; Xstruct X_lex_h __restore = { "restore", X 87, 0,NULL }; Xstruct X_lex_h __rightmargin = { "rightmargin", X 73, 1,NULL }; Xstruct X_lex_h __justify = { "justify", X 41, 1,NULL }; Xstruct X_lex_h __output = { "output", X 61, 0,NULL }; Xstruct X_lex_h __autoparagraph = { "autoparagraph", X 99, 1,NULL }; Xstruct X_lex_h __printcont = { "printcont", X 105, 0,NULL }; Xstruct X_lex_h __bd = { "bd", X 3, 0,NULL }; Xstruct X_lex_h __db = { "db", X 5, 0,&__bd }; Xstruct X_lex_h __cc = { "cc", X 19, 0,&__db }; Xstruct X_lex_h __eb = { "eb", X 7, 0,NULL }; X X X/* Hash Table */ X Xstruct _lex_h *lextab[100] = { X &__ec, X &__de, &__f, &__nojustify, NULL, X &__he, &__j, &__cl, &__ig, X &__el, &__bp, &__pc, &__noautoparagraph, X &__of, NULL, &__s, &__nj, X &__lm, NULL, &__nap, &__get, X &__vg, &__pn, &__rm, &__lt, X &__ul, &__so, &__left, &__lx, X &__lex, &__paging, &__save, &__set, X &__wr, NULL, NULL, NULL, X NULL, NULL, &__skip, &__include, X &__spacing, NULL, NULL, &__ignore, X NULL, NULL, &__offset, NULL, X &__literal, &__enablebolding, &__nopaging, NULL, X NULL, NULL, &__write, &__pagesize, X &__source, &__m1, &__m2, &__endliteral, X &__testpage, &__pagenumber, NULL, NULL, X &__require, &__underline, NULL, NULL, X NULL, NULL, NULL, &__restore, X NULL, NULL, NULL, NULL, X NULL, NULL, NULL, &__rightmargin, X NULL, &__justify, NULL, NULL, X NULL, NULL, NULL, NULL, X &__output, NULL, &__autoparagraph, NULL, X &__printcont, NULL, NULL, NULL, X NULL, &__cc, &__eb }; END_OF_lextab.h if test 9281 -ne `wc -c look.c <<'END_OF_look.c' X X X X X/* X * from K&R "The C Programming language" X * Table lookup routines X * X */ X#include X#include "lookup.h" X/* X * hash - for a hash value for string s X * X */ Xhash(s) Xchar *s; X{ X int hashval; X X for (hashval = 0; *s != '\0';) X hashval += *s++; X return (hashval % HASHMAX); X} X X/* X * lookup - lookup for a string s in the hash table X * X */ Xstruct hashlist X*lookup(s, hashtab) Xchar *s; Xstruct hashlist *hashtab[]; X{ X struct hashlist *np; X X for (np = hashtab[hash(s)]; np != NULL; np = np->next) X if (strcmp(s, np->name) == 0) X return(np); /* found */ X return(NULL); /* not found */ X} X X/* X * install - install a string name in hashtable and its value def X * at a given hashtable. X */ Xstruct hashlist X*install(name,def,hashtab) Xchar *name; Xchar *def; Xstruct hashlist *hashtab[]; X{ X int hashval; X struct hashlist *np, *lookup(); X char *strsave(), *malloc(); X X if ((np = lookup(name, hashtab)) == NULL) { /* not found.. */ X np = (struct hashlist *) malloc(sizeof(*np)); X if (np == NULL) X return(NULL); X if ((np->name = strsave(name)) == NULL) X return(NULL); X hashval = hash(np->name); X np->next = hashtab[hashval]; X hashtab[hashval] = np; X } else /* found.. */ X free(np->def); /* free prev. */ X if ((np->def = strsave(def)) == NULL) X return(NULL); X return(np); X} X X/* X * strsave - save string s somewhere X * X */ Xchar X*strsave(s) Xchar *s; X{ X char *p, *malloc(); X register int n; X X n = strlen(s) + 1; X if ((p = malloc(n)) != NULL) X strcpy(p, s); X return(p); X} X X/* X * lexinstal - instal a string name in hashtable and its value X * used by lexical analyser to quickly match a token X * and return its lexical value. X * X */ Xstruct lexlist X*lexinstal(name,val,flag,lextable) Xchar *name; Xint val; Xint flag; Xstruct lexlist *lextable[]; X{ X int hashval; X struct lexlist *np,*lexlook(); X char *strsave(), *malloc(); X X if ((np = lexlook(name,lextable)) == NULL) { /* not found.. */ X np = (struct lexlist *) malloc(sizeof(*np)); X if (np == NULL) X return(NULL); X if ((np->name = strsave(name)) == NULL) X return(NULL); X hashval = hash(np->name); X np->link = lextable[hashval]; X lextable[hashval] = np; X } X np->val = val; /* replace prev */ X np->flag = flag; X return(np); X} X X/* X * lexlook - lookup for a string s in the hash table X * used by lexinstal only. X * X */ Xstruct lexlist X*lexlook(s,table) Xchar *s; Xstruct lexlist *table[]; X{ X struct lexlist *np; X X for (np = table[hash(s)]; np != NULL; np = np->link) X if (strcmp(s, np->name) == 0) X return(np); /* found */ X return(NULL); /* not found */ X} X X/* X * remove an item from the hash table forever X * X */ Xstruct lexlist X*remove(s, table) Xchar *s; Xstruct lexlist *table[]; X{ X struct lexlist *np, *xp; X X np = table[hash(s)]; X xp = np; X while (np != NULL) { X if (strcmp(s, np->name) == 0) { X xp->link = np->link; /* remove the link */ X return(np); /* return the lost */ X } X xp = np; X np = np->link; X } X return(NULL); X} X END_OF_look.c if test 2939 -ne `wc -c lookup.c <<'END_OF_lookup.c' X X X X X/* X * from K&R "The C Programming language" X * Table lookup routines X * X */ X#include X#include "proff.h" X/* X * hash - for a hash value for string s X * X */ Xhash(s) Xchar *s; X{ X int hashval; X X for (hashval = 0; *s != '\0';) X hashval += *s++; X return (hashval % HASHMAX); X} X X/* X * lookup - lookup for a string s in the hash table X * X */ Xstruct hashlist X*lookup(s, hashtab) Xchar *s; Xstruct hashlist *hashtab[]; X{ X struct hashlist *np; X X for (np = hashtab[hash(s)]; np != NULL; np = np->next) X if (strcmp(s, np->name) == 0) X return(np); /* found */ X return(NULL); /* not found */ X} X X/* X * install - install a string name in hashtable and its value def X * at a given hashtable. X */ Xstruct hashlist X*install(name,def,hashtab) Xchar *name; Xchar *def; Xstruct hashlist *hashtab[]; X{ X int hashval; X struct hashlist *np, *lookup(); X char *strsave(), *malloc(); X X if ((np = lookup(name, hashtab)) == NULL) { /* not found.. */ X np = (struct hashlist *) malloc(sizeof(*np)); X p_memoryus += sizeof(*np); X if (np == NULL) X return(NULL); X if ((np->name = strsave(name)) == NULL) X return(NULL); X hashval = hash(np->name); X np->next = hashtab[hashval]; X hashtab[hashval] = np; X } else /* found.. */ X free(np->def); /* free prev. */ X if ((np->def = strsave(def)) == NULL) X return(NULL); X return(np); X} X X/* X * strsave - save string s somewhere X * X */ Xchar X*strsave(s) Xchar *s; X{ X char *p, *malloc(); X register int n; X X n = strlen(s) + 1; X if ((p = malloc(n)) != NULL) { X p_memoryus += n; X strcpy(p, s); X } X return(p); X} X X/* X * lexinstal - instal a string name in hashtable and its value X * used by lexical analyser to quickly match a token X * and return its lexical value. X * X */ Xstruct lexlist X*lexinstal(name,val,flag,lextable) Xchar *name; Xint val; Xint flag; Xstruct lexlist *lextable[]; X{ X int hashval; X struct lexlist *np,*lexlook(); X char *strsave(), *malloc(); X X if ((np = lexlook(name,lextable)) == NULL) { /* not found.. */ X np = (struct lexlist *) malloc(sizeof(*np)); X p_memoryus += sizeof(*np); X if (np == NULL) X return(NULL); X if ((np->name = strsave(name)) == NULL) X return(NULL); X hashval = hash(np->name); X np->link = lextable[hashval]; X lextable[hashval] = np; X } X np->val = val; /* replace prev */ X np->flag = flag; X return(np); X} X X/* X * lexlook - lookup for a string s in the hash table X * used by lexinstal only. X * X */ Xstruct lexlist X*lexlook(s,table) Xchar *s; Xstruct lexlist *table[]; X{ X struct lexlist *np; X X for (np = table[hash(s)]; np != NULL; np = np->link) X if (strcmp(s, np->name) == 0) X return(np); /* found */ X return(NULL); /* not found */ X} X X/* X * remove an item from the hash table forever X * X */ Xstruct lexlist X*remove(s, table) Xchar *s; Xstruct lexlist *table[]; X{ X struct lexlist *np, *xp; X X np = table[hash(s)]; X xp = np; X while (np != NULL) { X if (strcmp(s, np->name) == 0) { X xp->link = np->link; /* remove the link */ X return(np); /* return the lost */ X } X xp = np; X np = np->link; X } X return(NULL); X} X END_OF_lookup.c if test 3017 -ne `wc -c lookup.h <<'END_OF_lookup.h' X X X X/* X * from K&R "The C Programming language" X * Table lookup routines X * structure and definitions X * X */ X X /* basic table entry */ Xstruct hashlist { X char *name; X char *def; X struct hashlist *next; /* next in chain */ X}; X /* basic table entry */ Xstruct lexlist { X char *name; X int val; /* lexical value */ X int flag; /* optional flag val */ X struct lexlist *link; /* next in chain */ X}; X X X#define HASHMAX 100 /* size of hashtable */ X Xstruct Xlexlist (*(*lextable))[];/* global pointer for lexical analyser hash table */ X END_OF_lookup.h if test 553 -ne `wc -c ltb.c <<'END_OF_ltb.c' X/* X * ltb.c - Lexical Table Builder X * X * Functional description: X * X * This program builds a file containing the data X * structures of a compile-time-initialised hash table. X * This hash table may later be used for lexical analysis, X * where number of symbols to look up is sufficiently large X * to avoid a run-time table initialization. X * In order to guarantee the success of this setup, the X * hash routine, the lookup and install routines should be X * the same between ltb and the lexical analysis. X * X * synopsis: X * X * ltb [table name] X * X * input file format: X * X * [flag value] X * X * token: string of alphanumeric characters to be X * matched by the lexical analyser (no blanks). X * these token strings are "installed" to a hash X * table by ltb to avoid run-time overhead. X * value X * identifier: A constant name to be used internally by the X * lexical analyser in place of the actual X * token value. a "#define " X * is generated for each value identifier, where X * value is an odd and unique integer constant. If X * the value identifier is a `*' (star), then the X * previous value is repeated. Thus: X * X * token ident. flag X * X * sp SP 1 X * space * { inherits SP } X * blank * { inherits SP } X * . . . X * . . . X * X * flag value: An additional integer field to pass flags etc. to X * the lexical analyser. If not specified, set to X * 0. token value field must be present for this field X * to be obtained. X * X * outputs: X * X * ltb generates two C include files: X * X * [tablename].d: compile time lexical constants (defines) X * [tablename].h: initialised hash table. X * X * where [tablename] is the name of the hash table as specified X * in the command line of ltb. If not specified, "lextab" is used X * as a default. X * X * routines used by LTB: X * X * hash, lookup and a modified version of install routines, X * as defined in K&R, pp. 134 - 136. X * X * Application areas: X * X * Lexical analysers for compilers, interpreters, spelling X * checkers. X * X * Author: X * Ozan S. Yigit X * Dept. of Computer Science X * York University X * X */ X X#define MAXLINE 80 X#define MAXSYM 80 X X#include X#include X#include "lookup.h" X Xstatic struct lexlist *hashtab[HASHMAX]; Xstatic struct lexlist *defitab[HASHMAX]; X Xchar *tabnam; /* table name */ X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X FILE *fp; X char line[MAXLINE]; X char sym[MAXSYM],def[MAXSYM]; X register int val; X register int prev, *p; X register char *ptr; X int flag; X struct lexlist *np, *lexlook(); X X if (argc <= 2) { X fprintf(stderr,"%s [-] [tablename]", X argv[0]); X exit(1); X } X X if (*argv[1] == '-') { X val = atoi(argv[1]+1); /* skip "-" and convert */ X val = (val & 1) ? val : val+1; X p = argv[2]; X } X else { X val = 1; X p = argv[1]; X } X X if (argc < 3) X tabnam = "lextab"; X else X tabnam = argv[argc-1]; X X if ((fp = fopen(p,"r")) == NULL) { X fprintf(stderr,"%s:cannot open.\n",argv[1]); X exit(1); X } X else { X prev = val; X while (fgets(line,MAXLINE,fp) != NULL) { X if (*line != '!') { X flag = 0; X def[0] = '\0'; X ptr = line; X while (isspace(*ptr)) X ptr++; X if (*ptr == '\0') X continue; X sscanf(line,"%s %s %d",sym,def,&flag); X if (!(def[0] == '*' && def[1] == '\0')) { X if ((np = lexlook(def,defitab)) == NULL) { X /* value define */ X lexinstal(def,val,0,defitab); X prev = val; X val += 2; X } X else X prev = np->val; X } X /* lexical token */ X lexinstal(sym,prev,flag,hashtab); X } X } X defgen(); X lexgen(); X } X} X/* X * lexgen - print out the hash table in static form X * X */ Xlexgen() X{ X register int i; X register struct lexlist *np; X char filebuf[12]; X char *file; X FILE *op; X X file = filebuf; X X strncpy(file,tabnam,8); X strcat(file,".h"); X X if ((op = fopen(file,"w")) == NULL) { X fprintf(stderr,"%s: cannot create.\n",file); X exit(1); X } X X fprintf(op,"#ifndef STRUC_DEFINED\n\n"); X fprintf(op,"\/\*\t%s\t\*\/\n\n%s\n%s\n%s\n%s\n%s\n",file, X "struct _lex_h { char *__s;", X " int __v;", X " int __f;", X " struct _lex_h *__l;", X "};"); X fprintf(op,"\n#define STRUC_DEFINED\n#endif\n"); X X /* X * generate the hash table entries. X * each entry is followed by the next entry in its X * chain. X * In the operating systems with memory paging, this X * should have the extra advantage of localized X * memory referances. X * X */ X X for (i=0; i < HASHMAX; i++) X if ((np = hashtab[i]) != NULL) X prnode(np,op); X /* X * At last, we generate the pointer array (hashtable). X * this table should be assigned to lextable global X * variable before using with lexlook() or lexinstal(). X * lextable is defined in lookup.h X * X */ X X fprintf(op,"\n\n\/\* Hash Table \*\/\n\n"); X fprintf(op,"struct _lex_h *%s[%d] = {\n\t",tabnam,HASHMAX); X for (i=0; i < HASHMAX - 1; i++) { X np = hashtab[i]; X if(np == NULL) X fprintf(op,"NULL,\t"); X else X fprintf(op,"\&__%s,\t", np->name); X if (i % 4 == 0) X fprintf(op,"\n\t"); X } X np = hashtab[i]; X if (np == NULL) X fprintf(op,"NULL };\n"); X else X fprintf(op,"\&__%s };\n", np->name); X X fclose(op); X} X X/* X * prnode - print the current node. This routine is X * recursive such that printing starts from X * the end of the given list X * X */ Xprnode(np,op) Xregister struct Xlexlist *np; XFILE *op; X{ X if (np->link != NULL) X prnode(np->link,op); X fprintf(op,"struct\n_lex_h __%s = { ", X np->name); X fprintf(op,"\"%s\",\n %6d,%6d,", X np->name, X np->val, X np->flag); X if (np->link != NULL) X fprintf(op,"\&__%s };\n", X (np->link)->name); X else X fprintf(op,"NULL };\n"); X} X X/* X * defgen - generate a file containing the lexical X * constants to be equated to lexical symbols X */ Xdefgen() X{ X register int i; X register struct lexlist *np; X char *file; X char filebuf[12]; X FILE *op; X X file = filebuf; X strncpy(file,tabnam,8); X strcat(file,".d"); X X if ((op = fopen(file,"w")) == NULL) { X fprintf(stderr,"%s: cannot create.\n",file); X exit(1); X } X for (i=0; i < HASHMAX; i++) { X for (np = defitab[i]; np != NULL; np = np->link) X fprintf(op,"\#define %s\t%d\n", X np->name, X np->val); X } X fclose(op); X} X END_OF_ltb.c if test 6222 -ne `wc -c map.c <<'END_OF_map.c' X X X#include X/* X * map map every character of s1 that is specified in s2 X * into s3 and replace in s. (source s1 remains untouched) X */ X Xmap(s,s1,s2,s3) Xregister char *s; Xregister char *s1; Xregister char *s2; Xregister char *s3; X{ X char *t, *t1; X if (*s1 != '\0') { X t = s; X t1 = s1; X strcpy(t,t1); X X while (*s2 != '\0' && *s3 != '\0') { X while (*t1 != '\0') { X if (*t1 == *s2) X *t = *s3; X t++; X t1++; X } X t = s; X t1 = s1; X s2++; X s3++; X } X } X else X *s = '\0'; X} X X/* X * roman - convert a numeric string into roman numerals X * X * icon version: X *procedure roman(n) X * local arabic, result X * static equiv X * initial equiv := ["","I","II","III","IV","V","VI","VII","VIII","IX"] X * integer(n) > 0 | fail X * result := "" X * every arabic := !n do X * result := map(result,"IVXLCDM","XLCDM**") || equiv[arabic+1] X * if find("*",result) then fail else return result X * end X * X */ Xint Xcvtroman(num,rom) Xchar *num; Xchar *rom; X{ X char tmp[20]; X Xstatic char *equiv_U[] = { "","I","II","III","IV","V","VI","VII","VIII","IX" }; X X *rom = NULL; X while (*num != '\0') { X map(tmp,rom,"IVXLCDM","XLCDM**"); X strcpy(rom,tmp); X strcat(rom,equiv_U[*num - '0']); X num++; X } X return(strlen(rom)); X} X END_OF_map.c if test 1224 -ne `wc -c ms <<'END_OF_ms' X.! This file includes the proff versions of a few common nroff ms macros. X.! These are NOT identical to the ms ones, but do almost the same things. X.! X.! Set escape character same as ms uses X.ec \ X.! Non-indented paragraph preceded by a blank line. X.de LP X.ne 2 X.sp 1 X.en X.! Paragraph preceded by a blank line X.de PP X.ne 3 X.sp 1 X.ti +5 X.en X.! Paragraph NOT preceded by a blank line (same as ms ".PP 0") X.de PP0 X.ne 2 X.ti +5 X.en X.! Relative indented section X.de RS X.sp 1 X.in +5 X.en X.! End of relative indented section X.de RE X.in -5 X.en X.! Quoted paragraph (indent both margins by 5) X.de QP X.sp 1 X.rm -5 X.lm +5 X.en X.! End of quoted paragraph X.de QE X.br X.rm +5 X.lm -5 X.en X.! Bold font for words on line X.de B X.bold 1 X$1 $2 $3 $4 $5 $6 $7 $8 $9 X.en X.! Italic font for words on line (actually underline) X.de I X.ul 1 X$1 $2 $3 $4 $5 $6 $7 $8 $9 X.en X.! Underline words on line X.de UL X.ul 1 X$1 $2 $3 $4 $5 $6 $7 $8 $9 X.en X.! Force a line break X.de BR X.br X.en X.! Set line spacing X.de LS X.ls $1 X.en X.! Insert N blank lines X.de SP X.sp $1 X.en X.! Force a page break X.de BP X.bp X.en X.! Set Date (not implemented) X.de ND X.en X.! Enable/Disable hyphenation (not implemented) X.de HY X.en X.! Section Heading (centered) X.de SH X.ne 4 X.sp 1 X.ce on X.en X.! End of section heading X.de EH X.ce off X.br X.en X.! Centered, literal display X.de CD X.sv X.ce on X.nf X.sp X.ne 3 X.en X.! Literal display X.de DS X.sv X.sp X.nf X.ne 3 X.en X.! Literal display X.de LD X.sv X.sp X.nf X.ne 3 X.en X.! Indented section X.de IS X.sp X.in +8 X.ne 3 X.en X.! Need lines on page X.de NE X.ne $1 X.en X.! Display end X.de DE X.rs X.ce off X.en X.! Indented section end X.de IE X.in -8 X.en X.! Return to Roman text X.de R X.ul off X.bd off X.en X.! Generate table of contents entry X.de TC X.cl 0 $1 $2 $3 $4 $5 $6 $7 $8 $9 X$1 $2 $3 $4 $5 $6 $7 $8 $9 X.en X.! Center and Bold a title line X.de TL X.ce 1 X.bd 1 X.en END_OF_ms if test 1817 -ne `wc -c ms-README <<'END_OF_ms-README' XArticle 1605 of net.sources: XRelay-Version: version B 2.10.3 4.3bds beta 6/6/85; site bu-cs.BU.EDU XPath: bu-cs!mit-eddie!rutgers!sri-unix!hplabs!cae780!tektronix!tekig!tekig4!georgew XFrom: georgew@tekig4.UUCP (George Walker) XNewsgroups: net.sources XSubject: Proff macros to emulate Nroff ms macros XMessage-ID: <1095@tekig4.UUCP> XDate: 15 Nov 86 23:35:52 GMT XDate-Received: 16 Nov 86 08:31:50 GMT XReply-To: georgew@tekig4.UUCP (George Walker) XDistribution: na XOrganization: Oregon Home for Orphaned Responses XLines: 157 X XWell, no one responded to my requests for this, so I went ahead and wrote a Xmacro package for Proff. (For the uninitiated, proff is similar to nroff, Xbut runs on micros.) This is a hack. It only supports some of the common Xms macros, and leaves out some important ones like .IP that are trickier. XIf someone thinks they have a better package, please mail or post. X XGeorge S. Walker {decvax,ucbvax,...}!tektronix!tekig4!georgew UUCP XTektronix, Inc. tekig4!georgew@tektronix CSNET XP.O. Box 500, M/S 39-222 tekig4!georgew.tektronix@Udel-Relay ARPANET XBeaverton, OR 97077 503-627-4669 X------------------------------------------------------------------------------ END_OF_ms-README if test 1208 -ne `wc -c