2 * "$Id: mantohtml.c 9226 2010-08-06 12:15:50Z mike $"
4 * Man page to HTML conversion program.
6 * Copyright 2007-2010 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-private.h>
34 static void putc_entity(int ch, FILE *fp);
35 static void strmove(char *d, const char *s);
39 * 'main()' - Convert a man page to HTML.
42 int /* O - Exit status */
43 main(int argc, /* I - Number of command-line args */
44 char *argv[]) /* I - Command-line arguments */
46 FILE *infile, /* Input file */
47 *outfile; /* Output file */
48 char line[1024], /* Line from file */
49 *lineptr, /* Pointer into line */
50 *endptr, /* Pointer to end of current */
51 endchar, /* End character */
52 *paren, /* Pointer to parenthesis */
53 name[1024]; /* Man page name */
54 int section, /* Man page section */
55 pre, /* Preformatted */
56 font, /* Current font */
57 blist, /* In a bullet list? */
58 list, /* In a list? */
59 linenum; /* Current line number */
60 const char *post; /* Text to add after the current line */
61 static const char /* Start/end tags for fonts */
62 * const start_fonts[] = { "", "<b>", "<i>" },
63 * const end_fonts[] = { "", "</b>", "</i>" };
71 fputs("Usage: mantohtml [filename.man [filename.html]]\n", stderr);
76 * Open files as needed...
81 if ((infile = fopen(argv[1], "r")) == NULL)
92 if ((outfile = fopen(argv[2], "w")) == NULL)
103 * Read from input and write the output...
106 fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" "
107 "\"http://www.w3.org/TR/html4/loose.dtd\">\n"
109 "<!-- SECTION: Man Pages -->\n"
111 "\t<link rel=\"stylesheet\" type=\"text/css\" "
112 "href=\"../cups-printable.css\">\n", outfile);
122 while (fgets(line, sizeof(line), infile))
129 * Strip leading whitespace...
132 while (line[1] == ' ' || line[1] == '\t')
133 strmove(line + 1, line + 2);
136 * Process man page commands...
139 if (!strncmp(line, ".TH ", 4) && section < 0)
142 * Grab man page title...
145 sscanf(line + 4, "%s%d", name, §ion);
148 "\t<title>%s(%d)</title>\n"
151 "<h1 class=\"title\">%s(%d)</h1>\n"
153 name, section, name, section, start_fonts[font]);
155 else if (section < 0)
157 else if (!strncmp(line, ".SH ", 4) || !strncmp(line, ".SS ", 4))
165 fputs(end_fonts[font], outfile);
169 fputs("</li>\n</ul>\n", outfile);
176 fputs("</dt>\n", outfile);
178 fputs("</dd>\n", outfile);
180 fputs("</dl>\n", outfile);
184 line[strlen(line) - 1] = '\0'; /* Strip LF */
187 fputs("<h2 class=\"title\"><a name=\"", outfile);
189 fputs("<h3><a name=\"", outfile);
191 for (lineptr = line + 4; *lineptr; lineptr ++)
192 if (*lineptr == '\"')
194 else if (*lineptr == ' ')
195 putc_entity('_', outfile);
197 putc_entity(*lineptr, outfile);
199 fputs("\">", outfile);
201 for (lineptr = line + 4; *lineptr; lineptr ++)
202 if (*lineptr == '\"')
204 else if (*lineptr == ' ')
206 putc_entity(' ', outfile);
213 putc_entity(*lineptr, outfile);
215 putc_entity(tolower(*lineptr), outfile);
221 fprintf(outfile, "</a></h2>\n%s", start_fonts[font]);
223 fprintf(outfile, "</a></h3>\n%s", start_fonts[font]);
225 else if (!strncmp(line, ".LP", 3) || !strncmp(line, ".PP", 3))
231 fputs(end_fonts[font], outfile);
235 fputs("</li>\n</ul>\n", outfile);
242 fputs("</dt>\n", outfile);
244 fputs("</dd>\n", outfile);
246 fputs("</dl>\n", outfile);
250 fputs("<p>", outfile);
253 else if (!strncmp(line, ".TP ", 4))
259 fputs(end_fonts[font], outfile);
263 fputs("</li>\n</ul>\n", outfile);
268 fputs("<dl>\n", outfile);
270 fputs("</dt>\n", outfile);
272 fputs("</dd>\n", outfile);
274 fputs("<dt>", outfile);
278 else if (!strncmp(line, ".br", 3))
286 fputs("</dt>\n<dd>", outfile);
290 fputs("</dd>\n<dd>", outfile);
292 fputs("<br>\n", outfile);
294 else if (!strncmp(line, ".de ", 4))
297 * Define macro - ignore...
300 while (fgets(line, sizeof(line), infile))
304 if (!strncmp(line, "..", 2))
308 else if (!strncmp(line, ".RS", 3))
314 fputs("<div style='margin-left: 3em;'>\n", outfile);
316 else if (!strncmp(line, ".RE", 3))
322 fputs("</div>\n", outfile);
324 else if (!strncmp(line, ".ds ", 4) || !strncmp(line, ".rm ", 4) ||
325 !strncmp(line, ".tr ", 4) || !strncmp(line, ".hy ", 4) ||
326 !strncmp(line, ".IX ", 4) || !strncmp(line, ".PD", 3) ||
327 !strncmp(line, ".Sp", 3))
330 * Ignore unused commands...
333 else if (!strncmp(line, ".Vb", 3) || !strncmp(line, ".nf", 3))
336 * Start preformatted...
340 fputs("<pre>\n", outfile);
342 else if (!strncmp(line, ".Ve", 3) || !strncmp(line, ".fi", 3))
345 * End preformatted...
351 fputs("</pre>\n", outfile);
354 else if (!strncmp(line, ".IP \\(bu", 8))
361 fputs("</li>\n", outfile);
364 fputs("<ul>\n", outfile);
368 fputs("<li>", outfile);
370 else if (!strncmp(line, ".IP ", 4))
373 * Indented paragraph...
378 fputs("</li>\n</ul>\n", outfile);
382 fputs("<p style='margin-left: 3em;'>", outfile);
384 for (lineptr = line + 4; isspace(*lineptr); lineptr ++);
386 if (*lineptr == '\"')
388 strmove(line, lineptr + 1);
390 if ((lineptr = strchr(line, '\"')) != NULL)
395 strmove(line, lineptr);
397 if ((lineptr = strchr(line, ' ')) != NULL)
402 * Process the text as if it was in-line...
405 post = "\n<br>\n<br>";
408 else if (!strncmp(line, ".\\}", 3))
411 * Ignore close block...
414 else if (!strncmp(line, ".ie", 3) || !strncmp(line, ".if", 3) ||
415 !strncmp(line, ".el", 3))
418 * If/else - ignore...
421 if (strchr(line, '{') != NULL)
424 * Skip whole block...
427 while (fgets(line, sizeof(line), infile))
431 if (strchr(line, '}') != NULL)
437 else if (!strncmp(line, ". ", 4))
444 else if (!strncmp(line, ".B ", 3))
450 fprintf(outfile, "%s<b>%s</b>%s", end_fonts[font], line + 3,
453 else if (!strncmp(line, ".I ", 3))
456 * Grab italic text...
459 fprintf(outfile, "%s<i>%s</i>%s", end_fonts[font], line + 3,
462 else if (strncmp(line, ".\\\"", 3))
468 if ((lineptr = strchr(line, ' ')) != NULL)
470 else if ((lineptr = strchr(line, '\n')) != NULL)
473 fprintf(stderr, "mantohtml: Unknown man page command \'%s\' on line %d!\n",
478 * Skip continuation lines...
481 lineptr = line + strlen(line) - 2;
482 if (lineptr >= line && *lineptr == '\\')
484 while (fgets(line, sizeof(line), infile))
487 lineptr = line + strlen(line) - 2;
489 if (lineptr < line || *lineptr != '\\')
497 * Process man page text...
502 for (lineptr = line; *lineptr; lineptr ++)
504 if (!strncmp(lineptr, "http://", 7))
510 for (endptr = lineptr + 7;
511 *endptr && !isspace(*endptr & 255);
517 fprintf(outfile, "<a href='%s'>%s</a>", lineptr, lineptr);
519 lineptr = endptr - 1;
521 else if (!strncmp(lineptr, "\\fI", 3) &&
522 (endptr = strstr(lineptr, "\\fR")) != NULL &&
523 (paren = strchr(lineptr, '(')) != NULL &&
530 char manfile[1024], /* Man page filename */
531 manurl[1024]; /* Man page URL */
535 * See if the man file is available locally...
542 snprintf(manfile, sizeof(manfile), "%s.man", lineptr);
543 snprintf(manurl, sizeof(manurl), "man-%s.html?TOPIC=Man+Pages",
550 if (access(manfile, 0))
553 * Not a local man page, just do it italic...
556 fputs("<i>", outfile);
558 putc_entity(*lineptr++, outfile);
559 fputs("</i>", outfile);
564 * Local man page, do a link...
567 fprintf(outfile, "<a href='%s'>", manurl);
569 putc_entity(*lineptr++, outfile);
570 fputs("</a>", outfile);
574 lineptr = endptr + 2;
576 else if (*lineptr == '\\')
581 else if (isdigit(lineptr[0]) && isdigit(lineptr[1]) &&
584 fprintf(outfile, "&#%d;", ((lineptr[0] - '0') * 8 +
585 lineptr[1] - '0') * 8 +
589 else if (*lineptr == '&')
591 else if (*lineptr == 's')
593 while (lineptr[1] == '-' || isdigit(lineptr[1]))
596 else if (*lineptr == '*')
600 else if (*lineptr != 'f')
601 putc_entity(*lineptr, outfile);
609 fputs(end_fonts[font], outfile);
613 default : /* Regular */
616 case 'B' : /* Bold */
620 case 'I' : /* Italic */
626 fputs(start_fonts[font], outfile);
631 putc_entity(*lineptr, outfile);
636 fputs(post, outfile);
642 fputs("</dt>\n<dd>", outfile);
648 fprintf(outfile, "%s\n", end_fonts[font]);
652 fputs("</li>\n</ul>\n", outfile);
658 fputs("</dt>\n", outfile);
660 fputs("</dd>\n", outfile);
662 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 9226 2010-08-06 12:15:50Z mike $".