home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / cmdparse.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  8.0 KB  |  268 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. //Designed specifically for pulling out command line arugments
  20. //used in the command line startup routine.  This class knows 
  21. //about two kinds of delimeters, spaces and quotes.  Quotes
  22. //when placed in front and in back of characters delimit spaces and
  23. //any combination of any other characters.  Spaces delimit quoted
  24. //strings and other non quoted strings.  Error checking is flaged
  25. //on quoted string groups and non quoted string  which are 
  26. //not separated by a space.  There is no failure continue mode.
  27. //When an error is flaged, the routine exits and signals false.
  28.  
  29. //Command line parsing implementation file.     
  30. #include "stdafx.h"
  31. #include "cmdparse.h"
  32. #include <ctype.h>
  33.  
  34.  
  35. /************************************************************************/
  36. //Purpose:  Contructor takes two arguments to initialize the class.
  37. //Args:        pszStringToParse:  a pointer to the command line to parse
  38. //            lStringList:    A reference to the list to hold the arguments
  39. /************************************************************************/
  40.  
  41. CCmdParse::CCmdParse(char *pszStringToParse,CStringList &lStringList)
  42. {
  43.     strcpy(m_szParseString,pszStringToParse);
  44.     m_pStringList = &lStringList;
  45.     m_nIndex = 0;
  46. }
  47.  
  48. CCmdParse::CCmdParse()
  49. {
  50.     m_pStringList = NULL;
  51.     m_nIndex = 0;
  52.  
  53. }
  54. /************************************************************************/
  55. //Purpose:  Destructor removes any objects still on the list
  56. /************************************************************************/
  57.                                                                            
  58. CCmdParse::~CCmdParse()
  59. {
  60.     if(m_pStringList)
  61.     {                       
  62.         POSITION pos1,pos2;
  63.           char *pTemp = NULL;
  64.           if (m_pStringList->GetCount() > 0)
  65.         {
  66.             for( pos1 = m_pStringList->GetHeadPosition(); ( pos2 = pos1 ) != NULL; )
  67.             {
  68.                 m_pStringList->GetNext( pos1 );
  69.                                                                                              
  70.                 // Save the old pointer for
  71.                 //deletion.
  72.                 m_pStringList->RemoveAt( pos2 );
  73.                  
  74.             }
  75.         }
  76.     }
  77. }
  78.  
  79. /************************************************************************/
  80. //Purpose:  Initialize class members and construction has taken place
  81. /************************************************************************/
  82. void CCmdParse::Init(char *pszStringToParse,CStringList &lStringList)
  83. {
  84.     strcpy(m_szParseString,pszStringToParse);
  85.     m_pStringList = &lStringList;
  86.     m_nIndex = 0;
  87. }
  88. /************************************************************************/
  89. //Purpose:  Places the accumulated character in m_Token on the list in
  90. //            the order they were seen, and resets m_Token.
  91. /************************************************************************/
  92.  
  93. void CCmdParse::AddNewToken()
  94. {
  95.     CString strNew = m_Token;
  96.     m_pStringList->AddTail(strNew);
  97.     memset(m_Token,'\0',sizeof(m_Token));
  98.     m_nIndex = 0;
  99. }
  100.  
  101. /************************************************************************/
  102. //Purpose:  State machine and token builder.  This optionally could have
  103. //            been broken down into separate modules for each state; however
  104. //            due to the limited number of states and delimeters it seemed 
  105. //            resonable to bundle it in this function.  Additional 
  106. //            functionality would require breaking this up into constituent
  107. //            subroutines.
  108. //Called by:    ProcessCmdLine();
  109. /************************************************************************/
  110.  
  111. void CCmdParse::AddChar()
  112. {                        
  113.    if (*m_pCurrent == '\0')
  114.    {    //check to see if we were in the middle of building something,
  115.            //otherwise quit.
  116.         if (strlen(m_Token) > 0)
  117.             AddNewToken();
  118.            State = e_end;
  119.            return;
  120.    }
  121.    
  122.    if (State == e_start  && (*m_pCurrent == '"'))
  123.    {    //we are handling a quoted string
  124.         State = e_quote;
  125.         Previous = e_start;
  126.         ++m_pCurrent;
  127.         return;
  128.    }        
  129.    
  130.    if (State == e_start && ((*m_pCurrent != '"') && (!isspace(*m_pCurrent))) )
  131.    {    //we are handling a non quoted string
  132.         State = e_other;
  133.         Previous = e_start;
  134.         return;       
  135.    }
  136.    
  137.    if (State == e_start && (isspace(*m_pCurrent)))
  138.    {
  139.        State = e_space;
  140.        Previous = e_start;
  141.        return;
  142.    }
  143.        
  144.    if (State == e_quote && (*m_pCurrent != '"'))   
  145.    {    //add it to the token builder
  146.            m_Token[m_nIndex++] = *m_pCurrent++;
  147.            return;    
  148.    }                     
  149.    
  150.    if (State == e_quote && (*m_pCurrent == '"'))
  151.    {    //we found another quote.             
  152.            if (*(m_pCurrent -1) == '"')
  153.            {   //look back and see if quotes are wrong
  154.                //path names must be separated by quotes!!!!
  155.                State = e_error;
  156.                return;
  157.            }
  158.            if( !isspace(*(m_pCurrent +1)) && (*(m_pCurrent +1) != '\0') )
  159.            {
  160.                //look ahead and make sure they delimeted the quoted argument
  161.                State = e_error;
  162.                return;
  163.            }
  164.            Previous = State;//not used
  165.            //set the state so we know what we last saw and can expect
  166.            State = e_end_quote;
  167.          //add the quoted string minus the quotes
  168.            AddNewToken();
  169.           return;
  170.    }   
  171.    
  172.    if (State == e_end_quote && (*m_pCurrent != '"'))
  173.    {    //we are expecting a space or a non quote
  174.               if(isspace(*m_pCurrent))
  175.               {    
  176.                   ++m_pCurrent;
  177.                   State = e_space;
  178.                   Previous = e_end_quote;
  179.               }
  180.               else
  181.               {
  182.                   State = e_other;         
  183.                   Previous = e_end_quote;
  184.               }
  185.               return;                
  186.    }
  187.    if (State == e_end_quote && (*m_pCurrent == '"'))
  188.    {    //suscpicious
  189.            ++m_pCurrent; 
  190.            return;
  191.    }
  192.    
  193.    
  194.    if (State == e_other && ((!isspace(*m_pCurrent)) && (*m_pCurrent != '"')) )
  195.    {    //add it to the token builder                        
  196.         m_Token[m_nIndex++] = *m_pCurrent++;
  197.            return;           
  198.    }
  199.    else if(State == e_other && (isspace(*m_pCurrent)) )
  200.    {    //add the non quoted token
  201.            AddNewToken();
  202.            Previous =  e_other;
  203.            if ( isspace(*m_pCurrent) )
  204.                State =  e_space;
  205.            else
  206.                State = e_start;                               
  207.  
  208.         return;
  209.     }
  210.     else if(State == e_other && (*m_pCurrent == '"'))
  211.     {
  212.          State = e_error;
  213.          return;
  214.     }
  215.     
  216.     if (State == e_space && (!isspace(*m_pCurrent) ) )
  217.     {
  218.         State = e_start;
  219.         Previous = e_space;
  220.         return;    
  221.     }
  222.     
  223.     if (State == e_space && (isspace(*m_pCurrent)) )
  224.     {   //eat up spaces.
  225.         while (isspace(*m_pCurrent))
  226.             ++m_pCurrent;
  227.         return;
  228.     }
  229.     
  230.      
  231.    
  232.    
  233. }
  234.  
  235. /*************************************************************************/
  236. //Purpose:    Called to start command line processing.
  237. //            This function is used in a very minimal sense.  However, it
  238. //            is prepared to grow such that more detailed errors and
  239. //            potentially more states may be added to compensate for
  240. //            additional delimiters.  Currently it simply calls AddChar()
  241. //            and waits for an error or state end.  
  242. //RETURNS:    True on success and False on failure.
  243. /*************************************************************************/
  244. BOOL CCmdParse::ProcessCmdLine()
  245. {
  246.     State = e_start;
  247.     Previous = State; //may be used in the future
  248.  
  249.     m_pCurrent = &m_szParseString[0];                              
  250.     memset(m_Token,'\0',512);
  251.     
  252.     while(State != e_end)
  253.     {
  254.         switch(State)
  255.         {  
  256.             //   
  257.             case e_error:
  258.                 return FALSE;
  259.               
  260.             default:
  261.                 AddChar();
  262.                  
  263.         }
  264.     }
  265.     return TRUE;        
  266. }
  267.     
  268.