■ CソースをHTML化するサンプル(旧版)→新版はこちら
/*
* c2html.c : CソースをHTML化する
*
* Copyright (c) 2000, 2001 AOK.
*
* 2000/04/01 - 初版
* 2001/10/03 - 10版
*
* 使い方: C2HTML ファイル名
*
* 出力されるHTMLファイル名は内部で作成される(.c → .htm)
* 同名のファイルがあると上書きされてしまう(^-^;)
*
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/* HTMLのカラーを指定 */
const char *color_keyword = "blue";
const char *color_comment = "red";
const char *color_string = "teal";
#ifndef LSI_C /* Borland C++ 5.5 */
#include <mbctype.h>
#include <mbstring.h>
#define chkctype(x, y) _mbbtype(x, y)
#define CT_ANK _MBC_SINGLE
#define CT_KJ1 _MBC_LEAD
#define CT_KJ2 _MBC_TRAIL
#define CT_ILGL _MBC_ILLEGAL
#else /* LSI C-86 */
#include <jctype.h>
#endif
typedef int (*FPTR)(const void*, const void*);
#define BUFLEN 127
#define TABWIDTH 4
#define AL_NON 0
#define AL_COM 1
#define AL_STR 2
#define AL_CHR 3
#define NUM_OF_ARR(x) (sizeof(x)/sizeof(x[0]))
char key[][10] = { /* 昇順に並べておく */
"#define","#elif","#else","#endif","#error","#if","#ifdef",
"#ifndef","#import","#include","#line","#pragma","#undef",
"auto","break","case","char","const","continue","default",
"do","double","else","enum","extern","float","for","goto",
"if","int","long","register","return","short","signed",
"sizeof","static","struct","switch","typedef","union",
"unsigned","void","volatile","while" };
/* 拡張子の付け替え */
int change_ext(char *fname)
{
char *p;
int len;
len = strlen(fname);
p = strrchr(fname, '.');
if (len >= 3 && len <= FILENAME_MAX-2 && p != NULL)
{
if (strcmpi(p, ".c") == 0 || strcmpi(p, ".h") == 0)
strcpy(p, ".htm");
else
{
*fname = '\0';
puts("入力ファイルはCソースではありません.");
return 0;
}
}
else
{
*fname = '\0';
puts("拡張子の付け替えが出来ません.");
return 0;
}
return 1;
}
/* 予約語かどうか(2分探索) */
int check_keyword(char *c)
{
return (bsearch(c, key, NUM_OF_ARR(key), sizeof(key[0]), (FPTR)strcmp) != NULL);
}
/* バッファの書き出し */
void empty_buffer(char buf[], int align, FILE *fp)
{
if (buf[0]=='\0') return;
if (align == AL_NON && check_keyword(buf))
{
fprintf(fp, "<font color=\"%s\">", color_keyword);
fputs(buf, fp);
fputs("</font>", fp);
}
else
fputs(buf, fp);
buf[0] = '\0';
}
/* バッファへ1文字入れる */
void input_buffer(char buf[], char c)
{
int len;
len = strlen(buf);
buf[len] = c;
buf[len+1] = '\0';
}
/* タブをスペースに変換 */
void fill_space(int n, FILE *fp)
{
int num, i;
num = TABWIDTH - n % TABWIDTH;
for (i = 0; i < num; i++)
putc(' ', fp);
}
/* 変換の本体 */
void convert(FILE *fin, FILE *fout)
{
int n, len, mode = 0;
char ch;
char buf[BUFLEN+1];
int align = AL_NON, col = 0;
buf[0] = '\0';
while ((n = getc(fin)) != EOF)
{
ch = (char)n;
mode = chkctype(ch, mode);
if (mode == CT_ANK || mode == CT_ILGL)
{
switch (ch)
{
case '\"':
switch (align)
{
case AL_NON:
empty_buffer(buf, align, fout);
fprintf(fout, "<font color=\"%s\">", color_string);
fputs(""", fout);
align = AL_STR;
break;
case AL_STR:
if (strcmp(buf, "\\") != 0)
{
empty_buffer(buf, align, fout);
fputs(""", fout);
fputs("</font>", fout);
align = AL_NON;
}
else
{
empty_buffer(buf, align, fout);
fputs(""", fout);
}
break;
default:
empty_buffer(buf, align, fout);
fputs(""", fout);
break;
}
break;
case '\'':
switch (align)
{
case AL_NON:
empty_buffer(buf, align, fout);
fprintf(fout, "<font color=\"%s\">", color_string);
fputs("\'", fout);
align = AL_CHR;
break;
case AL_CHR:
if (strcmp(buf, "\\") != 0)
{
empty_buffer(buf, align, fout);
fputs("\'", fout);
fputs("</font>", fout);
align = AL_NON;
}
else
{
empty_buffer(buf, align, fout);
fputs("\'", fout);
}
break;
default:
empty_buffer(buf, align, fout);
fputs("\'", fout);
break;
}
break;
case '/':
if (align == AL_COM && strcmp(buf, "*") == 0)
{
align = AL_NON;
empty_buffer(buf, align, fout);
putc(ch, fout);
fputs("</font>", fout);
}
else
{
empty_buffer(buf, align, fout);
input_buffer(buf, ch);
}
break;
case '*':
if (align == AL_NON && strcmp(buf, "/") == 0)
{
align = AL_COM;
fprintf(fout, "<font color=\"%s\">", color_comment);
empty_buffer(buf, align, fout);
putc(ch, fout);
}
else
{
empty_buffer(buf, align, fout);
input_buffer(buf, ch);
}
break;
case '\\':
if (strcmp(buf, "\\") == 0)
{
empty_buffer(buf, align, fout);
putc(ch, fout);
}
else
{
empty_buffer(buf, align, fout);
input_buffer(buf, ch);
}
break;
case '\n':
col = -1;
case '\t': case ' ':
case '+': case '-': case '%': case '|': case '=': case '!':
case '(': case ')': case '{': case '}': case '[': case ']':
case ',': case ':': case ';': case '&': case '>': case '<':
if (buf[0] == '*')
{
putc('*', fout);
strcpy(buf, buf+1);
}
else if (buf[0] == '/')
{
putc('/', fout);
strcpy(buf, buf+1);
}
empty_buffer(buf, align, fout);
if (ch == '\t')
{
fill_space(col, fout);
col = -1;
}
else if (ch == '&')
fputs("&", fout);
else if (ch == '>')
fputs(">", fout);
else if (ch == '<')
fputs("<", fout);
else
putc(ch, fout);
break;
default:
len = strlen(buf);
if (len > BUFLEN-1)
empty_buffer(buf, align, fout);
input_buffer(buf, ch);
break;
}
}
else if (mode == CT_KJ1 || mode == CT_KJ2)
{
empty_buffer(buf, align, fout);
putc(ch, fout);
}
col++;
}
/* バッファに溜まっている文字列の処理 */
empty_buffer(buf, align, fout);
}
/* プログラムのエントリポイント */
int main(int argc, char *argv[])
{
char fname[FILENAME_MAX+1];
FILE *fin, *fout;
/* コマンドライン引き数のチェック */
if (argc >= 2)
{
strncpy(fname, argv[1], FILENAME_MAX);
fname[FILENAME_MAX] = '\0';
}
else
{
puts("パラメータが足りません.\n\n使い方: C2HTML ファイル名");
exit(EXIT_FAILURE);
}
/* 入出力ファイルをオープン */
printf("入力ファイル名: %s\n", fname);
if ((fin = fopen(fname, "r")) == NULL)
{
perror("入力ファイルをオープン出来ません.\n");
exit(EXIT_FAILURE);
}
if (change_ext(fname) == 0) /* 拡張子の付け替え */
{
fclose(fin);
exit(EXIT_FAILURE);
}
printf("出力ファイル名: %s\n", fname);
if ((fout = fopen(fname, "w")) == NULL)
{
perror("出力ファイルをオープン出来ません.\n");
fclose(fin);
exit(EXIT_FAILURE);
}
/* 変換実行 */
fputs("<html>\n<head>\n", fout);
fputs("<meta http-equiv=\"Content-Type\" content=\"text/html;charset=Shift_JIS\">\n", fout);
fputs("<meta name=\"GENERATOR\" content=\"C2HTML (c)2000,2001 AOK\">\n", fout);
fputs("</head>\n<body>\n<pre>", fout);
convert(fin, fout); /* 変換の本体 */
fputs("</pre>\n</body>\n</html>", fout);
/* 入出力ファイルをクローズ */
fclose(fin);
fclose(fout);
puts("\n*** 変換に成功しました.");
return 0;
}