2 * This program was written by Richard Verhoeven (NL:5482ZX35)
3 * at the Eindhoven University of Technology. Email: rcb5@win.tue.nl
5 * Permission is granted to distribute, modify and use this program as long
6 * as this comment is not removed or changed.
8 * THIS IS A MODIFIED VERSION. IT WAS MODIFIED BY chet@po.cwru.edu FOR
13 * man2html will add links to the converted manpages. The function add_links
14 * is used for that. At the moment it will add links as follows, where
15 * indicates what should match to start with:
17 * Recognition Item Link
18 * ----------------------------------------------------------
19 * name(*) Manpage ../man?/name.*
21 * name@hostname Email address mailto:name@hostname
23 * method://string URL method://string
25 * www.host.name WWW server http://www.host.name
27 * ftp.host.name FTP server ftp://ftp.host.name
29 * <file.h> Include file file:/usr/include/file.h
32 * Since man2html does not check if manpages, hosts or email addresses exist,
33 * some links might not work. For manpages, some extra checks are performed
34 * to make sure not every () pair creates a link. Also out of date pages
35 * might point to incorrect places.
37 * The program will not allow users to get system specific files, such as
38 * /etc/passwd. It will check that "man" is part of the specified file and
39 * that "/../" isn't. Even if someone manages to get such file, man2html will
40 * handle it like a manpage and will usually not produce any output (or crash).
42 * If you find any bugs when normal manpages are converted, please report
43 * them to me (rcb5@win.tue.nl) after you have checked that man(1) can handle
44 * the manpage correct.
46 * Known bugs and missing features:
48 * * Equations are not converted at all.
49 * * Tables are converted but some features are not possible in html.
50 * * The tabbing environment is converted by counting characters and adding
51 * spaces. This might go wrong (outside <PRE>)
52 * * Some pages look better if man2html works in troff mode, especially pages
53 * with tables. You can decide at compile time which made you want to use.
55 * -DNROFF=0 troff mode
56 * -DNROFF=1 nroff mode (default)
58 * if you install both modes, you should compile with the correct CGIBASE.
59 * * Some manpages rely on the fact that troff/nroff is used to convert
60 * them and use features which are not descripted in the man manpages.
61 * (definitions, calculations, conditionals, requests). I can't guarantee
62 * that all these features work on all manpages. (I didn't have the
63 * time to look through all the available manpages.)
77 #include <sys/types.h>
82 #define NULL_TERMINATED(n) ((n) + 1)
84 #define HUGE_STR_MAX 10000
85 #define LARGE_STR_MAX 2000
86 #define MED_STR_MAX 500
87 #define SMALL_STR_MAX 100
88 #define TINY_STR_MAX 10
90 #define MAX_MAN_PATHS 100 /* Max number of directories */
91 #define MAX_ZCATS 10 /* Max number of zcat style programs */
92 #define MAX_WORDLIST 100
95 #define EXIT_SUCCESS 0
98 #define EXIT_FAILURE 1
104 static char location_base
[NULL_TERMINATED(MED_STR_MAX
)] = "";
106 static char th_page_and_sec
[128] = { '\0' };
107 static char th_datestr
[128] = { '\0' };
108 static char th_version
[128] = { '\0' };
110 char *signature
= "<HR>\nThis document was created by man2html from %s.<BR>\nTime: %s\n";
112 /* timeformat for signature */
113 #define TIMEFORMAT "%d %B %Y %T %Z"
117 /* BSD mandoc Bl/El lists to HTML list types */
118 #define BL_DESC_LIST 1
119 #define BL_BULLET_LIST 2
120 #define BL_ENUM_LIST 4
122 /* BSD mandoc Bd/Ed example(?) blocks */
126 #ifndef HAVE_STRERROR
130 static char emsg
[40];
132 #if defined (HAVE_SYS_ERRLIST)
134 extern char *sys_errlist
[];
136 if (e
> 0 && e
< sys_nerr
)
137 return (sys_errlist
[e
]);
139 #endif /* HAVE_SYS_ERRLIST */
141 sprintf(emsg
, "Unknown system error %d", e
);
145 #endif /* !HAVE_STRERROR */
148 strgrow(char *old
, int len
)
150 char *new = realloc(old
, (strlen(old
) + len
+ 1) * sizeof(char));
153 fprintf(stderr
, "man2html: out of memory");
162 /* allocate enough for len + NULL */
163 char *new = malloc((len
+ 1) * sizeof(char));
166 fprintf(stderr
, "man2html: out of memory");
173 xmalloc (size_t size
)
179 fprintf(stderr
, "man2html: out of memory");
186 * Some systems don't have strdup so lets use our own - which can also
187 * check for out of memory.
190 strduplicate(char *from
)
192 char *new = stralloc(strlen(from
));
198 /* Assumes space for n plus a null */
200 strmaxcpy(char *to
, char *from
, int n
)
202 int len
= strlen(from
);
204 strncpy(to
, from
, n
);
205 to
[(len
<= n
) ? len
: n
] = '\0';
210 strmaxcat(char *to
, char *from
, int n
)
212 int to_len
= strlen(to
);
215 int from_len
= strlen(from
);
216 int cp
= (to_len
+ from_len
<= n
) ? from_len
: n
- to_len
;
218 strncpy(to
+ to_len
, from
, cp
);
219 to
[to_len
+ cp
] = '\0';
224 /* Assumes space for limit plus a null */
226 strlimitcpy(char *to
, char *from
, int n
, int limit
)
228 int len
= n
> limit
? limit
: n
;
230 strmaxcpy(to
, from
, len
);
236 * takes string and escapes all metacharacters. should be used before
237 * including string in system() or similar call.
240 escape_input(char *str
)
243 static char new[NULL_TERMINATED(MED_STR_MAX
)];
245 if (strlen(str
) * 2 + 1 > MED_STR_MAX
) {
247 "man2html: escape_input - str too long:\n%-80s...\n",
251 for (i
= 0; i
< strlen(str
); i
++) {
252 if (!(((str
[i
] >= 'A') && (str
[i
] <= 'Z')) ||
253 ((str
[i
] >= 'a') && (str
[i
] <= 'z')) ||
254 ((str
[i
] >= '0') && (str
[i
] <= '9')))) {
268 fprintf(stderr
, "man2html: usage: man2html filename\n");
274 * below this you should not change anything unless you know a lot
275 * about this program or about troff.
278 typedef struct STRDEF STRDEF
;
285 typedef struct INTDEF INTDEF
;
293 static char NEWLINE
[2] = "\n";
294 static char idxlabel
[6] = "ixAAA";
296 #define INDEXFILE "/tmp/manindex.list"
299 static FILE *idxfile
;
301 static STRDEF
*chardef
, *strdef
, *defdef
;
302 static INTDEF
*intdef
;
304 #define V(A,B) ((A)*256+(B))
306 static INTDEF standardint
[] = {
307 {V('n', ' '), NROFF
, 0, NULL
},
308 {V('t', ' '), 1 - NROFF
, 0, NULL
},
309 {V('o', ' '), 1, 0, NULL
},
310 {V('e', ' '), 0, 0, NULL
},
311 {V('.', 'l'), 70, 0, NULL
},
312 {V('.', '$'), 0, 0, NULL
},
313 {V('.', 'A'), NROFF
, 0, NULL
},
314 {V('.', 'T'), 1 - NROFF
, 0, NULL
},
315 {V('.', 'V'), 1, 0, NULL
}, /* the me package tests for this */
318 static STRDEF standardstring
[] = {
319 {V('R', ' '), 1, "®", NULL
},
320 {V('l', 'q'), 2, "``", NULL
},
321 {V('r', 'q'), 2, "''", NULL
},
326 static STRDEF standardchar
[] = {
327 {V('*', '*'), 1, "*", NULL
},
328 {V('*', 'A'), 1, "A", NULL
},
329 {V('*', 'B'), 1, "B", NULL
},
330 {V('*', 'C'), 2, "Xi", NULL
},
331 {V('*', 'D'), 5, "Delta", NULL
},
332 {V('*', 'E'), 1, "E", NULL
},
333 {V('*', 'F'), 3, "Phi", NULL
},
334 {V('*', 'G'), 5, "Gamma", NULL
},
335 {V('*', 'H'), 5, "Theta", NULL
},
336 {V('*', 'I'), 1, "I", NULL
},
337 {V('*', 'K'), 1, "K", NULL
},
338 {V('*', 'L'), 6, "Lambda", NULL
},
339 {V('*', 'M'), 1, "M", NULL
},
340 {V('*', 'N'), 1, "N", NULL
},
341 {V('*', 'O'), 1, "O", NULL
},
342 {V('*', 'P'), 2, "Pi", NULL
},
343 {V('*', 'Q'), 3, "Psi", NULL
},
344 {V('*', 'R'), 1, "P", NULL
},
345 {V('*', 'S'), 5, "Sigma", NULL
},
346 {V('*', 'T'), 1, "T", NULL
},
347 {V('*', 'U'), 1, "Y", NULL
},
348 {V('*', 'W'), 5, "Omega", NULL
},
349 {V('*', 'X'), 1, "X", NULL
},
350 {V('*', 'Y'), 1, "H", NULL
},
351 {V('*', 'Z'), 1, "Z", NULL
},
352 {V('*', 'a'), 5, "alpha", NULL
},
353 {V('*', 'b'), 4, "beta", NULL
},
354 {V('*', 'c'), 2, "xi", NULL
},
355 {V('*', 'd'), 5, "delta", NULL
},
356 {V('*', 'e'), 7, "epsilon", NULL
},
357 {V('*', 'f'), 3, "phi", NULL
},
358 {V('*', 'g'), 5, "gamma", NULL
},
359 {V('*', 'h'), 5, "theta", NULL
},
360 {V('*', 'i'), 4, "iota", NULL
},
361 {V('*', 'k'), 5, "kappa", NULL
},
362 {V('*', 'l'), 6, "lambda", NULL
},
363 {V('*', 'm'), 1, "µ", NULL
},
364 {V('*', 'n'), 2, "nu", NULL
},
365 {V('*', 'o'), 1, "o", NULL
},
366 {V('*', 'p'), 2, "pi", NULL
},
367 {V('*', 'q'), 3, "psi", NULL
},
368 {V('*', 'r'), 3, "rho", NULL
},
369 {V('*', 's'), 5, "sigma", NULL
},
370 {V('*', 't'), 3, "tau", NULL
},
371 {V('*', 'u'), 7, "upsilon", NULL
},
372 {V('*', 'w'), 5, "omega", NULL
},
373 {V('*', 'x'), 3, "chi", NULL
},
374 {V('*', 'y'), 3, "eta", NULL
},
375 {V('*', 'z'), 4, "zeta", NULL
},
376 {V('t', 's'), 5, "sigma", NULL
},
377 {V('+', '-'), 1, "±", NULL
},
378 {V('1', '2'), 1, "½", NULL
},
379 {V('1', '4'), 1, "¼", NULL
},
380 {V('3', '4'), 1, "¾", NULL
},
381 {V('F', 'i'), 3, "ffi", NULL
},
382 {V('F', 'l'), 3, "ffl", NULL
},
383 {V('a', 'a'), 1, "´", NULL
},
384 {V('a', 'p'), 1, "~", NULL
},
385 {V('b', 'r'), 1, "|", NULL
},
386 {V('b', 'u'), 1, "*", NULL
},
387 {V('b', 'v'), 1, "|", NULL
},
388 {V('c', 'i'), 1, "o", NULL
},
389 {V('c', 'o'), 1, "©", NULL
},
390 {V('c', 't'), 1, "¢", NULL
},
391 {V('d', 'e'), 1, "°", NULL
},
392 {V('d', 'g'), 1, "+", NULL
},
393 {V('d', 'i'), 1, "÷", NULL
},
394 {V('e', 'm'), 1, "-", NULL
},
395 {V('e', 'm'), 3, "---", NULL
},
396 {V('e', 'q'), 1, "=", NULL
},
397 {V('e', 's'), 1, "Ø", NULL
},
398 {V('f', 'f'), 2, "ff", NULL
},
399 {V('f', 'i'), 2, "fi", NULL
},
400 {V('f', 'l'), 2, "fl", NULL
},
401 {V('f', 'm'), 1, "´", NULL
},
402 {V('g', 'a'), 1, "`", NULL
},
403 {V('h', 'y'), 1, "-", NULL
},
404 {V('l', 'c'), 2, "|¯", NULL
},
405 {V('l', 'f'), 2, "|_", NULL
},
406 {V('l', 'k'), 1, "<FONT SIZE=+2>{</FONT>", NULL
},
407 {V('m', 'i'), 1, "-", NULL
},
408 {V('m', 'u'), 1, "×", NULL
},
409 {V('n', 'o'), 1, "¬", NULL
},
410 {V('o', 'r'), 1, "|", NULL
},
411 {V('p', 'l'), 1, "+", NULL
},
412 {V('r', 'c'), 2, "¯|", NULL
},
413 {V('r', 'f'), 2, "_|", NULL
},
414 {V('r', 'g'), 1, "®", NULL
},
415 {V('r', 'k'), 1, "<FONT SIZE=+2>}</FONT>", NULL
},
416 {V('r', 'n'), 1, "¯", NULL
},
417 {V('r', 'u'), 1, "_", NULL
},
418 {V('s', 'c'), 1, "§", NULL
},
419 {V('s', 'l'), 1, "/", NULL
},
420 {V('s', 'q'), 2, "[]", NULL
},
421 {V('u', 'l'), 1, "_", NULL
},
425 /* default: print code */
428 static char eqndelimopen
= 0, eqndelimclose
= 0;
429 static char escapesym
= '\\', nobreaksym
= '\'', controlsym
= '.', fieldsym
= 0, padsym
= 0;
431 static char *buffer
= NULL
;
432 static int buffpos
= 0, buffmax
= 0;
433 static int scaninbuff
= 0;
434 static int itemdepth
= 0;
435 static int dl_set
[20] = {0};
436 static int still_dd
= 0;
437 static int tabstops
[20] = {8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96};
438 static int maxtstop
= 12;
439 static int curpos
= 0;
441 static char *scan_troff(char *c
, int san
, char **result
);
442 static char *scan_troff_mandoc(char *c
, int san
, char **result
);
444 static char **argument
= NULL
;
446 static char charb
[TINY_STR_MAX
];
451 char datbuf
[NULL_TERMINATED(MED_STR_MAX
)];
457 timetm
= localtime(&clock
);
458 strftime(datbuf
, MED_STR_MAX
, TIMEFORMAT
, timetm
);
459 printf(signature
, manpage
, datbuf
);
479 if (charb
[0] == '<') { /* Fix up <= */
481 strncpy(charb
, "<", 4);
489 expand_string(int nr
)
505 read_man_page(char *filename
)
507 char *man_buf
= NULL
;
509 FILE *man_stream
= NULL
;
513 if (stat(filename
, &stbuf
) == -1)
516 buf_size
= stbuf
.st_size
;
517 man_buf
= stralloc(buf_size
+ 5);
518 man_stream
= fopen(filename
, "r");
521 if (fread(man_buf
+ 1, 1, buf_size
, man_stream
) == buf_size
) {
522 man_buf
[buf_size
] = '\n';
523 man_buf
[buf_size
+ 1] = man_buf
[buf_size
+ 2] = '\0';
534 static char outbuffer
[NULL_TERMINATED(HUGE_STR_MAX
)];
536 static int no_newline_output
= 0;
537 static int newline_for_fun
= 0;
538 static int output_possible
= 0;
539 static int out_length
= 0;
542 * Add the links to the output. At the moment the following are
546 * name(*) -> ../man?/name.*
548 * method://string -> method://string
549 * www.host.name -> http://www.host.name
550 * ftp.host.name -> ftp://ftp.host.name
551 * name@host -> mailto:name@host
552 * <name.h> -> file:/usr/include/name.h (guess)
554 * Other possible links to add in the future:
556 * /dir/dir/file -> file:/dir/dir/file
563 char *idtest
[6]; /* url, mailto, www, ftp, manpage */
565 out_length
+= strlen(c
);
566 /* search for (section) */
568 idtest
[0] = strstr(c
+ 1, "://");
569 idtest
[1] = strchr(c
+ 1, '@');
570 idtest
[2] = strstr(c
, "www.");
571 idtest
[3] = strstr(c
, "ftp.");
573 idtest
[4] = strchr(c
+ 1, '(');
577 idtest
[5] = strstr(c
+ 1, ".h>");
578 for (i
= 0; i
< 6; i
++)
579 nr
+= (idtest
[i
] != NULL
);
582 for (i
= 0; i
< 6; i
++)
583 if (idtest
[i
] && (j
< 0 || idtest
[i
] < idtest
[j
]))
586 case 5: /* <name.h> */
590 while (g
> c
&& g
[-1] != ';')
600 printf("<A HREF=\"file:/usr/include/%s\">%s</A>>", g
, g
);
609 case 4: /* manpage */
614 if (g
&& f
- g
< 6 && (isalnum(f
[-1]) || f
[-1] == '>') &&
615 ((isdigit(f
[1]) && f
[1] != '0' &&
616 (f
[2] == ')' || (isalpha(f
[2]) && f
[3] == ')') || f
[2] == 'X')) ||
617 (f
[2] == ')' && (f
[1] == 'n' || f
[1] == 'l')))) {
618 /* this might be a link */
620 /* skip html makeup */
621 while (h
> c
&& *h
== '>') {
622 while (h
!= c
&& *h
!= '<')
628 char t
, sec
, subsec
, *e
;
633 if ((subsec
== 'X' && f
[3] != ')') || subsec
== ')')
635 while (h
> c
&& (isalnum(h
[-1]) || h
[-1] == '_' ||
636 h
[-1] == '-' || h
[-1] == '.'))
647 "?man%c/%s.%c%c\">%s</A>",
648 sec
, h
, sec
, tolower(subsec
), h
);
652 "?man%c/%s.%c\">%s</A>",
668 while (*g
&& (isalnum(*g
) || *g
== '_' || *g
== '-' || *g
== '+' ||
682 printf("<A HREF=\"%s://%s\">%s</A>", (j
== 3 ? "ftp" : "http"),
695 while (g
> c
&& (isalnum(g
[-1]) || g
[-1] == '_' || g
[-1] == '-' ||
696 g
[-1] == '+' || g
[-1] == '.' || g
[-1] == '%'))
699 while (*h
&& (isalnum(*h
) || *h
== '_' || *h
== '-' || *h
== '+' ||
704 if (h
- f
> 4 && f
- g
> 1) {
713 printf("<A HREF=\"mailto:%s\">%s</A>", g
, g
);
726 while (g
> c
&& isalpha(g
[-1]) && islower(g
[-1]))
729 while (*h
&& !isspace(*h
) && *h
!= '<' && *h
!= '>' && *h
!= '"' &&
732 if (f
- g
> 2 && f
- g
< 7 && h
- f
> 3) {
741 printf("<A HREF=\"%s\">%s</A>", g
, g
);
755 if (idtest
[0] && idtest
[0] < c
)
756 idtest
[0] = strstr(c
+ 1, "://");
757 if (idtest
[1] && idtest
[1] < c
)
758 idtest
[1] = strchr(c
+ 1, '@');
759 if (idtest
[2] && idtest
[2] < c
)
760 idtest
[2] = strstr(c
, "www.");
761 if (idtest
[3] && idtest
[3] < c
)
762 idtest
[3] = strstr(c
, "ftp.");
763 if (idtest
[4] && idtest
[4] < c
)
764 idtest
[4] = strchr(c
+ 1, '(');
765 if (idtest
[5] && idtest
[5] < c
)
766 idtest
[5] = strstr(c
+ 1, ".h>");
767 for (i
= 0; i
< 6; i
++)
768 nr
+= (idtest
[i
] != NULL
);
773 static int current_font
= 0;
774 static int current_size
= 0;
775 static int fillout
= 1;
782 if (no_newline_output
) {
785 no_newline_output
= 1;
787 if (!no_newline_output
)
790 no_newline_output
= 1;
793 if (!no_newline_output
)
798 if (buffpos
>= buffmax
) {
801 h
= realloc(buffer
, buffmax
* 2);
807 buffer
[buffpos
++] = *c
++;
809 } else if (output_possible
) {
811 outbuffer
[obp
++] = *c
;
812 if (*c
== '\n' || obp
> HUGE_STR_MAX
) {
813 outbuffer
[obp
] = '\0';
814 add_links(outbuffer
);
831 static char *switchfont
[16] = {
832 "", FC0 FO1
, FC0 FO2
, FC0 FO3
,
833 FC1 FO0
, "", FC1 FO2
, FC1 FO3
,
834 FC2 FO0
, FC2 FO1
, "", FC2 FO3
,
835 FC3 FO0
, FC3 FO1
, FC3 FO2
, ""
839 change_to_font(int nr
)
877 i
= current_font
* 4 + nr
% 4;
878 current_font
= nr
% 4;
879 return switchfont
[i
];
882 static char sizebuf
[200];
885 change_to_size(int nr
)
905 nr
= current_size
+ nr
;
912 if (nr
== current_size
)
916 strcat(sizebuf
, change_to_font(0));
918 strcat(sizebuf
, "</FONT>");
923 strcat(sizebuf
, "<FONT SIZE=");
928 sizebuf
[l
++] = '-', nr
= -nr
;
929 sizebuf
[l
++] = nr
+ '0';
933 strcat(sizebuf
, change_to_font(i
));
937 static int asint
= 0;
938 static int intresult
= 0;
940 #define SKIPEOL while (*c && *c++!='\n')
942 static int skip_escape
= 0;
943 static int single_escape
= 0;
951 int exoutputp
, exskipescape
;
977 if (!(h
= argument
[i
]))
984 c
= scan_escape(c
+ 1);
1010 i
= c
[0] * 256 + c
[1];
1018 i
= c
[0] * 256 + c
[1];
1022 h
= expand_string(i
);
1031 } else if (*c
!= '(')
1035 i
= c
[0] * 256 + c
[1];
1039 h
= change_to_font(i
);
1050 } else if (*c
== '+') {
1056 else if (*c
== '\\') {
1063 while (isdigit(*c
) && (!i
|| (!j
&& i
< 4)))
1064 i
= i
* 10 + (*c
++) - '0';
1071 h
= change_to_size(i
* j
);
1099 while (intd
&& intd
->nr
!= i
)
1102 intd
->val
= intd
->val
+ j
* intd
->incr
;
1103 intresult
= intd
->val
;
1107 intresult
= current_size
;
1110 intresult
= current_font
;
1123 exoutputp
= output_possible
;
1124 exskipescape
= skip_escape
;
1125 output_possible
= 0;
1130 if (*c
== escapesym
)
1131 c
= scan_escape(c
+ 1);
1135 output_possible
= exoutputp
;
1136 skip_escape
= exskipescape
;
1151 exoutputp
= output_possible
;
1152 exskipescape
= skip_escape
;
1153 output_possible
= 0;
1156 if (*c
== escapesym
)
1157 c
= scan_escape(c
+ 1);
1160 output_possible
= exoutputp
;
1161 skip_escape
= exskipescape
;
1164 no_newline_output
= 1;
1171 if (newline_for_fun
)
1181 curpos
= (curpos
+ 8) & 0xfff8;
1192 if (single_escape
) {
1209 typedef struct TABLEITEM TABLEITEM
;
1213 int size
, align
, valign
, colspan
, rowspan
, font
, vleft
, vright
, space
,
1218 static TABLEITEM emptyfield
= {NULL
, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, NULL
};
1220 typedef struct TABLEROW TABLEROW
;
1224 TABLEROW
*prev
, *next
;
1227 static char *tableopt
[] = {
1228 "center", "expand", "box", "allbox", "doublebox",
1229 "tab", "linesize", "delim", NULL
1231 static int tableoptl
[] = {6, 6, 3, 6, 9, 3, 8, 5, 0};
1234 clear_table(TABLEROW
* table
)
1236 TABLEROW
*tr1
, *tr2
;
1237 TABLEITEM
*ti1
, *ti2
;
1247 free(ti1
->contents
);
1257 static char *scan_expression(char *c
, int *result
);
1260 scan_format(char *c
, TABLEROW
** result
, int *maxcol
)
1262 TABLEROW
*layout
, *currow
;
1263 TABLEITEM
*curfield
;
1267 clear_table(*result
);
1269 layout
= currow
= (TABLEROW
*) xmalloc(sizeof(TABLEROW
));
1270 currow
->next
= currow
->prev
= NULL
;
1271 currow
->first
= curfield
= (TABLEITEM
*) xmalloc(sizeof(TABLEITEM
));
1272 *curfield
= emptyfield
;
1273 while (*c
&& *c
!= '.') {
1289 if (curfield
->align
) {
1290 curfield
->next
= (TABLEITEM
*) xmalloc(sizeof(TABLEITEM
));
1291 curfield
= curfield
->next
;
1292 *curfield
= emptyfield
;
1294 curfield
->align
= toupper(*c
);
1301 curfield
->font
= toupper(*c
);
1307 curfield
->font
= toupper(*c
);
1314 curfield
->valign
= 't';
1330 i
= i
* 10 + (*c
++) - '0';
1332 curfield
->size
= i
* j
;
1334 curfield
->size
= j
- 10;
1340 c
= scan_expression(c
+ 2, &curfield
->width
);
1343 if (curfield
->align
)
1365 i
= i
* 10 + (*c
++) - '0';
1366 curfield
->space
= i
;
1370 currow
->next
= (TABLEROW
*) xmalloc(sizeof(TABLEROW
));
1371 currow
->next
->prev
= currow
;
1372 currow
= currow
->next
;
1373 currow
->next
= NULL
;
1374 curfield
= currow
->first
= (TABLEITEM
*) xmalloc(sizeof(TABLEITEM
));
1375 *curfield
= emptyfield
;
1384 while (*c
++ != '\n');
1388 curfield
= layout
->first
;
1392 curfield
= curfield
->next
;
1396 currow
= currow
->next
;
1403 next_row(TABLEROW
* tr
)
1411 TABLEITEM
*ti
, *ti2
;
1413 tr
->next
= (TABLEROW
*) xmalloc(sizeof(TABLEROW
));
1414 tr
->next
->prev
= tr
;
1419 tr
->first
= ti2
= (TABLEITEM
*) xmalloc(sizeof(TABLEITEM
));
1421 tr
->first
= ti2
= NULL
;
1424 ti2
->contents
= NULL
;
1425 if ((ti
= ti
->next
)) {
1426 ti2
->next
= (TABLEITEM
*) xmalloc(sizeof(TABLEITEM
));
1434 static char itemreset
[20] = "\\fR\\s0";
1440 int center
= 0, expand
= 0, box
= 0, border
= 0, linesize
= 1;
1441 int i
, j
, maxcol
= 0, finished
= 0;
1442 int oldfont
, oldsize
, oldfillout
;
1443 char itemsep
= '\t';
1444 TABLEROW
*layout
= NULL
, *currow
, *ftable
;
1445 TABLEITEM
*curfield
;
1447 while (*c
++ != '\n');
1451 oldfont
= current_font
;
1452 oldsize
= current_size
;
1453 oldfillout
= fillout
;
1454 out_html(change_to_font(0));
1455 out_html(change_to_size(0));
1460 while (*h
&& *h
!= '\n')
1463 /* scan table options */
1467 for (i
= 0; tableopt
[i
] && strncmp(tableopt
[i
], c
, tableoptl
[i
]); i
++);
1468 c
= c
+ tableoptl
[i
];
1486 while (*c
++ != '(');
1490 while (*c
++ != '(');
1493 linesize
= linesize
* 10 + (*c
++) - '0';
1506 c
= scan_format(c
, &layout
, &maxcol
);
1509 curfield
= layout
->first
;
1514 if ((*c
== '_' || *c
== '=') && (c
[1] == itemsep
|| c
[1] == '\n')) {
1515 if (c
[-1] == '\n' && c
[1] == '\n') {
1517 currow
->prev
->next
= (TABLEROW
*) xmalloc(sizeof(TABLEROW
));
1518 currow
->prev
->next
->next
= currow
;
1519 currow
->prev
->next
->prev
= currow
->prev
;
1520 currow
->prev
= currow
->prev
->next
;
1522 currow
->prev
= layout
= (TABLEROW
*) xmalloc(sizeof(TABLEROW
));
1523 currow
->prev
->prev
= NULL
;
1524 currow
->prev
->next
= currow
;
1526 curfield
= currow
->prev
->first
=
1527 (TABLEITEM
*) xmalloc(sizeof(TABLEITEM
));
1528 *curfield
= emptyfield
;
1529 curfield
->align
= *c
;
1530 curfield
->colspan
= maxcol
;
1531 curfield
= currow
->first
;
1535 curfield
->align
= *c
;
1537 curfield
= curfield
->next
;
1538 } while (curfield
&& curfield
->align
== 'S');
1541 currow
= next_row(currow
);
1542 curfield
= currow
->first
;
1546 } else if (*c
== 'T' && c
[1] == '{') {
1548 c
= strstr(h
, "\nT}");
1552 scan_troff(h
, 0, &g
);
1553 scan_troff(itemreset
, 0, &g
);
1557 curfield
->contents
= g
;
1559 curfield
= curfield
->next
;
1560 } while (curfield
&& curfield
->align
== 'S');
1563 if (c
[-1] == '\n') {
1564 currow
= next_row(currow
);
1565 curfield
= currow
->first
;
1567 } else if (*c
== '.' && c
[1] == 'T' && c
[2] == '&' && c
[-1] == '\n') {
1570 while (*c
++ != '\n');
1572 currow
= currow
->prev
;
1574 c
= scan_format(c
, &hr
, &i
);
1579 curfield
= currow
->first
;
1580 } else if (*c
== '.' && c
[1] == 'T' && c
[2] == 'E' && c
[-1] == '\n') {
1582 while (*c
++ != '\n');
1584 currow
->prev
->next
= NULL
;
1585 currow
->prev
= NULL
;
1586 clear_table(currow
);
1587 } else if (*c
== '.' && c
[-1] == '\n' && !isdigit(c
[1])) {
1589 * skip troff request inside table (usually only .sp
1592 while (*c
++ != '\n');
1595 while (*c
&& (*c
!= itemsep
|| c
[-1] == '\\') &&
1596 (*c
!= '\n' || c
[-1] == '\\'))
1599 if (*c
== itemsep
) {
1603 if (h
[0] == '\\' && h
[2] == '\n' &&
1604 (h
[1] == '_' || h
[1] == '^')) {
1606 curfield
->align
= h
[1];
1608 curfield
= curfield
->next
;
1609 } while (curfield
&& curfield
->align
== 'S');
1614 h
= scan_troff(h
, 1, &g
);
1615 scan_troff(itemreset
, 0, &g
);
1617 curfield
->contents
= g
;
1619 curfield
= curfield
->next
;
1620 } while (curfield
&& curfield
->align
== 'S');
1627 if (c
[-1] == '\n') {
1628 currow
= next_row(currow
);
1629 curfield
= currow
->first
;
1633 /* calculate colspan and rowspan */
1635 while (currow
->next
)
1636 currow
= currow
->next
;
1638 TABLEITEM
*ti
, *ti1
= NULL
, *ti2
= NULL
;
1642 ti1
= currow
->prev
->first
;
1644 switch (ti
->align
) {
1648 if (ti2
->rowspan
< ti
->rowspan
)
1649 ti2
->rowspan
= ti
->rowspan
;
1661 } while (ti2
&& curfield
->align
== 'S');
1669 currow
= currow
->prev
;
1671 /* produce html output */
1673 out_html("<CENTER>");
1675 out_html("<TABLE BORDER><TR><TD>");
1677 if (box
|| border
) {
1678 out_html(" BORDER");
1680 out_html("><TR><TD><TABLE");
1682 out_html(" WIDTH=100%");
1688 out_html("<TR VALIGN=top>");
1689 curfield
= currow
->first
;
1691 if (curfield
->align
!= 'S' && curfield
->align
!= '^') {
1693 switch (curfield
->align
) {
1695 curfield
->space
+= 4;
1697 out_html(" ALIGN=right");
1700 out_html(" ALIGN=center");
1704 if (!curfield
->valign
&& curfield
->rowspan
> 1)
1705 out_html(" VALIGN=center");
1706 if (curfield
->colspan
> 1) {
1709 out_html(" COLSPAN=");
1710 sprintf(buf
, "%i", curfield
->colspan
);
1713 if (curfield
->rowspan
> 1) {
1716 out_html(" ROWSPAN=");
1717 sprintf(buf
, "%i", curfield
->rowspan
);
1720 j
= j
+ curfield
->colspan
;
1723 out_html(change_to_size(curfield
->size
));
1725 out_html(change_to_font(curfield
->font
));
1726 switch (curfield
->align
) {
1728 out_html("<HR><HR>");
1734 if (curfield
->contents
)
1735 out_html(curfield
->contents
);
1738 if (curfield
->space
)
1739 for (i
= 0; i
< curfield
->space
; i
++)
1742 out_html(change_to_font(0));
1744 out_html(change_to_size(0));
1745 if (j
>= maxcol
&& curfield
->align
> '@' && curfield
->align
!= '_')
1749 curfield
= curfield
->next
;
1751 out_html("</TR>\n");
1752 currow
= currow
->next
;
1755 out_html("</TABLE>");
1756 out_html("</TABLE>");
1758 out_html("</TABLE>");
1760 out_html("</CENTER>\n");
1765 fillout
= oldfillout
;
1766 out_html(change_to_size(oldsize
));
1767 out_html(change_to_font(oldfont
));
1772 scan_expression(char *c
, int *result
)
1774 int value
= 0, value2
, j
= 0, sign
= 1, opex
= 0;
1778 c
= scan_expression(c
+ 1, &value
);
1780 } else if (*c
== 'n') {
1783 } else if (*c
== 't') {
1786 } else if (*c
== '\'' || *c
== '"' || *c
< ' ' || (*c
== '\\' && c
[1] == '(')) {
1788 * ?string1?string2? test if string1 equals string2.
1790 char *st1
= NULL
, *st2
= NULL
, *h
;
1801 while (*c
!= sep
&& (!tcmp
|| strncmp(c
, tcmp
, 4)))
1804 scan_troff(h
, 1, &st1
);
1810 while (*c
!= sep
&& (!tcmp
|| strncmp(c
, tcmp
, 4)))
1813 scan_troff(h
, 1, &st2
);
1817 else if (!st1
|| !st2
)
1820 value
= (!strcmp(st1
, st2
));
1829 while (*c
&& !isspace(*c
) && *c
!= ')') {
1833 c
= scan_expression(c
+ 1, &value2
);
1834 value2
= sign
* value2
;
1848 int num
= 0, denum
= 1;
1852 value2
= value2
* 10 + ((*c
++) - '0');
1855 while (isdigit(*c
)) {
1856 num
= num
* 10 + ((*c
++) - '0');
1861 /* scale indicator */
1863 case 'i': /* inch -> 10pt */
1864 value2
= value2
* 10 + (num
* 10 + denum
/ 2) / denum
;
1872 value2
= value2
+ (num
+ denum
/ 2) / denum
;
1873 value2
= sign
* value2
;
1878 c
= scan_escape(c
+ 1);
1879 value2
= intresult
* sign
;
1881 c
++; /* scale indicator */
1916 value
= value
- value2
;
1919 value
= value
+ value2
;
1922 value
= value
* value2
;
1926 value
= value
/ value2
;
1930 value
= value
% value2
;
1933 value
= (value
< value2
);
1936 value
= (value
> value2
);
1939 value
= (value
>= value2
);
1942 value
= (value
<= value2
);
1946 value
= (value
== value2
);
1949 value
= (value
&& value2
);
1952 value
= (value
|| value2
);
1955 fprintf(stderr
, "man2html: unknown operator %c.\n", oper
);
1968 trans_char(char *c
, char s
, char t
)
1973 while (*sl
!= '\n' || slash
) {
1975 if (*sl
== escapesym
)
1985 /* Remove \a from C in place. Return modified C. */
1993 while (i
< l
&& c
[i
]) {
1996 memmove (c
+ i
, c
+ i
+ 1, l
- i
);
2008 fill_words(char *c
, char *words
[], int *n
)
2016 while (*sl
&& (*sl
!= '\n' || slash
)) {
2020 skipspace
= !skipspace
;
2021 } else if (*sl
== '\a') {
2022 /* handle already-translated " */
2023 skipspace
= !skipspace
;
2024 } else if (*sl
== escapesym
)
2026 else if ((*sl
== ' ' || *sl
== '\t') && !skipspace
) {
2028 if (words
[*n
] != sl
)
2036 if (words
[*n
] != sl
)
2039 while (*sl
&& *sl
!= '\n')
2048 if (sl
!= words
[*n
])
2053 static char *abbrev_list
[] = {
2054 "GSBG", "Getting Started ",
2055 "SUBG", "Customizing SunOS",
2056 "SHBG", "Basic Troubleshooting",
2057 "SVBG", "SunView User's Guide",
2058 "MMBG", "Mail and Messages",
2059 "DMBG", "Doing More with SunOS",
2060 "UNBG", "Using the Network",
2061 "GDBG", "Games, Demos & Other Pursuits",
2062 "CHANGE", "SunOS 4.1 Release Manual",
2063 "INSTALL", "Installing SunOS 4.1",
2064 "ADMIN", "System and Network Administration",
2065 "SECUR", "Security Features Guide",
2066 "PROM", "PROM User's Manual",
2067 "DIAG", "Sun System Diagnostics",
2068 "SUNDIAG", "Sundiag User's Guide",
2069 "MANPAGES", "SunOS Reference Manual",
2070 "REFMAN", "SunOS Reference Manual",
2071 "SSI", "Sun System Introduction",
2072 "SSO", "System Services Overview",
2073 "TEXT", "Editing Text Files",
2074 "DOCS", "Formatting Documents",
2075 "TROFF", "Using <B>nroff</B> and <B>troff</B>",
2076 "INDEX", "Global Index",
2077 "CPG", "C Programmer's Guide",
2078 "CREF", "C Reference Manual",
2079 "ASSY", "Assembly Language Reference",
2080 "PUL", "Programming Utilities and Libraries",
2081 "DEBUG", "Debugging Tools",
2082 "NETP", "Network Programming",
2083 "DRIVER", "Writing Device Drivers",
2084 "STREAMS", "STREAMS Programming",
2085 "SBDK", "SBus Developer's Kit",
2086 "WDDS", "Writing Device Drivers for the SBus",
2087 "FPOINT", "Floating-Point Programmer's Guide",
2088 "SVPG", "SunView 1 Programmer's Guide",
2089 "SVSPG", "SunView 1 System Programmer's Guide",
2090 "PIXRCT", "Pixrect Reference Manual",
2091 "CGI", "SunCGI Reference Manual",
2092 "CORE", "SunCore Reference Manual",
2093 "4ASSY", "Sun-4 Assembly Language Reference",
2094 "SARCH", "<FONT SIZE=-1>SPARC</FONT> Architecture Manual",
2095 "KR", "The C Programming Language",
2099 lookup_abbrev(char *c
)
2105 while (abbrev_list
[i
] && strcmp(c
, abbrev_list
[i
]))
2108 return abbrev_list
[i
+ 1];
2113 static char manidx
[NULL_TERMINATED(HUGE_STR_MAX
)];
2114 static int subs
= 0;
2116 static char label
[5] = "lbAA";
2119 add_to_index(int level
, char *item
)
2124 if (label
[3] > 'Z') {
2128 if (level
!= subs
) {
2130 strmaxcpy(manidx
+ mip
, "</DL>\n", HUGE_STR_MAX
- mip
);
2133 strmaxcpy(manidx
+ mip
, "<DL>\n", HUGE_STR_MAX
- mip
);
2138 scan_troff(item
, 1, &c
);
2139 sprintf(manidx
+ mip
, "<DT><A HREF=\"#%s\">%s</A><DD>\n", label
, c
);
2147 skip_till_newline(char *c
)
2151 while (*c
&& *c
!= '\n' || lvl
> 0) {
2162 if (lvl
< 0 && newline_for_fun
) {
2163 newline_for_fun
= newline_for_fun
+ lvl
;
2164 if (newline_for_fun
< 0)
2165 newline_for_fun
= 0;
2171 outputPageHeader(char *l
, char *c
, char *r
)
2173 out_html("<TABLE WIDTH=100%>\n<TR>\n");
2174 out_html("<TH ALIGN=LEFT width=33%>");
2176 out_html("<TH ALIGN=CENTER width=33%>");
2178 out_html("<TH ALIGN=RIGHT width=33%>");
2180 out_html("\n</TR>\n</TABLE>\n");
2184 outputPageFooter(char *l
, char *c
, char *r
)
2187 outputPageHeader(l
, c
, r
);
2190 static int ifelseval
= 0;
2193 scan_request(char *c
)
2195 /* BSD Mandoc stuff */
2196 static int mandoc_synopsis
= 0; /* True if we are in the synopsis
2198 static int mandoc_command
= 0; /* True if this is mandoc page */
2199 static int mandoc_bd_options
; /* Only copes with non-nested Bd's */
2203 char *wordlist
[MAX_WORDLIST
];
2208 while (*c
== ' ' || *c
== '\t')
2216 while (c
[j
] == ' ' || c
[j
] == '\t')
2218 if (c
[0] == escapesym
) {
2219 /* some pages use .\" .\$1 .\} */
2220 /* .\$1 is too difficult/stupid */
2222 c
= skip_till_newline(c
);
2224 c
= scan_escape(c
+ 1);
2230 while (*h
&& *h
!= '\n')
2233 if (scaninbuff
&& buffpos
) {
2234 buffer
[buffpos
] = '\0';
2237 /* fprintf(stderr, "%s\n", c+2); */
2243 int oldcurpos
= curpos
;
2251 while (*c
&& *c
!= '\n')
2255 while (*c
&& strncmp(c
, ".di", 3))
2256 while (*c
&& *c
++ != '\n');
2259 while (de
&& de
->nr
!= i
)
2262 de
= (STRDEF
*) xmalloc(sizeof(STRDEF
));
2274 scan_troff(h
, 0, &de
->st
);
2276 while (*c
&& *c
++ != '\n');
2284 int oldcurpos
= curpos
;
2289 while (c
[j
] && c
[j
] != '\n')
2304 while (de
&& de
->nr
!= i
)
2311 de
= (STRDEF
*) xmalloc(sizeof(STRDEF
));
2318 c
= scan_troff(c
, 1, &h
);
2325 c
= scan_troff(c
, 1, &h
);
2330 c
= scan_troff(c
, 1, &de
->st
);
2344 if (c
[0] == escapesym
) {
2345 c
= scan_escape(c
+ 1);
2347 c
= skip_till_newline(c
);
2355 c
= skip_till_newline(c
);
2363 c
= skip_till_newline(c
);
2371 while ('0' <= *c
&& *c
<= '9') {
2372 i
= i
* 10 + *c
- '0';
2376 c
= skip_till_newline(c
);
2377 /* center next i lines */
2379 out_html("<CENTER>\n");
2383 c
= scan_troff(c
, 1, &line
);
2384 if (line
&& strncmp(line
, "<BR>", 4)) {
2390 out_html("</CENTER>\n");
2401 c
= skip_till_newline(c
);
2404 c
= skip_till_newline(c
);
2412 fieldsym
= padsym
= '\0';
2417 c
= skip_till_newline(c
);
2421 out_html(change_to_font(0));
2422 out_html(change_to_size('0'));
2423 out_html("</PRE>\n");
2427 c
= skip_till_newline(c
);
2432 out_html(change_to_font(0));
2434 if (*c
== escapesym
) {
2437 c
= scan_expression(c
, &fn
);
2439 out_html(change_to_font(fn
));
2441 out_html(change_to_font(*c
));
2445 c
= skip_till_newline(c
);
2448 /* .el anything : else part of if else */
2452 c
= scan_troff(c
, 1, NULL
);
2454 c
= skip_till_newline(c
+ j
);
2457 /* .ie c anything : then part of if else */
2460 * .if c anything .if !c anything .if N anything .if
2461 * !N anything .if 'string1'string2' anything .if
2462 * !'string1'string2' anything
2465 c
= scan_expression(c
, &i
);
2470 c
= scan_troff(c
, 1, NULL
);
2472 c
= skip_till_newline(c
);
2476 char *endwith
= "..\n";
2484 while (*c
&& *c
!= '\n')
2488 while (*c
&& strncmp(c
, endwith
, i
))
2489 while (*c
++ != '\n');
2490 while (*c
++ != '\n');
2495 out_html(change_to_font(0));
2496 out_html(change_to_size('0'));
2497 out_html("<PRE>\n");
2501 c
= skip_till_newline(c
);
2506 out_html(change_to_size('0'));
2513 } else if (*c
== '+') {
2517 c
= scan_expression(c
, &i
);
2523 out_html(change_to_size(i
* j
));
2525 c
= skip_till_newline(c
);
2536 c
= skip_till_newline(c
);
2559 scan_troff(h
, 1, &name
);
2564 if (stat(h
, &stbuf
) != -1)
2570 t
= strrchr(fname
, '/');
2573 fprintf(stderr
, "ln -s %s.html %s.html\n", h
, t
);
2574 s
= strrchr(t
, '.');
2577 printf("<HTML><HEAD><TITLE> Manpage of %s</TITLE>\n"
2579 "See the manpage for <A HREF=\"%s.html\">%s</A>.\n"
2586 * this works alright, except for
2589 buf
= read_man_page(h
);
2592 fprintf(stderr
, "man2html: unable to open or read file %s.\n",
2594 out_html("<BLOCKQUOTE>"
2595 "man2html: unable to open or read file.\n");
2597 out_html("</BLOCKQUOTE>\n");
2599 buf
[0] = buf
[l
] = '\n';
2600 buf
[l
+ 1] = buf
[l
+ 2] = '\0';
2601 scan_troff(buf
+ 1, 0, NULL
);
2612 while (*c
!= '\n') {
2613 sl
= scan_expression(c
, &tabstops
[j
]);
2614 if (*c
== '-' || *c
== '+')
2615 tabstops
[j
] += tabstops
[j
- 1];
2617 while (*c
== ' ' || *c
== '\t')
2626 * while (itemdepth || dl_set[itemdepth]) {
2627 * out_html("</DL>\n"); if (dl_set[itemdepth])
2628 * dl_set[itemdepth]=0; else itemdepth--; }
2632 c
= scan_expression(c
, &j
);
2633 for (i
= 0; i
< j
; i
++)
2636 c
= skip_till_newline(c
);
2644 /* fprintf(stderr,"%s\n", h); */
2651 /* parse one line in a certain font */
2652 out_html(change_to_font(*c
));
2653 trans_char(c
, '"', '\a');
2657 c
= scan_troff(c
, 1, NULL
);
2658 out_html(change_to_font('R'));
2665 case V('O', 'P'): /* groff manpages use this
2667 /* .OP a b : [ <B>a</B> <I>b</I> ] */
2671 out_html(change_to_font('R'));
2688 sl
= fill_words(c
, wordlist
, &words
);
2691 * .BR name (section) indicates a link. It
2692 * will be added in the output routine.
2694 for (i
= 0; i
< words
; i
++) {
2699 wordlist
[i
][-1] = ' ';
2700 out_html(change_to_font(font
[i
& 1]));
2701 scan_troff(wordlist
[i
], 1, NULL
);
2703 out_html(change_to_font('R'));
2716 for (j
= 0; j
< 20; j
++)
2717 tabstops
[j
] = (j
+ 1) * 8;
2719 c
= skip_till_newline(c
);
2722 sl
= fill_words(c
+ j
, wordlist
, &words
);
2724 if (!dl_set
[itemdepth
]) {
2725 out_html("<DL COMPACT>\n");
2726 dl_set
[itemdepth
] = 1;
2730 scan_troff(wordlist
[0], 1, NULL
);
2736 if (!dl_set
[itemdepth
]) {
2737 out_html("<DL COMPACT>\n");
2738 dl_set
[itemdepth
] = 1;
2741 c
= skip_till_newline(c
);
2742 /* somewhere a definition ends with '.TP' */
2746 c
= scan_troff(c
, 1, NULL
);
2753 sl
= fill_words(c
+ j
, wordlist
, &words
);
2756 while (idxlabel
[j
] == 'Z')
2757 idxlabel
[j
--] = 'A';
2760 fprintf(idxfile
, "%s@%s@", fname
, idxlabel
);
2761 for (j
= 0; j
< words
; j
++) {
2763 scan_troff(wordlist
[j
], 1, &h
);
2764 fprintf(idxfile
, "_\b@%s", h
);
2767 fprintf(idxfile
, "\n");
2769 out_html("<A NAME=\"");
2772 * this will not work in mosaic (due to a bug).
2773 * Adding ' ' between '>' and '<' solves it, but
2774 * creates some space. A normal space does not work.
2776 out_html("\"></A>");
2780 if (dl_set
[itemdepth
]) {
2781 out_html("</DL>\n");
2782 dl_set
[itemdepth
] = 0;
2791 c
= skip_till_newline(c
);
2794 if (!dl_set
[itemdepth
]) {
2795 out_html("<DL COMPACT>");
2796 dl_set
[itemdepth
] = 1;
2800 c
= skip_till_newline(c
);
2804 c
= skip_till_newline(c
);
2806 case V('R', 's'): /* BSD mandoc */
2808 sl
= fill_words(c
+ j
, wordlist
, &words
);
2811 scan_expression(wordlist
[0], &j
);
2814 dl_set
[itemdepth
] = 0;
2815 out_html("<DL COMPACT><DT><DD>");
2816 c
= skip_till_newline(c
);
2820 case V('R', 'e'): /* BSD mandoc */
2822 if (itemdepth
> 0) {
2823 if (dl_set
[itemdepth
])
2825 out_html("</DL>\n");
2828 c
= skip_till_newline(c
);
2832 out_html(change_to_size(-1));
2833 out_html(change_to_font('B'));
2834 c
= scan_troff(c
+ j
, 1, NULL
);
2835 out_html(change_to_font('R'));
2836 out_html(change_to_size('0'));
2842 out_html(change_to_size(-1));
2843 trans_char(c
, '"', '\a');
2844 c
= scan_troff(c
, 1, NULL
);
2845 out_html(change_to_size('0'));
2847 case V('S', 's'): /* BSD mandoc */
2851 case V('S', 'h'): /* BSD mandoc */
2852 /* hack for fallthru from above */
2853 mandoc_command
= !mode
|| mandoc_command
;
2858 while (itemdepth
|| dl_set
[itemdepth
]) {
2859 out_html("</DL>\n");
2860 if (dl_set
[itemdepth
])
2861 dl_set
[itemdepth
] = 0;
2862 else if (itemdepth
> 0)
2865 out_html(change_to_font(0));
2866 out_html(change_to_size(0));
2871 trans_char(c
, '"', '\a');
2872 add_to_index(mode
, c
);
2873 out_html("<A NAME=\"");
2875 /* for mosaic users */
2877 out_html("\"> </A>\n<H4>");
2879 out_html("\"> </A>\n<H3>");
2880 mandoc_synopsis
= strncmp(c
, "SYNOPSIS", 8) == 0;
2881 c
= mandoc_command
? scan_troff_mandoc(c
, 1, NULL
) : scan_troff(c
, 1, NULL
);
2883 out_html("</H4>\n");
2885 out_html("</H3>\n");
2891 case V('D', 't'): /* BSD mandoc */
2894 if (!output_possible
) {
2895 sl
= fill_words(c
+ j
, wordlist
, &words
);
2898 for (i
= 1; i
< words
; i
++)
2899 wordlist
[i
][-1] = '\0';
2901 output_possible
= 1;
2902 sprintf(th_page_and_sec
, "%s(%s)", wordlist
[0], wordlist
[1]);
2904 t
= unescape(wordlist
[2]);
2905 strncpy(th_datestr
, t
, sizeof(th_datestr
));
2906 th_datestr
[sizeof(th_datestr
) - 1] = '\0';
2908 th_datestr
[0] = '\0';
2910 t
= unescape(wordlist
[3]);
2911 strncpy(th_version
, t
, sizeof(th_version
));
2912 th_version
[sizeof(th_version
) - 1] = '\0';
2914 th_version
[0] = '\0';
2915 out_html("<HTML><HEAD>\n<TITLE>");
2916 out_html(th_page_and_sec
);
2917 out_html(" Manual Page");
2918 out_html("</TITLE>\n</HEAD>\n<BODY>");
2920 outputPageHeader(th_page_and_sec
, th_datestr
, th_page_and_sec
);
2922 out_html("<BR><A HREF=\"#index\">Index</A>\n");
2926 out_html("<BR>BSD mandoc<BR>");
2930 c
= skip_till_newline(c
);
2934 sl
= fill_words(c
+ j
, wordlist
, &words
);
2936 out_html(change_to_font('I'));
2938 wordlist
[1][-1] = '\0';
2939 c
= lookup_abbrev(wordlist
[0]);
2940 curpos
+= strlen(c
);
2942 out_html(change_to_font('R'));
2944 out_html(wordlist
[1]);
2949 /* .rm xx : Remove request, macro or string */
2952 * .rn xx yy : Rename request, macro or string xx to
2961 while (isspace(*c
) && *c
!= '\n')
2964 while (*c
&& *c
!= '\n')
2968 while (de
&& de
->nr
!= j
)
2976 while (de
&& de
->nr
!= i
)
2983 /* .nx filename : next file. */
2985 /* .in +-N : Indent */
2986 c
= skip_till_newline(c
);
2990 * .nr R +-N M: define and set number register R by
2991 * +-N; auto-increment by M
3000 while (intd
&& intd
->nr
!= i
)
3003 intd
= (INTDEF
*) xmalloc(sizeof(INTDEF
));
3007 intd
->next
= intdef
;
3010 while (*c
== ' ' || *c
== '\t')
3012 c
= scan_expression(c
, &intd
->val
);
3014 while (*c
== ' ' || *c
== '\t')
3016 c
= scan_expression(c
, &intd
->incr
);
3018 c
= skip_till_newline(c
);
3022 /* .am xx yy : append to a macro. */
3023 /* define or handle as .ig yy */
3027 * .de xx yy : define or redefine macro xx; end at
3030 /* define or handle as .ig yy */
3036 sl
= fill_words(c
, wordlist
, &words
);
3043 wordlist
[1][0] = '.';
3048 while (*c
&& strncmp(c
, wordlist
[1], j
))
3049 c
= skip_till_newline(c
);
3051 while (de
&& de
->nr
!= i
)
3054 olen
= strlen(de
->st
);
3056 h
= stralloc(j
* 2 + 4);
3058 for (j
= 0; j
< olen
; j
++)
3060 if (!j
|| h
[j
- 1] != '\n')
3063 if (sl
[0] == '\\' && sl
[1] == '\\') {
3076 de
= (STRDEF
*) xmalloc(sizeof(STRDEF
));
3084 c
= skip_till_newline(c
);
3086 case V('B', 'l'): /* BSD mandoc */
3088 char list_options
[NULL_TERMINATED(MED_STR_MAX
)];
3089 char *nl
= strchr(c
, '\n');
3092 if (dl_set
[itemdepth
]) { /* These things can
3096 if (nl
) { /* Parse list options */
3097 strlimitcpy(list_options
, c
, nl
- c
, MED_STR_MAX
);
3099 if (strstr(list_options
, "-bullet")) { /* HTML Unnumbered List */
3100 dl_set
[itemdepth
] = BL_BULLET_LIST
;
3102 } else if (strstr(list_options
, "-enum")) { /* HTML Ordered List */
3103 dl_set
[itemdepth
] = BL_ENUM_LIST
;
3105 } else { /* HTML Descriptive List */
3106 dl_set
[itemdepth
] = BL_DESC_LIST
;
3107 out_html("<DL COMPACT>\n");
3116 c
= skip_till_newline(c
);
3119 case V('E', 'l'): /* BSD mandoc */
3121 if (dl_set
[itemdepth
] & BL_DESC_LIST
) {
3122 out_html("</DL>\n");
3123 } else if (dl_set
[itemdepth
] & BL_BULLET_LIST
) {
3124 out_html("</UL>\n");
3125 } else if (dl_set
[itemdepth
] & BL_ENUM_LIST
) {
3126 out_html("</OL>\n");
3128 dl_set
[itemdepth
] = 0;
3138 c
= skip_till_newline(c
);
3140 case V('I', 't'): /* BSD mandoc */
3142 if (strncmp(c
, "Xo", 2) == 0 && isspace(*(c
+ 2))) {
3143 c
= skip_till_newline(c
);
3145 if (dl_set
[itemdepth
] & BL_DESC_LIST
) {
3147 out_html(change_to_font('B'));
3148 if (*c
== '\n') { /* Don't allow embedded
3149 * comms after a newline */
3151 c
= scan_troff(c
, 1, NULL
);
3152 } else { /* Do allow embedded comms on
3154 c
= scan_troff_mandoc(c
, 1, NULL
);
3156 out_html(change_to_font('R'));
3159 } else if (dl_set
[itemdepth
] & (BL_BULLET_LIST
| BL_ENUM_LIST
)) {
3161 c
= scan_troff_mandoc(c
, 1, NULL
);
3169 case V('B', 'k'): /* BSD mandoc */
3170 case V('E', 'k'): /* BSD mandoc */
3171 case V('D', 'd'): /* BSD mandoc */
3172 case V('O', 's'): /* BSD mandoc */
3173 trans_char(c
, '"', '\a');
3177 c
= scan_troff_mandoc(c
, 1, NULL
);
3184 case V('B', 't'): /* BSD mandoc */
3185 trans_char(c
, '"', '\a');
3187 out_html(" is currently in beta test.");
3193 case V('B', 'x'): /* BSD mandoc */
3194 trans_char(c
, '"', '\a');
3199 c
= scan_troff_mandoc(c
, 1, NULL
);
3205 case V('D', 'l'): /* BSD mandoc */
3208 out_html("<BLOCKQUOTE>");
3209 out_html(change_to_font('L'));
3212 c
= scan_troff_mandoc(c
, 1, NULL
);
3213 out_html(change_to_font('R'));
3214 out_html("</BLOCKQUOTE>");
3220 case V('B', 'd'): /* BSD mandoc */
3221 { /* Seems like a kind of example/literal mode */
3222 char bd_options
[NULL_TERMINATED(MED_STR_MAX
)];
3223 char *nl
= strchr(c
, '\n');
3227 strlimitcpy(bd_options
, c
, nl
- c
, MED_STR_MAX
);
3230 mandoc_bd_options
= 0; /* Remember options for
3232 if (strstr(bd_options
, "-offset indent")) {
3233 mandoc_bd_options
|= BD_INDENT
;
3234 out_html("<BLOCKQUOTE>\n");
3236 if (strstr(bd_options
, "-literal")
3237 || strstr(bd_options
, "-unfilled")) {
3239 mandoc_bd_options
|= BD_LITERAL
;
3240 out_html(change_to_font(0));
3241 out_html(change_to_size('0'));
3242 out_html("<PRE>\n");
3247 c
= skip_till_newline(c
);
3250 case V('E', 'd'): /* BSD mandoc */
3251 if (mandoc_bd_options
& BD_LITERAL
) {
3253 out_html(change_to_font(0));
3254 out_html(change_to_size('0'));
3255 out_html("</PRE>\n");
3258 if (mandoc_bd_options
& BD_INDENT
)
3259 out_html("</BLOCKQUOTE>\n");
3262 c
= skip_till_newline(c
);
3264 case V('B', 'e'): /* BSD mandoc */
3273 c
= skip_till_newline(c
);
3275 case V('X', 'r'): /* BSD mandoc */
3278 * Translate xyz 1 to xyz(1) Allow for
3279 * multiple spaces. Allow the section to be
3282 char buff
[NULL_TERMINATED(MED_STR_MAX
)];
3285 trans_char(c
, '"', '\a');
3289 c
++; /* Skip spaces */
3290 while (isspace(*c
) && *c
!= '\n')
3292 while (isalnum(*c
)) { /* Copy the xyz part */
3295 if (bufptr
>= buff
+ MED_STR_MAX
)
3299 while (isspace(*c
) && *c
!= '\n')
3300 c
++; /* Skip spaces */
3301 if (isdigit(*c
)) { /* Convert the number if
3305 if (bufptr
< buff
+ MED_STR_MAX
) {
3306 while (isalnum(*c
)) {
3309 if (bufptr
>= buff
+ MED_STR_MAX
)
3313 if (bufptr
< buff
+ MED_STR_MAX
) {
3319 while (*c
!= '\n') { /* Copy the remainder */
3323 if (bufptr
>= buff
+ MED_STR_MAX
)
3329 scan_troff_mandoc(buff
, 1, NULL
);
3338 case V('F', 'l'): /* BSD mandoc */
3339 trans_char(c
, '"', '\a');
3343 out_html(change_to_font('B'));
3344 c
= scan_troff_mandoc(c
, 1, NULL
);
3345 out_html(change_to_font('R'));
3353 case V('P', 'a'): /* BSD mandoc */
3354 case V('P', 'f'): /* BSD mandoc */
3355 trans_char(c
, '"', '\a');
3359 c
= scan_troff_mandoc(c
, 1, NULL
);
3366 case V('P', 'p'): /* BSD mandoc */
3374 c
= skip_till_newline(c
);
3376 case V('D', 'q'): /* BSD mandoc */
3377 trans_char(c
, '"', '\a');
3382 c
= scan_troff_mandoc(c
, 1, NULL
);
3390 case V('O', 'p'): /* BSD mandoc */
3391 trans_char(c
, '"', '\a');
3395 out_html(change_to_font('R'));
3397 c
= scan_troff_mandoc(c
, 1, NULL
);
3398 out_html(change_to_font('R'));
3406 case V('O', 'o'): /* BSD mandoc */
3407 trans_char(c
, '"', '\a');
3411 out_html(change_to_font('R'));
3413 c
= scan_troff_mandoc(c
, 1, NULL
);
3419 case V('O', 'c'): /* BSD mandoc */
3420 trans_char(c
, '"', '\a');
3422 c
= scan_troff_mandoc(c
, 1, NULL
);
3423 out_html(change_to_font('R'));
3430 case V('P', 'q'): /* BSD mandoc */
3431 trans_char(c
, '"', '\a');
3436 c
= scan_troff_mandoc(c
, 1, NULL
);
3444 case V('Q', 'l'): /* BSD mandoc */
3445 { /* Single quote first word in the line */
3448 trans_char(c
, '"', '\a');
3453 do { /* Find first whitespace after the
3454 * first word that isn't a mandoc
3456 while (*sp
&& isspace(*sp
))
3458 while (*sp
&& !isspace(*sp
))
3460 } while (*sp
&& isupper(*(sp
- 2)) && islower(*(sp
- 1)));
3463 * Use a newline to mark the end of text to
3468 out_html("`"); /* Quote the text */
3469 c
= scan_troff_mandoc(c
, 1, NULL
);
3478 case V('S', 'q'): /* BSD mandoc */
3479 trans_char(c
, '"', '\a');
3484 c
= scan_troff_mandoc(c
, 1, NULL
);
3492 case V('A', 'r'): /* BSD mandoc */
3493 /* parse one line in italics */
3494 out_html(change_to_font('I'));
3495 trans_char(c
, '"', '\a');
3497 if (*c
== '\n') { /* An empty Ar means "file
3499 out_html("file ...");
3501 c
= scan_troff_mandoc(c
, 1, NULL
);
3503 out_html(change_to_font('R'));
3510 case V('A', 'd'): /* BSD mandoc */
3511 case V('E', 'm'): /* BSD mandoc */
3512 case V('V', 'a'): /* BSD mandoc */
3513 case V('X', 'c'): /* BSD mandoc */
3514 /* parse one line in italics */
3515 out_html(change_to_font('I'));
3516 trans_char(c
, '"', '\a');
3520 c
= scan_troff_mandoc(c
, 1, NULL
);
3521 out_html(change_to_font('R'));
3528 case V('N', 'd'): /* BSD mandoc */
3529 trans_char(c
, '"', '\a');
3534 c
= scan_troff_mandoc(c
, 1, NULL
);
3541 case V('N', 'm'): /* BSD mandoc */
3543 static char mandoc_name
[NULL_TERMINATED(SMALL_STR_MAX
)] = "";
3545 trans_char(c
, '"', '\a');
3547 if (mandoc_synopsis
) { /* Break lines only in
3550 * seems to be treated
3551 * as a special case -
3553 static int count
= 0; /* Don't break on the
3559 char *end
= strchr(c
, '\n');
3561 if (end
) { /* Remember the name for
3563 strlimitcpy(mandoc_name
, c
, end
- c
, SMALL_STR_MAX
);
3568 out_html(change_to_font('B'));
3569 while (*c
== ' ' || *c
== '\t')
3571 if (*c
== '\n') { /* If Nm has no
3573 * from an earlier Nm
3574 * command that did have
3579 out_html(mandoc_name
);
3581 c
= scan_troff_mandoc(c
, 1, NULL
);
3583 out_html(change_to_font('R'));
3591 case V('C', 'd'): /* BSD mandoc */
3592 case V('C', 'm'): /* BSD mandoc */
3593 case V('I', 'c'): /* BSD mandoc */
3594 case V('M', 's'): /* BSD mandoc */
3595 case V('O', 'r'): /* BSD mandoc */
3596 case V('S', 'y'): /* BSD mandoc */
3597 /* parse one line in bold */
3598 out_html(change_to_font('B'));
3599 trans_char(c
, '"', '\a');
3603 c
= scan_troff_mandoc(c
, 1, NULL
);
3604 out_html(change_to_font('R'));
3611 case V('D', 'v'): /* BSD mandoc */
3612 case V('E', 'v'): /* BSD mandoc */
3613 case V('F', 'r'): /* BSD mandoc */
3614 case V('L', 'i'): /* BSD mandoc */
3615 case V('N', 'o'): /* BSD mandoc */
3616 case V('N', 's'): /* BSD mandoc */
3617 case V('T', 'n'): /* BSD mandoc */
3618 case V('n', 'N'): /* BSD mandoc */
3619 trans_char(c
, '"', '\a');
3623 out_html(change_to_font('B'));
3624 c
= scan_troff_mandoc(c
, 1, NULL
);
3625 out_html(change_to_font('R'));
3632 case V('%', 'A'): /* BSD mandoc biblio stuff */
3642 c
= scan_troff(c
, 1, NULL
); /* Don't allow embedded
3654 out_html(change_to_font('I'));
3657 c
= scan_troff(c
, 1, NULL
); /* Don't allow embedded
3659 out_html(change_to_font('R'));
3666 /* search macro database of self-defined macros */
3668 while (owndef
&& owndef
->nr
!= i
)
3669 owndef
= owndef
->next
;
3675 sl
= fill_words(c
+ j
, wordlist
, &words
);
3678 for (i
= 1; i
< words
; i
++)
3679 wordlist
[i
][-1] = '\0';
3680 for (i
= 0; i
< words
; i
++) {
3683 if (mandoc_command
) {
3684 scan_troff_mandoc(wordlist
[i
], 1, &h
);
3686 scan_troff(wordlist
[i
], 1, &h
);
3690 for (i
= words
; i
< 20; i
++)
3692 deflen
= strlen(owndef
->st
);
3693 for (i
= 0; owndef
->st
[deflen
+ 2 + i
] = owndef
->st
[i
]; i
++);
3694 oldargument
= argument
;
3695 argument
= wordlist
;
3696 onff
= newline_for_fun
;
3697 if (mandoc_command
) {
3698 scan_troff_mandoc(owndef
->st
+ deflen
+ 2, 0, NULL
);
3700 scan_troff(owndef
->st
+ deflen
+ 2, 0, NULL
);
3702 newline_for_fun
= onff
;
3703 argument
= oldargument
;
3704 for (i
= 0; i
< words
; i
++)
3708 } else if (mandoc_command
&&
3709 ((isupper(*c
) && islower(*(c
+ 1)))
3710 || (islower(*c
) && isupper(*(c
+ 1))))
3711 ) { /* Let through any BSD mandoc
3712 * commands that haven't been delt
3713 * with. I don't want to miss
3714 * anything out of the text. */
3720 out_html(buf
); /* Print the command (it
3721 * might just be text). */
3723 trans_char(c
, '"', '\a');
3726 out_html(change_to_font('R'));
3727 c
= scan_troff(c
, 1, NULL
);
3734 c
= skip_till_newline(c
);
3752 static int contained_tab
= 0;
3753 static int mandoc_line
= 0; /* Signals whether to look for embedded
3754 * mandoc commands. */
3756 /* san : stop at newline */
3758 scan_troff(char *c
, int san
, char **result
)
3761 char intbuff
[NULL_TERMINATED(MED_STR_MAX
)];
3765 int exbuffpos
, exbuffmax
, exscaninbuff
, exnewline_for_fun
;
3768 #define FLUSHIBP if (ibp) { intbuff[ibp]=0; out_html(intbuff); ibp=0; }
3771 exbuffpos
= buffpos
;
3772 exbuffmax
= buffmax
;
3773 exnewline_for_fun
= newline_for_fun
;
3774 exscaninbuff
= scaninbuff
;
3775 newline_for_fun
= 0;
3779 buffpos
= strlen(buffer
);
3782 buffer
= stralloc(LARGE_STR_MAX
);
3784 buffmax
= LARGE_STR_MAX
;
3789 /* start scanning */
3791 while (*h
&& (!san
|| newline_for_fun
|| *h
!= '\n')) {
3793 if (*h
== escapesym
) {
3797 } else if (*h
== controlsym
&& h
[-1] == '\n') {
3800 h
= scan_request(h
);
3801 if (san
&& h
[-1] == '\n')
3803 } else if (mandoc_line
3804 && *(h
) && isupper(*(h
))
3805 && *(h
+ 1) && islower(*(h
+ 1))
3806 && *(h
+ 2) && isspace(*(h
+ 2))) {
3808 * BSD embedded command eg ".It Fl Ar arg1 Fl Ar
3812 h
= scan_request(h
);
3813 if (san
&& h
[-1] == '\n')
3815 } else if (*h
== nobreaksym
&& h
[-1] == '\n') {
3818 h
= scan_request(h
);
3819 if (san
&& h
[-1] == '\n')
3824 if (h
[-1] == '\n' && still_dd
&& isalnum(*h
)) {
3826 * sometimes a .HP request is not followed by
3836 intbuff
[ibp
++] = '&';
3837 intbuff
[ibp
++] = 'a';
3838 intbuff
[ibp
++] = 'm';
3839 intbuff
[ibp
++] = 'p';
3840 intbuff
[ibp
++] = ';';
3844 intbuff
[ibp
++] = '&';
3845 intbuff
[ibp
++] = 'l';
3846 intbuff
[ibp
++] = 't';
3847 intbuff
[ibp
++] = ';';
3851 intbuff
[ibp
++] = '&';
3852 intbuff
[ibp
++] = 'g';
3853 intbuff
[ibp
++] = 't';
3854 intbuff
[ibp
++] = ';';
3858 intbuff
[ibp
++] = '&';
3859 intbuff
[ibp
++] = 'q';
3860 intbuff
[ibp
++] = 'u';
3861 intbuff
[ibp
++] = 'o';
3862 intbuff
[ibp
++] = 't';
3863 intbuff
[ibp
++] = ';';
3867 if (h
[-1] == '\n' && fillout
) {
3868 intbuff
[ibp
++] = '<';
3869 intbuff
[ibp
++] = 'P';
3870 intbuff
[ibp
++] = '>';
3872 if (contained_tab
&& fillout
) {
3873 intbuff
[ibp
++] = '<';
3874 intbuff
[ibp
++] = 'B';
3875 intbuff
[ibp
++] = 'R';
3876 intbuff
[ibp
++] = '>';
3881 intbuff
[ibp
++] = '\n';
3889 /* like a typewriter, not like TeX */
3890 tabstops
[19] = curpos
+ 1;
3891 while (curtab
< maxtstop
&& tabstops
[curtab
] <= curpos
)
3893 if (curtab
< maxtstop
) {
3895 while (curpos
< tabstops
[curtab
]) {
3896 intbuff
[ibp
++] = ' ';
3904 while (curpos
< tabstops
[curtab
]) {
3914 if (*h
== ' ' && (h
[-1] == '\n' || usenbsp
)) {
3916 if (!usenbsp
&& fillout
) {
3924 intbuff
[ibp
++] = ' ';
3925 } else if (*h
> 31 && *h
< 127)
3926 intbuff
[ibp
++] = *h
;
3927 else if (((unsigned char) (*h
)) > 127) {
3928 intbuff
[ibp
++] = '&';
3929 intbuff
[ibp
++] = '#';
3930 intbuff
[ibp
++] = '0' + ((unsigned char) (*h
)) / 100;
3931 intbuff
[ibp
++] = '0' + (((unsigned char) (*h
)) % 100) / 10;
3932 intbuff
[ibp
++] = '0' + ((unsigned char) (*h
)) % 10;
3933 intbuff
[ibp
++] = ';';
3938 if (ibp
> (MED_STR_MAX
- 20))
3945 buffer
[buffpos
] = '\0';
3948 newline_for_fun
= exnewline_for_fun
;
3952 buffpos
= exbuffpos
;
3953 buffmax
= exbuffmax
;
3954 scaninbuff
= exscaninbuff
;
3961 scan_troff_mandoc(char *c
, int san
, char **result
)
3963 char *ret
, *end
= c
;
3964 int oldval
= mandoc_line
;
3967 while (*end
&& *end
!= '\n') {
3972 && ispunct(*(end
- 1))
3973 && isspace(*(end
- 2)) && *(end
- 2) != '\n') {
3975 * Don't format lonely punctuation E.g. in "xyz ," format the
3976 * xyz and then append the comma removing the space.
3979 ret
= scan_troff(c
, san
, result
);
3980 *(end
- 2) = *(end
- 1);
3983 ret
= scan_troff(c
, san
, result
);
3985 mandoc_line
= oldval
;
3990 main(int argc
, char **argv
)
4000 while ((i
= getopt(argc
, argv
, "")) != EOF
) {
4012 manpage
= h
= t
= argv
[1];
4015 buf
= read_man_page(h
);
4017 fprintf(stderr
, "man2html: cannot read %s: %s\n", h
, strerror(errno
));
4021 idxfile
= fopen(INDEXFILE
, "a");
4023 stdf
= &standardchar
[0];
4026 stdf
->next
= &standardchar
[i
];
4030 chardef
= &standardchar
[0];
4032 stdf
= &standardstring
[0];
4035 stdf
->next
= &standardstring
[i
];
4039 strdef
= &standardstring
[0];
4041 intdef
= &standardint
[0];
4043 while (intdef
->nr
) {
4044 intdef
->next
= &standardint
[i
];
4045 intdef
= intdef
->next
;
4048 intdef
= &standardint
[0];
4052 scan_troff(buf
+ 1, 0, NULL
);
4054 while (itemdepth
|| dl_set
[itemdepth
]) {
4055 out_html("</DL>\n");
4056 if (dl_set
[itemdepth
])
4057 dl_set
[itemdepth
] = 0;
4058 else if (itemdepth
> 0)
4062 out_html(change_to_font(0));
4063 out_html(change_to_size(0));
4070 if (output_possible
) {
4071 outputPageFooter(th_version
, th_datestr
, th_page_and_sec
);
4072 /* for mosaic users */
4073 fputs("<HR>\n<A NAME=\"index\"> </A><H2>Index</H2>\n<DL>\n", stdout
);
4075 fputs(manidx
, stdout
);
4077 fputs("</DL>\n", stdout
);
4078 fputs("</DL>\n", stdout
);
4080 fputs("</BODY>\n</HTML>\n", stdout
);
4082 fprintf(stderr
, "man2html: no output produced\n");