const char * UsageLines [] = {
       "Usage: doctohtml (article number) [(article link URLs) ]",
       "Takes text from standard input and prints simple HTML using",
       "H2, P, UL, LI, and BR, to standard output.",
       "",
       "Input text is treated as a series of articles.  Articles are",
       "separated from each other by three consecutive blank lines.",
       "Only the specified article will be printed in full.  The",
       "other articles will only print links.  A URL should be",
       "specified for each article except the one being printed.",
       "Use 1 for the first article, or the only article.",
       "Input processing stops at end, or at a sequence of four",
       "consecutive blank lines, whichever comes first.",
       "Specifying an article number of 0 will print only links.",
       "The first input line in each article is considered to be",
       "the article title, and is used in links from the other",
       "articles.",
       "",
       "Input text should not contain any soft line breaks.  Any input",
       "line break within a paragraph will be written as BR.  A paragraph",
       "is separated from the previous paragraph by a blank line.",
       "A heading (H2) is preceded by two blank lines.",
       "",
       "June 2, 2011.  Newest is at gopher -p users/julianbr sdf.org",
       };
const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] );


const struct {
       const char * entity;
       const unsigned char character;
       } Entities [] = {
       {"&lt;", '<'},
       {"&gt;", '>'},
       {"&amp;", '&'},
       {"&nbsp;", 160},
       {"&iexcl;", 161},
       {"&cent;", 162},
       {"&pound;", 163},
       {"&curren;", 164},
       {"&yen;", 165},
       {"&brvbar;", 166},
       {"&sect;", 167},
       {"&uml;", 168},
       {"&copy;", 169},
       {"&ordf;", 170},
       {"&laquo;", 171},
       {"&not;", 172},
       {"&shy;", 173},
       {"&reg;", 174},
       {"&macr;", 175},
       {"&deg;", 176},
       {"&plusmn;", 177},
       {"&sup2;", 178},
       {"&sup3;", 179},
       {"&acute;", 180},
       {"&micro;", 181},
       {"&para;", 182},
       {"&middot;", 183},
       {"&cedil;", 184},
       {"&supl;", 185},
       {"&ordm;", 186},
       {"&raquo;", 187},
       {"&frac14;", 188},
       {"&frac12;", 189},
       {"&frac34;", 190},
       {"&iquest;", 191},
       {"&Agrave;", 192},
       {"&Aacute;", 193},
       {"&Acirc;", 194},
       {"&Atilde;", 195},
       {"&Auml;", 196},
       {"&Aring;", 197},
       {"&AElig;", 198},
       {"&Ccedil;", 199},
       {"&Egrave;", 200},
       {"&Eacute;", 201},
       {"&Ecirc;", 202},
       {"&Euml;", 203},
       {"&Igrave;", 204},
       {"&Iacute;", 205},
       {"&Icirc;", 206},
       {"&Iuml;", 207},
       {"&ETH;", 208},
       {"&Ntilde;", 209},
       {"&Ograve;", 210},
       {"&Oacute;", 211},
       {"&Ocirc;", 212},
       {"&Otilde;", 213},
       {"&Ouml;", 214},
       {"&times;", 215},
       {"&Oslash;", 216},
       {"&Ugrave;", 217},
       {"&Uacute;", 218},
       {"&Ucirc;", 219},
       {"&Uuml;", 220},
       {"&Yacute;", 221},
       {"&THORN;", 222},
       {"&szlig;", 223},
       {"&agrave;", 224},
       {"&aacute;", 225},
       {"&acirc;", 226},
       {"&atilde;", 227},
       {"&auml;", 228},
       {"&aring;", 229},
       {"&aelig;", 230},
       {"&ccedil;", 231},
       {"&egrave;", 232},
       {"&eacute;", 233},
       {"&ecirc;", 234},
       {"&euml;", 235},
       {"&igrave;", 236},
       {"&iacute;", 237},
       {"&icirc;", 238},
       {"&iuml;", 239},
       {"&eth;", 240},
       {"&ntilde;", 241},
       {"&ograve;", 242},
       {"&oacute;", 243},
       {"&ocirc;", 244},
       {"&otilde;", 245},
       {"&ouml;", 246},
       {"&divide;", 247},
       {"&oslash;", 248},
       {"&ugrave;", 249},
       {"&uacute;", 250},
       {"&ucirc;", 251},
       {"&uuml;", 252},
       {"&yacute;", 253},
       {"&thorn;", 254},
       {"&yuml;", 255},
       };
const int NumEntities = sizeof (Entities)/sizeof (Entities [0] );
/* const int NumEntities = 0 */
/* To NOT replace characters with entities, uncomment above line */
/* and comment the line above that. */

#include <stdio.h>


void WriteEntity (unsigned char c)
       {
       int i;

       i = 0;
       while (i < NumEntities && Entities [i].character != c)
               i++;
       if (i < NumEntities)
               fputs (Entities [i].entity, stdout);
       else
               putchar (c);
       }


void Write (int ArticleNum, char * * Urls, int NumUrls)
       {
       int UrlNum, NumArticles;
       char c;

       printf ("<HTML>\n");
       printf ("\t<HEAD>\n");
       printf ("\t\t<STYLE><!--\n");
       printf ("\t\t\tBODY {\n");
       printf ("\t\t\t\tbackground-color: rgb(90%%,90%%,95%%);\n");
       printf ("\t\t\t\tborder: lightblue solid 15px;\n");
       printf ("\t\t\t\tmargin: 0;\n");
       printf ("\t\t\t\tpadding-top: 1%%;\n");
       printf ("\t\t\t\tpadding-left: 1%%;\n");
       printf ("\t\t\t\tpadding-right: 5%%;\n");
       printf ("\t\t\t\tpadding-bottom: 10%%;\n");
       printf ("\t\t\t\t}\n");
       printf ("\t\t\t--></STYLE>\n");
       printf ("\t\t</HEAD>\n");
       printf ("\t<BODY>\n");
       printf ("\t\t<UL>\n");
       NumArticles = 0;
       UrlNum = 0;
       c = getchar ();
       while (c != EOF && c != '\n') {
               NumArticles++;
               if (NumArticles == ArticleNum) {
                       /* Title not part of printed article */
                       while (c != EOF && c != '\n')
                               c = getchar ();
                       }
               else {
                       if (UrlNum < NumUrls) {
                               printf ("\t\t\t<LI><A HREF");
                               printf ("=\"%s\">", Urls [UrlNum] );
                               while (c != EOF && c != '\n') {
                                       WriteEntity (c);
                                       c = getchar ();
                                       }
                               printf ("</A></LI>\n");
                               }
                       else {
                               fprintf (stderr, "***doctohtml: Need URL");
                               fprintf (stderr, " for article \"");
                               while (c != EOF && c != '\n') {
                                       fputc (c, stderr);
                                       c = getchar ();
                                       }
                               fprintf (stderr, "\".\n");
                               }
                       UrlNum++;
                       }
               if (NumArticles == ArticleNum)
                       printf ("\t\t\t</UL>\n");
               /* Blank line optional before first paragraph */
               if (c == '\n')
                       c = getchar ();
               /* Paragraphs */
               while (c != EOF && c != '\n') {
                       if (NumArticles == ArticleNum)
                               printf ("\t\t<P>");
                       while (c != EOF && c != '\n') {
                               while (c != EOF && c != '\n') {
                                       if (NumArticles == ArticleNum)
                                               WriteEntity (c);
                                       c = getchar ();
                                       }
                               if (c != EOF)
                                       c = getchar ();
                               if (c != EOF && c != '\n') {
                                       if (NumArticles == ArticleNum)
                                               printf ("<BR>");
                                       }
                               }
                       if (NumArticles == ArticleNum)
                               printf ("</P>\n");
                       if (c != EOF)
                               c = getchar ();
                       }
               if (c != EOF)
                       c = getchar ();
               while (c != EOF && c != '\n') {
                       if (NumArticles == ArticleNum)
                               printf ("\t\t<H2>");
                       while (c != EOF && c != '\n') {
                               if (NumArticles == ArticleNum)
                                       WriteEntity (c);
                               c = getchar ();
                               }
                       if (NumArticles == ArticleNum)
                               printf ("</H2>\n");
                       if (c != EOF)
                               c = getchar ();
                       /* Blank line optional before first paragraph */
                       if (c == '\n')
                               c = getchar ();
                       /* Paragraphs */
                       while (c != EOF && c != '\n') {
                               if (NumArticles == ArticleNum)
                                       printf ("\t\t<P>");
                               while (c != EOF && c != '\n') {
                                       while (c != EOF && c != '\n') {
                                               if (NumArticles == ArticleNum)
                                                       WriteEntity (c);
                                               c = getchar ();
                                               }
                                       if (c != EOF)
                                               c = getchar ();
                                       if (c != EOF && c != '\n') {
                                               if (NumArticles == ArticleNum)
                                                       printf ("<BR>");
                                               }
                                       }
                               if (NumArticles == ArticleNum)
                                       printf ("</P>\n");
                               if (c != EOF)
                                       c = getchar ();
                               }
                       if (c != EOF)
                               c = getchar ();
                       }
               if (NumArticles == ArticleNum)
                       printf ("\t\t<UL>\n");
               if (c != EOF)
                       c = getchar ();
               }
       printf ("\t\t\t</UL>\n");
       printf ("\t\t</BODY>\n");
       printf ("\t</HTML>\n");
       if (NumArticles < ArticleNum) {
               fprintf (stderr, "***doctohtml: Never found article");
               fprintf (stderr, " #%d.\n", ArticleNum);
               fprintf (stderr, "***doctohtml: Only found");
               fprintf (stderr, " %d articles.\n", NumArticles);
               }
       while (UrlNum < NumUrls) {
               fprintf (stderr, "***doctohtml: Never found article");
               fprintf (stderr, " for URL \"%s\".\n", Urls [UrlNum] );
               UrlNum++;
               }
       }


int main (int argc, char * argv [] )
       {
       int i, ArticleNum;
       char c;

       if (argc < 2) {
               for (i = 0; i < NumUsageLines; i++)
                       printf ("%s\n", UsageLines [i] );
               }
       else if (argc > 1) {
               if (sscanf (argv [1], "%d%c", & ArticleNum, & c) != 1) {
                       fprintf (stderr, "***doctohtml: Expecting");
                       fprintf (stderr, " article number, found");
                       fprintf (stderr, " \"%s\".\n", argv [1] );
                       }
               else
                       Write (ArticleNum, argv + 2, argc - 2);
               }
       return 0;
       }