]>
git.ipfire.org Git - thirdparty/cups.git/blob - man/mantohtml.c
2 * "$Id: mantohtml.c 7662 2008-06-17 14:34:20Z mike $"
4 * Man page to HTML conversion program.
6 * Copyright 2007 by Apple Inc.
7 * Copyright 2004-2006 by Easy Software Products.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
17 * main() - Convert a man page to HTML.
18 * putc_entity() - Put a single character, using entities as needed.
19 * strmove() - Move characters within a string.
23 * Include necessary headers.
26 #include <cups/string.h>
35 static void putc_entity(int ch
, FILE *fp
);
36 static void strmove(char *d
, const char *s
);
40 * 'main()' - Convert a man page to HTML.
43 int /* O - Exit status */
44 main(int argc
, /* I - Number of command-line args */
45 char *argv
[]) /* I - Command-line arguments */
47 FILE *infile
, /* Input file */
48 *outfile
; /* Output file */
49 char line
[1024], /* Line from file */
50 *lineptr
, /* Pointer into line */
51 *endptr
, /* Pointer to end of current */
52 endchar
, /* End character */
53 *paren
, /* Pointer to parenthesis */
54 name
[1024]; /* Man page name */
55 int section
, /* Man page section */
56 pre
, /* Preformatted */
57 font
, /* Current font */
58 blist
, /* In a bullet list? */
59 list
, /* In a list? */
60 linenum
; /* Current line number */
61 const char *post
; /* Text to add after the current line */
62 static const char /* Start/end tags for fonts */
63 * const start_fonts
[] = { "", "<b>", "<i>" },
64 * const end_fonts
[] = { "", "</b>", "</i>" };
72 fputs("Usage: mantohtml [filename.man [filename.html]]\n", stderr
);
77 * Open files as needed...
82 if ((infile
= fopen(argv
[1], "r")) == NULL
)
93 if ((outfile
= fopen(argv
[2], "w")) == NULL
)
104 * Read from input and write the output...
107 fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" "
108 "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n"
110 "<!-- SECTION: Man Pages -->\n"
112 "\t<style type='text/css'><!--\n"
113 "\th1, h2, h3, p { font-family: sans-serif; text-align: justify; }\n"
114 "\ttt, pre a:link, pre a:visited, tt a:link, tt a:visited { font-weight: bold; color: #7f0000; }\n"
115 "\tpre { font-weight: bold; color: #7f0000; margin-left: 2em; }\n"
116 "\th1.title, h2.title, h3.title { border-bottom: solid 2px #000000; }\n"
117 "\t--></style>\n", outfile
);
127 while (fgets(line
, sizeof(line
), infile
))
134 * Strip leading whitespace...
137 while (line
[1] == ' ' || line
[1] == '\t')
138 strmove(line
+ 1, line
+ 2);
141 * Process man page commands...
144 if (!strncmp(line
, ".TH ", 4) && section
< 0)
147 * Grab man page title...
150 sscanf(line
+ 4, "%s%d", name
, §ion
);
153 "\t<title>%s(%d)</title>\n"
157 name
, section
, start_fonts
[font
]);
159 else if (section
< 0)
161 else if (!strncmp(line
, ".SH ", 4) || !strncmp(line
, ".SS ", 4))
169 fputs(end_fonts
[font
], outfile
);
173 fputs("</li>\n</ul>\n", outfile
);
180 fputs("</dt>\n", outfile
);
182 fputs("</dd>\n", outfile
);
184 fputs("</dl>\n", outfile
);
188 line
[strlen(line
) - 1] = '\0'; /* Strip LF */
191 fputs("<h2><a name='", outfile
);
193 fputs("<h3><a name='", outfile
);
195 for (lineptr
= line
+ 4; *lineptr
; lineptr
++)
196 if (*lineptr
== '\"')
198 else if (*lineptr
== ' ')
199 putc_entity('_', outfile
);
201 putc_entity(*lineptr
, outfile
);
203 fputs("'>", outfile
);
205 for (lineptr
= line
+ 4; *lineptr
; lineptr
++)
206 if (*lineptr
== '\"')
208 else if (*lineptr
== ' ')
210 putc_entity(' ', outfile
);
217 putc_entity(*lineptr
, outfile
);
219 putc_entity(tolower(*lineptr
), outfile
);
225 fprintf(outfile
, "</a></h2>\n%s", start_fonts
[font
]);
227 fprintf(outfile
, "</a></h3>\n%s", start_fonts
[font
]);
229 else if (!strncmp(line
, ".LP", 3) || !strncmp(line
, ".PP", 3))
235 fputs(end_fonts
[font
], outfile
);
239 fputs("</li>\n</ul>\n", outfile
);
246 fputs("</dt>\n", outfile
);
248 fputs("</dd>\n", outfile
);
250 fputs("</dl>\n", outfile
);
254 fputs("<p>", outfile
);
257 else if (!strncmp(line
, ".TP ", 4))
263 fputs(end_fonts
[font
], outfile
);
267 fputs("</li>\n</ul>\n", outfile
);
272 fputs("<dl>\n", outfile
);
274 fputs("</dt>\n", outfile
);
276 fputs("</dd>\n", outfile
);
278 fputs("<dt>", outfile
);
282 else if (!strncmp(line
, ".br", 3))
290 fputs("</dt>\n<dd>", outfile
);
294 fputs("</dd>\n<dd>", outfile
);
296 fputs("<br>\n", outfile
);
298 else if (!strncmp(line
, ".de ", 4))
301 * Define macro - ignore...
304 while (fgets(line
, sizeof(line
), infile
))
308 if (!strncmp(line
, "..", 2))
312 else if (!strncmp(line
, ".RS", 3))
318 fputs("<div style='margin-left: 3em;'>\n", outfile
);
320 else if (!strncmp(line
, ".RE", 3))
326 fputs("</div>\n", outfile
);
328 else if (!strncmp(line
, ".ds ", 4) || !strncmp(line
, ".rm ", 4) ||
329 !strncmp(line
, ".tr ", 4) || !strncmp(line
, ".hy ", 4) ||
330 !strncmp(line
, ".IX ", 4) || !strncmp(line
, ".PD", 3) ||
331 !strncmp(line
, ".Sp", 3))
334 * Ignore unused commands...
337 else if (!strncmp(line
, ".Vb", 3) || !strncmp(line
, ".nf", 3))
340 * Start preformatted...
344 fputs("<pre>\n", outfile
);
346 else if (!strncmp(line
, ".Ve", 3) || !strncmp(line
, ".fi", 3))
349 * End preformatted...
355 fputs("</pre>\n", outfile
);
358 else if (!strncmp(line
, ".IP \\(bu", 8))
365 fputs("</li>\n", outfile
);
368 fputs("<ul>\n", outfile
);
372 fputs("<li>", outfile
);
374 else if (!strncmp(line
, ".IP ", 4))
377 * Indented paragraph...
382 fputs("</li>\n</ul>\n", outfile
);
386 fputs("<p style='margin-left: 3em;'>", outfile
);
388 for (lineptr
= line
+ 4; isspace(*lineptr
); lineptr
++);
390 if (*lineptr
== '\"')
392 strmove(line
, lineptr
+ 1);
394 if ((lineptr
= strchr(line
, '\"')) != NULL
)
399 strmove(line
, lineptr
);
401 if ((lineptr
= strchr(line
, ' ')) != NULL
)
406 * Process the text as if it was in-line...
409 post
= "\n<br />\n<br />";
412 else if (!strncmp(line
, ".\\}", 3))
415 * Ignore close block...
418 else if (!strncmp(line
, ".ie", 3) || !strncmp(line
, ".if", 3) ||
419 !strncmp(line
, ".el", 3))
422 * If/else - ignore...
425 if (strchr(line
, '{') != NULL
)
428 * Skip whole block...
431 while (fgets(line
, sizeof(line
), infile
))
435 if (strchr(line
, '}') != NULL
)
441 else if (!strncmp(line
, ". ", 4))
448 else if (!strncmp(line
, ".B ", 3))
454 fprintf(outfile
, "%s<b>%s</b>%s", end_fonts
[font
], line
+ 3,
457 else if (!strncmp(line
, ".I ", 3))
460 * Grab italic text...
463 fprintf(outfile
, "%s<i>%s</i>%s", end_fonts
[font
], line
+ 3,
466 else if (strncmp(line
, ".\\\"", 3))
472 if ((lineptr
= strchr(line
, ' ')) != NULL
)
474 else if ((lineptr
= strchr(line
, '\n')) != NULL
)
477 fprintf(stderr
, "mantohtml: Unknown man page command \'%s\' on line %d!\n",
482 * Skip continuation lines...
485 lineptr
= line
+ strlen(line
) - 2;
486 if (lineptr
>= line
&& *lineptr
== '\\')
488 while (fgets(line
, sizeof(line
), infile
))
491 lineptr
= line
+ strlen(line
) - 2;
493 if (lineptr
< line
|| *lineptr
!= '\\')
501 * Process man page text...
506 for (lineptr
= line
; *lineptr
; lineptr
++)
508 if (!strncmp(lineptr
, "http://", 7))
514 for (endptr
= lineptr
+ 7;
515 *endptr
&& !isspace(*endptr
& 255);
521 fprintf(outfile
, "<a href='%s'>%s</a>", lineptr
, lineptr
);
523 lineptr
= endptr
- 1;
525 else if (!strncmp(lineptr
, "\\fI", 3) &&
526 (endptr
= strstr(lineptr
, "\\fR")) != NULL
&&
527 (paren
= strchr(lineptr
, '(')) != NULL
&&
534 char manfile
[1024], /* Man page filename */
535 manurl
[1024]; /* Man page URL */
539 * See if the man file is available locally...
546 snprintf(manfile
, sizeof(manfile
), "%s.man", lineptr
);
547 snprintf(manurl
, sizeof(manurl
), "man-%s.html?TOPIC=Man+Pages",
554 if (access(manfile
, 0))
557 * Not a local man page, just do it italic...
560 fputs("<i>", outfile
);
562 putc_entity(*lineptr
++, outfile
);
563 fputs("</i>", outfile
);
568 * Local man page, do a link...
571 fprintf(outfile
, "<a href='%s'>", manurl
);
573 putc_entity(*lineptr
++, outfile
);
574 fputs("</a>", outfile
);
578 lineptr
= endptr
+ 2;
580 else if (*lineptr
== '\\')
585 else if (isdigit(lineptr
[0]) && isdigit(lineptr
[1]) &&
588 fprintf(outfile
, "&#%d;", ((lineptr
[0] - '0') * 8 +
589 lineptr
[1] - '0') * 8 +
593 else if (*lineptr
== '&')
595 else if (*lineptr
== 's')
597 while (lineptr
[1] == '-' || isdigit(lineptr
[1]))
600 else if (*lineptr
== '*')
604 else if (*lineptr
!= 'f')
605 putc_entity(*lineptr
, outfile
);
613 fputs(end_fonts
[font
], outfile
);
617 default : /* Regular */
620 case 'B' : /* Bold */
624 case 'I' : /* Italic */
630 fputs(start_fonts
[font
], outfile
);
635 putc_entity(*lineptr
, outfile
);
640 fputs(post
, outfile
);
646 fprintf(outfile
, "%s\n", end_fonts
[font
]);
650 fputs("</li>\n</ul>\n", outfile
);
657 fputs("</dt>\n", outfile
);
659 fputs("</dd>\n", outfile
);
661 fputs("</dl>\n", outfile
);
666 "</html>\n", outfile
);
675 if (outfile
!= stdout
)
679 * Return with no errors...
687 * 'putc_entity()' - Put a single character, using entities as needed.
691 putc_entity(int ch
, /* I - Character */
692 FILE *fp
) /* I - File */
704 * 'strmove()' - Move characters within a string.
708 strmove(char *d
, /* I - Destination */
709 const char *s
) /* I - Source */
719 * End of "$Id: mantohtml.c 7662 2008-06-17 14:34:20Z mike $".