rscfix againd904abf19 years agoHistory
871 lines · 15.9 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <bio.h>#include <ctype.h> enum{	Nfont = 11,	Wid = 20	/* tmac.anhtml sets page width to 20" so we can recognize .nf text */}; typedef ulong Char;typedef struct Troffchar Troffchar;typedef struct Htmlchar Htmlchar;typedef struct Font Font;typedef struct HTMLfont HTMLfont; /* a Char is 32 bits. low 16 bits are the rune. higher are attributes */enum{	Italic	=	16,	Bold,	CW,	Indent1,	Indent2,	Indent3,	Heading =	25,	Anchor =	26	/* must be last */}; enum	/* magic emissions */{	Estring = 0,	Epp = 1<<16}; int attrorder[] = { Indent1, Indent2, Indent3, Heading, Anchor, Italic, Bold, CW }; int nest[10];int nnest; struct Troffchar{	char *name;	char *value;}; struct Htmlchar{	char *utf;	char *name;	int value;}; #include "chars.h" struct Font{	char		*name;	HTMLfont	*htmlfont;}; struct HTMLfont{	char	*name;	char	*htmlname;	int	bit;}; /* R must be first; it's the default representation for fonts we don't recognize */HTMLfont htmlfonts[] ={	"R",			nil,		0,	"LuxiSans",	nil,		0,	"I",			"i",	Italic,	"LuxiSans-Oblique",	"i",	Italic,	"CW",		"tt",		CW,	"LuxiMono",	"tt",		CW,	nil,	nil}; #define TABLE "<table border=0 cellpadding=0 cellspacing=0>" char*onattr[8*sizeof(ulong)] ={	0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0,	"<i>",	/* italic */	"<b>",	/* bold */	"<tt><font size=+1>",	/* cw */	"<+table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>\n",	/* indent1 */	"<+table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>\n",	/* indent2 */	"<+table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>\n",	/* indent3 */	0,	0,	0,	"<p><font size=+1><b>",	/* heading 25 */	"<unused>",	/* anchor 26 */}; char*offattr[8*sizeof(ulong)] ={	0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0,	"</i>",	/* italic */	"</b>",	/* bold */	"</font></tt>",	/* cw */	"<-/table>",	/* indent1 */	"<-/table>",	/* indent2 */	"<-/table>",	/* indent3 */	0,	0,	0,	"</b></font>",	/* heading 25 */	"</a>",	/* anchor 26 */}; Font *font[Nfont]; Biobuf bout;int	debug = 0; /* troff state */int	page = 1;int	ft = 1;int	vp = 0;int	hp = 0;int	ps = 1;int	res = 720; int		didP = 0;int		atnewline = 1;int		prevlineH = 0;ulong	attr = 0;	/* or'ed into each Char */ Char		*chars;int		nchars;int		nalloc;char**	anchors;	/* allocated in order */int		nanchors; char *pagename;char *section; char	*filename;int	cno;char	buf[8192];char	*title = "Plan 9 man page"; void	process(Biobuf*, char*);void	mountfont(int, char*);void	switchfont(int);void	header(char*);void	flush(void);void	trailer(void); void*emalloc(ulong n){	void *p; 	p = malloc(n);	if(p == nil)		sysfatal("malloc failed: %r");	return p;} void*erealloc(void *p, ulong n){ 	p = realloc(p, n);	if(p == nil)		sysfatal("realloc failed: %r");	return p;} char*estrdup(char *s){	char *t; 	t = strdup(s);	if(t == nil)		sysfatal("strdup failed: %r");	return t;} voidusage(void){	fprint(2, "usage: troff2html [-d] [-t title] [file ...]\n");	exits("usage");} inthccmp(const void *va, const void *vb){	Htmlchar *a, *b; 	a = (Htmlchar*)va;	b = (Htmlchar*)vb;	return a->value - b->value;} voidmain(int argc, char *argv[]){	int i;	Biobuf in, *inp;	Rune r; 	for(i=0; i<nelem(htmlchars); i++){		chartorune(&r, htmlchars[i].utf);		htmlchars[i].value = r;	}	qsort(htmlchars, nelem(htmlchars), sizeof(htmlchars[0]), hccmp); 	ARGBEGIN{	case 't':		title = ARGF();		if(title == nil)			usage();		break;	case 'd':		debug++;		break;	default:		usage();	}ARGEND 	Binit(&bout, 1, OWRITE);	if(argc == 0){		Binit(&in, 0, OREAD);		process(&in, "<stdin>");	}else{		for(i=0; i<argc; i++){			inp = Bopen(argv[i], OREAD);			if(inp == nil)				sysfatal("can't open %s: %r", argv[i]);			process(inp, argv[i]);			Bterm(inp);		}	}	header(title);	flush();	trailer();	exits(nil);} voidemitul(ulong ul, int special){	ulong a, c; 	if(nalloc == nchars){		nalloc += 10000;		chars = realloc(chars, nalloc*sizeof(chars[0]));		if(chars == nil)			sysfatal("malloc failed: %r");	} 	if(!special){		a = ul&~0xFFFF;		c = ul&0xFFFF;		/*		 * Attr-specific transformations.		 */		if((a&(1<<CW)) && c=='-')			c = 0x2212;		if(!(a&(1<<CW))){			if(c == '`')				c = 0x2018;			if(c == '\'')				c = 0x2019;		}		ul = a|c; 		/*		 * Turn single quotes into double quotes.		 */		if(nchars > 0){			if(c == 0x2018 && (chars[nchars-1]&0xFFFF) == 0x2018			&& a==(chars[nchars-1]&~0xFFFF)){				chars[nchars-1] = (ul&~0xFFFF) | 0x201C;				return;			}			if(c == 0x2019 && (chars[nchars-1]&0xFFFF) == 0x2019			&& a==(chars[nchars-1]&~0xFFFF)){				chars[nchars-1] = (ul&~0xFFFF) | 0x201D;				return;			}		}	}	chars[nchars++] = ul;} voidemit(Rune r){	emitul(r | attr, 0);	/*	 * Close man page references early, so that 	 * .IR proof (1),	 * doesn't make the comma part of the link.	 */	if(r == ')')		attr &= ~(1<<Anchor);} voidemitstr(char *s){	emitul(Estring | attr, 0);	emitul((ulong)s, 1);} int indentlevel;int linelen; voidiputrune(Biobuf *b, Rune r){	int i; 	if(linelen++ > 60 && r == ' ')		r = '\n';	if(r >= 0x80)		Bprint(b, "&#%d;", r);	else		Bputrune(b, r);	if(r == '\n'){		for(i=0; i<indentlevel; i++)			Bprint(b, "    ");		linelen = 0;	}} voidiputs(Biobuf *b, char *s){	if(s[0]=='<' && s[1]=='+'){		iputrune(b, '\n');		Bprint(b, "<%s", s+2);		indentlevel++;		iputrune(b, '\n');	}else if(s[0]=='<' && s[1]=='-'){		indentlevel--;		iputrune(b, '\n');		Bprint(b, "<%s", s+2);		iputrune(b, '\n');	}else		Bprint(b, "%s", s);} voidsetattr(ulong a){	int on, off, i, j; 	on = a & ~attr;	off = attr & ~a; 	/* walk up the nest stack until we reach something we need to turn off. */	for(i=0; i<nnest; i++)		if(off&(1<<nest[i]))			break; 	/* turn off everything above that */	for(j=nnest-1; j>=i; j--)		iputs(&bout, offattr[nest[j]]); 	/* turn on everything we just turned off but didn't want to */	for(j=i; j<nnest; j++)		if(a&(1<<nest[j]))			iputs(&bout, onattr[nest[j]]);		else			nest[j] = 0; 	/* shift the zeros (turned off things) up */	for(i=j=0; i<nnest; i++)		if(nest[i] != 0)			nest[j++] = nest[i];	nnest = j; 	/* now turn on the new attributes */	for(i=0; i<nelem(attrorder); i++){		j = attrorder[i];		if(on&(1<<j)){			if(j == Anchor)				onattr[j] = anchors[nanchors++];			iputs(&bout, onattr[j]);			nest[nnest++] = j;		}	}	attr = a;} voidflush(void){	int i;	ulong c, a; 	nanchors = 0;	for(i=0; i<nchars; i++){		c = chars[i];		if(c == Epp){			iputrune(&bout, '\n');			iputs(&bout, TABLE "<tr height=5><td></table>");			iputrune(&bout, '\n');			continue;		}		a = c & ~0xFFFF;		c &= 0xFFFF;		/*		 * If we're going to something off after a space,		 * let's just turn it off before.		 */		if(c==' ' && i<nchars-1 && (chars[i+1]&0xFFFF) >= 32)			a ^= a & ~chars[i+1];		setattr(a);		if(c == Estring){			/* next word is string to print */			iputs(&bout, (char*)chars[++i]);			continue;		}		iputrune(&bout, c & 0xFFFF);	}} voidheader(char *s){	char *p; 	Bprint(&bout, "<head>\n");	if(pagename && section){		char buf[512];		strecpy(buf, buf+sizeof buf, pagename);		for(p=buf; *p; p++)			*p = tolower((uchar)*p);		Bprint(&bout, "<title>%s(%s) - %s</title>\n", buf, section, s);	}else		Bprint(&bout, "<title>%s</title>\n", s);	Bprint(&bout, "<meta content=\"text/html; charset=utf-8\" http-equiv=Content-Type>\n");	Bprint(&bout, "</head>\n");	Bprint(&bout, "<body bgcolor=#ffffff>\n");	Bprint(&bout, "<table border=0 cellpadding=0 cellspacing=0 width=100%%>\n");	Bprint(&bout, "<tr height=10><td>\n");	Bprint(&bout, "<tr><td width=20><td>\n");	if(pagename && section){		Bprint(&bout, "<tr><td width=20><td><b>%s(%s)</b><td align=right><b>%s(%s)</b>\n",			pagename, section, pagename, section);	}	Bprint(&bout, "<tr><td width=20><td colspan=2>\n");} voidtrailer(void){	Bprint(&bout, "<td width=20>\n");	Bprint(&bout, "<tr height=20><td>\n");	Bprint(&bout, "</table>\n"); #ifdef LUCENT    {	Tm *t; 	t = localtime(time(nil));	Bprint(&bout, TABLE "<tr height=20><td></table>\n");	Bprint(&bout, "<font size=-1><a href=\"http:/*www.lucent.com/copyright.html\">\n"); */	Bprint(&bout, "Portions Copyright</A> &#169; %d Lucent Technologies.  All rights reserved.</font>\n", t->year+1900);    }#endif	Bprint(&bout, "<!-- TRAILER -->\n");	Bprint(&bout, "</body></html>\n");} intgetc(Biobuf *b){	cno++;	return Bgetrune(b);} voidungetc(Biobuf *b){	cno--;	Bungetrune(b);} char*getline(Biobuf *b){	int i, c; 	for(i=0; i<sizeof buf; i++){		c = getc(b);		if(c == Beof)

Lines 1–500 of 871.