gecko-dev/cmd/winfe/cmdparse.cpp

268 строки
7.8 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
//Designed specifically for pulling out command line arugments
//used in the command line startup routine. This class knows
//about two kinds of delimeters, spaces and quotes. Quotes
//when placed in front and in back of characters delimit spaces and
//any combination of any other characters. Spaces delimit quoted
//strings and other non quoted strings. Error checking is flaged
//on quoted string groups and non quoted string which are
//not separated by a space. There is no failure continue mode.
//When an error is flaged, the routine exits and signals false.
//Command line parsing implementation file.
#include "stdafx.h"
#include "cmdparse.h"
#include <ctype.h>
/************************************************************************/
//Purpose: Contructor takes two arguments to initialize the class.
//Args: pszStringToParse: a pointer to the command line to parse
// lStringList: A reference to the list to hold the arguments
/************************************************************************/
CCmdParse::CCmdParse(char *pszStringToParse,CStringList &lStringList)
{
strcpy(m_szParseString,pszStringToParse);
m_pStringList = &lStringList;
m_nIndex = 0;
}
CCmdParse::CCmdParse()
{
m_pStringList = NULL;
m_nIndex = 0;
}
/************************************************************************/
//Purpose: Destructor removes any objects still on the list
/************************************************************************/
CCmdParse::~CCmdParse()
{
if(m_pStringList)
{
POSITION pos1,pos2;
char *pTemp = NULL;
if (m_pStringList->GetCount() > 0)
{
for( pos1 = m_pStringList->GetHeadPosition(); ( pos2 = pos1 ) != NULL; )
{
m_pStringList->GetNext( pos1 );
// Save the old pointer for
//deletion.
m_pStringList->RemoveAt( pos2 );
}
}
}
}
/************************************************************************/
//Purpose: Initialize class members and construction has taken place
/************************************************************************/
void CCmdParse::Init(char *pszStringToParse,CStringList &lStringList)
{
strcpy(m_szParseString,pszStringToParse);
m_pStringList = &lStringList;
m_nIndex = 0;
}
/************************************************************************/
//Purpose: Places the accumulated character in m_Token on the list in
// the order they were seen, and resets m_Token.
/************************************************************************/
void CCmdParse::AddNewToken()
{
CString strNew = m_Token;
m_pStringList->AddTail(strNew);
memset(m_Token,'\0',sizeof(m_Token));
m_nIndex = 0;
}
/************************************************************************/
//Purpose: State machine and token builder. This optionally could have
// been broken down into separate modules for each state; however
// due to the limited number of states and delimeters it seemed
// resonable to bundle it in this function. Additional
// functionality would require breaking this up into constituent
// subroutines.
//Called by: ProcessCmdLine();
/************************************************************************/
void CCmdParse::AddChar()
{
if (*m_pCurrent == '\0')
{ //check to see if we were in the middle of building something,
//otherwise quit.
if (strlen(m_Token) > 0)
AddNewToken();
State = e_end;
return;
}
if (State == e_start && (*m_pCurrent == '"'))
{ //we are handling a quoted string
State = e_quote;
Previous = e_start;
++m_pCurrent;
return;
}
if (State == e_start && ((*m_pCurrent != '"') && (!isspace(*m_pCurrent))) )
{ //we are handling a non quoted string
State = e_other;
Previous = e_start;
return;
}
if (State == e_start && (isspace(*m_pCurrent)))
{
State = e_space;
Previous = e_start;
return;
}
if (State == e_quote && (*m_pCurrent != '"'))
{ //add it to the token builder
m_Token[m_nIndex++] = *m_pCurrent++;
return;
}
if (State == e_quote && (*m_pCurrent == '"'))
{ //we found another quote.
if (*(m_pCurrent -1) == '"')
{ //look back and see if quotes are wrong
//path names must be separated by quotes!!!!
State = e_error;
return;
}
if( !isspace(*(m_pCurrent +1)) && (*(m_pCurrent +1) != '\0') )
{
//look ahead and make sure they delimeted the quoted argument
State = e_error;
return;
}
Previous = State;//not used
//set the state so we know what we last saw and can expect
State = e_end_quote;
//add the quoted string minus the quotes
AddNewToken();
return;
}
if (State == e_end_quote && (*m_pCurrent != '"'))
{ //we are expecting a space or a non quote
if(isspace(*m_pCurrent))
{
++m_pCurrent;
State = e_space;
Previous = e_end_quote;
}
else
{
State = e_other;
Previous = e_end_quote;
}
return;
}
if (State == e_end_quote && (*m_pCurrent == '"'))
{ //suscpicious
++m_pCurrent;
return;
}
if (State == e_other && ((!isspace(*m_pCurrent)) && (*m_pCurrent != '"')) )
{ //add it to the token builder
m_Token[m_nIndex++] = *m_pCurrent++;
return;
}
else if(State == e_other && (isspace(*m_pCurrent)) )
{ //add the non quoted token
AddNewToken();
Previous = e_other;
if ( isspace(*m_pCurrent) )
State = e_space;
else
State = e_start;
return;
}
else if(State == e_other && (*m_pCurrent == '"'))
{
State = e_error;
return;
}
if (State == e_space && (!isspace(*m_pCurrent) ) )
{
State = e_start;
Previous = e_space;
return;
}
if (State == e_space && (isspace(*m_pCurrent)) )
{ //eat up spaces.
while (isspace(*m_pCurrent))
++m_pCurrent;
return;
}
}
/*************************************************************************/
//Purpose: Called to start command line processing.
// This function is used in a very minimal sense. However, it
// is prepared to grow such that more detailed errors and
// potentially more states may be added to compensate for
// additional delimiters. Currently it simply calls AddChar()
// and waits for an error or state end.
//RETURNS: True on success and False on failure.
/*************************************************************************/
BOOL CCmdParse::ProcessCmdLine()
{
State = e_start;
Previous = State; //may be used in the future
m_pCurrent = &m_szParseString[0];
memset(m_Token,'\0',512);
while(State != e_end)
{
switch(State)
{
//
case e_error:
return FALSE;
default:
AddChar();
}
}
return TRUE;
}