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

📄 fcbfns.c

📁 开源DOS的C代码源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************/
/*                                                              */
/*                          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 + -