", outfile); if (anchor[0]) { fprintf(outfile, "", anchor); anchor[0] = '\0'; } } else if (!strcmp(line, ".RS") || !strncmp(line, ".RS ", 4)) { /* * Indent... */ float amount = 3.0; /* Indentation */ if (line[3]) amount = (float)atof(line + 4); fputs(end_fonts[font], outfile); font = 0; if (list) { nested = list; list = NULL; nested_indent = list_indent; list_indent = 0.0f; } fprintf(outfile, "
", amount, -amount);
if (anchor[0])
{
fprintf(outfile, "", anchor);
anchor[0] = '\0';
}
if (line[1] == 'T')
post = "
\n";
}
else if (!strcmp(line, ".TP") || !strncmp(line, ".TP ", 4))
{
/*
* Tagged list...
*
* .TP i
*/
float amount = 3.0; /* Indentation */
if (line[3])
amount = (float)atof(line + 4);
fputs(end_fonts[font], outfile);
font = 0;
if (list && strcmp(list, "dl"))
{
fprintf(outfile, "%s>\n", list);
list = NULL;
}
if (!list)
{
fputs("
", amount);
if (anchor[0])
{
fprintf(outfile, "", anchor);
anchor[0] = '\0';
}
}
else if (!strncmp(line, ".br", 3))
{
/*
* Grab line break...
*/
fputs("
\n", outfile);
}
else if (!strncmp(line, ".de ", 4))
{
/*
* Define macro - ignore...
*/
while (fgets(line, sizeof(line), infile))
{
linenum ++;
if (!strncmp(line, "..", 2))
break;
}
}
else if (!strncmp(line, ".ds ", 4) || !strncmp(line, ".rm ", 4) ||
!strncmp(line, ".tr ", 4) || !strncmp(line, ".hy ", 4) ||
!strncmp(line, ".IX ", 4) || !strncmp(line, ".PD", 3) ||
!strncmp(line, ".Sp", 3))
{
/*
* Ignore unused commands...
*/
}
else if (!strncmp(line, ".Vb", 3) || !strncmp(line, ".nf", 3) || !strncmp(line, ".EX", 3))
{
/*
* Start preformatted...
*/
fputs(end_fonts[font], outfile);
font = 0;
// if (list)
// {
// fprintf(outfile, "%s>\n", list);
// list = NULL;
// }
pre = 1;
fputs("
\n", outfile);
}
else if (!strncmp(line, ".Ve", 3) || !strncmp(line, ".fi", 3) || !strncmp(line, ".EE", 3))
{
/*
* End preformatted...
*/
fputs(end_fonts[font], outfile);
font = 0;
if (pre)
{
pre = 0;
fputs("\n", outfile);
}
}
else if (!strncmp(line, ".\\}", 3))
{
/*
* Ignore close block...
*/
}
else if (!strncmp(line, ".ie", 3) || !strncmp(line, ".if", 3) ||
!strncmp(line, ".el", 3))
{
/*
* If/else - ignore...
*/
if (strchr(line, '{') != NULL)
{
/*
* Skip whole block...
*/
while (fgets(line, sizeof(line), infile))
{
linenum ++;
if (strchr(line, '}') != NULL)
break;
}
}
}
#if 0
else if (!strncmp(line, ". ", 4))
{
/*
* Grab ...
*/
}
#endif /* 0 */
else if (!strncmp(line, ".\\\"#", 4))
{
/*
* Anchor for HTML output...
*/
strlcpy(anchor, line + 4, sizeof(anchor));
}
else if (strncmp(line, ".\\\"", 3))
{
/*
* Unknown...
*/
if ((lineptr = strchr(line, ' ')) != NULL)
*lineptr = '\0';
else if ((lineptr = strchr(line, '\n')) != NULL)
*lineptr = '\0';
fprintf(stderr, "mantohtml: Unknown man page command \'%s\' on line %d.\n", line, linenum);
}
/*
* Skip continuation lines...
*/
lineptr = line + strlen(line) - 1;
if (lineptr >= line && *lineptr == '\\')
{
while (fgets(line, sizeof(line), infile))
{
linenum ++;
lineptr = line + strlen(line) - 2;
if (lineptr < line || *lineptr != '\\')
break;
}
}
}
else
{
/*
* Process man page text...
*/
html_fputs(line, &font, outfile);
putc('\n', outfile);
if (post)
{
fputs(post, outfile);
post = NULL;
}
}
}
fprintf(outfile, "%s\n", end_fonts[font]);
font = 0;
if (list)
{
fprintf(outfile, "%s>\n", list);
list = NULL;
}
fputs("\n"
"\n", outfile);
/*
* Close files...
*/
if (infile != stdin)
fclose(infile);
if (outfile != stdout)
fclose(outfile);
/*
* Return with no errors...
*/
return (0);
}
/*
* 'html_alternate()' - Alternate words between two styles of text.
*/
static void
html_alternate(const char *s, /* I - String */
const char *first, /* I - First style or NULL */
const char *second, /* I - Second style of NULL */
FILE *fp) /* I - File */
{
int i = 0; /* Which style */
int quote = 0; /* Saw quote? */
int dolinks, /* Do hyperlinks to other man pages? */
link = 0; /* Doing a link now? */
/*
* Skip leading whitespace...
*/
while (isspace(*s & 255))
s ++;
dolinks = first && !strcmp(first, "b") && !second;
while (*s)
{
if (!i && dolinks)
{
/*
* See if we need to make a link to a man page...
*/
const char *end; /* End of current word */
const char *next; /* Start of next word */
for (end = s; *end && !isspace(*end & 255); end ++);
for (next = end; isspace(*next & 255); next ++);
if (isalnum(*s & 255) && *next == '(')
{
/*
* See if the man file is available locally...
*/
char name[1024], /* Name */
manfile[1024], /* Man page filename */
manurl[1024]; /* Man page URL */
strlcpy(name, s, sizeof(name));
if ((size_t)(end - s) < sizeof(name))
name[end - s] = '\0';
snprintf(manfile, sizeof(manfile), "%s.man", name);
snprintf(manurl, sizeof(manurl), "man-%s.html?TOPIC=Man+Pages", name);
if (!access(manfile, 0))
{
/*
* Local man page, do a link...
*/
fprintf(fp, "", manurl);
link = 1;
}
}
}
if (!i && first)
fprintf(fp, "<%s>", first);
else if (i && second)
fprintf(fp, "<%s>", second);
while ((!isspace(*s & 255) || quote) && *s)
{
if (*s == '\"')
quote = !quote;
if (*s == '\\' && s[1])
{
s ++;
html_putc(*s++, fp);
}
else
html_putc(*s++, fp);
}
if (!i && first)
fprintf(fp, "%s>", first);
else if (i && second)
fprintf(fp, "%s>", second);
if (i && link)
{
fputs("", fp);
link = 0;
}
i = 1 - i;
/*
* Skip trailing whitespace...
*/
while (isspace(*s & 255))
s ++;
}
putc('\n', fp);
}
/*
* 'html_fputs()' - Output a string, quoting as needed HTML entities.
*/
static void
html_fputs(const char *s, /* I - String */
int *font, /* IO - Font */
FILE *fp) /* I - File */
{
while (*s)
{
if (*s == '\\')
{
s ++;
if (!*s)
break;
if (*s == 'f')
{
int newfont; /* New font */
s ++;
if (!*s)
break;
if (!font)
{
s ++;
continue;
}
switch (*s++)
{
case 'R' :
case 'P' :
newfont = 0;
break;
case 'b' :
case 'B' :
newfont = 1;
break;
case 'i' :
case 'I' :
newfont = 2;
break;
default :
fprintf(stderr, "mantohtml: Unknown font \"\\f%c\" ignored.\n", s[-1]);
newfont = *font;
break;
}
if (newfont != *font)
{
fputs(end_fonts[*font], fp);
*font = newfont;
fputs(start_fonts[*font], fp);
}
}
else if (*s == '*')
{
/*
* Substitute macro...
*/
s ++;
if (!*s)
break;
switch (*s++)
{
case 'R' :
fputs("®", fp);
break;
case '(' :
if (!strncmp(s, "lq", 2))
fputs("“", fp);
else if (!strncmp(s, "rq", 2))
fputs("”", fp);
else if (!strncmp(s, "Tm", 2))
fputs("TM", fp);
else
fprintf(stderr, "mantohtml: Unknown macro \"\\*(%2s\" ignored.\n", s);
if (*s)
s ++;
if (*s)
s ++;
break;
default :
fprintf(stderr, "mantohtml: Unknown macro \"\\*%c\" ignored.\n", s[-1]);
break;
}
}
else if (*s == '(')
{
if (!strncmp(s, "(em", 3))
{
fputs("—", fp);
s += 3;
}
else if (!strncmp(s, "(en", 3))
{
fputs("–", fp);
s += 3;
}
else
{
putc(*s, fp);
s ++;
}
}
else if (*s == '[')
{
/*
* Substitute escaped character...
*/
s ++;
if (!strncmp(s, "co]", 3))
fputs("©", fp);
else if (!strncmp(s, "de]", 3))
fputs("°", fp);
else if (!strncmp(s, "rg]", 3))
fputs("®", fp);
else if (!strncmp(s, "tm]", 3))
fputs("TM", fp);
if (*s)
s ++;
if (*s)
s ++;
if (*s)
s ++;
}
else if (isdigit(s[0]) && isdigit(s[1]) &&
isdigit(s[2]))
{
fprintf(fp, "%d;", ((s[0] - '0') * 8 + s[1] - '0') * 8 + s[2] - '0');
s += 3;
}
else
{
if (*s != '\\' && *s != '\"' && *s != '\'' && *s != '-')
{
fprintf(stderr, "mantohtml: Unrecognized escape \"\\%c\" ignored.\n", *s);
html_putc('\\', fp);
}
html_putc(*s++, fp);
}
}
else if (!strncmp(s, "http://", 7) || !strncmp(s, "https://", 8) || !strncmp(s, "ftp://", 6))
{
/*
* Embed URL...
*/
char temp[1024]; /* Temporary string */
const char *end = s + 6; /* End of URL */
while (*end && !isspace(*end & 255))
end ++;
if (end[-1] == ',' || end[-1] == '.' || end[-1] == ')')
end --;
strlcpy(temp, s, sizeof(temp));
if ((size_t)(end -s) < sizeof(temp))
temp[end - s] = '\0';
fprintf(fp, "%s", temp, temp);
s = end;
}
else
html_putc(*s++ & 255, fp);
}
}
/*
* 'html_putc()' - Put a single character, using entities as needed.
*/
static void
html_putc(int ch, /* I - Character */
FILE *fp) /* I - File */
{
if (ch == '&')
fputs("&", fp);
else if (ch == '<')
fputs("<", fp);
else
putc(ch, fp);
}
/*
* 'strmove()' - Move characters within a string.
*/
static void
strmove(char *d, /* I - Destination */
const char *s) /* I - Source */
{
while (*s)
*d++ = *s++;
*d = '\0';
}