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>"", sccol); 277 else 278 fprintf(stdout, """); 279 break; 280 case DEND: /* Stringende */ 281 if (cflag) 282 fprintf(stdout, ""</FONT>"); 283 else 284 fprintf(stdout, """); 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, """); 303 break; 304 case '&': /* HTML-Sonderzeichen -> Entity */ 305 fprintf(stdout, "&"); 306 break; 307 case '<': /* HTML-Sonderzeichen -> Entity */ 308 fprintf(stdout, "<"); 309 break; 310 case '>': /* HTML-Sonderzeichen -> Entity */ 311 fprintf(stdout, ">"); 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%%\"> </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%%\"> </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 |