精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>C/C++>>编码解码>>HQX解码

主题:HQX解码
发信人: wenbobo()
整理人: wenbobo(2002-12-21 23:57:45), 站内信件
下载了个网页减肥的东西SpaceAgent5.0,.hqx,winrar居然不能识别,又不想装winzip,于是找了个unhqx,85年的unix陈酿,vc下一大排警告错误,改了下贴出来。看得出hqx的编码效率低下,难怪快绝种了,想不到还有网站用,估计是为了躲避商业软件联盟BSA的追杀(M$不支持这种格式)。


/*
 * Generic source code to un-HQX a file ... from Unix to windows
 * 
 * 
 * xbin -- unpack BinHex format file into suitable
 * format for downloading with macput
 *
 *
 * (c) 1984 Dave Johnson, Brown University Computer Science
 * (c) 2002 Bowen, Lite-On Technology Corporation
 *
 * may be used but not sold without permission
 *
 *
 * created ddj 12/16/84
 * revised ddj 03/10/85 -- version 4.0 compatibility, other minor mods
 * revised ddj 03/11/85 -- strip LOCKED bit from m_flags
 * revised ahm 03/12/85 -- System V compatibility
 * revised dba 03/16/85 -- (Darin Adler, TMQ Software)  4.0 EOF fixed,
 *             4.0 checksum added
 * revised ddj 03/17/85 -- extend new features to older formats: -l, stdin
 * revised ddj 03/24/85 -- check for filename truncation, allow multiple files
 * revised ddj 03/26/85 -- fixed USG botches, many problems w/multiple files
 * revised jcb 03/30/85 -- (Jim Budler, amdcad!jimb), revised for compatibility
 *             with 16-bit int machines
 * revised dl  06/16/85 -- (Dan LaLiberte, liberte@uiucdcs) character
 *             translation speedup
 * revised ddj 09/30/85 -- fixed problem with run of RUNCHAR
 * revised wb  12/21/02 -- fixed some problems, revised for compatibility with ANSI C lib
 * revised wb  12/21/02 -- change to new C style
 */



const char* version = "un-HQX Version 2.4, 12/21/2002";

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <process.h>

#ifndef DIRSIZ
    #define DIRSIZ 260
#endif

#ifdef MAXNAMLEN    /* 4.2 BSD */
#define FNAMELEN MAXNAMLEN
#else
#define FNAMELEN DIRSIZ
#endif

#ifdef BSD
#include <sys/time.h>
#include <sys/timeb.h>
#define search_last rindex
extern char *rindex();
#else
#include <time.h>
//extern long timezone;
#define search_last strrchr
//extern char *strrchr();
#endif

/* Mac time of 00:00:00 GMT, Jan 1, 1970 */
#define TIMEDIFF 0x7c25b080

#define DATABYTES 128

#define BYTEMASK 0xff
#define BYTEBIT 0x100
#define WORDMASK 0xffff
#define WORDBIT 0x10000

#define NAMEBYTES 63
#define H_NLENOFF 1
#define H_NAMEOFF 2

/* 65 <-> 80 is the FInfo structure */
#define H_TYPEOFF 65
#define H_AUTHOFF 69
#define H_FLAGOFF 73

#define H_LOCKOFF 81
#define H_DLENOFF 83
#define H_RLENOFF 87
#define H_CTIMOFF 91
#define H_MTIMOFF 95

#define H_OLD_DLENOFF 81
#define H_OLD_RLENOFF 85

#define F_BUNDLE 0x2000
#define F_LOCKED 0x8000

struct macheader {
    char m_name[NAMEBYTES+1];
    char m_type[4];
    char m_author[4];
    short m_flags;
    long m_datalen;
    long m_rsrclen;
    long m_createtime;
    long m_modifytime;
} mh;

struct filenames {
    char f_info[256];
    char f_data[256];
    char f_rsrc[256];
} files;

int pre_beta;   /* options */
int listmode;
int verbose;

int compressed; /* state variables */
int qformat;
FILE *ifp;

char usage[] = "usage: \"xbin [-v] [-l] [-o] [-n name] [-] filename\"\n";
//============================================================================
void q_init();
setup_files( char *filename, char *macname );
void print_header();
void process_forks();
void forge_info();
int find_header();
void do_q_header(char *macname);
void do_o_header(char* macname, char* filename );
void do_q_fork(char* fname, long len);
void do_o_forks();
void put2(char* bp, short value);
void put4( char* bp, long value);
int getq();
int getq_nocrc();
int getqbuf( char* buf, int n );
void comp_q_crc( unsigned int c );
void verify_crc(unsigned int calc_crc, unsigned int file_crc);
int getq_raw();
int get6bits();
int comp_to_bin(char ibuf[], FILE* outf);
int hex_to_bin( char ibuf[], FILE* outf);
int hexit( int c );
//============================================================================
int main( int ac, char* av[] )
{
    char *filename = "", *macname = "";

    printf( "%s\n", version );
    ac--; av++;
    while (ac) 
    {
        if (av[0][0] == '-') 
        {
            switch (av[0][1]) 
            {
                case '\0':
                    filename = "-";
                    break;
                case 'v':
                    verbose++;
                    break;
                case 'l':
                    listmode++;
                        break;
                case 'o':
                    pre_beta++;
                    break;
                case 'n':
                    if (ac > 1) 
                    {
                        ac--; 
                        av++;
                        macname = av[0];
                        filename = "";
                        break;
                    }
                    else
                        goto bad_usage;
                default:
                        goto bad_usage;
            }
        }
        else
            filename = av[0];
        if (filename[0] != '\0') 
        {
            setup_files(filename, macname);
            if (listmode) 
                print_header();
            else 
            {
                process_forks();
                /* now that we know the size of the forks */
                forge_info();
            }
            if (ifp != stdin)
                fclose(ifp);
            macname = "";
            ifp = NULL;         /* reset state */
            qformat = 0;
            compressed = 0;
        }
        ac--; av++;
    }
    if (*filename == '\0') 
    {
        bad_usage:
        fprintf(stderr, usage);
        exit(1);
    }
}

char *extensions[] = 
{
    ".hqx",
    ".hcx",
    ".hex",
    "",
    NULL
};

setup_files(
    char *filename,     /* input file name -- extension optional */
    char *macname      /* name to use on the mac side of things */
)
{
    char namebuf[256], *np;
    char **ep;
    int n;
    struct stat stbuf = {0};
    long curtime;

    if (filename[0] == '-')
    {
        ifp = stdin;
        filename = "stdin";
    }
    else 
    {
        /* find input file and open it */
        for (ep = extensions; *ep != NULL; ep++) 
        {
            sprintf(namebuf, "%s%s", filename, *ep);
            if (stat(namebuf, &stbuf) == 0)
                break;
        }
        if (*ep == NULL) 
        {
            perror(namebuf);
            exit(-1);
        }
        ifp = fopen(namebuf, "r");
        if (ifp == NULL) 
        {
            perror(namebuf);
            exit(-1);
        }
    }
    if (ifp == stdin) 
    {
        curtime = time(0);
        mh.m_createtime = curtime;
        mh.m_modifytime = curtime;
    }
    else 
    {
        mh.m_createtime = stbuf.st_mtime;
        mh.m_modifytime = stbuf.st_mtime;
    }
    if (listmode || verbose) 
    {
        fprintf( stderr, "%s %s%s", listmode ? "\nListing" : "Converting",
            namebuf, listmode ? ":\n" : " " );
    }

    qformat = find_header(); /* eat mailer header &cetera, intuit format */

    if (qformat)
        do_q_header(macname);
    else
        do_o_header(macname, filename);

    /* make sure host file name doesn't get truncated beyond recognition */
    n = strlen(mh.m_name);
    if (n > FNAMELEN - 2)
        n = FNAMELEN - 2;
    strncpy(namebuf, mh.m_name, n);
    namebuf[n] = '\0';

    /* get rid of troublesome characters */
    for (np = namebuf; *np; np++)
        if (*np == ' ' || *np == '/')
            *np = '_';

    sprintf(files.f_data, "%s.data", namebuf);
    sprintf(files.f_rsrc, "%s.rsrc", namebuf);
    sprintf(files.f_info, "%s.info", namebuf);
    if (verbose)
        fprintf(stderr, "==> %s.{info,data,rsrc}\n", namebuf);
}

/* print out header information in human-readable format */
void print_header()
{
    char *ctime();

    printf("macname: %s\n", mh.m_name);
    printf("filetype: %.4s, ", mh.m_type);
    printf("author: %.4s, ", mh.m_author);
    printf("flags: 0x%x\n", mh.m_flags);
    if (qformat) 
    {
        printf("data length: %ld, ", mh.m_datalen);
        printf("rsrc length: %ld\n", mh.m_rsrclen);
    }
    if (!pre_beta) 
        printf("create time: %s", ctime(&mh.m_createtime));
}

void process_forks()
{
    if (qformat) 
    {
        /* read data and resource forks of .hqx file */
        do_q_fork(files.f_data, mh.m_datalen);
        do_q_fork(files.f_rsrc, mh.m_rsrclen);
    }
    else
        do_o_forks();
}

/* write out .info file from information in the mh structure */
void forge_info()
{
    static char buf[DATABYTES];
    char *np;
    FILE *fp;
    int n;
    long tdiff;
    struct tm *tp;
#ifdef BSD
    struct timeb tbuf;
#else
    long bs;
#endif

    for (np = mh.m_name; *np; np++)
        if (*np == '_') *np = ' ';

    buf[H_NLENOFF] = n = np - mh.m_name;
    strncpy(buf + H_NAMEOFF, mh.m_name, n);
    strncpy(buf + H_TYPEOFF, mh.m_type, 4);
    strncpy(buf + H_AUTHOFF, mh.m_author, 4);
    put2(buf + H_FLAGOFF, mh.m_flags & ~F_LOCKED);
    if (pre_beta) 
    {
        put4(buf + H_OLD_DLENOFF, mh.m_datalen);
        put4(buf + H_OLD_RLENOFF, mh.m_rsrclen);
    }
    else 
    {
        put4(buf + H_DLENOFF, mh.m_datalen);
        put4(buf + H_RLENOFF, mh.m_rsrclen);

        /* convert unix file time to mac time format */
#ifdef BSD
        ftime(&tbuf);
        tp = localtime(&tbuf.time);
        tdiff = TIMEDIFF - tbuf.timezone * 60;
        if (tp->tm_isdst)
            tdiff += 60 * 60;
#else
        /* I hope this is right! -andy */
        time(&bs);
        tp = localtime(&bs);
        tdiff = TIMEDIFF - timezone;
        if (tp->tm_isdst)
            tdiff += 60 * 60;
#endif
        put4(buf + H_CTIMOFF, mh.m_createtime + tdiff);
        put4(buf + H_MTIMOFF, mh.m_modifytime + tdiff);
    }
    fp = fopen(files.f_info, "w");
    if (fp == NULL) 
    {
        perror("info file");
        exit(-1);
    }
    fwrite(buf, 1, DATABYTES, fp);
    fclose(fp);
}

/* eat characters until header detected, return which format */
find_header()
{
    int c, at_bol;
    char ibuf[BUFSIZ];

    /* look for "(This file ...)" line */
    while (fgets(ibuf, BUFSIZ, ifp) != NULL) 
    {
        if (strncmp(ibuf, "(This file", 10) == 0)
            break;
    }
    at_bol = 1;
    while ((c = getc(ifp)) != EOF) 
    {
        switch (c) 
        {
            case '\n':
            case '\r':
                at_bol = 1;
                break;
            case ':':
                if (at_bol)     /* q format */
                    return 1;
                break;
            case '#':
                if (at_bol) 
                {   /* old format */
                    ungetc(c, ifp);
                    return 0;
                }
                break;
            default:
                at_bol = 0;
                break;
        }
    }

    fprintf(stderr, "unexpected EOF\n");
    exit(2);
    /* NOTREACHED */
}

static unsigned int crc;

short get2q();
long get4q();

/* read header of .hqx file */
void do_q_header(char *macname)
{
    char namebuf[256];          /* big enough for both att & bsd */
    int n;
    unsigned int calc_crc=0, file_crc=0;

    crc = 0;            /* compute a crc for the header */
    q_init();               /* reset static variables */

    n = getq();             /* namelength */
    n++;                /* must read trailing null also */
    getqbuf(namebuf, n);        /* read name */
    if (macname[0] == '\0')
        macname = namebuf;

    n = strlen(macname);
    if (n > NAMEBYTES)
        n = NAMEBYTES;
    strncpy(mh.m_name, macname, n);
    mh.m_name[n] = '\0';

    getqbuf(mh.m_type, 4);
    getqbuf(mh.m_author, 4);
    mh.m_flags = get2q();
    mh.m_datalen = get4q();
    mh.m_rsrclen = get4q();

    comp_q_crc(0);
    comp_q_crc(0);
    calc_crc = crc;
    file_crc = get2q();
    verify_crc(calc_crc, file_crc);
}

void do_q_fork(char* fname, long len)
{
    FILE *outf;
    int c, i;
    unsigned int calc_crc, file_crc;

    outf = fopen(fname, "w");
    if (outf == NULL) 
    {
        perror(fname);
        exit(-1);
    }

    crc = 0;    /* compute a crc for a fork */

    if (len)
        for (i = 0; i < len; i++)
{
if ((c = getq()) == EOF)
{
fprintf(stderr, "unexpected EOF\n");
exit(2);
}
putc(c, outf);
}

comp_q_crc(0);
comp_q_crc(0);
calc_crc = crc;
file_crc = get2q();
verify_crc(calc_crc, file_crc);
fclose(outf);
}

/* verify_crc(); -- check if crc's check out */
void verify_crc(unsigned int calc_crc, unsigned int file_crc)
{
calc_crc &= WORDMASK;
file_crc &= WORDMASK;

if (calc_crc != file_crc)
{
fprintf(stderr, "CRC error\n---------\n");
fprintf(stderr, "CRC in file:\t0x%x\n", file_crc);
fprintf(stderr, "calculated CRC:\t0x%x\n", calc_crc);
exit(3);
}
}

static int EndOfFile;
static char obuf[3];
static char *op, *oend;

/* initialize static variables for q format input */
void q_init()
{
EndOfFile = 0;
op = obuf;
oend = obuf + sizeof obuf;
}

/* get2q(); q format -- read 2 bytes from input, return short */
short get2q()
{
int c;
short value = 0;

c = getq();
value = (c & BYTEMASK) << 8;
c = getq();
value |= (c & BYTEMASK);

return value;
}

/* get4q(); q format -- read 4 bytes from input, return long */
long get4q()
{
int c, i;
long value = 0L;

for (i = 0; i < 4; i++)
{
c = getq();
value <<= 8;
value |= (c & BYTEMASK);
}
return value;
}

/* getqbuf(); q format -- read n characters from input into buf */
/* All or nothing -- no partial buffer allowed */
int getqbuf( char* buf, int n )
{
int c, i;

for (i = 0; i < n; i++)
{
if ((c = getq()) == EOF)
return EOF;
*buf++ = c;
}
return 0;
}

#define RUNCHAR 0x90

/* q format -- return one byte per call, keeping track of run codes */
int getq()
{
int c;

if ((c = getq_nocrc()) == EOF)
return EOF;
comp_q_crc((unsigned)c);
return c;
}

int getq_nocrc()
{
static int rep, lastc;
int c;

if (rep)
{
rep--;
return lastc;
}
if ((c = getq_raw()) == EOF)
return EOF;

if (c == RUNCHAR)
{
if ((rep = getq_raw()) == EOF)
return EOF;
if (rep != 0)
{
/* already returned one, about to return another */
rep -= 2;
return lastc;
}
else
{
lastc = RUNCHAR;
return RUNCHAR;
}
}
else
{
lastc = c;
return c;
}
}

/* q format -- return next 8 bits from file without interpreting run codes */
int getq_raw()
{
char ibuf[4];
char *ip = ibuf, *iend = ibuf + sizeof ibuf;
int c;

if (op == obuf)
{
for (ip = ibuf; ip < iend; ip++)
{
if ((c = get6bits()) == EOF)
if (ip <= &ibuf[1])
return EOF;
else if (ip == &ibuf[2])
EndOfFile = 1;
else
EndOfFile = 2;
*ip = c;
}
obuf[0] = (ibuf[0] << 2 | ibuf[1] >> 4);
        obuf[1] = (ibuf[1] << 4 | ibuf[2] >> 2);
        obuf[2] = (ibuf[2] << 6 | ibuf[3]);
}
if ((EndOfFile) & (op >= &obuf[EndOfFile]))
        return EOF;
    c = *op++;
    if (op >= oend)
        op = obuf;
    return (c & BYTEMASK);
}

/*
char tr[] = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
         0 123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
         0            1           2           3 
trlookup is used to translate by direct lookup.  The input character
is an index into trlookup.  If the result is 0xFF, a bad char has been read.
Added by:  Dan LaLiberte, [email protected], ihnp4!uiucdcs!liberte
*/
char trlookup[83] = {   '\xFF', '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06',
            '\x07', '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\xFF', '\xFF',
            '\x0D', '\x0E', '\x0F', '\x10', '\x11', '\x12', '\x13', '\xFF',
            '\x14', '\x15', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF',
            '\x16', '\x17', '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D',
            '\x1E', '\x1F', '\x20', '\x21', '\x22', '\x23', '\x24', '\xFF',
            '\x25', '\x26', '\x27', '\x28', '\x29', '\x2A', '\x2B', '\xFF',
            '\x2C', '\x2D', '\x2E', '\x2F', '\xFF', '\xFF', '\xFF', '\xFF',
            '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\xFF',
            '\x37', '\x38', '\x39', '\x3A', '\x3B', '\x3C', '\xFF', '\xFF',
            '\x3D', '\x3E', '\x3F' };

/* q format -- decode one byte into 6 bit binary */
int get6bits()
{
    int c;
    int tc;

    while (1) {
        c = getc(ifp);
        switch (c) {
        case '\n':
        case '\r':
            continue;
        case ':':
        case EOF:
            return EOF;
        default:
            tc = ((c-' ') < 83) ? trlookup[c-' '] : 0xff;
/* fprintf(stderr, "c = '%c' tc = %4x\n", c, tc); */
if (tc != 0xff)
return (tc);
fprintf(stderr, "bad char: '%c'\n", c);
return EOF;
}
}
}


#define CRCCONSTANT 0x1021

void comp_q_crc( unsigned int c )
{
int i;
unsigned long temp = crc;

for (i=0; i<8; i++)
{
c <<= 1;
if ((temp <<= 1) & WORDBIT)
temp = (temp & WORDMASK) ^ CRCCONSTANT;
temp ^= (c >> 8);
        c &= BYTEMASK;
    }
    crc = temp;
}

/* old format -- process .hex and .hcx files */
void do_o_header(char* macname, char* filename )
{
    char namebuf[256];          /* big enough for both att & bsd */
    char ibuf[BUFSIZ];
    int n;

    /* set up name for output files */
    if (macname[0] == '\0') 
    {
        strcpy(namebuf, filename);

        /* strip directories */
        macname = search_last(namebuf, '/');
        if (macname == NULL)
            macname = namebuf;
        else
            macname++;

        /* strip extension */
        n = strlen(macname);
        if (n > 4) 
        {
            n -= 4;
            if (macname[n] == '.' && macname[n+1] == 'h'
                        && macname[n+3] == 'x')
                macname[n] = '\0';
        }
    }
    n = strlen(macname);
    if (n > NAMEBYTES)
        n = NAMEBYTES;
    strncpy(mh.m_name, macname, n);
    mh.m_name[n] = '\0';

    /* read "#TYPEAUTH$flag"  line */
    if (fgets(ibuf, BUFSIZ, ifp) == NULL) 
    {
        fprintf(stderr, "unexpected EOF\n");
        exit(2);
    }
    n = strlen(ibuf);
    if (n >= 7 && ibuf[0] == '#' && ibuf[n-6] == '$') 
    {
        if (n >= 11)
            strncpy(mh.m_type, &ibuf[1], 4);
        if (n >= 15)
            strncpy(mh.m_author, &ibuf[5], 4);
        sscanf(&ibuf[n-5], "%4hx", &mh.m_flags);
    }
}

void do_o_forks()
{
    char ibuf[BUFSIZ];
    int forks = 0, found_crc = 0;
    unsigned int calc_crc=0, file_crc=0;
    extern long make_file();


    crc = 0;    /* calculate a crc for both forks */

    /* create empty files ahead of time */
    close(creat(files.f_data, 0666));
    close(creat(files.f_rsrc, 0666));

    while (!found_crc && fgets(ibuf, BUFSIZ, ifp) != NULL) 
    {
        if (forks == 0 && strncmp(ibuf, "***COMPRESSED", 13) == 0) 
        {
            compressed++;
            continue;
        }
        if (strncmp(ibuf, "***DATA", 7) == 0) 
        {
            mh.m_datalen = make_file(files.f_data, compressed);
            forks++;
            continue;
        }
        if (strncmp(ibuf, "***RESOURCE", 11) == 0) 
        {
            mh.m_rsrclen = make_file(files.f_rsrc, compressed);
            forks++;
            continue;
        }
        if (compressed && strncmp(ibuf, "***CRC:", 7) == 0) 
        {
            found_crc++;
            calc_crc = crc;
            sscanf(&ibuf[7], "%x", &file_crc);
            break;
        }
        if (!compressed && strncmp(ibuf, "***CHECKSUM:", 12) == 0) 
        {
            found_crc++;
            calc_crc = crc & BYTEMASK;
            sscanf(&ibuf[12], "%x", &file_crc);
            file_crc &= BYTEMASK;
            break;
        }
    }

    if (found_crc)
        verify_crc(calc_crc, file_crc);
    else 
    {
        fprintf(stderr, "missing CRC\n");
        exit(3);
    }
}

long make_file(char* fname, int compressed)
{
    char ibuf[BUFSIZ];
    FILE *outf;
    long nbytes = 0L;

    outf = fopen(fname, "w");
    if (outf == NULL) 
    {
        perror(fname);
        exit(-1);
    }

    while (fgets(ibuf, BUFSIZ, ifp) != NULL) 
    {
        if (strncmp(ibuf, "***END", 6) == 0)
            break;
        if (compressed)
            nbytes += comp_to_bin(ibuf, outf);
        else
            nbytes += hex_to_bin(ibuf, outf);
    }

    fclose(outf);
    return nbytes;
}

comp_c_crc(unsigned char c)
{
    crc = (crc + c) & WORDMASK;
    crc = ((crc << 3) & WORDMASK) | (crc >> 13);
}

comp_e_crc(unsigned char c)
{
    crc += c;
}

#define SIXB(c) (((c)-0x20) & 0x3f)

int comp_to_bin(char ibuf[], FILE* outf)
{
    char obuf[BUFSIZ];
    char *ip = ibuf;
    char *op = obuf;
    int n, outcount;
    int numread, incount;

    numread = strlen(ibuf);
    ip[numread-1] = ' ';        /* zap out the newline */
    outcount = (SIXB(ip[0]) << 2) | (SIXB(ip[1]) >> 4);
    incount = ((outcount / 3) + 1) * 4;
    for (n = numread; n < incount; n++) /* restore lost spaces */
ibuf[n] = ' ';

n = 0;
while (n <= outcount)
{
*op++ = SIXB(ip[0]) << 2 | SIXB(ip[1]) >> 4;
        *op++ = SIXB(ip[1]) << 4 | SIXB(ip[2]) >> 2;
        *op++ = SIXB(ip[2]) << 6 | SIXB(ip[3]);
ip += 4;
n += 3;
}

for (n=1; n <= outcount; n++)
comp_c_crc((unsigned)obuf[n]);

fwrite(obuf+1, 1, outcount, outf);
return outcount;
}

int hex_to_bin( char ibuf[], FILE* outf)
{
char *ip = ibuf;
int n, outcount;
int c;

n = strlen(ibuf) - 1;
outcount = n / 2;
for (n = 0; n < outcount; n++)
{
c = hexit(*ip++);
comp_e_crc((unsigned)(c = (c << 4) | hexit(*ip++)));
fputc(c, outf);
}
return outcount;
}

int hexit( int c )
{
if ('0' <= c && c <= '9')
return c - '0';
if ('A' <= c && c <= 'F')
return c - 'A' + 10;

fprintf(stderr, "illegal hex digit: %c", c);
exit(4);
/* NOTREACHED */
}

void put2(char* bp, short value)
{
*bp++ = (value >> 8) & BYTEMASK;
    *bp++ = value & BYTEMASK;
}

void put4( char* bp, long value)
{
    int i, c;

    for (i = 0; i < 4; i++)
{
c = (value >> 24) & BYTEMASK;
        value <<= 8;
*bp++ = c;
}
}

[关闭][返回]