mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
add
This commit is contained in:
parent
49a1496cbb
commit
c42a1d3d61
31 changed files with 4745 additions and 2 deletions
148
src/cmd/htmlroff/a.h
Normal file
148
src/cmd/htmlroff/a.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
enum
|
||||
{
|
||||
Unbsp = 0x00A0,
|
||||
Uprivate = 0xF000,
|
||||
Uempty, /* \& */
|
||||
Uamp, /* raw & */
|
||||
Ult, /* raw < */
|
||||
Ugt, /* raw > */
|
||||
Utick, /* raw ' */
|
||||
Ubtick, /* raw ` */
|
||||
Uminus, /* raw - */
|
||||
Uspace, /* raw space */
|
||||
Upl, /* symbol + */
|
||||
Ueq, /* symbol = */
|
||||
Umi, /* symbol - */
|
||||
Uformatted, /* start diverted output */
|
||||
Uunformatted, /* end diverted output */
|
||||
|
||||
UPI = 720, /* units per inch */
|
||||
UPX = 10, /* units per pixel */
|
||||
|
||||
/* special input modes */
|
||||
CopyMode = 1<<1,
|
||||
ExpandMode = 1<<2,
|
||||
ArgMode = 1<<3,
|
||||
HtmlMode = 1<<4,
|
||||
|
||||
MaxLine = 1024,
|
||||
};
|
||||
|
||||
Rune* L(char*);
|
||||
|
||||
void addesc(Rune, int (*)(void), int);
|
||||
void addraw(Rune*, void(*)(Rune*));
|
||||
void addreq(Rune*, void(*)(int, Rune**), int);
|
||||
void af(Rune*, Rune*);
|
||||
void as(Rune*, Rune*);
|
||||
void br(void);
|
||||
void closehtml(void);
|
||||
Rune* copyarg(void);
|
||||
void delraw(Rune*);
|
||||
void delreq(Rune*);
|
||||
void ds(Rune*, Rune*);
|
||||
int dv(int);
|
||||
int e_nop(void);
|
||||
int e_warn(void);
|
||||
void* emalloc(uint);
|
||||
void* erealloc(void*, uint);
|
||||
Rune* erunesmprint(char*, ...);
|
||||
Rune* erunestrdup(Rune*);
|
||||
char* esmprint(char*, ...);
|
||||
char* estrdup(char*);
|
||||
int eval(Rune*);
|
||||
int evalscale(Rune*, int);
|
||||
Rune* getname(void);
|
||||
int getnext(void);
|
||||
Rune* getds(Rune*);
|
||||
Rune* _getnr(Rune*);
|
||||
int getnr(Rune*);
|
||||
int getnrr(Rune*);
|
||||
int getrune(void);
|
||||
Rune* getqarg(void);
|
||||
Rune* getline(void);
|
||||
void hideihtml(void);
|
||||
void html(Rune*, Rune*);
|
||||
void htmlinit(void);
|
||||
void ihtml(Rune*, Rune*);
|
||||
void inputnotify(void(*)(void));
|
||||
void itrap(void);
|
||||
void itrapset(void);
|
||||
int linefmt(Fmt*);
|
||||
void nr(Rune*, int);
|
||||
void _nr(Rune*, Rune*);
|
||||
void out(Rune*);
|
||||
void (*outcb)(Rune);
|
||||
void outhtml(Rune*);
|
||||
void outrune(Rune);
|
||||
void outtrap(void);
|
||||
int popinput(void);
|
||||
void printds(int);
|
||||
int pushinputfile(Rune*);
|
||||
void pushinputstring(Rune*);
|
||||
int pushstdin(void);
|
||||
int queueinputfile(Rune*);
|
||||
int queuestdin(void);
|
||||
void r_nop(int, Rune**);
|
||||
void r_warn(int, Rune**);
|
||||
Rune *readline(int);
|
||||
void reitag(void);
|
||||
void renraw(Rune*, Rune*);
|
||||
void renreq(Rune*, Rune*);
|
||||
void run(void);
|
||||
void runinput(void);
|
||||
int runmacro(int, int, Rune**);
|
||||
void runmacro1(Rune*);
|
||||
Rune* rune2html(Rune);
|
||||
void setlinenumber(Rune*, int);
|
||||
void showihtml(void);
|
||||
void sp(int);
|
||||
void t1init(void);
|
||||
void t2init(void);
|
||||
void t3init(void);
|
||||
void t4init(void);
|
||||
void t5init(void);
|
||||
void t6init(void);
|
||||
void t7init(void);
|
||||
void t8init(void);
|
||||
void t9init(void);
|
||||
void t10init(void);
|
||||
void t11init(void);
|
||||
void t12init(void);
|
||||
void t13init(void);
|
||||
void t14init(void);
|
||||
void t15init(void);
|
||||
void t16init(void);
|
||||
void t17init(void);
|
||||
void t18init(void);
|
||||
void t19init(void);
|
||||
void t20init(void);
|
||||
Rune troff2rune(Rune*);
|
||||
void unfont(void);
|
||||
void ungetnext(Rune);
|
||||
void ungetrune(Rune);
|
||||
void unitag(void);
|
||||
void warn(char*, ...);
|
||||
|
||||
extern int backslash;
|
||||
extern int bol;
|
||||
extern Biobuf bout;
|
||||
extern int broke;
|
||||
extern int dot;
|
||||
extern int inputmode;
|
||||
extern int inrequest;
|
||||
extern int tick;
|
||||
extern int utf8;
|
||||
extern int verbose;
|
||||
extern int linepos;
|
||||
|
||||
#define runemalloc(n) (Rune*)emalloc((n)*sizeof(Rune))
|
||||
#define runerealloc(r, n) (Rune*)erealloc(r, (n)*sizeof(Rune))
|
||||
#define runemove(a, b, n) memmove(a, b, (n)*sizeof(Rune))
|
||||
|
||||
#pragma varargck type "L" void
|
116
src/cmd/htmlroff/char.c
Normal file
116
src/cmd/htmlroff/char.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* Translate Unicode to HTML by asking tcs(1).
|
||||
* This way we don't have yet another table.
|
||||
*/
|
||||
Rune*
|
||||
rune2html(Rune r)
|
||||
{
|
||||
static Biobuf b;
|
||||
static int fd = -1;
|
||||
static Rune **tcscache[256];
|
||||
int p[2];
|
||||
char *q;
|
||||
|
||||
if(r == '\n')
|
||||
return L("\n");
|
||||
|
||||
if(tcscache[r>>8] && tcscache[r>>8][r&0xFF])
|
||||
return tcscache[r>>8][r&0xFF];
|
||||
|
||||
if(fd < 0){
|
||||
if(pipe(p) < 0)
|
||||
sysfatal("pipe: %r");
|
||||
switch(fork()){
|
||||
case -1:
|
||||
sysfatal("fork: %r");
|
||||
case 0:
|
||||
dup(p[0], 0);
|
||||
dup(p[0], 1);
|
||||
close(p[1]);
|
||||
execl("tcs", "tcs", "-t", "html", nil);
|
||||
_exits(0);
|
||||
default:
|
||||
close(p[0]);
|
||||
fd = p[1];
|
||||
Binit(&b, fd, OREAD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprint(fd, "%C\n", r);
|
||||
q = Brdline(&b, '\n');
|
||||
if(q == nil)
|
||||
sysfatal("tcs: early eof");
|
||||
q[Blinelen(&b)-1] = 0;
|
||||
if(tcscache[r>>8] == nil)
|
||||
tcscache[r>>8] = emalloc(256*sizeof tcscache[0][0]);
|
||||
tcscache[r>>8][r&0xFF] = erunesmprint("%s", q);
|
||||
return tcscache[r>>8][r&0xFF];
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate troff to Unicode by looking in troff's utfmap.
|
||||
* This way we don't have yet another hard-coded table.
|
||||
*/
|
||||
typedef struct Trtab Trtab;
|
||||
struct Trtab
|
||||
{
|
||||
char t[3];
|
||||
Rune r;
|
||||
};
|
||||
|
||||
static Trtab trtab[200];
|
||||
int ntrtab;
|
||||
|
||||
static Trtab trinit[] =
|
||||
{
|
||||
"pl", Upl,
|
||||
"eq", Ueq,
|
||||
"em", 0x2014,
|
||||
"en", 0x2013,
|
||||
"mi", Umi,
|
||||
"fm", 0x2032,
|
||||
};
|
||||
|
||||
Rune
|
||||
troff2rune(Rune *rs)
|
||||
{
|
||||
char *file, *f[10], *p, s[3];
|
||||
int i, nf;
|
||||
Biobuf *b;
|
||||
|
||||
if(rs[0] >= Runeself || rs[1] >= Runeself)
|
||||
return Runeerror;
|
||||
s[0] = rs[0];
|
||||
s[1] = rs[1];
|
||||
s[2] = 0;
|
||||
if(ntrtab == 0){
|
||||
for(i=0; i<nelem(trinit) && ntrtab < nelem(trtab); i++){
|
||||
trtab[ntrtab] = trinit[i];
|
||||
ntrtab++;
|
||||
}
|
||||
file = "/sys/lib/troff/font/devutf/utfmap";
|
||||
if((b = Bopen(file, OREAD)) == nil)
|
||||
sysfatal("open %s: %r", file);
|
||||
while((p = Brdline(b, '\n')) != nil){
|
||||
p[Blinelen(b)-1] = 0;
|
||||
nf = getfields(p, f, nelem(f), 0, "\t");
|
||||
for(i=0; i+2<=nf && ntrtab<nelem(trtab); i+=2){
|
||||
chartorune(&trtab[ntrtab].r, f[i]);
|
||||
memmove(trtab[ntrtab].t, f[i+1], 2);
|
||||
ntrtab++;
|
||||
}
|
||||
}
|
||||
Bterm(b);
|
||||
|
||||
if(ntrtab >= nelem(trtab))
|
||||
fprint(2, "%s: trtab too small\n", argv0);
|
||||
}
|
||||
|
||||
for(i=0; i<ntrtab; i++)
|
||||
if(strcmp(s, trtab[i].t) == 0)
|
||||
return trtab[i].r;
|
||||
return Runeerror;
|
||||
}
|
||||
|
287
src/cmd/htmlroff/html.c
Normal file
287
src/cmd/htmlroff/html.c
Normal file
|
@ -0,0 +1,287 @@
|
|||
/*
|
||||
* Emit html. Keep track of tags so that user doesn't have to.
|
||||
*/
|
||||
|
||||
#include "a.h"
|
||||
|
||||
typedef struct Tag Tag;
|
||||
struct Tag
|
||||
{
|
||||
Tag *next;
|
||||
Rune *id;
|
||||
Rune *open;
|
||||
Rune *close;
|
||||
};
|
||||
|
||||
Tag *tagstack;
|
||||
Tag *tagset;
|
||||
int hidingset;
|
||||
|
||||
static Rune*
|
||||
closingtag(Rune *s)
|
||||
{
|
||||
Rune *t;
|
||||
Rune *p0, *p;
|
||||
|
||||
t = runemalloc(sizeof(Rune));
|
||||
if(s == nil)
|
||||
return t;
|
||||
for(p=s; *p; p++){
|
||||
if(*p == Ult){
|
||||
p++;
|
||||
if(*p == '/'){
|
||||
while(*p && *p != Ugt)
|
||||
p++;
|
||||
goto close;
|
||||
}
|
||||
p0 = p;
|
||||
while(*p && !isspacerune(*p) && *p != Uspace && *p != Ugt)
|
||||
p++;
|
||||
t = runerealloc(t, 1+(p-p0)+2+runestrlen(t)+1);
|
||||
runemove(t+(p-p0)+3, t, runestrlen(t)+1);
|
||||
t[0] = Ult;
|
||||
t[1] = '/';
|
||||
runemove(t+2, p0, p-p0);
|
||||
t[2+(p-p0)] = Ugt;
|
||||
}
|
||||
|
||||
if(*p == Ugt && p>s && *(p-1) == '/'){
|
||||
close:
|
||||
for(p0=t+1; *p0 && *p0 != Ult; p0++)
|
||||
;
|
||||
runemove(t, p0, runestrlen(p0)+1);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
void
|
||||
html(Rune *id, Rune *s)
|
||||
{
|
||||
Rune *es;
|
||||
Tag *t, *tt, *next;
|
||||
|
||||
br();
|
||||
hideihtml(); /* br already did, but be paranoid */
|
||||
for(t=tagstack; t; t=t->next){
|
||||
if(runestrcmp(t->id, id) == 0){
|
||||
for(tt=tagstack;; tt=next){
|
||||
next = tt->next;
|
||||
free(tt->id);
|
||||
free(tt->open);
|
||||
out(tt->close);
|
||||
outrune('\n');
|
||||
free(tt->close);
|
||||
free(tt);
|
||||
if(tt == t){
|
||||
tagstack = next;
|
||||
goto cleared;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleared:
|
||||
if(s == nil || s[0] == 0)
|
||||
return;
|
||||
out(s);
|
||||
outrune('\n');
|
||||
es = closingtag(s);
|
||||
if(es[0] == 0){
|
||||
free(es);
|
||||
return;
|
||||
}
|
||||
if(runestrcmp(id, L("-")) == 0){
|
||||
out(es);
|
||||
outrune('\n');
|
||||
free(es);
|
||||
return;
|
||||
}
|
||||
t = emalloc(sizeof *t);
|
||||
t->id = erunestrdup(id);
|
||||
t->close = es;
|
||||
t->next = tagstack;
|
||||
tagstack = t;
|
||||
}
|
||||
|
||||
void
|
||||
closehtml(void)
|
||||
{
|
||||
Tag *t, *next;
|
||||
|
||||
br();
|
||||
hideihtml();
|
||||
for(t=tagstack; t; t=next){
|
||||
next = t->next;
|
||||
out(t->close);
|
||||
outrune('\n');
|
||||
free(t->id);
|
||||
free(t->close);
|
||||
free(t);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rshow(Tag *t, Tag *end)
|
||||
{
|
||||
if(t == nil || t == end)
|
||||
return;
|
||||
rshow(t->next, end);
|
||||
out(t->open);
|
||||
}
|
||||
|
||||
void
|
||||
ihtml(Rune *id, Rune *s)
|
||||
{
|
||||
Tag *t, *tt, **l;
|
||||
|
||||
for(t=tagset; t; t=t->next){
|
||||
if(runestrcmp(t->id, id) == 0){
|
||||
if(s && t->open && runestrcmp(t->open, s) == 0)
|
||||
return;
|
||||
for(l=&tagset; (tt=*l); l=&tt->next){
|
||||
if(!hidingset)
|
||||
out(tt->close);
|
||||
if(tt == t)
|
||||
break;
|
||||
}
|
||||
*l = t->next;
|
||||
free(t->id);
|
||||
free(t->close);
|
||||
free(t->open);
|
||||
free(t);
|
||||
if(!hidingset)
|
||||
rshow(tagset, *l);
|
||||
goto cleared;
|
||||
}
|
||||
}
|
||||
|
||||
cleared:
|
||||
if(s == nil || s[0] == 0)
|
||||
return;
|
||||
t = emalloc(sizeof *t);
|
||||
t->id = erunestrdup(id);
|
||||
t->open = erunestrdup(s);
|
||||
t->close = closingtag(s);
|
||||
if(!hidingset)
|
||||
out(s);
|
||||
t->next = tagset;
|
||||
tagset = t;
|
||||
}
|
||||
|
||||
void
|
||||
hideihtml(void)
|
||||
{
|
||||
Tag *t;
|
||||
|
||||
if(hidingset)
|
||||
return;
|
||||
hidingset = 1;
|
||||
for(t=tagset; t; t=t->next)
|
||||
out(t->close);
|
||||
}
|
||||
|
||||
void
|
||||
showihtml(void)
|
||||
{
|
||||
if(!hidingset)
|
||||
return;
|
||||
hidingset = 0;
|
||||
rshow(tagset, nil);
|
||||
}
|
||||
|
||||
int
|
||||
e_lt(void)
|
||||
{
|
||||
return Ult;
|
||||
}
|
||||
|
||||
int
|
||||
e_gt(void)
|
||||
{
|
||||
return Ugt;
|
||||
}
|
||||
|
||||
int
|
||||
e_at(void)
|
||||
{
|
||||
return Uamp;
|
||||
}
|
||||
|
||||
int
|
||||
e_tick(void)
|
||||
{
|
||||
return Utick;
|
||||
}
|
||||
|
||||
int
|
||||
e_btick(void)
|
||||
{
|
||||
return Ubtick;
|
||||
}
|
||||
|
||||
int
|
||||
e_minus(void)
|
||||
{
|
||||
return Uminus;
|
||||
}
|
||||
|
||||
void
|
||||
r_html(Rune *name)
|
||||
{
|
||||
Rune *id, *line, *p;
|
||||
|
||||
id = copyarg();
|
||||
line = readline(HtmlMode);
|
||||
for(p=line; *p; p++){
|
||||
switch(*p){
|
||||
case '<':
|
||||
*p = Ult;
|
||||
break;
|
||||
case '>':
|
||||
*p = Ugt;
|
||||
break;
|
||||
case '&':
|
||||
*p = Uamp;
|
||||
break;
|
||||
case ' ':
|
||||
*p = Uspace;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(name[0] == 'i')
|
||||
ihtml(id, line);
|
||||
else
|
||||
html(id, line);
|
||||
free(id);
|
||||
free(line);
|
||||
}
|
||||
|
||||
char defaultfont[] =
|
||||
".ihtml f1\n"
|
||||
".ihtml f\n"
|
||||
".ihtml f <span style=\"font-size=\\n(.spt\">\n"
|
||||
".if \\n(.f==2 .ihtml f1 <i>\n"
|
||||
".if \\n(.f==3 .ihtml f1 <b>\n"
|
||||
".if \\n(.f==4 .ihtml f1 <b><i>\n"
|
||||
".if \\n(.f==5 .ihtml f1 <tt>\n"
|
||||
".if \\n(.f==6 .ihtml f1 <tt><i>\n"
|
||||
"..\n"
|
||||
;
|
||||
|
||||
void
|
||||
htmlinit(void)
|
||||
{
|
||||
addraw(L("html"), r_html);
|
||||
addraw(L("ihtml"), r_html);
|
||||
|
||||
addesc('<', e_lt, CopyMode);
|
||||
addesc('>', e_gt, CopyMode);
|
||||
addesc('\'', e_tick, CopyMode);
|
||||
addesc('`', e_btick, CopyMode);
|
||||
addesc('-', e_minus, CopyMode);
|
||||
addesc('@', e_at, CopyMode);
|
||||
|
||||
ds(L("font"), L(defaultfont));
|
||||
}
|
||||
|
241
src/cmd/htmlroff/input.c
Normal file
241
src/cmd/htmlroff/input.c
Normal file
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* Read input files.
|
||||
*/
|
||||
#include "a.h"
|
||||
|
||||
typedef struct Istack Istack;
|
||||
struct Istack
|
||||
{
|
||||
Rune unget[3];
|
||||
int nunget;
|
||||
Biobuf *b;
|
||||
Rune *p;
|
||||
Rune *ep;
|
||||
Rune *s;
|
||||
int lineno;
|
||||
Rune *name;
|
||||
Istack *next;
|
||||
void (*fn)(void);
|
||||
};
|
||||
|
||||
Istack *istack;
|
||||
Istack *ibottom;
|
||||
|
||||
static void
|
||||
setname(void)
|
||||
{
|
||||
Rune *r, *p;
|
||||
|
||||
if(istack == nil || istack->name == nil)
|
||||
return;
|
||||
_nr(L(".F"), istack->name);
|
||||
r = erunestrdup(istack->name);
|
||||
p = runestrchr(r, '.');
|
||||
if(p)
|
||||
*p = 0;
|
||||
_nr(L(".B"), r);
|
||||
free(r);
|
||||
}
|
||||
|
||||
static void
|
||||
ipush(Istack *is)
|
||||
{
|
||||
if(istack == nil)
|
||||
ibottom = is;
|
||||
else
|
||||
is->next = istack;
|
||||
istack = is;
|
||||
setname();
|
||||
}
|
||||
|
||||
static void
|
||||
iqueue(Istack *is)
|
||||
{
|
||||
if(ibottom == nil){
|
||||
istack = is;
|
||||
setname();
|
||||
}else
|
||||
ibottom->next = is;
|
||||
ibottom = is;
|
||||
}
|
||||
|
||||
int
|
||||
_inputfile(Rune *s, void (*push)(Istack*))
|
||||
{
|
||||
Istack *is;
|
||||
Biobuf *b;
|
||||
char *t;
|
||||
|
||||
t = esmprint("%S", s);
|
||||
if((b = Bopen(t, OREAD)) == nil){
|
||||
free(t);
|
||||
fprint(2, "%s: open %S: %r\n", argv0, s);
|
||||
return -1;
|
||||
}
|
||||
free(t);
|
||||
is = emalloc(sizeof *is);
|
||||
is->b = b;
|
||||
is->name = erunestrdup(s);
|
||||
is->lineno = 1;
|
||||
push(is);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
pushinputfile(Rune *s)
|
||||
{
|
||||
return _inputfile(s, ipush);
|
||||
}
|
||||
|
||||
int
|
||||
queueinputfile(Rune *s)
|
||||
{
|
||||
return _inputfile(s, iqueue);
|
||||
}
|
||||
|
||||
int
|
||||
_inputstdin(void (*push)(Istack*))
|
||||
{
|
||||
Biobuf *b;
|
||||
Istack *is;
|
||||
|
||||
if((b = Bopen("/dev/null", OREAD)) == nil){
|
||||
fprint(2, "%s: open /dev/null: %r\n", argv0);
|
||||
return -1;
|
||||
}
|
||||
dup(0, b->fid);
|
||||
is = emalloc(sizeof *is);
|
||||
is->b = b;
|
||||
is->name = erunestrdup(L("stdin"));
|
||||
is->lineno = 1;
|
||||
push(is);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
pushstdin(void)
|
||||
{
|
||||
return _inputstdin(ipush);
|
||||
}
|
||||
|
||||
int
|
||||
queuestdin(void)
|
||||
{
|
||||
return _inputstdin(iqueue);
|
||||
}
|
||||
|
||||
void
|
||||
_inputstring(Rune *s, void (*push)(Istack*))
|
||||
{
|
||||
Istack *is;
|
||||
|
||||
is = emalloc(sizeof *is);
|
||||
is->s = erunestrdup(s);
|
||||
is->p = is->s;
|
||||
is->ep = is->p+runestrlen(is->p);
|
||||
push(is);
|
||||
}
|
||||
|
||||
void
|
||||
pushinputstring(Rune *s)
|
||||
{
|
||||
_inputstring(s, ipush);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
inputnotify(void (*fn)(void))
|
||||
{
|
||||
if(istack)
|
||||
istack->fn = fn;
|
||||
}
|
||||
|
||||
int
|
||||
popinput(void)
|
||||
{
|
||||
Istack *is;
|
||||
|
||||
is = istack;
|
||||
if(is == nil)
|
||||
return 0;
|
||||
|
||||
istack = istack->next;
|
||||
if(is->b)
|
||||
Bterm(is->b);
|
||||
free(is->s);
|
||||
free(is->name);
|
||||
if(is->fn)
|
||||
is->fn();
|
||||
free(is);
|
||||
setname();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
getrune(void)
|
||||
{
|
||||
Rune r;
|
||||
int c;
|
||||
|
||||
top:
|
||||
if(istack == nil)
|
||||
return -1;
|
||||
if(istack->nunget)
|
||||
return istack->unget[--istack->nunget];
|
||||
else if(istack->p){
|
||||
if(istack->p >= istack->ep){
|
||||
popinput();
|
||||
goto top;
|
||||
}
|
||||
r = *istack->p++;
|
||||
}else if(istack->b){
|
||||
if((c = Bgetrune(istack->b)) < 0){
|
||||
popinput();
|
||||
goto top;
|
||||
}
|
||||
r = c;
|
||||
}else{
|
||||
r = 0;
|
||||
sysfatal("getrune - can't happen");
|
||||
}
|
||||
if(r == '\n')
|
||||
istack->lineno++;
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
ungetrune(Rune r)
|
||||
{
|
||||
if(istack == nil || istack->nunget >= nelem(istack->unget))
|
||||
pushinputstring(L(""));
|
||||
istack->unget[istack->nunget++] = r;
|
||||
}
|
||||
|
||||
int
|
||||
linefmt(Fmt *f)
|
||||
{
|
||||
Istack *is;
|
||||
|
||||
for(is=istack; is && !is->b; is=is->next)
|
||||
;
|
||||
if(is)
|
||||
return fmtprint(f, "%S:%d", is->name, is->lineno);
|
||||
else
|
||||
return fmtprint(f, "<no input>");
|
||||
}
|
||||
|
||||
void
|
||||
setlinenumber(Rune *s, int n)
|
||||
{
|
||||
Istack *is;
|
||||
|
||||
for(is=istack; is && !is->name; is=is->next)
|
||||
;
|
||||
if(is){
|
||||
if(s){
|
||||
free(is->name);
|
||||
is->name = erunestrdup(s);
|
||||
}
|
||||
is->lineno = n;
|
||||
}
|
||||
}
|
72
src/cmd/htmlroff/main.c
Normal file
72
src/cmd/htmlroff/main.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Convert troff -ms input to HTML.
|
||||
*/
|
||||
|
||||
#include "a.h"
|
||||
|
||||
Biobuf bout;
|
||||
char* tmacdir;
|
||||
int verbose;
|
||||
int utf8 = 0;
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: htmlroff [-iuv] [-m mac] [-r an] [file...]\n");
|
||||
exits("usage");
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i, dostdin;
|
||||
char *p;
|
||||
Rune *r;
|
||||
Rune buf[2];
|
||||
|
||||
Binit(&bout, 1, OWRITE);
|
||||
fmtinstall('L', linefmt);
|
||||
quotefmtinstall();
|
||||
|
||||
tmacdir = unsharp("#9/tmac");
|
||||
dostdin = 0;
|
||||
ARGBEGIN{
|
||||
case 'i':
|
||||
dostdin = 1;
|
||||
break;
|
||||
case 'm':
|
||||
r = erunesmprint("%s/tmac.%s", tmacdir, EARGF(usage()));
|
||||
if(queueinputfile(r) < 0)
|
||||
fprint(2, "%S: %r\n", r);
|
||||
break;
|
||||
case 'r':
|
||||
p = EARGF(usage());
|
||||
p += chartorune(buf, p);
|
||||
buf[1] = 0;
|
||||
_nr(buf, erunesmprint("%s", p+1));
|
||||
break;
|
||||
case 'u':
|
||||
utf8 = 1;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}ARGEND
|
||||
|
||||
for(i=0; i<argc; i++){
|
||||
if(strcmp(argv[i], "-") == 0)
|
||||
queuestdin();
|
||||
else
|
||||
queueinputfile(erunesmprint("%s", argv[i]));
|
||||
}
|
||||
if(argc == 0 || dostdin)
|
||||
queuestdin();
|
||||
|
||||
run();
|
||||
Bprint(&bout, "\n");
|
||||
Bterm(&bout);
|
||||
exits(nil);
|
||||
}
|
||||
|
58
src/cmd/htmlroff/mkfile
Normal file
58
src/cmd/htmlroff/mkfile
Normal file
|
@ -0,0 +1,58 @@
|
|||
<$PLAN9/src/mkhdr
|
||||
|
||||
TARG=htmlroff
|
||||
|
||||
OFILES=\
|
||||
char.$O\
|
||||
html.$O\
|
||||
input.$O\
|
||||
main.$O\
|
||||
roff.$O\
|
||||
t1.$O\
|
||||
t2.$O\
|
||||
t3.$O\
|
||||
t4.$O\
|
||||
t5.$O\
|
||||
t6.$O\
|
||||
t7.$O\
|
||||
t8.$O\
|
||||
# t9.$O\
|
||||
t10.$O\
|
||||
t11.$O\
|
||||
# t12.$O\
|
||||
t13.$O\
|
||||
t14.$O\
|
||||
t15.$O\
|
||||
t16.$O\
|
||||
t17.$O\
|
||||
t18.$O\
|
||||
t19.$O\
|
||||
t20.$O\
|
||||
util.$O\
|
||||
|
||||
HFILES=a.h
|
||||
|
||||
<$PLAN9/src/mkone
|
||||
|
||||
auth:V: auth.html
|
||||
web auth.html
|
||||
|
||||
auth.html: o.htmlroff auth.ms htmlmac.s
|
||||
9 pic auth.ms | 9 eqn | ./o.htmlroff -ms >auth.html
|
||||
# 9 pic auth.ms | 9 eqn | ./o.htmlroff htmlmac.s /usr/local/plan9/tmac/tmac.skeep - >auth.html
|
||||
|
||||
test%.html: o.htmlroff test.% htmlmac.s
|
||||
./o.htmlroff htmlmac.s test.$stem - >$target
|
||||
|
||||
eqn:V: eqn.html
|
||||
web eqn.html
|
||||
|
||||
eqn.html: o.htmlroff htmlmac.s eqn.ms
|
||||
9 eqn eqn.ms | ./o.htmlroff htmlmac.s - >eqn.html
|
||||
|
||||
eqn0.html: o.htmlroff htmlmac.s eqn0.ms
|
||||
./o.htmlroff htmlmac.s eqn0.ms - >eqn0.html
|
||||
|
||||
rc.html: o.htmlroff rc.ms htmlmac.s
|
||||
9 tbl rc.ms | ./o.htmlroff -ms >rc.html
|
||||
|
750
src/cmd/htmlroff/roff.c
Normal file
750
src/cmd/htmlroff/roff.c
Normal file
|
@ -0,0 +1,750 @@
|
|||
#include "a.h"
|
||||
|
||||
enum
|
||||
{
|
||||
MAXREQ = 100,
|
||||
MAXRAW = 40,
|
||||
MAXESC = 60,
|
||||
MAXLINE = 1024,
|
||||
MAXIF = 20,
|
||||
MAXARG = 10,
|
||||
};
|
||||
|
||||
typedef struct Esc Esc;
|
||||
typedef struct Req Req;
|
||||
typedef struct Raw Raw;
|
||||
|
||||
/* escape sequence handler, like for \c */
|
||||
struct Esc
|
||||
{
|
||||
Rune r;
|
||||
int (*f)(void);
|
||||
int mode;
|
||||
};
|
||||
|
||||
/* raw request handler, like for .ie */
|
||||
struct Raw
|
||||
{
|
||||
Rune *name;
|
||||
void (*f)(Rune*);
|
||||
};
|
||||
|
||||
/* regular request handler, like for .ft */
|
||||
struct Req
|
||||
{
|
||||
int argc;
|
||||
Rune *name;
|
||||
void (*f)(int, Rune**);
|
||||
};
|
||||
|
||||
int dot = '.';
|
||||
int tick = '\'';
|
||||
int backslash = '\\';
|
||||
|
||||
int inputmode;
|
||||
Req req[MAXREQ];
|
||||
int nreq;
|
||||
Raw raw[MAXRAW];
|
||||
int nraw;
|
||||
Esc esc[MAXESC];
|
||||
int nesc;
|
||||
int iftrue[MAXIF];
|
||||
int niftrue;
|
||||
|
||||
int isoutput;
|
||||
int linepos;
|
||||
|
||||
|
||||
void
|
||||
addraw(Rune *name, void (*f)(Rune*))
|
||||
{
|
||||
Raw *r;
|
||||
|
||||
if(nraw >= nelem(raw)){
|
||||
fprint(2, "too many raw requets\n");
|
||||
return;
|
||||
}
|
||||
r = &raw[nraw++];
|
||||
r->name = erunestrdup(name);
|
||||
r->f = f;
|
||||
}
|
||||
|
||||
void
|
||||
delraw(Rune *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<nraw; i++){
|
||||
if(runestrcmp(raw[i].name, name) == 0){
|
||||
if(i != --nraw){
|
||||
free(raw[i].name);
|
||||
raw[i] = raw[nraw];
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
renraw(Rune *from, Rune *to)
|
||||
{
|
||||
int i;
|
||||
|
||||
delraw(to);
|
||||
for(i=0; i<nraw; i++)
|
||||
if(runestrcmp(raw[i].name, from) == 0){
|
||||
free(raw[i].name);
|
||||
raw[i].name = erunestrdup(to);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
addreq(Rune *s, void (*f)(int, Rune**), int argc)
|
||||
{
|
||||
Req *r;
|
||||
|
||||
if(nreq >= nelem(req)){
|
||||
fprint(2, "too many requests\n");
|
||||
return;
|
||||
}
|
||||
r = &req[nreq++];
|
||||
r->name = erunestrdup(s);
|
||||
r->f = f;
|
||||
r->argc = argc;
|
||||
}
|
||||
|
||||
void
|
||||
delreq(Rune *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<nreq; i++){
|
||||
if(runestrcmp(req[i].name, name) == 0){
|
||||
if(i != --nreq){
|
||||
free(req[i].name);
|
||||
req[i] = req[nreq];
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
renreq(Rune *from, Rune *to)
|
||||
{
|
||||
int i;
|
||||
|
||||
delreq(to);
|
||||
for(i=0; i<nreq; i++)
|
||||
if(runestrcmp(req[i].name, from) == 0){
|
||||
free(req[i].name);
|
||||
req[i].name = erunestrdup(to);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
addesc(Rune r, int (*f)(void), int mode)
|
||||
{
|
||||
Esc *e;
|
||||
|
||||
if(nesc >= nelem(esc)){
|
||||
fprint(2, "too many escapes\n");
|
||||
return;
|
||||
}
|
||||
e = &esc[nesc++];
|
||||
e->r = r;
|
||||
e->f = f;
|
||||
e->mode = mode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next logical character in the input stream.
|
||||
*/
|
||||
int
|
||||
getnext(void)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
next:
|
||||
r = getrune();
|
||||
if(r < 0)
|
||||
return -1;
|
||||
if(r == Uformatted){
|
||||
br();
|
||||
assert(!isoutput);
|
||||
while((r = getrune()) >= 0 && r != Uunformatted){
|
||||
if(r == Uformatted)
|
||||
continue;
|
||||
outrune(r);
|
||||
}
|
||||
goto next;
|
||||
}
|
||||
if(r == Uunformatted)
|
||||
goto next;
|
||||
if(r == backslash){
|
||||
r = getrune();
|
||||
if(r < 0)
|
||||
return -1;
|
||||
for(i=0; i<nesc; i++){
|
||||
if(r == esc[i].r && (inputmode&esc[i].mode)==inputmode){
|
||||
if(esc[i].f == e_warn)
|
||||
warn("ignoring %C%C", backslash, r);
|
||||
r = esc[i].f();
|
||||
if(r <= 0)
|
||||
goto next;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
if(inputmode&(ArgMode|CopyMode)){
|
||||
ungetrune(r);
|
||||
r = backslash;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
ungetnext(Rune r)
|
||||
{
|
||||
/*
|
||||
* really we want to undo the getrunes that led us here,
|
||||
* since the call after ungetnext might be getrune!
|
||||
*/
|
||||
ungetrune(r);
|
||||
}
|
||||
|
||||
int
|
||||
_readx(Rune *p, int n, int nmode, int line)
|
||||
{
|
||||
int c, omode;
|
||||
Rune *e;
|
||||
|
||||
while((c = getrune()) == ' ' || c == '\t')
|
||||
;
|
||||
ungetrune(c);
|
||||
omode = inputmode;
|
||||
inputmode = nmode;
|
||||
e = p+n-1;
|
||||
for(c=getnext(); p<e; c=getnext()){
|
||||
if(c < 0)
|
||||
break;
|
||||
if(!line && (c == ' ' || c == '\t'))
|
||||
break;
|
||||
if(c == '\n'){
|
||||
if(!line)
|
||||
ungetnext(c);
|
||||
break;
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
inputmode = omode;
|
||||
*p = 0;
|
||||
if(c < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next argument from the current line.
|
||||
*/
|
||||
Rune*
|
||||
copyarg(void)
|
||||
{
|
||||
static Rune buf[MaxLine];
|
||||
int c;
|
||||
Rune *r;
|
||||
|
||||
if(_readx(buf, sizeof buf, ArgMode, 0) < 0)
|
||||
return nil;
|
||||
r = runestrstr(buf, L("\\\""));
|
||||
if(r){
|
||||
*r = 0;
|
||||
while((c = getrune()) >= 0 && c != '\n')
|
||||
;
|
||||
ungetrune('\n');
|
||||
}
|
||||
r = erunestrdup(buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the current line in given mode. Newline not kept.
|
||||
* Uses different buffer from copyarg!
|
||||
*/
|
||||
Rune*
|
||||
readline(int m)
|
||||
{
|
||||
static Rune buf[MaxLine];
|
||||
Rune *r;
|
||||
|
||||
if(_readx(buf, sizeof buf, m, 1) < 0)
|
||||
return nil;
|
||||
r = erunestrdup(buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the argument line (already read in copy+arg mode),
|
||||
* parse into arguments. Note that \" has been left in place
|
||||
* during copy+arg mode parsing, so comments still need to be stripped.
|
||||
*/
|
||||
int
|
||||
parseargs(Rune *p, Rune **argv)
|
||||
{
|
||||
int argc;
|
||||
Rune *w;
|
||||
|
||||
for(argc=0; argc<MAXARG; argc++){
|
||||
while(*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
if(*p == 0)
|
||||
break;
|
||||
argv[argc] = p;
|
||||
if(*p == '"'){
|
||||
/* quoted argument */
|
||||
if(*(p+1) == '"'){
|
||||
/* empty argument */
|
||||
*p = 0;
|
||||
p += 2;
|
||||
}else{
|
||||
/* parse quoted string */
|
||||
w = p++;
|
||||
for(; *p; p++){
|
||||
if(*p == '"' && *(p+1) == '"')
|
||||
*w++ = '"';
|
||||
else if(*p == '"'){
|
||||
p++;
|
||||
break;
|
||||
}else
|
||||
*w++ = *p;
|
||||
}
|
||||
*w = 0;
|
||||
}
|
||||
}else{
|
||||
/* unquoted argument - need to watch out for \" comment */
|
||||
for(; *p; p++){
|
||||
if(*p == ' ' || *p == '\t'){
|
||||
*p++ = 0;
|
||||
break;
|
||||
}
|
||||
if(*p == '\\' && *(p+1) == '"'){
|
||||
*p = 0;
|
||||
if(p != argv[argc])
|
||||
argc++;
|
||||
return argc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return argc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a dot line. The dot has been read.
|
||||
*/
|
||||
void
|
||||
dotline(int dot)
|
||||
{
|
||||
int argc, i;
|
||||
Rune *a, *argv[1+MAXARG];
|
||||
|
||||
/*
|
||||
* Read request/macro name
|
||||
*/
|
||||
a = copyarg();
|
||||
if(a == nil || a[0] == 0){
|
||||
free(a);
|
||||
getrune(); /* \n */
|
||||
return;
|
||||
}
|
||||
argv[0] = a;
|
||||
/*
|
||||
* Check for .if, .ie, and others with special parsing.
|
||||
*/
|
||||
for(i=0; i<nraw; i++){
|
||||
if(runestrcmp(raw[i].name, a) == 0){
|
||||
raw[i].f(raw[i].name);
|
||||
free(a);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read rest of line in copy mode, invoke regular request.
|
||||
*/
|
||||
a = readline(ArgMode);
|
||||
if(a == nil){
|
||||
free(argv[0]);
|
||||
return;
|
||||
}
|
||||
argc = 1+parseargs(a, argv+1);
|
||||
for(i=0; i<nreq; i++){
|
||||
if(runestrcmp(req[i].name, argv[0]) == 0){
|
||||
if(req[i].argc != -1){
|
||||
if(argc < 1+req[i].argc){
|
||||
warn("not enough arguments for %C%S", dot, req[i].name);
|
||||
free(argv[0]);
|
||||
free(a);
|
||||
return;
|
||||
}
|
||||
if(argc > 1+req[i].argc)
|
||||
warn("too many arguments for %C%S", dot, req[i].name);
|
||||
}
|
||||
req[i].f(argc, argv);
|
||||
free(argv[0]);
|
||||
free(a);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke user-defined macros.
|
||||
*/
|
||||
runmacro(dot, argc, argv);
|
||||
free(argv[0]);
|
||||
free(a);
|
||||
}
|
||||
|
||||
/*
|
||||
* newlines are magical in various ways.
|
||||
*/
|
||||
int bol;
|
||||
void
|
||||
newline(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
if(bol)
|
||||
sp(eval(L("1v")));
|
||||
bol = 1;
|
||||
if((n=getnr(L(".ce"))) > 0){
|
||||
nr(L(".ce"), n-1);
|
||||
br();
|
||||
}
|
||||
if(getnr(L(".fi")) == 0)
|
||||
br();
|
||||
outrune('\n');
|
||||
}
|
||||
|
||||
void
|
||||
startoutput(void)
|
||||
{
|
||||
char *align;
|
||||
double ps, vs, lm, rm, ti;
|
||||
Rune buf[200];
|
||||
|
||||
if(isoutput)
|
||||
return;
|
||||
isoutput = 1;
|
||||
|
||||
if(getnr(L(".paragraph")) == 0)
|
||||
return;
|
||||
|
||||
nr(L(".ns"), 0);
|
||||
isoutput = 1;
|
||||
ps = getnr(L(".s"));
|
||||
if(ps <= 1)
|
||||
ps = 10;
|
||||
ps /= 72.0;
|
||||
USED(ps);
|
||||
|
||||
vs = getnr(L(".v"))*getnr(L(".ls")) * 1.0/UPI;
|
||||
vs /= (10.0/72.0); /* ps */
|
||||
if(vs == 0)
|
||||
vs = 1.2;
|
||||
|
||||
lm = (getnr(L(".o"))+getnr(L(".i"))) * 1.0/UPI;
|
||||
ti = getnr(L(".ti")) * 1.0/UPI;
|
||||
nr(L(".ti"), 0);
|
||||
|
||||
rm = 8.0 - getnr(L(".l"))*1.0/UPI - getnr(L(".o"))*1.0/UPI;
|
||||
if(rm < 0)
|
||||
rm = 0;
|
||||
switch(getnr(L(".j"))){
|
||||
default:
|
||||
case 0:
|
||||
align = "left";
|
||||
break;
|
||||
case 1:
|
||||
align = "justify";
|
||||
break;
|
||||
case 3:
|
||||
align = "center";
|
||||
break;
|
||||
case 5:
|
||||
align = "right";
|
||||
break;
|
||||
}
|
||||
if(getnr(L(".ce")))
|
||||
align = "center";
|
||||
if(!getnr(L(".margin")))
|
||||
runesnprint(buf, nelem(buf), "<p style=\"line-height: %.1fem; text-indent: %.2fin; margin-top: 0; margin-bottom: 0; text-align: %s;\">\n",
|
||||
vs, ti, align);
|
||||
else
|
||||
runesnprint(buf, nelem(buf), "<p style=\"line-height: %.1fem; margin-left: %.2fin; text-indent: %.2fin; margin-right: %.2fin; margin-top: 0; margin-bottom: 0; text-align: %s;\">\n",
|
||||
vs, lm, ti, rm, align);
|
||||
outhtml(buf);
|
||||
}
|
||||
void
|
||||
br(void)
|
||||
{
|
||||
if(!isoutput)
|
||||
return;
|
||||
isoutput = 0;
|
||||
|
||||
nr(L(".dv"), 0);
|
||||
dv(0);
|
||||
hideihtml();
|
||||
if(getnr(L(".paragraph")))
|
||||
outhtml(L("</p>"));
|
||||
}
|
||||
|
||||
void
|
||||
r_margin(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
|
||||
nr(L(".margin"), eval(argv[1]));
|
||||
}
|
||||
|
||||
int inrequest;
|
||||
void
|
||||
runinput(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
bol = 1;
|
||||
for(;;){
|
||||
c = getnext();
|
||||
if(c < 0)
|
||||
break;
|
||||
if((c == dot || c == tick) && bol){
|
||||
inrequest = 1;
|
||||
dotline(c);
|
||||
bol = 1;
|
||||
inrequest = 0;
|
||||
}else if(c == '\n'){
|
||||
newline();
|
||||
itrap();
|
||||
linepos = 0;
|
||||
}else{
|
||||
outtrap();
|
||||
startoutput();
|
||||
showihtml();
|
||||
if(c == '\t'){
|
||||
/* XXX do better */
|
||||
outrune(' ');
|
||||
while(++linepos%4)
|
||||
outrune(' ');
|
||||
}else{
|
||||
outrune(c);
|
||||
linepos++;
|
||||
}
|
||||
bol = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run(void)
|
||||
{
|
||||
t1init();
|
||||
t2init();
|
||||
t3init();
|
||||
t4init();
|
||||
t5init();
|
||||
t6init();
|
||||
t7init();
|
||||
t8init();
|
||||
/* t9init(); t9.c */
|
||||
t10init();
|
||||
t11init();
|
||||
/* t12init(); t12.c */
|
||||
t13init();
|
||||
t14init();
|
||||
t15init();
|
||||
t16init();
|
||||
t17init();
|
||||
t18init();
|
||||
t19init();
|
||||
t20init();
|
||||
htmlinit();
|
||||
hideihtml();
|
||||
|
||||
addreq(L("margin"), r_margin, 1);
|
||||
nr(L(".margin"), 1);
|
||||
nr(L(".paragraph"), 1);
|
||||
|
||||
runinput();
|
||||
while(popinput())
|
||||
;
|
||||
dot = '.';
|
||||
if(verbose)
|
||||
fprint(2, "eof\n");
|
||||
runmacro1(L("eof"));
|
||||
closehtml();
|
||||
}
|
||||
|
||||
void
|
||||
out(Rune *s)
|
||||
{
|
||||
if(s == nil)
|
||||
return;
|
||||
for(; *s; s++)
|
||||
outrune(*s);
|
||||
}
|
||||
|
||||
void (*outcb)(Rune);
|
||||
|
||||
void
|
||||
inroman(Rune r)
|
||||
{
|
||||
int f;
|
||||
|
||||
f = getnr(L(".f"));
|
||||
nr(L(".f"), 1);
|
||||
runmacro1(L("font"));
|
||||
outrune(r);
|
||||
nr(L(".f"), f);
|
||||
runmacro1(L("font"));
|
||||
}
|
||||
|
||||
void
|
||||
Brune(Rune r)
|
||||
{
|
||||
if(r == '&')
|
||||
Bprint(&bout, "&");
|
||||
else if(r == '<')
|
||||
Bprint(&bout, "<");
|
||||
else if(r == '>')
|
||||
Bprint(&bout, ">");
|
||||
else if(r < Runeself || utf8)
|
||||
Bprint(&bout, "%C", r);
|
||||
else
|
||||
Bprint(&bout, "%S", rune2html(r));
|
||||
}
|
||||
|
||||
void
|
||||
outhtml(Rune *s)
|
||||
{
|
||||
Rune r;
|
||||
|
||||
for(; *s; s++){
|
||||
switch(r = *s){
|
||||
case '<':
|
||||
r = Ult;
|
||||
break;
|
||||
case '>':
|
||||
r = Ugt;
|
||||
break;
|
||||
case '&':
|
||||
r = Uamp;
|
||||
break;
|
||||
case ' ':
|
||||
r = Uspace;
|
||||
break;
|
||||
}
|
||||
outrune(r);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outrune(Rune r)
|
||||
{
|
||||
switch(r){
|
||||
case ' ':
|
||||
if(getnr(L(".fi")) == 0)
|
||||
r = Unbsp;
|
||||
break;
|
||||
case Uformatted:
|
||||
case Uunformatted:
|
||||
abort();
|
||||
}
|
||||
if(outcb){
|
||||
if(r == ' ')
|
||||
r = Uspace;
|
||||
outcb(r);
|
||||
return;
|
||||
}
|
||||
/* writing to bout */
|
||||
switch(r){
|
||||
case Uempty:
|
||||
return;
|
||||
case Upl:
|
||||
inroman('+');
|
||||
return;
|
||||
case Ueq:
|
||||
inroman('=');
|
||||
return;
|
||||
case Umi:
|
||||
inroman(0x2212);
|
||||
return;
|
||||
case Utick:
|
||||
r = '\'';
|
||||
break;
|
||||
case Ubtick:
|
||||
r = '`';
|
||||
break;
|
||||
case Uminus:
|
||||
r = '-';
|
||||
break;
|
||||
case '\'':
|
||||
Bprint(&bout, "’");
|
||||
return;
|
||||
case '`':
|
||||
Bprint(&bout, "‘");
|
||||
return;
|
||||
case Uamp:
|
||||
Bputrune(&bout, '&');
|
||||
return;
|
||||
case Ult:
|
||||
Bputrune(&bout, '<');
|
||||
return;
|
||||
case Ugt:
|
||||
Bputrune(&bout, '>');
|
||||
return;
|
||||
case Uspace:
|
||||
Bputrune(&bout, ' ');
|
||||
return;
|
||||
case 0x2032:
|
||||
/*
|
||||
* In Firefox, at least, the prime is not
|
||||
* a superscript by default.
|
||||
*/
|
||||
Bprint(&bout, "<sup>");
|
||||
Brune(r);
|
||||
Bprint(&bout, "</sup>");
|
||||
return;
|
||||
}
|
||||
Brune(r);
|
||||
}
|
||||
|
||||
void
|
||||
r_nop(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
USED(argv);
|
||||
}
|
||||
|
||||
void
|
||||
r_warn(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
warn("ignoring %C%S", dot, argv[0]);
|
||||
}
|
||||
|
||||
int
|
||||
e_warn(void)
|
||||
{
|
||||
/* dispatch loop prints a warning for us */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_nop(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
186
src/cmd/htmlroff/t1.c
Normal file
186
src/cmd/htmlroff/t1.c
Normal file
|
@ -0,0 +1,186 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* Section 1 - General Explanation.
|
||||
*/
|
||||
|
||||
/* 1.3 - Numerical parameter input. */
|
||||
char *units = "icPmnpuvx";
|
||||
int
|
||||
scale2units(char c)
|
||||
{
|
||||
int x;
|
||||
|
||||
switch(c){
|
||||
case 'i': /* inch */
|
||||
return UPI;
|
||||
case 'c': /* centimeter */
|
||||
return 0.3937008 * UPI;
|
||||
case 'P': /* pica = 1/6 inch */
|
||||
return UPI / 6;
|
||||
case 'm': /* em = S points */
|
||||
return UPI / 72.0 * getnr(L(".s"));
|
||||
case 'n': /* en = em/2 */
|
||||
return UPI / 72.0 * getnr(L(".s")) / 2;
|
||||
case 'p': /* point = 1/72 inch */
|
||||
return UPI / 72;
|
||||
case 'u': /* basic unit */
|
||||
return 1;
|
||||
case 'v': /* vertical line space V */
|
||||
x = getnr(L(".v"));
|
||||
if(x == 0)
|
||||
x = 12 * UPI / 72;
|
||||
return x;
|
||||
case 'x': /* pixel (htmlroff addition) */
|
||||
return UPX;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 1.4 - Numerical expressions. */
|
||||
int eval0(Rune**, int, int);
|
||||
int
|
||||
eval(Rune *s)
|
||||
{
|
||||
return eval0(&s, 1, 1);
|
||||
}
|
||||
long
|
||||
runestrtol(Rune *a, Rune **p)
|
||||
{
|
||||
long n;
|
||||
|
||||
n = 0;
|
||||
while('0' <= *a && *a <= '9'){
|
||||
n = n*10 + *a-'0';
|
||||
a++;
|
||||
}
|
||||
*p = a;
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
evalscale(Rune *s, int c)
|
||||
{
|
||||
return eval0(&s, scale2units(c), 1);
|
||||
}
|
||||
|
||||
int
|
||||
eval0(Rune **pline, int scale, int recur)
|
||||
{
|
||||
Rune *p;
|
||||
int neg;
|
||||
double f, p10;
|
||||
int x, y;
|
||||
|
||||
neg = 0;
|
||||
p = *pline;
|
||||
while(*p == '-'){
|
||||
neg = 1 - neg;
|
||||
p++;
|
||||
}
|
||||
if(*p == '('){
|
||||
p++;
|
||||
x = eval0(&p, scale, 1);
|
||||
if (*p != ')'){
|
||||
*pline = p;
|
||||
return x;
|
||||
}
|
||||
p++;
|
||||
}else{
|
||||
f = runestrtol(p, &p);
|
||||
if(*p == '.'){
|
||||
p10 = 1.0;
|
||||
p++;
|
||||
while('0' <= *p && *p <= '9'){
|
||||
p10 /= 10;
|
||||
f += p10*(*p++ - '0');
|
||||
}
|
||||
}
|
||||
if(*p && strchr(units, *p)){
|
||||
if(scale)
|
||||
f *= scale2units(*p);
|
||||
p++;
|
||||
}else if(scale)
|
||||
f *= scale;
|
||||
x = f;
|
||||
}
|
||||
if(neg)
|
||||
x = -x;
|
||||
if(!recur){
|
||||
*pline = p;
|
||||
return x;
|
||||
}
|
||||
|
||||
while(*p){
|
||||
switch(*p++) {
|
||||
case '+':
|
||||
x += eval0(&p, scale, 0);
|
||||
continue;
|
||||
case '-':
|
||||
x -= eval0(&p, scale, 0);
|
||||
continue;
|
||||
case '*':
|
||||
x *= eval0(&p, scale, 0);
|
||||
continue;
|
||||
case '/':
|
||||
y = eval0(&p, scale, 0);
|
||||
if (y == 0) {
|
||||
fprint(2, "%L: divide by zero %S\n", p);
|
||||
y = 1;
|
||||
}
|
||||
x /= y;
|
||||
continue;
|
||||
case '%':
|
||||
y = eval0(&p, scale, 0);
|
||||
if (!y) {
|
||||
fprint(2, "%L: modulo by zero %S\n", p);
|
||||
y = 1;
|
||||
}
|
||||
x %= y;
|
||||
continue;
|
||||
case '<':
|
||||
if (*p == '=') {
|
||||
p++;
|
||||
x = x <= eval0(&p, scale, 0);
|
||||
continue;
|
||||
}
|
||||
x = x < eval0(&p, scale, 0);
|
||||
continue;
|
||||
case '>':
|
||||
if (*p == '=') {
|
||||
p++;
|
||||
x = x >= eval0(&p, scale, 0);
|
||||
continue;
|
||||
}
|
||||
x = x > eval0(&p, scale, 0);
|
||||
continue;
|
||||
case '=':
|
||||
if (*p == '=')
|
||||
p++;
|
||||
x = x == eval0(&p, scale, 0);
|
||||
continue;
|
||||
case '&':
|
||||
x &= eval0(&p, scale, 0);
|
||||
continue;
|
||||
case ':':
|
||||
x |= eval0(&p, scale, 0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*pline = p;
|
||||
return x;
|
||||
}
|
||||
|
||||
void
|
||||
t1init(void)
|
||||
{
|
||||
Tm tm;
|
||||
|
||||
tm = *localtime(time(0));
|
||||
nr(L("dw"), tm.wday+1);
|
||||
nr(L("dy"), tm.mday);
|
||||
nr(L("mo"), tm.mon);
|
||||
nr(L("yr"), tm.year%100);
|
||||
}
|
||||
|
140
src/cmd/htmlroff/t10.c
Normal file
140
src/cmd/htmlroff/t10.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* 10. Input and Output Conventions and Character Translation.
|
||||
*/
|
||||
|
||||
/* set escape character */
|
||||
void
|
||||
r_ec(int argc, Rune **argv)
|
||||
{
|
||||
if(argc == 1)
|
||||
backslash = '\\';
|
||||
else
|
||||
backslash = argv[1][0];
|
||||
}
|
||||
|
||||
/* turn off escape character */
|
||||
void
|
||||
r_eo(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
USED(argv);
|
||||
backslash = -2;
|
||||
}
|
||||
|
||||
/* continuous underline (same as ul in troff) for the next N lines */
|
||||
/* set underline font */
|
||||
void
|
||||
g_uf(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
USED(argv);
|
||||
}
|
||||
|
||||
/* set control character */
|
||||
void
|
||||
r_cc(int argc, Rune **argv)
|
||||
{
|
||||
if(argc == 1)
|
||||
dot = '.';
|
||||
else
|
||||
dot = argv[1][0];
|
||||
}
|
||||
|
||||
/* set no-break control character */
|
||||
void
|
||||
r_c2(int argc, Rune **argv)
|
||||
{
|
||||
if(argc == 1)
|
||||
tick = '\'';
|
||||
else
|
||||
tick = argv[1][0];
|
||||
}
|
||||
|
||||
/* output translation */
|
||||
|
||||
int
|
||||
e_bang(void)
|
||||
{
|
||||
Rune *line;
|
||||
|
||||
line = readline(CopyMode);
|
||||
out(line);
|
||||
outrune('\n');
|
||||
free(line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_X(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
while((c = getrune()) >= 0 && c != '\'' && c != '\n')
|
||||
outrune(c);
|
||||
if(c == '\n'){
|
||||
warn("newline in %CX'...'", backslash);
|
||||
outrune(c);
|
||||
}
|
||||
if(c < 0)
|
||||
warn("eof in %CX'...'", backslash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_quote(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
if(inputmode&ArgMode){
|
||||
/* Leave \" around for argument parsing */
|
||||
ungetrune('"');
|
||||
return '\\';
|
||||
}
|
||||
while((c = getrune()) >= 0 && c != '\n')
|
||||
;
|
||||
return '\n';
|
||||
}
|
||||
|
||||
int
|
||||
e_newline(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_e(void)
|
||||
{
|
||||
return backslash;
|
||||
}
|
||||
|
||||
void
|
||||
r_comment(Rune *name)
|
||||
{
|
||||
int c;
|
||||
|
||||
USED(name);
|
||||
while((c = getrune()) >= 0 && c != '\n')
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
t10init(void)
|
||||
{
|
||||
addreq(L("ec"), r_ec, -1);
|
||||
addreq(L("eo"), r_eo, 0);
|
||||
addreq(L("lg"), r_nop, -1);
|
||||
addreq(L("cc"), r_cc, -1);
|
||||
addreq(L("c2"), r_c2, -1);
|
||||
addreq(L("tr"), r_warn, -1);
|
||||
addreq(L("ul"), r_nop, -1);
|
||||
addraw(L("\\\""), r_comment);
|
||||
|
||||
addesc('!', e_bang, 0);
|
||||
addesc('X', e_X, 0);
|
||||
addesc('\"', e_quote, CopyMode|ArgMode);
|
||||
addesc('\n', e_newline, CopyMode|ArgMode|HtmlMode);
|
||||
addesc('e', e_e, 0);
|
||||
}
|
||||
|
107
src/cmd/htmlroff/t11.c
Normal file
107
src/cmd/htmlroff/t11.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* 11. Local Horizontal and Vertical Motions, and the Width Function.
|
||||
*/
|
||||
|
||||
int
|
||||
e_0(void)
|
||||
{
|
||||
/* digit-width space */
|
||||
return ' ';
|
||||
}
|
||||
|
||||
int
|
||||
dv(int d)
|
||||
{
|
||||
Rune sub[6];
|
||||
|
||||
d += getnr(L(".dv"));
|
||||
nr(L(".dv"), d);
|
||||
|
||||
runestrcpy(sub, L("<sub>"));
|
||||
sub[0] = Ult;
|
||||
sub[4] = Ugt;
|
||||
if(d < 0){
|
||||
sub[3] = 'p';
|
||||
ihtml(L(".dv"), sub);
|
||||
}else if(d > 0)
|
||||
ihtml(L(".dv"), sub);
|
||||
else
|
||||
ihtml(L(".dv"), nil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_v(void)
|
||||
{
|
||||
dv(eval(getqarg()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_u(void)
|
||||
{
|
||||
dv(eval(L("-0.5m")));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_d(void)
|
||||
{
|
||||
dv(eval(L("0.5m")));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_r(void)
|
||||
{
|
||||
dv(eval(L("-1m")));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_h(void)
|
||||
{
|
||||
getqarg();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_w(void)
|
||||
{
|
||||
Rune *a;
|
||||
Rune buf[40];
|
||||
|
||||
a = getqarg();
|
||||
runesnprint(buf, sizeof buf, "%ld", runestrlen(a));
|
||||
pushinputstring(buf);
|
||||
nr(L("st"), 0);
|
||||
nr(L("sb"), 0);
|
||||
nr(L("ct"), 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_k(void)
|
||||
{
|
||||
getname();
|
||||
warn("%Ck not available", backslash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
t11init(void)
|
||||
{
|
||||
addesc('|', e_nop, 0);
|
||||
addesc('^', e_nop, 0);
|
||||
addesc('v', e_v, 0);
|
||||
addesc('h', e_h, 0);
|
||||
addesc('w', e_w, 0);
|
||||
addesc('0', e_0, 0);
|
||||
addesc('u', e_u, 0);
|
||||
addesc('d', e_d, 0);
|
||||
addesc('r', e_r, 0);
|
||||
addesc('k', e_k, 0);
|
||||
}
|
||||
|
67
src/cmd/htmlroff/t12.c
Normal file
67
src/cmd/htmlroff/t12.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* 12. Overstrike, bracket, line-drawing, graphics, and zero-width functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
\o'asdf'
|
||||
\zc
|
||||
\b'asdf'
|
||||
\l'Nc'
|
||||
\L'Nc'
|
||||
\D'xxx'
|
||||
*/
|
||||
|
||||
int
|
||||
e_o(void)
|
||||
{
|
||||
pushinputstring(getqarg());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_z(void)
|
||||
{
|
||||
getnext();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_b(void)
|
||||
{
|
||||
pushinputstring(getqarg());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_l(void)
|
||||
{
|
||||
getqarg();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_L(void)
|
||||
{
|
||||
getqarg();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_D(void)
|
||||
{
|
||||
getqarg();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
t12init(void)
|
||||
{
|
||||
addesc('o', e_o, 0);
|
||||
addesc('z', e_z, 0);
|
||||
addesc('b', e_b, 0);
|
||||
addesc('l', e_l, 0);
|
||||
addesc('L', e_L, 0);
|
||||
addesc('D', e_D, 0);
|
||||
}
|
17
src/cmd/htmlroff/t13.c
Normal file
17
src/cmd/htmlroff/t13.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* 13. Hyphenation.
|
||||
*/
|
||||
|
||||
void
|
||||
t13init(void)
|
||||
{
|
||||
addreq(L("nh"), r_nop, -1);
|
||||
addreq(L("hy"), r_nop, -1);
|
||||
addreq(L("hc"), r_nop, -1);
|
||||
addreq(L("hw"), r_nop, -1);
|
||||
|
||||
addesc('%', e_nop, 0);
|
||||
}
|
||||
|
33
src/cmd/htmlroff/t14.c
Normal file
33
src/cmd/htmlroff/t14.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* 14. Three-part titles.
|
||||
*/
|
||||
void
|
||||
r_lt(int argc, Rune **argv)
|
||||
{
|
||||
Rune *p;
|
||||
|
||||
if(argc < 2)
|
||||
nr(L(".lt"), evalscale(L("6.5i"), 'm'));
|
||||
else{
|
||||
if(argc > 2)
|
||||
warn("too many arguments for .lt");
|
||||
p = argv[1];
|
||||
if(p[0] == '-')
|
||||
nr(L(".lt"), getnr(L(".lt"))-evalscale(p+1, 'm'));
|
||||
else if(p[0] == '+')
|
||||
nr(L(".lt"), getnr(L(".lt"))+evalscale(p+1, 'm'));
|
||||
else
|
||||
nr(L(".lt"), evalscale(p, 'm'));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
t14init(void)
|
||||
{
|
||||
addreq(L("tl"), r_warn, -1);
|
||||
addreq(L("pc"), r_nop, -1); /* page number char */
|
||||
addreq(L("lt"), r_lt, -1);
|
||||
}
|
||||
|
13
src/cmd/htmlroff/t15.c
Normal file
13
src/cmd/htmlroff/t15.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* 15. Output line numbering.
|
||||
*/
|
||||
|
||||
void
|
||||
t15init(void)
|
||||
{
|
||||
addreq(L("nm"), r_warn, -1);
|
||||
addreq(L("nn"), r_warn, -1);
|
||||
}
|
||||
|
156
src/cmd/htmlroff/t16.c
Normal file
156
src/cmd/htmlroff/t16.c
Normal file
|
@ -0,0 +1,156 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* 16. Conditional acceptance of input.
|
||||
*
|
||||
* conditions are
|
||||
* c - condition letter (o, e, t, n)
|
||||
* !c - not c
|
||||
* N - N>0
|
||||
* !N - N <= 0
|
||||
* 'a'b' - if a==b
|
||||
* !'a'b' - if a!=b
|
||||
*
|
||||
* \{xxx\} can be used for newline in bodies
|
||||
*
|
||||
* .if .ie .el
|
||||
*
|
||||
*/
|
||||
|
||||
int iftrue[20];
|
||||
int niftrue;
|
||||
|
||||
void
|
||||
startbody(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
while((c = getrune()) == ' ' || c == '\t')
|
||||
;
|
||||
ungetrune(c);
|
||||
}
|
||||
|
||||
void
|
||||
skipbody(void)
|
||||
{
|
||||
int c, cc, nbrace;
|
||||
|
||||
nbrace = 0;
|
||||
for(cc=0; (c = getrune()) >= 0; cc=c){
|
||||
if(c == '\n' && nbrace <= 0)
|
||||
break;
|
||||
if(cc == '\\' && c == '{')
|
||||
nbrace++;
|
||||
if(cc == '\\' && c == '}')
|
||||
nbrace--;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ifeval(void)
|
||||
{
|
||||
int c, cc, neg, nc;
|
||||
Rune line[MaxLine], *p, *e, *q;
|
||||
Rune *a;
|
||||
|
||||
while((c = getnext()) == ' ' || c == '\t')
|
||||
;
|
||||
neg = 0;
|
||||
while(c == '!'){
|
||||
neg = !neg;
|
||||
c = getnext();
|
||||
}
|
||||
|
||||
if('0' <= c && c <= '9'){
|
||||
ungetnext(c);
|
||||
a = copyarg();
|
||||
c = (eval(a)>0) ^ neg;
|
||||
free(a);
|
||||
return c;
|
||||
}
|
||||
|
||||
switch(c){
|
||||
case ' ':
|
||||
case '\n':
|
||||
ungetnext(c);
|
||||
return !neg;
|
||||
case 'o': /* odd page */
|
||||
case 't': /* troff */
|
||||
case 'h': /* htmlroff */
|
||||
while((c = getrune()) != ' ' && c != '\t' && c != '\n' && c >= 0)
|
||||
;
|
||||
return 1 ^ neg;
|
||||
case 'n': /* nroff */
|
||||
case 'e': /* even page */
|
||||
while((c = getnext()) != ' ' && c != '\t' && c != '\n' && c >= 0)
|
||||
;
|
||||
return 0 ^ neg;
|
||||
}
|
||||
|
||||
/* string comparison 'string1'string2' */
|
||||
p = line;
|
||||
e = p+nelem(line);
|
||||
nc = 0;
|
||||
q = nil;
|
||||
while((cc=getnext()) >= 0 && cc != '\n' && p<e){
|
||||
if(cc == c){
|
||||
if(++nc == 2)
|
||||
break;
|
||||
q = p;
|
||||
}
|
||||
*p++ = cc;
|
||||
}
|
||||
if(cc != c){
|
||||
ungetnext(cc);
|
||||
return 0;
|
||||
}
|
||||
if(nc < 2){
|
||||
return 0;
|
||||
}
|
||||
*p = 0;
|
||||
return (q-line == p-(q+1)
|
||||
&& memcmp(line, q+1, (q-line)*sizeof(Rune))==0) ^ neg;
|
||||
}
|
||||
|
||||
void
|
||||
r_if(Rune *name)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = ifeval();
|
||||
if(runestrcmp(name, L("ie")) == 0){
|
||||
if(niftrue >= nelem(iftrue))
|
||||
sysfatal("%Cie overflow", dot);
|
||||
iftrue[niftrue++] = n;
|
||||
}
|
||||
if(n)
|
||||
startbody();
|
||||
else
|
||||
skipbody();
|
||||
}
|
||||
|
||||
void
|
||||
r_el(Rune *name)
|
||||
{
|
||||
USED(name);
|
||||
|
||||
if(niftrue <= 0){
|
||||
warn("%Cel underflow", dot);
|
||||
return;
|
||||
}
|
||||
if(iftrue[--niftrue])
|
||||
skipbody();
|
||||
else
|
||||
startbody();
|
||||
}
|
||||
|
||||
void
|
||||
t16init(void)
|
||||
{
|
||||
addraw(L("if"), r_if);
|
||||
addraw(L("ie"), r_if);
|
||||
addraw(L("el"), r_el);
|
||||
|
||||
addesc('{', e_nop, HtmlMode|ArgMode);
|
||||
addesc('}', e_nop, HtmlMode|ArgMode);
|
||||
}
|
131
src/cmd/htmlroff/t17.c
Normal file
131
src/cmd/htmlroff/t17.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* 17. Environment switching.
|
||||
*/
|
||||
typedef struct Env Env;
|
||||
struct Env
|
||||
{
|
||||
int s;
|
||||
int s0;
|
||||
int f;
|
||||
int f0;
|
||||
int fi;
|
||||
int ad;
|
||||
int ce;
|
||||
int v;
|
||||
int v0;
|
||||
int ls;
|
||||
int ls0;
|
||||
int it;
|
||||
/* - ta */
|
||||
/* - tc */
|
||||
/* - lc */
|
||||
/* - ul */
|
||||
/* - cu */
|
||||
/* - cc */
|
||||
/* - c2 */
|
||||
/* - nh */
|
||||
/* - hy */
|
||||
/* - hc */
|
||||
/* - lt */
|
||||
/* - nm */
|
||||
/* - nn */
|
||||
/* - mc */
|
||||
};
|
||||
|
||||
Env defenv =
|
||||
{
|
||||
10,
|
||||
10,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
12,
|
||||
12,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
Env env[3];
|
||||
Env *evstack[20];
|
||||
int nevstack;
|
||||
|
||||
void
|
||||
saveenv(Env *e)
|
||||
{
|
||||
e->s = getnr(L(".s"));
|
||||
e->s0 = getnr(L(".s0"));
|
||||
e->f = getnr(L(".f"));
|
||||
e->f0 = getnr(L(".f0"));
|
||||
e->fi = getnr(L(".fi"));
|
||||
e->ad = getnr(L(".ad"));
|
||||
e->ce = getnr(L(".ce"));
|
||||
e->v = getnr(L(".v"));
|
||||
e->v0 = getnr(L(".v0"));
|
||||
e->ls = getnr(L(".ls"));
|
||||
e->ls0 = getnr(L(".ls0"));
|
||||
e->it = getnr(L(".it"));
|
||||
}
|
||||
|
||||
void
|
||||
restoreenv(Env *e)
|
||||
{
|
||||
nr(L(".s"), e->s);
|
||||
nr(L(".s0"), e->s0);
|
||||
nr(L(".f"), e->f);
|
||||
nr(L(".f0"), e->f0);
|
||||
nr(L(".fi"), e->fi);
|
||||
nr(L(".ad"), e->ad);
|
||||
nr(L(".ce"), e->ce);
|
||||
nr(L(".v"), e->v);
|
||||
nr(L(".v0"), e->v0);
|
||||
nr(L(".ls"), e->ls);
|
||||
nr(L(".ls0"), e->ls0);
|
||||
nr(L(".it"), e->it);
|
||||
|
||||
nr(L(".ev"), e-env);
|
||||
runmacro1(L("font"));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
r_ev(int argc, Rune **argv)
|
||||
{
|
||||
int i;
|
||||
Env *e;
|
||||
|
||||
if(argc == 1){
|
||||
if(nevstack <= 0){
|
||||
if(verbose) warn(".ev stack underflow");
|
||||
return;
|
||||
}
|
||||
restoreenv(evstack[--nevstack]);
|
||||
return;
|
||||
}
|
||||
if(nevstack >= nelem(evstack))
|
||||
sysfatal(".ev stack overflow");
|
||||
i = eval(argv[1]);
|
||||
if(i < 0 || i > 2){
|
||||
warn(".ev bad environment %d", i);
|
||||
i = 0;
|
||||
}
|
||||
e = &env[getnr(L(".ev"))];
|
||||
saveenv(e);
|
||||
evstack[nevstack++] = e;
|
||||
restoreenv(&env[i]);
|
||||
}
|
||||
|
||||
void
|
||||
t17init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<nelem(env); i++)
|
||||
env[i] = defenv;
|
||||
|
||||
addreq(L("ev"), r_ev, -1);
|
||||
}
|
67
src/cmd/htmlroff/t18.c
Normal file
67
src/cmd/htmlroff/t18.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* 18. Insertions from the standard input
|
||||
*/
|
||||
void
|
||||
r_rd(int argc, Rune **argv)
|
||||
{
|
||||
char *s;
|
||||
Rune *p;
|
||||
Fmt fmt;
|
||||
static int didstdin;
|
||||
static Biobuf bstdin;
|
||||
|
||||
/*
|
||||
* print prompt, then read until double newline,
|
||||
* then run the text just read as though it were
|
||||
* a macro body, using the remaining arguments.
|
||||
*/
|
||||
if(isatty(0)){
|
||||
if(argc > 1)
|
||||
fprint(2, "%S", argv[1]);
|
||||
else
|
||||
fprint(2, "%c", 7/*BEL*/);
|
||||
}
|
||||
|
||||
if(!didstdin){
|
||||
Binit(&bstdin, 0, OREAD);
|
||||
didstdin = 1;
|
||||
}
|
||||
runefmtstrinit(&fmt);
|
||||
while((s = Brdstr(&bstdin, '\n', 0)) != nil){
|
||||
if(s[0] == '\n'){
|
||||
free(s);
|
||||
break;
|
||||
}
|
||||
fmtprint(&fmt, "%s", s);
|
||||
free(s);
|
||||
}
|
||||
p = runefmtstrflush(&fmt);
|
||||
if(p == nil)
|
||||
warn("out of memory in %Crd", dot);
|
||||
ds(L(".rd"), p);
|
||||
argc--;
|
||||
argv++;
|
||||
argv[0] = L(".rd");
|
||||
runmacro('.', argc, argv);
|
||||
ds(L(".rd"), nil);
|
||||
}
|
||||
|
||||
/* terminate exactly as if input had ended */
|
||||
void
|
||||
r_ex(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
USED(argv);
|
||||
|
||||
while(popinput())
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
t18init(void)
|
||||
{
|
||||
addreq(L("rd"), r_rd, -1);
|
||||
addreq(L("ex"), r_ex, 0);
|
||||
}
|
142
src/cmd/htmlroff/t19.c
Normal file
142
src/cmd/htmlroff/t19.c
Normal file
|
@ -0,0 +1,142 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* 19. Input/output file switching.
|
||||
*/
|
||||
|
||||
/* .so - push new source file */
|
||||
void
|
||||
r_so(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
pushinputfile(erunesmprint("%s", unsharp(esmprint("%S", argv[1]))));
|
||||
}
|
||||
|
||||
/* .nx - end this file, switch to arg */
|
||||
void
|
||||
r_nx(int argc, Rune **argv)
|
||||
{
|
||||
int n;
|
||||
|
||||
if(argc == 1){
|
||||
while(popinput())
|
||||
;
|
||||
}else{
|
||||
if(argc > 2)
|
||||
warn("too many arguments for .nx");
|
||||
while((n=popinput()) && n != 2)
|
||||
;
|
||||
pushinputfile(argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* .sy - system: run string */
|
||||
void
|
||||
r_sy(Rune *name)
|
||||
{
|
||||
USED(name);
|
||||
warn(".sy not implemented");
|
||||
}
|
||||
|
||||
/* .pi - pipe output to string */
|
||||
void
|
||||
r_pi(Rune *name)
|
||||
{
|
||||
USED(name);
|
||||
warn(".pi not implemented");
|
||||
}
|
||||
|
||||
/* .cf - copy contents of filename to output */
|
||||
void
|
||||
r_cf(int argc, Rune **argv)
|
||||
{
|
||||
int c;
|
||||
char *p;
|
||||
Biobuf *b;
|
||||
|
||||
USED(argc);
|
||||
p = esmprint("%S", argv[1]);
|
||||
if((b = Bopen(p, OREAD)) == nil){
|
||||
fprint(2, "%L: open %s: %r\n", p);
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
free(p);
|
||||
|
||||
while((c = Bgetrune(b)) >= 0)
|
||||
outrune(c);
|
||||
Bterm(b);
|
||||
}
|
||||
|
||||
void
|
||||
r_inputpipe(Rune *name)
|
||||
{
|
||||
Rune *cmd, *stop, *line;
|
||||
int n, pid, p[2], len;
|
||||
Waitmsg *w;
|
||||
|
||||
USED(name);
|
||||
if(pipe(p) < 0){
|
||||
warn("pipe: %r");
|
||||
return;
|
||||
}
|
||||
stop = copyarg();
|
||||
cmd = readline(CopyMode);
|
||||
pid = fork();
|
||||
switch(pid){
|
||||
case 0:
|
||||
if(p[0] != 0){
|
||||
dup(p[0], 0);
|
||||
close(p[0]);
|
||||
}
|
||||
close(p[1]);
|
||||
execl(unsharp("#9/bin/rc"), "rc", "-c", esmprint("%S", cmd), nil);
|
||||
warn("%Cdp %S: %r", dot, cmd);
|
||||
_exits(nil);
|
||||
case -1:
|
||||
warn("fork: %r");
|
||||
default:
|
||||
close(p[0]);
|
||||
len = runestrlen(stop);
|
||||
fprint(p[1], ".ps %d\n", getnr(L(".s")));
|
||||
fprint(p[1], ".vs %du\n", getnr(L(".v")));
|
||||
fprint(p[1], ".ft %d\n", getnr(L(".f")));
|
||||
fprint(p[1], ".ll 8i\n");
|
||||
fprint(p[1], ".pl 30i\n");
|
||||
while((line = readline(~0)) != nil){
|
||||
if(runestrncmp(line, stop, len) == 0
|
||||
&& (line[len]==' ' || line[len]==0 || line[len]=='\t'
|
||||
|| (line[len]=='\\' && line[len+1]=='}')))
|
||||
break;
|
||||
n = runestrlen(line);
|
||||
line[n] = '\n';
|
||||
fprint(p[1], "%.*S", n+1, line);
|
||||
free(line);
|
||||
}
|
||||
free(stop);
|
||||
close(p[1]);
|
||||
w = wait();
|
||||
if(w == nil){
|
||||
warn("wait: %r");
|
||||
return;
|
||||
}
|
||||
if(w->msg[0])
|
||||
sysfatal("%C%S %S: %s", dot, name, cmd, w->msg);
|
||||
free(cmd);
|
||||
free(w);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
t19init(void)
|
||||
{
|
||||
addreq(L("so"), r_so, 1);
|
||||
addreq(L("nx"), r_nx, -1);
|
||||
addraw(L("sy"), r_sy);
|
||||
addraw(L("inputpipe"), r_inputpipe);
|
||||
addraw(L("pi"), r_pi);
|
||||
addreq(L("cf"), r_cf, 1);
|
||||
|
||||
nr(L("$$"), getpid());
|
||||
}
|
||||
|
274
src/cmd/htmlroff/t2.c
Normal file
274
src/cmd/htmlroff/t2.c
Normal file
|
@ -0,0 +1,274 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* Section 2 - Font and character size control.
|
||||
*/
|
||||
|
||||
/* 2.1 - Character set */
|
||||
/* XXX
|
||||
*
|
||||
* \C'name' - character named name
|
||||
* \N'n' - character number
|
||||
* \(xx - two-letter character
|
||||
* \-
|
||||
* \`
|
||||
* \'
|
||||
* `
|
||||
* '
|
||||
* -
|
||||
*/
|
||||
|
||||
Rune*
|
||||
getqarg(void)
|
||||
{
|
||||
static Rune buf[MaxLine];
|
||||
int c;
|
||||
Rune *p, *e;
|
||||
|
||||
p = buf;
|
||||
e = p+sizeof buf-1;
|
||||
|
||||
if(getrune() != '\'')
|
||||
return nil;
|
||||
while(p < e){
|
||||
c = getrune();
|
||||
if(c < 0)
|
||||
return nil;
|
||||
if(c == '\'')
|
||||
break;
|
||||
*p++ = c;
|
||||
}
|
||||
*p = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
int
|
||||
e_N(void)
|
||||
{
|
||||
Rune *a;
|
||||
if((a = getqarg()) == nil)
|
||||
goto error;
|
||||
return eval(a);
|
||||
|
||||
error:
|
||||
warn("malformed %CN'...'", backslash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_paren(void)
|
||||
{
|
||||
int c, cc;
|
||||
Rune buf[2], r;
|
||||
|
||||
if((c = getrune()) < 0 || c == '\n')
|
||||
goto error;
|
||||
if((cc = getrune()) < 0 || cc == '\n')
|
||||
goto error;
|
||||
buf[0] = c;
|
||||
buf[1] = cc;
|
||||
r = troff2rune(buf);
|
||||
if(r == Runeerror)
|
||||
warn("unknown char %C(%C%C", backslash, c, cc);
|
||||
return r;
|
||||
|
||||
error:
|
||||
warn("malformed %C(xx", backslash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 2.2 - Fonts */
|
||||
Rune fonttab[10][100];
|
||||
|
||||
/*
|
||||
* \fx \f(xx \fN - font change
|
||||
* number register .f - current font
|
||||
* \f0 previous font (undocumented?)
|
||||
*/
|
||||
/* change to font f. also \fx, \f(xx, \fN */
|
||||
/* .ft LongName is okay - temporarily at fp 0 */
|
||||
void
|
||||
ft(Rune *f)
|
||||
{
|
||||
int i;
|
||||
int fn;
|
||||
|
||||
if(f && runestrcmp(f, L("P")) == 0)
|
||||
f = nil;
|
||||
if(f == nil)
|
||||
fn = 0;
|
||||
else if(isdigit(f[0]))
|
||||
fn = eval(f);
|
||||
else{
|
||||
for(i=0; i<nelem(fonttab); i++){
|
||||
if(runestrcmp(fonttab[i], f) == 0){
|
||||
fn = i;
|
||||
goto have;
|
||||
}
|
||||
}
|
||||
warn("unknown font %S", f);
|
||||
fn = 1;
|
||||
}
|
||||
have:
|
||||
if(fn < 0 || fn >= nelem(fonttab)){
|
||||
warn("unknown font %d", fn);
|
||||
fn = 1;
|
||||
}
|
||||
if(fn == 0)
|
||||
fn = getnr(L(".f0"));
|
||||
nr(L(".f0"), getnr(L(".f")));
|
||||
nr(L(".f"), fn);
|
||||
runmacro1(L("font"));
|
||||
}
|
||||
|
||||
/* mount font named f on physical position N */
|
||||
void
|
||||
fp(int i, Rune *f)
|
||||
{
|
||||
if(i <= 0 || i >= nelem(fonttab)){
|
||||
warn("bad font position %d", i);
|
||||
return;
|
||||
}
|
||||
runestrecpy(fonttab[i], fonttab[i]+sizeof fonttab[i], f);
|
||||
}
|
||||
|
||||
int
|
||||
e_f(void)
|
||||
{
|
||||
ft(getname());
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
r_ft(int argc, Rune **argv)
|
||||
{
|
||||
if(argc == 1)
|
||||
ft(nil);
|
||||
else
|
||||
ft(argv[1]);
|
||||
}
|
||||
|
||||
void
|
||||
r_fp(int argc, Rune **argv)
|
||||
{
|
||||
if(argc < 3){
|
||||
warn("missing arguments to %Cfp", dot);
|
||||
return;
|
||||
}
|
||||
fp(eval(argv[1]), argv[2]);
|
||||
}
|
||||
|
||||
/* 2.3 - Character size */
|
||||
|
||||
/* \H'±N' sets height */
|
||||
|
||||
void
|
||||
ps(int s)
|
||||
{
|
||||
if(s == 0)
|
||||
s = getnr(L(".s0"));
|
||||
nr(L(".s0"), getnr(L(".s")));
|
||||
nr(L(".s"), s);
|
||||
runmacro1(L("font"));
|
||||
}
|
||||
|
||||
/* set point size */
|
||||
void
|
||||
r_ps(int argc, Rune **argv)
|
||||
{
|
||||
Rune *p;
|
||||
|
||||
if(argc == 1 || argv[1][0] == 0)
|
||||
ps(0);
|
||||
else{
|
||||
p = argv[1];
|
||||
if(p[0] == '-')
|
||||
ps(getnr(L(".s"))-eval(p+1));
|
||||
else if(p[0] == '+')
|
||||
ps(getnr(L(".s"))+eval(p+1));
|
||||
else
|
||||
ps(eval(p));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
e_s(void)
|
||||
{
|
||||
int c, cc, ccc, n, twodigit;
|
||||
|
||||
c = getnext();
|
||||
if(c < 0)
|
||||
return 0;
|
||||
if(c == '+' || c == '-'){
|
||||
cc = getnext();
|
||||
if(cc == '('){
|
||||
cc = getnext();
|
||||
ccc = getnext();
|
||||
if(cc < '0' || cc > '9' || ccc < '0' || ccc > '9'){
|
||||
warn("bad size %Cs%C(%C%C", backslash, c, cc, ccc);
|
||||
return 0;
|
||||
}
|
||||
n = (cc-'0')*10+ccc-'0';
|
||||
}else{
|
||||
if(cc < '0' || cc > '9'){
|
||||
warn("bad size %Cs%C%C", backslash, c, cc);
|
||||
return 0;
|
||||
}
|
||||
n = cc-'0';
|
||||
}
|
||||
if(c == '+')
|
||||
ps(getnr(L(".s"))+n);
|
||||
else
|
||||
ps(getnr(L(".s"))-n);
|
||||
return 0;
|
||||
}
|
||||
twodigit = 0;
|
||||
if(c == '('){
|
||||
twodigit = 1;
|
||||
c = getnext();
|
||||
if(c < 0)
|
||||
return 0;
|
||||
}
|
||||
if(c < '0' || c > '9'){
|
||||
warn("bad size %Cs%C", backslash, c);
|
||||
ungetnext(c);
|
||||
return 0;
|
||||
}
|
||||
if(twodigit || (c < '4' && c != '0')){
|
||||
cc = getnext();
|
||||
if(c < 0)
|
||||
return 0;
|
||||
n = (c-'0')*10+cc-'0';
|
||||
}else
|
||||
n = c-'0';
|
||||
ps(n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
t2init(void)
|
||||
{
|
||||
fp(1, L("R"));
|
||||
fp(2, L("I"));
|
||||
fp(3, L("B"));
|
||||
fp(4, L("BI"));
|
||||
fp(5, L("CW"));
|
||||
|
||||
nr(L(".s"), 10);
|
||||
nr(L(".s0"), 10);
|
||||
|
||||
addreq(L("ft"), r_ft, -1);
|
||||
addreq(L("fp"), r_fp, -1);
|
||||
addreq(L("ps"), r_ps, -1);
|
||||
addreq(L("ss"), r_warn, -1);
|
||||
addreq(L("cs"), r_warn, -1);
|
||||
addreq(L("bd"), r_warn, -1);
|
||||
|
||||
addesc('f', e_f, 0);
|
||||
addesc('s', e_s, 0);
|
||||
addesc('(', e_paren, 0); /* ) */
|
||||
addesc('C', e_warn, 0);
|
||||
addesc('N', e_N, 0);
|
||||
/* \- \' \` are handled in html.c */
|
||||
}
|
||||
|
79
src/cmd/htmlroff/t20.c
Normal file
79
src/cmd/htmlroff/t20.c
Normal file
|
@ -0,0 +1,79 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* 20. Miscellaneous
|
||||
*/
|
||||
|
||||
/* .mc - margin character */
|
||||
/* .ig - ignore; treated like a macro in t7.c */
|
||||
|
||||
/* .pm - print macros and strings */
|
||||
|
||||
void
|
||||
r_pm(int argc, Rune **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(argc == 1){
|
||||
printds(0);
|
||||
return;
|
||||
}
|
||||
if(runestrcmp(argv[1], L("t")) == 0){
|
||||
printds(1);
|
||||
return;
|
||||
}
|
||||
for(i=1; i<argc; i++)
|
||||
fprint(2, "%S: %S\n", argv[i], getds(argv[i]));
|
||||
}
|
||||
|
||||
void
|
||||
r_tm(Rune *name)
|
||||
{
|
||||
Rune *line;
|
||||
|
||||
USED(name);
|
||||
|
||||
line = readline(CopyMode);
|
||||
fprint(2, "%S\n", line);
|
||||
free(line);
|
||||
}
|
||||
|
||||
void
|
||||
r_ab(Rune *name)
|
||||
{
|
||||
USED(name);
|
||||
|
||||
r_tm(L("ab"));
|
||||
exits(".ab");
|
||||
}
|
||||
|
||||
void
|
||||
r_lf(int argc, Rune **argv)
|
||||
{
|
||||
if(argc == 1)
|
||||
return;
|
||||
if(argc == 2)
|
||||
setlinenumber(nil, eval(argv[1]));
|
||||
if(argc == 3)
|
||||
setlinenumber(argv[2], eval(argv[1]));
|
||||
}
|
||||
|
||||
void
|
||||
r_fl(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
USED(argv);
|
||||
Bflush(&bout);
|
||||
}
|
||||
|
||||
void
|
||||
t20init(void)
|
||||
{
|
||||
addreq(L("mc"), r_warn, -1);
|
||||
addraw(L("tm"), r_tm);
|
||||
addraw(L("ab"), r_ab);
|
||||
addreq(L("lf"), r_lf, -1);
|
||||
addreq(L("pm"), r_pm, -1);
|
||||
addreq(L("fl"), r_fl, 0);
|
||||
}
|
||||
|
49
src/cmd/htmlroff/t3.c
Normal file
49
src/cmd/htmlroff/t3.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* Section 3 - page control (mostly irrelevant).
|
||||
*/
|
||||
|
||||
/* page offset */
|
||||
void
|
||||
po(int o)
|
||||
{
|
||||
nr(L(".o0"), getnr(L(".o")));
|
||||
nr(L(".o"), o);
|
||||
}
|
||||
|
||||
void
|
||||
r_po(int argc, Rune **argv)
|
||||
{
|
||||
if(argc == 1){
|
||||
po(getnr(L(".o0")));
|
||||
return;
|
||||
}
|
||||
if(argv[1][0] == '+')
|
||||
po(getnr(L(".o"))+evalscale(argv[1]+1, 'v'));
|
||||
else if(argv[1][0] == '-')
|
||||
po(getnr(L(".o"))-evalscale(argv[1]+1, 'v'));
|
||||
else
|
||||
po(evalscale(argv[1], 'v'));
|
||||
}
|
||||
|
||||
/* .ne - need vertical space */
|
||||
/* .mk - mark current vertical place */
|
||||
/* .rt - return upward */
|
||||
|
||||
void
|
||||
t3init(void)
|
||||
{
|
||||
nr(L(".o"), eval(L("1i")));
|
||||
nr(L(".o0"), eval(L("1i")));
|
||||
nr(L(".p"), eval(L("11i")));
|
||||
|
||||
addreq(L("pl"), r_warn, -1);
|
||||
addreq(L("bp"), r_nop, -1);
|
||||
addreq(L("pn"), r_warn, -1);
|
||||
addreq(L("po"), r_po, -1);
|
||||
addreq(L("ne"), r_nop, -1);
|
||||
addreq(L("mk"), r_nop, -1);
|
||||
addreq(L("rt"), r_warn, -1);
|
||||
}
|
||||
|
142
src/cmd/htmlroff/t4.c
Normal file
142
src/cmd/htmlroff/t4.c
Normal file
|
@ -0,0 +1,142 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* 4 - Text filling, centering, and adjusting.
|
||||
* "\ " - unbreakable space
|
||||
* .n register - length of last line
|
||||
* nl register - text baseline position on this page
|
||||
* .h register - baseline high water mark
|
||||
* .k register - current horizontal output position
|
||||
* \p - cause break at end of word, justify
|
||||
* \& - non-printing zero-width filler
|
||||
* tr - output translation
|
||||
* \c - break (but don't) input line in .nf mode
|
||||
* \c - break (but don't) word in .fi mode
|
||||
*/
|
||||
|
||||
int
|
||||
e_space(void)
|
||||
{
|
||||
return 0xA0; /* non-breaking space */
|
||||
}
|
||||
|
||||
int
|
||||
e_amp(void)
|
||||
{
|
||||
return Uempty;
|
||||
}
|
||||
|
||||
int
|
||||
e_c(void)
|
||||
{
|
||||
getrune();
|
||||
bol = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
r_br(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
USED(argv);
|
||||
br();
|
||||
}
|
||||
|
||||
/* fill mode on */
|
||||
void
|
||||
r_fi(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
USED(argv);
|
||||
nr(L(".fi"), 1);
|
||||
// warn(".fi");
|
||||
}
|
||||
|
||||
/* no-fill mode */
|
||||
void
|
||||
r_nf(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
USED(argv);
|
||||
nr(L(".fi"), 0);
|
||||
}
|
||||
|
||||
/* adjust */
|
||||
void
|
||||
r_ad(int argc, Rune **argv)
|
||||
{
|
||||
int c, n;
|
||||
|
||||
nr(L(".j"), getnr(L(".j"))|1);
|
||||
if(argc < 2)
|
||||
return;
|
||||
c = argv[1][0];
|
||||
switch(c){
|
||||
default:
|
||||
fprint(2, "%L: bad adjust %C\n", c);
|
||||
return;
|
||||
case 'r':
|
||||
n = 2*2|1;
|
||||
break;
|
||||
case 'l':
|
||||
n = 0;
|
||||
break;
|
||||
case 'c':
|
||||
n = 1*2|1;
|
||||
break;
|
||||
case 'b':
|
||||
case 'n':
|
||||
n = 0*2|1;
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
n = c-'0';
|
||||
break;
|
||||
}
|
||||
nr(L(".j"), n);
|
||||
}
|
||||
|
||||
/* no adjust */
|
||||
void
|
||||
r_na(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
USED(argv);
|
||||
|
||||
nr(L(".j"), getnr(L(".j"))&~1);
|
||||
}
|
||||
|
||||
/* center next N lines */
|
||||
void
|
||||
r_ce(int argc, Rune **argv)
|
||||
{
|
||||
if(argc < 2)
|
||||
nr(L(".ce"), 1);
|
||||
else
|
||||
nr(L(".ce"), eval(argv[1]));
|
||||
/* XXX set trap */
|
||||
}
|
||||
|
||||
void
|
||||
t4init(void)
|
||||
{
|
||||
nr(L(".fi"), 1);
|
||||
nr(L(".j"), 1);
|
||||
|
||||
addreq(L("br"), r_br, 0);
|
||||
addreq(L("fi"), r_fi, 0);
|
||||
addreq(L("nf"), r_nf, 0);
|
||||
addreq(L("ad"), r_ad, -1);
|
||||
addreq(L("na"), r_na, 0);
|
||||
addreq(L("ce"), r_ce, -1);
|
||||
|
||||
addesc(' ', e_space, 0);
|
||||
addesc('p', e_warn, 0);
|
||||
addesc('&', e_amp, 0);
|
||||
addesc('c', e_c, 0);
|
||||
}
|
||||
|
110
src/cmd/htmlroff/t5.c
Normal file
110
src/cmd/htmlroff/t5.c
Normal file
|
@ -0,0 +1,110 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* 5. Vertical spacing.
|
||||
*/
|
||||
|
||||
/* set vertical baseline spacing */
|
||||
void
|
||||
vs(int v)
|
||||
{
|
||||
if(v == 0)
|
||||
v = getnr(L(".v0"));
|
||||
nr(L(".v0"), getnr(L(".v")));
|
||||
nr(L(".v"), v);
|
||||
}
|
||||
|
||||
void
|
||||
r_vs(int argc, Rune **argv)
|
||||
{
|
||||
if(argc < 2)
|
||||
vs(eval(L("12p")));
|
||||
else if(argv[1][0] == '+')
|
||||
vs(getnr(L(".v"))+evalscale(argv[1]+1, 'p'));
|
||||
else if(argv[1][0] == '-')
|
||||
vs(getnr(L(".v"))-evalscale(argv[1]+1, 'p'));
|
||||
else
|
||||
vs(evalscale(argv[1], 'p'));
|
||||
}
|
||||
|
||||
/* set line spacing */
|
||||
void
|
||||
ls(int v)
|
||||
{
|
||||
if(v == 0)
|
||||
v = getnr(L(".ls0"));
|
||||
nr(L(".ls0"), getnr(L(".ls")));
|
||||
nr(L(".ls"), v);
|
||||
}
|
||||
void
|
||||
r_ls(int argc, Rune **argv)
|
||||
{
|
||||
ls(argc < 2 ? 0 : eval(argv[1]));
|
||||
}
|
||||
|
||||
/* .sp - space vertically */
|
||||
/* .sv - save a contiguous vertical block */
|
||||
void
|
||||
sp(int v)
|
||||
{
|
||||
Rune buf[100];
|
||||
double fv;
|
||||
|
||||
br();
|
||||
fv = v * 1.0/UPI;
|
||||
if(fv > 5)
|
||||
fv = eval(L("1v")) * 1.0/UPI;
|
||||
runesnprint(buf, nelem(buf), "<p style=\"margin-top: 0; margin-bottom: %.2fin\"></p>\n", fv);
|
||||
outhtml(buf);
|
||||
}
|
||||
void
|
||||
r_sp(int argc, Rune **argv)
|
||||
{
|
||||
if(getnr(L(".ns")))
|
||||
return;
|
||||
if(argc < 2)
|
||||
sp(eval(L("1v")));
|
||||
else{
|
||||
if(argv[1][0] == '|'){
|
||||
/* XXX if there's no output yet, do the absolute! */
|
||||
if(verbose)
|
||||
warn("ignoring absolute .sp %d", eval(argv[1]+1));
|
||||
return;
|
||||
}
|
||||
sp(evalscale(argv[1], 'v'));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
r_ns(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
USED(argv);
|
||||
nr(L(".ns"), 1);
|
||||
}
|
||||
|
||||
void
|
||||
r_rs(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
USED(argv);
|
||||
nr(L(".ns"), 0);
|
||||
}
|
||||
|
||||
void
|
||||
t5init(void)
|
||||
{
|
||||
addreq(L("vs"), r_vs, -1);
|
||||
addreq(L("ls"), r_ls, -1);
|
||||
addreq(L("sp"), r_sp, -1);
|
||||
addreq(L("sv"), r_sp, -1);
|
||||
addreq(L("os"), r_nop, -1);
|
||||
addreq(L("ns"), r_ns, 0);
|
||||
addreq(L("rs"), r_rs, 0);
|
||||
|
||||
nr(L(".v"), eval(L("12p")));
|
||||
nr(L(".v0"), eval(L("12p")));
|
||||
nr(L(".ls"), 1);
|
||||
nr(L(".ls0"), 1);
|
||||
}
|
||||
|
74
src/cmd/htmlroff/t6.c
Normal file
74
src/cmd/htmlroff/t6.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
#include "a.h"
|
||||
|
||||
/*
|
||||
* Section 6 - line length and indenting.
|
||||
*/
|
||||
|
||||
/* set line length */
|
||||
void
|
||||
ll(int v)
|
||||
{
|
||||
if(v == 0)
|
||||
v = getnr(L(".l0"));
|
||||
nr(L(".l0"), getnr(L(".l")));
|
||||
nr(L(".l"), v);
|
||||
}
|
||||
void
|
||||
r_ll(int argc, Rune **argv)
|
||||
{
|
||||
if(argc < 2)
|
||||
ll(0);
|
||||
else if(argv[1][0] == '+')
|
||||
ll(getnr(L(".l"))+evalscale(argv[1]+1, 'v'));
|
||||
else if(argv[1][0] == '-')
|
||||
ll(getnr(L(".l"))-evalscale(argv[1]+1, 'v'));
|
||||
else
|
||||
ll(evalscale(argv[1], 'm'));
|
||||
if(argc > 2)
|
||||
warn("extra arguments to .ll");
|
||||
}
|
||||
|
||||
void
|
||||
in(int v)
|
||||
{
|
||||
nr(L(".i0"), getnr(L(".i")));
|
||||
nr(L(".i"), v);
|
||||
/* XXX */
|
||||
}
|
||||
void
|
||||
r_in(int argc, Rune **argv)
|
||||
{
|
||||
if(argc < 2)
|
||||
in(getnr(L(".i0")));
|
||||
else if(argv[1][0] == '+')
|
||||
in(getnr(L(".i"))+evalscale(argv[1]+1, 'm'));
|
||||
else if(argv[1][0] == '-')
|
||||
in(getnr(L(".i"))-evalscale(argv[1]+1, 'm'));
|
||||
else
|
||||
in(evalscale(argv[1], 'm'));
|
||||
if(argc > 3)
|
||||
warn("extra arguments to .in");
|
||||
}
|
||||
|
||||
void
|
||||
ti(int v)
|
||||
{
|
||||
nr(L(".ti"), v);
|
||||
}
|
||||
void
|
||||
r_ti(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
ti(evalscale(argv[1], 'm'));
|
||||
}
|
||||
|
||||
void
|
||||
t6init(void)
|
||||
{
|
||||
addreq(L("ll"), r_ll, -1);
|
||||
addreq(L("in"), r_in, -1);
|
||||
addreq(L("ti"), r_ti, 1);
|
||||
|
||||
nr(L(".l"), eval(L("6.5i")));
|
||||
}
|
||||
|
543
src/cmd/htmlroff/t7.c
Normal file
543
src/cmd/htmlroff/t7.c
Normal file
|
@ -0,0 +1,543 @@
|
|||
/*
|
||||
* 7. Macros, strings, diversion, and position traps.
|
||||
*
|
||||
* macros can override builtins
|
||||
* builtins can be renamed or removed!
|
||||
*/
|
||||
|
||||
#include "a.h"
|
||||
|
||||
enum
|
||||
{
|
||||
MAXARG = 10,
|
||||
MAXMSTACK = 40
|
||||
};
|
||||
|
||||
/* macro invocation frame */
|
||||
typedef struct Mac Mac;
|
||||
struct Mac
|
||||
{
|
||||
int argc;
|
||||
Rune *argv[MAXARG];
|
||||
};
|
||||
|
||||
Mac mstack[MAXMSTACK];
|
||||
int nmstack;
|
||||
void emitdi(void);
|
||||
void flushdi(void);
|
||||
|
||||
/*
|
||||
* Run a user-defined macro.
|
||||
*/
|
||||
void popmacro(void);
|
||||
int
|
||||
runmacro(int dot, int argc, Rune **argv)
|
||||
{
|
||||
Rune *p;
|
||||
int i;
|
||||
Mac *m;
|
||||
|
||||
if(verbose && isupperrune(argv[0][0])) fprint(2, "run: %S\n", argv[0]);
|
||||
p = getds(argv[0]);
|
||||
if(p == nil){
|
||||
if(verbose)
|
||||
warn("ignoring unknown request %C%S", dot, argv[0]);
|
||||
if(verbose > 1){
|
||||
for(i=0; i<argc; i++)
|
||||
fprint(2, " %S", argv[i]);
|
||||
fprint(2, "\n");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if(nmstack >= nelem(mstack)){
|
||||
fprint(2, "%L: macro stack overflow:");
|
||||
for(i=0; i<nmstack; i++)
|
||||
fprint(2, " %S", mstack[i].argv[0]);
|
||||
fprint(2, "\n");
|
||||
return -1;
|
||||
}
|
||||
m = &mstack[nmstack++];
|
||||
m->argc = argc;
|
||||
for(i=0; i<argc; i++)
|
||||
m->argv[i] = erunestrdup(argv[i]);
|
||||
pushinputstring(p);
|
||||
nr(L(".$"), argc-1);
|
||||
inputnotify(popmacro);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
popmacro(void)
|
||||
{
|
||||
int i;
|
||||
Mac *m;
|
||||
|
||||
if(--nmstack < 0){
|
||||
fprint(2, "%L: macro stack underflow\n");
|
||||
return;
|
||||
}
|
||||
m = &mstack[nmstack];
|
||||
for(i=0; i<m->argc; i++)
|
||||
free(m->argv[i]);
|
||||
if(nmstack > 0)
|
||||
nr(L(".$"), mstack[nmstack-1].argc-1);
|
||||
else
|
||||
nr(L(".$"), 0);
|
||||
}
|
||||
|
||||
void popmacro1(void);
|
||||
jmp_buf runjb[10];
|
||||
int nrunjb;
|
||||
|
||||
void
|
||||
runmacro1(Rune *name)
|
||||
{
|
||||
Rune *argv[2];
|
||||
int obol;
|
||||
|
||||
if(verbose) fprint(2, "outcb %p\n", outcb);
|
||||
obol = bol;
|
||||
argv[0] = name;
|
||||
argv[1] = nil;
|
||||
bol = 1;
|
||||
if(runmacro('.', 1, argv) >= 0){
|
||||
inputnotify(popmacro1);
|
||||
if(!setjmp(runjb[nrunjb++]))
|
||||
runinput();
|
||||
else
|
||||
if(verbose) fprint(2, "finished %S\n", name);
|
||||
}
|
||||
bol = obol;
|
||||
}
|
||||
|
||||
void
|
||||
popmacro1(void)
|
||||
{
|
||||
popmacro();
|
||||
if(nrunjb >= 0)
|
||||
longjmp(runjb[--nrunjb], 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* macro arguments
|
||||
*
|
||||
* "" means " inside " "
|
||||
* "" empty string
|
||||
* \newline can be done
|
||||
* argument separator is space (not tab)
|
||||
* number register .$ = number of arguments
|
||||
* no arguments outside macros or in strings
|
||||
*
|
||||
* arguments copied in copy mode
|
||||
*/
|
||||
|
||||
/*
|
||||
* diversions
|
||||
*
|
||||
* processed output diverted
|
||||
* dn dl registers vertical and horizontal size of last diversion
|
||||
* .z - current diversion name
|
||||
*/
|
||||
|
||||
/*
|
||||
* traps
|
||||
*
|
||||
* skip most
|
||||
* .t register - distance to next trap
|
||||
*/
|
||||
static Rune *trap0;
|
||||
|
||||
void
|
||||
outtrap(void)
|
||||
{
|
||||
Rune *t;
|
||||
|
||||
if(outcb)
|
||||
return;
|
||||
if(trap0){
|
||||
if(verbose) fprint(2, "trap: %S\n", trap0);
|
||||
t = trap0;
|
||||
trap0 = nil;
|
||||
runmacro1(t);
|
||||
free(t);
|
||||
}
|
||||
}
|
||||
|
||||
/* .wh - install trap */
|
||||
void
|
||||
r_wh(int argc, Rune **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(argc < 2)
|
||||
return;
|
||||
|
||||
i = eval(argv[1]);
|
||||
if(argc == 2){
|
||||
if(i == 0){
|
||||
free(trap0);
|
||||
trap0 = nil;
|
||||
}else
|
||||
if(verbose)
|
||||
warn("not removing trap at %d", i);
|
||||
}
|
||||
if(argc > 2){
|
||||
if(i == 0){
|
||||
free(trap0);
|
||||
trap0 = erunestrdup(argv[2]);
|
||||
}else
|
||||
if(verbose)
|
||||
warn("not installing %S trap at %d", argv[2], i);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
r_ch(int argc, Rune **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(argc == 2){
|
||||
if(trap0 && runestrcmp(argv[1], trap0) == 0){
|
||||
free(trap0);
|
||||
trap0 = nil;
|
||||
}else
|
||||
if(verbose)
|
||||
warn("not removing %S trap", argv[1]);
|
||||
return;
|
||||
}
|
||||
if(argc >= 3){
|
||||
i = eval(argv[2]);
|
||||
if(i == 0){
|
||||
free(trap0);
|
||||
trap0 = erunestrdup(argv[1]);
|
||||
}else
|
||||
if(verbose)
|
||||
warn("not moving %S trap to %d", argv[1], i);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
r_dt(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
USED(argv);
|
||||
warn("ignoring diversion trap");
|
||||
}
|
||||
|
||||
/* define macro - .de, .am, .ig */
|
||||
void
|
||||
r_de(int argc, Rune **argv)
|
||||
{
|
||||
Rune *end, *p;
|
||||
Fmt fmt;
|
||||
int ignore, len;
|
||||
|
||||
delreq(argv[1]);
|
||||
delraw(argv[1]);
|
||||
ignore = runestrcmp(argv[0], L("ig")) == 0;
|
||||
if(!ignore)
|
||||
runefmtstrinit(&fmt);
|
||||
end = L("..");
|
||||
if(argc >= 3)
|
||||
end = argv[2];
|
||||
if(runestrcmp(argv[0], L("am")) == 0 && (p=getds(argv[1])) != nil)
|
||||
fmtrunestrcpy(&fmt, p);
|
||||
len = runestrlen(end);
|
||||
while((p = readline(CopyMode)) != nil){
|
||||
if(runestrncmp(p, end, len) == 0
|
||||
&& (p[len]==' ' || p[len]==0 || p[len]=='\t'
|
||||
|| (p[len]=='\\' && p[len+1]=='}'))){
|
||||
free(p);
|
||||
goto done;
|
||||
}
|
||||
if(!ignore)
|
||||
fmtprint(&fmt, "%S\n", p);
|
||||
free(p);
|
||||
}
|
||||
warn("eof in %C%S %S - looking for %#Q", dot, argv[0], argv[1], end);
|
||||
done:
|
||||
if(ignore)
|
||||
return;
|
||||
p = runefmtstrflush(&fmt);
|
||||
if(p == nil)
|
||||
sysfatal("out of memory");
|
||||
ds(argv[1], p);
|
||||
free(p);
|
||||
}
|
||||
|
||||
/* define string .ds .as */
|
||||
void
|
||||
r_ds(Rune *cmd)
|
||||
{
|
||||
Rune *name, *line, *p;
|
||||
|
||||
name = copyarg();
|
||||
line = readline(CopyMode);
|
||||
if(name == nil || line == nil){
|
||||
free(name);
|
||||
return;
|
||||
}
|
||||
p = line;
|
||||
if(*p == '"')
|
||||
p++;
|
||||
if(cmd[0] == 'd')
|
||||
ds(name, p);
|
||||
else
|
||||
as(name, p);
|
||||
free(name);
|
||||
free(line);
|
||||
}
|
||||
|
||||
/* remove request, macro, or string */
|
||||
void
|
||||
r_rm(int argc, Rune **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
emitdi();
|
||||
for(i=1; i<argc; i++){
|
||||
delreq(argv[i]);
|
||||
delraw(argv[i]);
|
||||
ds(argv[i], nil);
|
||||
}
|
||||
}
|
||||
|
||||
/* .rn - rename request, macro, or string */
|
||||
void
|
||||
r_rn(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
renreq(argv[1], argv[2]);
|
||||
renraw(argv[1], argv[2]);
|
||||
ds(argv[2], getds(argv[1]));
|
||||
ds(argv[1], nil);
|
||||
}
|
||||
|
||||
/* .di - divert output to macro xx */
|
||||
/* .da - divert, appending to macro */
|
||||
/* page offsetting is not done! */
|
||||
Fmt difmt;
|
||||
int difmtinit;
|
||||
Rune di[20][100];
|
||||
int ndi;
|
||||
|
||||
void
|
||||
emitdi(void)
|
||||
{
|
||||
flushdi();
|
||||
runefmtstrinit(&difmt);
|
||||
difmtinit = 1;
|
||||
fmtrune(&difmt, Uformatted);
|
||||
}
|
||||
|
||||
void
|
||||
flushdi(void)
|
||||
{
|
||||
int n;
|
||||
Rune *p;
|
||||
|
||||
if(ndi == 0 || difmtinit == 0)
|
||||
return;
|
||||
fmtrune(&difmt, Uunformatted);
|
||||
p = runefmtstrflush(&difmt);
|
||||
memset(&difmt, 0, sizeof difmt);
|
||||
difmtinit = 0;
|
||||
if(p == nil)
|
||||
warn("out of memory in diversion %C%S", dot, di[ndi-1]);
|
||||
else{
|
||||
n = runestrlen(p);
|
||||
if(n > 0 && p[n-1] != '\n'){
|
||||
p = runerealloc(p, n+2);
|
||||
p[n] = '\n';
|
||||
p[n+1] = 0;
|
||||
}
|
||||
}
|
||||
as(di[ndi-1], p);
|
||||
free(p);
|
||||
}
|
||||
|
||||
void
|
||||
outdi(Rune r)
|
||||
{
|
||||
if(!difmtinit) abort();
|
||||
if(r == Uempty)
|
||||
return;
|
||||
fmtrune(&difmt, r);
|
||||
}
|
||||
|
||||
/* .di, .da */
|
||||
void
|
||||
r_di(int argc, Rune **argv)
|
||||
{
|
||||
br();
|
||||
if(argc > 2)
|
||||
warn("extra arguments to %C%S", dot, argv[0]);
|
||||
if(argc == 1){
|
||||
/* end diversion */
|
||||
if(ndi <= 0){
|
||||
// warn("unmatched %C%S", dot, argv[0]);
|
||||
return;
|
||||
}
|
||||
flushdi();
|
||||
if(--ndi == 0){
|
||||
_nr(L(".z"), nil);
|
||||
outcb = nil;
|
||||
}else{
|
||||
_nr(L(".z"), di[ndi-1]);
|
||||
runefmtstrinit(&difmt);
|
||||
fmtrune(&difmt, Uformatted);
|
||||
difmtinit = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* start diversion */
|
||||
/* various register state should be saved, but it's all useless to us */
|
||||
flushdi();
|
||||
if(ndi >= nelem(di))
|
||||
sysfatal("%Cdi overflow", dot);
|
||||
if(argv[0][1] == 'i')
|
||||
ds(argv[1], nil);
|
||||
_nr(L(".z"), argv[1]);
|
||||
runestrcpy(di[ndi++], argv[1]);
|
||||
runefmtstrinit(&difmt);
|
||||
fmtrune(&difmt, Uformatted);
|
||||
difmtinit = 1;
|
||||
outcb = outdi;
|
||||
}
|
||||
|
||||
/* .wh - install trap */
|
||||
/* .ch - change trap */
|
||||
/* .dt - install diversion trap */
|
||||
|
||||
/* set input-line count trap */
|
||||
int itrapcount;
|
||||
int itrapwaiting;
|
||||
Rune *itrapname;
|
||||
|
||||
void
|
||||
r_it(int argc, Rune **argv)
|
||||
{
|
||||
if(argc < 3){
|
||||
itrapcount = 0;
|
||||
return;
|
||||
}
|
||||
itrapcount = eval(argv[1]);
|
||||
free(itrapname);
|
||||
itrapname = erunestrdup(argv[2]);
|
||||
}
|
||||
|
||||
void
|
||||
itrap(void)
|
||||
{
|
||||
itrapset();
|
||||
if(itrapwaiting){
|
||||
itrapwaiting = 0;
|
||||
runmacro1(itrapname);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
itrapset(void)
|
||||
{
|
||||
if(itrapcount > 0 && --itrapcount == 0)
|
||||
itrapwaiting = 1;
|
||||
}
|
||||
|
||||
/* .em - invoke macro when all input is over */
|
||||
void
|
||||
r_em(int argc, Rune **argv)
|
||||
{
|
||||
Rune buf[20];
|
||||
|
||||
USED(argc);
|
||||
runesnprint(buf, nelem(buf), ".%S\n", argv[1]);
|
||||
as(L("eof"), buf);
|
||||
}
|
||||
|
||||
int
|
||||
e_star(void)
|
||||
{
|
||||
Rune *p;
|
||||
|
||||
p = getds(getname());
|
||||
if(p)
|
||||
pushinputstring(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_t(void)
|
||||
{
|
||||
if(inputmode&CopyMode)
|
||||
return '\t';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_a(void)
|
||||
{
|
||||
if(inputmode&CopyMode)
|
||||
return '\a';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
e_backslash(void)
|
||||
{
|
||||
if(inputmode&ArgMode)
|
||||
ungetrune('\\');
|
||||
return backslash;
|
||||
}
|
||||
|
||||
int
|
||||
e_dot(void)
|
||||
{
|
||||
return '.';
|
||||
}
|
||||
|
||||
int
|
||||
e_dollar(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = getnext();
|
||||
if(c < '1' || c > '9'){
|
||||
ungetnext(c);
|
||||
return 0;
|
||||
}
|
||||
c -= '0';
|
||||
if(nmstack <= 0 || mstack[nmstack-1].argc <= c)
|
||||
return 0;
|
||||
pushinputstring(mstack[nmstack-1].argv[c]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
t7init(void)
|
||||
{
|
||||
addreq(L("de"), r_de, -1);
|
||||
addreq(L("am"), r_de, -1);
|
||||
addreq(L("ig"), r_de, -1);
|
||||
addraw(L("ds"), r_ds);
|
||||
addraw(L("as"), r_ds);
|
||||
addreq(L("rm"), r_rm, -1);
|
||||
addreq(L("rn"), r_rn, -1);
|
||||
addreq(L("di"), r_di, -1);
|
||||
addreq(L("da"), r_di, -1);
|
||||
addreq(L("it"), r_it, -1);
|
||||
addreq(L("em"), r_em, 1);
|
||||
addreq(L("wh"), r_wh, -1);
|
||||
addreq(L("ch"), r_ch, -1);
|
||||
addreq(L("dt"), r_dt, -1);
|
||||
|
||||
addesc('$', e_dollar, CopyMode|ArgMode|HtmlMode);
|
||||
addesc('*', e_star, CopyMode|ArgMode|HtmlMode);
|
||||
addesc('t', e_t, CopyMode|ArgMode);
|
||||
addesc('a', e_a, CopyMode|ArgMode);
|
||||
addesc('\\', e_backslash, ArgMode|CopyMode);
|
||||
addesc('.', e_dot, CopyMode|ArgMode);
|
||||
|
||||
ds(L("eof"), L(".sp 0.5i\n"));
|
||||
ds(L(".."), L(""));
|
||||
}
|
||||
|
449
src/cmd/htmlroff/t8.c
Normal file
449
src/cmd/htmlroff/t8.c
Normal file
|
@ -0,0 +1,449 @@
|
|||
#include "a.h"
|
||||
/*
|
||||
* 8. Number Registers
|
||||
* (Reg register implementation is also here.)
|
||||
*/
|
||||
|
||||
/*
|
||||
* \nx N
|
||||
* \n(xx N
|
||||
* \n+x N+=M
|
||||
* \n-x N-=M
|
||||
*
|
||||
* .nr R ±N M
|
||||
* .af R c
|
||||
*
|
||||
* formats
|
||||
* 1 0, 1, 2, 3, ...
|
||||
* 001 001, 002, 003, ...
|
||||
* i 0, i, ii, iii, iv, v, ...
|
||||
* I 0, I, II, III, IV, V, ...
|
||||
* a 0, a, b, ..., aa, ab, ..., zz, aaa, ...
|
||||
* A 0, A, B, ..., AA, AB, ..., ZZ, AAA, ...
|
||||
*
|
||||
* \gx \g(xx return format of number register
|
||||
*
|
||||
* .rr R
|
||||
*/
|
||||
|
||||
typedef struct Reg Reg;
|
||||
struct Reg
|
||||
{
|
||||
Reg *next;
|
||||
Rune *name;
|
||||
Rune *val;
|
||||
Rune *fmt;
|
||||
int inc;
|
||||
};
|
||||
|
||||
Reg *dslist;
|
||||
Reg *nrlist;
|
||||
|
||||
/*
|
||||
* Define strings and numbers.
|
||||
*/
|
||||
void
|
||||
dsnr(Rune *name, Rune *val, Reg **l)
|
||||
{
|
||||
Reg *s;
|
||||
|
||||
for(s = *l; s != nil; s = *l){
|
||||
if(runestrcmp(s->name, name) == 0)
|
||||
break;
|
||||
l = &s->next;
|
||||
}
|
||||
if(val == nil){
|
||||
if(s){
|
||||
*l = s->next;
|
||||
free(s->val);
|
||||
free(s->fmt);
|
||||
free(s);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(s == nil){
|
||||
s = emalloc(sizeof(Reg));
|
||||
*l = s;
|
||||
s->name = erunestrdup(name);
|
||||
}else
|
||||
free(s->val);
|
||||
s->val = erunestrdup(val);
|
||||
}
|
||||
|
||||
Rune*
|
||||
getdsnr(Rune *name, Reg *list)
|
||||
{
|
||||
Reg *s;
|
||||
|
||||
for(s=list; s; s=s->next)
|
||||
if(runestrcmp(name, s->name) == 0)
|
||||
return s->val;
|
||||
return nil;
|
||||
}
|
||||
|
||||
void
|
||||
ds(Rune *name, Rune *val)
|
||||
{
|
||||
dsnr(name, val, &dslist);
|
||||
}
|
||||
|
||||
void
|
||||
as(Rune *name, Rune *val)
|
||||
{
|
||||
Rune *p, *q;
|
||||
|
||||
p = getds(name);
|
||||
if(p == nil)
|
||||
p = L("");
|
||||
q = runemalloc(runestrlen(p)+runestrlen(val)+1);
|
||||
runestrcpy(q, p);
|
||||
runestrcat(q, val);
|
||||
ds(name, q);
|
||||
free(q);
|
||||
}
|
||||
|
||||
Rune*
|
||||
getds(Rune *name)
|
||||
{
|
||||
return getdsnr(name, dslist);
|
||||
}
|
||||
|
||||
void
|
||||
printds(int t)
|
||||
{
|
||||
int n, total;
|
||||
Reg *s;
|
||||
|
||||
total = 0;
|
||||
for(s=dslist; s; s=s->next){
|
||||
if(s->val)
|
||||
n = runestrlen(s->val);
|
||||
else
|
||||
n = 0;
|
||||
total += n;
|
||||
if(!t)
|
||||
fprint(2, "%S\t%d\n", s->name, n);
|
||||
}
|
||||
fprint(2, "total\t%d\n", total);
|
||||
}
|
||||
|
||||
void
|
||||
nr(Rune *name, int val)
|
||||
{
|
||||
Rune buf[20];
|
||||
|
||||
runesnprint(buf, nelem(buf), "%d", val);
|
||||
_nr(name, buf);
|
||||
}
|
||||
|
||||
void
|
||||
af(Rune *name, Rune *fmt)
|
||||
{
|
||||
Reg *s;
|
||||
|
||||
if(_getnr(name) == nil)
|
||||
_nr(name, L("0"));
|
||||
for(s=nrlist; s; s=s->next)
|
||||
if(runestrcmp(s->name, name) == 0)
|
||||
s->fmt = erunestrdup(fmt);
|
||||
}
|
||||
|
||||
Rune*
|
||||
getaf(Rune *name)
|
||||
{
|
||||
Reg *s;
|
||||
|
||||
for(s=nrlist; s; s=s->next)
|
||||
if(runestrcmp(s->name, name) == 0)
|
||||
return s->fmt;
|
||||
return nil;
|
||||
}
|
||||
|
||||
void
|
||||
printnr(void)
|
||||
{
|
||||
Reg *r;
|
||||
|
||||
for(r=nrlist; r; r=r->next)
|
||||
fprint(2, "%S %S %d\n", r->name, r->val, r->inc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some internal number registers are actually strings,
|
||||
* so provide _ versions to get at them.
|
||||
*/
|
||||
void
|
||||
_nr(Rune *name, Rune *val)
|
||||
{
|
||||
dsnr(name, val, &nrlist);
|
||||
}
|
||||
|
||||
Rune*
|
||||
_getnr(Rune *name)
|
||||
{
|
||||
return getdsnr(name, nrlist);
|
||||
}
|
||||
|
||||
int
|
||||
getnr(Rune *name)
|
||||
{
|
||||
Rune *p;
|
||||
|
||||
p = _getnr(name);
|
||||
if(p == nil)
|
||||
return 0;
|
||||
return eval(p);
|
||||
}
|
||||
|
||||
/* new register */
|
||||
void
|
||||
r_nr(int argc, Rune **argv)
|
||||
{
|
||||
Reg *s;
|
||||
|
||||
if(argc < 2)
|
||||
return;
|
||||
if(argc < 3)
|
||||
nr(argv[1], 0);
|
||||
else{
|
||||
if(argv[2][0] == '+')
|
||||
nr(argv[1], getnr(argv[1])+eval(argv[2]+1));
|
||||
else if(argv[2][0] == '-')
|
||||
nr(argv[1], getnr(argv[1])-eval(argv[2]+1));
|
||||
else
|
||||
nr(argv[1], eval(argv[2]));
|
||||
}
|
||||
if(argc > 3){
|
||||
for(s=nrlist; s; s=s->next)
|
||||
if(runestrcmp(s->name, argv[1]) == 0)
|
||||
s->inc = eval(argv[3]);
|
||||
}
|
||||
}
|
||||
|
||||
/* assign format */
|
||||
void
|
||||
r_af(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
|
||||
af(argv[1], argv[2]);
|
||||
}
|
||||
|
||||
/* remove register */
|
||||
void
|
||||
r_rr(int argc, Rune **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=1; i<argc; i++)
|
||||
_nr(argv[i], nil);
|
||||
}
|
||||
|
||||
/* fmt integer in base 26 */
|
||||
void
|
||||
alpha(Rune *buf, int n, int a)
|
||||
{
|
||||
int i, v;
|
||||
|
||||
i = 1;
|
||||
for(v=n; v>0; v/=26)
|
||||
i++;
|
||||
if(i == 0)
|
||||
i = 1;
|
||||
buf[i] = 0;
|
||||
while(i > 0){
|
||||
buf[--i] = a+n%26;
|
||||
n /= 26;
|
||||
}
|
||||
}
|
||||
|
||||
struct romanv {
|
||||
char *s;
|
||||
int v;
|
||||
} romanv[] =
|
||||
{
|
||||
"m", 1000,
|
||||
"cm", 900,
|
||||
"d", 500,
|
||||
"cd", 400,
|
||||
"c", 100,
|
||||
"xc", 90,
|
||||
"l", 50,
|
||||
"xl", 40,
|
||||
"x", 10,
|
||||
"ix", 9,
|
||||
"v", 5,
|
||||
"iv", 4,
|
||||
"i", 1
|
||||
};
|
||||
|
||||
/* fmt integer in roman numerals! */
|
||||
void
|
||||
roman(Rune *buf, int n, int upper)
|
||||
{
|
||||
Rune *p;
|
||||
char *q;
|
||||
struct romanv *r;
|
||||
|
||||
if(upper)
|
||||
upper = 'A' - 'a';
|
||||
if(n >= 5000 || n <= 0){
|
||||
runestrcpy(buf, L("-"));
|
||||
return;
|
||||
}
|
||||
p = buf;
|
||||
r = romanv;
|
||||
while(n > 0){
|
||||
while(n >= r->v){
|
||||
for(q=r->s; *q; q++)
|
||||
*p++ = *q + upper;
|
||||
n -= r->v;
|
||||
}
|
||||
r++;
|
||||
}
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
Rune*
|
||||
getname(void)
|
||||
{
|
||||
int i, c, cc;
|
||||
static Rune buf[100];
|
||||
|
||||
/* XXX add [name] syntax as in groff */
|
||||
c = getnext();
|
||||
if(c < 0)
|
||||
return L("");
|
||||
if(c == '\n'){
|
||||
warn("newline in name\n");
|
||||
ungetnext(c);
|
||||
return L("");
|
||||
}
|
||||
if(c == '['){
|
||||
for(i=0; i<nelem(buf)-1; i++){
|
||||
if((c = getrune()) < 0)
|
||||
return L("");
|
||||
if(c == ']'){
|
||||
buf[i] = 0;
|
||||
return buf;
|
||||
}
|
||||
buf[i] = c;
|
||||
}
|
||||
return L("");
|
||||
}
|
||||
if(c != '('){
|
||||
buf[0] = c;
|
||||
buf[1] = 0;
|
||||
return buf;
|
||||
}
|
||||
c = getnext();
|
||||
cc = getnext();
|
||||
if(c < 0 || cc < 0)
|
||||
return L("");
|
||||
if(c == '\n' | cc == '\n'){
|
||||
warn("newline in \\n");
|
||||
ungetnext(cc);
|
||||
if(c == '\n')
|
||||
ungetnext(c);
|
||||
}
|
||||
buf[0] = c;
|
||||
buf[1] = cc;
|
||||
buf[2] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* \n - return number register */
|
||||
int
|
||||
e_n(void)
|
||||
{
|
||||
int inc, v, l;
|
||||
Rune *name, *fmt, buf[100];
|
||||
Reg *s;
|
||||
|
||||
inc = getnext();
|
||||
if(inc < 0)
|
||||
return -1;
|
||||
if(inc != '+' && inc != '-'){
|
||||
ungetnext(inc);
|
||||
inc = 0;
|
||||
}
|
||||
name = getname();
|
||||
if(_getnr(name) == nil)
|
||||
_nr(name, L("0"));
|
||||
for(s=nrlist; s; s=s->next){
|
||||
if(runestrcmp(s->name, name) == 0){
|
||||
if(s->fmt == nil && !inc && s->val[0]){
|
||||
/* might be a string! */
|
||||
pushinputstring(s->val);
|
||||
return 0;
|
||||
}
|
||||
v = eval(s->val);
|
||||
if(inc){
|
||||
if(inc == '+')
|
||||
v += s->inc;
|
||||
else
|
||||
v -= s->inc;
|
||||
runesnprint(buf, nelem(buf), "%d", v);
|
||||
free(s->val);
|
||||
s->val = erunestrdup(buf);
|
||||
}
|
||||
fmt = s->fmt;
|
||||
if(fmt == nil)
|
||||
fmt = L("1");
|
||||
switch(fmt[0]){
|
||||
case 'i':
|
||||
case 'I':
|
||||
roman(buf, v, fmt[0]=='I');
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
alpha(buf, v, fmt[0]);
|
||||
break;
|
||||
default:
|
||||
l = runestrlen(fmt);
|
||||
if(l == 0)
|
||||
l = 1;
|
||||
runesnprint(buf, sizeof buf, "%0*d", l, v);
|
||||
break;
|
||||
}
|
||||
pushinputstring(buf);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pushinputstring(L(""));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* \g - number register format */
|
||||
int
|
||||
e_g(void)
|
||||
{
|
||||
Rune *p;
|
||||
|
||||
p = getaf(getname());
|
||||
if(p == nil)
|
||||
p = L("1");
|
||||
pushinputstring(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
r_pnr(int argc, Rune **argv)
|
||||
{
|
||||
USED(argc);
|
||||
USED(argv);
|
||||
printnr();
|
||||
}
|
||||
|
||||
void
|
||||
t8init(void)
|
||||
{
|
||||
addreq(L("nr"), r_nr, -1);
|
||||
addreq(L("af"), r_af, 2);
|
||||
addreq(L("rr"), r_rr, -1);
|
||||
addreq(L("pnr"), r_pnr, 0);
|
||||
|
||||
addesc('n', e_n, CopyMode|ArgMode|HtmlMode);
|
||||
addesc('g', e_g, 0);
|
||||
}
|
||||
|
6
src/cmd/htmlroff/t9.c
Normal file
6
src/cmd/htmlroff/t9.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
/*
|
||||
* 9. Tabs, leaders, and fields.
|
||||
*/
|
||||
|
||||
XXX
|
||||
|
123
src/cmd/htmlroff/util.c
Normal file
123
src/cmd/htmlroff/util.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
#include "a.h"
|
||||
|
||||
void*
|
||||
emalloc(uint n)
|
||||
{
|
||||
void *v;
|
||||
|
||||
v = mallocz(n, 1);
|
||||
if(v == nil)
|
||||
sysfatal("out of memory");
|
||||
return v;
|
||||
}
|
||||
|
||||
char*
|
||||
estrdup(char *s)
|
||||
{
|
||||
char *t;
|
||||
|
||||
t = strdup(s);
|
||||
if(t == nil)
|
||||
sysfatal("out of memory");
|
||||
return t;
|
||||
}
|
||||
|
||||
Rune*
|
||||
erunestrdup(Rune *s)
|
||||
{
|
||||
Rune *t;
|
||||
|
||||
t = emalloc(sizeof(Rune)*(runestrlen(s)+1));
|
||||
if(t == nil)
|
||||
sysfatal("out of memory");
|
||||
runestrcpy(t, s);
|
||||
return t;
|
||||
}
|
||||
|
||||
void*
|
||||
erealloc(void *ov, uint n)
|
||||
{
|
||||
void *v;
|
||||
|
||||
v = realloc(ov, n);
|
||||
if(v == nil)
|
||||
sysfatal("out of memory");
|
||||
return v;
|
||||
}
|
||||
|
||||
Rune*
|
||||
erunesmprint(char *fmt, ...)
|
||||
{
|
||||
Rune *s;
|
||||
va_list arg;
|
||||
|
||||
va_start(arg, fmt);
|
||||
s = runevsmprint(fmt, arg);
|
||||
va_end(arg);
|
||||
if(s == nil)
|
||||
sysfatal("out of memory");
|
||||
return s;
|
||||
}
|
||||
|
||||
char*
|
||||
esmprint(char *fmt, ...)
|
||||
{
|
||||
char *s;
|
||||
va_list arg;
|
||||
|
||||
va_start(arg, fmt);
|
||||
s = vsmprint(fmt, arg);
|
||||
va_end(arg);
|
||||
if(s == nil)
|
||||
sysfatal("out of memory");
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
warn(char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
|
||||
fprint(2, "htmlroff: %L: ");
|
||||
va_start(arg, fmt);
|
||||
vfprint(2, fmt, arg);
|
||||
va_end(arg);
|
||||
fprint(2, "\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* For non-Unicode compilers, so we can say
|
||||
* L("asdf") and get a Rune string. Assumes strings
|
||||
* are identified by their pointers, so no mutable strings!
|
||||
*/
|
||||
typedef struct Lhash Lhash;
|
||||
struct Lhash
|
||||
{
|
||||
char *s;
|
||||
Lhash *next;
|
||||
Rune r[1];
|
||||
};
|
||||
static Lhash *hash[1127];
|
||||
|
||||
Rune*
|
||||
L(char *s)
|
||||
{
|
||||
Rune *p;
|
||||
Lhash *l;
|
||||
uint h;
|
||||
|
||||
h = (uintptr)s%nelem(hash);
|
||||
for(l=hash[h]; l; l=l->next)
|
||||
if(l->s == s)
|
||||
return l->r;
|
||||
l = emalloc(sizeof *l+(utflen(s)+1)*sizeof(Rune));
|
||||
p = l->r;
|
||||
l->s = s;
|
||||
while(*s)
|
||||
s += chartorune(p++, s);
|
||||
*p = 0;
|
||||
l->next = hash[h];
|
||||
hash[h] = l;
|
||||
return l->r;
|
||||
}
|
||||
|
94
tmac/tmac.html
Normal file
94
tmac/tmac.html
Normal file
|
@ -0,0 +1,94 @@
|
|||
.de HTML
|
||||
\! \<?xml version="1.0" encoding="utf-8"?\>
|
||||
\! \<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
\! "http://www.w3.org/TR/html4/loose.dtd"\>
|
||||
.html html <html>
|
||||
.html head <head>
|
||||
.if !'\\$1'' .html title <title>\\$1</title>
|
||||
.HEAD
|
||||
.html head
|
||||
.html body <body>
|
||||
..
|
||||
.de FSFIRST
|
||||
.de NOTES xx
|
||||
._NOTES
|
||||
.rm _NOTES
|
||||
xx
|
||||
.em NOTES
|
||||
.da _NOTES
|
||||
.sp
|
||||
.B "Notes
|
||||
.sp
|
||||
.da
|
||||
..
|
||||
.de FS
|
||||
.FSFIRST
|
||||
.rm FSFIRST
|
||||
.da _NOTES
|
||||
..
|
||||
.de FE
|
||||
.sp
|
||||
.da
|
||||
..
|
||||
.nr png -1 1
|
||||
.de TS
|
||||
.ds pngbase "\\*[basename]
|
||||
.if '\\*[pngbase]'' .ds pngbase \\n(.B
|
||||
.ds pngfile \\*[pngbase]\\n+[png].png
|
||||
.html - <center><img src="\\*[pngfile]"></center>
|
||||
.\" The .inputpipe must be the last line of the macro!
|
||||
.inputpipe .TE troff2png >\\*[pngfile]
|
||||
..
|
||||
.de TE
|
||||
..
|
||||
.de PS
|
||||
.ds pngbase "\\*[basename]
|
||||
.if '\\*[pngbase]'' .ds pngbase \\n(.B
|
||||
.ds pngfile \\*[pngbase]\\n+[png].png
|
||||
.html - <center><img src="\\*[pngfile]"></center>
|
||||
.inputpipe .PE troff2png >\\*[pngfile]
|
||||
..
|
||||
.de PE
|
||||
..
|
||||
.de B1
|
||||
.margin 0
|
||||
.nr TW 10
|
||||
.nr TW1 80
|
||||
.if !'\\$1'' .nr TW \\$1
|
||||
.if !'\\$2'' .nr TW1 \\$2
|
||||
.html box \
|
||||
<center>\
|
||||
<table width=\\n[TW1]% cellspacing=0 cellpadding=0 border=0>\
|
||||
<tr height=1>\
|
||||
<td width=1 bgcolor=#000000 />\
|
||||
<td width=\\n(TW bgcolor=#000000 />\
|
||||
<td bgcolor=#000000 />\
|
||||
<td width=\\n(TW bgcolor=#000000 />\
|
||||
<td width=1 bgcolor=#000000 />\
|
||||
</tr>\
|
||||
<tr height=\\n(TW>\
|
||||
<td width=1 bgcolor=#000000 />\
|
||||
<td width=\\n(TW />\
|
||||
<td />\
|
||||
<td width=\\n(TW />\
|
||||
<td width=1 bgcolor=#000000 />\
|
||||
</tr>
|
||||
.html box0 <tr>
|
||||
.html box1 <td width=1 bgcolor=#000000 /><td width=\\n(TW /><td>
|
||||
..
|
||||
.de B2
|
||||
.html box1 <td width=\\n(TW /><td width=1 bgcolor=#000000 />
|
||||
.html box0 <tr height=\\n(TW><td width=1 bgcolor=#000000 />\
|
||||
<td width=\\n(TW /><td /><td width=\\n(TW />\
|
||||
<td width=1 bgcolor=#000000 />\
|
||||
</tr>\
|
||||
<tr height=1>\
|
||||
<td width=1 bgcolor=#000000 />\
|
||||
<td width=\\n(TW bgcolor=#000000 />\
|
||||
<td bgcolor=#000000 />\
|
||||
<td width=\\n(TW bgcolor=#000000 />\
|
||||
<td width=1 bgcolor=#000000 />\
|
||||
</tr>
|
||||
.html box
|
||||
.margin 1
|
||||
..
|
71
tmac/tmac.s
71
tmac/tmac.s
|
@ -308,9 +308,11 @@
|
|||
.di WT
|
||||
.na
|
||||
.fi
|
||||
.ie h .ll \\n(LLu
|
||||
.el \{\
|
||||
.ll 5.0i
|
||||
.if n .if \\n(TN .ll 29
|
||||
.if t .if \\n(TN .ll 3.5i
|
||||
.if t .if \\n(TN .ll 3.5i \}
|
||||
.ft 3
|
||||
.ps \\n(PS
|
||||
.if !\\n(TN \{\
|
||||
|
@ -318,6 +320,7 @@
|
|||
. vs \\n(.s+2
|
||||
. rm CS\}
|
||||
.hy 0
|
||||
.if h .ce 999
|
||||
..
|
||||
.de TX
|
||||
.rs
|
||||
|
@ -358,6 +361,7 @@
|
|||
. ft 3
|
||||
. ll 16\}\}
|
||||
.ps \\n(PS
|
||||
.if h .ce 999
|
||||
..
|
||||
.de AX
|
||||
.ft 1
|
||||
|
@ -503,6 +507,7 @@ ABSTRACT
|
|||
.ie \\n(VS>=41 .vs \\n(VSu
|
||||
.el .vs \\n(VSp
|
||||
.ti +\\n(PIu
|
||||
.fi
|
||||
..
|
||||
. \"AE - end of an abstract
|
||||
.de AE
|
||||
|
@ -704,6 +709,14 @@ Computing Science Technical Report No. \\*(MN
|
|||
.if \\$1H .TQ
|
||||
.nr IX 1
|
||||
..
|
||||
.if h \{\
|
||||
.de TS
|
||||
.nr tp -1 1
|
||||
.ds tp x\\n+(tp.png
|
||||
.html - <center><img src="\\*(tp"></center>
|
||||
.dp .TE troff2png >\\*(tp
|
||||
..
|
||||
.\}
|
||||
.de TQ
|
||||
.di TT
|
||||
.nr IT 1
|
||||
|
@ -818,9 +831,18 @@ Computing Science Technical Report No. \\*(MN
|
|||
.in
|
||||
.if \\n($1>0 .sp .65
|
||||
..
|
||||
.if h \{\
|
||||
.de PS
|
||||
.nr tp -1 1
|
||||
.ds tp x\\n+(tp.png
|
||||
.html - <center><img src="\\*(tp" /></center>
|
||||
.dp .PE troff2png >\\*(tp
|
||||
..
|
||||
.\}
|
||||
. \" .P1/.P2 macros for programs
|
||||
.
|
||||
.nr XP 1 \" delta point size for program
|
||||
.if h .nr XP 0
|
||||
.nr XV 1p \" delta vertical for programs
|
||||
.nr XT 8 \" delta tab stop for programs
|
||||
.nr DV .5v \" space before start of program
|
||||
|
@ -832,10 +854,11 @@ Computing Science Technical Report No. \\*(MN
|
|||
.br
|
||||
.nr v \\n(.v
|
||||
.di p1
|
||||
.in \\n(P1u
|
||||
.in +\\n(P1u
|
||||
.nf
|
||||
.ps -\\n(XP
|
||||
.vs -\\n(XVu
|
||||
.nr xx \\n(.sp
|
||||
.ft CW
|
||||
.nr t \\n(XT*\\w'x'u
|
||||
.ta 1u*\\ntu 2u*\\ntu 3u*\\ntu 4u*\\ntu 5u*\\ntu 6u*\\ntu 7u*\\ntu 8u*\\ntu 9u*\\ntu 10u*\\ntu 11u*\\ntu 12u*\\ntu 13u*\\ntu 14u*\\ntu
|
||||
|
@ -1565,6 +1588,50 @@ operating system\\$1
|
|||
.if \\n(BQ .fi
|
||||
.br
|
||||
..
|
||||
.if h \{\
|
||||
.de B1
|
||||
.margin 0
|
||||
.nr TW 10
|
||||
.nr TW1 80
|
||||
.if !'\\$1'' .nr TW \\$1
|
||||
.if !'\\$2'' .nr TW1 \\$2
|
||||
.html pic \
|
||||
<center>\
|
||||
<table width=\\n[TW1]% cellspacing=0 cellpadding=0 border=0>\
|
||||
<tr height=1>\
|
||||
<td width=1 bgcolor=#000000 />\
|
||||
<td width=\\n(TW bgcolor=#000000 />\
|
||||
<td bgcolor=#000000 />\
|
||||
<td width=\\n(TW bgcolor=#000000 />\
|
||||
<td width=1 bgcolor=#000000 />\
|
||||
</tr>\
|
||||
<tr height=\\n(TW>\
|
||||
<td width=1 bgcolor=#000000 />\
|
||||
<td width=\\n(TW />\
|
||||
<td />\
|
||||
<td width=\\n(TW />\
|
||||
<td width=1 bgcolor=#000000 />\
|
||||
</tr>
|
||||
.html pic0 <tr>
|
||||
.html pic1 <td width=1 bgcolor=#000000 /><td width=\\n(TW /><td>\}
|
||||
..
|
||||
.de B2
|
||||
.html pic1 <td width=\\n(TW /><td width=1 bgcolor=#000000 />
|
||||
.html pic0 <tr height=\\n(TW><td width=1 bgcolor=#000000 />\
|
||||
<td width=\\n(TW /><td /><td width=\\n(TW />\
|
||||
<td width=1 bgcolor=#000000 />\
|
||||
</tr>\
|
||||
<tr height=1>\
|
||||
<td width=1 bgcolor=#000000 />\
|
||||
<td width=\\n(TW bgcolor=#000000 />\
|
||||
<td bgcolor=#000000 />\
|
||||
<td width=\\n(TW bgcolor=#000000 />\
|
||||
<td width=1 bgcolor=#000000 />\
|
||||
</tr>
|
||||
.html pic \}
|
||||
.margin 1
|
||||
..
|
||||
.\}
|
||||
.de AT
|
||||
.nf
|
||||
.sp
|
||||
|
|
|
@ -71,12 +71,14 @@
|
|||
.in 0
|
||||
.ls 1
|
||||
.if \\n(TB=0 .ev
|
||||
.if \\n(TB=0 .KX
|
||||
.if \\n(TB=0 .br
|
||||
.if \\n(TB=0 .ev 2
|
||||
.if \\n(TB=0 .KK
|
||||
.ls
|
||||
.ce 0
|
||||
.if \\n(TB=0 .rm KK
|
||||
.if \\n(TB=0 .KY
|
||||
.if \\n(TB .da KJ
|
||||
.if \\n(TB \!.KD \\n(dn \\n(KV
|
||||
.if \\n(TB .KK
|
||||
|
|
Loading…
Reference in a new issue