]> git.ipfire.org Git - thirdparty/cups.git/blame - standards/rfctohtml.c
Merge changes from CUPS 1.4svn-r8628.
[thirdparty/cups.git] / standards / rfctohtml.c
CommitLineData
fa73b229 1/*
bc44d920 2 * "$Id: rfctohtml.c 6649 2007-07-11 21:46:42Z mike $"
fa73b229 3 *
4 * RFC file to HTML conversion program.
5 *
745129be 6 * Copyright 2007-2009 by Apple Inc.
fa73b229 7 * Copyright 2006 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 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/".
fa73b229 14 *
15 * Contents:
16 *
ecdc0628 17 * main() - Convert a man page to HTML.
18 * put_entity() - Put a single character, using entities as needed.
19 * put_line() - Put a whole string for a line.
fa73b229 20 */
21
22/*
23 * Include necessary headers.
24 */
25
26#include <cups/string.h>
27#include <stdlib.h>
28#include <cups/file.h>
29
30
31/*
32 * Local functions...
33 */
34
35void put_entity(cups_file_t *fp, int ch);
36void put_line(cups_file_t *fp, const char *line);
37
38
39/*
40 * 'main()' - Convert a man page to HTML.
41 */
42
43int /* O - Exit status */
44main(int argc, /* I - Number of command-line args */
45 char *argv[]) /* I - Command-line arguments */
46{
47 cups_file_t *infile, /* Input file */
48 *outfile; /* Output file */
49 char line[1024], /* Line from file */
50 *lineptr, /* Pointer into line */
178cb736
MS
51 title[2048], /* Title string */
52 *titleptr, /* Pointer into title */
fa73b229 53 name[1024], /* Heading anchor name */
54 *nameptr; /* Pointer into anchor name */
ecdc0628 55 int rfc, /* RFC # */
56 inheading, /* Inside a heading? */
fa73b229 57 inpre, /* Inside preformatted text? */
58 intoc, /* Inside table-of-contents? */
59 toclevel, /* Current table-of-contents level */
60 linenum; /* Current line on page */
61
62
63 /*
64 * Check arguments...
65 */
66
67 if (argc > 3)
68 {
69 fputs("Usage: rfctohtml [rfcNNNN.txt [rfcNNNN.html]]\n", stderr);
70 return (1);
71 }
72
73 /*
74 * Open files as needed...
75 */
76
77 if (argc > 1)
78 {
79 if ((infile = cupsFileOpen(argv[1], "r")) == NULL)
80 {
81 perror(argv[1]);
82 return (1);
83 }
84 }
85 else
86 infile = cupsFileOpenFd(0, "r");
87
88 if (argc > 2)
89 {
90 if ((outfile = cupsFileOpen(argv[2], "w")) == NULL)
91 {
92 perror(argv[2]);
93 cupsFileClose(infile);
94 return (1);
95 }
96 }
97 else
98 outfile = cupsFileOpenFd(1, "w");
99
100 /*
101 * Read from input and write the output...
102 */
103
104 cupsFilePuts(outfile,
745129be
MS
105 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" "
106 "\"http://www.w3.org/TR/html4/loose.dtd\">\n"
fa73b229 107 "<html>\n"
108 "<!-- SECTION: Specifications -->\n"
109 "<head>\n"
178cb736
MS
110 "\t<link rel=\"stylesheet\" type=\"text/css\" "
111 "href=\"../cups-printable.css\">\n");
fa73b229 112
113 /*
114 * Skip the initial header stuff (working group ID, RFC #, authors, and
115 * copyright...
116 */
117
118 linenum = 0;
ecdc0628 119 rfc = 0;
fa73b229 120
121 while (cupsFileGets(infile, line, sizeof(line)))
122 {
123 linenum ++;
124
125 if (line[0])
126 break;
127 }
128
129 while (cupsFileGets(infile, line, sizeof(line)))
130 {
131 linenum ++;
132
133 if (!line[0])
134 break;
ecdc0628 135 else if (!strncasecmp(line, "Request for Comments:", 21))
136 rfc = atoi(line + 21);
fa73b229 137 }
138
139 /*
140 * Read the document title...
141 */
142
143 while (cupsFileGets(infile, line, sizeof(line)))
144 {
145 linenum ++;
146
147 if (line[0])
148 break;
149 }
150
151 for (lineptr = line; isspace(*lineptr & 255); lineptr ++);
152
178cb736
MS
153 snprintf(title, sizeof(title), "RFC %d: %s", rfc, lineptr);
154 titleptr = title + strlen(title);
fa73b229 155
156 while (cupsFileGets(infile, line, sizeof(line)))
157 {
158 linenum ++;
159
160 if (!line[0])
161 break;
162 else
163 {
164 for (lineptr = line; isspace(*lineptr & 255); lineptr ++);
178cb736
MS
165
166 snprintf(titleptr, sizeof(title) - (titleptr - title), " %s", lineptr);
167 titleptr += strlen(titleptr);
fa73b229 168 }
169 }
170
178cb736
MS
171 cupsFilePrintf(outfile, "\t<title>%s</title>\n"
172 "</head>\n"
173 "<body>\n"
174 "<h1 class='title'>%s</h1>\n", title, title);
fa73b229 175
176 /*
177 * Read the rest of the file...
178 */
179
180 inheading = 0;
181 inpre = 0;
182 intoc = 0;
183 toclevel = 0;
184
185 while (cupsFileGets(infile, line, sizeof(line)))
186 {
187 linenum ++;
188
189 if (!line[0])
190 {
191 if (linenum > 50)
192 continue;
193
194 if (inpre)
195 {
196 cupsFilePuts(outfile, "</pre>\n");
197 inpre = 0;
198 }
199
200 if (inheading)
201 {
202 if (inheading < 0)
178cb736 203 cupsFilePuts(outfile, "</h2>\n");
fa73b229 204 else
205 cupsFilePrintf(outfile, "</a></h%d>\n", inheading);
206
207 inheading = 0;
208 }
209 }
210 else if ((line[0] == ' ' ||
211 (!isupper(line[0] & 255) && !isdigit(line[0] & 255) &&
212 !strstr(line, "[Page "))) && !inheading)
213 {
214 if (inheading)
215 {
216 if (inheading < 0)
178cb736 217 cupsFilePuts(outfile, "</h2>\n");
fa73b229 218 else
219 cupsFilePrintf(outfile, "</a></h%d>\n", inheading);
220
221 inheading = 0;
222 }
223
224 for (lineptr = line; *lineptr == ' '; lineptr ++);
225
226 if (intoc)
227 {
228 char *temp; /* Temporary pointer into line */
229 int level; /* Heading level */
230
231
232 if (isdigit(*lineptr & 255))
233 {
234 strlcpy(name, lineptr, sizeof(name));
235
236 for (nameptr = name, level = -1; *nameptr;)
237 if (isdigit(*nameptr & 255))
238 {
239 while (isdigit(*nameptr & 255))
240 nameptr ++;
241
242 level ++;
243 }
244 else if (*nameptr == ' ')
245 {
246 *nameptr = '\0';
247 break;
248 }
249 else
250 nameptr ++;
251
252 while (toclevel > level)
253 {
254 cupsFilePuts(outfile, "\n</ul>");
255 toclevel --;
256 }
257
258 while (toclevel < level)
259 {
260 cupsFilePuts(outfile, "\n<ul style=\"list-style-type: none;\">\n");
261 toclevel ++;
262 }
263
264 cupsFilePrintf(outfile, "\n<%s><a href=\"#s%s\">", toclevel ? "li" : "p",
265 name);
266 }
267
268 temp = lineptr + strlen(lineptr) - 1;
269
270 while (temp > lineptr)
271 if (*temp == ' ' || !isdigit(*temp & 255))
272 break;
273 else
274 temp --;
275
276 if (*temp == ' ')
277 {
278 while (temp > lineptr)
279 if (*temp != ' ' && *temp != '.')
280 break;
281 else
282 *temp-- = '\0';
283 }
284 else
285 temp = NULL;
286
287 if (isdigit(*lineptr & 255))
288 put_line(outfile, lineptr);
289 else
290 put_line(outfile, lineptr - 1);
291
292 if (temp)
293 cupsFilePuts(outfile, "</a>");
294 }
295 else if (!inpre)
296 {
297 cupsFilePuts(outfile, "\n<pre>");
298 put_line(outfile, line);
299 inpre = 1;
300 }
301 else
302 {
303 cupsFilePutChar(outfile, '\n');
304 put_line(outfile, line);
305 }
306 }
307 else if (strstr(line, "[Page "))
308 {
309 /*
310 * Skip page footer and header...
311 */
312
313 cupsFileGets(infile, line, sizeof(line));
314 cupsFileGets(infile, line, sizeof(line));
315 cupsFileGets(infile, line, sizeof(line));
316 cupsFileGets(infile, line, sizeof(line));
317 linenum = 3;
318 }
319 else if (isdigit(line[0] & 255) && !inheading)
320 {
321 int level; /* Heading level */
322
323
324 if (intoc)
325 {
326 while (toclevel > 0)
327 {
328 cupsFilePuts(outfile, "\n</ul>");
329 toclevel --;
330 }
331
332 cupsFilePutChar(outfile, '\n');
333 intoc = 0;
334 }
335
336 if (inpre)
337 {
338 cupsFilePuts(outfile, "</pre>\n");
339 inpre = 0;
340 }
341
342 strlcpy(name, line, sizeof(name));
ecdc0628 343 for (nameptr = name, level = 1; *nameptr;)
fa73b229 344 if (isdigit(*nameptr & 255))
345 {
346 while (isdigit(*nameptr & 255))
347 nameptr ++;
348
349 level ++;
350 }
351 else if (*nameptr == ' ')
352 {
353 *nameptr = '\0';
354 break;
355 }
356 else
357 nameptr ++;
358
ecdc0628 359 cupsFilePrintf(outfile, "\n<h%d class='title'><a name='s%s'>", level,
360 name);
fa73b229 361 put_line(outfile, line);
362
363 intoc = 0;
364 inheading = level;
365 }
366 else
367 {
368 if (intoc)
369 {
370 while (toclevel > 0)
371 {
372 cupsFilePuts(outfile, "\n</ul>");
373 toclevel --;
374 }
375
376 cupsFilePutChar(outfile, '\n');
377 intoc = 0;
378 }
379
380 if (!inheading)
381 {
ecdc0628 382 cupsFilePuts(outfile, "\n<h2 class='title'>");
fa73b229 383 inheading = -1;
384 }
385
386 put_line(outfile, line);
387
388 intoc = !strcasecmp(line, "Table of Contents");
389 toclevel = 0;
390 }
391 }
392
393 if (inpre)
394 cupsFilePuts(outfile, "</pre>\n");
395
396 if (inheading)
397 {
398 if (inheading < 0)
ecdc0628 399 cupsFilePuts(outfile, "</h2>\n");
fa73b229 400 else
401 cupsFilePrintf(outfile, "</a></h%d>\n", inheading);
402 }
403
404 cupsFilePuts(outfile, "</body>\n"
405 "</html>\n");
406
407 /*
408 * Close files...
409 */
410
411 cupsFileClose(infile);
412 cupsFileClose(outfile);
413
414 /*
415 * Return with no errors...
416 */
417
418 return (0);
419}
420
421
422/*
423 * 'put_entity()' - Put a single character, using entities as needed.
424 */
425
426void
427put_entity(cups_file_t *fp, /* I - File */
428 int ch) /* I - Character */
429{
430 if (ch == '&')
431 cupsFilePuts(fp, "&amp;");
432 else if (ch == '<')
433 cupsFilePuts(fp, "&lt;");
434 else
435 cupsFilePutChar(fp, ch);
436}
437
438
439/*
440 * 'put_line()' - Put a whole string for a line.
441 */
442
443void
444put_line(cups_file_t *fp, /* I - File */
445 const char *s) /* I - String */
446{
447 int whitespace, /* Saw whitespace */
448 i, /* Looping var */
449 len; /* Length of keyword */
450 static const char * const keywords[] =/* Special keywords to boldface */
451 {
452 "MAY",
453 "MUST",
178cb736 454 "NEED",
fa73b229 455 "NOT",
178cb736
MS
456 "OPTIONAL",
457 "OPTIONALLY",
458 "RECOMMENDED",
459 "REQUIRED",
fa73b229 460 "SHALL",
461 "SHOULD"
462 };
463
464
465 whitespace = 1;
466
467 while (*s)
468 {
469 if (*s == ' ')
470 whitespace = 1;
471
472 if (whitespace && isupper(*s & 255))
473 {
474 whitespace = 0;
475
476 for (i = 0; i < (int)(sizeof(keywords) / sizeof(sizeof(keywords[0]))); i ++)
477 {
478 len = strlen(keywords[i]);
178cb736
MS
479 if (!strncmp(s, keywords[i], len) &&
480 (isspace(s[len] & 255) || ispunct(s[len] & 255) || !*s))
fa73b229 481 {
482 cupsFilePrintf(fp, "<b>%s</b>", keywords[i]);
483 s += len;
484 break;
485 }
486 }
487
488 if (i >= (int)(sizeof(keywords) / sizeof(sizeof(keywords[0]))))
489 put_entity(fp, *s++);
490 }
491 else
492 {
493 if (*s != ' ')
494 whitespace = 0;
495
496 put_entity(fp, *s++);
497 }
498 }
499}
500
501
502/*
bc44d920 503 * End of "$Id: rfctohtml.c 6649 2007-07-11 21:46:42Z mike $".
fa73b229 504 */