", 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... */ if (pre == 1) { pre ++; if (!line[0]) continue; // Skip initial blank line } 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 == '(') { // "name (section)" - 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(manurl, sizeof(manurl), "man-%s.html?TOPIC=Man+Pages", name); snprintf(manfile, sizeof(manfile), "%s.%d", name, atoi(next + 1)); 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 *tempptr; // Pointer into temporary string for (tempptr = temp; *s && !isspace(*s & 255) && tempptr < (temp + sizeof(temp) - 1); s ++) { if (strchr(",.)", *s) && strchr(",. \n\r\t", s[1])) { // End of URL break; } else if (*s == '\\' && s[1]) { // Escaped character s ++; *tempptr++ = *s; } else { // Regular character... *tempptr++ = *s; } } *tempptr = '\0'; fprintf(fp, "%s", temp, temp); } 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'; }