decode.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 609 行 · 第 1/2 页
C
609 行
curroffset++;
}
}
extern void NoShannonDecode( unsigned long textsize )
/***************************************************/
/* Decoding/Uncompressing */
{
int i, j, k, r, c;
unsigned long count;
if (textsize == 0) return;
getlen = 0;
getbuf = 0;
secondbuf = DecReadByte();
for (i = 0; i < N - F; i++) {
text_buf[i] = ' ';
}
r = N - F;
for (count = 0; count < textsize; ) {
if( getlen == 0 ) {
getbuf = ((unsigned short)secondbuf << 8) | DecReadByte();
getlen = 16;
secondbuf = DecReadByte();
} else if( getlen <= 8 ) {
getbuf |= (unsigned short)secondbuf << ( 8 - getlen );
getlen += 8;
secondbuf = DecReadByte();
}
if( (short int) getbuf < 0 ) { // it is a copy command.
j = (getbuf >> 9) & 0x3F;
getlen -= 7;
getbuf <<= 7;
i = (r - DecodePosition() - 1) & (N - 1);
for (k = 0; k < j; k++) {
c = text_buf[(i + k) & (N - 1)];
text_buf[r++] = c;
DecWriteByte( c );
r &= (N - 1);
}
count += j;
} else {
c = getbuf >> 7;
getbuf <<= 9;
getlen -= 9;
DecWriteByte( c);
text_buf[r++] = c;
r &= (N - 1);
count++;
}
}
FlushWrite();
}
extern void DoDecode( unsigned long textsize )
/********************************************/
/* Decoding/Uncompressing */
{
int i, j, k, r, c;
int spare;
int codelen;
unsigned long count;
if (textsize == 0) return;
MakeShannonTrie();
getlen = 0;
getbuf = 0;
secondbuf = DecReadByte();
for (i = 0; i < N - F; i++) {
text_buf[i] = ' ';
}
r = N - F;
for (count = 0; count < textsize; ) {
if( getlen < 8 ) {
getbuf |= (unsigned short)secondbuf << ( 8 - getlen );
getlen += 8;
secondbuf = DecReadByte();
}
spare = getlen - 8;
getlen = 16;
getbuf |= secondbuf >> spare; // fill getbuf to 16 bits.
codelen = MinCodeLen;
for(;;) {
if( getbuf >= MinVal[ codelen ] )break;
codelen++;
}
c = CharMap[ MapOffset[ codelen ] +
((getbuf - MinVal[ codelen ]) >> (16 - codelen)) ];
getbuf <<= codelen;
getlen -= codelen;
if( spare > codelen ) {
getlen -= 8 - spare;
} else {
getbuf |= (secondbuf & Mask[ spare ]) << (codelen - spare);
getlen += spare;
secondbuf = DecReadByte();
}
if (c < 256) {
DecWriteByte( c);
text_buf[r++] = c;
r &= (N - 1);
count++;
} else {
i = (r - DecodePosition() - 1) & (N - 1);
j = c - 255 + THRESHOLD;
for (k = 0; k < j; k++) {
c = text_buf[(i + k) & (N - 1)];
text_buf[r++] = c;
DecWriteByte( c );
r &= (N - 1);
}
count += j;
}
}
FlushWrite();
}
static bool CompareCRC( unsigned long crcvalue )
/**********************************************/
// this modifies the old CRC for the bit lookahead, checks the CRC, and then
// it adds the lookahead to the CRC for the next file.
// note this assumes intel byte ordering
{
bool retval;
if( getlen == 16 ) {
ModifyCRC( &crcvalue, getbuf >> 8 );
ModifyCRC( &crcvalue, getbuf & 0xFF );
ModifyCRC( &crcvalue, secondbuf );
retval = CheckCRC( crcvalue );
UnReadByte( secondbuf );
UnReadByte( getbuf & 0xFF );
UnReadByte( getbuf >> 8 );
} else if( getlen >= 8 ) {
getbuf >>= 16 - getlen;
ModifyCRC( &crcvalue, getbuf & 0xFF );
ModifyCRC( &crcvalue, secondbuf );
retval = CheckCRC( crcvalue );
UnReadByte( secondbuf );
UnReadByte( getbuf );
} else {
ModifyCRC( &crcvalue, secondbuf );
retval = CheckCRC( crcvalue );
UnReadByte( secondbuf );
}
return( retval );
}
static int FileExists( char *name, file_info *info ); // FileExists defined further down in this file
extern bool DecodeFile( file_info *info, arccmd *cmd )
/****************************************************/
{
char drive[_MAX_DRIVE];
char directory[_MAX_DIR];
char fname[_MAX_FNAME];
char extin[_MAX_EXT];
char * name;
char * thename; // filename terminated with a nullchar.
int pathlen;
unsigned short namelen;
namelen = info->namelen & NAMELEN_MASK;
thename = alloca( namelen + 1 );
memcpy( thename, info->name, namelen );
*(thename + namelen) = '\0';
if( (cmd->flags & KEEP_PATHNAME) ) {
name = cmd->u.path;
} else if( !(cmd->flags & (REPLACE_PATH | PREPEND_PATH)) ) {
name = thename;
} else {
pathlen = strlen( cmd->u.path );
name = alloca( namelen + pathlen + 1 );
if( cmd->flags & REPLACE_PATH ) {
_splitpath( cmd->u.path, drive, directory, NULL, NULL );
_splitpath( thename, NULL, NULL, fname, extin );
_makepath( name, drive, directory, fname, extin );
} else {
memcpy( name, cmd->u.path, pathlen );
memcpy( name + pathlen, info->name, namelen );
*(name + pathlen + namelen) = '\0';
}
}
if( ! FileExists( name, info ) ) {
outfile = QOpenW( name );
if( outfile == -1 ) {
return( FALSE );
} else {
LogUnPacking( name );
if( info->namelen & NO_SHANNON_CODE ) {
NoShannonDecode( info->length );
} else {
DoDecode( info->length );
}
QClose( outfile );
QSetDate( name, info->stamp );
if( !CompareCRC( info->crc ) && info->length > 0 ) {
char msg[ 100 ];
strcpy( msg, LookupText( NULL, TXT_WARN_FILE ) );
strcat( msg, " \'" );
strcat( msg, name );
strcat( msg, "\' " );
strcat( msg, LookupText( NULL, TXT_INC_CRC ) );
Error( TXT_INC_CRC, msg );
return( FALSE );
}
}
}
return( TRUE );
}
static int FileExists( char *name, file_info *info ) /* 26-may-90 */
{
auto struct stat statblk;
#if !defined( UNIX ) && !defined( __UNIX__ )
unsigned attribute;
#endif
int rc;
rc = stat( name, &statblk );
if( rc == 0 ) {
#if defined( UNIX ) || defined( __UNIX__ )
if( !( statblk.st_mode & S_IWRITE ) ) {
#else
_dos_getfileattr( name, &attribute );
if( attribute & ( _A_RDONLY | _A_HIDDEN ) ) {
#endif
/* file is read-only */
if( !OK_ReplaceRDOnly( name ) ) {
return( 1 );
}
#if defined( UNIX ) || defined( __UNIX__ )
chmod( name, 0777 );
#else
_dos_setfileattr( name, _A_NORMAL );
#endif
}
if( UnPackHook( name ) ) return( 0 ); // this is allowed to modify name
if( statblk.st_mtime == info->stamp ) {
return( 1 );
}
if( statblk.st_mtime > info->stamp ) { /* 14-sep-91 */
/* file already exists with newer date */
if( !OK_ToReplace( name ) ) {
return( 1 );
}
}
} else {
UnPackHook( name );
}
return( 0 ); /* file does not exist, or it has different date or size */
}
extern int Decode( arccmd *cmd )
/*******************************/
{
file_info ** currfile;
file_info ** filedata;
wpackfile * currname;
arc_header header;
unsigned short namelen;
char *msg;
filedata = ReadHeader( cmd, &header );
if( filedata == NULL ) {
msg = LookupText( NULL, TXT_ARC_NOT_EXIST );
Error( TXT_ARC_NOT_EXIST, msg );
return FALSE;
}
if( cmd->files == NULL || cmd->files->filename == NULL ) {
// BufSeek( sizeof( arc_header ) ); // skip header.
for( currfile = filedata; *currfile != NULL; currfile++ ) {
if( BufSeek( (*currfile)->disk_addr ) != -1 ) {
if( !DecodeFile( *currfile, cmd ) ) {
return FALSE;
}
}
}
} else {
for( currname = cmd->files; currname->filename != NULL; currname++ ) {
for( currfile = filedata; *currfile != NULL; currfile++ ) {
namelen = (*currfile)->namelen & NAMELEN_MASK;
if( strlen( currname->filename ) == namelen &&
memicmp(currname->filename, (*currfile)->name, namelen) == 0 ) {
if( BufSeek( (*currfile)->disk_addr ) != -1 ) {
if( !DecodeFile( *currfile, cmd ) ) {
return FALSE;
}
}
break;
}
}
if( *currfile == NULL ) {
char msg[ 50 ];
strcpy( msg, LookupText( NULL, TXT_NOT_IN_ARC ) );
Log( LookupText( NULL, TXT_WARN_FILE ), "\"", currname->filename, "\"",
msg, NULL );
}
} // end for
} // end if
QClose( infile ); // close the archive file.
FreeHeader( filedata );
return TRUE;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?