#include <cups/string-private.h>
#include <stdlib.h>
#include <cups/file.h>
void put_entity(cups_file_t *fp, int ch);
void put_line(cups_file_t *fp, const char *line);
int
main(int argc,
char *argv[])
{
cups_file_t *infile,
*outfile;
char line[1024],
*lineptr,
title[2048],
*titleptr,
name[1024],
*nameptr;
int rfc,
inheading,
inpre,
intoc,
toclevel,
linenum;
if (argc > 3)
{
fputs("Usage: rfctohtml [rfcNNNN.txt [rfcNNNN.html]]\n", stderr);
return (1);
}
if (argc > 1)
{
if ((infile = cupsFileOpen(argv[1], "r")) == NULL)
{
perror(argv[1]);
return (1);
}
}
else
infile = cupsFileOpenFd(0, "r");
if (argc > 2)
{
if ((outfile = cupsFileOpen(argv[2], "w")) == NULL)
{
perror(argv[2]);
cupsFileClose(infile);
return (1);
}
}
else
outfile = cupsFileOpenFd(1, "w");
cupsFilePuts(outfile,
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" "
"\"http://www.w3.org/TR/html4/loose.dtd\">\n"
"<html>\n"
"<!-- SECTION: Specifications -->\n"
"<head>\n"
"\t<link rel=\"stylesheet\" type=\"text/css\" "
"href=\"../cups-printable.css\">\n");
linenum = 0;
rfc = 0;
while (cupsFileGets(infile, line, sizeof(line)))
{
linenum ++;
if (line[0])
break;
}
while (cupsFileGets(infile, line, sizeof(line)))
{
linenum ++;
if (!line[0])
break;
else if (!_cups_strncasecmp(line, "Request for Comments:", 21))
rfc = atoi(line + 21);
}
while (cupsFileGets(infile, line, sizeof(line)))
{
linenum ++;
if (line[0])
break;
}
for (lineptr = line; isspace(*lineptr & 255); lineptr ++);
snprintf(title, sizeof(title), "RFC %d: %s", rfc, lineptr);
titleptr = title + strlen(title);
while (cupsFileGets(infile, line, sizeof(line)))
{
linenum ++;
if (!line[0])
break;
else
{
for (lineptr = line; isspace(*lineptr & 255); lineptr ++);
snprintf(titleptr, sizeof(title) - (titleptr - title), " %s", lineptr);
titleptr += strlen(titleptr);
}
}
cupsFilePrintf(outfile, "\t<title>%s</title>\n"
"</head>\n"
"<body>\n"
"<h1 class='title'>%s</h1>\n", title, title);
inheading = 0;
inpre = 0;
intoc = 0;
toclevel = 0;
while (cupsFileGets(infile, line, sizeof(line)))
{
linenum ++;
if (!line[0])
{
if (linenum > 50)
continue;
if (inpre)
{
cupsFilePuts(outfile, "</pre>\n");
inpre = 0;
}
if (inheading)
{
if (inheading < 0)
cupsFilePuts(outfile, "</h2>\n");
else
cupsFilePrintf(outfile, "</a></h%d>\n", inheading);
inheading = 0;
}
}
else if ((line[0] == ' ' ||
(!isupper(line[0] & 255) && !isdigit(line[0] & 255) &&
!strstr(line, "[Page "))) && !inheading)
{
if (inheading)
{
if (inheading < 0)
cupsFilePuts(outfile, "</h2>\n");
else
cupsFilePrintf(outfile, "</a></h%d>\n", inheading);
inheading = 0;
}
for (lineptr = line; *lineptr == ' '; lineptr ++);
if (intoc)
{
char *temp;
int level;
if (isdigit(*lineptr & 255))
{
strlcpy(name, lineptr, sizeof(name));
for (nameptr = name, level = -1; *nameptr;)
if (isdigit(*nameptr & 255))
{
while (isdigit(*nameptr & 255))
nameptr ++;
level ++;
}
else if (*nameptr == ' ')
{
*nameptr = '\0';
break;
}
else
nameptr ++;
while (toclevel > level)
{
cupsFilePuts(outfile, "\n</ul>");
toclevel --;
}
while (toclevel < level)
{
cupsFilePuts(outfile, "\n<ul style=\"list-style-type: none;\">\n");
toclevel ++;
}
cupsFilePrintf(outfile, "\n<%s><a href=\"#s%s\">", toclevel ? "li" : "p",
name);
}
temp = lineptr + strlen(lineptr) - 1;
while (temp > lineptr)
if (*temp == ' ' || !isdigit(*temp & 255))
break;
else
temp --;
if (*temp == ' ')
{
while (temp > lineptr)
if (*temp != ' ' && *temp != '.')
break;
else
*temp-- = '\0';
}
else
temp = NULL;
if (isdigit(*lineptr & 255))
put_line(outfile, lineptr);
else
put_line(outfile, lineptr - 1);
if (temp)
cupsFilePuts(outfile, "</a>");
}
else if (!inpre)
{
cupsFilePuts(outfile, "\n<pre>");
put_line(outfile, line);
inpre = 1;
}
else
{
cupsFilePutChar(outfile, '\n');
put_line(outfile, line);
}
}
else if (strstr(line, "[Page "))
{
cupsFileGets(infile, line, sizeof(line));
cupsFileGets(infile, line, sizeof(line));
cupsFileGets(infile, line, sizeof(line));
cupsFileGets(infile, line, sizeof(line));
linenum = 3;
}
else if (isdigit(line[0] & 255) && !inheading)
{
int level;
if (intoc)
{
while (toclevel > 0)
{
cupsFilePuts(outfile, "\n</ul>");
toclevel --;
}
cupsFilePutChar(outfile, '\n');
intoc = 0;
}
if (inpre)
{
cupsFilePuts(outfile, "</pre>\n");
inpre = 0;
}
strlcpy(name, line, sizeof(name));
for (nameptr = name, level = 1; *nameptr;)
if (isdigit(*nameptr & 255))
{
while (isdigit(*nameptr & 255))
nameptr ++;
level ++;
}
else if (*nameptr == ' ')
{
*nameptr = '\0';
break;
}
else
nameptr ++;
cupsFilePrintf(outfile, "\n<h%d class='title'><a name='s%s'>", level,
name);
put_line(outfile, line);
intoc = 0;
inheading = level;
}
else
{
if (intoc)
{
while (toclevel > 0)
{
cupsFilePuts(outfile, "\n</ul>");
toclevel --;
}
cupsFilePutChar(outfile, '\n');
intoc = 0;
}
if (!inheading)
{
cupsFilePuts(outfile, "\n<h2 class='title'>");
inheading = -1;
}
put_line(outfile, line);
intoc = !_cups_strcasecmp(line, "Table of Contents");
toclevel = 0;
}
}
if (inpre)
cupsFilePuts(outfile, "</pre>\n");
if (inheading)
{
if (inheading < 0)
cupsFilePuts(outfile, "</h2>\n");
else
cupsFilePrintf(outfile, "</a></h%d>\n", inheading);
}
cupsFilePuts(outfile, "</body>\n"
"</html>\n");
cupsFileClose(infile);
cupsFileClose(outfile);
return (0);
}
void
put_entity(cups_file_t *fp,
int ch)
{
if (ch == '&')
cupsFilePuts(fp, "&");
else if (ch == '<')
cupsFilePuts(fp, "<");
else
cupsFilePutChar(fp, ch);
}
void
put_line(cups_file_t *fp,
const char *s)
{
int whitespace,
i,
len;
static const char * const keywords[] =
{
"MAY",
"MUST",
"NEED",
"NOT",
"OPTIONAL",
"OPTIONALLY",
"RECOMMENDED",
"REQUIRED",
"SHALL",
"SHOULD"
};
whitespace = 1;
while (*s)
{
if (*s == ' ')
whitespace = 1;
if (whitespace && isupper(*s & 255))
{
whitespace = 0;
for (i = 0; i < (int)(sizeof(keywords) / sizeof(sizeof(keywords[0]))); i ++)
{
len = strlen(keywords[i]);
if (!strncmp(s, keywords[i], len) &&
(isspace(s[len] & 255) || ispunct(s[len] & 255) || !*s))
{
cupsFilePrintf(fp, "<b>%s</b>", keywords[i]);
s += len;
break;
}
}
if (i >= (int)(sizeof(keywords) / sizeof(sizeof(keywords[0]))))
put_entity(fp, *s++);
}
else
{
if (*s != ' ')
whitespace = 0;
put_entity(fp, *s++);
}
}
}