Ejemplo n.º 1
0
        /// <summary>
        /// Parses the command line arguments.
        /// </summary>
        public void Parse(int initPos, bool xlatStrings)
        {
            string MethodName = "CommandLine.Parse";
             bool Done = false;
             char Ch;
             bool ParamIsOptional = false;
             int TemplPtr = 0;
             CmdLinePtr = initPos;
             LogWrite(MethodName + ": Parsing \"" + this.Text + "\" using template, \"" + Template +
             "\" starting at CharPos " + initPos.ToString() + ".");
             LogWrite(MethodName + ": IgnoringExtraneousText = " + IgnoringExtraneousText);
             LogWrite(MethodName + ": ParamIsOptional = " + ParamIsOptional);
             int State = 0;
             ToState(ref State, 1, MethodName);

             while (!Done)
             {
            switch (State)
            {
               case 1:
                  Ch = GetNextChar(Template, ref TemplPtr);

                  switch (Ch)
                  {
                     case 'n':
                        ToState(ref State, 2, MethodName);
                        break;

                     case 's':
                        ToState(ref State, 3, MethodName);
                        break;

                     case '[':
                        ParamIsOptional = true;
                        LogWrite(MethodName + ": ParamIsOptional = " + ParamIsOptional);
                        break;

                     case ']':

                        // do nothing

                        break;

                     case '.':
                        ToState(ref State, 4, MethodName);
                        break;

                     case '/':

                        // switch encountered

                        ToState(ref State, 7, MethodName);
                        break;

                     case '\0':

                        // end of template encountered

                        ToState(ref State, 5, MethodName);
                        break;

                     case ' ':

                        // Ignore and keep scanning...

                        break;

                     case '\t':

                        // Ignore and keep scanning...

                        break;

                     default:

                        // Invalid template character.

                        throw new PipeWrenchEngineException("Template is invalid.");
                  }
                  break;

               case 2:

                  // An integer is expected according to the template.

                  Ch = GetNextChar(this.Text, ref iCmdLinePtr);

                  if ("0123456789-+".IndexOf(Ch) != -1)
                  {
                     // Found an integer.  Back up a character and parse it:

                     CmdLinePtr--;
                     string Token = "";

                     while ((CmdLinePtr < this.Text.Length) && (this.Text[CmdLinePtr] != ' ') &&
                     (this.Text[CmdLinePtr] != '\t'))
                     {
                        Token += this.Text[CmdLinePtr];
                        CmdLinePtr++;
                     }

                     try
                     {
                        // Convert the token to an integer value:

                        int Value = Convert.ToInt32(Token);
                        LogWrite(MethodName + ": IntArg value = " + Value.ToString());
                        Argument arg = new Argument(Value, CmdLinePtr);
                        Args.Add(arg);
                     }
                     catch (Exception)
                     {
                        PipeWrenchCompileException ex = new PipeWrenchCompileException("Integer value is invalid.");
                        ex.Data.Add("CharPos", CmdLinePtr);
                        ex.Data.Add("CmdLine", this.Text);
                        throw ex;
                     }

                     if (ParamIsOptional)
                     {
                        // Found first parameter in optional
                        // sequence.  Now all other parameters
                        // to end of sequence are required.

                        ParamIsOptional = false;
                        LogWrite(MethodName + ": ParamIsOptional = " + ParamIsOptional);
                     }

                     ToState(ref State, 1, MethodName);
                  }
                  else
                  {
                     if (Ch == '\'')
                     {
                        // String encountered instead of an integer.

                        PipeWrenchCompileException ex = new PipeWrenchCompileException("Integer expected for this parameter.");
                        ex.Data.Add("CharPos", CmdLinePtr);
                        ex.Data.Add("CmdLine", this.Text);
                        throw ex;
                     }
                     else
                     {
                        if (Ch == '/')
                        {
                           // Switch encountered instead of an integer.

                           if (ParamIsOptional)
                           {
                              ToState(ref State, 6, MethodName);
                           }
                           else
                           {
                              // Expected integer value was not found.

                              PipeWrenchCompileException ex =
                              new PipeWrenchCompileException("Expected an integer parameter but switch was encountered.");
                              ex.Data.Add("CharPos", CmdLinePtr);
                              ex.Data.Add("CmdLine", this.Text);
                              throw ex;
                           }
                        }
                        else
                        {
                           if (Ch == '\0')
                           {
                              // Reached the end of the command line.

                              if (ParamIsOptional)
                              {
                                 Done = true;
                              }
                              else
                              {
                                 // Expected integer value was not found.

                                 PipeWrenchCompileException ex =
                                 new PipeWrenchCompileException("Expected an integer parameter but end-of-line was encountered.");
                                 ex.Data.Add("CharPos", CmdLinePtr);
                                 ex.Data.Add("CmdLine", this.Text);
                                 throw ex;
                              }
                           }
                           else
                           {
                              if ((Ch == ' ') || (Ch == '\t'))
                              {
                                 // It's a whitespace character.  Just ignore it and keep scanning...
                              }
                              else
                              {
                                 // Expected integer value was not found.

                                 PipeWrenchCompileException ex =
                                 new PipeWrenchCompileException("Integer expected for this parameter.");
                                 ex.Data.Add("CharPos", CmdLinePtr);
                                 ex.Data.Add("CmdLine", this.Text);
                                 throw ex;
                              }
                           }
                        }
                     }
                  }

                  break;

               case 3:

                  // A string is expected according to the template.

                  Ch = GetNextChar(this.Text, ref iCmdLinePtr);

                  if (Ch == '\'')
                  {
                     // Found a string.  Back up and parse it:

                     CmdLinePtr--;
                     string Token;

                     if (xlatStrings)
                     {
                        string tempStr = GetString(this.Text, ref iCmdLinePtr, '\'', true);

                        try
                        {
                           Token = XlatEscapes(tempStr);
                        }

                        catch (PipeWrenchCompileException ex)
                        {
                           ex.Data.Add("CmdLine", this.Text);
                           ex.Data["CharPos"] = CmdLinePtr - tempStr.Length + (int) ex.Data["Offset"];
                           throw ex;
                        }
                     }
                     else
                     {
                        Token = GetString(this.Text, ref iCmdLinePtr, '\'', false);
                     }

                     Argument arg = new Argument(Token, iCmdLinePtr);
                     Args.Add(arg);

                     if (ParamIsOptional)
                     {
                        // Found first parameter in optional sequence.  Now all other
                        // parameters to end of sequence are required.

                        ParamIsOptional = false;
                        LogWrite(MethodName + ": ParamIsOptional = " + ParamIsOptional);
                     }

                     ToState(ref State, 1, MethodName);
                  }
                  else
                  {
                     if ("0123456789-+".IndexOf(Ch) != -1)
                     {
                        // An integer was encountered.

                        PipeWrenchCompileException ex =
                        new PipeWrenchCompileException("String expected for this parameter.");
                        ex.Data.Add("CharPos", CmdLinePtr);
                        ex.Data.Add("CmdLine", this.Text);
                        throw ex;
                     }
                     else
                     {
                        if (Ch == '/')
                        {
                           // A switch was encountered.

                           if (ParamIsOptional)
                           {
                              ToState(ref State, 6, MethodName);
                           }
                           else
                           {
                              PipeWrenchCompileException ex =
                              new PipeWrenchCompileException("Expected a string parameter but switch was encountered.");
                              ex.Data.Add("CharPos", CmdLinePtr);
                              ex.Data.Add("CmdLine", this.Text);
                              throw ex;
                           }
                        }
                        else
                        {
                           if (Ch == '\0')
                           {
                              // Reached the end of the command line.

                              if (ParamIsOptional)
                              {
                                 Done = true;
                              }
                              else
                              {
                                 // Expected string value was not found.

                                 PipeWrenchCompileException ex =
                                 new PipeWrenchCompileException("Expected a string parameter but end-of-line was encountered.");
                                 ex.Data.Add("CharPos", CmdLinePtr);
                                 ex.Data.Add("CmdLine", this.Text);
                                 throw ex;
                              }
                           }
                           else
                           {
                              if ((Ch == ' ') || (Ch == '\t'))
                              {
                                 // It's a whitespace character.  Just ignore it and keep scanning...
                              }
                              else
                              {
                                 // Expected string value was not found.

                                 PipeWrenchCompileException ex =
                                 new PipeWrenchCompileException("String expected for this parameter.");
                                 ex.Data.Add("CharPos", CmdLinePtr);
                                 ex.Data.Add("CmdLine", this.Text);
                                 throw ex;
                              }
                           }
                        }
                     }
                  }

                  break;

               case 4:

                  // Backtracking through optional sequence.

                  int savedTemplPtr = TemplPtr;

                  try
                  {
                     while (Template[TemplPtr] != '[')
                     {
                        TemplPtr--;
                     }
                  }

                  catch (Exception)
                  {
                     PipeWrenchTemplateException ex =
                     new PipeWrenchTemplateException(
                     "Template error: Repeating group (...) is only allowed inside \"[]\".");
                     ex.Data.Add("CharPos", savedTemplPtr);
                     ex.Data.Add("Template", Template);
                     throw ex;
                  }

                  TemplPtr++;
                  ParamIsOptional = true;
                  LogWrite(MethodName + ": ParamIsOptional = " + ParamIsOptional);
                  ToState(ref State, 1, MethodName);
                  break;

               case 5:

                  // End of template encountered.

                  if (!IgnoringExtraneousText)
                  {
                     // Be sure that remainder of command line is clear
                     // as additional parameters, (including switches)
                     // are not expected:

                     Ch = GetNextChar(this.Text, ref iCmdLinePtr);

                     if (Ch == '\0')
                     {
                        Done = true;
                     }
                     else
                     {
                        if ((Ch == ' ') || (Ch == '\t'))
                        {
                           // It's a whitespace character.  Just ignore it and keep scanning...
                        }
                        else
                        {
                           PipeWrenchCompileException ex =
                           new PipeWrenchCompileException("Parameter or switch is extraneous.");
                           ex.Data.Add("CharPos", CmdLinePtr);
                           ex.Data.Add("CmdLine", this.Text);
                           throw ex;
                        }
                     }
                  }
                  else
                  {
                     Done = true;
                  }

                  break;

               case 6:

                  // Switch encountered.

                  if (CmdLinePtr < this.Text.Length)
                  {
                     // Not yet to the end of the command line.

                     string SwitchID = "/" + Char.ToUpper(this.Text[CmdLinePtr]);
                     CmdLinePtr++;
                     ParseSwitch(SwitchID, ref iCmdLinePtr, ref TemplPtr, xlatStrings);
                     ToState(ref State, 7, MethodName);
                  }
                  else
                  {
                     // End of command line was encountered.  Switch
                     // character, (/) was found without a succeeding
                     // ID character.

                     PipeWrenchCompileException ex =
                     new PipeWrenchCompileException("Switch is incomplete.");
                     ex.Data.Add("CharPos", CmdLinePtr);
                     ex.Data.Add("CmdLine", this.Text);
                     throw ex;
                  }

                  break;

               case 7:

                  // Locate the next switch on the command line:

                  Ch = GetNextChar(this.Text, ref iCmdLinePtr);

                  switch (Ch)
                  {
                     case '/':

                        // Found it.

                        ToState(ref State, 6, MethodName);
                        break;

                     case '\0':
                        Done = true;
                        break;

                     case ' ':

                        // Whitespace character.  Just ignore it and keep scanning...

                        break;

                     case '\t':

                        // Whitespace character.  Just ignore it and keep scanning...

                        break;

                     default:
                        PipeWrenchCompileException ex =
                        new PipeWrenchCompileException("A switch was expected.");
                        ex.Data.Add("CharPos", CmdLinePtr);
                        ex.Data.Add("CmdLine", this.Text);
                        throw ex;
                  }

                  break;

               default:
                  throw new PipeWrenchEngineException(MethodName +
                  ": Invalid state (" + State.ToString() + ").");
            }
             }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Parses the command line arguments.
        /// </summary>
        public void Parse(int initPos, bool xlatStrings)
        {
            string MethodName = "CommandLine.Parse";
            bool   Done       = false;
            char   Ch;
            bool   ParamIsOptional = false;
            int    TemplPtr        = 0;

            CmdLinePtr = initPos;
            LogWrite(MethodName + ": Parsing \"" + this.Text + "\" using template, \"" + Template +
                     "\" starting at CharPos " + initPos.ToString() + ".");
            LogWrite(MethodName + ": IgnoringExtraneousText = " + IgnoringExtraneousText);
            LogWrite(MethodName + ": ParamIsOptional = " + ParamIsOptional);
            int State = 0;

            ToState(ref State, 1, MethodName);

            while (!Done)
            {
                switch (State)
                {
                case 1:
                    Ch = GetNextChar(Template, ref TemplPtr);

                    switch (Ch)
                    {
                    case 'n':
                        ToState(ref State, 2, MethodName);
                        break;

                    case 's':
                        ToState(ref State, 3, MethodName);
                        break;

                    case '[':
                        ParamIsOptional = true;
                        LogWrite(MethodName + ": ParamIsOptional = " + ParamIsOptional);
                        break;

                    case ']':

                        // do nothing

                        break;

                    case '.':
                        ToState(ref State, 4, MethodName);
                        break;

                    case '/':

                        // switch encountered

                        ToState(ref State, 7, MethodName);
                        break;

                    case '\0':

                        // end of template encountered

                        ToState(ref State, 5, MethodName);
                        break;

                    case ' ':

                        // Ignore and keep scanning...

                        break;

                    case '\t':

                        // Ignore and keep scanning...

                        break;

                    default:

                        // Invalid template character.

                        throw new PipeWrenchEngineException("Template is invalid.");
                    }
                    break;

                case 2:

                    // An integer is expected according to the template.

                    Ch = GetNextChar(this.Text, ref iCmdLinePtr);

                    if ("0123456789-+".IndexOf(Ch) != -1)
                    {
                        // Found an integer.  Back up a character and parse it:

                        CmdLinePtr--;
                        string Token = "";

                        while ((CmdLinePtr < this.Text.Length) && (this.Text[CmdLinePtr] != ' ') &&
                               (this.Text[CmdLinePtr] != '\t'))
                        {
                            Token += this.Text[CmdLinePtr];
                            CmdLinePtr++;
                        }

                        try
                        {
                            // Convert the token to an integer value:

                            int Value = Convert.ToInt32(Token);
                            LogWrite(MethodName + ": IntArg value = " + Value.ToString());
                            Argument arg = new Argument(Value, CmdLinePtr);
                            Args.Add(arg);
                        }
                        catch (Exception)
                        {
                            PipeWrenchCompileException ex = new PipeWrenchCompileException("Integer value is invalid.");
                            ex.Data.Add("CharPos", CmdLinePtr);
                            ex.Data.Add("CmdLine", this.Text);
                            throw ex;
                        }

                        if (ParamIsOptional)
                        {
                            // Found first parameter in optional
                            // sequence.  Now all other parameters
                            // to end of sequence are required.

                            ParamIsOptional = false;
                            LogWrite(MethodName + ": ParamIsOptional = " + ParamIsOptional);
                        }

                        ToState(ref State, 1, MethodName);
                    }
                    else
                    {
                        if (Ch == '\'')
                        {
                            // String encountered instead of an integer.

                            PipeWrenchCompileException ex = new PipeWrenchCompileException("Integer expected for this parameter.");
                            ex.Data.Add("CharPos", CmdLinePtr);
                            ex.Data.Add("CmdLine", this.Text);
                            throw ex;
                        }
                        else
                        {
                            if (Ch == '/')
                            {
                                // Switch encountered instead of an integer.

                                if (ParamIsOptional)
                                {
                                    ToState(ref State, 6, MethodName);
                                }
                                else
                                {
                                    // Expected integer value was not found.

                                    PipeWrenchCompileException ex =
                                        new PipeWrenchCompileException("Expected an integer parameter but switch was encountered.");
                                    ex.Data.Add("CharPos", CmdLinePtr);
                                    ex.Data.Add("CmdLine", this.Text);
                                    throw ex;
                                }
                            }
                            else
                            {
                                if (Ch == '\0')
                                {
                                    // Reached the end of the command line.

                                    if (ParamIsOptional)
                                    {
                                        Done = true;
                                    }
                                    else
                                    {
                                        // Expected integer value was not found.

                                        PipeWrenchCompileException ex =
                                            new PipeWrenchCompileException("Expected an integer parameter but end-of-line was encountered.");
                                        ex.Data.Add("CharPos", CmdLinePtr);
                                        ex.Data.Add("CmdLine", this.Text);
                                        throw ex;
                                    }
                                }
                                else
                                {
                                    if ((Ch == ' ') || (Ch == '\t'))
                                    {
                                        // It's a whitespace character.  Just ignore it and keep scanning...
                                    }
                                    else
                                    {
                                        // Expected integer value was not found.

                                        PipeWrenchCompileException ex =
                                            new PipeWrenchCompileException("Integer expected for this parameter.");
                                        ex.Data.Add("CharPos", CmdLinePtr);
                                        ex.Data.Add("CmdLine", this.Text);
                                        throw ex;
                                    }
                                }
                            }
                        }
                    }

                    break;

                case 3:

                    // A string is expected according to the template.

                    Ch = GetNextChar(this.Text, ref iCmdLinePtr);

                    if (Ch == '\'')
                    {
                        // Found a string.  Back up and parse it:

                        CmdLinePtr--;
                        string Token;

                        if (xlatStrings)
                        {
                            string tempStr = GetString(this.Text, ref iCmdLinePtr, '\'', true);

                            try
                            {
                                Token = XlatEscapes(tempStr);
                            }

                            catch (PipeWrenchCompileException ex)
                            {
                                ex.Data.Add("CmdLine", this.Text);
                                ex.Data["CharPos"] = CmdLinePtr - tempStr.Length + (int)ex.Data["Offset"];
                                throw ex;
                            }
                        }
                        else
                        {
                            Token = GetString(this.Text, ref iCmdLinePtr, '\'', false);
                        }

                        Argument arg = new Argument(Token, iCmdLinePtr);
                        Args.Add(arg);

                        if (ParamIsOptional)
                        {
                            // Found first parameter in optional sequence.  Now all other
                            // parameters to end of sequence are required.

                            ParamIsOptional = false;
                            LogWrite(MethodName + ": ParamIsOptional = " + ParamIsOptional);
                        }

                        ToState(ref State, 1, MethodName);
                    }
                    else
                    {
                        if ("0123456789-+".IndexOf(Ch) != -1)
                        {
                            // An integer was encountered.

                            PipeWrenchCompileException ex =
                                new PipeWrenchCompileException("String expected for this parameter.");
                            ex.Data.Add("CharPos", CmdLinePtr);
                            ex.Data.Add("CmdLine", this.Text);
                            throw ex;
                        }
                        else
                        {
                            if (Ch == '/')
                            {
                                // A switch was encountered.

                                if (ParamIsOptional)
                                {
                                    ToState(ref State, 6, MethodName);
                                }
                                else
                                {
                                    PipeWrenchCompileException ex =
                                        new PipeWrenchCompileException("Expected a string parameter but switch was encountered.");
                                    ex.Data.Add("CharPos", CmdLinePtr);
                                    ex.Data.Add("CmdLine", this.Text);
                                    throw ex;
                                }
                            }
                            else
                            {
                                if (Ch == '\0')
                                {
                                    // Reached the end of the command line.

                                    if (ParamIsOptional)
                                    {
                                        Done = true;
                                    }
                                    else
                                    {
                                        // Expected string value was not found.

                                        PipeWrenchCompileException ex =
                                            new PipeWrenchCompileException("Expected a string parameter but end-of-line was encountered.");
                                        ex.Data.Add("CharPos", CmdLinePtr);
                                        ex.Data.Add("CmdLine", this.Text);
                                        throw ex;
                                    }
                                }
                                else
                                {
                                    if ((Ch == ' ') || (Ch == '\t'))
                                    {
                                        // It's a whitespace character.  Just ignore it and keep scanning...
                                    }
                                    else
                                    {
                                        // Expected string value was not found.

                                        PipeWrenchCompileException ex =
                                            new PipeWrenchCompileException("String expected for this parameter.");
                                        ex.Data.Add("CharPos", CmdLinePtr);
                                        ex.Data.Add("CmdLine", this.Text);
                                        throw ex;
                                    }
                                }
                            }
                        }
                    }

                    break;

                case 4:

                    // Backtracking through optional sequence.

                    int savedTemplPtr = TemplPtr;

                    try
                    {
                        while (Template[TemplPtr] != '[')
                        {
                            TemplPtr--;
                        }
                    }

                    catch (Exception)
                    {
                        PipeWrenchTemplateException ex =
                            new PipeWrenchTemplateException(
                                "Template error: Repeating group (...) is only allowed inside \"[]\".");
                        ex.Data.Add("CharPos", savedTemplPtr);
                        ex.Data.Add("Template", Template);
                        throw ex;
                    }

                    TemplPtr++;
                    ParamIsOptional = true;
                    LogWrite(MethodName + ": ParamIsOptional = " + ParamIsOptional);
                    ToState(ref State, 1, MethodName);
                    break;

                case 5:

                    // End of template encountered.

                    if (!IgnoringExtraneousText)
                    {
                        // Be sure that remainder of command line is clear
                        // as additional parameters, (including switches)
                        // are not expected:

                        Ch = GetNextChar(this.Text, ref iCmdLinePtr);

                        if (Ch == '\0')
                        {
                            Done = true;
                        }
                        else
                        {
                            if ((Ch == ' ') || (Ch == '\t'))
                            {
                                // It's a whitespace character.  Just ignore it and keep scanning...
                            }
                            else
                            {
                                PipeWrenchCompileException ex =
                                    new PipeWrenchCompileException("Parameter or switch is extraneous.");
                                ex.Data.Add("CharPos", CmdLinePtr);
                                ex.Data.Add("CmdLine", this.Text);
                                throw ex;
                            }
                        }
                    }
                    else
                    {
                        Done = true;
                    }

                    break;

                case 6:

                    // Switch encountered.

                    if (CmdLinePtr < this.Text.Length)
                    {
                        // Not yet to the end of the command line.

                        string SwitchID = "/" + Char.ToUpper(this.Text[CmdLinePtr]);
                        CmdLinePtr++;
                        ParseSwitch(SwitchID, ref iCmdLinePtr, ref TemplPtr, xlatStrings);
                        ToState(ref State, 7, MethodName);
                    }
                    else
                    {
                        // End of command line was encountered.  Switch
                        // character, (/) was found without a succeeding
                        // ID character.

                        PipeWrenchCompileException ex =
                            new PipeWrenchCompileException("Switch is incomplete.");
                        ex.Data.Add("CharPos", CmdLinePtr);
                        ex.Data.Add("CmdLine", this.Text);
                        throw ex;
                    }

                    break;

                case 7:

                    // Locate the next switch on the command line:

                    Ch = GetNextChar(this.Text, ref iCmdLinePtr);

                    switch (Ch)
                    {
                    case '/':

                        // Found it.

                        ToState(ref State, 6, MethodName);
                        break;

                    case '\0':
                        Done = true;
                        break;

                    case ' ':

                        // Whitespace character.  Just ignore it and keep scanning...

                        break;

                    case '\t':

                        // Whitespace character.  Just ignore it and keep scanning...

                        break;

                    default:
                        PipeWrenchCompileException ex =
                            new PipeWrenchCompileException("A switch was expected.");
                        ex.Data.Add("CharPos", CmdLinePtr);
                        ex.Data.Add("CmdLine", this.Text);
                        throw ex;
                    }

                    break;

                default:
                    throw new PipeWrenchEngineException(MethodName +
                                                        ": Invalid state (" + State.ToString() + ").");
                }
            }
        }