char*
changesize(int amount)
{
static int curamount;
static char buf[200];
int i;
buf[0] = 0;
if (curamount >= 0)
for (i = 0; i < curamount; i++)
strcat(buf, "</big>");
else
for (i = 0; i < -curamount; i++)
strcat(buf, "</small>");
curamount = 0;
if (amount >= 0)
for (i = 0; i < amount; i++)
strcat(buf, "<big>");
else
for (i = 0; i < -amount; i++)
strcat(buf, "<small>");
curamount = amount;
return buf;
}
/* get next logical character. expand it with escapes */
char*
getnext(void)
{
int r;
Entity *e;
Troffspec *t;
Rune R;
char str[4];
static char buf[8];
/* ignore immediately following newline */
case 'c':
r = getrune();
if (r == '\n') {
sol = ignore_nl = 1;
if (indirective)
break;
}
else
ungetrune();
return getnext();
/* escape backslash */
case 'e':
return "\\";
/* font change */
case 'f':
r = getrune();
switch(r){
case '(':
str[0] = getrune();
str[1] = getrune();
str[2] = 0;
token[0] = 0;
if(strcmp("BI", str) == 0)
return changefont(&bifont);
else if(strcmp("CW", str) == 0)
return changefont(&cwfont);
else
return changefont(nil);
case '3':
case 'B':
return changefont(&bfont);
case '2':
case 'I':
return changefont(&ifont);
case '4':
return changefont(&bifont);
case '5':
return changefont(&cwfont);
case 'P':
return changebackfont();
case 'R':
default:
return changefont(nil);
}
/* number register */
case 'n':
r = getrune();
if (r == '(') /*)*/ {
r = getrune();
if (r < 0)
return nil;
str[0] = r;
r = getrune();
if (r < 0)
return nil;
str[1] = r;
str[2] = 0;
}
else {
str[0] = r;
str[1] = 0;
}
pushstr(getnr(str));
return getnext();
/* font size */
case 's':
r = getrune();
switch(r){
case '0':
return changesize(0);
case '-':
r = getrune();
if (!isdigit(r))
return getnext();
return changesize(-(r - '0'));
case '+':
r = getrune();
if (!isdigit(r))
return getnext();
return changesize(r - '0');
}
return getnext();
/* vertical movement */
case 'v':
r = getrune();
if(r != '\''){
ungetrune();
return getnext();
}
r = getrune();
if(r != '-')
vert--;
else
vert++;
while(r != '\'' && r != '\n')
r = getrune();
if(r != '\'')
ungetrune();
if(vert > 0)
return "^";
return getnext();
/* horizontal line */
case 'l':
r = getrune();
if(r != '\''){
ungetrune();
return "<HR>";
}
while(getrune() != '\'')
;
return "<HR>";
/* character height and slant */
case 'S':
case 'H':
r = getrune();
if(r != '\''){
ungetrune();
return "<HR>";
}
while(getrune() != '\'')
;
return getnext();
/* digit-width space */
case '0':
return " ";
/*for .if, .ie, .el */
case '{':
return "\\{"; /*}*/
case '}':
return "";
/* up and down */
case 'u':
if (isdown) {
isdown = 0;
return "</sub>";
}
isup = 1;
return "<sup>";
case 'd':
if (isup) {
isup = 0;
return "</sup>";
}
isdown = 1;
return "<sub>";
}
break;
case '&':
if(msp >= 0 || strsp >= 0)
return "&";
return "&";
case '<':
if(msp >= 0 || strsp >= 0)
return "<";
return "<";
case '>':
if(msp >= 0 || strsp >= 0)
return ">";
return ">";
}
if (r < Runeself) {
token[0] = r;
token[1] = 0;
}
else {
R = r;
token[runetochar(token,&R)] = 0;
}
return token;
}
/* if arg0 is set, read up to (and expand) to the next whitespace, else to the end of line */
char*
copyline(char *p, char *e, int arg0)
{
int c;
Rune r;
char *p1;
while((c = getrune()) == ' ' || c == '\t')
;
for(indirective = 1; p < e; c = getrune()) {
if (c < 0)
goto done;
switch(c) {
case '\\':
break;
case '\n':
if (arg0)
ungetrune();
goto done;
case ' ':
case '\t':
if (arg0)
goto done;
default:
r = c;
p += runetochar(p,&r);
continue;
}
ungetrune();
p1 = getnext();
if (p1 == nil)
goto done;
if (*p1 == '\n') {
if (arg0)
ungetrune();
break;
}
while((*p = *p1++) && p < e)
p++;
}
done:
indirective = 0;
*p++ = 0;
return p;
}
char*
copyarg(char *p, char *e, int *nullarg)
{
int c, quoted, last;
Rune r;
*nullarg = 0;
quoted = 0;
do{
c = getrune();
} while(c == ' ' || c == '\t');
last = 0;
for(; p < e; c = getrune()) {
if (c < 0)
break;
switch(c) {
case '\n':
ungetrune();
goto done;
case '\\':
r = c;
p += runetochar(p,&r);
if(last == '\\')
r = 0;
break;
case ' ':
case '\t':
if(!quoted && last != '\\')
goto done;
r = c;
p += runetochar(p,&r);
break;
case '"':
if(quoted && last != '\\')
goto done;
r = c;
p += runetochar(p,&r);
break;
default:
r = c;
p += runetochar(p,&r);
break;
}
last = r;
}
done:
*p++ = 0;
return p;
}
int
parseargs(char *p, char *e, char **argv)
{
int argc;
char *np;
int nullarg;
/* close a list */
void
closel(void)
{
g_P2(1, nil);
dohangingau();
if(paragraph){
Bprint(&bout, "</P>\n");
paragraph = 0;
}
switch(list){
case Lordered:
Bprint(&bout, "</ol>\n");
break;
case Lunordered:
Bprint(&bout, "</ul>\n");
break;
case Lother:
case Ldef:
Bprint(&bout, "</dl>\n");
break;
}
list = 0;
}
void
g_IP(int argc, char **argv)
{
switch(list){
default:
closel();
if(argc > 1){
if(strcmp(argv[1], "1") == 0){
list = Lordered;
listnum = 1;
Bprint(&bout, "<OL>\n");
} else if(strcmp(argv[1], "\\(bu") == 0){
list = Lunordered;
Bprint(&bout, "<UL>\n");
} else {
list = Lother;
Bprint(&bout, "<DL COMPACT>\n");
}
} else {
list = Lother;
Bprint(&bout, "<DL>\n");
}
break;
case Lother:
case Lordered:
case Lunordered:
break;
}
switch(list){
case Lother:
Bprint(&bout, "<DT>");
if(argc > 1)
printarg(argv[1]);
else
Bprint(&bout, "<DT> ");
Bprint(&bout, "<DD>\n");
break;
case Lordered:
case Lunordered:
Bprint(&bout, "<LI>\n");
break;
}
}
/*
* .5i is one <DL><DT><DD>
*/
void
g_in(int argc, char **argv)
{
float f;
int delta, x;
char *p;
f = indent/0.5;
delta = f;
if(argc <= 1){
indent = 0.0;
} else {
f = strtod(argv[1], &p);
switch(*p){
case 'i':
break;
case 'c':
f = f / 2.54;
break;
case 'P':
f = f / 6;
break;
default:
case 'u':
case 'm':
f = f * (12 / 72);
break;
case 'n':
f = f * (6 / 72);
break;
case 'p':
f = f / 72.0;
break;
}
switch(argv[1][0]){
case '+':
case '-':
indent += f;
break;
default:
indent = f;
break;
}
}
if(indent < 0.0)
indent = 0.0;
f = (indent/0.5);
x = f;
delta = x - delta;
while(delta < 0){
Bprint(&bout, "</DL>\n");
delta++;
}
while(delta > 0){
Bprint(&bout, "<DL><DT><DD>\n");
delta--;
}
}
if(!titleseen){
if(!title){
/* get base part of filename */
p = strrchr(ssp->filename, '/');
if(p == nil)
p = ssp->filename;
else
p++;
strncpy(name, p, sizeof(name));
name[sizeof(name)-1] = 0;
switch(argv[1][0]){
case '3':
case 'B':
pushfont(&bfont);
break;
case '2':
case 'I':
pushfont(&ifont);
break;
case '4':
pushfont(&bifont);
break;
case '5':
pushfont(&cwfont);
break;
case 'P':
popfont();
break;
case 'R':
default:
pushfont(nil);
break;
}
}
void
g_sp(int argc, char **argv)
{
int n;
n = 1;
if(argc > 1){
n = atoi(argv[1]);
if(n < 1)
n = 1;
if(argv[1][strlen(argv[1])-1] == 'i')
n *= 4;
}
if(n > 5){
Bprint(&bout, "<br> <br>\n");
Bprint(&bout, "<HR>\n");
Bprint(&bout, "<br> <br>\n");
} else
for(; n > 0; n--)
Bprint(&bout, "<br> <br>\n");
}
int
numval(char **pline, int recur)
{
char *p;
int neg, x, y;
x = neg = 0;
p = *pline;
while(*p == '-') {
neg = 1 - neg;
p++;
}
if (*p == '(') {
p++;
x = numval(&p, 1);
if (*p != ')')
goto done;
p++;
}
else while(*p >= '0' && *p <= '9')
x = 10*x + *p++ - '0';
if (neg)
x = -x;
if (recur)
for(;;) {
switch(*p++) {
case '+':
x += numval(&p, 0);
continue;
case '-':
x -= numval(&p, 0);
continue;
case '*':
x *= numval(&p, 0);
continue;
case '/':
y = numval(&p, 0);
if (y == 0) {
zerodivide();
x = 0;
goto done;
}
x /= y;
continue;
case '<':
if (*p == '=') {
p++;
x = x <= numval(&p, 0);
continue;
}
x = x < numval(&p, 0);
continue;
case '>':
if (*p == '=') {
p++;
x = x >= numval(&p, 0);
continue;
}
x = x > numval(&p, 0);
continue;
case '=':
if (*p == '=')
p++;
x = x == numval(&p, 0);
continue;
case '&':
x &= numval(&p, 0);
continue;
case ':':
x |= numval(&p, 0);
continue;
case '%':
y = numval(&p, 0);
if (!y) {
zerodivide();
goto done;
}
x %= y;
continue;
}
--p;
break;
}
done:
*pline = p;
return x;
}
int
iftest(char *p, char **bp)
{
char *p1;
int c, neg, rv;
rv = neg = 0;
if (*p == '!') {
neg = 1;
p++;
}
c = *p;
if (c >= '0' && c <= '9' || c == '+' || c == '-' || c == '('/*)*/) {
if (numval(&p,1) >= 1)
rv = 1;
goto done;
}
switch(c) {
case 't':
case 'o':
rv = 1;
case 'n':
case 'e':
p++;
goto done;
}
for(p1 = ++p; *p != c; p++)
if (!*p)
goto done;
for(p++;;) {
if (*p != *p1++) {
while(*p && *p++ != c);
goto done;
}
if (*p++ == c)
break;
}
rv = 1;
done:
if (neg)
rv = 1 - rv;
while(*p == ' ' || *p == '\t')
p++;
*bp = p;
return rv;
}
void
scanline(char *p, char *e, int wantnl)
{
int c;
Rune r;
while((c = getrune()) == ' ' || c == '\t') ;
while(p < e) {
if (c < 0)
break;
if (c < Runeself) {
if (c == '\n') {
if (wantnl)
*p++ = c;
break;
}
*p++ = c;
}
else {
r = c;
p += runetochar(p, &r);
}
c = getrune();
}
*p = 0;
}
void
pushbody(char *line)
{
char *b;
if (line[0] == '\\' && line[1] == '{' /*}*/ )
line += 2;
if (strsp < Maxmstack - 1) {
pushstr(b = strdup(line));
mustfree[strsp] = b;
}
}
void
skipbody(char *line)
{
int c, n;
if (line[0] != '\\' || line[1] != '{' /*}*/ )
return;
for(n = 1;;) {
while((c = getrune()) != '\\')
if (c < 0)
return;
c = getrune();
if (c == '{')
n++;
else if ((c == '}' && (c = getrune()) == '\n' && !--n)
|| c < 0)
return;
}
}
int
ifstart(char *line, char *e, char **bp)
{
int it;
char *b;
b = copyline(line, e, 1);
ungetrune();
b[-1] = getrune();
scanline(b, e, 1);
it = iftest(line, bp);
return it;
}
void
g_ie(char *line, char *e)
{
char *b;
if (elsetop >= Maxif-1) {
fprint(2, "ms2html: .ie's too deep\n");
return;
}
if (ifwastrue[++elsetop] = ifstart(line, e, &b))
pushbody(b);
else
skipbody(b);
}
void
g_if(char *line, char *e)
{
char *b;
if (ifstart(line, e, &b))
pushbody(b);
else
skipbody(b);
}
void
g_el(char *line, char *e)
{
if (elsetop < 0)
return;
scanline(line, e, 1);
if (ifwastrue[elsetop--])
skipbody(line);
else
pushbody(line);
}
void
g_ig(int argc, char **argv)
{
char *p, *s;
s = "..";
if (argc > 1)
s = argv[1];
for(;;) {
p = Brdline(&ssp->in, '\n');
if(p == nil)
break;
p[Blinelen(&ssp->in)-1] = 0;
if(strcmp(p, s) == 0)
break;
}
}
void
g_ds(char *line, char *e)
{
char *b;
b = copyline(line, e, 1);
if (b > line) {
copyline(b, e, 0);
if (*b == '"')
b++;
ds(line, b);
}
}
b = copyline(line, e, 1);
if (b == line)
return;
copyline(b, e, 0);
if (*b == '"')
b++;
for(s = strings; s != nil; s = s->next)
if(strcmp(line, s->name) == 0)
break;