/* PolyglotMan by Thomas A. Phelps (phelps@ACM.org) accept man pages as formatted by (10) Hewlett-Packard HP-UX, AT&T System V, SunOS, Sun Solaris, OSF/1, DEC Ultrix, SGI IRIX, Linux, FreeBSD, SCO output as (9) printable ASCII, section headers only, TkMan, [tn]roff, HTML, LaTeX, LaTeX2e, RTF, Perl pod, MIME, DocBook XML written March 24, 1993 bs2tk generalized into RosettaMan November 4-5, 1993 source interpretation added September 24, 1996 renamed PolyglotMan due to lawsuit by Rosetta, Inc. August 8, 1997 */ /* $XFree86: xc/extras/rman/rman.c,v 1.21 2006/03/13 00:54:46 dickey Exp $ */ #include #include #include #include #include #include #include #include #include #if defined(Lynx) || defined(__QNXNTO__) extern int optind; extern char *optarg; #endif #ifdef __CYGWIN__ #include #endif /*** make #define's into consts? => can't because compilers not smart enough ***/ /* maximum number of tags per line */ #define MAXTAGS 50*100 #define MAXBUF 2*5000 #define MAXLINES 20000 #define MAXTOC 500 #define xputchar(c) (fcharout? putchar(c): (c)) #define sputchar(c) (fcharout? plain[sI++]=(char)c: (char)(c)) #define stagadd(tag) tagadd(tag,sI,0) enum { c_dagger='\xa7', c_bullet='\xb7', c_plusminus='\xb1' }; /*** tag management ***/ enum tagtype { NOTAG, TITLE, ITALICS, BOLD, SYMBOL, SMALLCAPS, BOLDITALICS, MONO, MANREF }; /* MANREF last */ struct { enum tagtype type; int first; int last; } tags[MAXTAGS], tagtmp; int tagc=0; struct { char *text; int type; int line; } toc[MAXTOC]; int tocc=0; /* characters in this list automatically prefixed by a backslash (set in output format function */ char *escchars=""; char *vollist = VOLLIST; const char *manvalid = "._-+:"; /* in addition to alphanumerics, valid characters to find in a man page name */ char *manrefname; char *manrefsect; enum command { NOCOMMAND=-1, /*BEGINCHARTAGS,*/ CHARTAB='\t', CHARPERIOD='.', CHARLSQUOTE='`', CHARRSQUOTE='\'', CHARGT='>', CHARLT='<', CHARAMP='&', CHARBACKSLASH='\\', CHARDASH='-', CHARHAT='^', CHARVBAR='|', CHARNBSP=0xa0, CHARCENT=0xa2, CHARSECT=0xa7, CHARCOPYR=0xa9, CHARNOT=0xac, CHARDAGGER=0xad, CHARREGTM=0xae, CHARDEG=0xb0, CHARPLUSMINUS=0xb1, CHARACUTE=0xb4, CHARBULLET=0xb7, CHAR14=0xbc, CHAR12=0xbd, CHAR34=0xbe, CHARMUL=0xd7, CHARDIV=0xf7, CHANGEBAR=0x100, CHARLQUOTE, CHARRQUOTE, /*ENDCHARTAGS,*/ /*BEGINFONTTAGS,*/ BEGINBOLD, ENDBOLD, BEGINITALICS, ENDITALICS, BEGINBOLDITALICS, ENDBOLDITALICS, BEGINSC, ENDSC, BEGINY, ENDY, BEGINCODE, ENDCODE, BEGINMANREF, ENDMANREF, FONTSIZE, /*ENDFONTTAGS*/ /*BEGINLAYOUTTAGS,*/ ITAB, BEGINCENTER, ENDCENTER, HR, /*ENDLAYOUTTAGS,*/ /*BEGINSTRUCTTAGS,*/ BEGINDOC, ENDDOC, BEGINCOMMENT, ENDCOMMENT, COMMENTLINE, BEGINBODY, ENDBODY, BEGINHEADER, ENDHEADER, BEGINFOOTER, ENDFOOTER, BEGINLINE, ENDLINE, SHORTLINE, BEGINSECTION, ENDSECTION, BEGINSUBSECTION, ENDSUBSECTION, BEGINSECTHEAD, ENDSECTHEAD, BEGINSUBSECTHEAD, ENDSUBSECTHEAD, BEGINBULPAIR, ENDBULPAIR, BEGINBULLET, ENDBULLET, BEGINBULTXT, ENDBULTXT, BEGINTABLE, ENDTABLE, BEGINTABLELINE, ENDTABLELINE, BEGINTABLEENTRY, ENDTABLEENTRY, BEGININDENT, ENDINDENT, BEGINCODEBLOCK, ENDCODEBLOCK, BEGINDIFFA, ENDDIFFA, BEGINDIFFD, ENDDIFFD /*,*//*ENDSTRUCTTAGS,*/ }; const char *tcltkOP[] = { "Command-Line Name", "Database Name", "Database Class" }; /* characters that need special handling in any output format, *more than just a backslash* */ /* characters in this list need a corresponding case statement in each output format */ /*char *trouble="\t.`'><&\\^|-\xa7\xb7\xb1";*/ const unsigned char trouble[]= { CHARTAB, CHARPERIOD, CHARLSQUOTE, CHARRSQUOTE, CHARGT, CHARLT, CHARAMP, CHARBACKSLASH, CHARDASH, CHARHAT, CHARVBAR, CHARCENT, CHARSECT, CHARCOPYR, CHARNOT, CHARDAGGER, CHARREGTM, CHARDEG, CHARPLUSMINUS, CHARACUTE, CHARBULLET, CHAR14, CHAR12, CHAR34, CHARMUL, CHARDIV, 0 }; enum command tagbeginend[][2] = { /* parallel to enum tagtype */ { NOCOMMAND, NOCOMMAND }, { NOCOMMAND, NOCOMMAND }, { BEGINITALICS, ENDITALICS }, { BEGINBOLD, ENDBOLD }, { BEGINY, ENDY }, { BEGINSC, ENDSC }, { BEGINBOLDITALICS, ENDBOLDITALICS }, { NOCOMMAND, NOCOMMAND }, { BEGINMANREF, ENDMANREF } }; void (*fn)(enum command) = NULL; enum command prevcmd = BEGINDOC; /*** globals ***/ int fSource=-1; /* -1 => not determined yet */ int finlist=0; int fDiff=0; FILE *difffd; char diffline[MAXBUF]; char diffline2[MAXBUF]; char *message = NULL; int fontdelta=0; int intArg; int fPara=0; /* line or paragraph groupings of text */ int fSubsections=0; /* extract subsection titles too? */ int fChangeleft=0; /* move change bars to left? (-1 => delete them) */ int fReflow=0; int fURL=0; /* scan for URLs too? */ #if 0 int fMan=1; /* invoke agressive man page filtering? */ #endif int fQS=0; /* squeeze out spaces (scnt and interword)? */ int fIQS=0; /* squeeze out initial spaces (controlled separately from fQS) */ int fILQS=0; /* squeeze out spaces for usual indent */ int fHeadfoot=0; /* show canonical header and footer at bottom? */ int falluc=0; int itabcnt=0; int fQuiet=0; int fTclTk=0; /* patterns observed in section heads that don't conform to first-letter-uppercase-rest-lowercase pattern (stay all uc, or go all lc, or have subsequent uc) */ int lcexceptionslen = -1; /* computed by system */ char *lcexceptions[] = { /* new rule: double/all consonants == UC? */ /* articles, verbs, conjunctions, prepositions, pronouns */ "a", "an", "the", "am", "are", "is", "were", "and", "or", "by", "for", "from", "in", "into", "it", "of", "on", "to", "with", "that", "this", /* terms */ "API", "CD", "GUI", "UI", /*I/O=>I/O already*/ "ID", "IDs", "OO", "IOCTLs", "IPC", "RPC", /* system names */ "AWK", "cvs", "rcs", "GL", "vi", "PGP", "QuickTime", "DDD", "XPG/3", "NFS", "NIS", "NIS+", "AFS", "UNIX", "SysV", "XFree86", "ICCCM", "MH", "MIME", "TeX", "LaTeX", "PicTeX", "PostScript", "EPS", "EPSF", "EPSI", "HTML", "URL", "WWW", /* institution names */ "ANSI", "CERN", "GNU", "ISO", "NCSA", /* Sun-specific */ "MT-Level", "SPARC", NULL }; int TabStops=8; int hanging=0; /* location of hanging indent (if ==0, none) */ enum { NAME, SYNOPSIS, DESCRIPTION, SEEALSO, FILES, AUTHOR, RANDOM/*last!*/ }; char *sectheadname[] = { "NAME:NOMBRE", "SYNOPSIS", "DESCRIPTION:INTRODUCTION", "SEE ALSO:RELATED INFORMATION", "FILES", "AUTHOR:AUTHORS", "RANDOM" }; int sectheadid = RANDOM; int oldsectheadid = RANDOM; int fCodeline=0; int fNOHY=0; /* re-linebreak so no words are hyphenated; not used by TkMan, but gotta keep for people converting formatted text */ int fNORM=0; /* normalize? initial space => tabs, no changebars, exactly one blank line between sections */ const char TABLEOFCONTENTS[] = "Table of Contents"; const char HEADERANDFOOTER[] = "Header and Footer"; char manName[80] = "man page"; char manSect[10] = "1"; const char PROVENANCE[] = "manual page source format generated by PolyglotMan v" POLYGLOTMANVERSION; const char HOME[] = "available at http://polyglotman.sourceforge.net/"; const char horizontalrule[] = "------------------------------------------------------------"; const int LINEBREAK = 70; int linelen = 0; /* length of result in plain[] */ int spcsqz; /* number of spaces squeezed out */ int ccnt = 0; /* # of changebars */ int scnt, scnt2; /* counts of initial spaces in line */ int s_sum, s_cnt; int bs_sum, bs_cnt; int ncnt=0, oncnt=0; /* count of interline newlines */ int CurLine=1; int AbsLine=1-1; /* absolute line number */ int indent=0; /* global indentation */ int lindent=0; /* usual local indent */ int auxindent=0; /* aux indent */ int I; /* index into line/paragraph */ int fcharout=1; /* show text or not */ char lookahead; /*int tabgram[MAXBUF];*/ /* histogram of first character positions */ char buf[MAXBUF]; char plain[MAXBUF]; /* current text line with control characters stripped out */ char hitxt[MAXBUF]; /* highlighted text (available at time of BEGIN signal */ char header[MAXBUF]; /* complete line */ char header2[MAXBUF]; /* SGIs have two lines of headers and footers */ char header3[MAXBUF]; /* GNU and some others have a third! */ char footer[MAXBUF]; char footer2[MAXBUF]; #define CRUFTS 5 char *cruft[CRUFTS] = { header, header2, header3, footer, footer2 }; char *File, *in; /* File = pointer to full file contents, in = current file pointer */ char *argv0; int finTable=0; char tableSep='\0'; /*\t';*/ /*int fTable=0; int fotable=0;*/ char *tblcellformat; int tblcellspan; /*int tblspanmax;*/ int listtype=-1; /* current list type bogus to begin with */ enum listtypes { DL, OL, UL }; int fIP=0; /*** utility functions ***/ /* case insensitive versions of strcmp and strncmp */ static int stricmp(const char *s1, const char *s2) { assert(s1!=NULL && s2!=NULL); /*strincmp(s1, s2, strlen(s1)+1);*/ while (tolower(*s1)==tolower(*s2)) { if (*s1=='\0' /*&& *s2=='\0'*/) return 0; s1++; s2++; } if (tolower(*s1)0); while (n>0 && tolower(*s1)==tolower(*s2)) { n--; s1++; s2++; } if (n==0) return 0; else if (tolower(*s1)=-1 && end<=255); assert(sen==0 || sen==1); if (*l==':') l++; /* tolerate a leading colon */ /* invariant: c and v point to start of strings to compare */ while (*l) { assert(l==list || l[-1]==':'); for (c=candidate; *c && *l; c++,l++) if ((sen && *c!=*l) || (!sen && tolower(*c)!=tolower(*l))) break; /* if candidate matches a valid one as far as valid goes, it's a keeper */ if ((*l=='\0' || *l==':') && (*c==end || end==-1)) { if (*c=='\b') { c2 = c[-1]; while (*c=='\b' && c[1]==c2) c+=2; } /* no volume qualifiers with digits */ if (!isdigit(*c)) return 1; } /* bump to start of next valid */ while (*l && *l++!=':') /* nada */; } return 0; } static int strcoloncmp(char *candidate, int end, const char *list) { int sen=1; const char *l = list; assert(candidate!=NULL && list!=NULL); assert(end>=-1 && end<=255); if (*l=='=') l++; else end=-1; if (*l=='i') { sen=0; l++; } return strcoloncmp2(candidate, end, l, sen); } /* strdup not universally available */ static char * mystrdup(const char *p) { char *q; if (p==NULL) return NULL; q = malloc(strlen(p)+1); /* +1 gives space for \0 that is not reported by strlen */ if (q!=NULL) strcpy(q,p); return q; } /* given line of text, return "casified" version in place: if word in exceptions list, return exception conversion else uc first letter, lc rest */ static void casify(char *p) { char tmpch, *q, **exp; int fuc; for (fuc=1; *p; p++) { if (isspace(*p) || strchr("&/",*p)!=NULL) fuc=1; else if (fuc) { /* usually */ if (p[1] && isupper(p[1]) /*&& p[2] && isupper(p[2])*/) fuc=0; /* check for exceptions */ for (q=p; *q && !isspace(*q); q++) /*nada*/; tmpch = *q; *q='\0'; exp = (char **)bsearch(&p, lcexceptions, lcexceptionslen, sizeof(char *), lcexceptionscmp); *q = tmpch; if (exp!=NULL) { for (q=*exp; *q; q++) *p++=*q; fuc = 1; } } else *p=tolower(*p); } } /* add an attribute tag to a range of characters */ static void tagadd(int /*enum tagtype--abused in source parsing*/ type, int first, int last) { assert(type!=NOTAG); if (tagc0); assert(type==BEGINSECTION || type==BEGINSUBSECTION); if (tocc'"; static char *punct = ".,:;)]}?!"; while (*p==' ') p++; if (strincmp(p,"http",4)==0) { href="%s"; manrefname = p; p+=4; while (*p && !isspace(*p) && !strchr(nonhref,*p)) p++; while (strchr(punct, *(p - 1))) p--; } else { href = manRef; manrefname = p; while (*p && *p!=' ' && *p!='(') p++; *p++='\0'; while (*p==' ' || *p=='(') p++; p0=p; #ifdef XFree86 /* Don't allow a letter after the man section number */ p++; #else while (*p && *p!=')') p++; #endif manrefsect = p0; } *p='\0'; } /* * OUTPUT FORMATS */ static void formattedonly(void) { fprintf(stderr, "The output formats for Tk and TkMan require nroff-formatted input\n"); exit(1); } /* * DefaultFormat -- in weak OO inheritance, top of hierarchy for everybody */ static void DefaultFormat(enum command cmd) { int i; switch (cmd) { case ITAB: for (i=0; i=2 && ((c=='-' || c=='%' || c=='\\' || c=='$' /**/ /* not much talk of money in man pages so reasonable */) && (isalnum(plain[1]) /*<= plain[1]!='-'*//*no dash*/ || ncnt/*GNU long option*/) && plain[1]!=' ') ) clo[clocnt++] = CurLine; /* would like to require second letter to be a capital letter to cut down on number of matches, but command names usually start with lowercase letter maybe use a uppercase requirement as secondary strategy, but probably not */ if ((ncnt || lastsect) && linelen>0 && scnt>0 && scnt<=7/*used to be <=5 until groff spontaneously started putting in 7*/) para[paracnt++] = CurLine; lastsect=0; /* rebus too, instead of search through whole Tk widget */ if (rebuspatcnt && scnt>=5 /* not sect or subsect heads */) { for (p=plain; *p && *p!=' '; p++) /*empty*/; /* never first word */ while (*p) { for (i=0; i50) && (abs(scnt-lastscnt)<=1 || abs(scnt-hanging)<=1)) { finflow=1; putchar(' '); } else { Tk(ENDLINE); /*if ((CurLine&0x3f)==0x3f) printf("\"\nupdate idletasks\n$t insert end \""); blows up some Tk text buffer, apparently, on long lines*/ if ((CurLine&0x1f)==0x1f) printf("\"\nupdate idletasks\n$t insert end \""); finflow=0; /*if (fCodeline) printf("CODE");*/ } lastlinelen=linelen; lastscnt=scnt; break; case ENDLINE: /* don't call Tk(ENDLINE) */ break; default: /* if not caught above, it's the same as Tk */ Tk(cmd); } } /* * ASCII */ static void ASCII(enum command cmd) { int i; switch (cmd) { case ENDDOC: if (fHeadfoot) { printf("\n%s\n", HEADERANDFOOTER); for (i=0; i"); break; case BEGINBULLET: printf("\n=item "); break; case ENDBULLET: printf("\n\n"); fcharout=0; break; case BEGINBULTXT: fcharout=1; auxindent=hanging; break; case ENDBULTXT: auxindent=0; break; case ENDDOC: case BEGINBODY: case ENDBODY: case BEGINHEADER: case ENDHEADER: case BEGINFOOTER: case ENDFOOTER: case BEGINSECTION: case ENDSECTION: case BEGINSUBSECTION: case ENDSUBSECTION: case BEGINBULPAIR: case ENDBULPAIR: case SHORTLINE: case BEGINTABLE: case ENDTABLE: case BEGINTABLELINE: case ENDTABLELINE: case BEGINTABLEENTRY: case ENDTABLEENTRY: case BEGININDENT: case ENDINDENT: case FONTSIZE: case BEGINBOLDITALICS: case ENDBOLDITALICS: case BEGINY: case ENDY: case BEGINSC: case ENDSC: /* nothing */ break; default: DefaultLine(cmd); } } static void Sections(enum command cmd) { switch (cmd) { case ENDSECTHEAD: case ENDSUBSECTHEAD: putchar('\n'); case BEGINDOC: fcharout=0; break; case BEGINCOMMENT: fcharout=0; break; case ENDCOMMENT: fcharout=1; break; case COMMENTLINE: break; case BEGINSUBSECTHEAD: printf(" "); /* no break */ case BEGINSECTHEAD: fcharout=1; break; case CHARRQUOTE: case CHARLQUOTE: xputchar('"'); break; case CHARLSQUOTE: xputchar('`'); break; case CHARRSQUOTE: case CHARACUTE: xputchar('\''); break; case BEGINTABLE: case ENDTABLE: case BEGINTABLELINE: case ENDTABLELINE: case BEGINTABLEENTRY: case ENDTABLEENTRY: case BEGININDENT: case ENDINDENT: case FONTSIZE: break; case CHARPERIOD: case CHARTAB: case CHARDASH: case CHARBACKSLASH: case CHARLT: case CHARGT: case CHARHAT: case CHARVBAR: case CHARAMP: case CHARNBSP: xputchar(cmd); break; case CHARDAGGER: xputchar('+'); break; case CHARBULLET: xputchar('*'); break; case CHARPLUSMINUS: xputchar('+'); xputchar('-'); break; case CHARCENT: xputchar('c'); break; case CHARSECT: xputchar('S'); break; case CHARCOPYR: xputchar('('); xputchar('C'); xputchar(')'); break; case CHARNOT: xputchar('~'); break; case CHARREGTM: xputchar('('); xputchar('R'); xputchar(')'); break; case CHARDEG: xputchar('o'); break; case CHAR14: xputchar('1'); xputchar('/'); xputchar('4'); break; case CHAR12: xputchar('1'); xputchar('/'); xputchar('2'); break; case CHAR34: xputchar('3'); xputchar('/'); xputchar('4'); break; case CHARMUL: xputchar('X'); break; case CHARDIV: xputchar('/'); break; case ITAB: DefaultLine(cmd); break; default: /* nothing */ break; } } static void Roff(enum command cmd) { switch (cmd) { case BEGINDOC: I=1; printf(".TH %s %s \"generated by PolyglotMan\" UCB\n", manName, manSect); printf(".\\\" %s,\n", PROVENANCE); printf(".\\\" %s\n", HOME); CurLine=1; break; case BEGINBODY: printf(".LP\n"); break; case BEGINCOMMENT: case ENDCOMMENT: break; case COMMENTLINE: printf("'\\\" "); break; case BEGINSECTHEAD: printf(".SH "); break; case BEGINSUBSECTHEAD:printf(".SS "); break; case BEGINBULPAIR: printf(".IP "); break; case SHORTLINE: printf("\n.br"); break; case BEGINBOLD: printf("\\fB"); break; /* \n.B -- grr! */ case ENDCODE: case ENDBOLD: printf("\\fR"); break; /* putchar('\n'); */ case BEGINITALICS: printf("\\fI"); break; case ENDITALICS: printf("\\fR"); break; case BEGINCODE: case BEGINBOLDITALICS:printf("\\f4"); break; case ENDBOLDITALICS: printf("\\fR"); break; case CHARLQUOTE: printf("\\*(rq"); break; case CHARRQUOTE: printf("\\*(lq"); break; case CHARNBSP: printf("\\|"); break; case CHARLSQUOTE: putchar('`'); break; case CHARRSQUOTE: putchar('\''); break; case CHARPERIOD: if (I==1) printf("\\&"); putchar('.'); I++; break; case CHARDASH: printf("\\-"); break; case CHARTAB: case CHARLT: case CHARGT: case CHARHAT: case CHARVBAR: case CHARAMP: putchar(cmd); break; case CHARBULLET: printf("\\(bu"); break; case CHARDAGGER: printf("\\(dg"); break; case CHARPLUSMINUS: printf("\\(+-"); break; case CHANGEBAR: putchar('|'); break; case CHARCENT: printf("\\(ct"); break; case CHARSECT: printf("\\(sc"); break; case CHARCOPYR: printf("\\(co"); break; case CHARNOT: printf("\\(no"); break; case CHARREGTM: printf("\\(rg"); break; case CHARDEG: printf("\\(de"); break; case CHARACUTE: printf("\\(aa"); break; case CHAR14: printf("\\(14"); break; case CHAR12: printf("\\(12"); break; case CHAR34: printf("\\(34"); break; case CHARMUL: printf("\\(mu"); break; case CHARDIV: printf("\\(di"); break; case HR: /*printf("\n%s\n", horizontalrule);*/ break; case CHARBACKSLASH: printf("\\\\"); break; /* correct? */ case BEGINLINE: /*for (i=0; i0 || !finlist) printf("·"/*"·"*//*§--middot hardly visible*/); break; case CHARPLUSMINUS: printf("±"); break; case CHARGT: printf(">"); break; case CHARLT: printf("<"); break; case CHARAMP: printf("&"); break; case CHARCENT: printf("¢"); break; case CHARSECT: printf("§"); break; case CHARCOPYR: printf("©"); break; case CHARNOT: printf("¬"); break; case CHARREGTM: printf("®"); break; case CHARDEG: printf("°"); break; case CHARACUTE: printf("´"); break; case CHAR14: printf("¼"); break; case CHAR12: printf("½"); break; case CHAR34: printf("¾"); break; case CHARMUL: printf("×"); break; case CHARDIV: printf("÷"); break; default: break; } /* while in pre mode... */ if (pre) { switch (cmd) { case ENDLINE: I=0; CurLine++; if (!fPara && scnt) printf("
"); printf("\n"); break; case ENDTABLE: if (fSource) { printf("\n"); } else { printf("
\n"); pre=0; fQS=fIQS=fPara=1; } break; case ENDCODEBLOCK: printf(""); pre=0; break; case SHORTLINE: case ENDBODY: printf("\n"); break; case BEGINBOLD: printf(""); break; case ENDBOLD: printf(""); break; case BEGINITALICS: printf(""); break; case ENDITALICS: printf(""); break; default: /* nothing */ break; } return; } /* usual operation */ switch (cmd) { case BEGINDOC: /* escchars = ... => HTML doesn't backslash-quote metacharacters */ printf("\n", PROVENANCE); printf("\n\n", HOME); printf("\n\n"); /* printf("\n");*/ /* better title possible? */ printf(""); printf(manTitle, manName, manSect); printf("\n"); #ifdef XFree86 printf("\n\n"); #else printf("\n\n"); #endif printf("%s

\n", TABLEOFCONTENTS); I=0; break; case ENDDOC: /* header and footer wanted? */ printf("

\n"); if (fHeadfoot) { printf("


%s

\n", HEADERANDFOOTER); for (i=0; i\n", cruft[i]); } if (!tocc) { /*printf("\n

ERROR: Empty man page

\n");*/ } else { printf("\n

\n"); printf("%s

\n", TABLEOFCONTENTS); printf("

    \n"); for (i=0, lasttoc=BEGINSECTION; i\n"); else printf("
\n"); } printf("
  • %s
  • \n", i, i, toc[i].text); } if (lasttoc==BEGINSUBSECTION) printf(""); printf("\n"); } printf("\n\n"); break; case BEGINBODY: printf("

    \n"); break; case ENDBODY: break; case BEGINCOMMENT: printf("\n\n"); break; case COMMENTLINE: printf(" "); break; case BEGINSECTHEAD: printf("\n

    ", tocc, tocc); break; case ENDSECTHEAD: printf("

    \n"); /* useful extraction from FILES, ENVIRONMENT? */ break; case BEGINSUBSECTHEAD: printf("\n

    ", tocc, tocc); break; case ENDSUBSECTHEAD: printf("

    \n"); break; case BEGINSECTION: break; case ENDSECTION: if (sectheadid==NAME && message!=NULL) printf(message); break; case BEGINSUBSECTION: break; case ENDSUBSECTION: break; case BEGINBULPAIR: if (listtype==OL) printf("\n
      \n"); else if (listtype==UL) printf("\n
        \n"); else printf("\n
        \n"); break; case ENDBULPAIR: if (listtype==OL) printf("\n
    \n"); else if (listtype==UL) printf("\n\n"); else printf("\n"); break; case BEGINBULLET: if (listtype==OL || listtype==UL) fcharout=0; else printf("\n
    "); break; case ENDBULLET: if (listtype==OL || listtype==UL) fcharout=1; else printf("
    "); break; case BEGINBULTXT: if (listtype==OL || listtype==UL) printf("
  • "); else printf("\n
    "); break; case ENDBULTXT: if (listtype==OL || listtype==UL) printf("
  • "); else printf("\n"); break; case BEGINLINE: /* if (ncnt) printf("

    \n"); -- if haven't already generated structural tag */ if (ncnt) printf("\n

    "); /* trailing spaces already trimmed off, so look for eol now */ if (fCodeline) { printf(""); for (i=0; i
    "); fCodeline=0; } I=0; CurLine++; if (!fPara && scnt) printf("
    "); printf("\n"); break; case SHORTLINE: if (fCodeline) { printf("
    "); fCodeline=0; } if (!fIP) printf("
    \n"); break; case BEGINTABLE: if (fSource) { /*printf("

    \n");*/ printf("
    \n"); } else { printf("
    \n"); pre=1; fQS=fIQS=fPara=0;
    		}
    		break;
    	   case ENDTABLE:
    		if (fSource) {
    		  printf("
    \n"); } else { printf("
    \n"); pre=0; fQS=fIQS=fPara=1; } break; case BEGINTABLELINE: printf(""); break; case ENDTABLELINE: printf("\n"); break; case BEGINTABLEENTRY: printf("1) printf(" colspan=%d", tblcellspan); printf("'>"); break; case ENDTABLEENTRY: printf(""); break; /* something better with CSS */ case BEGININDENT: printf("
    "); break; case ENDINDENT: printf("
    \n"); break; case FONTSIZE: /* HTML font step sizes are bigger than troff's */ if ((fontdelta+=intArg)!=0) printf("", (intArg>0)?'+':'-'); else printf("\n"); break; case BEGINBOLD: printf(""); break; case ENDBOLD: printf(""); break; case BEGINITALICS: printf(""); break; case ENDITALICS: printf(""); break; case BEGINBOLDITALICS: case BEGINCODE: printf(""); break; case ENDBOLDITALICS: case ENDCODE: printf(""); break; case BEGINCODEBLOCK: printf("
    "); pre=1; break;	/* wrong for two-column lists in kermit.1, pine.1, perl4.1 */
    	   case ENDCODEBLOCK:	printf("
    "); pre=0; break; case BEGINCENTER: printf("
    "); break; case ENDCENTER: printf("
    "); break; case BEGINMANREF: manrefextract(hitxt); if (fmanRef) { printf(""); } else printf(""); break; case ENDMANREF: if (fmanRef) printf("\n"); else printf(""); break; case HR: printf("\n
    \n"); break; /* U (was B, I), strike -- all temporary until HTML 4.0's INS and DEL widespread */ case BEGINDIFFA: printf(""); break; case ENDDIFFA: printf(""); break; case BEGINDIFFD: printf(""); break; case ENDDIFFD: printf(""); break; case BEGINSC: case ENDSC: case BEGINY: case ENDY: case BEGINHEADER: case ENDHEADER: case BEGINFOOTER: case ENDFOOTER: case CHANGEBAR: /* nothing */ break; default: DefaultPara(cmd); } } /* * DocBook XML * improvements by Aaron Hawley applied 2003 June 5 * * N.B. The framework for XML is in place but not done. If you * are familiar with the DocBook DTD, however, it shouldn't be * too difficult to finish it. If you do so, please send your * code to me so that I may share the wealth in the next release. */ const char *DOCBOOKPATH = "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"; static void XML(enum command cmd) { static int pre=0; int i; char *p; static int fRefEntry=0; static int fRefPurpose=0; /*static char *bads => XML doesn't backslash-quote metacharacters */ /* */ /* always respond to these signals */ switch (cmd) { case CHARLQUOTE: case CHARRQUOTE: printf("""); break; case CHARBULLET: printf("•"); break; case CHARDAGGER: printf("†"); break; case CHARPLUSMINUS: printf("±"); break; case CHARCOPYR: printf("©"); break; case CHARNOT: printf("¬"); break; case CHARMUL: printf("×"); break; case CHARDIV: printf("÷"); break; case CHARAMP: printf("&"); break; case CHARDASH: if (sectheadid==NAME && !fRefPurpose) { printf(""); fRefPurpose=1; } else putchar('-'); break; case CHARBACKSLASH: putchar('\\'); break; case CHARGT: printf(">"); break; case CHARLT: printf("<"); break; case CHARLSQUOTE: case CHARRSQUOTE: case CHARPERIOD: case CHARTAB: case CHARHAT: case CHARVBAR: case CHARNBSP: case CHARCENT: case CHARSECT: case CHARREGTM: case CHARDEG: case CHARACUTE: case CHAR14: case CHAR12: case CHAR34: putchar(cmd); break; default: break; } /* while in pre mode... */ if (pre) { switch (cmd) { case ENDLINE: I=0; CurLine++; if (!fPara && scnt) putchar(' '); break; case ENDTABLE: if (fSource) printf("\n"); else { printf("\n"); pre=0; fQS=fIQS=fPara=1; } break; default: /* nothing */ break; } return; } /* usual operation */ switch (cmd) { case BEGINDOC: printf("\n\n", DOCBOOKPATH); printf("\n"); printf("\n\n",HOME); /* better title possible? */ for (p=manName; *p; p++) *p = tolower(*p); printf("\n", manName, manSect); printf("\n%s\n", manName); printf("%s\n\n\n", manSect); I=0; break; case ENDDOC: /* header and footer wanted? */ if (fHeadfoot) { printf("\n\n%s\n", HEADERANDFOOTER); for (i=0; i%s\n", cruft[i]); printf("\n"); } /* table of contents, such as found in HTML, can be generated automatically by XML software */ printf("\n"); break; case BEGINBODY: if (fPara) printf("\n"); printf(""); fPara = 1; break; case ENDBODY: if (fRefPurpose) { printf(""); fRefPurpose=0; } else { printf("\n"); fPara=0; } break; case BEGINCOMMENT: printf("\n\n"); break; case COMMENTLINE: break; case BEGINSECTHEAD: case BEGINSUBSECTHEAD: if (sectheadid != NAME && sectheadid != SYNOPSIS) printf(""); break; case ENDSECTHEAD: case ENDSUBSECTHEAD: if (sectheadid == NAME) printf("<refname>"); else if (sectheadid == SYNOPSIS) {} else { printf("\n"); fPara=1; } break; case BEGINSECTION: if (sectheadid==NAME) printf("\n"); /*printf(""); -- do lotsa parsing here for RefName, RefPurpose*/ else if (sectheadid==SYNOPSIS) printf("\n\n"); else printf("\n\n"); break; case ENDSECTION: if (sectheadid==NAME) { if (fRefPurpose) { printf(""); fRefPurpose=0; } printf("\n\n\n"); } else if (sectheadid==SYNOPSIS) printf("\n\n\n"); else { if (fPara) { printf("\n"); fPara=0; } printf("\n\n"); } break; case BEGINSUBSECTION: printf("\n"); break; case ENDSUBSECTION: printf("\n"); break; /* need to update this for enumerated and plain lists */ case BEGINBULPAIR: printf("\n"); break; case ENDBULPAIR: printf("\n"); break; case BEGINBULLET: printf(""); break; case ENDBULLET: printf("\n"); break; case BEGINBULTXT: printf("\n"); break; case ENDBULTXT: printf("\n\n"); break; case BEGINLINE: /* remember, get BEGINBODY call at start of paragraph */ if (fRefEntry) { if (fRefPurpose) { for (p=plain; *p!='-'; p++) { /* nothing?! */ } } } break; case ENDLINE: /*if (fCodeline) { fIQS=1; fCodeline=0; }*/ if (fCodeline) { printf(""); fCodeline=0; } /* */ I=0; CurLine++; if (!fPara && scnt) printf(""); else putchar(' '); break; case SHORTLINE: if (fCodeline) { printf(""); fCodeline=0; } if (!fIP && !fPara) printf("\n"); break; case BEGINTABLE: if (fSource) printf("\n"); else { printf("\n"); pre=1; fQS=fIQS=fPara=0; } break; case ENDTABLE: if (fSource) printf("
    \n"); else { printf("\n"); pre=0; fQS=fIQS=fPara=1; } break; case BEGINTABLELINE: printf(""); break; case ENDTABLELINE: printf("\n"); break; case BEGINTABLEENTRY: printf(""); break; case ENDTABLEENTRY: printf(""); break; case BEGININDENT: case ENDINDENT: case FONTSIZE: break; /* have to make some guess about bold and italics */ case BEGINBOLD: printf(""); break; case ENDBOLD: printf(""); break; case BEGINITALICS: printf(""); break; /* could be literal or arg */ case ENDITALICS: printf(""); break; case BEGINBOLDITALICS: case BEGINCODE: printf(""); break; case ENDBOLDITALICS: case ENDCODE: printf(""); break; case BEGINMANREF: manrefextract(hitxt); if (fmanRef) { printf(""); } break; case ENDMANREF: if (fmanRef) printf(""); break; case HR: case BEGINSC: case ENDSC: case BEGINY: case ENDY: case BEGINHEADER: case ENDHEADER: case BEGINFOOTER: case ENDFOOTER: case CHANGEBAR: /* nothing */ break; default: DefaultPara(cmd); } } /* generates MIME compliant to RFC 1563 */ static void MIME(enum command cmd) { static int pre=0; int i; /* always respond to these signals */ switch (cmd) { case CHARDASH: case CHARAMP: case CHARPERIOD: case CHARTAB: putchar(cmd); break; case CHARLSQUOTE: putchar('`'); break; case CHARACUTE: case CHARRSQUOTE: putchar('\''); break; case CHARBULLET: putchar('*'); break; case CHARDAGGER: putchar('|'); break; case CHARPLUSMINUS: printf("+-"); break; case CHARNBSP: putchar(' '); break; case CHARCENT: putchar('c'); break; case CHARSECT: putchar('S'); break; case CHARCOPYR: printf("(C)"); break; case CHARNOT: putchar('~'); break; case CHARREGTM: printf("(R)"); break; case CHARDEG: putchar('o'); break; case CHAR14: printf("1/4"); break; case CHAR12: printf("1/2"); break; case CHAR34: printf("3/4"); break; case CHARMUL: putchar('X'); break; case CHARDIV: putchar('/'); break; case CHARLQUOTE: case CHARRQUOTE: putchar('"'); break; case CHARBACKSLASH: /* these should be caught as escaped chars */ case CHARGT: case CHARLT: #if 0 assert(1); #endif break; default: break; } /* while in pre mode... */ if (pre) { switch (cmd) { case ENDLINE: I=0; CurLine++; if (!fPara && scnt) printf("\n\n"); break; case ENDTABLE: printf("\n\n"); pre=0; fQS=fIQS=fPara=1; break; default: /* nothing */ break; } return; } /* usual operation */ switch (cmd) { case BEGINDOC: printf("Content-Type: text/enriched\n"); printf("Text-Width: 60\n"); escchars = "<>\\"; I=0; break; case ENDDOC: /* header and footer wanted? */ printf("\n\n"); if (fHeadfoot) { printf("\n"); MIME(BEGINSECTHEAD); printf("%s",HEADERANDFOOTER); MIME(ENDSECTHEAD); for (i=0; i\n"); printf("%s\n%s\n", PROVENANCE, HOME); printf("\n\n"); */ /* printf("\n

    \n"); printf("%s

    \n", TABLEOFCONTENTS); printf("

      \n"); for (i=0, lasttoc=BEGINSECTION; i\n"); else printf("
    \n"); } printf("
  • %s
  • \n", i, i, toc[i].text); } if (lasttoc==BEGINSUBSECTION) printf(""); printf("\n"); printf("\n"); */ break; case BEGINBODY: printf("\n\n"); break; case ENDBODY: break; case BEGINCOMMENT: fcharout=0; break; case ENDCOMMENT: fcharout=1; break; case COMMENTLINE: break; case BEGINSECTHEAD: printf("\n"); /*A NAME=\"sect%d\" HREF=\"#toc%d\">

    ", tocc, tocc);*/ break; case ENDSECTHEAD: printf("\n\n"); /* useful extraction from files, environment? */ break; case BEGINSUBSECTHEAD: printf(""); /*\n

    ", tocc, tocc);*/ break; case ENDSUBSECTHEAD: printf("\n\n"); break; case BEGINSECTION: case BEGINSUBSECTION: break; case ENDSECTION: case ENDSUBSECTION: printf("\n"); break; case BEGINBULPAIR: break; case ENDBULPAIR: break; case BEGINBULLET: printf(""); break; case ENDBULLET: printf("\t"); break; case BEGINBULTXT: case BEGININDENT: printf(""); break; case ENDBULTXT: case ENDINDENT: printf("\n"); break; case FONTSIZE: if ((fontdelta+=intArg)==0) { if (intArg>0) printf(""); else printf(""); } else { if (intArg>0) printf(""); else printf(""); } break; case BEGINLINE: /*if (ncnt) printf("\n\n");*/ break; case ENDLINE: I=0; CurLine++; printf("\n"); break; case SHORTLINE: if (!fIP) printf("\n\n"); break; case BEGINTABLE: printf("\n"); pre=1; fQS=fIQS=fPara=0; break; case ENDTABLE: printf("\n"); pre=0; fQS=fIQS=fPara=1; break; case BEGINTABLELINE: case ENDTABLELINE: case BEGINTABLEENTRY: case ENDTABLEENTRY: break; /* could use a new list type */ case BEGINBOLD: printf(""); break; case ENDBOLD: printf(""); break; case BEGINITALICS: printf(""); break; case ENDITALICS: printf(""); break; case BEGINCODE: case BEGINBOLDITALICS:printf(""); break; case ENDCODE: case ENDBOLDITALICS: printf(""); break; case BEGINMANREF: printf("blue"); /* how to make this hypertext? manrefextract(hitxt); if (fmanRef) { printf("\n"); } else printf(""); break; */ break; case ENDMANREF: printf(""); break; case HR: printf("\n\n%s\n\n", horizontalrule); break; case BEGINSC: case ENDSC: case BEGINY: case ENDY: case BEGINHEADER: case ENDHEADER: case BEGINFOOTER: case ENDFOOTER: case CHANGEBAR: /* nothing */ break; default: DefaultPara(cmd); } } /* * LaTeX */ static void LaTeX(enum command cmd) { switch (cmd) { case BEGINDOC: escchars = "$&%#_{}"; /* and more to come? */ printf("%% %s,\n", PROVENANCE); printf("%% %s\n\n", HOME); /* definitions */ printf( "\\documentstyle{article}\n" "\\def\\thefootnote{\\fnsymbol{footnote}}\n" "\\setlength{\\parindent}{0pt}\n" "\\setlength{\\parskip}{0.5\\baselineskip plus 2pt minus 1pt}\n" "\\begin{document}\n" ); I=0; break; case ENDDOC: /* header and footer wanted? */ printf("\n\\end{document}\n"); break; case BEGINBODY: printf("\n\n"); break; case ENDBODY: break; case BEGINCOMMENT: case ENDCOMMENT: break; case COMMENTLINE: printf("%% "); break; case BEGINSECTION: break; case ENDSECTION: break; case BEGINSECTHEAD: printf("\n\\section{"); tagc=0; break; case ENDSECTHEAD: printf("}"); /* if (CurLine==1) printf("\\footnote{" "\\it conversion to \\LaTeX\ format by PolyglotMan " "available via anonymous ftp from {\\tt ftp.berkeley.edu:/ucb/people/phelps/tcltk}}" ); */ /* useful extraction from files, environment? */ printf("\n"); break; case BEGINSUBSECTHEAD:printf("\n\\subsection{"); break; case ENDSUBSECTHEAD: printf("}"); break; case BEGINSUBSECTION: break; case ENDSUBSECTION: break; case BEGINBULPAIR: printf("\\begin{itemize}\n"); break; case ENDBULPAIR: printf("\\end{itemize}\n"); break; case BEGINBULLET: printf("\\item ["); break; case ENDBULLET: printf("] "); break; case BEGINLINE: /*if (ncnt) printf("\n\n");*/ break; case ENDLINE: I=0; putchar('\n'); CurLine++; break; case BEGINTABLE: printf("\\begin{verbatim}\n"); break; case ENDTABLE: printf("\\end{verbatim}\n"); break; case BEGINTABLELINE: case ENDTABLELINE: case BEGINTABLEENTRY: case ENDTABLEENTRY: break; case BEGININDENT: case ENDINDENT: case FONTSIZE: break; case SHORTLINE: if (!fIP) printf("\n\n"); break; case BEGINBULTXT: break; case ENDBULTXT: putchar('\n'); break; case CHARLQUOTE: printf("``"); break; case CHARRQUOTE: printf("''"); break; case CHARLSQUOTE: case CHARRSQUOTE: case CHARPERIOD: case CHARTAB: case CHARDASH: case CHARNBSP: putchar(cmd); break; case CHARBACKSLASH: printf("$\\backslash$"); break; case CHARGT: printf("$>$"); break; case CHARLT: printf("$<$"); break; case CHARHAT: printf("$\\char94{}$"); break; case CHARVBAR: printf("$|$"); break; case CHARAMP: printf("\\&"); break; case CHARBULLET: printf("$\\bullet$ "); break; case CHARDAGGER: printf("\\dag "); break; case CHARPLUSMINUS: printf("\\pm "); break; case CHARCENT: printf("\\hbox{\\rm\\rlap/c}"); break; case CHARSECT: printf("\\S "); break; case CHARCOPYR: printf("\\copyright "); break; case CHARNOT: printf("$\\neg$"); break; case CHARREGTM: printf("(R)"); break; case CHARDEG: printf("$^\\circ$"); break; case CHARACUTE: putchar('\''); break; case CHAR14: printf("$\\frac{1}{4}$"); break; case CHAR12: printf("$\\frac{1}{2}$"); break; case CHAR34: printf("$\\frac{3}{4}$"); break; case CHARMUL: printf("\\times "); break; case CHARDIV: printf("\\div "); break; case BEGINCODE: case BEGINBOLD: printf("{\\bf "); break; /* } */ case BEGINSC: printf("{\\sc "); break; /* } */ case BEGINITALICS: printf("{\\it "); break; /* } */ case BEGINBOLDITALICS:printf("{\\bf\\it "); break; /* } */ case BEGINMANREF: printf("{\\sf "); break; /* } */ case ENDCODE: case ENDBOLD: case ENDSC: case ENDITALICS: case ENDBOLDITALICS: case ENDMANREF: /* { */ putchar('}'); break; case HR: /*printf("\n%s\n", horizontalrule);*/ break; case BEGINY: case ENDY: case BEGINHEADER: case ENDHEADER: case BEGINFOOTER: case ENDFOOTER: case CHANGEBAR: /* nothing */ break; default: DefaultPara(cmd); } } static void LaTeX2e(enum command cmd) { switch (cmd) { /* replace selected commands ... */ case BEGINDOC: escchars = "$&%#_{}"; printf("%% %s,\n", PROVENANCE); printf("%% %s\n\n", HOME); /* definitions */ printf( "\\documentclass{article}\n" "\\def\\thefootnote{\\fnsymbol{footnote}}\n" "\\setlength{\\parindent}{0pt}\n" "\\setlength{\\parskip}{0.5\\baselineskip plus 2pt minus 1pt}\n" "\\begin{document}\n" ); I=0; break; case BEGINCODE: case BEGINBOLD: printf("\\textbf{"); break; /* } */ case BEGINSC: printf("\\textsc{"); break; /* } */ case BEGINITALICS: printf("\\textit{"); break; /* } */ case BEGINBOLDITALICS:printf("\\textbf{\\textit{"); break; /* }} */ case BEGINMANREF: printf("\\textsf{"); break; /* } {{ */ case ENDBOLDITALICS: printf("}}"); break; /* ... rest same as old LaTeX */ default: LaTeX(cmd); } } /* * Rich Text Format (RTF) */ /* RTF could use more work */ static void RTF(enum command cmd) { switch (cmd) { case BEGINDOC: escchars = "{}"; /* definitions */ printf( /* fonts */ "{\\rtf1\\deff2 {\\fonttbl" "{\\f20\\froman Times;}{\\f150\\fnil I Times Italic;}" "{\\f151\\fnil B Times Bold;}{\\f152\\fnil BI Times BoldItalic;}" "{\\f22\\fmodern Courier;}{\\f23\\ftech Symbol;}" "{\\f135\\fnil I Courier Oblique;}{\\f136\\fnil B Courier Bold;}{\\f137\\fnil BI Courier BoldOblique;}" "{\\f138\\fnil I Helvetica Oblique;}{\\f139\\fnil B Helvetica Bold;}}" "\n" /* style sheets */ "{\\stylesheet{\\li720\\sa120 \\f20 \\sbasedon222\\snext0 Normal;}" "{\\s2\\sb200\\sa120 \\b\\f3\\fs20 \\sbasedon0\\snext2 section head;}" "{\\s3\\li180\\sa120 \\b\\f20 \\sbasedon0\\snext3 subsection head;}" "{\\s4\\fi-1440\\li2160\\sa240\\tx2160 \\f20 \\sbasedon0\\snext4 detailed list;}}" "\n" /* more header to come--do undefined values default to nice values? */ ); I=0; break; case ENDDOC: /* header and footer wanted? */ printf("\\par{\\f150 %s,\n%s}", PROVENANCE, HOME); printf("}\n"); break; case BEGINBODY: printf("\n\n"); break; case ENDBODY: CurLine++; printf("\\par\n"); tagc=0; break; case BEGINCOMMENT: fcharout=0; break; case ENDCOMMENT: fcharout=1; break; case COMMENTLINE: break; case BEGINSECTION: break; case ENDSECTION: printf("\n\\par\n"); break; case BEGINSECTHEAD: printf("{\\s2 "); tagc=0; break; case ENDSECTHEAD: printf("}\\par"); /* useful extraction from files, environment? */ printf("\n"); break; case BEGINSUBSECTHEAD:printf("{\\s3 "); break; case ENDSUBSECTHEAD: printf("}\\par\n"); break; case BEGINSUBSECTION: break; case ENDSUBSECTION: break; case BEGINLINE: /*if (ncnt) printf("\n\n");*/ break; case ENDLINE: I=0; putchar(' '); /*putchar('\n'); CurLine++;*/ break; case SHORTLINE: if (!fIP) printf("\\line\n"); break; case BEGINBULPAIR: printf("{\\s4 "); break; case ENDBULPAIR: printf("}\\par\n"); break; case BEGINBULLET: break; case ENDBULLET: printf("\\tab "); fcharout=0; break; case BEGINBULTXT: fcharout=1; break; case ENDBULTXT: break; case CHARLQUOTE: printf("``"); break; case CHARRQUOTE: printf("''"); break; case CHARLSQUOTE: case CHARRSQUOTE: case CHARPERIOD: case CHARTAB: case CHARDASH: case CHARBACKSLASH: case CHARGT: case CHARLT: case CHARHAT: case CHARVBAR: case CHARAMP: case CHARNBSP: case CHARCENT: case CHARSECT: case CHARCOPYR: case CHARNOT: case CHARREGTM: case CHARDEG: case CHARACUTE: case CHAR14: case CHAR12: case CHAR34: case CHARMUL: case CHARDIV: putchar(cmd); break; case CHARBULLET: printf("\\bullet "); break; case CHARDAGGER: printf("\\dag "); break; case CHARPLUSMINUS: printf("\\pm "); break; case BEGINCODE: case BEGINBOLD: printf("{\\b "); break; /* } */ case BEGINSC: printf("{\\fs20 "); break; /* } */ case BEGINITALICS: printf("{\\i "); break; /* } */ case BEGINBOLDITALICS:printf("{\\b \\i "); break; /* } */ case BEGINMANREF: printf("{\\f22 "); break; /* } */ case ENDBOLD: case ENDCODE: case ENDSC: case ENDITALICS: case ENDBOLDITALICS: case ENDMANREF: /* { */ putchar('}'); break; case HR: printf("\n%s\n", horizontalrule); break; case BEGINY: case ENDY: case BEGINHEADER: case ENDHEADER: case BEGINFOOTER: case ENDFOOTER: case BEGINTABLE: case ENDTABLE: case BEGINTABLELINE: case ENDTABLELINE: case BEGINTABLEENTRY: case ENDTABLEENTRY: case BEGININDENT: case ENDINDENT: case FONTSIZE: case CHANGEBAR: /* nothing */ break; default: DefaultPara(cmd); } } /* * pointers to existing tools */ static void PostScript(enum command cmd) { fprintf(stderr, "Use groff or psroff to generate PostScript.\n"); exit(1); } static void FrameMaker(enum command cmd) { fprintf(stderr, "FrameMaker comes with filters that convert from roff to MIF.\n"); exit(1); } /* * Utilities common to both parses */ /* level 0: DOC - need match level 1: SECTION - need match level 2: SUBSECTION | BODY | BULLETPAIR level 3: BODY (within SUB) | BULLETPAIR (within SUB) | BULTXT (within BULLETPAIR) level 4: BULTXT (within BULLETPAIR within SUBSECTION) never see: SECTHEAD, SUBSECTHEAD, BULLET */ int Psect=0, Psub=0, Pbp=0, Pbt=0, Pb=0, Pbul=0; static void pop(enum command cmd) { assert(cmd==ENDINDENT || cmd==BEGINBULLET || cmd==BEGINBULTXT || cmd==BEGINBULPAIR || cmd==BEGINBODY || cmd==BEGINSECTION || cmd==BEGINSUBSECTION || cmd==ENDDOC); /* int i; int p; int match; p=cmdp-1; for (i=cmdp-1;i>=0; i--) if (cmd==cmdstack[i]) { match=i; break; } */ /* if match, pop off all up to and including match */ /* otherwise, pop off one level*/ if (Pbul) { (*fn)(ENDBULLET); Pbul=0; if (cmd==BEGINBULLET) return; } /* else close off ENDBULTXT */ if (Pbt) { (*fn)(ENDBULTXT); Pbt=0; } if (cmd==BEGINBULTXT || cmd==BEGINBULLET) return; if (Pb && cmd==BEGINBULPAIR) { (*fn)(ENDBODY); Pb=0; } /* special */ if (Pbp) { (*fn)(ENDBULPAIR); Pbp=0; } if (cmd==BEGINBULPAIR || cmd==ENDINDENT) return; if (Pb) { (*fn)(ENDBODY); Pb=0; } if (cmd==BEGINBODY) return; if (Psub) { (*fn)(ENDSUBSECTION); Psub=0; } if (cmd==BEGINSUBSECTION) return; if (Psect) { (*fn)(ENDSECTION); Psect=0; } if (cmd==BEGINSECTION) return; } static void poppush(enum command cmd) { assert(cmd==ENDINDENT || cmd==BEGINBULLET || cmd==BEGINBULTXT || cmd==BEGINBULPAIR || cmd==BEGINBODY || cmd==BEGINSECTION || cmd==BEGINSUBSECTION); pop(cmd); switch (cmd) { case BEGINBULLET: Pbul=1; break; case BEGINBULTXT: Pbt=1; break; case BEGINBULPAIR: Pbp=1; break; case BEGINBODY: Pb=1; break; case BEGINSECTION: Psect=1; break; case BEGINSUBSECTION: Psub=1; break; default: if (!fQuiet) fprintf(stderr, "poppush: unrecognized code %d\n", cmd); } (*fn)(cmd); prevcmd = cmd; } /* * PREFORMATTED PAGES PARSING */ /* wrapper for getchar() that expands tabs, and sends maximum of n=40 consecutive spaces */ static int getchartab(void) { static int tabexp = 0; static int charinline = 0; static int cspccnt = 0; char c; c = lookahead; if (tabexp) tabexp--; else if (c=='\n') { charinline=0; cspccnt=0; } else if (c=='\t') {