■ 「BinHex 4.0」のデコードサンプル
/*
* debh4.c : 「BinHex 4.0」のデコードサンプル
*
* Copyright (c) 2000 AOK.
*
* 2000.4.4 - 初版
* 2000.4.5 - 2版
*
* 使い方: DEBH4 入力ファイル名
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFLEN 64
typedef int BOOL;
#define TRUE 1
#define FALSE 0
const char *ench =
"!\"#$%&\'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
const char *sol = "(This file must be converted with BinHex 4.0)\n";
/* RLEのデコード */
int put_decode_char(char c, int mark, FILE *fp)
{
static char wc1, wc2;
int i, ret = 0;
switch (mark)
{
case 0:
if (c != 0x90)
putc(c, fp);
else
{
wc2 = wc1;
ret = 1;
}
break;
case 1:
if (c != 0x00)
for (i=0; i<c-1; i++)
putc(wc2, fp);
else
ret = 2;
break;
case 2:
if (c != 0x90)
{
putc(0x90, fp);
putc(c, fp);
}
else
ret = 3;
break;
case 3:
for (i=0; i<c; i++)
putc(0x90, fp);
break;
}
wc1 = c;
return ret;
}
/* 6-bit デコード */
int decode(char c, FILE *fp)
{
static int mode = 0, mark = 0;
static char wc = 0;
char dc, *t;
if (c != ':')
{
if ((t = strchr(ench, c)) == NULL)
return 0;
dc = (t - ench)/sizeof(char);
}
else
dc = 0;
switch (mode)
{
case 0:
wc = (dc << 2) & 0xFC;
break;
case 1:
wc |= (dc >> 4) & 0x03;
mark = put_decode_char(wc, mark, fp);
wc = (dc << 4) & 0xF0;
break;
case 2:
wc |= (dc >> 2) & 0x0F;
mark = put_decode_char(wc, mark, fp);
wc = (dc << 6) & 0xC0;
break;
case 3:
wc |= dc & 0x3F;
mark = put_decode_char(wc, mark, fp);
wc = 0;
break;
}
if (++mode > 3)
mode = 0;
return 1;
}
/* プログラムのエントリポイント */
int main(int argc, char *argv[])
{
FILE *fin, *fout, *fd;
char f1[FILENAME_MAX+1];
char f2[FILENAME_MAX+1];
char ch, n, s[BUFLEN+1], *dname, *p;
unsigned long fsize = 0, i;
BOOL found = FALSE;
int c;
/* コマンドライン引き数のチェック */
if (argc == 2)
{
strncpy(f1, argv[1], FILENAME_MAX);
strncpy(f2, argv[1], FILENAME_MAX);
}
else
{
puts("パラメータが足りません.\n\n使い方: DEBH4 入力ファイル名");
return 1;
}
/* 入力ファイルのオープン */
if ((fin = fopen(f1, "r+b")) == NULL)
{
perror("入力ファイルをオープン出来ません.\n");
return 1;
}
/* ヘッダを探す */
while (fgets(s, BUFLEN, fin) != NULL)
{
if (strcmp(s, sol) == 0)
{
puts(" * ヘッダを見つけました.");
found = TRUE;
break;
}
}
if (!found)
{
puts(" * ヘッダが見つかりません.");
fseek(fin, 0, SEEK_SET);
}
/* データの先頭まで読み飛ばす */
found = FALSE;
while ((c = getc(fin)) != EOF)
{
ch = (char)c;
if (ch == ':')
{
puts(" * デコード開始位置を見つけました.");
found = TRUE;
break;
}
}
if (!found)
{
puts(" * デコード開始位置が見つかりません.");
fclose(fin);
return 1;
}
/* 6-bit デコード */
fout = tmpfile();
while ((c = getc(fin)) != EOF)
{
ch = (char)c;
decode(ch, fout);
if (ch == ':')
break;
}
fclose(fin);
/* テンポラリファイルの先頭へ移動 */
fseek(fout, 0, SEEK_SET);
fread(&n, sizeof(char), 1, fout);
dname = malloc((n+1)*sizeof(char));
fread(dname, sizeof(char), n+1, fout);
fseek(fout, 10, SEEK_CUR);
for (i=0; i<sizeof(long); i++)
{
ch = (char)getc(fout);
fsize |= ch << (24-i*8);
}
/* 出力ファイル名作成 */
if ((p = strrchr(f2, '\\')) != NULL)
strcpy(p+1, dname);
else
strcpy(f2, dname);
free(dname);
printf(" * 出力ファイルネーム -> %s\n", f2);
printf(" * 出力ファイルサイズ -> %ld バイト\n", fsize);
/* データフォークのみ取り出す */
fseek(fout, 6, SEEK_CUR);
if ((fd = fopen(f2, "w+b")) != NULL)
{
for (i=0; i<fsize; i++)
putc((char)getc(fout), fd);
fclose(fd);
puts(" * デコードに成功しました.");
}
else
{
perror("出力ファイルが作成できません.\n");
puts(" * デコードに失敗しました.");
}
fclose(fout);
return 0;
}