C2HTML
Description
c2html permet de formatter rapidement des sources C en utilisant la syntaxe
du HTML pour publier des sources claires et lisibles sur le web.
Il réalise une coloration des mots-clés et des commentaires, et
conserve l'indentation du code.
Son fichier de configuration (c2html.conf) permet de définir les mots-clés.
c2html.conf
Deux options sont disponibles pour l'instant :
- dstdir=repertoire indique le repertoire de destination des sources
formattées. Par défaut, c'est le répertoire courant.
- keywords=mot1,mot2,mot3... pour définir les mots-clés
à colorer.
Syntaxe
c2html source.c page.htm
Todo
- Compteur de lignes
- Options (pas d'entete html, couleurs, ...)
New
27/12/2002: correction du bug concernant la coloration des directives du préprocesseur
Sources (Visual C++) - 200 lignes
/* Formattage d'un fichier source C en utilisant le langage HTML */ #include <stdio.h> #include <string.h> #include <stdlib.h> #define TAB " " #define COMMENT1 1 #define COMMENT2 2 #define PREPROCESS 3 int main(int argc, char **argv) { /* Fichiers */ FILE *src, *dst; /* Manipulation du contenu du fichier */ char buf[512]; char *p_deb, *p_fin, *p_save; /* Mots clés */ char keywords[20][10]; int word_count; int r=0, c, d, marge=20; short type=0, mot=0; /* Options */ char dstdir[128]; /*int ligne=2;*/ /* Syntaxe correcte ? */ if (argc<3) { printf("Syntaxe: c2html src.c dst.htm\n"); return -1; } /* Chargement de la configuration */ if ((src=fopen("c2html.conf", "rb"))==NULL) { printf("Impossible d'ouvrir le fichier de config\n"); return -1; } word_count=0; *dstdir=0x00; while (fgets(buf, 511, src)!=NULL) { if ((p_deb=strchr(buf, '\r'))!=NULL) *p_deb=0x00; if ((p_deb=strchr(buf, '='))!=NULL) { *p_deb=0x00; p_deb++; if (strcmp(buf, "dstdir")==0) { strcpy(dstdir, p_deb); c=strlen(dstdir); if (dstdir[c-1]!='/' && dstdir[c-1]!='\\') { dstdir[c++]='/'; dstdir[c]=0x00; } } else if (strcmp(buf, "keywords")==0) { while((p_save=strchr(p_deb, ','))!=NULL) { *p_save=0x00; strcpy(keywords[word_count++], p_deb); p_deb=p_save+1; } strcpy(keywords[word_count++], p_deb); } else printf("Option inconnue: %s\n", buf); } } fclose(src); printf("Loaded %d keywords\n", word_count); /* Ouverture de fichier source C */ if ((src=fopen(argv[1], "rb"))==NULL) { printf("Ouverture de %s impossible\n", argv[1]); return -1; } /* Ouverture du fichier html */ strcat(dstdir, argv[2]); if ((dst=fopen(dstdir, "wb"))==NULL) { printf("Ouverture de %s impossible\n", argv[2]); return -1; } /* Ecriture de l'entete */ fputs("<html><head><title>\r\n", dst); fprintf(dst, "Source: %s\n", argv[1]); fputs("</title></head>\r\n", dst); fputs("<!- Formatte par c2html ->\r\n", dst); fputs("<body><pre><font face=\"Courier New\" size=2>", dst); r=c=0; /* Boucle de lecture */ while ((r+=fread(buf+c, 1, 500-c, src))>c) { /* buf[r]='\0'; */ /* Dernière lecture dans le fichier */ if (r<500) { marge=0; /*printf("Theoriquement derniere lecture dans le fichier\n");*/ } /* Caractère par caractère */ for(p_deb=p_fin=buf; p_fin<buf+r-marge; p_fin++) { switch (*p_fin) { /* */ case '#': if (type) break; type=PREPROCESS; fwrite(p_deb, 1, p_fin-p_deb, dst); p_deb=p_fin; fputs("<FONT COLOR=blue>", dst); break; /* Probablement un commentaire */ case '/': if (type) break; if (*(p_fin+1)=='/') type=COMMENT1; else if (*(p_fin+1)=='*') type=COMMENT2; else break; fwrite(p_deb, 1, p_fin-p_deb, dst); p_deb=p_fin; fputs("<FONT COLOR=green>", dst); break; /* Fin de ligne */ case '\n': fwrite(p_deb, 1, p_fin-p_deb+1, dst); if (type==COMMENT1 || type==PREPROCESS) { type=0; fputs("</font>", dst); } /*fputs("<br>", dst);*/ /* Numéro de ligne */ /*fprintf(dst, "%d%s", ligne++, TAB);*/ p_deb=p_fin+1; mot=1; break; /* Tabulation */ case '\t': fwrite(p_deb, 1, p_fin-p_deb, dst); fputs(TAB, dst); p_deb=p_fin+1; /* Espace */ case ' ': if (type==PREPROCESS) { fwrite(p_deb, 1, p_fin-p_deb+1, dst); fputs("</font>", dst); p_deb=p_fin+1; type=0; } /* Parenthèse */ case '(': mot=1; break; /* Fin de commentaire */ case '*': if ((type==COMMENT2) && (*(p_fin+1)=='/')) { type=0; p_fin+=2; fwrite(p_deb, 1, p_fin-p_deb, dst); fputs("</font>", dst); p_deb=p_fin; p_fin--; } break; /* Sinon html croit que c'est une balise */ case '<': fwrite(p_deb, 1, p_fin-p_deb, dst); p_deb=p_fin+1; fputs("<", dst); break; /* Sinon html croit que c'est une balise */ case '>': fwrite(p_deb, 1, p_fin-p_deb, dst); p_deb=p_fin+1; fputs(">", dst); break; /* Peut être un mot clé */ default: if (type) mot=0; if (!mot) break; /* Teste tous les mots-clé */ for(p_save=p_fin, c=0; c<word_count && keywords[c][0]<=*p_fin; c++) { p_save=p_fin; /* Teste toutes les lettres du mot-clé*/ for(d=0; keywords[c][d]!='\0'; d++, p_save++) if (*p_save!=keywords[c][d]) goto not_keyword; if ((*p_save==' ') || (*p_save==',') || (*p_save==';') || (*p_save==':') || (*p_save=='(') || (*p_save=='\r') || (*p_save==')')) { fwrite(p_deb, 1, p_fin-p_deb, dst); fputs("<font color=blue>", dst); p_deb=keywords[c]; fwrite(p_deb, 1, strlen(p_deb), dst); fputs("</font>", dst); p_fin=p_save-1; p_deb=p_save; goto end_loop; } not_keyword: /* nothing */; } end_loop: mot=0; break; } /* switch */ } /* for */ fwrite(p_deb, 1, p_fin-p_deb, dst); buf[r]=0x00; strcpy(buf, p_fin); r=c=buf+r-p_fin; } /* while */ fputs("</font></pre></body></html>\r\n", dst); fseek(dst, 0, SEEK_END); printf("Taille de %s: %d bytes\n", argv[2], ftell(dst)); fclose(src); fclose(dst); return 0; }