Converted .c to .cpp

This commit is contained in:
Ianos Gnatiuc 2006-05-06 09:10:18 +00:00
parent 0573c95f34
commit 7a646ca788
11 changed files with 18068 additions and 0 deletions

5066
goldlib/glibc/regex.cpp Normal file

File diff suppressed because it is too large Load Diff

813
goldlib/smblib/lzh.cpp Normal file
View File

@ -0,0 +1,813 @@
/* lzh.c */
/* Synchronet LZH compression library */
/* $Id$ */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Rob Swindell's conversion of 1988 LZH (LHarc) encoding functions *
* Based on Japanese version 29-NOV-1988 *
* LZSS coded by Haruhiko Okumura *
* Adaptive Huffman Coding coded by Haruyasu Yoshizaki *
* *
* Anonymous FTP access to the most recent released source is available at *
* ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
* *
* Anonymous CVS access to the development source and modification history *
* is available at cvs.synchro.net:/cvsroot/sbbs, example: *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login *
* (just hit return, no password is necessary) *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* You are encouraged to submit any modifications (preferably in Unix diff *
* format) via e-mail to mods@synchro.net *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* FreeBSD's malloc.h is deprecated, it drops a warning and */
/* #includes <stdlib.h>, which is already here. */
#if !defined(__FreeBSD__) && !defined(__APPLE__)
#include <malloc.h>
#endif
#include "lzh.h"
/****************************************************************************/
/* Memory allocation macros for various compilers and environments */
/* MALLOC is used for allocations of 64k or less */
/* FREE is used to free buffers allocated with MALLOC */
/* LMALLOC is used for allocations of possibly larger than 64k */
/* LFREE is used to free buffers allocated with LMALLOC */
/* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer */
/****************************************************************************/
#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
#if defined(__TURBOC__)
#define REALLOC(x,y) farrealloc(x,y)
#define LMALLOC(x) farmalloc(x)
#define MALLOC(x) farmalloc(x)
#define LFREE(x) farfree(x)
#define FREE(x) farfree(x)
#elif defined(__WATCOMC__)
#define REALLOC realloc
#define LMALLOC(x) halloc(x,1) /* far heap, but slow */
#define MALLOC malloc /* far heap, but 64k max */
#define LFREE hfree
#define FREE free
#else /* Other 16-bit Compiler */
#define REALLOC realloc
#define LMALLOC malloc
#define MALLOC malloc
#define LFREE free
#define FREE free
#endif
#else /* 32-bit Compiler or Small Memory Model */
#define REALLOC realloc
#define LMALLOC malloc
#define MALLOC malloc
#define LFREE free
#define FREE free
#endif
/* LZSS Parameters */
#define LZH_N 4096 /* Size of string buffer */
#define LZH_F 60 /* Size of look-ahead buffer */
#define LZH_THRESHOLD 2
#define LZH_NIL LZH_N /* End of tree's node */
#ifdef LZH_DYNAMIC_BUF
uint8_t *lzh_text_buf;
int16_t lzh_match_position, lzh_match_length,
*lzh_lson, *lzh_rson, *lzh_dad;
#else
uint8_t lzh_text_buf[LZH_N + LZH_F - 1];
int16_t lzh_match_position, lzh_match_length,
lzh_lson[LZH_N + 1], lzh_rson[LZH_N + 257], lzh_dad[LZH_N + 1];
#endif
void lzh_init_tree(void) /* Initializing tree */
{
int16_t i;
for (i = LZH_N + 1; i <= LZH_N + 256; i++)
lzh_rson[i] = LZH_NIL; /* root */
for (i = 0; i < LZH_N; i++)
lzh_dad[i] = LZH_NIL; /* node */
}
/******************************/
/* Inserting node to the tree */
/* Only used during encoding */
/******************************/
void lzh_insert_node(int16_t r)
{
int16_t i, p, cmp;
uint8_t *key;
uint32_t c;
cmp = 1;
key = lzh_text_buf+r;
p = LZH_N + 1 + key[0];
lzh_rson[r] = lzh_lson[r] = LZH_NIL;
lzh_match_length = 0;
for ( ; ; ) {
if (cmp >= 0) {
if (lzh_rson[p] != LZH_NIL)
p = lzh_rson[p];
else {
lzh_rson[p] = r;
lzh_dad[r] = p;
return;
}
} else {
if (lzh_lson[p] != LZH_NIL)
p = lzh_lson[p];
else {
lzh_lson[p] = r;
lzh_dad[r] = p;
return;
}
}
for (i = 1; i < LZH_F; i++)
if ((cmp = key[i] - lzh_text_buf[p + i]) != 0)
break;
if (i > LZH_THRESHOLD) {
if (i > lzh_match_length) {
lzh_match_position = ((r - p) & (LZH_N - 1)) - 1;
if ((lzh_match_length = i) >= LZH_F)
break;
}
if (i == lzh_match_length) {
if ((c = ((r - p) & (LZH_N - 1)) - 1)
< (uint32_t)lzh_match_position) {
lzh_match_position = c;
}
}
}
}
lzh_dad[r] = lzh_dad[p];
lzh_lson[r] = lzh_lson[p];
lzh_rson[r] = lzh_rson[p];
lzh_dad[lzh_lson[p]] = r;
lzh_dad[lzh_rson[p]] = r;
if (lzh_rson[lzh_dad[p]] == p)
lzh_rson[lzh_dad[p]] = r;
else
lzh_lson[lzh_dad[p]] = r;
lzh_dad[p] = LZH_NIL; /* remove p */
}
void lzh_delete_node(int16_t p) /* Deleting node from the tree */
{
int16_t q;
if (lzh_dad[p] == LZH_NIL)
return; /* unregistered */
if (lzh_rson[p] == LZH_NIL)
q = lzh_lson[p];
else
if (lzh_lson[p] == LZH_NIL)
q = lzh_rson[p];
else {
q = lzh_lson[p];
if (lzh_rson[q] != LZH_NIL) {
do {
q = lzh_rson[q];
} while (lzh_rson[q] != LZH_NIL);
lzh_rson[lzh_dad[q]] = lzh_lson[q];
lzh_dad[lzh_lson[q]] = lzh_dad[q];
lzh_lson[q] = lzh_lson[p];
lzh_dad[lzh_lson[p]] = q;
}
lzh_rson[q] = lzh_rson[p];
lzh_dad[lzh_rson[p]] = q;
}
lzh_dad[q] = lzh_dad[p];
if (lzh_rson[lzh_dad[p]] == p)
lzh_rson[lzh_dad[p]] = q;
else
lzh_lson[lzh_dad[p]] = q;
lzh_dad[p] = LZH_NIL;
}
/* Huffman coding parameters */
#define LZH_N_CHAR (256 - LZH_THRESHOLD + LZH_F)
/* character code (= 0..LZH_N_CHAR-1) */
#define LZH_T (LZH_N_CHAR * 2 - 1) /* Size of table */
#define LZH_R (LZH_T - 1) /* root position */
#define MAX_FREQ 0x8000
/* update when cumulative frequency */
/* reaches to this value */
/*
* Tables for encoding/decoding upper 6 bits of
* sliding dictionary pointer
*/
/* encoder table */
uint8_t lzh_p_len[64] = {
0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
};
uint8_t lzh_p_code[64] = {
0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};
/* decoder table */
uint8_t lzh_d_code[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
};
uint8_t lzh_d_len[256] = {
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
};
#ifdef LZH_DYNAMIC_BUF
uint16_t *lzh_freq = NULL; /* cumulative freq table */
/*
* pointing parent nodes.
* area [LZH_T..(LZH_T + LZH_N_CHAR - 1)] are pointers for leaves
*/
int16_t *lzh_prnt = NULL;
/* pointing children nodes (son[], son[] + 1)*/
int16_t *lzh_son = NULL;
#else /* STATIC */
uint16_t lzh_freq[LZH_T + 1]; /* cumulative freq table */
int16_t lzh_prnt[LZH_T + LZH_N_CHAR];
int16_t lzh_son[LZH_T + 1]; /* bug fixed by Digital Dynamics */
#endif
uint16_t lzh_getbuf = 0; /* Was just "unsigned" fixed 04/12/95 */
uint8_t lzh_getlen = 0;
int lzh_getbit(uint8_t *inbuf, int32_t *incnt, int32_t inlen) /* get one bit */
{
int16_t i;
while (lzh_getlen <= 8) {
if((*incnt)>=inlen)
i=0;
else
i=inbuf[(*incnt)++];
lzh_getbuf |= i << (8 - lzh_getlen);
lzh_getlen += 8;
}
i = lzh_getbuf;
lzh_getbuf <<= 1;
lzh_getlen--;
return (i < 0);
}
int16_t lzh_getbyte(uint8_t *inbuf, int32_t *incnt, int32_t inlen) /* get a byte */
{
uint16_t i;
while (lzh_getlen <= 8) {
if((*incnt)>=inlen)
i=0;
else
i=inbuf[(*incnt)++];
lzh_getbuf |= i << (8 - lzh_getlen);
lzh_getlen += 8;
}
i = lzh_getbuf;
lzh_getbuf <<= 8;
lzh_getlen -= 8;
return i >> 8;
}
uint32_t lzh_putbuf = 0;
uint8_t lzh_putlen = 0;
/* output c bits */
void lzh_putcode(int16_t l, uint16_t c, uint8_t *outbuf, int32_t *outlen)
{
lzh_putbuf |= c >> lzh_putlen;
if ((lzh_putlen += l) >= 8) {
outbuf[(*outlen)++]=(lzh_putbuf >> 8);
if ((lzh_putlen -= 8) >= 8) {
outbuf[(*outlen)++]=lzh_putbuf;
lzh_putlen -= 8;
lzh_putbuf = c << (l - lzh_putlen);
} else {
lzh_putbuf <<= 8;
}
}
}
/* initialize freq tree */
void lzh_start_huff(void)
{
int16_t i, j;
lzh_getbuf = 0; /* Added by Digital Dynamics for repeating operations */
lzh_getlen = 0;
lzh_putbuf = 0;
lzh_putlen = 0;
for (i = 0; i < LZH_N_CHAR; i++) {
lzh_freq[i] = 1;
lzh_son[i] = i + LZH_T;
lzh_prnt[i + LZH_T] = i;
}
i = 0; j = LZH_N_CHAR;
while (j <= LZH_R) {
lzh_freq[j] = lzh_freq[i] + lzh_freq[i + 1];
lzh_son[j] = i;
lzh_prnt[i] = lzh_prnt[i + 1] = j;
i += 2; j++;
}
lzh_freq[LZH_T] = 0xffff;
lzh_prnt[LZH_R] = 0;
}
/* reconstruct freq tree */
void lzh_reconst(void)
{
int16_t i, j, k;
uint16_t f, l;
/* halven cumulative freq for leaf nodes */
j = 0;
for (i = 0; i < LZH_T; i++) {
if (lzh_son[i] >= LZH_T) {
lzh_freq[j] = (lzh_freq[i] + 1) / 2;
lzh_son[j] = lzh_son[i];
j++;
}
}
/* make a tree : first, connect children nodes */
for (i = 0, j = LZH_N_CHAR; j < LZH_T; i += 2, j++) {
k = i + 1;
f = lzh_freq[j] = lzh_freq[i] + lzh_freq[k];
for (k = j - 1; f < lzh_freq[k]; k--);
k++;
l = (j - k) * 2;
/* movmem() is Turbo-C dependent
rewritten to memmove() by Kenji */
/* movmem(&lzh_freq[k], &lzh_freq[k + 1], l); */
(void)memmove(lzh_freq+k+1,lzh_freq+k, l);
lzh_freq[k] = f;
/* movmem(&lzh_son[k], &lzh_son[k + 1], l); */
(void)memmove(lzh_son+k+1,lzh_son+k, l);
lzh_son[k] = i;
}
/* connect parent nodes */
for (i = 0; i < LZH_T; i++) {
if ((k = lzh_son[i]) >= LZH_T) {
lzh_prnt[k] = i;
} else {
lzh_prnt[k] = lzh_prnt[k + 1] = i;
}
}
}
/* update freq tree */
void lzh_update(int16_t c)
{
int16_t i, j, k, l;
if (lzh_freq[LZH_R] == MAX_FREQ) {
lzh_reconst();
}
c = lzh_prnt[c + LZH_T];
do {
k = ++lzh_freq[c];
/* swap nodes to keep the tree freq-ordered */
if (k > lzh_freq[l = c + 1]) {
while (k > lzh_freq[++l]);
l--;
lzh_freq[c] = lzh_freq[l];
lzh_freq[l] = k;
i = lzh_son[c];
lzh_prnt[i] = l;
if (i < LZH_T) lzh_prnt[i + 1] = l;
j = lzh_son[l];
lzh_son[l] = i;
lzh_prnt[j] = c;
if (j < LZH_T) lzh_prnt[j + 1] = c;
lzh_son[c] = j;
c = l;
}
} while ((c = lzh_prnt[c]) != 0); /* do it until reaching the root */
}
uint16_t lzh_code, lzh_len;
void lzh_encode_char(uint16_t c, uint8_t *outbuf, int32_t *outlen)
{
uint16_t i;
int16_t j, k;
i = 0;
j = 0;
k = lzh_prnt[c + LZH_T];
/* search connections from leaf node to the root */
do {
i >>= 1;
/*
if node's address is odd, output 1
else output 0
*/
if (k & 1) i += 0x8000;
j++;
} while ((k = lzh_prnt[k]) != LZH_R);
lzh_putcode(j, i, outbuf, outlen);
lzh_code = i;
lzh_len = j;
lzh_update(c);
}
void lzh_encode_position(uint16_t c, uint8_t *outbuf, int32_t *outlen)
{
uint16_t i;
/* output upper 6 bits with encoding */
i = c >> 6;
lzh_putcode(lzh_p_len[i], (uint16_t)(lzh_p_code[i] << 8), outbuf, outlen);
/* output lower 6 bits directly */
lzh_putcode(6, (uint16_t)((c & 0x3f) << 10), outbuf, outlen);
}
void lzh_encode_end(uint8_t *outbuf, int32_t *outlen)
{
if (lzh_putlen) {
outbuf[(*outlen)++]=(lzh_putbuf >> 8);
}
}
int16_t lzh_decode_char(uint8_t *inbuf, int32_t *incnt, int32_t inlen)
{
uint16_t c;
c = lzh_son[LZH_R];
/*
* start searching tree from the root to leaves.
* choose node #(lzh_son[]) if input bit == 0
* else choose #(lzh_son[]+1) (input bit == 1)
*/
while (c < LZH_T) {
c += lzh_getbit(inbuf,incnt,inlen);
c = lzh_son[c];
}
c -= LZH_T;
lzh_update(c);
return c;
}
int16_t lzh_decode_position(uint8_t *inbuf, int32_t *incnt, int32_t inlen)
{
uint16_t i, j, c;
/* decode upper 6 bits from given table */
i = lzh_getbyte(inbuf,incnt,inlen);
c = (uint32_t)lzh_d_code[i] << 6;
j = lzh_d_len[i];
/* input lower 6 bits directly */
j -= 2;
while (j--) {
i = (i << 1) + lzh_getbit(inbuf,incnt,inlen);
}
return c | (i & 0x3f);
}
/* Compression */
/* Encoding/Compressing */
/* Returns length of outbuf */
int32_t LZHCALL lzh_encode(uint8_t *inbuf, int32_t inlen, uint8_t *outbuf)
{
int16_t i, c, len, r, s, last_match_length;
int32_t incnt, outlen; /* textsize=0; */
#ifdef LZH_DYNAMIC_BUF
if((lzh_text_buf=(uint8_t *)MALLOC(LZH_N + LZH_F - 1))==NULL)
return(-1);
if((lzh_freq=(uint16_t *)MALLOC((LZH_T + 1)*sizeof(uint16_t)))==NULL) {
FREE(lzh_text_buf);
return(-1); }
if((lzh_prnt=(int16_t *)MALLOC((LZH_T + LZH_N_CHAR)*sizeof(int16_t)))==NULL) {
FREE(lzh_text_buf);
FREE(lzh_freq);
return(-1); }
if((lzh_son=(int16_t *)MALLOC((LZH_T + 1) * sizeof(int16_t)))==NULL) {
FREE(lzh_text_buf);
FREE(lzh_prnt);
FREE(lzh_freq);
return(-1); }
if((lzh_lson=(int16_t *)MALLOC((LZH_N + 1)*sizeof(int16_t)))==NULL) {
FREE(lzh_text_buf);
FREE(lzh_prnt);
FREE(lzh_freq);
FREE(lzh_son);
return(-1); }
if((lzh_rson=(int16_t *)MALLOC((LZH_N + 257)*sizeof(int16_t)))==NULL) {
FREE(lzh_text_buf);
FREE(lzh_prnt);
FREE(lzh_freq);
FREE(lzh_son);
FREE(lzh_lson);
return(-1); }
if((lzh_dad=(int16_t *)MALLOC((LZH_N + 1)*sizeof(int16_t)))==NULL) {
FREE(lzh_text_buf);
FREE(lzh_prnt);
FREE(lzh_freq);
FREE(lzh_son);
FREE(lzh_lson);
FREE(lzh_rson);
return(-1); }
#endif
incnt=0;
memcpy(outbuf,&inlen,sizeof(inlen));
outlen=sizeof(inlen);
if(!inlen) {
#ifdef LZH_DYNAMIC_BUF
FREE(lzh_text_buf);
FREE(lzh_prnt);
FREE(lzh_freq);
FREE(lzh_son);
FREE(lzh_lson);
FREE(lzh_rson);
FREE(lzh_dad);
#endif
return(outlen); }
lzh_start_huff();
lzh_init_tree();
s = 0;
r = LZH_N - LZH_F;
for (i = s; i < r; i++)
lzh_text_buf[i] = ' ';
for (len = 0; len < LZH_F && incnt<inlen; len++)
lzh_text_buf[r + len] = inbuf[incnt++];
/* textsize = len; */
for (i = 1; i <= LZH_F; i++)
lzh_insert_node((int16_t)(r - i));
lzh_insert_node(r);
do {
if (lzh_match_length > len)
lzh_match_length = len;
if (lzh_match_length <= LZH_THRESHOLD) {
lzh_match_length = 1;
lzh_encode_char(lzh_text_buf[r],outbuf,&outlen);
} else {
lzh_encode_char((uint16_t)(255 - LZH_THRESHOLD + lzh_match_length)
,outbuf,&outlen);
lzh_encode_position(lzh_match_position
,outbuf,&outlen);
}
last_match_length = lzh_match_length;
for (i = 0; i < last_match_length && incnt<inlen; i++) {
lzh_delete_node(s);
c=inbuf[incnt++];
lzh_text_buf[s] = (uint8_t)c;
if (s < LZH_F - 1)
lzh_text_buf[s + LZH_N] = (uint8_t)c;
s = (s + 1) & (LZH_N - 1);
r = (r + 1) & (LZH_N - 1);
lzh_insert_node(r);
}
/***
if ((textsize += i) > printcount) {
printf("%12ld\r", textsize);
printcount += 1024;
}
***/
while (i++ < last_match_length) {
lzh_delete_node(s);
s = (s + 1) & (LZH_N - 1);
r = (r + 1) & (LZH_N - 1);
if (--len) lzh_insert_node(r);
}
} while (len > 0);
lzh_encode_end(outbuf,&outlen);
/*
printf("input: %ld (%ld) bytes\n", inlen,textsize);
printf("output: %ld bytes\n", outlen);
printf("output/input: %.3f\n", (double)outlen / inlen);
*/
#ifdef LZH_DYNAMIC_BUF
FREE(lzh_text_buf);
FREE(lzh_prnt);
FREE(lzh_freq);
FREE(lzh_son);
FREE(lzh_lson);
FREE(lzh_rson);
FREE(lzh_dad);
#endif
return(outlen);
}
/* Decoding/Uncompressing */
/* Returns length of outbuf */
int32_t LZHCALL lzh_decode(uint8_t *inbuf, int32_t inlen, uint8_t *outbuf)
{
int16_t i, j, k, r, c;
uint32_t count;
int32_t incnt, textsize;
#ifdef LZH_DYNAMIC_BUF
if((lzh_text_buf=(uint8_t *)MALLOC((LZH_N + LZH_F - 1)*2))==NULL)
return(-1);
if((lzh_freq=(uint16_t *)MALLOC((LZH_T + 1)*sizeof(uint16_t)))
==NULL) {
FREE(lzh_text_buf);
return(-1); }
if((lzh_prnt=(int16_t *)MALLOC((LZH_T + LZH_N_CHAR)*sizeof(int16_t)))==NULL) {
FREE(lzh_text_buf);
FREE(lzh_freq);
return(-1); }
if((lzh_son=(int16_t *)MALLOC((LZH_T + 1) * sizeof(int16_t)))==NULL) {
FREE(lzh_text_buf);
FREE(lzh_prnt);
FREE(lzh_freq);
return(-1); }
#endif
incnt=0;
memcpy(&textsize,inbuf,sizeof(textsize));
incnt+=sizeof(textsize);
if (textsize == 0) {
#ifdef LZH_DYNAMIC_BUF
FREE(lzh_text_buf);
FREE(lzh_prnt);
FREE(lzh_freq);
FREE(lzh_son);
#endif
return(textsize); }
lzh_start_huff();
for (i = 0; i < LZH_N - LZH_F; i++)
*(lzh_text_buf+i) = ' ';
r = LZH_N - LZH_F;
for (count = 0; count < (uint32_t)textsize; ) {
c = lzh_decode_char(inbuf,&incnt,inlen);
if (c < 256) {
outbuf[count]=(uint8_t)c;
#if 0
if(r>(LZH_N + LZH_F - 1) || r<0) {
printf("Overflow! (%d)\n",r);
getch();
exit(-1); }
#endif
*(lzh_text_buf+r) = (uint8_t)c;
r++;
r &= (LZH_N - 1);
count++;
} else {
i = (r - lzh_decode_position(inbuf,&incnt,inlen) - 1)
& (LZH_N - 1);
j = c - 255 + LZH_THRESHOLD;
for (k = 0; k < j && count<(uint32_t)textsize; k++) {
c = lzh_text_buf[(i + k) & (LZH_N - 1)];
outbuf[count]=(uint8_t)c;
#if 0
if(r>(LZH_N + LZH_F - 1) || r<0) {
printf("Overflow! (%d)\n",r);
exit(-1); }
#endif
*(lzh_text_buf+r) = (uint8_t)c;
r++;
r &= (LZH_N - 1);
count++;
}
}
}
/***
printf("%12ld\n", count);
***/
#ifdef LZH_DYNAMIC_BUF
FREE(lzh_text_buf);
FREE(lzh_prnt);
FREE(lzh_freq);
FREE(lzh_son);
#endif
return(count);
}

1729
goldlib/smblib/smblib.cpp Normal file

File diff suppressed because it is too large Load Diff

514
goldlib/uulib/fptools.cpp Normal file
View File

@ -0,0 +1,514 @@
/*
* fptools.c, some helper functions for getcgi.c and uu(en|de)view
*
* Distributed under the terms of the GNU General Public License.
* Use and be happy.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef SYSTEM_WINDLL
#include <windows.h>
#endif
#ifdef SYSTEM_OS2
#include <os2.h>
#endif
/*
* This file provides replacements for some handy functions that aren't
* available on all systems, like most of the <string.h> functions. They
* should behave exactly as their counterparts. There are also extensions
* that aren't portable at all (like strirstr etc.).
* The proper behaviour in a configure script is as follows:
* AC_CHECK_FUNC(strrchr,AC_DEFINE(strrchr,_FP_strrchr))
* This way, the (probably less efficient) replacements will only be used
* where it is not provided by the default libraries. Be aware that this
* does not work with replacements that just shadow wrong behaviour (like
* _FP_free) or provide extended functionality (_FP_gets).
* The above is not used in the uuenview/uudeview configuration script,
* since both only use the replacement functions in non-performance-cri-
* tical sections (except for _FP_tempnam and _FP_strerror, where some
* functionality of the original would be lost).
*/
#include <stdio.h>
#ifdef STDC_HEADERS
#include <stdlib.h>
#include <string.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#include <gdefs.h>
#include <gctype.h>
#include <fptools.h>
#if 0
#ifdef SYSTEM_WINDLL
BOOL _export WINAPI
DllEntryPoint (HINSTANCE hInstance, DWORD seginfo,
LPVOID lpCmdLine)
{
/* Don't do anything, so just return true */
return TRUE;
}
#endif
#endif
char * fptools_id = "$Id$";
/*
* some versions of free can't handle a NULL pointer properly
* (ANSI says, free ignores a NULL pointer, but some machines
* prefer to SIGSEGV on it)
*/
void TOOLEXPORT
_FP_free (void *ptr)
{
if (ptr) free (ptr);
}
/*
* This is non-standard, so I'm defining my own
*/
char * TOOLEXPORT
_FP_strdup (char *string)
{
char *result;
if (string == NULL)
return NULL;
if ((result = (char *) malloc (strlen (string) + 1)) == NULL)
return NULL;
strcpy (result, string);
return result;
}
/*
* limited-length string copy. this function behaves differently from
* the original in that the dest string is always terminated with a
* NULL character.
*/
char * TOOLEXPORT
_FP_strncpy (char *dest, char *src, int length)
{
char *odest=dest;
if (src == NULL || dest == NULL || length-- <= 0)
return dest;
while (length-- && *src)
*dest++ = *src++;
*dest++ = '\0';
return odest;
}
/*
* duplicate a memory area
*/
void * TOOLEXPORT
_FP_memdup (void *ptr, int len)
{
void *result;
if (ptr == NULL)
return NULL;
if ((result = malloc (len)) == NULL)
return NULL;
memcpy (result, ptr, len);
return result;
}
/*
* case-insensitive compare
*/
int TOOLEXPORT
_FP_stricmp (char *str1, char *str2)
{
if (str1==NULL || str2==NULL)
return -1;
while (*str1) {
if (g_tolower(*str1) != g_tolower(*str2))
break;
str1++;
str2++;
}
return (g_tolower (*str1) - g_tolower (*str2));
}
int TOOLEXPORT
_FP_strnicmp (char *str1, char *str2, int count)
{
if (str1==NULL || str2==NULL)
return -1;
while (*str1 && count) {
if (g_tolower(*str1) != g_tolower(*str2))
break;
str1++;
str2++;
count--;
}
return count ? (g_tolower (*str1) - g_tolower (*str2)) : 0;
}
/*
* autoconf says this function might be a compatibility problem
*/
char * TOOLEXPORT
_FP_strstr (char *str1, char *str2)
{
char *ptr1, *ptr2;
if (str1==NULL)
return NULL;
if (str2==NULL)
return str1;
while (*(ptr1=str1)) {
for (ptr2=str2;
*ptr1 && *ptr2 && *ptr1==*ptr2;
ptr1++, ptr2++)
/* empty loop */ ;
if (*ptr2 == '\0')
return str1;
str1++;
}
return NULL;
}
char * TOOLEXPORT
_FP_strpbrk (char *str, char *accept)
{
char *ptr;
if (str == NULL)
return NULL;
if (accept == NULL || *accept == '\0')
return str;
for (; *str; str++)
for (ptr=accept; *ptr; ptr++)
if (*str == *ptr)
return str;
return NULL;
}
/*
* autoconf also complains about this one
*/
char * TOOLEXPORT
_FP_strtok (char *str1, char *str2)
{
static char *optr;
char *ptr;
if (str2 == NULL)
return NULL;
if (str1) {
optr = str1;
}
else {
if (*optr == '\0')
return NULL;
}
while (*optr && strchr (str2, *optr)) /* look for beginning of token */
optr++;
if (*optr == '\0') /* no token found */
return NULL;
ptr = optr;
while (*optr && strchr (str2, *optr) == NULL) /* look for end of token */
optr++;
if (*optr) {
*optr++ = '\0';
}
return ptr;
}
/*
* case insensitive strstr.
*/
char * TOOLEXPORT
_FP_stristr (char *str1, char *str2)
{
char *ptr1, *ptr2;
if (str1==NULL)
return NULL;
if (str2==NULL)
return str1;
while (*(ptr1=str1)) {
for (ptr2=str2;
*ptr1 && *ptr2 && g_tolower(*ptr1)==g_tolower(*ptr2);
ptr1++, ptr2++)
/* empty loop */ ;
if (*ptr2 == '\0')
return str1;
str1++;
}
return NULL;
}
/*
* Nice fake of the real (non-standard) one
*/
char * TOOLEXPORT
_FP_strrstr (char *ptr, char *str)
{
char *found=NULL, *pstr, *iter=ptr;
if (ptr==NULL || str==NULL)
return NULL;
if (*str == '\0')
return ptr;
while ((pstr = _FP_strstr (iter, str)) != NULL) {
found = pstr;
iter = pstr + 1;
}
return found;
}
char * TOOLEXPORT
_FP_strirstr (char *ptr, char *str)
{
char *found=NULL, *iter=ptr, *pstr;
if (ptr==NULL || str==NULL)
return NULL;
if (*str == '\0')
return ptr;
while ((pstr = _FP_stristr (iter, str)) != NULL) {
found = pstr;
iter = pstr + 1;
}
return found;
}
/*
* convert whole string to case
*/
char * TOOLEXPORT
_FP_stoupper (char *input)
{
char *iter = input;
if (input == NULL)
return NULL;
while (*iter) {
*iter = g_toupper (*iter);
iter++;
}
return input;
}
char * TOOLEXPORT
_FP_stolower (char *input)
{
char *iter = input;
if (input == NULL)
return NULL;
while (*iter) {
*iter = g_tolower (*iter);
iter++;
}
return input;
}
/*
* string matching with wildcards
*/
int TOOLEXPORT
_FP_strmatch (char *string, char *pattern)
{
char *p1 = string, *p2 = pattern;
if (pattern==NULL || string==NULL)
return 0;
while (*p1 && *p2) {
if (*p2 == '?') {
p1++; p2++;
}
else if (*p2 == '*') {
if (*++p2 == '\0')
return 1;
while (*p1 && *p1 != *p2)
p1++;
}
else if (*p1 == *p2) {
p1++; p2++;
}
else
return 0;
}
if (*p1 || *p2)
return 0;
return 1;
}
char * TOOLEXPORT
_FP_strrchr (char *string, int tc)
{
char *ptr;
if (string == NULL)
return NULL;
ptr = string + strlen (string) - 1;
while (ptr != string && *ptr != tc)
ptr--;
if (*ptr == tc)
return ptr;
return NULL;
}
/*
* strip directory information from a filename. Works only on DOS and
* Unix systems so far ...
*/
char * TOOLEXPORT
_FP_cutdir (char *filename)
{
char *ptr;
if (filename == NULL)
return NULL;
if ((ptr = _FP_strrchr (filename, '/')) != NULL)
ptr++;
else if ((ptr = _FP_strrchr (filename, '\\')) != NULL)
ptr++;
else
ptr = filename;
return ptr;
}
/*
* My own fgets function. It handles all kinds of line terminators
* properly: LF (Unix), CRLF (DOS) and CR (Mac). In all cases, the
* terminator is replaced by a single LF
*/
char * TOOLEXPORT
_FP_fgets (char *buf, int n, FILE *stream)
{
char *obp = buf;
int c;
if (feof (stream))
return NULL;
while (--n) {
if ((c = fgetc (stream)) == EOF) {
if (ferror (stream))
return NULL;
else {
if (obp == buf)
return NULL;
*buf = '\0';
return obp;
}
}
if (c == '\015') { /* CR */
/*
* Peek next character. If it's no LF, push it back.
* ungetc(EOF, stream) is handled correctly according
* to the manual page
*/
if ((c = fgetc (stream)) != '\012')
if (!feof (stream))
ungetc (c, stream);
*buf++ = '\012';
*buf = '\0';
return obp;
}
else if (c == '\012') { /* LF */
*buf++ = '\012';
*buf = '\0';
return obp;
}
/*
* just another standard character
*/
*buf++ = c;
}
/*
* n-1 characters already transferred
*/
*buf = '\0';
return obp;
}
#if 0
/*
* A replacement strerror function that just returns the error code
*/
char * TOOLEXPORT
_FP_strerror (int errcode)
{
static char number[8];
sprintf (number, "%03d", errcode);
return number;
}
/*
* tempnam is not ANSI, but tmpnam is. Ignore the prefix here.
*/
char * TOOLEXPORT
_FP_tempnam (char *dir, char *pfx)
{
return _FP_strdup (tmpnam (NULL));
}
#endif

1467
goldlib/uulib/uucheck.cpp Normal file

File diff suppressed because it is too large Load Diff

1793
goldlib/uulib/uuencode.cpp Normal file

File diff suppressed because it is too large Load Diff

1242
goldlib/uulib/uulib.cpp Normal file

File diff suppressed because it is too large Load Diff

1625
goldlib/uulib/uunconc.cpp Normal file

File diff suppressed because it is too large Load Diff

3170
goldlib/uulib/uuscan.cpp Normal file

File diff suppressed because it is too large Load Diff

168
goldlib/uulib/uustring.cpp Normal file
View File

@ -0,0 +1,168 @@
/*
* This file is part of uudeview, the simple and friendly multi-part multi-
* file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may
* be contacted at fp@fpx.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/*
* Strings used in the library for easier translation etc.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef SYSTEM_WINDLL
#include <windows.h>
#endif
#ifdef SYSTEM_OS2
#include <os2.h>
#endif
#include <stdio.h>
#ifdef STDC_HEADERS
#include <stdlib.h>
#include <string.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#include <uudeview.h>
#include <uuint.h>
#include <uustring.h>
char * uustring_id = "$Id$";
typedef struct {
int code;
char * msg;
} stringmap;
/*
* Map of messages. This table is not exported, the messages must
* be retrieved via the below uustring() function.
*/
static stringmap messages[] = {
/* I/O related errors/messages. Last parameter is strerror() */
{ S_NOT_OPEN_SOURCE, "Could not open source file %s: %s" },
{ S_NOT_OPEN_TARGET, "Could not open target file %s for writing: %s" },
{ S_NOT_OPEN_FILE, "Could not open file %s: %s" },
{ S_NOT_STAT_FILE, "Could not stat file %s: %s" },
{ S_SOURCE_READ_ERR, "Read error on source file: %s" },
{ S_READ_ERROR, "Error reading from %s: %s" },
{ S_IO_ERR_TARGET, "I/O error on target file %s: %s" },
{ S_WR_ERR_TARGET, "Write error on target file %s: %s" },
{ S_WR_ERR_TEMP, "Write error on temp file: %s" },
{ S_TMP_NOT_REMOVED, "Could not remove temp file %s: %s (ignored)" },
/* some other problems */
{ S_OUT_OF_MEMORY, "Out of memory allocating %d bytes" },
{ S_TARGET_EXISTS, "Target file %s exists and overwriting is not allowed" },
{ S_NOT_RENAME, "Could not change name of %s to %s" },
{ S_ERR_ENCODING, "Error while encoding %s: %s" },
{ S_STAT_ONE_PART, "Could not stat input, encoding to one part only" },
{ S_PARM_CHECK, "Parameter check failed in %s" },
{ S_SHORT_BINHEX, "BinHex encoded file %s ended prematurely (%ld bytes left)" },
{ S_DECODE_CANCEL, "Decode operation canceled" },
{ S_ENCODE_CANCEL, "Encode operation canceled" },
{ S_SCAN_CANCEL, "Scanning canceled" },
{ S_SIZE_MISMATCH, "%s: Decoded size (%ld) does not match expected size (%ld)" },
{ S_PSIZE_MISMATCH, "%s part %d: Decoded size (%ld) does not match expected size (%ld)" },
{ S_CRC_MISMATCH, "CRC32 mismatch in %s. Decoded file probably corrupt." },
{ S_PCRC_MISMATCH, "PCRC32 mismatch in %s part %d. Decoded file probably corrupt." },
/* informational messages */
{ S_LOADED_PART, "Loaded from %s: '%s' (%s): %s part %d %s %s %s" },
{ S_NO_DATA_FOUND, "No encoded data found in %s" },
{ S_NO_BIN_FILE, "Oops, could not find decoded file?" },
{ S_STRIPPED_SETUID, "Stripped setuid/setgid bits from target file %s mode %d" },
{ S_DATA_SUSPICIOUS, "Data looks suspicious. Decoded file might be corrupt." },
{ S_NO_TEMP_NAME, "Could not get name for temporary file" },
{ S_BINHEX_SIZES, "BinHex file: data/resource fork sizes %ld/%ld" },
{ S_BINHEX_BOTH, "BinHex file: both forks non-empty, decoding data fork" },
{ S_SMERGE_MERGED, "Parts of '%s' merged with parts of '%s' (%d)" },
/* MIME-related messages */
{ S_MIME_NO_BOUNDARY, "Multipart message without boundary ignored" },
{ S_MIME_B_NOT_FOUND, "Boundary expected on Multipart message but found EOF" },
{ S_MIME_MULTI_DEPTH, "Multipart message nested too deep" },
{ S_MIME_PART_MULTI, "Handling partial multipart message as plain text" },
{ 0, "" }
};
/*
* description of the return values UURET_*
*/
char *uuretcodes[] = {
"OK",
"File I/O Error",
"Not Enough Memory",
"Illegal Value",
"No Data found",
"Unexpected End of File",
"Unsupported function",
"File exists",
"Continue -- no error", /* only to be seen internally */
"Operation Canceled"
};
/*
* Names of encoding types
*/
char *codenames[8] = {
"", "UUdata", "Base64", "XXdata", "Binhex", "Text", "Text", "yEnc"
};
/*
* Message types
*/
char *msgnames[6] = {
"", "Note: ", "Warning: ", "ERROR: ", "FATAL ERROR: ", "PANIC: "
};
/*
* Retrieve one of the messages. We never return NULL
* but instead escape to "oops".
*/
char *
uustring (int codeno)
{
static char * faileddef = "oops";
stringmap *ptr = messages;
while (ptr->code) {
if (ptr->code == codeno)
return ptr->msg;
ptr++;
}
UUMessage (uustring_id, __LINE__, UUMSG_ERROR,
"Could not retrieve string no %d",
codeno);
return faileddef;
}

481
goldlib/uulib/uuutil.cpp Normal file
View File

@ -0,0 +1,481 @@
/*
* This file is part of uudeview, the simple and friendly multi-part multi-
* file uudecoder program (c) 1994-2001 by Frank Pilhofer. The author may
* be contacted at fp@fpx.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/*
* certain utilitarian functions that didn't fit anywhere else
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef SYSTEM_WINDLL
#include <windows.h>
#endif
#ifdef SYSTEM_OS2
#include <os2.h>
#endif
#include <stdio.h>
#ifdef STDC_HEADERS
#include <stdlib.h>
#include <string.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_IO_H
#include <io.h>
#endif
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <uudeview.h>
#include <uuint.h>
#include <fptools.h>
#include <uustring.h>
char * uuutil_id = "$Id$";
/*
* Parts with different known extensions will not be merged by SPMS.
* if first character is '@', it is synonymous to the previous one.
*/
static char *knownexts[] = {
"mpg", "@mpeg", "avi", "mov",
"gif", "jpg", "@jpeg", "tif",
"voc", "wav", "@wave", "au",
"zip", "arj", "tar",
NULL
};
/*
* forward declarations of local functions
*/
static int UUSMPKnownExt (char *filename);
static uulist * UU_smparts_r (uulist *, int);
/*
* mallocable areas
*/
char *uuutil_bhwtmp;
/*
* free some memory
**/
void
UUkillfread (fileread *data)
{
if (data != NULL) {
_FP_free (data->subject);
_FP_free (data->filename);
_FP_free (data->origin);
_FP_free (data->mimeid);
_FP_free (data->mimetype);
_FP_free (data->sfname);
_FP_free (data);
}
}
void
UUkillfile (uufile *data)
{
uufile *next;
while (data) {
_FP_free (data->filename);
_FP_free (data->subfname);
_FP_free (data->mimeid);
_FP_free (data->mimetype);
UUkillfread (data->data);
next = data->NEXT;
_FP_free (data);
data = next;
}
}
void
UUkilllist (uulist *data)
{
uulist *next;
while (data) {
if (data->binfile != NULL)
if (unlink (data->binfile))
UUMessage (uuutil_id, __LINE__, UUMSG_WARNING,
uustring (S_TMP_NOT_REMOVED),
data->binfile, strerror (errno));
_FP_free (data->filename);
_FP_free (data->subfname);
_FP_free (data->mimeid);
_FP_free (data->mimetype);
_FP_free (data->binfile);
UUkillfile (data->thisfile);
_FP_free (data->haveparts);
_FP_free (data->misparts);
next = data->NEXT;
_FP_free (data);
data = next;
}
}
/*
* this kill function is an exception in that it doesn't kill data itself
*/
void
UUkillheaders (headers *data)
{
if (data != NULL) {
_FP_free (data->from);
_FP_free (data->subject);
_FP_free (data->rcpt);
_FP_free (data->date);
_FP_free (data->mimevers);
_FP_free (data->ctype);
_FP_free (data->ctenc);
_FP_free (data->fname);
_FP_free (data->boundary);
_FP_free (data->mimeid);
memset (data, 0, sizeof (headers));
}
}
/*
* checks for various well-known extensions. if two parts have different
* known extensions, we won't merge them.
*/
static int
UUSMPKnownExt (char *filename)
{
char **eiter = knownexts, *ptr=_FP_strrchr(filename, '.');
int count=0, where=0;
if (ptr == NULL)
return -1;
ptr++;
while (*eiter) {
if (_FP_stricmp (ptr, (**eiter=='@')?*eiter+1:*eiter) == 0)
return where;
else
eiter++;
if (*eiter == NULL)
break;
if (**eiter=='@')
count++;
else
where = ++count;
}
return -1;
}
/*
* de-compress a binhex RLE stream
* the data read from in is uncompressed, and at most maxcount bytes
* (or octets, as they say) are copied to out. Because an uncompression
* might not be completed because of this maximum number of bytes. There-
* for, the leftover character and repetition count is saved. If a marker
* has been read but not the repetition count, *rpc is set to -256.
*
* the function returns the number of bytes eaten from in. If opc is not
* NULL, the total number of characters stored in out is saved there
*
* with repetition counts, remember that we've already transferred *one*
* occurence
*/
int
UUbhdecomp (char *in, char *out, char *last, int *rpc,
size_t inc, size_t max, size_t *opc)
{
size_t count, used=0, dummy;
char marker = '\220' /* '\x90' */;
if (opc == NULL)
opc = &dummy;
else
*opc = 0;
if (*rpc == -256) {
if (inc == 0)
return 0;
*rpc = (int) (unsigned char) *in++; used++;
if (*rpc == 0) {
*last = *out++ = marker;
max--; *opc+=1;
}
else
*rpc-=1;
}
if (*rpc) {
count = (max > (size_t) *rpc) ? (size_t) *rpc : max;
memset (out, *last, count);
out += count;
*opc += count;
max -= count;
*rpc -= count;
}
while (used < inc && max) {
if (*in == marker) {
used++; in++;
if (used == inc) {
*rpc = -256;
return used;
}
*rpc = (int) (unsigned char) *in++; used++;
if (*rpc == 0) {
*last = *out++ = marker;
max--; *opc+=1;
continue;
}
else
*rpc -= 1;
count = (max > (size_t) *rpc) ? (size_t) *rpc : max;
memset (out, *last, count);
out += count;
*opc += count;
max -= count;
*rpc -= count;
}
else {
*last = *out++ = *in++;
used++; *opc+=1; max--;
}
}
return used;
}
/*
* write to binhex file
*/
size_t
UUbhwrite (char *ptr, size_t sel, size_t nel, FILE *file)
{
char *tmpstring=uuutil_bhwtmp;
static int rpc = 0;
static char lc;
int count, tc=0;
size_t opc;
if (ptr == NULL) { /* init */
rpc = 0;
return 0;
}
while (nel || (rpc != 0 && rpc != -256)) {
count = UUbhdecomp (ptr, tmpstring, &lc, &rpc,
nel, 256, &opc);
if (fwrite (tmpstring, 1, opc, file) != opc)
return 0;
if (ferror (file))
return 0;
nel -= count;
ptr += count;
tc += count;
}
return tc;
}
static uulist *
UU_smparts_r (uulist *addit, int pass)
{
uulist *iter = UUGlobalFileList;
uufile *fiter, *dest, *temp;
int count, flag, a, b;
while (iter) {
if ((iter->state & UUFILE_OK) || iter->uudet == 0) {
iter = iter->NEXT;
continue;
}
if (iter == addit) {
iter = iter->NEXT;
continue;
}
if ((iter->begin && addit->begin) || (iter->end && addit->end) ||
(iter->uudet != addit->uudet)) {
iter = iter->NEXT;
continue;
}
if ((a = UUSMPKnownExt (addit->subfname)) != -1 &&
(b = UUSMPKnownExt (iter->subfname)) != -1)
if (a != b) {
iter = iter->NEXT;
continue;
}
flag = count = 0;
fiter = iter->thisfile;
temp = addit->thisfile;
dest = NULL;
while (temp) {
if (!(temp->data->uudet)) {
temp = temp->NEXT;
continue;
}
while (fiter && fiter->partno < temp->partno) {
dest = fiter;
fiter = fiter->NEXT;
}
if (fiter && fiter->partno == temp->partno) {
flag = 0;
break;
}
else {
flag = 1;
count += ((dest) ? temp->partno - dest->partno - 1 : 0) +
((fiter) ? fiter->partno - temp->partno - 1 : 0);
}
temp = temp->NEXT;
}
if (flag == 0 ||
(pass == 0 && count > 0) ||
(pass == 1 && count > 5)) {
iter = iter->NEXT;
continue;
}
dest = iter->thisfile;
fiter = addit->thisfile;
if (iter->filename == NULL && addit->filename != NULL)
iter->filename = _FP_strdup (addit->filename);
if (addit->begin) iter->begin = 1;
if (addit->end) iter->end = 1;
if (addit->mode != 0 && iter->mode == 0)
iter->mode = addit->mode;
while (fiter) {
flag = 0;
if (fiter->partno == iter->thisfile->partno ||
(dest->NEXT != NULL && fiter->partno == dest->NEXT->partno)) {
temp = fiter->NEXT;
fiter->NEXT = NULL;
UUkillfile (fiter);
addit->thisfile= temp;
fiter = temp;
continue;
}
if (fiter->partno < iter->thisfile->partno) {
temp = fiter->NEXT;
fiter->NEXT = iter->thisfile;
iter->thisfile = fiter;
dest = fiter;
addit->thisfile= temp;
fiter = temp;
}
else if (dest->NEXT == NULL || fiter->partno < dest->NEXT->partno) {
temp = fiter->NEXT;
fiter->NEXT = dest->NEXT;
dest->NEXT = fiter;
addit->thisfile= temp;
fiter = temp;
}
else {
dest = dest->NEXT;
}
}
break;
}
return iter;
}
int UUEXPORT
UUSmerge (int pass)
{
uulist *iter = UUGlobalFileList, *last=NULL, *res, *temp;
int flag = 0;
while (iter) {
if ((iter->state & UUFILE_OK) || iter->uudet == 0) {
last = iter;
iter = iter->NEXT;
continue;
}
if ((res = UU_smparts_r (iter, pass)) != NULL) {
UUMessage (uuutil_id, __LINE__, UUMSG_MESSAGE,
uustring (S_SMERGE_MERGED),
(iter->subfname) ? iter->subfname : "",
(res->subfname) ? res->subfname : "", pass);
temp = iter->NEXT;
iter->NEXT = NULL;
UUkilllist (iter);
flag++;
if (last == NULL) {
UUGlobalFileList = temp;
iter = temp;
}
else {
last->NEXT = temp;
iter = temp;
}
continue;
}
last = iter;
iter = iter->NEXT;
}
/*
* check again
*/
UUCheckGlobalList ();
return flag;
}