⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expand.c

📁 DOS 源代码 系列之 command 源码
💻 C
📖 第 1 页 / 共 3 页
字号:


// 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 + -