macutils/hexbin/hecx.c

257 lines
5.3 KiB
C

#include "hexbin.h"
#ifdef HECX
#include "globals.h"
#include "crc.h"
#include "readline.h"
#include "../util/masks.h"
#include "../util/util.h"
#include "../fileio/machdr.h"
#include "../fileio/wrfile.h"
#include "buffer.h"
#include "printhdr.h"
extern void exit();
static void do_o_forks();
static long make_file();
static void comp_c_crc();
static void comp_e_crc();
static int comp_to_bin();
static int hex_to_bin();
static int hexit();
static int compressed;
/* old format -- process .hex and .hcx files */
void hecx(macname, filename)
char *macname, *filename;
{
int n;
for(n = 0; n < INFOBYTES; n++) {
info[n] = 0;
}
compressed = 0;
/* set up name for output files */
if(macname[0] == '\0') {
/* strip directories */
macname = search_last(filename, '/');
if(macname == NULL) {
macname = filename;
} else {
macname++;
}
/* strip extension */
n = strlen(macname);
if(n > 4) {
n -= 4;
if(!strncmp(macname + n, ".hex", 4) ||
!strncmp(macname + n, ".hcx", 4)) {
macname[n] = '\0';
}
}
}
n = strlen(macname);
if(n > F_NAMELEN) {
n = F_NAMELEN;
}
(void)strncpy(mh.m_name, macname, n);
mh.m_name[n] = '\0';
/* "#TYPEAUTH$flag" line already read */
n = strlen(line);
if(n >= 6 && line[0] == '#' && line[n-5] == '$') {
if(n >= 10) {
(void)strncpy(mh.m_type, &line[1], 4);
}
if(n >= 14) {
(void)strncpy(mh.m_author, &line[5], 4);
}
(void)sscanf(&line[n-4], "%4hx", &mh.m_flags);
}
transname(mh.m_name, trname, n);
define_name(trname);
do_o_forks();
if(listmode) {
if(!compressed) {
(void)fprintf(stderr, "This file is in \"hex\" format.\n");
} else {
(void)fprintf(stderr, "This file is in \"hcx\" format.\n");
}
}
print_header0(0);
print_header1(0, 0);
info[I_NAMEOFF] = n;
(void)strncpy(info + I_NAMEOFF + 1, mh.m_name, n);
(void)strncpy(info + I_TYPEOFF, mh.m_type, 4);
(void)strncpy(info + I_AUTHOFF, mh.m_author, 4);
put2(info + I_FLAGOFF, (unsigned long)mh.m_flags);
put4(info + I_DLENOFF, (unsigned long)mh.m_datalen);
put4(info + I_RLENOFF, (unsigned long)mh.m_rsrclen);
put4(info + I_CTIMOFF, (unsigned long)mh.m_createtime);
put4(info + I_MTIMOFF, (unsigned long)mh.m_modifytime);
print_header2(0);
end_put();
}
static void do_o_forks()
{
int forks = 0, found_crc = 0;
unsigned long calc_crc, file_crc;
crc = 0; /* calculate a crc for both forks */
set_put(0);
set_put(1);
while(!found_crc && readline()) {
if(line[0] == 0) {
continue;
}
if(forks == 0 && strncmp(line, "***COMPRESSED", 13) == 0) {
compressed++;
continue;
}
if(strncmp(line, "***DATA", 7) == 0) {
set_put(1);
mh.m_datalen = make_file(compressed);
forks++;
continue;
}
if(strncmp(line, "***RESOURCE", 11) == 0) {
set_put(0);
mh.m_rsrclen = make_file(compressed);
forks++;
continue;
}
if(compressed && strncmp(line, "***CRC:", 7) == 0) {
found_crc++;
calc_crc = crc;
(void)sscanf(&line[7], "%lx", &file_crc);
break;
}
if(!compressed && strncmp(line, "***CHECKSUM:", 12) == 0) {
found_crc++;
calc_crc = crc & BYTEMASK;
(void)sscanf(&line[12], "%lx", &file_crc);
file_crc &= BYTEMASK;
break;
}
}
if(found_crc) {
verify_crc(calc_crc, file_crc);
} else {
(void)fprintf(stderr, "missing CRC\n");
#ifdef SCAN
do_error("hexbin: missing CRC");
#endif /* SCAN */
exit(1);
}
}
static long make_file(compressed)
int compressed;
{
register long nbytes = 0L;
while(readline()) {
if(line[0] == 0) {
continue;
}
if(strncmp(line, "***END", 6) == 0) {
break;
}
if(compressed) {
nbytes += comp_to_bin();
} else {
nbytes += hex_to_bin();
}
}
return nbytes;
}
static void comp_c_crc(c)
unsigned char c;
{
crc = (crc + c) & WORDMASK;
crc = ((crc << 3) & WORDMASK) | (crc >> 13);
}
static void comp_e_crc(c)
unsigned char c;
{
crc += c;
}
#define SIXB(c) (((c)-0x20) & 0x3f)
static int comp_to_bin()
{
char obuf[BUFSIZ];
register char *ip = line;
register char *op = obuf;
register int n, outcount;
int numread, incount;
numread = strlen(line);
outcount = (SIXB(ip[0]) << 2) | (SIXB(ip[1]) >> 4);
incount = ((outcount / 3) + 1) * 4;
for(n = numread; n < incount; n++) { /* restore lost spaces */
line[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]);
put_byte(obuf[n]);
}
return outcount;
}
static int hex_to_bin()
{
register char *ip = line;
register int n, outcount;
int c;
n = strlen(line);
outcount = n / 2;
for(n = 0; n < outcount; n++) {
c = hexit((int)*ip++);
comp_e_crc((unsigned)(c = (c << 4) | hexit((int)*ip++)));
put_byte((char)c);
}
return outcount;
}
static int hexit(c)
int c;
{
if('0' <= c && c <= '9') {
return c - '0';
}
if('A' <= c && c <= 'F') {
return c - 'A' + 10;
}
(void)fprintf(stderr, "illegal hex digit: %c", c);
#ifdef SCAN
do_error("hexbin: illegal hex digit");
#endif /* SCAN */
exit(1);
/* NOTREACHED */
}
#else /* HECX */
int hecx; /* keep lint and some compilers happy */
#endif /* HECX */