Datei: c2html.c


    1   /*
    2    *      c2html.c
    3    *      C Quelltext nach HTML konvertieren
    4    *      1.00, Klingebiel, Tue Dec 23 08:04:07 1997
    5    *      1.01, Klingebiel, Thu Nov 18 09:48:02 1999
    6    *      1.02, Klingebiel, Mon Mar 11 13:02:56 2002, Zwei Bugfixes
    7    *                        (gemeldet von Robert, robc@free.fr)
    8    *
    9    *      Aufruf: c2html [-a][-c][-h][-l][-n][-t] [infile.c] [outfile.html]
   10    */
   11   
   12   static const char *sccs = "@(#) c2html.c 1.02 (klin) Mar 11 2002";
   13   static const char *prgname = "c2html";
   14   static const char *prgvers = "1.02";
   15   
   16   /*
   17    *      Headerdateien
   18    */
   19   
   20   #include <stdio.h>
   21   #include <string.h>
   22   #include <stdlib.h>
   23   
   24   /*
   25    *      Farbdefinitionen
   26    */
   27   
   28   #include "c2html.h"
   29   
   30   static char *bgcol = BGCOL;             /* Hintergrund          */
   31   static char *tdcol = TDCOL;             /* Tabellenhintergrund  */
   32   static const char *txcol = TXCOL;       /* Text                 */
   33   static const char *rwcol = RWCOL;       /* Schluesselworte      */
   34   static const char *sccol = SCCOL;       /* Strings/Zeichen      */
   35   static const char *cmcol = CMCOL;       /* Kommentare           */
   36   static const char *lncol = LNCOL;       /* Zeilennummern        */
   37   
   38   /*
   39    *      Reservierte Worte in C und CPP
   40    *      und die Groessen der Tabellen
   41    */
   42   
   43   static const char *ckeytab[] = {
   44     "auto",       "break",        "case",
   45     "char",       "const",        "continue",
   46     "default",    "do",           "double",
   47     "else",       "enum",         "extern",
   48     "float",      "for",          "goto",
   49     "if",         "int",          "long",
   50     "register",   "return",       "short",
   51     "signed",     "sizeof",       "static",
   52     "struct",     "switch",       "typedef",
   53     "union",      "unsigned",     "void",
   54     "volatile",   "while",
   55   };
   56   
   57   static const int nckeys = (sizeof(ckeytab) / sizeof(char *));
   58   
   59   static const char *pkeytab[] = {
   60     "define",     "defined",      "elif",         "else",
   61     "endif",      "error",        "if",
   62     "ifdef",      "ifndef",       "include",
   63     "line",       "pragma",       "undef",
   64   };
   65   
   66   static const int npkeys = (sizeof(pkeytab) / sizeof(char *));
   67   
   68   /*
   69    *      Symbole fuer Zeichentypen wie sie
   70    *      von getword() geliefert werden
   71    */
   72   
   73   #define LETTER  0x0100          /* Zeichen/Wort         */
   74   #define DIGIT   0x0200          /* Ziffer               */
   75   #define CSTART  0x0300          /* Kommentaranfang      */
   76   #define CEND    0x0400          /* Kommentarende        */
   77   #define MASK    0x0500          /* Maskierung           */
   78   #define BSTART  0x0600          /* Blockanfang          */
   79   #define BEND    0x0700          /* Blockende            */
   80   #define DSTART  0x0800          /* Stringanfang         */
   81   #define DEND    0x0900          /* Stringende           */
   82   #define SSTART  0x0a00          /* Zeichenanfang        */
   83   #define SEND    0x0b00          /* Zeichenende          */
   84   
   85   /*
   86    *      Weitere Konstanten
   87    */
   88   
   89   #define MAXWORD 512             /* Maximale Wortlaenge  */
   90   
   91   /*
   92    *      Zustandsflags
   93    */
   94   
   95   static int comment = 0;         /* Kommentarflag        */
   96   static int squote  = 0;         /* Anfuehrungszeichen   */
   97   static int dquote  = 0;         /* Anfuehrungszeichen   */
   98   static int hash    = 0;         /* Hash-Zeichen         */
   99   static int newline = 0;         /* Neue Zeile           */
  100   
  101   /*
  102    *      Prototypen
  103    */
  104   
  105   static void c2html(int, int);
  106   static int  binary(char *, const char *[], const int);
  107   static int  getword(char *, int);
  108   static int  type(int);
  109   static void putheader(char *, int, int, int);
  110   static void puttrailer(int);
  111   static int  iseof(void);
  112   
  113   /*
  114    *      Main
  115    */
  116   
  117   void main(int argc, char *argv[])
  118   {
  119     int cflag = 0;        /* Colorflag            */
  120     int lflag = 0;        /* Linkflag             */
  121     int nflag = 0;        /* Zeilennummerflag     */
  122     int tflag = 0;        /* Tabellenflag         */
  123   
  124     /* Optionen pruefen */
  125     while (argc > 1 && argv[1][0] == '-') {
  126       /* Zeilennummer zaehlen */
  127       if (strcmp(argv[1], "-n") == 0) {
  128         nflag = 1;
  129         --argc;
  130         ++argv;
  131       }
  132       /* Farben in Ausgabe nutzen */
  133       else if (strcmp(argv[1], "-c") == 0) {
  134         cflag = 1;
  135         --argc;
  136         ++argv;
  137       }
  138       /* Tabelle in Ausgabe nutzen */
  139       else if (strcmp(argv[1], "-t") == 0) {
  140         tflag = 1;
  141         --argc;
  142         ++argv;
  143       }
  144       /* Link auf Quelle setzen */
  145       else if (strcmp(argv[1], "-l") == 0) {
  146         lflag = 1;
  147         --argc;
  148         ++argv;
  149       }
  150       /* Alle Optionen nutzen */
  151       else if (strcmp(argv[1], "-a") == 0) {
  152         cflag = lflag = nflag = tflag = 1;
  153         --argc;
  154         ++argv;
  155       }
  156       /* Ende der Optionen */
  157       else if (strcmp(argv[1], "--") == 0) {
  158         --argc;
  159         ++argv;
  160         break;
  161       }
  162       /* Hilfe */
  163       else if (strcmp(argv[1], "-h") == 0) {
  164         fprintf(stderr, "Aufruf: %s [-a][-c][-h][-l][-n][-t] [infile.c] [outfile.html]\n", prgname);
  165         fprintf(stderr, "\t-a\tAlle Optionen (clnt) einschalten\n");
  166         fprintf(stderr, "\t-c\tSchluesselworte und Kommentare in Farbe ausgeben\n");
  167         fprintf(stderr, "\t-h\tHilfe zu Aufruf und Optionen ausgeben\n");
  168         fprintf(stderr, "\t-l\tLink auf Quelldatei setzen\n");
  169         fprintf(stderr, "\t-n\tZeilennummern ausgeben\n");
  170         fprintf(stderr, "\t-t\tTabelle nutzen\n");
  171         exit(0);
  172       }
  173       /* Falsche Option */
  174       else {
  175         fprintf(stderr, "Aufruf: %s [-a][-c][-h][-l][-n][-t] [infile.c] [outfile.html]\n", prgname);
  176         exit(1);
  177       }
  178     }
  179   
  180     /* Parameter pruefen */
  181     if (argc > 1 && freopen(argv[1], "r", stdin) == NULL) {
  182       fprintf(stderr, "%s: Kann Datei %s nicht oeffnen\n", prgname, argv[1]);
  183       /* Besser: perror(argv[1]); */
  184       exit(1);
  185     }
  186     if (argc > 2 && freopen(argv[2], "w", stdout) == NULL) {
  187       fprintf(stderr, "%s: Kann Datei %s nicht oeffnen\n", prgname, argv[2]);
  188       /* Besser: perror(argv[2]); */
  189       exit(1);
  190     }
  191     if (tflag) {
  192       bgcol = TDCOL;
  193       tdcol = BGCOL;
  194     }
  195   
  196     /* HTML-Header ausgeben */
  197     putheader(argc > 1 ? argv[1] : NULL, cflag, lflag, tflag);
  198   
  199     /* Aktion: Lesen, Formatieren, Schreiben */
  200     c2html(cflag, nflag);
  201   
  202     /* HTML-Trailer ausgeben */
  203     puttrailer(tflag);
  204   
  205     exit(0);
  206   
  207   } /* main() */
  208   
  209   /*
  210    *      C wortweise lesen und nach HTML konvertieren
  211    */
  212   
  213   static void c2html(int cflag, int nflag)
  214   {
  215     char word[MAXWORD];   /* Eingabewort          */
  216     int t;                /* Zeichen/Symbol       */
  217     int nline = 1;        /* Zeilennummer         */
  218   
  219     /* Ggfs. Zeilennummer ausgeben */
  220     if (nflag && !iseof()) {
  221       /* BUGFIX 1.02, klin, Mon Mar 11 13:09:18 2002
  222       if (cflag)
  223       else
  224         fprintf(stdout, "<I>%5d   </I>", nline);
  225       */
  226       fprintf(stdout, "<FONT COLOR=%s><I>%5d   </I></FONT>", lncol, nline);
  227     }
  228   
  229     /* Bis EOF wort-/zeichenweise lesen */
  230     while ((t = getword(word, MAXWORD)) != EOF) {
  231       switch (t) {
  232         case LETTER:      /* Wort */
  233   	/* Kommentar oder String */
  234   	if (comment || dquote || squote) {
  235   	  fprintf(stdout, "%s", word);
  236   	}
  237   	/* CPP-Schluesselwort */
  238   	else if (hash && binary(word, pkeytab, npkeys) >= 0) {
  239   	  if (cflag)
  240   	    fprintf(stdout, "<FONT COLOR=%s><B>%s</B></FONT>", rwcol, word);
  241   	  else
  242   	    fprintf(stdout, "<B>%s</B>", word);
  243   	}
  244   	/* C-Schluesselwort */
  245   	else if (!hash && binary(word, ckeytab, nckeys) >= 0) {
  246   	  if (cflag)
  247   	    fprintf(stdout, "<FONT COLOR=%s><B>%s</B></FONT>", rwcol, word);
  248   	  else
  249   	    fprintf(stdout, "<B>%s</B>", word);
  250   	}
  251   	/* Sonstiges Wort */
  252   	else {
  253   	  fprintf(stdout, "%s", word);
  254   	}
  255   	break;
  256         case CSTART:      /* Kommentaranfang */
  257   	if (cflag)
  258   	  fprintf(stdout, "<FONT COLOR=%s><I>%s", cmcol, word);
  259   	else
  260   	  fprintf(stdout, "<I>%s", word);
  261   	break;
  262         case CEND:        /* Kommentarende */
  263   	if (cflag)
  264   	  fprintf(stdout, "%s</I></FONT>", word);
  265   	else
  266   	  fprintf(stdout, "%s</I>", word);
  267   	break;
  268         case BSTART:      /* Blockanfang */
  269   	fprintf(stdout, "<B>%s</B>", word);
  270   	break;
  271         case BEND:        /* Blockende */
  272   	fprintf(stdout, "<B>%s</B>", word);
  273   	break;
  274         case DSTART:      /* Stringanfang */
  275   	if (cflag)
  276   	  fprintf(stdout, "<FONT COLOR=%s>&quot;", sccol);
  277   	else
  278   	  fprintf(stdout, "&quot;");
  279   	break;
  280         case DEND:        /* Stringende */
  281   	if (cflag)
  282   	  fprintf(stdout, "&quot;</FONT>");
  283   	else
  284   	  fprintf(stdout, "&quot;");
  285   	break;
  286         case SSTART:      /* Zeichenanfang */
  287   	if (cflag)
  288   	  fprintf(stdout, "<FONT COLOR=%s>\'", sccol);
  289   	else
  290   	  fprintf(stdout, "\'");
  291   	break;
  292         case SEND:        /* Zeichenende */
  293   	if (cflag)
  294   	  fprintf(stdout, "\'</FONT>");
  295   	else
  296   	  fprintf(stdout, "\'");
  297   	break;
  298         case MASK:        /* Maskierung */
  299   	fprintf(stdout, "%s", word);
  300   	break;
  301         case '\"':        /* HTML-Sonderzeichen -> Entity */
  302   	fprintf(stdout, "&quot;");
  303   	break;
  304         case '&':         /* HTML-Sonderzeichen -> Entity */
  305   	fprintf(stdout, "&amp;");
  306   	break;
  307         case '<':         /* HTML-Sonderzeichen -> Entity */
  308   	fprintf(stdout, "&lt;");
  309   	break;
  310         case '>':         /* HTML-Sonderzeichen -> Entity */
  311   	fprintf(stdout, "&gt;");
  312   	break;
  313         case '\n':        /* Zeilenende */
  314   	if (nflag && !iseof()) {
  315   	  ++nline;
  316   	  if (comment) {
  317   	    if (cflag) {
  318   	      fprintf(stdout, "</I></FONT>");
  319   	      fprintf(stdout, "\n<FONT COLOR=%s><I>%5d   </I></FONT>", lncol, nline);
  320   	      fprintf(stdout, "<FONT COLOR=%s><I>", cmcol);
  321   	    }
  322   	    else
  323   	      /* BUGFIX 1.20, klin, Mon Mar 11 13:07:54 2002
  324   	      fprintf(stdout, "</I>\n<I>%5d   </I><I>", nline);
  325   	      */
  326   	      fprintf(stdout, "\n<FONT COLOR=%s><I>%5d   </I></FONT>", lncol, nline);
  327   	  }
  328   	  else
  329   	    fprintf(stdout, "\n<FONT COLOR=%s><I>%5d   </I></FONT>", lncol, nline);
  330   	  break;
  331   	}
  332   	/* Sonst: NL ausgeben wie sonstige Zeichen */
  333         default:          /* Sonstiges Zeichen */
  334   	fprintf(stdout, "%c", t);
  335   	break;
  336       }
  337     }
  338   
  339   } /* c2html() */
  340   
  341   /*
  342    *      HTML-Header ausgeben
  343    */
  344   
  345   static void putheader(char *name, int cflag, int lflag, int tflag)
  346   {
  347     fprintf(stdout, "<HTML>\n");
  348     fprintf(stdout, "<HEAD>\n");
  349     if (name)
  350       fprintf(stdout, "<TITLE>Datei: %s</TITLE>\n", name);
  351     else
  352       fprintf(stdout, "<TITLE>C Quelltext</TITLE>\n");
  353     if (cflag)
  354       fprintf(stdout, "<BODY BACKGROUND="../spiral.gif" BGCOLOR=\"%s\" TEXT=%s>\n", bgcol, txcol);
  355     else
  356       fprintf(stdout, "<BODY>\n");
  357     if (tflag) {
  358       fprintf(stdout, "<TABLE BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"6\" WIDTH=\"100%%\" HEIGHT=\"100%%\">");
  359       fprintf(stdout, "<TR>\n<TD BGCOLOR=\"%s\" WIDTH=\"10%%\">&nbsp;</TD>\n", bgcol);
  360       fprintf(stdout, "<TD WIDTH=\"80%%\" VALIGN=\"top\" BGCOLOR=\"%s\">\n", tdcol);
  361     }
  362     if (name) {
  363       if (lflag)
  364         fprintf(stdout, "<H2>Datei: <A HREF=\"%s\">%s</A></H2>\n<HR>\n", name, name);
  365       else
  366         fprintf(stdout, "<H2>Datei: %s</H2>\n<HR>\n", name);
  367     }
  368     fprintf(stdout, "<P>\n");
  369     fprintf(stdout, "<PRE>\n");
  370   
  371   } /* putheader() */
  372   
  373   /*
  374    *      HTML-Trailer ausgeben
  375    */
  376   
  377   static void puttrailer(int tflag)
  378   {
  379     fprintf(stdout, "</PRE>\n");
  380     fprintf(stdout, "<P>\n");
  381     fprintf(stdout, "<HR>\n");
  382     fprintf(stdout, "<I>Erzeugt von %s %s</I>\n", prgname, prgvers);
  383     if (tflag)
  384       fprintf(stdout, "</TD>\n<TD BGCOLOR=\"%s\" WIDTH=\"10%%\">&nbsp;</TD>\n</TR>\n</TABLE>\n", bgcol);
  385     fprintf(stdout, "</BODY>\n");
  386     fprintf(stdout, "</HTML>\n");
  387   
  388   } /* puttrailer() */
  389   
  390   /*
  391    *      Wort word in lexikalisch sortierter Tabelle tab finden
  392    */
  393   
  394   static int binary(char *word, const char *tab[], const int n)
  395   {
  396     int low, high, mid, cond;
  397   
  398     low = 0;
  399     high = n - 1;
  400     while (low <= high) {
  401       mid = (low + high) / 2;
  402       cond = strcmp(word, tab[mid]);
  403       if (cond < 0)
  404         high = mid - 1;
  405       else if (cond > 0)
  406         low = mid + 1;
  407       else
  408         return(mid);
  409     }
  410     return(-1);
  411   
  412   } /* binary() */
  413   
  414   /*
  415    *      Naechstes Wort aus der Eingabe holen
  416    */
  417   
  418   static int getword(char *w, int lim)
  419   {
  420     int c, cc, t;
  421   
  422     c = getc(stdin);
  423     /* Kein Wort: Einzelzeichen! */
  424     if (type(c) != LETTER) {
  425       /* Newlineflag/Hashflag pruefen und ggfs. ruecksetzen */
  426       if (c == '\n') {
  427         newline = 1;
  428         hash = 0;
  429       }
  430       /* BUGFIX 1.02, klin, Mon Mar 11 13:01:18 2002
  431       else if (newline && !comment && !dquote && !squote && c == '#') {
  432       */
  433       else if ( !comment && !dquote && !squote && c == '#') {
  434         hash = 1;
  435       }
  436       else if (newline) {
  437         newline = 0;
  438       }
  439       /* Maskierung */
  440       if (c == '\\' && !comment) {
  441         cc = getc(stdin);
  442         *w++ = c;
  443         *w++ = cc;
  444         if (type(cc) == DIGIT) {
  445   	while (--lim > 2) {
  446   	  c = getc(stdin);
  447   	  t = type(c);
  448   	  if (t != DIGIT) {
  449   	    ungetc(c, stdin);
  450   	    break;
  451   	  }
  452   	  *w++ = c;
  453   	}
  454         }
  455         *w = '\0';
  456         return(MASK);
  457       }
  458       /* Einfache Anfuehrungszeichen */
  459       else if (c == '\'' && !comment && !dquote) {
  460         if (squote) {
  461   	squote = 0;
  462   	return(SEND);
  463         }
  464         else {
  465   	squote = 1;
  466   	return(SSTART);
  467         }
  468       }
  469       /* Doppelte Anfuehrungszeichen */
  470       else if (c == '\"' && !comment && !squote) {
  471         if (dquote) {
  472   	dquote = 0;
  473   	return(DEND);
  474         }
  475         else {
  476   	dquote = 1;
  477   	return(DSTART);
  478         }
  479       }
  480       /* Blockanfang */
  481       else if (c == '{' && !comment && !dquote && !squote) {
  482         *w++ = c;
  483         *w = '\0';
  484         return(BSTART);
  485       }
  486       /* Blockende */
  487       else if (c == '}' && !comment && !dquote && !squote) {
  488         *w++ = c;
  489         *w = '\0';
  490         return(BEND);
  491       }
  492       /* Kommentaranfang ? */
  493       else if (c == '/' && !comment && !dquote && !squote) {
  494   	if ((cc = getc(stdin)) == '*') {
  495   	  comment = 1;
  496   	  *w++ = c;
  497   	  *w++ = cc;
  498   	  *w = '\0';
  499   	  return(CSTART);
  500   	}
  501   	ungetc(cc, stdin);
  502       }
  503       /* Kommentarende ? */
  504       else if (c == '*' && comment && !dquote && !squote) {
  505         if ((cc = getc(stdin)) == '/') {
  506   	comment = 0;
  507   	*w++ = c;
  508   	*w++ = cc;
  509   	*w = '\0';
  510   	return(CEND);
  511         }
  512         ungetc(cc, stdin);
  513       }
  514       *w++ = c;
  515       *w = '\0';
  516       return(c);
  517     }
  518     /* Wort lesen */
  519     *w++ = c;
  520     while (--lim > 0) {
  521       c = getc(stdin);
  522       t = type(c);
  523       if (t != LETTER && t != DIGIT) {
  524         ungetc(c, stdin);
  525         break;
  526       }
  527       *w++ = c;
  528     }
  529     *w = '\0';
  530     return(LETTER);
  531   
  532   } /* getword() */
  533   
  534   /*
  535    *      Typ eines ASCII Zeichens liefern
  536    */
  537   
  538   static int type(int c)
  539   {
  540     if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_')
  541       return(LETTER);
  542     else if (c >= '0' && c <= '9')
  543       return(DIGIT);
  544     else
  545       return(c);
  546   
  547   } /* type() */
  548   
  549   /*
  550    *      Pruefen, ob naechstes Zeichen EOF
  551    */
  552   
  553   static int iseof(void)
  554   {
  555     int c;
  556   
  557     if ((c = getc(stdin)) == EOF)
  558       return(1);
  559     ungetc(c, stdin);
  560     return(0);
  561   
  562   } /* iseof() */


Erzeugt von c2html 1.02