📄 expand.c
字号:
// LZInitTree
//
// Initializes trees for LZ compression.
//
void LZInitTree(void)
{
int i;
/* For i = 0 to cbRingBufMax - 1, rightChild[i] and leftChild[i] will be the
right and left children of node i. These nodes need not be initialized.
Also, parent[i] is the parent of node i. These are initialized to
NIL (= N), which stands for 'not used.'
For i = 0 to 255, rightChild[cbRingBufMax + i + 1] is the root of the tree
for strings that begin with character i. These are initialized to NIL.
n.b., there are 256 trees.
*/
for (i = cbRingBufMax + 1; i <= cbRingBufMax + 256; i++)
rightChild[i] = NIL;
for (i = 0; i < cbRingBufMax; i++)
parent[i] = NIL;
return;
} // LZInitTree()
// LZInsertNode()
//
// Inserts string of length cbStrMax, rguchRingBuf[r..r + cbStrMax - 1], into one of
// the trees (rguchRingBuf[r]'th tree) and returns the longest-match position
// and length via the global variables iCurMatch and cbCurMatch. If
// cbCurMatch == cbStrMax, removes the old node in favor of the new one,
// since the old one will be deleted sooner. n.b., r plays a double role, as
// both tree node and position in buffer.
//
void LZInsertNode(int r) // node to insert
{
int i, p, cmp;
UCHAR FAR *key;
cmp = 1;
key = &rguchRingBuf[r];
p = cbRingBufMax + 1 + key[0];
rightChild[r] = leftChild[r] = NIL;
cbCurMatch = 0;
FOREVER
{
if (cmp >= 0)
{
if (rightChild[p] != NIL)
p = rightChild[p];
else
{
rightChild[p] = r;
parent[r] = p;
return;
}
}
else
{
if (leftChild[p] != NIL)
p = leftChild[p];
else
{
leftChild[p] = r;
parent[r] = p;
return;
}
}
for (i = 1; i < cbStrMax; i++)
if ((cmp = key[i] - rguchRingBuf[p + i]) != 0)
break;
if (i > cbCurMatch)
{
iCurMatch = p;
if ((cbCurMatch = i) >= cbStrMax)
break;
}
}
parent[r] = parent[p];
leftChild[r] = leftChild[p];
rightChild[r] = rightChild[p];
parent[leftChild[p]] = r;
parent[rightChild[p]] = r;
if (rightChild[parent[p]] == p)
rightChild[parent[p]] = r;
else
leftChild[parent[p]] = r;
parent[p] = NIL; // remove p
return;
} // LZInsertNode()
// LZDeleteNode()
//
// Deletes node p from tree.
//
void LZDeleteNode(int p) // node to delete
{
int q;
if (parent[p] == NIL)
// node p is not in the tree
return;
if (rightChild[p] == NIL)
q = leftChild[p];
else if (leftChild[p] == NIL)
q = rightChild[p];
else
{
q = leftChild[p];
if (rightChild[q] != NIL)
{
do
{
q = rightChild[q];
} while (rightChild[q] != NIL);
rightChild[parent[q]] = leftChild[q];
parent[leftChild[q]] = parent[q];
leftChild[q] = leftChild[p];
parent[leftChild[p]] = q;
}
rightChild[q] = rightChild[p];
parent[rightChild[p]] = q;
}
parent[q] = parent[p];
if (rightChild[parent[p]] == p)
rightChild[parent[p]] = q;
else
leftChild[parent[p]] = q;
parent[p] = NIL; // remove p
return;
} // LZDeleteNode()
/* int GetSourceHandle(char *pszSource)
*
* Get Source file handle.
*
* ENTRY: pszSource -> Source filename
*
* EXIT: returns file handle; file handle = -1 if source file not found.
*
* NOTES: If the pszSource filename can't be found, we try an alternate
* filename by substituting the '_' for the 3rd character of the
* pszSource filename extension.
*
* HISTORY: M001 Created.
*
*/
int GetSourceHandle(char *pszSource)
{
int i;
int doshSrc; /* Source file handle */
char szAltSource[MAXFILESPECLEN]; /* Alternate source file name */
if ( (doshSrc = FOPEN(pszSource)) != -1 )
return(doshSrc);
else
{
if( (i = strlen(pszSource)) > (MAXFILESPECLEN - 1) ||
i < 5 ||
pszSource[i-4] != CHAR_PERIOD )
{
return(doshSrc);
}
else
strcpy(szAltSource, pszSource);
/* Change 3rd character of extension to '_' */
szAltSource[i-1] = CHAR_UNDERSCORE;
if( (doshSrc = FOPEN(szAltSource)) == -1 )
return(doshSrc);
else
{
/* Alternate filename found, so reflect change in pszSource. */
pszSource[i-1] = CHAR_UNDERSCORE;
return(doshSrc);
}
}
}
BOOL GetIOHandles(char *pszSource,char *pszDest,int *pdoshSource,int *pdoshDest)
{
if (pszSource != NULL)
{
/* M001: Find and open source file */
if ((*pdoshSource = GetSourceHandle(pszSource)) == -1)
{
printf(pszNO_OPEN_INPUT, pszSource);
return(FALSE);
}
// Move to the end of the input file to find its length,
// then return to the beginning.
if ((cblInSize = FSEEK(*pdoshSource, 0L, SEEK_END)) < 0L ||
FSEEK(*pdoshSource, 0L, SEEK_SET) != 0L)
{
FCLOSE(*pdoshSource);
printf(pszNO_READ_INPUT, pszSource);
return(FALSE);
}
}
else
*pdoshSource = -1;
// Set up output DOS file handle.
if (pszDest != NULL)
{
/* M001: Verify that source and destination files are not the same file.
* Must do this BEFORE creating destination file, since if source
* == dest., the dest. create operation will truncate source file to
* zero length.
*/
if( IsSourceDest(pszSource, pszDest) )
{
printf(pszSOURCE_IS_DEST, pszSource);
return(FALSE);
}
if ((*pdoshDest = FCREATE(pszDest)) == -1)
{
FCLOSE(*pdoshSource);
printf(pszNO_OPEN_OUTPUT, pszDest);
return(FALSE);
}
}
else
*pdoshDest = -1;
return(TRUE);
} // GetIOHandles()
/* BOOL Decompress( char *pszSource, char *pszDest );
*
* Decompress source to destination.
*
* ENTRY: pszSource -> Source pathname
* pszDest -> Destination pathname
*
* EXIT: TRUE if successful; FALSE otherwise.
*
* HISTORY: M001 Added progress messages.
*
*/
BOOL Decompress(char *pszSource,
char *pszDest)
{
int doshSource, // input file handle
doshDest, // output file handle
fAppsComp, // 'apps' compression
f;
FH FHIn; // structure holding header information from
// compressed input file (used for decoding)
long lWritten;
// Set up source and dest file handles.
if (! GetIOHandles(pszSource, pszDest, &doshSource, &doshDest))
return(FALSE);
// Determine if file was compressed using one of the special applications
// division methods.
fAppsComp = WReadHeaderInfo(doshSource) > 0;
// make sure source file is in compressed format
// make sure file shows Lempel-Ziv algorithm indicator
if (! fAppsComp &&
(! GetHdr(&FHIn, doshSource) || ! ChkHdr(FHIn) ||
(FHIn.uchAlgorithm != uchALG_LEMPEL_ZIV)))
{
BOOL rc = FALSE;
printf(pszINPUT_NOT_COMPRESSED_FMT, pszSource); /* M001 */
/* seek to beginning of file because of header read */
if ( FSEEK(doshSource, 0L, SEEK_SET) == 0L )
{
/* M001: Display progress message. */
printf( pszPROGRESS, strupr(pszSource), strupr(pszDest) );
/* Copy file */
rc = (BOOL) fnFileCopy(doshDest,doshSource);
}
FCLOSE(doshDest);
FCLOSE(doshSource);
if( rc == TRUE )
iFiles++; /* M001: Update file count */
return(rc);
}
// set up globals for reading and writing
pszInFile = pszSource;
pszOutFile = pszDest;
doshIn = doshSource;
doshOut = doshDest;
// compressed header found, so decompress file
/* M001: Display progress message. */
printf( pszPROGRESS, strupr(pszSource), strupr(pszDest) );
if (fAppsComp)
{
f = LZDECODE_OK;
lWritten = LcbDecompressToFile( doshSource, doshDest, LCBNIL, 0L, TRUE );
if (lWritten < 0L)
if (lWritten == rcWriteError)
f = LZERROR_BADOUTHANDLE;
else if (lWritten == rcReadError)
f = LZERROR_BADINHANDLE;
else
f = LZERROR_READ;
}
if (!fAppsComp)
f = LZDecode(doshSource, doshDest);
if (f != LZDECODE_OK)
{
if (f == LZERROR_BADINHANDLE)
printf(pszNO_READ_INPUT, pszSource);
else if (f == LZERROR_BADOUTHANDLE)
printf(pszNO_WRITE_OUTPUT, pszDest);
else if (f == LZERROR_READ)
printf(pszFORMAT_ERROR, pszSource);
else // (f == LZERROR_WRITE), actually this case will never occur
// since the multi-disk version of writeOutBuf() can only
// return LZERROR_BADINHANDLE or LZERROR_BADOUTHANDLE as error
// conditions
printf(pszOUT_OF_SPACE, pszDest);
FCLOSE(doshSource);
FCLOSE(doshDest);
return(EXIT_FAILURE);
}
/* M001: At this point, source file has been expanded to destination, so
* update file count.
*/
iFiles++;
f = CopyCreateDate(doshSource, doshDest);
if (doshDest != NO_DOSH && f != COPYCREATEDATE_OK)
{
printf(pszNO_COPY_TIME);
if (f == LZERROR_BADINHANDLE)
printf(pszFROM_INPUT, pszSource);
else // (f == LZERROR_BADOUTHANDLE)
printf(pszTO_OUTPUT, pszDest);
FCLOSE(doshSource);
FCLOSE(doshDest);
return(FALSE);
}
FCLOSE(doshSource);
FCLOSE(doshDest);
return(TRUE);
} // Decompress()
/* unsigned fnFileCopy(int doshDest, int doshSource);
*
* Function copies files given a source and destination file handle.
* will preserve source file date and time.
*
* ENTRY: doshDest - destination file handle.
*
* doshSource - Source file handle.
*
* EXIT: unsigned as to success or failure of file copy function.
*
* Zero == Success. Non Zero == Failure.
*
*/
unsigned fnFileCopy(fhDst,fhSrc)
int fhDst;
int fhSrc;
{
LPSTR lpBuf = NULL; /* copy buffer pointer */
unsigned size;
unsigned date;
unsigned time;
int f = 0;
_dos_getftime(fhSrc,&date,&time);
lpBuf = FALLOC(4096*sizeof(char)); // 4kb on far heap for a copy buffer.
if (! lpBuf )
return(FALSE);
while (size = FREAD(fhSrc,lpBuf,4096)) {
if (FWRITE(fhDst,lpBuf,size) != size) {
/* write error? */
f = FERROR();
if (f == ERROR_OK)
f = ERROR_WRITE;
break;
}
}
FFREE(lpBuf);
if (! f )
{
_dos_setftime(fhDst,date,time);
f = TRUE;
}
return f;
}
/* BOOL IsSourceDest( char *pszSource, char *pszDest );
*
* Checks if source and destination files are the same file.
*
* ENTRY: pszSource -> source filename
* pszDest -> destination filename
*
* EXIT: TRUE if files are the same; FALSE otherwise.
*
* NOTES: If DOS version >= 3.1, we use the DOS Truename function. Else,
* we do a DosFindFirst() and compare the reserved fields in the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -