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>"", sccol); 273 else 274 fprintf(stdout, """); 275 break; 276 case DEND: /* Stringende */ 277 if (cflag) 278 fprintf(stdout, ""</FONT>"); 279 else 280 fprintf(stdout, """); 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, """); 299 break; 300 case '&': /* HTML-Sonderzeichen -> Entity */ 301 fprintf(stdout, "&"); 302 break; 303 case '<': /* HTML-Sonderzeichen -> Entity */ 304 fprintf(stdout, "<"); 305 break; 306 case '>': /* HTML-Sonderzeichen -> Entity */ 307 fprintf(stdout, ">"); 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%%\"> </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%%\"> </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 |