Last Update: Jan.10,2001

C Source Library

「LSI C-86 Ver.3.30c 試食版」を使用しています。

■ 「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;
}