📄 man2html.c
字号:
if (!s) s = t; printf("<HTML><HEAD><TITLE> Manpage of %s</TITLE>\n" "</HEAD><BODY>\n" "See the manpage for <A HREF=\"%s.html\">%s</A>.\n" "</BODY></HTML>\n", s, h, h); } else#endif { /* * this works alright, except for * section 3 */ buf = read_man_page(h); if (!buf) { fprintf(stderr, "man2html: unable to open or read file %s.\n", h); out_html("<BLOCKQUOTE>" "man2html: unable to open or read file.\n"); out_html(h); out_html("</BLOCKQUOTE>\n"); } else { buf[0] = buf[l] = '\n'; buf[l + 1] = buf[l + 2] = '\0'; scan_troff(buf + 1, 0, NULL); } if (buf) free(buf); } *c++ = '\n'; break; } case V('t', 'a'): c = c + j; j = 0; while (*c != '\n') { sl = scan_expression(c, &tabstops[j]); if (*c == '-' || *c == '+') tabstops[j] += tabstops[j - 1]; c = sl; while (*c == ' ' || *c == '\t') c++; j++; } maxtstop = j; curpos = 0; break; case V('t', 'i'): /* * while (itemdepth || dl_set[itemdepth]) { * out_html("</DL>\n"); if (dl_set[itemdepth]) * dl_set[itemdepth]=0; else itemdepth--; } */ out_html("<BR>\n"); c = c + j; c = scan_expression(c, &j); for (i = 0; i < j; i++) out_html(" "); curpos = j; c = skip_till_newline(c); break; case V('t', 'm'): c = c + j; h = c; while (*c != '\n') c++; *c = '\0'; /* fprintf(stderr,"%s\n", h); */ *c = '\n'; break; case V('B', ' '): case V('B', '\n'): case V('I', ' '): case V('I', '\n'): /* parse one line in a certain font */ out_html(change_to_font(*c)); trans_char(c, '"', '\a'); c = c + j; if (*c == '\n') c++; c = scan_troff(c, 1, NULL); out_html(change_to_font('R')); out_html(NEWLINE); if (fillout) curpos++; else curpos = 0; break; case V('O', 'P'): /* groff manpages use this * construction */ /* .OP a b : [ <B>a</B> <I>b</I> ] */ mode = 1; c[0] = 'B'; c[1] = 'I'; out_html(change_to_font('R')); out_html("["); curpos++; case V('B', 'R'): case V('B', 'I'): case V('I', 'B'): case V('I', 'R'): case V('R', 'B'): case V('R', 'I'): { char font[2]; font[0] = c[0]; font[1] = c[1]; c = c + j; if (*c == '\n') c++; sl = fill_words(c, wordlist, &words); c = sl + 1; /* * .BR name (section) indicates a link. It * will be added in the output routine. */ for (i = 0; i < words; i++) { if (mode) { out_html(" "); curpos++; } wordlist[i][-1] = ' '; out_html(change_to_font(font[i & 1])); scan_troff(wordlist[i], 1, NULL); } out_html(change_to_font('R')); if (mode) { out_html(" ]"); curpos++; } out_html(NEWLINE); if (!fillout) curpos = 0; else curpos++; } break; case V('D', 'T'): for (j = 0; j < 20; j++) tabstops[j] = (j + 1) * 8; maxtstop = 20; c = skip_till_newline(c); break; case V('I', 'P'): sl = fill_words(c + j, wordlist, &words); c = sl + 1; if (!dl_set[itemdepth]) { out_html("<DL COMPACT>\n"); dl_set[itemdepth] = 1; } out_html("<DT>"); if (words) { scan_troff(wordlist[0], 1, NULL); } out_html("<DD>"); curpos = 0; break; case V('T', 'P'): if (!dl_set[itemdepth]) { out_html("<DL COMPACT>\n"); dl_set[itemdepth] = 1; } out_html("<DT>"); c = skip_till_newline(c); /* somewhere a definition ends with '.TP' */ if (!*c) still_dd = 1; else { c = scan_troff(c, 1, NULL); out_html("<DD>"); } curpos = 0; break; case V('I', 'X'): /* general index */ sl = fill_words(c + j, wordlist, &words); c = sl + 1; j = 4; while (idxlabel[j] == 'Z') idxlabel[j--] = 'A'; idxlabel[j]++;#ifdef MAKEINDEX fprintf(idxfile, "%s@%s@", fname, idxlabel); for (j = 0; j < words; j++) { h = NULL; scan_troff(wordlist[j], 1, &h); fprintf(idxfile, "_\b@%s", h); free(h); } fprintf(idxfile, "\n");#endif out_html("<A NAME=\""); out_html(idxlabel); /* * this will not work in mosaic (due to a bug). * Adding ' ' between '>' and '<' solves it, but * creates some space. A normal space does not work. */ out_html("\"></A>"); break; case V('L', 'P'): case V('P', 'P'): if (dl_set[itemdepth]) { out_html("</DL>\n"); dl_set[itemdepth] = 0; } if (fillout) out_html("<P>\n"); else { out_html(NEWLINE); NEWLINE[0] = '\n'; } curpos = 0; c = skip_till_newline(c); break; case V('H', 'P'): if (!dl_set[itemdepth]) { out_html("<DL COMPACT>"); dl_set[itemdepth] = 1; } out_html("<DT>\n"); still_dd = 1; c = skip_till_newline(c); curpos = 0; break; case V('P', 'D'): c = skip_till_newline(c); break; case V('R', 's'): /* BSD mandoc */ case V('R', 'S'): sl = fill_words(c + j, wordlist, &words); j = 1; if (words > 0) scan_expression(wordlist[0], &j); if (j >= 0) { itemdepth++; dl_set[itemdepth] = 0; out_html("<DL COMPACT><DT><DD>"); c = skip_till_newline(c); curpos = 0; break; } case V('R', 'e'): /* BSD mandoc */ case V('R', 'E'): if (itemdepth > 0) { if (dl_set[itemdepth]) out_html("</DL>"); out_html("</DL>\n"); itemdepth--; } c = skip_till_newline(c); curpos = 0; break; case V('S', 'B'): out_html(change_to_size(-1)); out_html(change_to_font('B')); c = scan_troff(c + j, 1, NULL); out_html(change_to_font('R')); out_html(change_to_size('0')); break; case V('S', 'M'): c = c + j; if (*c == '\n') c++; out_html(change_to_size(-1)); trans_char(c, '"', '\a'); c = scan_troff(c, 1, NULL); out_html(change_to_size('0')); break; case V('S', 's'): /* BSD mandoc */ mandoc_command = 1; case V('S', 'S'): mode = 1; case V('S', 'h'): /* BSD mandoc */ /* hack for fallthru from above */ mandoc_command = !mode || mandoc_command; case V('S', 'H'): c = c + j; if (*c == '\n') c++; while (itemdepth || dl_set[itemdepth]) { out_html("</DL>\n"); if (dl_set[itemdepth]) dl_set[itemdepth] = 0; else if (itemdepth > 0) itemdepth--; } out_html(change_to_font(0)); out_html(change_to_size(0)); if (!fillout) { fillout = 1; out_html("</PRE>"); } trans_char(c, '"', '\a'); add_to_index(mode, c); out_html("<A NAME=\""); out_html(label); /* for mosaic users */ if (mode) out_html("\"> </A>\n<H4>"); else out_html("\"> </A>\n<H3>"); mandoc_synopsis = strncmp(c, "SYNOPSIS", 8) == 0; c = mandoc_command ? scan_troff_mandoc(c, 1, NULL) : scan_troff(c, 1, NULL); if (mode) out_html("</H4>\n"); else out_html("</H3>\n"); curpos = 0; break; case V('T', 'S'): c = scan_table(c); break; case V('D', 't'): /* BSD mandoc */ mandoc_command = 1; case V('T', 'H'): if (!output_possible) { sl = fill_words(c + j, wordlist, &words); if (words > 1) { char *t; for (i = 1; i < words; i++) wordlist[i][-1] = '\0'; *sl = '\0'; output_possible = 1; sprintf(th_page_and_sec, "%s(%s)", wordlist[0], wordlist[1]); if (words > 2) { t = unescape(wordlist[2]); strncpy(th_datestr, t, sizeof(th_datestr)); th_datestr[sizeof(th_datestr) - 1] = '\0'; } else th_datestr[0] = '\0'; if (words > 3) { t = unescape(wordlist[3]); strncpy(th_version, t, sizeof(th_version)); th_version[sizeof(th_version) - 1] = '\0'; } else th_version[0] = '\0'; out_html("<HTML><HEAD>\n<TITLE>"); out_html(th_page_and_sec); out_html(" Manual Page"); out_html("</TITLE>\n</HEAD>\n<BODY>"); outputPageHeader(th_page_and_sec, th_datestr, th_page_and_sec); out_html("<BR><A HREF=\"#index\">Index</A>\n"); *sl = '\n'; out_html("<HR>\n"); if (mandoc_command) out_html("<BR>BSD mandoc<BR>"); } c = sl + 1; } else c = skip_till_newline(c); curpos = 0; break; case V('T', 'X'): sl = fill_words(c + j, wordlist, &words); *sl = '\0'; out_html(change_to_font('I')); if (words > 1) wordlist[1][-1] = '\0'; c = lookup_abbrev(wordlist[0]); curpos += strlen(c); out_html(c); out_html(change_to_font('R')); if (words > 1) out_html(wordlist[1]); *sl = '\n'; c = sl + 1; break; case V('r', 'm'): /* .rm xx : Remove request, macro or string */ case V('r', 'n'): /* * .rn xx yy : Rename request, macro or string xx to * yy */ { STRDEF *de; c = c + j; i = V(c[0], c[1]); c = c + 2; while (isspace(*c) && *c != '\n') c++; j = V(c[0], c[1]); while (*c && *c != '\n') c++; c++; de = strdef; while (de && de->nr != j) de = de->next; if (de) { if (de->st) free(de->st); de->nr = 0; } de = strdef; while (de && de->nr != i) de = de->next; if (de) de->nr = j; break; } case V('n', 'x'): /* .nx filename : next file. */ case V('i', 'n'): /* .in +-N : Indent */ c = skip_till_newline(c); break; case V('n', 'r'): /* * .nr R +-N M: define and set number register R by * +-N; auto-increment by M */ { INTDEF *intd; c = c + j; i = V(c[0], c[1]); c = c + 2; intd = intdef; while (intd && intd->nr != i) intd = intd->next; if (!intd) { intd = (INTDEF *) malloc(sizeof(INTDEF)); intd->nr = i; intd->val = 0; intd->incr = 0; intd->next = intdef; intdef = intd; } while (*c == ' ' || *c == '\t') c++; c = scan_expression(c, &intd->val); if (*c != '\n') { while (*c == ' ' || *c == '\t') c++; c = scan_expression(c, &intd->incr); } c = skip_till_newline(c); break; } case V('a', 'm'): /* .am xx yy : append to a macro. */ /* define or handle as .ig yy */ mode = 1; case V('d', 'e'): /* * .de xx yy : define or redefine macro xx; end at * .yy (..) */ /* define or handle as .ig yy */ { STRDEF *de; int olen = 0; c = c + j; sl = fill_words(c, wordlist, &words); i = V(c[0], c[1]); j = 2; if (words == 1) wordlist[1] = ".."; else { wordlist[1]--; wordlist[1][0] = '.'; j = 3; } c = sl + 1; sl = c; while (*c && strncmp(c, wordlist[1], j)) c = skip_till_newline(c); de = defdef; while (de && de->nr != i) de = de->next; if (mode && de) olen = strlen(de->st); j = olen + c - sl; h = stralloc(j * 2 + 4); if (h) { for (j = 0; j < olen; j++) h[j] = de->st[j]; if (!j || h[j - 1] != '\n') h[j++] = '\n'; while (sl != c) { if (sl[0] == '\\' && sl[1] == '\\') { h[j++] = '\\'; sl++; } else h[j++] = *sl; sl++; } h[j] = '\0'; if (de) { if (de->st) free(de->st); de->st = h; } else { de = (STRDEF *) malloc(sizeof(STRDEF)); de->nr = i; de->next = defdef; de->st = h; defdef = de; } } } c = skip_till_newline(c); break; case V('B', 'l'): /* BSD mandoc */ { char list_options[NULL_TERMINATED(MED_STR_MAX)]; char *nl = strchr(c, '\n'); c = c + j; if (dl_set[itemdepth]) { /* These things can * nest. */ itemdepth++; } if (nl) { /* Parse list options */ strlimitcpy(list_options, c, nl - c, MED_STR_MAX); } if (strstr(list_options, "-bullet")) { /* HTML Unnumbered List */ dl_set[itemdepth] = BL_BULLET_LIST; out_html("<UL>\n"); } else if (strstr(list_options, "-enum")) { /* HTML Ordered List */ dl_set[itemdepth] = BL_ENUM_LIST; out_html("<OL>\n"); } else { /* HTML Descriptive List */ dl_set[itemdepth] = BL_DESC_LIST; out_html("<DL COMPACT>\n"); } if (fillout) out_html("<P>\n"); else { out_html(NEWLINE); NEWLINE[0] = '\n'; } curpos = 0; c = skip_till_newline(c); break; } case V('E', 'l'): /* BSD mandoc */ c = c + j; if (dl_set[itemdepth] & BL_DESC_LIST) { out_html("</DL>\n"); } else if (dl_set[itemdepth] & BL_BULLET_LIST) { out_html("</UL>\n"); } else if (dl_set[itemdepth] & BL_ENUM_LIST) { out_html("</OL>\n"); } dl_set[itemdepth] = 0; if (itemdepth > 0) itemdepth--; if (fillout) out_html("<P>\n"); else { out_html(NEWLINE); NEWLINE[0] = '\n'; } curpos = 0; c = skip_till_newline(c); break; case V('I', 't'): /* BSD mandoc */ c = c + j; if (strncmp(c, "Xo", 2) == 0 && isspace(*(c + 2))) { c = skip_till_newline(c); } if (dl_set[itemdepth] & BL_DESC_LIST) { out_html("<DT>"); out_html(change_to_font('B')); if (*c == '\n') { /* Don't allow embedded * comms after a newline */ c++; c = scan_troff(c, 1, NULL); } else { /* Do allow embedded comms on * the same line. */ c = scan_troff_mandoc(c, 1, NULL); } out_html(change_to_font('R')); out_html(NEWLINE); out_html("<DD>"); } else if (dl_set[itemdepth] & (BL_BULLET_LIST | BL_ENUM_LIST)) { out_html("<LI>"); c = scan_troff_mandoc(c, 1, NULL); out_html(NEWLINE); } if (fillout) curpos++; else curpos = 0; break; case V('B', 'k'): /* BSD mandoc */ case V('E', 'k'): /* BSD mandoc */ case V('D', 'd'): /* BSD mandoc */ case V('O', 's'): /* BSD mandoc */ trans_char(c, '"', '\a'); c = c + j; if (*c == '\n') c++; c = scan_troff_mandoc(c, 1, NULL); out_html(NEWLINE); if (fillout) curpos++; else curpos = 0; break; case V('B', 't'): /* BSD mandoc */ trans_char(c, '"', '\a'); c = c + j; out_html(" is currently in beta test."); if (fillout) curpos++; else curpos = 0; break; case V('B', 'x'): /* BSD mandoc */ trans_char(c, '"', '\a'); c = c + j; if (*c == '\n') c++; out_html("BSD "); c = scan_troff_mandoc(c, 1, NULL); if (fillout) curpos++; else curpos = 0; break; case V('D', 'l'): /* BSD mandoc */ c = c + j; out_html(NEWLINE); out_html("<BLOCKQUOTE>"); out_html(change_to_font('L'));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -