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