home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DEV / DASD / CDROM / ATAPI / CMDPARSE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-14  |  32.2 KB  |  1,073 lines

  1. /*DDK*************************************************************************/
  2. /*                                                                           */
  3. /* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
  4. /*                                                                           */
  5. /*    The following IBM OS/2 WARP source code is provided to you solely for  */
  6. /*    the purpose of assisting you in your development of OS/2 WARP device   */
  7. /*    drivers. You may use this code in accordance with the IBM License      */
  8. /*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
  9. /*    Copyright statement may not be removed.                                */
  10. /*                                                                           */
  11. /*****************************************************************************/
  12. /**************************************************************************
  13.  *
  14.  * SOURCE FILE NAME = CMDPARSE.C
  15.  *
  16.  *
  17.  *
  18.  *
  19.  * VERSION = V2.0
  20.  *
  21.  * DATE
  22.  *
  23.  * DESCRIPTION : ADD CONFIG.SYS Command Line Parser Helper Routine
  24.  *
  25.  * Purpose: This module consists of the Command_Parser Function and
  26.  *          its associated local routines.  For detailed description
  27.  *          of the Command_Parser interface refer to the CMDPARSE.H
  28.  *          file.
  29.  *
  30.  *
  31.  *
  32. */
  33.  
  34.  
  35.  #define INCL_NOBASEAPI
  36.  #define INCL_NOPMAPI
  37.  #define INCL_NO_SCB
  38.  #define INCL_INITRP_ONLY
  39.  #include "os2.h"
  40.  #include "dos.h"
  41.  
  42.  #include "iorb.h"
  43.  #include "reqpkt.h"
  44.  #include "dhcalls.h"
  45.  #include "addcalls.h"
  46.  #include "dskinit.h"
  47.  
  48.  #include "atapicon.h"
  49.  #include "atapityp.h"
  50.  #include "atapiext.h"
  51.  
  52.  #include "cmdproto.h"
  53.  
  54. #define TOKVBUF_LEN 255
  55. #define UNDEFINED   -1
  56.  
  57. /*******************************************************************************
  58. *                                                                              *
  59. *   Command_Parser -  external entry point into this module                    *
  60. *                                                                              *
  61. *******************************************************************************/
  62.  
  63. CC FAR Command_Parser(pCmdLine,pOptTable,pOutBuf,OutBuf_Len)
  64.  
  65. PSZ           pCmdLine;
  66. POPTIONTABLE  pOptTable;
  67. PBYTE         pOutBuf;
  68. USHORT        OutBuf_Len;
  69.  
  70. {
  71.    USHORT j, end_index;
  72.  
  73.    if (OutBuf_Len < (TOKL_ID_END + TOK_MIN_LENGTH))
  74.    {
  75.       cc.ret_code = BUF_TOO_SMALL_ERR;
  76.       cc.err_index = 0;
  77.       return (cc);
  78.    }
  79.  
  80.    poutbuf_end = pOutBuf + OutBuf_Len;
  81.  
  82.    poutbuf1 = pOutBuf;
  83.    for (poutbuf1 = pOutBuf;
  84.         (poutbuf1 < poutbuf_end);
  85.         poutbuf1++)
  86.        *poutbuf1 = 0;
  87.    poutbuf1 = pOutBuf;
  88.  
  89.    Insert_End_Token();
  90.  
  91.    /*-------------------------------------------------------------------*/
  92.    /*  Locate the last entry in the Option Table. This special entry    */
  93.    /*  defines whether or not an option is required based on the index  */
  94.    /*  in the state table.                                              */
  95.    /*-------------------------------------------------------------------*/
  96.  
  97.    for (end_index = 0 ;
  98.         (pOptTable->poption[end_index]->id != TOK_ID_END);
  99.         end_index++);
  100.    pend_option = pOptTable->poption[end_index];
  101.  
  102.    /*-------------------------------------------------*/
  103.    /*  Setup the initial index into the state table.  */
  104.    /*-------------------------------------------------*/
  105.  
  106.    state_index = pOptTable->entry_state;
  107.    if (!Validate_State_Index(pOptTable->max_states))
  108.       return (cc);
  109.  
  110.    /*--------------------------------------------------------*/
  111.    /*  On return from Locate_First_Slash call pcmdline_slash */
  112.    /*  contains the ptr to the / in the command line.        */
  113.    /*--------------------------------------------------------*/
  114.  
  115.    pcmdline_start = pCmdLine;
  116.    pcmdline1 = pCmdLine;
  117.    if (!Locate_First_Slash())
  118.       return (cc);
  119.  
  120.    for (j=0;j < end_index;j++)
  121.    {
  122.       /*--------------------------------------------------------------------*/
  123.       /*  Locate valid options in Option Table, based on state table index. */
  124.       /*--------------------------------------------------------------------*/
  125.  
  126.       if (pOptTable->poption[j]->state[state_index] != E)
  127.       {
  128.         /*-----------------------------------------------------------*/
  129.         /*  Found a valid option. Check to see if this is the option */
  130.         /*  entered at this point in command line.                   */
  131.         /*-----------------------------------------------------------*/
  132.  
  133.         ptable_option = pOptTable->poption[j];
  134.         length = strlen(ptable_option->string);
  135.         if (strncmp(pcmdline_slash,ptable_option->string, length) == TRUE)
  136.         {
  137.  
  138.            /*--------------------------------------------------------*/
  139.            /* Found the command line option.  Now, syntax check its  */
  140.            /* associated value.                                      */
  141.            /*--------------------------------------------------------*/
  142.  
  143.            if (!Parse_Option_Value())
  144.               return (cc);
  145.  
  146.            /*----------------------------------------------------------*/
  147.            /* No syntax err detected.  Now, insert the option and its  */
  148.            /* associated value into the output buffer in token format. */
  149.            /*----------------------------------------------------------*/
  150.  
  151.            if (!Insert_Token())
  152.               return (cc);
  153.  
  154.            /*-----------------------------------------*/
  155.            /*  Setup next index into the state table. */
  156.            /*-----------------------------------------*/
  157.  
  158.            state_index = ptable_option->state[state_index];
  159.            if (!Validate_State_Index(pOptTable->max_states))
  160.               return (cc);
  161.  
  162.            /*-----------------------------------------------------------*/
  163.            /*  Setup cmdline_slash to point the the next / (option) in  */
  164.            /*  the command line.                                        */
  165.            /*  Parsing stops once either an invalid character is        */
  166.            /*  found on the command line or the end of the command line */
  167.            /*  is detected.                                             */
  168.            /*-----------------------------------------------------------*/
  169.  
  170.            if (!Locate_Next_Slash())
  171.               return (cc);
  172.  
  173.            /*----------------------------------------------------------------*/
  174.            /* Setup for option search. Point to the top of the Option Table. */
  175.            /*----------------------------------------------------------------*/
  176.  
  177.            j = -1;
  178.  
  179.         } /* endif */
  180.  
  181.       } /* endif */
  182.  
  183.    } /* endfor */
  184.  
  185.  
  186.    if (pend_option->state[state_index] == R)
  187.    {
  188.    /*------------------------------------------------------*/
  189.    /* A required option was not found on the command line. */
  190.    /*------------------------------------------------------*/
  191.  
  192.       cc.ret_code = REQ_OPT_ERR;
  193.    }
  194.    else
  195.    {
  196.    /*--------------------------------------------------------------------*/
  197.    /* Characters on the command line are not defined in the Option Table */
  198.    /* as a valid option.  All options must start with a / character.     */
  199.    /*--------------------------------------------------------------------*/
  200.  
  201.       cc.ret_code = INVALID_OPT_ERR;
  202.    }
  203.    cc.err_index = pcmdline_slash-pCmdLine;
  204.    return (cc);
  205.  
  206. }
  207.  
  208. /*******************************************************************************
  209. *                                                                              *
  210. *   FUNCTION: Insert the end of token marker into the output buffer            *
  211. *                                                                              *
  212. *******************************************************************************/
  213. STATIC VOID NEAR Insert_End_Token()
  214. {
  215.      *poutbuf1 = TOKL_ID_END;
  216.      *(poutbuf1+1) = TOK_ID_END;
  217.      return;
  218. }
  219.  
  220. /*******************************************************************************
  221. *                                                                              *
  222. *   FUNCTION: Locate the / on the command line.  All characters entered prior  *
  223. *             to the first / are ignored.  This allows the parser to bypass    *
  224. *             the BASEDEV = xxxxxxxx.xxx portion of the command line.          *
  225. *                                                                              *
  226. *******************************************************************************/
  227. STATIC BOOL NEAR Locate_First_Slash()
  228. {
  229.  
  230.  
  231.      while ((*pcmdline1 != '\0') &&
  232.             (*pcmdline1 != '\n') &&
  233.             (*pcmdline1 != '\r'))
  234.      {
  235.          if (*pcmdline1 == '/')
  236.          {
  237.             pcmdline_slash = pcmdline1;
  238.             return(TRUE);
  239.          }
  240.  
  241.          pcmdline1++;
  242.      }
  243.  
  244.      cc.err_index = 0;
  245.      cc.ret_code = NO_OPTIONS_FND_ERR;
  246.      if (pend_option->state[state_index] == R)
  247.         cc.ret_code = REQ_OPT_ERR;
  248.  
  249.      return(FALSE);
  250. }
  251.  
  252. /*******************************************************************************
  253. *                                                                              *
  254. *   FUNCTION: Return the length of a string                                    *
  255. *                                                                              *
  256. *******************************************************************************/
  257. STATIC INT  NEAR strlen(s)
  258.  
  259. CHAR FAR *s;
  260. {
  261.      INT i;
  262.  
  263.      for (i = 0; *s != '\0' ; s++)
  264.          i++;
  265.  
  266.      return(i);
  267. }
  268.  
  269. /*******************************************************************************
  270. *                                                                              *
  271. *   FUNCTION: Compare n number of characters in 2 strings, return TRUE if =    *
  272. *             If s1 is in lower case, convert to upper prior to comparing.     *
  273. *                                                                              *
  274. *******************************************************************************/
  275. STATIC BOOL NEAR strncmp(s1,s2,n)
  276.  
  277. CHAR FAR *s1, FAR *s2;
  278. INT  n;
  279. {
  280.      INT i;
  281.      CHAR temp;
  282.  
  283.      for (i=0;i < n;i++,s1++,s2++)
  284.  
  285.          if (*s1 != *s2)
  286.          {
  287.             if ((*s1 >= 'a') && (*s1 <= 'z'))
  288.             {
  289.                temp = *s1 - ' ';
  290.                if (temp == *s2)
  291.                   continue;
  292.             }
  293.             return(FALSE);
  294.          }
  295.  
  296.      return(TRUE);
  297. }
  298.  
  299.  
  300. /*******************************************************************************
  301. *                                                                              *
  302. *   FUNCTION: Parse the command line for the value assigned to located option  *
  303. *                                                                              *
  304. *******************************************************************************/
  305. STATIC BOOL  NEAR Parse_Option_Value()
  306. {
  307.       pcmdline1 = pcmdline_slash + length;
  308.       Skip_Over_Blanks();
  309.  
  310.       for (tokv_index = 0; tokv_index <= TOKVBUF_LEN; tokv_index++)
  311.            tokvbuf[tokv_index].byte_value= 0;
  312.  
  313.       tokv_index = UNDEFINED;
  314.  
  315.       cc.ret_code = NO_ERR;
  316.       cc.err_index = 0;
  317.  
  318.       switch (ptable_option->type)
  319.       {
  320.       case TYPE_0:
  321.            break;
  322.  
  323.       case TYPE_CHAR:
  324.            char_parser();
  325.            break;
  326.  
  327.       case TYPE_D:
  328.            d_parser();
  329.            break;
  330.  
  331.       case TYPE_DD:
  332.            dd_parser();
  333.            break;
  334.  
  335.       case TYPE_DDDD:
  336.            dddd_parser();
  337.            break;
  338.  
  339.       case TYPE_HH:
  340.            hh_parser();
  341.            break;
  342.  
  343.       case TYPE_HHHH:
  344.            hhhh_parser();
  345.            break;
  346.  
  347.       case TYPE_FORMAT:
  348.            format_parser();
  349.            break;
  350.  
  351.       case TYPE_SCSI_ID:
  352.            scsi_id_parser();
  353.            break;
  354.  
  355.       case TYPE_GEOMETRY:
  356.            geometry_parser();
  357.            break;
  358.  
  359.       case TYPE_CHGLINE:
  360.            chgline_parser();
  361.            break;
  362.  
  363.       default:
  364.            cc.ret_code = UNDEFINED_TYPE_ERR;
  365.  
  366.       } /* endswitch */
  367.  
  368.       if (cc.ret_code != NO_ERR)
  369.       {
  370.          cc.err_index = pcmdline1 - pcmdline_start;
  371.          return(FALSE);
  372.       }
  373.  
  374.       return(TRUE);
  375. }
  376.  
  377.  
  378. /*******************************************************************************
  379. *                                                                              *
  380. *   FUNCTION: Skip over all the blank and tab characters                       *
  381. *                                                                              *
  382. *******************************************************************************/
  383. STATIC VOID NEAR Skip_Over_Blanks()
  384. {
  385.      while ((*pcmdline1 == ' ') || (*pcmdline1 == '\t'))
  386.            pcmdline1++;
  387.      return;
  388. }
  389.  
  390. /*******************************************************************************
  391. *                                                                              *
  392. *   FUNCTION: TYPE_CHAR option parser - scan till blank,tab,cr,new line or     *
  393. *                                       end of string char                     *
  394. *                                                                              *
  395. *******************************************************************************/
  396. STATIC VOID NEAR  char_parser()
  397. {
  398.      while ((*pcmdline1 != '\0') &&
  399.             (*pcmdline1 != '\n') &&
  400.             (*pcmdline1 != '\r') &&
  401.             (*pcmdline1 != '/'))
  402.  
  403.      {
  404.            tokv_index++;
  405.            tokvbuf[tokv_index].char_value = *pcmdline1;
  406.            pcmdline1++;
  407.      }
  408.  
  409.      return;
  410. }
  411.  
  412.  
  413. /*******************************************************************************
  414. *                                                                              *
  415. *   FUNCTION: TYPE_D option parser - one digit decimal number (d)              *
  416. *                                                                              *
  417. *******************************************************************************/
  418. STATIC VOID NEAR  d_parser()
  419. {
  420.      if ((*pcmdline1 >= '0') && (*pcmdline1 <= '9'))
  421.      {
  422.         tokv_index++;
  423.         tokvbuf[tokv_index].byte_value = *pcmdline1 - '0';
  424.         pcmdline1++;
  425.      }
  426.      else
  427.      {
  428.         cc.ret_code = SYNTAX_ERR;
  429.      }
  430.  
  431.      return;
  432. }
  433.  
  434. /*******************************************************************************
  435. *                                                                              *
  436. *   FUNCTION: TYPE_DD option parser - two digit decimal number (dd)            *
  437. *                                                                              *
  438. *******************************************************************************/
  439. STATIC VOID NEAR dd_parser()
  440. {
  441.    USHORT     num;
  442.  
  443.    num = dd_parsersub();
  444.  
  445.    if ( cc.ret_code == NO_ERR )
  446.    {
  447.       if ( num < 100 )
  448.       {
  449.          tokv_index++;
  450.          tokvbuf[tokv_index].byte_value = (UCHAR) num;
  451.       }
  452.       else
  453.       {
  454.          cc.ret_code = SYNTAX_ERR;
  455.       }
  456.    }
  457.  
  458.  
  459. }
  460. /*******************************************************************************
  461. *                                                                              *
  462. *   FUNCTION: option parser - four digit decimal number ((-)dddd)              *
  463. *                                                                              *
  464. *******************************************************************************/
  465.  
  466. STATIC VOID NEAR dddd_parser()
  467. {
  468.    USHORT     num;
  469.  
  470.    num = dd_parsersub();
  471.  
  472.    if ( cc.ret_code == NO_ERR )
  473.    {
  474.       tokv_index++;
  475.       tokvbuf[tokv_index].byte_value = (UCHAR) num;
  476.       tokv_index++;
  477.       tokvbuf[tokv_index].byte_value = (UCHAR) (num >> 8);
  478.    }
  479.  
  480. }
  481.  
  482. /*******************************************************************************
  483. *                                                                              *
  484. *   FUNCTION: option parser -                                                  *
  485. *                                                                              *
  486. *******************************************************************************/
  487.  
  488. /* STATIC*/ USHORT NEAR dd_parsersub()
  489. {
  490.      INT        i;
  491.      USHORT     n;
  492.      BOOL       flag;
  493.      USHORT     sign = 0;
  494.  
  495.      if ( *pcmdline1 == '-' )
  496.      {
  497.        sign = 1;
  498.        pcmdline1++;
  499.      }
  500.  
  501.      n = 0;
  502.      flag = FALSE;
  503.      for ( i = 0; i < 4; i++)
  504.      {
  505.          if ((*pcmdline1 >= '0') && (*pcmdline1 <= '9'))
  506.          {
  507.             n = 10 * n + *pcmdline1 - '0';
  508.             pcmdline1++;
  509.             flag = TRUE;
  510.          }
  511.          else
  512.          {
  513.             /*--------------------------------------------------*/
  514.             /* Was at least 1 digit found on the command line?  */
  515.             /*--------------------------------------------------*/
  516.  
  517.             if (flag)
  518.                break;
  519.  
  520.             cc.ret_code = SYNTAX_ERR;
  521.             return( 0 );
  522.          }
  523.      }
  524.  
  525.  
  526.      return ((sign) ? -n : n);
  527. }
  528.  
  529. /*******************************************************************************
  530. *                                                                              *
  531. *   FUNCTION: TYPE_HH option parser        hh,hh format (h = hex char)         *
  532. *                                                                              *
  533. *******************************************************************************/
  534. STATIC VOID NEAR hh_parser()
  535. {
  536.      /*------------------------------------------------------------*/
  537.      /*  Convert command line HH char and setup token value buffer */
  538.      /*------------------------------------------------------------*/
  539.      if (!HH_Char_To_Byte())
  540.         return;
  541.  
  542.      Skip_Over_Blanks();
  543.      if (*pcmdline1 != ',')
  544.      {
  545.         cc.ret_code = SYNTAX_ERR;
  546.         return;
  547.      }
  548.      pcmdline1++;
  549.      Skip_Over_Blanks();
  550.  
  551.      /*------------------------------------------------------------*/
  552.      /*  Convert command line HH char and setup token value buffer */
  553.      /*------------------------------------------------------------*/
  554.      HH_Char_To_Byte();
  555.  
  556.      return;
  557. }
  558.  
  559.  
  560.  
  561. /*******************************************************************************
  562. *                                                                              *
  563. *   FUNCTION: Convert HH char to byte value                                    *
  564. *                                                                              *
  565. *******************************************************************************/
  566. STATIC BOOL NEAR HH_Char_To_Byte()
  567. {
  568.      BYTE n;
  569.      INT  i;
  570.      BOOL flag;
  571.  
  572.      n = 0;
  573.      flag = FALSE;
  574.  
  575.      for ( i = 0; i < 2; i++)
  576.      {
  577.          if ((*pcmdline1 >= '0') && (*pcmdline1 <= '9'))
  578.          {
  579.             n = 16 * n + *pcmdline1 - '0';
  580.             pcmdline1++;
  581.             flag = TRUE;
  582.             continue;
  583.          }
  584.  
  585.          if ((*pcmdline1 >= 'A') && (*pcmdline1 <= 'F'))
  586.          {
  587.             n = 16 * n + *pcmdline1 - '7';
  588.             pcmdline1++;
  589.             flag = TRUE;
  590.             continue;
  591.          }
  592.  
  593.          if ((*pcmdline1 >= 'a') && (*pcmdline1 <= 'f'))
  594.          {
  595.             n = 16 * n + *pcmdline1 - 'W';
  596.             pcmdline1++;
  597.             flag = TRUE;
  598.             continue;
  599.          }
  600.  
  601.          /*-----------------------------------------------------*/
  602.          /* Was at least 1 hex digit found on the command line? */
  603.          /*-----------------------------------------------------*/
  604.          if (flag)
  605.             break;
  606.  
  607.          cc.ret_code = SYNTAX_ERR;
  608.          return(FALSE);
  609.  
  610.      }
  611.  
  612.      tokv_index++;
  613.      tokvbuf[tokv_index].byte_value = n;
  614.  
  615.      return(TRUE);
  616. }
  617.  
  618.  
  619. /*******************************************************************************
  620. *                                                                              *
  621. *   FUNCTION: TYPE_HHHH option parser       hhhh format (h = hex char)         *
  622. *                                                                              *
  623. *******************************************************************************/
  624. STATIC VOID NEAR hhhh_parser()
  625. {
  626.      INT  i;
  627.      BOOL flag;
  628.      NUMBER un_number;
  629.  
  630.      un_number.n = 0;
  631.      flag = FALSE;
  632.  
  633.      for ( i = 0; i < 4; i++)
  634.      {
  635.          if ((*pcmdline1 >= '0') && (*pcmdline1 <= '9'))
  636.          {
  637.             un_number.n = 16 * un_number.n + *pcmdline1 - '0';
  638.             pcmdline1++;
  639.             flag = TRUE;
  640.             continue;
  641.          }
  642.  
  643.          if ((*pcmdline1 >= 'A') && (*pcmdline1 <= 'F'))
  644.          {
  645.             un_number.n = 16 * un_number.n + *pcmdline1 - '7';
  646.             pcmdline1++;
  647.             flag = TRUE;
  648.             continue;
  649.          }
  650.  
  651.          if ((*pcmdline1 >= 'a') && (*pcmdline1 <= 'f'))
  652.          {
  653.             un_number.n = 16 * un_number.n + *pcmdline1 - 'W';
  654.             pcmdline1++;
  655.             flag = TRUE;
  656.             continue;
  657.          }
  658.  
  659.          /*------------------------------------------------------*/
  660.          /* Was at least 1 hex digit found on the command line?  */
  661.          /*------------------------------------------------------*/
  662.          if (flag)
  663.             break;
  664.  
  665.          cc.ret_code = SYNTAX_ERR;
  666.          return;
  667.  
  668.  
  669.      }
  670.  
  671.      tokv_index++;
  672.      tokvbuf[tokv_index].byte_value = un_number.two_bytes.byte1;
  673.  
  674.      tokv_index++;
  675.      tokvbuf[tokv_index].byte_value = un_number.two_bytes.byte2;
  676.  
  677.      return;
  678. }
  679.  
  680.  
  681. /*******************************************************************************
  682. *                                                                              *
  683. *   FUNCTION: TYPE_FORMAT option parser -  format_table chars accepted         *
  684. *                                                                              *
  685. *******************************************************************************/
  686. STATIC VOID NEAR format_parser()
  687. {
  688.  
  689.     typedef struct _formattable
  690.      {
  691.          PSZ        string;
  692.          USHORT     type;
  693.          NUMBER     MegBytes;
  694.  
  695.      } FORMATTABLE;
  696.  
  697. /* FORMATTABLE type definitions  */
  698.                                     /* accepts # string followed by:    */
  699. #define M_BYTES             1       /* accepts MB,mb,Mb,mB, or nothing  */
  700. #define K_BYTES             2       /* accepts KB,kb,Kb,kB, or nothing  */
  701.  
  702.        INT  str_len, k;
  703. static FORMATTABLE format_table[] =
  704.      {
  705.       { "360",  K_BYTES, 360},
  706.       { "720",  K_BYTES, 720},
  707.       { "1200", K_BYTES, 1200},
  708.       { "1.2",  M_BYTES, 1200},
  709.       { "1440", K_BYTES, 1440},
  710.       { "1.44", M_BYTES, 1440},
  711.       { "2880", K_BYTES, 2880},
  712.       { "2.88", M_BYTES, 2880},
  713.       { "-1"},
  714.      };
  715.  
  716.      cc.ret_code = SYNTAX_ERR;
  717.      for (k = 0; (format_table[k].string != "-1"); k++)
  718.      {
  719.  
  720.          str_len = strlen(format_table[k].string);
  721.  
  722.          if (strncmp(pcmdline1,format_table[k].string, str_len)
  723.             == TRUE)
  724.          {
  725.             pcmdline1 += str_len;
  726.             if (format_table[k].type == K_BYTES)
  727.             {
  728.                if ((*pcmdline1 == 'K') || (*pcmdline1 == 'k'))
  729.                {
  730.                   ++pcmdline1;
  731.  
  732.                   if ((*(pcmdline1) == 'B') || (*(pcmdline1) == 'b'))
  733.                      ++pcmdline1;
  734.                }
  735.             }
  736.             else
  737.             {
  738.                if ((*pcmdline1 == 'M') || (*pcmdline1 == 'm'))
  739.                {
  740.                   ++pcmdline1;
  741.  
  742.                   if ((*(pcmdline1) == 'B') || (*(pcmdline1) == 'b'))
  743.                      ++pcmdline1;
  744.                 }
  745.             }
  746.  
  747.             tokv_index++;
  748.             tokvbuf[tokv_index].byte_value = format_table[k].MegBytes.two_bytes.byte1;
  749.             tokv_index++;
  750.             tokvbuf[tokv_index].byte_value = format_table[k].MegBytes.two_bytes.byte2;
  751.  
  752.             cc.ret_code = NO_ERR;
  753.             break;
  754.          }
  755.      }
  756.      return;
  757. }
  758.  
  759. /*******************************************************************************
  760. *                                                                              *
  761. *   FUNCTION: TYPE_SCSI_ID option parser - format d and (d,d) accepted         *
  762. *                                          where d = 0 - 7                     *
  763. *                                                                              *
  764. *******************************************************************************/
  765. STATIC VOID NEAR scsi_id_parser()
  766. {
  767.      BOOL found_bracket, found_one;
  768.  
  769.      found_bracket = FALSE;
  770.      found_one = FALSE;
  771.  
  772.      if (*pcmdline1 == '(')
  773.      {
  774.         found_bracket = TRUE;
  775.         pcmdline1++;
  776.         Skip_Over_Blanks();
  777.      }
  778.  
  779.  
  780.      while ((*pcmdline1 >= '0') && (*pcmdline1 <= '7'))
  781.      {
  782.            found_one = TRUE;
  783.            tokv_index++;
  784.            tokvbuf[tokv_index].byte_value = *pcmdline1 - '0';
  785.            pcmdline1++;
  786.            if (!found_bracket)
  787.            {
  788.               tokv_index++;
  789.               tokvbuf[tokv_index].byte_value = 0;
  790.            }
  791.  
  792.            Skip_Over_Blanks();
  793.            if (*pcmdline1 != ',')
  794.            {
  795.               if (found_bracket)
  796.                  cc.ret_code = SYNTAX_ERR;
  797.               return;
  798.            }
  799.  
  800.            pcmdline1++;
  801.            Skip_Over_Blanks();
  802.            if (found_bracket)
  803.            {
  804.               if ((*pcmdline1 >= '0') && (*pcmdline1 <= '7'))
  805.               {
  806.                  tokv_index++;
  807.                  tokvbuf[tokv_index].byte_value = *pcmdline1 - '0';
  808.                  pcmdline1++;
  809.                  Skip_Over_Blanks();
  810.                  if (*pcmdline1 != ')')
  811.                  {
  812.                    cc.ret_code = SYNTAX_ERR;
  813.                    return;
  814.                  }
  815.                  pcmdline1++;
  816.                  Skip_Over_Blanks();
  817.                  found_bracket = FALSE;
  818.  
  819.                  if (*pcmdline1 != ',')
  820.                     return;
  821.  
  822.                  pcmdline1++;
  823.                  Skip_Over_Blanks();
  824.               }
  825.            }
  826.  
  827.            if (*pcmdline1 == '(')
  828.            {
  829.               found_bracket = TRUE;
  830.               pcmdline1++;
  831.               Skip_Over_Blanks();
  832.            }
  833.      }
  834.  
  835.      if (found_bracket)
  836.         cc.ret_code = SYNTAX_ERR;
  837.  
  838.      if (!found_one)
  839.         cc.ret_code = SYNTAX_ERR;
  840.  
  841.      return;
  842. }
  843.  
  844.  
  845. /*******************************************************************************
  846. *                                                                              *
  847. *   FUNCTION: TYPE_GEOMETRY option parser - dd or (dddd,dddd,dddd) accepted    *
  848. *                                                                              *
  849. *******************************************************************************/
  850. /* STATIC */ VOID NEAR geometry_parser()
  851. {
  852.      USHORT i;
  853.      USHORT j;
  854.      USHORT k;
  855.  
  856.      USHORT GeomType;
  857.      UCHAR  c;
  858.  
  859.      GeomType = ++tokv_index;
  860.  
  861.      tokvbuf[tokv_index].byte_value = 0;
  862.  
  863.      for ( j = 0; j < 2 && cc.ret_code == NO_ERR; j++ )
  864.      {
  865.        if (*pcmdline1 == '(')
  866.        {
  867.          pcmdline1++;
  868.  
  869.          tokvbuf[GeomType].byte_value |= GEOTYPE_DRIVESPEC << ((!j) ? 4 : 0);
  870.  
  871.          for ( k=0; k < 4 && cc.ret_code == NO_ERR ; k++ )
  872.          {
  873.            dddd_parser();
  874.  
  875.            if ( *pcmdline1 == ',' )
  876.            {
  877.               if ( k < 3 )
  878.               {
  879.                 pcmdline1++;
  880.               }
  881.               else
  882.               {
  883.                 cc.ret_code = SYNTAX_ERR;
  884.                 continue;
  885.               }
  886.            }
  887.            else if ( *pcmdline1 == ')' )
  888.            {
  889.              pcmdline1++;
  890.              break;
  891.            }
  892.            else
  893.            {
  894.              cc.ret_code = SYNTAX_ERR;
  895.              break;
  896.            }
  897.          }
  898.  
  899.          if ( cc.ret_code == NO_ERR )
  900.          {
  901.            if ( k == 2 )
  902.            {
  903.              tokv_index++;
  904.              tokvbuf[tokv_index].byte_value  = -1;
  905.              tokv_index++;
  906.              tokvbuf[tokv_index].byte_value  = -1;
  907.            }
  908.            else if ( k < 2 )
  909.            {
  910.              cc.ret_code = SYNTAX_ERR;
  911.              continue;
  912.            }
  913.          }
  914.        }
  915.        else
  916.        {
  917.          tokvbuf[GeomType].byte_value |= GEOTYPE_DRIVETYPE << ((!j) ? 4 : 0);
  918.  
  919.          dddd_parser();
  920.          tokv_index += 6;
  921.        }
  922.  
  923.        if ( !j )
  924.        {
  925.          c = *pcmdline1;
  926.          if ( c == ',')
  927.          {
  928.            pcmdline1++;
  929.          }
  930.          else
  931.          {
  932.            break;
  933.          }
  934.        }
  935.      }
  936. }
  937.  
  938. /*******************************************************************************
  939. *                                                                              *
  940. *   FUNCTION: TYPE_CHGLINE option parser - Valid options: PS2                  *
  941. *                                                         AT                   *
  942. *                                                         NONE                 *
  943. *                                                                              *
  944. *******************************************************************************/
  945. VOID NEAR chgline_parser()
  946. {
  947.  
  948.      USHORT     k, str_len;
  949.      NPBYTE     chgline_opts[] = { "\0", "NONE", "AT", "PS2" };
  950.  
  951.      for (k = 1; k < sizeof(chgline_opts)/sizeof(chgline_opts[0]); k++ )
  952.      {
  953.          str_len = strlen(chgline_opts[k]);
  954.  
  955.          if ( strncmp(pcmdline1,chgline_opts[k], str_len) )
  956.          {
  957.             pcmdline1 += str_len;
  958.             tokv_index++;
  959.             tokvbuf[tokv_index].byte_value = k;
  960.             return;
  961.          }
  962.      }
  963.      cc.ret_code = SYNTAX_ERR;
  964.      return;
  965. }
  966.  
  967. /*******************************************************************************
  968. *                                                                              *
  969. *   FUNCTION: Insert the parsed option (token) into the output buffer.         *
  970. *                                                                              *
  971. *******************************************************************************/
  972. STATIC BOOL NEAR Insert_Token()
  973. {
  974.     USHORT t, tok_size;
  975.  
  976.     tok_size = TOK_MIN_LENGTH + tokv_index;
  977.     if ((poutbuf1 + tok_size + TOKL_ID_END) >= poutbuf_end)
  978.     {
  979.        cc.err_index = pcmdline_slash-pcmdline_start;
  980.        cc.ret_code = BUF_TOO_SMALL_ERR;
  981.        return(FALSE);
  982.     }
  983.  
  984.     *poutbuf1 = tok_size + 1;
  985.     poutbuf1++;
  986.     *poutbuf1 = ptable_option->id;
  987.     poutbuf1++;
  988.  
  989.     if (tokv_index != UNDEFINED)
  990.     {
  991.        for (t=0;t <= tokv_index;t++)
  992.        {
  993.            *poutbuf1 = tokvbuf[t].byte_value;
  994.             poutbuf1++;
  995.        }
  996.     }
  997.  
  998.     Insert_End_Token();
  999.  
  1000.     return(TRUE);
  1001. }
  1002.  
  1003. /*******************************************************************************
  1004. *                                                                              *
  1005. *   FUNCTION: Locate the next / char.                                          *
  1006. *                                                                              *
  1007. *******************************************************************************/
  1008. /*STATIC*/ BOOL NEAR Locate_Next_Slash()
  1009. {
  1010.  
  1011.      while ((*pcmdline1 != '\0') &&
  1012.             (*pcmdline1 != '\n') &&
  1013.             (*pcmdline1 != '\r'))
  1014.      {
  1015.  
  1016.            if ((*pcmdline1 == ' ') ||
  1017.                (*pcmdline1 == '\t'))
  1018.            {
  1019.               pcmdline1++;
  1020.            }
  1021.            else
  1022.            {
  1023.               if (*pcmdline1 == '/')
  1024.               {
  1025.                  pcmdline_slash = pcmdline1;
  1026.                  return(TRUE);
  1027.               }
  1028.               else
  1029.               {
  1030.                  cc.ret_code = INVALID_OPT_ERR;
  1031.                  cc.err_index = pcmdline1-pcmdline_start;
  1032.                  return(FALSE);
  1033.               }
  1034.            }
  1035.  
  1036.      } /* endwhile */
  1037.  
  1038.      if (pend_option->state[state_index] == R)
  1039.      {
  1040.         cc.ret_code = REQ_OPT_ERR;
  1041.         cc.err_index = pcmdline1-pcmdline_start;
  1042.      }
  1043.      else
  1044.      {
  1045.         cc.ret_code = NO_ERR;
  1046.         cc.err_index = 0;
  1047.      }
  1048.      return(FALSE);
  1049. }
  1050.  
  1051.  
  1052. /*******************************************************************************
  1053. *                                                                              *
  1054. *   FUNCTION: Validate the State Index                                         *
  1055. *                                                                              *
  1056. *******************************************************************************/
  1057. STATIC BOOL NEAR Validate_State_Index(maxstate)
  1058.  
  1059. USHORT  maxstate;
  1060. {
  1061.  
  1062.    if ((state_index > maxstate) ||
  1063.        (state_index < 0))
  1064.    {
  1065.       cc.ret_code = UNDEFINED_STATE_ERR;
  1066.       cc.err_index = 0;
  1067.       return(FALSE);
  1068.    }
  1069.  
  1070.    return(TRUE);
  1071. }
  1072.  
  1073.