Beispiel #1
0
STATIC int CharRequest(struct dhdr FAR **pdev, unsigned command)
{
  struct dhdr FAR *dev = *pdev;
  CharReqHdr.r_command = command;
  CharReqHdr.r_unit = 0;
  CharReqHdr.r_status = 0;
  CharReqHdr.r_length = sizeof(request);
  execrh(&CharReqHdr, dev);
  if (CharReqHdr.r_status & S_ERROR)
  {
    for (;;) {
      switch (char_error(&CharReqHdr, dev))
      {
      case ABORT:
      case FAIL:
        return DE_INVLDACC;
      case CONTINUE:
        CharReqHdr.r_count = 0;
        return 0;
      case RETRY:
        return 1;
      }
    }
  }
  return SUCCESS;
}
Beispiel #2
0
COUNT DosSetTime(BYTE FAR * hp, BYTE FAR * mp, BYTE FAR * sp, BYTE FAR * hdp)
{
  DosGetDate((BYTE FAR *) & DayOfWeek, (BYTE FAR *) & Month,
             (BYTE FAR *) & DayOfMonth, (COUNT FAR *) & Year);

  ClkRecord.clkHours = *hp;
  ClkRecord.clkMinutes = *mp;
  ClkRecord.clkSeconds = *sp;
  ClkRecord.clkHundredths = *hdp;

  YearsSince1980 = Year - 1980;
  ClkRecord.clkDays = DayOfMonth - 1
      + days[is_leap_year(Year)][Month - 1]
      + ((YearsSince1980) * 365)
      + ((YearsSince1980 + 3) / 4);

  ClkReqHdr.r_length = sizeof(request);
  ClkReqHdr.r_command = C_OUTPUT;
  ClkReqHdr.r_count = sizeof(struct ClockRecord);
  ClkReqHdr.r_trans = (BYTE FAR *) (&ClkRecord);
  ClkReqHdr.r_status = 0;
  execrh((request FAR *) & ClkReqHdr, (struct dhdr FAR *)clock);
  if (ClkReqHdr.r_status & S_ERROR)
    return char_error(&ClkReqHdr, (struct dhdr FAR *)clock);
  return SUCCESS;
}
Beispiel #3
0
UCOUNT BinaryCharIO(struct dhdr FAR * dev, UCOUNT n, void FAR * bp, unsigned command, COUNT *err)
{
  *err = SUCCESS;
    
  FOREVER
  {
    CharReqHdr.r_length = sizeof(request);
    CharReqHdr.r_command = command;
    CharReqHdr.r_count = n;
    CharReqHdr.r_trans = bp;
    CharReqHdr.r_status = 0;
    execrh(&CharReqHdr, dev);
    if (CharReqHdr.r_status & S_ERROR)
    {
    charloop:
      switch (char_error(&CharReqHdr, dev))
      {
        case ABORT:
        case FAIL:
          *err = DE_INVLDACC;
          return 0;
        case CONTINUE:
          break;
        case RETRY:
          continue;
        default:
          goto charloop;
      }
    }
    break;
  }
  return CharReqHdr.r_count;
}
Beispiel #4
0
COUNT DosSetTime(BYTE h, BYTE m, BYTE s, BYTE hd)
{
  /* for ClkRecord.clkDays */
  ExecuteClockDriverRequest(C_INPUT);

  ClkRecord.clkHours = h;
  ClkRecord.clkMinutes = m;
  ClkRecord.clkSeconds = s;
  ClkRecord.clkHundredths = hd;

  ExecuteClockDriverRequest(C_OUTPUT);

  if (ClkReqHdr.r_status & S_ERROR)
    return char_error(&ClkReqHdr, (struct dhdr FAR *)clock);
  return SUCCESS;
}
Beispiel #5
0
UCOUNT DosWrite(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err)
{
  sft FAR *s;
  WORD sys_idx;
  sfttbl FAR *sp;
  UCOUNT ReadCount;

  /* Test that the handle is valid                */
  if (hndl < 0)
  {
    *err = DE_INVLDHNDL;
    return 0;
  }

  /* Get the SFT block that contains the SFT      */
  if ((s = get_sft(hndl)) == (sft FAR *) - 1)
  {
    *err = DE_INVLDHNDL;
    return 0;
  }

  /* If this is not opened and it's not a write   */
  /* another error                                */
  if (s->sft_count == 0 ||
      (!(s->sft_mode & SFT_MWRITE) && !(s->sft_mode & SFT_MRDWR)))
  {
    *err = DE_ACCESS;
    return 0;
  }
  if (s->sft_flags & SFT_FSHARED)
  {
    ReadCount = Remote_RW(REM_WRITE, n, bp, s, err);
    if (err)
    {
      return ReadCount;
    }
    else
      return 0;
  }

  /* Do a device write if device                  */
  if (s->sft_flags & SFT_FDEVICE)
  {
    request rq;

    /* set to no EOF                        */
    s->sft_flags &= ~SFT_FEOF;

    /* if null just report full transfer    */
    if (s->sft_flags & SFT_FNUL)
    {
      *err = SUCCESS;
      return n;
    }

    /* Now handle raw and cooked modes      */
    if (s->sft_flags & SFT_FBINARY)
    {
      rq.r_length = sizeof(request);
      rq.r_command = C_OUTPUT;
      rq.r_count = n;
      rq.r_trans = (BYTE FAR *) bp;
      rq.r_status = 0;
      execrh((request FAR *) & rq, s->sft_dev);
      if (rq.r_status & S_ERROR)
      {
        char_error(&rq, s->sft_dev);
      }
      else
      {
        if (s->sft_flags & SFT_FCONOUT)
        {
          WORD cnt = rq.r_count;
          while (cnt--)
          {
            switch (*bp++)
            {
              case CR:
                scr_pos = 0;
                break;
              case LF:
              case BELL:
                break;
              case BS:
                --scr_pos;
                break;
              default:
                ++scr_pos;
            }
          }
        }
        *err = SUCCESS;
        return rq.r_count;
      }
    }
    else
    {
      REG WORD c,
        cnt = n,
        spaces_left = 0,
        next_pos,
        xfer = 0;
      static BYTE space = ' ';

    start:
      if (cnt-- == 0)
        goto end;
      if (*bp == CTL_Z)
        goto end;
      if (s->sft_flags & SFT_FCONOUT)
      {
        switch (*bp)
        {
          case CR:
            next_pos = 0;
            break;
          case LF:
          case BELL:
            next_pos = scr_pos;
            break;
          case BS:
            next_pos = scr_pos ? scr_pos - 1 : 0;
            break;
          case HT:
            spaces_left = 8 - (scr_pos & 7);
            next_pos = scr_pos + spaces_left;
            goto output_space;
          default:
            next_pos = scr_pos + 1;
        }
      }
      rq.r_length = sizeof(request);
      rq.r_command = C_OUTPUT;
      rq.r_count = 1;
      rq.r_trans = bp;
      rq.r_status = 0;
      execrh((request FAR *) & rq, s->sft_dev);
      if (rq.r_status & S_ERROR)
        char_error(&rq, s->sft_dev);
      goto post;
    output_space:
      rq.r_length = sizeof(request);
      rq.r_command = C_OUTPUT;
      rq.r_count = 1;
      rq.r_trans = &space;
      rq.r_status = 0;
      execrh((request FAR *) & rq, s->sft_dev);
      if (rq.r_status & S_ERROR)
        char_error(&rq, s->sft_dev);
      --spaces_left;
    post:
      if (spaces_left)
        goto output_space;
      ++bp;
      ++xfer;
      if (s->sft_flags & SFT_FCONOUT)
        scr_pos = next_pos;
      if (break_ena && control_break())
      {
        handle_break();
        goto end;
      }
      goto start;
    end:
      *err = SUCCESS;
      return xfer;
    }
  }
  else
    /* a block write                           */
  {
    COUNT rc;

    ReadCount = writeblock(s->sft_status, bp, n, &rc);
    if (rc < SUCCESS)
    {
      *err = rc;
      return 0;
    }
    else
    {
      *err = SUCCESS;
      return ReadCount;
    }
  }
  *err = SUCCESS;
  return 0;
}
Beispiel #6
0
/*
 * The `force_binary' parameter is a hack to allow functions 0x01, 0x06, 0x07,
 * and function 0x40 to use the same code for performing reads, even though the
 * two classes of functions behave quite differently: 0x01 etc. always do
 * binary reads, while for 0x40 the type of read (binary/text) depends on what
 * the SFT says. -- ror4
 */
UCOUNT GenericRead(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err,
                   BOOL force_binary)
{
  sft FAR *s;
  WORD sys_idx;
  sfttbl FAR *sp;
  UCOUNT ReadCount;

  /* Test that the handle is valid                */
  if (hndl < 0)
  {
    *err = DE_INVLDHNDL;
    return 0;
  }

  /* Get the SFT block that contains the SFT      */
  if ((s = get_sft(hndl)) == (sft FAR *) - 1)
  {
    *err = DE_INVLDHNDL;
    return 0;
  }

  /* If not open or write permission - exit       */
  if (s->sft_count == 0 || (s->sft_mode & SFT_MWRITE))
  {
    *err = DE_INVLDACC;
    return 0;
  }

/*
   *   Do remote first or return error.
   *   must have been opened from remote.
 */
  if (s->sft_flags & SFT_FSHARED)
  {
    ReadCount = Remote_RW(REM_READ, n, bp, s, err);
    if (err)
    {
      *err = SUCCESS;
      return ReadCount;
    }
    else
      return 0;
  }
  /* Do a device read if device                   */
  if (s->sft_flags & SFT_FDEVICE)
  {
    request rq;

    /* First test for eof and exit          */
    /* immediately if it is                 */
    if (!(s->sft_flags & SFT_FEOF) || (s->sft_flags & SFT_FNUL))
    {
      s->sft_flags &= ~SFT_FEOF;
      *err = SUCCESS;
      return 0;
    }

    /* Now handle raw and cooked modes      */
    if (force_binary || (s->sft_flags & SFT_FBINARY))
    {
      rq.r_length = sizeof(request);
      rq.r_command = C_INPUT;
      rq.r_count = n;
      rq.r_trans = (BYTE FAR *) bp;
      rq.r_status = 0;
      execrh((request FAR *) & rq, s->sft_dev);
      if (rq.r_status & S_ERROR)
      {
        char_error(&rq, s->sft_dev);
      }
      else
      {
        *err = SUCCESS;
        return rq.r_count;
      }
    }
    else if (s->sft_flags & SFT_FCONIN)
    {
      kb_buf.kb_size = LINESIZE - 1;
      kb_buf.kb_count = 0;
      sti((keyboard FAR *) & kb_buf);
      fbcopy((BYTE FAR *) kb_buf.kb_buf, bp, kb_buf.kb_count);
      *err = SUCCESS;
      return kb_buf.kb_count;
    }
    else
    {
      *bp = _sti();
      *err = SUCCESS;
      return 1;
    }
  }
  else
    /* a block read                            */
  {
    COUNT rc;

    ReadCount = readblock(s->sft_status, bp, n, &rc);
    if (rc != SUCCESS)
    {
      *err = rc;
      return 0;
    }
    else
    {
      *err = SUCCESS;
      return ReadCount;
    }
  }
  *err = SUCCESS;
  return 0;
}
Beispiel #7
0
COUNT DosDevIOctl(iregs FAR * r, COUNT FAR * err)
{
  sft FAR *s;
  struct dpb FAR *dpbp;
  BYTE FAR *pBuffer = MK_FP(r->DS, r->DX);
  COUNT nMode;

  /* Test that the handle is valid                                */
  switch (r->AL)
  {
    case 0x00:
    case 0x01:
    case 0x02:
    case 0x03:
    case 0x06:
    case 0x07:
    case 0x0a:
    case 0x0c:

      /* Get the SFT block that contains the SFT              */
      if ((s = get_sft(r->BX)) == (sft FAR *) - 1)
      {
        *err = DE_INVLDHNDL;
        return 0;
      }
      break;

    case 0x04:
    case 0x05:
    case 0x08:
    case 0x09:
    case 0x0d:
    case 0x0e:
    case 0x0f:
    case 0x10:
    case 0x11:
      if (r->BL > nblkdev)
      {
        *err = DE_INVLDDRV;
        return 0;
      }
      else
      {
/*
   This line previously returned the deviceheader at r->bl. But,
   DOS numbers its drives starting at 1, not 0. A=1, B=2, and so
   on. Changed this line so it is now zero-based.

   -SRM
 */
/* JPP - changed to use default drive if drive=0 */
        if (r->BL == 0)
          dpbp = &blk_devices[default_drive];
        else
          dpbp = &blk_devices[r->BL - 1];
      }
      break;

    case 0x0b:
      /* skip, it's a special case.                           */

      NetDelay = r->CX;
      if (!r->DX)
        NetRetry = r->DX;
      break;

    default:
      *err = DE_INVLDFUNC;
      return 0;
  }

  switch (r->AL)
  {
    case 0x00:
      /* Get the flags from the SFT                           */
      r->DX = r->AX = s->sft_flags;

      /* Test for file and network SFT.  These return a 0 in  */
      /* the AH register.                                     */
      if ((s->sft_flags & SFT_FSHARED)
          || !(s->sft_flags & SFT_FDEVICE))
      {
        r->AH = 0;
      }
      break;

    case 0x01:
      /* sft_flags is a file, return an error because you     */
      /* can't set the status of a file.                      */
      if (!(s->sft_flags & SFT_FDEVICE))
      {
        *err = DE_INVLDFUNC;
        return 0;
      }

      /* Set it to what we got in the DL register from the    */
      /* user.                                                */
      r->AL = s->sft_flags_lo = SFT_FDEVICE | r->DL;
      break;

    case 0x0c:
      nMode = C_GENIOCTL;
      goto IoCharCommon;
    case 0x02:
      nMode = C_IOCTLIN;
      goto IoCharCommon;
    case 0x10:
      nMode = C_IOCTLQRY;
      goto IoCharCommon;
    case 0x03:
      nMode = C_IOCTLOUT;
    IoCharCommon:

      if ((s->sft_flags & SFT_FDEVICE)
          || ((r->AL == 0x10) && !(s->sft_dev->dh_attr & ATTR_QRYIOCTL))
          || ((r->AL == 0x0c) && !(s->sft_dev->dh_attr & ATTR_GENIOCTL)))
      {
        if (s->sft_dev->dh_attr & SFT_FIOCTL)
        {
          CharReqHdr.r_unit = 0;
          CharReqHdr.r_length = sizeof(request);
          CharReqHdr.r_command = nMode;
          CharReqHdr.r_count = r->CX;
          CharReqHdr.r_trans = pBuffer;
          CharReqHdr.r_status = 0;
          execrh((request FAR *) & CharReqHdr, s->sft_dev);

          if (CharReqHdr.r_status & S_ERROR)
            return char_error(&CharReqHdr, s->sft_dev);
          if (r->AL == 0x07)
          {
            r->AL =
                CharReqHdr.r_status & S_BUSY ?
                00 : 0xff;
          }
          break;
        }
      }
      *err = DE_INVLDFUNC;
      return 0;

    case 0x0d:
      nMode = C_GENIOCTL;
      goto IoBlockCommon;
    case 0x04:
      nMode = C_IOCTLIN;
      goto IoBlockCommon;
    case 0x11:
      nMode = C_IOCTLQRY;
      goto IoBlockCommon;
    case 0x05:
      nMode = C_IOCTLOUT;
    IoBlockCommon:
      if ((dpbp->dpb_device->dh_attr & ATTR_IOCTL)
      || ((r->AL == 0x11) && !(dpbp->dpb_device->dh_attr & ATTR_QRYIOCTL))
          || ((r->AL == 0x0d) && !(dpbp->dpb_device->dh_attr & ATTR_GENIOCTL)))
      {
        *err = DE_INVLDFUNC;
        return 0;
      }

      CharReqHdr.r_unit = r->BL;
      CharReqHdr.r_length = sizeof(request);
      CharReqHdr.r_command = nMode;
      CharReqHdr.r_count = r->CX;
      CharReqHdr.r_trans = pBuffer;
      CharReqHdr.r_status = 0;
      execrh((request FAR *) & CharReqHdr,
             dpbp->dpb_device);
      if (r->AL == 0x08)
      {
        if (CharReqHdr.r_status & S_ERROR)
        {
          *err = DE_DEVICE;
          return 0;
        }
        r->AX = (CharReqHdr.r_status & S_BUSY) ? 1 : 0;
      }
      else
      {
        if (CharReqHdr.r_status & S_ERROR)
        {
          *err = DE_DEVICE;
          return 0;
        }
      }
      break;

    case 0x06:
      if (s->sft_flags & SFT_FDEVICE)
      {
        r->AL = s->sft_flags & SFT_FEOF ? 0 : 0xFF;
      }
      else
        r->AL = s->sft_posit >= s->sft_size ? 0xFF : 0;
      break;

    case 0x07:
      if (s->sft_flags & SFT_FDEVICE)
      {
        goto IoCharCommon;
      }
      r->AL = 0;
      break;

    case 0x08:
      if (dpbp->dpb_device->dh_attr & ATTR_EXCALLS)
      {
        nMode = C_REMMEDIA;
        goto IoBlockCommon;
      }
      *err = DE_INVLDFUNC;
      return 0;

    case 0x09:
      r->DX = dpbp->dpb_device->dh_attr;
      break;

    case 0x0a:
      r->DX = s->sft_dcb->dpb_device->dh_attr;
      break;

    case 0x0e:
      nMode = C_GETLDEV;
      goto IoLogCommon;
    case 0x0f:
      nMode = C_SETLDEV;
    IoLogCommon:
      if ((dpbp->dpb_device->dh_attr & ATTR_GENIOCTL))
      {
        if (r->BL == 0)
          r->BL = default_drive;

        CharReqHdr.r_unit = r->BL;
        CharReqHdr.r_length = sizeof(request);
        CharReqHdr.r_command = nMode;
        CharReqHdr.r_count = r->CX;
        CharReqHdr.r_trans = pBuffer;
        CharReqHdr.r_status = 0;
        execrh((request FAR *) & CharReqHdr,
               dpbp->dpb_device);

        if (CharReqHdr.r_status & S_ERROR)
          *err = DE_ACCESS;
        else
          *err = SUCCESS;
        return 0;
      }
      *err = DE_INVLDFUNC;
      return 0;

    default:
      *err = DE_INVLDFUNC;
      return 0;
  }
  *err = SUCCESS;
  return 0;
}
Beispiel #8
0
Datei: 2OS.C Projekt: ifilex/SRC
COUNT DosDevIOctl(iregs FAR * r, COUNT FAR * err)
{
  sft FAR *s;
  struct dpb FAR *dpbp;
  BYTE FAR *pBuffer = MK_FP(r->DS, r->DX);
  COUNT nMode;

  switch (r->AL)
  {
    case 0x00:
    case 0x01:
    case 0x02:
    case 0x03:
    case 0x06:
    case 0x07:
    case 0x0a:
    case 0x0c:

      if ((s = get_sft(r->BX)) == (sft FAR *) - 1)
      {
        *err = DE_INVLDHNDL;
        return 0;
      }
      break;

    case 0x04:
    case 0x05:
    case 0x08:
    case 0x09:
    case 0x0d:
    case 0x0e:
    case 0x0f:
    case 0x10:
    case 0x11:
      if (r->BL > nblkdev)
      {
        *err = DE_INVLDDRV;
        return 0;
      }
      else
      {
        if (r->BL == 0)
          dpbp = &blk_devices[default_drive];
        else
          dpbp = &blk_devices[r->BL - 1];
      }
      break;

    case 0x0b:
      break;

    default:
      *err = DE_INVLDFUNC;
      return 0;
  }

  switch (r->AL)
  {
    case 0x00:
      r->DX = r->AX = s->sft_flags;

      if ((s->sft_flags & SFT_FSHARED)
          || !(s->sft_flags & SFT_FDEVICE))
      {
        r->AH = 0;
      }
      break;

    case 0x01:
      if (!(s->sft_flags & SFT_FDEVICE))
      {
        *err = DE_INVLDFUNC;
        return 0;
      }

      r->AL = s->sft_flags_lo = SFT_FDEVICE | r->DL;
      break;

    case 0x0c:
      nMode = C_GENIOCTL;
      goto IoCharCommon;
    case 0x02:
      nMode = C_IOCTLIN;
      goto IoCharCommon;
    case 0x10:
      nMode = C_IOCTLQRY;
      goto IoCharCommon;
    case 0x03:
      nMode = C_IOCTLOUT;
    IoCharCommon:
      if (!(s->sft_flags & SFT_FDEVICE)
          || ((r->AL == 0x10) && !(s->sft_dev->dh_attr & ATTR_QRYIOCTL))
          || ((r->AL == 0x0c) && !(s->sft_dev->dh_attr & ATTR_GENIOCTL)))
      {
        if (s->sft_dev->dh_attr & SFT_FIOCTL)
        {
          CharReqHdr.r_unit = 0;
          CharReqHdr.r_length = sizeof(request);
          CharReqHdr.r_command = nMode;
          CharReqHdr.r_count = r->CX;
          CharReqHdr.r_trans = pBuffer;
          CharReqHdr.r_status = 0;
          execrh((request FAR *) & CharReqHdr,
                 s->sft_dev);
          if (CharReqHdr.r_status & S_ERROR)
            return char_error(&CharReqHdr,
                              s->sft_dev);
          if (r->AL == 0x07)
          {
            r->AL =
                CharReqHdr.r_status & S_BUSY ?
                00 : 0xff;
          }
          break;
        }
      }
      *err = DE_INVLDFUNC;
      return 0;

    case 0x0d:
      nMode = C_GENIOCTL;
      goto IoBlockCommon;
    case 0x04:
      nMode = C_IOCTLIN;
      goto IoBlockCommon;
    case 0x11:
      nMode = C_IOCTLQRY;
      goto IoBlockCommon;
    case 0x05:
      nMode = C_IOCTLOUT;
    IoBlockCommon:
      if (!(dpbp->dpb_device->dh_attr & ATTR_IOCTL)
      || ((r->AL == 0x11) && !(dpbp->dpb_device->dh_attr & ATTR_QRYIOCTL))
          || ((r->AL == 0x0d) && !(dpbp->dpb_device->dh_attr & ATTR_GENIOCTL)))
      {
        *err = DE_INVLDFUNC;
        return 0;
      }

      CharReqHdr.r_unit = r->BL;
      CharReqHdr.r_length = sizeof(request);
      CharReqHdr.r_command = nMode;
      CharReqHdr.r_count = r->CX;
      CharReqHdr.r_trans = pBuffer;
      CharReqHdr.r_status = 0;
      execrh((request FAR *) & CharReqHdr,
             dpbp->dpb_device);
      if (r->AL == 0x08)
      {
        if (CharReqHdr.r_status & S_ERROR)
        {
          *err = DE_DEVICE;
          return 0;
        }
        r->AX = (CharReqHdr.r_status & S_BUSY) ? 1 : 0;
      }
      else
      {
        if (CharReqHdr.r_status & S_ERROR)
        {
          *err = DE_DEVICE;
          return 0;
        }
      }
      break;

    case 0x06:
      if (s->sft_flags & SFT_FDEVICE)
      {
        r->AL = s->sft_flags & SFT_FEOF ? 0 : 0xFF;
      }
      else
        r->AL = s->sft_posit >= s->sft_size ? 0xFF : 0;
      break;

    case 0x07:
      if (s->sft_flags & SFT_FDEVICE)
      {
        goto IoCharCommon;
      }
      r->AL = 0;
      break;

    case 0x08:
      if (dpbp->dpb_device->dh_attr & ATTR_EXCALLS)
      {
        nMode = C_REMMEDIA;
        goto IoBlockCommon;
      }
      *err = DE_INVLDFUNC;
      return 0;

    case 0x09:
      r->DX = dpbp->dpb_device->dh_attr;
      break;

    case 0x0a:
      r->DX = s->sft_dcb->dpb_device->dh_attr;
      break;

    case 0x0e:
      nMode = C_GETLDEV;
      goto IoLogCommon;
    case 0x0f:
      nMode = C_SETLDEV;
    IoLogCommon:
      if (!(dpbp->dpb_device->dh_attr & ATTR_GENIOCTL))
      {
        if (r->BL == 0)
          r->BL = default_drive;

        CharReqHdr.r_unit = r->BL;
        CharReqHdr.r_length = sizeof(request);
        CharReqHdr.r_command = nMode;
        CharReqHdr.r_count = r->CX;
        CharReqHdr.r_trans = pBuffer;
        CharReqHdr.r_status = 0;
        execrh((request FAR *) & CharReqHdr,
               dpbp->dpb_device);

        if (CharReqHdr.r_status & S_ERROR)
          *err = DE_ACCESS;
        else
          *err = SUCCESS;
        return 0;
      }
      *err = DE_INVLDFUNC;
      return 0;

    default:
      *err = DE_INVLDFUNC;
      return 0;
  }
  *err = SUCCESS;
  return 0;
}