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