]>
git.ipfire.org Git - thirdparty/cups.git/blob - man/mantohtml.c
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 */