]> git.ipfire.org Git - thirdparty/cups.git/blame - standards/rfctohtml.c
Load cups into easysw/current.
[thirdparty/cups.git] / standards / rfctohtml.c
CommitLineData
fa73b229 1/*
2 * "$Id: rfctohtml.c 4966 2006-01-23 00:41:22Z 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 */
27
28/*
29 * Include necessary headers.
30 */
31
32#include <cups/string.h>
33#include <stdlib.h>
34#include <cups/file.h>
35
36
37/*
38 * Local functions...
39 */
40
41void put_entity(cups_file_t *fp, int ch);
42void put_line(cups_file_t *fp, const char *line);
43
44
45/*
46 * 'main()' - Convert a man page to HTML.
47 */
48
49int /* O - Exit status */
50main(int argc, /* I - Number of command-line args */
51 char *argv[]) /* I - Command-line arguments */
52{
53 cups_file_t *infile, /* Input file */
54 *outfile; /* Output file */
55 char line[1024], /* Line from file */
56 *lineptr, /* Pointer into line */
57 name[1024], /* Heading anchor name */
58 *nameptr; /* Pointer into anchor name */
59 int inheading, /* Inside a heading? */
60 inpre, /* Inside preformatted text? */
61 intoc, /* Inside table-of-contents? */
62 toclevel, /* Current table-of-contents level */
63 linenum; /* Current line on page */
64
65
66 /*
67 * Check arguments...
68 */
69
70 if (argc > 3)
71 {
72 fputs("Usage: rfctohtml [rfcNNNN.txt [rfcNNNN.html]]\n", stderr);
73 return (1);
74 }
75
76 /*
77 * Open files as needed...
78 */
79
80 if (argc > 1)
81 {
82 if ((infile = cupsFileOpen(argv[1], "r")) == NULL)
83 {
84 perror(argv[1]);
85 return (1);
86 }
87 }
88 else
89 infile = cupsFileOpenFd(0, "r");
90
91 if (argc > 2)
92 {
93 if ((outfile = cupsFileOpen(argv[2], "w")) == NULL)
94 {
95 perror(argv[2]);
96 cupsFileClose(infile);
97 return (1);
98 }
99 }
100 else
101 outfile = cupsFileOpenFd(1, "w");
102
103 /*
104 * Read from input and write the output...
105 */
106
107 cupsFilePuts(outfile,
108 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" "
109 "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n"
110 "<html>\n"
111 "<!-- SECTION: Specifications -->\n"
112 "<head>\n"
113 "\t<style type='text/css'><!--\n"
114 "\th1, h2, h3 { font-family: sans-serif; }\n"
115 "\tp, pre { font-family: monospace; }\n"
116 "\th1.title, h2.title, h3.title { border-bottom: solid "
117 "2px #000000; }\n"
118 "\t--></style>\n");
119
120 /*
121 * Skip the initial header stuff (working group ID, RFC #, authors, and
122 * copyright...
123 */
124
125 linenum = 0;
126
127 while (cupsFileGets(infile, line, sizeof(line)))
128 {
129 linenum ++;
130
131 if (line[0])
132 break;
133 }
134
135 while (cupsFileGets(infile, line, sizeof(line)))
136 {
137 linenum ++;
138
139 if (!line[0])
140 break;
141 }
142
143 /*
144 * Read the document title...
145 */
146
147 while (cupsFileGets(infile, line, sizeof(line)))
148 {
149 linenum ++;
150
151 if (line[0])
152 break;
153 }
154
155 for (lineptr = line; isspace(*lineptr & 255); lineptr ++);
156
157 cupsFilePrintf(outfile, "<title>%s", lineptr);
158
159 while (cupsFileGets(infile, line, sizeof(line)))
160 {
161 linenum ++;
162
163 if (!line[0])
164 break;
165 else
166 {
167 for (lineptr = line; isspace(*lineptr & 255); lineptr ++);
168 cupsFilePrintf(outfile, " %s", lineptr);
169 }
170 }
171
172 cupsFilePuts(outfile, "</title>\n"
173 "</head>\n"
174 "<body>\n");
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)
203 cupsFilePuts(outfile, "</h1>\n");
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)
217 cupsFilePuts(outfile, "</h1>\n");
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));
343 for (nameptr = name, level = 0; *nameptr;)
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
359 cupsFilePrintf(outfile, "\n<h%d class='title'><a name='s%s'>", level, name);
360 put_line(outfile, line);
361
362 intoc = 0;
363 inheading = level;
364 }
365 else
366 {
367 if (intoc)
368 {
369 while (toclevel > 0)
370 {
371 cupsFilePuts(outfile, "\n</ul>");
372 toclevel --;
373 }
374
375 cupsFilePutChar(outfile, '\n');
376 intoc = 0;
377 }
378
379 if (!inheading)
380 {
381 cupsFilePuts(outfile, "\n<h1 class='title'>");
382 inheading = -1;
383 }
384
385 put_line(outfile, line);
386
387 intoc = !strcasecmp(line, "Table of Contents");
388 toclevel = 0;
389 }
390 }
391
392 if (inpre)
393 cupsFilePuts(outfile, "</pre>\n");
394
395 if (inheading)
396 {
397 if (inheading < 0)
398 cupsFilePuts(outfile, "</h1>\n");
399 else
400 cupsFilePrintf(outfile, "</a></h%d>\n", inheading);
401 }
402
403 cupsFilePuts(outfile, "</body>\n"
404 "</html>\n");
405
406 /*
407 * Close files...
408 */
409
410 cupsFileClose(infile);
411 cupsFileClose(outfile);
412
413 /*
414 * Return with no errors...
415 */
416
417 return (0);
418}
419
420
421/*
422 * 'put_entity()' - Put a single character, using entities as needed.
423 */
424
425void
426put_entity(cups_file_t *fp, /* I - File */
427 int ch) /* I - Character */
428{
429 if (ch == '&')
430 cupsFilePuts(fp, "&amp;");
431 else if (ch == '<')
432 cupsFilePuts(fp, "&lt;");
433 else
434 cupsFilePutChar(fp, ch);
435}
436
437
438/*
439 * 'put_line()' - Put a whole string for a line.
440 */
441
442void
443put_line(cups_file_t *fp, /* I - File */
444 const char *s) /* I - String */
445{
446 int whitespace, /* Saw whitespace */
447 i, /* Looping var */
448 len; /* Length of keyword */
449 static const char * const keywords[] =/* Special keywords to boldface */
450 {
451 "MAY",
452 "MUST",
453 "NOT",
454 "SHALL",
455 "SHOULD"
456 };
457
458
459 whitespace = 1;
460
461 while (*s)
462 {
463 if (*s == ' ')
464 whitespace = 1;
465
466 if (whitespace && isupper(*s & 255))
467 {
468 whitespace = 0;
469
470 for (i = 0; i < (int)(sizeof(keywords) / sizeof(sizeof(keywords[0]))); i ++)
471 {
472 len = strlen(keywords[i]);
473 if (!strncmp(s, keywords[i], len) && (isspace(s[len] & 255) || !*s))
474 {
475 cupsFilePrintf(fp, "<b>%s</b>", keywords[i]);
476 s += len;
477 break;
478 }
479 }
480
481 if (i >= (int)(sizeof(keywords) / sizeof(sizeof(keywords[0]))))
482 put_entity(fp, *s++);
483 }
484 else
485 {
486 if (*s != ' ')
487 whitespace = 0;
488
489 put_entity(fp, *s++);
490 }
491 }
492}
493
494
495/*
496 * End of "$Id: rfctohtml.c 4966 2006-01-23 00:41:22Z mike $".
497 */