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


Erzeugt von c2html 1.01