📄 fcbfns.c
字号:
/****************************************************************/
/* */
/* fcbfns.c */
/* */
/* Old CP/M Style Function Handlers for Kernel */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C 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, or (at your option) any later version. */
/* */
/* DOS-C 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. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#include "portab.h"
#include "globals.h"
#ifdef VERSION_STRINGS
static BYTE *RcsId =
"$Id: fcbfns.c,v 1.44 2004/05/24 11:42:28 bartoldeman Exp $";
#endif
#define FCB_SUCCESS 0
#define FCB_ERR_NODATA 1
#define FCB_ERR_SEGMENT_WRAP 2
#define FCB_ERR_EOF 3
#define FCB_ERROR 0xff
STATIC fcb FAR *ExtFcbToFcb(xfcb FAR * lpExtFcb);
STATIC fcb FAR *CommonFcbInit(xfcb FAR * lpExtFcb, BYTE * pszBuffer,
COUNT * pCurDrive);
STATIC void FcbNameInit(fcb FAR * lpFcb, BYTE * pszBuffer, COUNT * pCurDrive);
STATIC void FcbNextRecord(fcb FAR * lpFcb);
STATIC void FcbCalcRec(xfcb FAR * lpXfcb);
#define TestCmnSeps(lpFileName) (*lpFileName && strchr(":<|>+=,", *lpFileName) != NULL)
#define TestFieldSeps(lpFileName) ((unsigned char)*lpFileName <= ' ' || strchr("/\"[]<>|.", *lpFileName) != NULL)
static dmatch Dmatch;
BYTE FAR *FatGetDrvData(UBYTE drive, UWORD * spc, UWORD * bps, UWORD * nc)
{
static BYTE mdb;
/* get the data available from dpb */
if (DosGetFree(drive, spc, NULL, bps, nc))
{
struct dpb FAR *dpbp = get_dpb(drive == 0 ? default_drive : drive - 1);
/* Point to the media desctriptor for this drive */
if (dpbp == NULL)
{
mdb = *spc >> 8;
*spc &= 0xff;
return &mdb;
}
else
{
return (BYTE FAR *) & (dpbp->dpb_mdb);
}
}
return NULL;
}
#define PARSE_SEP_STOP 0x01
#define PARSE_DFLT_DRIVE 0x02
#define PARSE_BLNK_FNAME 0x04
#define PARSE_BLNK_FEXT 0x08
#define PARSE_RET_NOWILD 0
#define PARSE_RET_WILD 1
#define PARSE_RET_BADDRIVE 0xff
#ifndef IPL
UWORD FcbParseFname(int *wTestMode, const BYTE FAR * lpFileName, fcb FAR * lpFcb)
{
WORD wRetCodeName = FALSE, wRetCodeExt = FALSE;
/* pjv -- ExtFcbToFcb? */
/* Start out with some simple stuff first. Check if we are */
/* going to use a default drive specificaton. */
if (!(*wTestMode & PARSE_DFLT_DRIVE))
lpFcb->fcb_drive = FDFLT_DRIVE;
if (!(*wTestMode & PARSE_BLNK_FNAME))
{
fmemset(lpFcb->fcb_fname, ' ', FNAME_SIZE);
}
if (!(*wTestMode & PARSE_BLNK_FEXT))
{
fmemset(lpFcb->fcb_fext, ' ', FEXT_SIZE);
}
/* Undocumented behavior, set record number & record size to 0 */
lpFcb->fcb_cublock = lpFcb->fcb_recsiz = 0;
if (!(*wTestMode & PARSE_SEP_STOP))
{
lpFileName = ParseSkipWh(lpFileName);
if (TestCmnSeps(lpFileName))
++lpFileName;
}
/* Undocumented "feature," we skip white space anyway */
lpFileName = ParseSkipWh(lpFileName);
/* Now check for drive specification */
if (*(lpFileName + 1) == ':')
{
/* non-portable construct to be changed */
REG UBYTE Drive = DosUpFChar(*lpFileName) - 'A';
if (Drive >= lastdrive)
{
*wTestMode = PARSE_RET_BADDRIVE;
return FP_OFF(lpFileName);
}
lpFcb->fcb_drive = Drive + 1;
lpFileName += 2;
}
/* special cases: '.' and '..' */
if (*lpFileName == '.')
{
lpFcb->fcb_fname[0] = '.';
++lpFileName;
if (*lpFileName == '.')
{
lpFcb->fcb_fname[1] = '.';
++lpFileName;
}
*wTestMode = PARSE_RET_NOWILD;
return FP_OFF(lpFileName);
}
/* Now to format the file name into the string */
lpFileName =
GetNameField(lpFileName, (BYTE FAR *) lpFcb->fcb_fname, FNAME_SIZE,
(BOOL *) & wRetCodeName);
/* Do we have an extension? If do, format it else return */
if (*lpFileName == '.')
lpFileName =
GetNameField(++lpFileName, (BYTE FAR *) lpFcb->fcb_fext,
FEXT_SIZE, (BOOL *) & wRetCodeExt);
*wTestMode = (wRetCodeName | wRetCodeExt) ? PARSE_RET_WILD : PARSE_RET_NOWILD;
return FP_OFF(lpFileName);
}
const BYTE FAR * ParseSkipWh(const BYTE FAR * lpFileName)
{
while (*lpFileName == ' ' || *lpFileName == '\t')
++lpFileName;
return lpFileName;
}
#if 0 /* defined above */
BOOL TestCmnSeps(BYTE FAR * lpFileName)
{
BYTE *pszTest, *pszCmnSeps = ":<|>+=,";
for (pszTest = pszCmnSeps; *pszTest != '\0'; ++pszTest)
if (*lpFileName == *pszTest)
return TRUE;
return FALSE;
}
#endif
#if 0
BOOL TestFieldSeps(BYTE FAR * lpFileName)
{
BYTE *pszTest, *pszCmnSeps = "/\"[]<>|.";
/* Another non-portable construct */
if (*lpFileName <= ' ')
return TRUE;
for (pszTest = pszCmnSeps; *pszTest != '\0'; ++pszTest)
if (*lpFileName == *pszTest)
return TRUE;
return FALSE;
}
#endif
const BYTE FAR * GetNameField(const BYTE FAR * lpFileName, BYTE FAR * lpDestField,
COUNT nFieldSize, BOOL * pbWildCard)
{
COUNT nIndex = 0;
BYTE cFill = ' ';
while (*lpFileName != '\0' && !TestFieldSeps(lpFileName)
&& nIndex < nFieldSize)
{
if (*lpFileName == ' ')
break;
if (*lpFileName == '*')
{
*pbWildCard = TRUE;
cFill = '?';
++lpFileName;
break;
}
if (*lpFileName == '?')
*pbWildCard = TRUE;
*lpDestField++ = DosUpFChar(*lpFileName++);
++nIndex;
}
/* Blank out remainder of field on exit */
fmemset(lpDestField, cFill, nFieldSize - nIndex);
return lpFileName;
}
STATIC VOID FcbNextRecord(fcb FAR * lpFcb)
{
if (++lpFcb->fcb_curec >= 128)
{
lpFcb->fcb_curec = 0;
++lpFcb->fcb_cublock;
}
}
STATIC ULONG FcbRec(fcb FAR *lpFcb)
{
return ((ULONG) lpFcb->fcb_cublock * 128) + lpFcb->fcb_curec;
}
UBYTE FcbReadWrite(xfcb FAR * lpXfcb, UCOUNT recno, int mode)
{
ULONG lPosit;
long nTransfer;
fcb FAR *lpFcb;
unsigned size;
unsigned long bigsize;
unsigned recsiz;
/* Convert to fcb if necessary */
lpFcb = ExtFcbToFcb(lpXfcb);
recsiz = lpFcb->fcb_recsiz;
bigsize = (ULONG)recsiz * recno;
if (bigsize > 0xffff)
return FCB_ERR_SEGMENT_WRAP;
size = (unsigned)bigsize;
if (FP_OFF(dta) + size < FP_OFF(dta))
return FCB_ERR_SEGMENT_WRAP;
/* Now update the fcb and compute where we need to position */
/* to. */
lPosit = FcbRec(lpFcb) * recsiz;
if ((CritErrCode = -SftSeek(lpFcb->fcb_sftno, lPosit, 0)) != SUCCESS)
return FCB_ERR_NODATA;
/* Do the read */
nTransfer = DosRWSft(lpFcb->fcb_sftno, size, dta, mode & ~XFR_FCB_RANDOM);
if (nTransfer < 0)
CritErrCode = -(int)nTransfer;
/* Now find out how we will return and do it. */
if (mode & XFR_WRITE)
lpFcb->fcb_fsize = SftGetFsize(lpFcb->fcb_sftno);
/* if end-of-file, then partial read should count last record */
if (mode & XFR_FCB_RANDOM && recsiz > 0)
lpFcb->fcb_rndm += ((unsigned)nTransfer + recsiz - 1) / recsiz;
size -= (unsigned)nTransfer;
if (size == 0)
{
FcbNextRecord(lpFcb);
return FCB_SUCCESS;
}
size %= lpFcb->fcb_recsiz;
if (mode & XFR_READ && size > 0)
{
fmemset((char FAR *)dta + (unsigned)nTransfer, 0, size);
FcbNextRecord(lpFcb);
return FCB_ERR_EOF;
}
return FCB_ERR_NODATA;
}
UBYTE FcbGetFileSize(xfcb FAR * lpXfcb)
{
int FcbDrive, sft_idx;
unsigned recsiz;
/* Build a traditional DOS file name */
fcb FAR *lpFcb = CommonFcbInit(lpXfcb, SecPathName, &FcbDrive);
recsiz = lpFcb->fcb_recsiz;
/* check for a device */
if (!lpFcb || IsDevice(SecPathName) || (recsiz == 0))
return FCB_ERROR;
sft_idx = (short)DosOpenSft(SecPathName, O_LEGACY | O_RDONLY | O_OPEN, 0);
if (sft_idx >= 0)
{
ULONG fsize;
/* Get the size */
fsize = SftGetFsize(sft_idx);
/* compute the size and update the fcb */
lpFcb->fcb_rndm = (fsize + (recsiz - 1)) / recsiz;
/* close the file and leave */
if ((CritErrCode = -DosCloseSft(sft_idx, FALSE)) == SUCCESS)
return FCB_SUCCESS;
}
else
CritErrCode = -sft_idx;
return FCB_ERROR;
}
void FcbSetRandom(xfcb FAR * lpXfcb)
{
/* Convert to fcb if necessary */
fcb FAR *lpFcb = ExtFcbToFcb(lpXfcb);
/* Now update the fcb and compute where we need to position */
/* to. */
lpFcb->fcb_rndm = FcbRec(lpFcb);
}
void FcbCalcRec(xfcb FAR * lpXfcb)
{
/* Convert to fcb if necessary */
fcb FAR *lpFcb = ExtFcbToFcb(lpXfcb);
/* Now update the fcb and compute where we need to position */
/* to. */
lpFcb->fcb_cublock = (UWORD)(lpFcb->fcb_rndm / 128);
lpFcb->fcb_curec = (UBYTE)lpFcb->fcb_rndm & 127;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -