Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ippCommandParser.cpp

Go to the documentation of this file.
00001 // 
00002 // DISCLAIMER: 
00003 //  This software was produced by the National Institute of Standards 
00004 //  and Technology (NIST), an agency of the U.S. government, and by statute is 
00005 //  not subject to copyright in the United States.  Recipients of this 
00006 //  software assume all responsibility associated with its operation,
00007 //  modification,maintenance, and subsequent redistribution. 
00008 //
00009 //  See NIST Administration Manual 4.09.07 b and Appendix I. 
00010 //
00011 #include "stdafx.h"
00012  
00013 #include "ippdme/Parser/ippCommandParser.h"
00014 #include "ippdme/Command/commands.h"
00015 
00016 #include "ippdme/ippOtherKeyType.h"
00017 #include "ippdme/ippErrorNameType.h"
00018 #include "ippPatternChecker.h"
00019 #include "ippdme/misc/ippPropDefinition.h"
00020 #include "ippdme/assert.h"
00021 
00022 #include <map>
00023 class ippCommandHashTable
00024 {
00025   typedef std::map<std::string,ippCommandNameType>   Map;
00026   typedef std::map<std::string,ippCommandNameType>::const_iterator  _Iter;
00027   typedef std::pair <std::string, ippCommandNameType> _Pair;
00028   Map _map;
00029 public:
00030   ippCommandHashTable();
00031   ippCommandNameType find(const std::string& string);
00032 } g_command_hash;
00033 
00034 
00035 
00036 #ifdef _DEBUG
00037 #define new DEBUG_NEW
00038 #undef THIS_FILE
00039 static char THIS_FILE[] = __FILE__;
00040 #endif
00041 
00042 bool IsInteger(double value)
00043 {
00044   return (value -(int)value) ==0;
00045 }
00046 bool IsBoolean(double value)
00047 {
00048   return ( value == 0 || value == 1);
00049 }
00050 bool AsBoolean(double value)
00051 {
00052   IPP_ASSERT(IsBoolean(value));
00053   return value != 0.0 ; 
00054 }
00055 int AsInteger(double value)
00056 {
00057   IPP_ASSERT(IsInteger(value));
00058   return (int)value; 
00059 }
00060 
00061 /* ippCommandParser.cc
00062 
00063 This is a command parser for version 1.40 of the I++ DME Spec.
00064 
00065 This defines functions in the ippCommandParser class and defines a main
00066 function outside the ippCommandParser class.
00067 
00068 Functions named makeXXX (where XXX is a command name) are used to
00069 check the arguments to each type of command and to return an instance
00070 of the command. The documentation for each of these gives the rules
00071 that it is enforcing and gives one or more references to pages of
00072 version 1.40 of the spec. The error code generated if a rule is
00073 broken is given after each rule.
00074 
00075 The rules concern allowable arguments only. Context rules are not
00076 handled by the ippCommandParser.
00077 
00078 The reference pages reference both text and examples. Text references
00079 are given in parentheses. Example references are given in brackets.
00080 Other references are not enclosed.
00081 
00082 Example: Reference pages: 23 26 (39) [40] 85
00083 This means there is relevant text on page 39 and an example on page 40.
00084 
00085 Page 17 is not referenced because the print is too small. Page 25 is not
00086 referenced since everything on it appears identically elsewhere.
00087 
00088 */
00089 
00090 
00091 
00092 
00093 
00094 ippCommandParser::ippCommandParser()
00095 {
00096   _argCount = 0;
00097   _argSize = INITARGS;
00098   _argDoubles.resize(_argSize);
00099   _argKeywords.resize(_argSize);
00100   _argStrings.resize(_argSize); // might set all to 0
00101   _argTypes.resize(_argSize);
00102   _arrayIndex = 0;
00103 }
00104 
00105 ippCommandParser::~ippCommandParser()
00106 {
00107 }
00108 
00109 
00110 
00111 void ippCommandParser::setInput(const char * input)
00112 {
00113   strcpy(_inputArray, input); 
00114 
00115   // add the terminiation if missing ....
00116   int length = strlen(_inputArray);
00117   if (length>2 && _inputArray[length-1]!='\n' && _inputArray[length-2]!='\r') {
00118     _inputArray[length+0]='\r';
00119     _inputArray[length+1]='\n';
00120     _inputArray[length+2]=0;
00121    
00122   }
00123 }
00124 
00125 
00126 /*******************************************************************/
00127 
00128 /* ippCommandParser::getErrorMessageString
00129 
00130 Returned Value : char *
00131   If there is a problem with providing a string, this returns NULL.
00132   Otherwise, it returns the buffer argument.
00133 
00134 Called By:
00135    external functions
00136    main (in stand-alone command parser and stand-alone command checker)
00137 
00138 This copies an error message into the buffer. If the error was found
00139 after a command name was recognized (i.e. the error occurred while
00140 parsing the argument list of a valid command), the name of the command
00141 is written into the buffer just before the error message.  For example,
00142 if the command is 05502 GoTo(X(#)), which is OK up to the #, the error
00143 message in the buffer will be "GoTo: BAD COMMAND ARGUMENTS".  If the
00144 command is A2345 GoTo(X(3.1)), which has an error that is detected
00145 before the command name is read, the error message in the buffer will
00146 be "BAD TAG CHARACTER"
00147 
00148 The symbol for each error code is the same as the text of the error
00149 message, except that the symbol has underscores. The symbol serves as
00150 an index into the array of strings defined here. The symbols are
00151 defined in ippCommandParser.h.
00152 
00153 */
00154 #define PARSER_ERROR_ENUMERATION\
00155   ENUM(OK ,"OK")\
00156   ENUM(ARGUMENT_FIRST_PART_MUST_BE_TOOL_OR_FOUNDTOOL,       "ARGUMENT FIRST PART MUST BE TOOL OR FOUNDTOOL")\
00157   ENUM(ARGUMENT_FOURTH_PART_MUST_BE_ACT,                    "ARGUMENT FOURTH PART MUST BE ACT")\
00158   ENUM(ARGUMENT_FOURTH_PART_BAD,                            "ARGUMENT FOURTH PART BAD")\
00159   ENUM(ARGUMENT_MUST_BE_A_NUMBER,                           "ARGUMENT MUST BE A NUMBER")\
00160   ENUM(ARGUMENT_MUST_BE_EVENT_TAG,                          "ARGUMENT MUST BE EVENT TAG")\
00161   ENUM(ARGUMENT_MUST_BE_INTEGER,                            "ARGUMENT MUST BE INTEGER")\
00162   ENUM(ARGUMENT_MUST_BE_POSITIVE,                           "ARGUMENT MUST BE POSITIVE")\
00163   ENUM(ARGUMENT_MUST_BE_STRING,                             "ARGUMENT MUST BE STRING")\
00164   ENUM(ARGUMENT_MUST_END_WITH_EMPTY_PARENTHESES,            "ARGUMENT MUST END WITH EMPTY PARENTHESES")\
00165   ENUM(ARGUMENT_MUST_END_WITH_NUMBER_IN_PARENTHESES,        "ARGUMENT MUST END WITH NUMBER IN PARENTHESES")\
00166   ENUM(ARGUMENT_SECOND_PART_BAD,                            "ARGUMENT SECOND PART BAD")\
00167   ENUM(ARGUMENT_SECOND_PART_MUST_BE_GOTOPAR_OR_PTMEASPAR,   "ARGUMENT SECOND PART MUST BE GOTOPAR OR PTMEASPAR")\
00168   ENUM(ARGUMENT_THIRD_PART_BAD,                             "ARGUMENT THIRD PART BAD")\
00169   ENUM(BAD_ARGUMENTS,                                       "BAD ARGUMENTS")\
00170   ENUM(BAD_CHARACTER_AFTER_COMMAND_END,                     "BAD CHARACTER AFTER COMMAND END")\
00171   ENUM(BAD_CHARACTER_AFTER_KEYWORD,                         "BAD CHARACTER AFTER KEYWORD")\
00172   ENUM(BAD_COMMAND_ARGUMENTS,                               "BAD COMMAND ARGUMENTS")\
00173   ENUM(BAD_COMMAND_NAME,                                    "BAD COMMAND NAME")\
00174   ENUM(BAD_DOTS,                                            "BAD DOTS")\
00175   ENUM(BAD_E_NUMBER_EXPONENT_MUST_HAVE_ONE_TWO_OR_THREE_DIGITS,"BAD E NUMBER EXPONENT MUST HAVE ONE TWO OR THREE DIGITS")\
00176   ENUM(BAD_FIRST_ARGUMENT,                                  "BAD FIRST ARGUMENT")\
00177   ENUM(BAD_IJK_NUMBERS,                                     "BAD IJK NUMBERS")\
00178   ENUM(BAD_KEYWORD,                                         "BAD KEYWORD")\
00179   ENUM(BAD_NUMBER_MORE_THAN_16_DIGITS,                      "BAD NUMBER MORE THAN 16 DIGITS")\
00180   ENUM(BAD_NUMBER_NO_DIGITS,                                "BAD NUMBER NO DIGITS")\
00181   ENUM(BAD_NUMBER_OF_THROUGHS,                              "BAD NUMBER OF THROUGHS")\
00182   ENUM(BAD_NUMBER_TWO_DECIMAL_POINTS,                       "BAD NUMBER TWO DECIMAL POINTS")\
00183   ENUM(BAD_STRING,                                          "BAD STRING")\
00184   ENUM(BAD_TAG_CHARACTER,                                   "BAD TAG CHARACTER")\
00185   ENUM(C_ARGUMENT_USED_TWICE,                               "C ARGUMENT USED TWICE")\
00186   ENUM(DIAMETER_MUST_BE_POSITIVE,                           "DIAMETER MUST BE POSITIVE")\
00187   ENUM(DIS_ARGUMENT_USED_TWICE,                             "DIS ARGUMENT USED TWICE")\
00188   ENUM(DIS_MUST_BE_FOLLOWED_BY_NUMBER_IN_PARENS,            "DIS MUST BE FOLLOWED BY NUMBER IN PARENS")\
00189   ENUM(ER_ARGUMENT_USED_TWICE,                              "ER ARGUMENT USED TWICE")\
00190   ENUM(EVENT_COMMAND_MUST_HAVE_EVENT_TAG,                   "EVENT COMMAND MUST HAVE EVENT TAG")\
00191   ENUM(IJK_ARGUMENT_USED_TWICE,                             "IJK ARGUMENT USED TWICE")\
00192   ENUM(IJK_NOT_FOLLOWED_BY_ARGIJK,                          "IJK NOT FOLLOWED BY ARGIJK")\
00193   ENUM(LMN_ARGUMENT_USED_TWICE,                             "LMN ARGUMENT USED TWICE")\
00194   ENUM(LMN_NOT_FOLLOWED_BY_ARGIJK,                          "LMN NOT FOLLOWED BY ARGIJK")\
00195   ENUM(ILLEGAL_SPACE,                                       "ILLEGAL SPACE")\
00196   ENUM(MUST_HAVE_NO_ARGUMENTS,                              "MUST HAVE NO ARGUMENTS")\
00197   ENUM(MUST_HAVE_ONE_ARGUMENT,                              "MUST HAVE ONE ARGUMENT")\
00198   ENUM(MUST_HAVE_4_ARGUMENTS,                               "MUST HAVE 4 ARGUMENTS")\
00199   ENUM(MUST_HAVE_4_OR_8_ARGUMENTS,                          "MUST HAVE 4 OR 8 ARGUMENTS")\
00200   ENUM(MUST_HAVE_7_ARGUMENTS,                               "MUST HAVE 7 ARGUMENTS")\
00201   ENUM(MUST_HAVE_7_OR_14_ARGUMENTS,                         "MUST HAVE 7 OR 14 ARGUMENTS")\
00202   ENUM(NON_EVENT_COMMAND_MUST_NOT_HAVE_EVENT_TAG,           "NON EVENT COMMAND MUST NOT HAVE EVENT TAG")\
00203   ENUM(NUMBER_THROUGH_MUST_BE_INTEGER,                      "NUMBER THROUGH MUST BE INTEGER")\
00204   ENUM(NUMBER_THROUGH_MUST_BE_POSITIVE,                     "NUMBER THROUGH MUST BE POSITIVE")\
00205   ENUM(PHI_ARGUMENT_USED_TWICE,                             "PHI ARGUMENT USED TWICE")\
00206   ENUM(Q_ARGUMENT_USED_TWICE,                               "Q ARGUMENT USED TWICE")\
00207   ENUM(R_ARGUMENT_USED_TWICE,                               "R ARGUMENT USED TWICE")\
00208   ENUM(SPACE_MISSING_AFTER_TAG,                             "SPACE MISSING AFTER TAG")\
00209   ENUM(STEPW_MUST_BE_POSITIVE,                              "STEPW MUST BE POSITIVE")\
00210   ENUM(TAG_NUMBER_OUT_OF_RANGE_FOR_EVENT_TAG,               "TAG NUMBER OUT OF RANGE FOR EVENT TAG")\
00211   ENUM(TAG_NUMBER_OUT_OF_RANGE_FOR_COMMAND_TAG,             "TAG NUMBER OUT OF RANGE FOR COMMAND TAG")\
00212   ENUM(THETA_OUT_OF_RANGE,                                  "THETA OUT OF RANGE")\
00213   ENUM(TIME_ARGUMENT_USED_TWICE,                            "TIME ARGUMENT USED TWICE")\
00214   ENUM(TIME_MUST_BE_FOLLOWED_BY_NUMBER_IN_PARENS,           "TIME MUST BE FOLLOWED BY NUMBER IN PARENS")\
00215   ENUM(TOOL_A_ARGUMENT_USED_TWICE,                          "TOOL A ARGUMENT USED TWICE")\
00216   ENUM(TOOL_B_ARGUMENT_USED_TWICE,                          "TOOL B ARGUMENT USED TWICE")\
00217   ENUM(TOOL_C_ARGUMENT_USED_TWICE,                          "TOOL C ARGUMENT USED TWICE")\
00218   ENUM(X_ARGUMENT_USED_TWICE,                               "X ARGUMENT USED TWICE")\
00219   ENUM(X_NOT_FOLLOWED_BY_NUMBER_IN_PARENS,                  "X NOT FOLLOWED BY NUMBER IN PARENS")\
00220   ENUM(X_Y_Z_ALL_MISSING,                                   "X Y Z ALL MISSING")\
00221   ENUM(Y_ARGUMENT_USED_TWICE,                               "Y ARGUMENT USED TWICE")\
00222   ENUM(Y_NOT_FOLLOWED_BY_NUMBER_IN_PARENS,                  "Y NOT FOLLOWED BY NUMBER IN PARENS")\
00223   ENUM(Z_ARGUMENT_USED_TWICE,                               "Z ARGUMENT USED TWICE")\
00224   ENUM(Z_NOT_FOLLOWED_BY_NUMBER_IN_PARENS,                  "Z NOT FOLLOWED BY NUMBER IN PARENS")\
00225   ENUM(TOOL_A_NOT_FOLLOWED_BY_NUMBER_IN_PARENS,             "TOOL.A NOT FOLLOWED BY NUMBER IN_PARENS")\
00226   ENUM(TOOL_B_NOT_FOLLOWED_BY_NUMBER_IN_PARENS,             "TOOL.B NOT FOLLOWED BY NUMBER IN_PARENS")\
00227   ENUM(TOOL_C_NOT_FOLLOWED_BY_NUMBER_IN_PARENS,             "TOOL.C NOT FOLLOWED BY NUMBER IN_PARENS")\
00228   ENUM(IJKACT_ARGUMENT_USED_TWICE,                          "IJKACT ARGUMENT USED TWICE")\
00229   ENUM(DENSITY_MUST_BE_POSITIVE,                            "DENSITY MUST BE POSITIVE")\
00230   ENUM(MINIMUM_RADIUS_OF_CURVATURE_MUST_BE_POSITIVE,        "MINIMUM RADIUS OF CURVATURE MUST BE POSITIVE")\
00231   ENUM(ANGLE_ARGUMENT_USED_TWICE,                           "ANGLE ARGUMENT USED TWICE")\
00232   ENUM(ATNOMINALS_ARGUMENT_USED_TWICE,                      "ATNOMINALS ARGUMENT USED TWICE")\
00233   ENUM(ANGLE_MUST_BE_FOLLOWED_BY_NUMBER_IN_PARENS,          "ANGLE MUST BE FOLLOWED BY NUMBER IN PARENS")\
00234   ENUM(ATNOMINALS_NOT_FOLLOWED_BY_BOOLEAN_IN_PARENS,        "ATNOMINALS NOT FOLLOWED BY BOOLEAN IN PARENS")\
00235   ENUM(BAD_SYNTAX_FOR_FORMAT_IN_SCANONCURVE,                "BAD SYNTAX FOR FORMAT IN SCANONCURVE")\
00236   ENUM(BAD_NUMBER_OF_ARGUMENT_FOR_DATA_IN_SCANONCURVE,      "BAD NUMBER OF ARGUMENT FOR DATA IN SCANONCURVE")\
00237   ENUM(NOT_IMPLEMENTED_YET,                                 "NOT_IMPLEMENTED_YET")
00238                                                             
00239                                                             
00240                                                             
00241 std::string  ippCommandParser::getErrorMessageString() const
00242 {                                                           
00243   std::string errorString ;
00244   switch(_errorCode) {
00245 #define ENUM(a,b) case a: errorString=b; break;
00246     PARSER_ERROR_ENUMERATION
00247 #undef ENUM
00248   }
00249 
00250   std::string retval;
00251 
00252   if ((_commandName > -1) && (_commandName < ippCOMMANDNAMETYPE_MAXIMUM)) {
00253     retval.append(getCommandNameString(_commandName));
00254     retval.append(" : ");
00255   } 
00256   
00257   retval.append(errorString);
00258   return retval;
00259 }
00260 
00261 /*******************************************************************/
00262 
00263 /* ippCommandParser::makeArraysBigger
00264 
00265 Returned Value: None.
00266 
00267 Called By: ippCommandParser::parseArguments
00268 
00269 Rules: None.
00270 
00271 This doubles the sizes of the four arrays in which arguments are stored.
00272 It also doubles argSize.
00273 
00274 This makes new arrays twice the size of its original size, this 
00275 preserve the content of existing data.
00276 
00277 */
00278 
00279 void ippCommandParser::makeArraysBigger()
00280 {
00281   _argSize = (2 * _argSize);
00282   _argDoubles.resize(_argSize);
00283   _argKeywords.resize(_argSize);
00284   _argStrings.resize(_argSize); 
00285   _argTypes.resize(_argSize);
00286 }
00287 
00288 
00289 /*******************************************************************/
00290 
00291 /* ippCommandParser::makeAbortE
00292 
00293 Returned Value: A ippCommand of commandNameType AbortE as described by the
00294   command text, or NULL.
00295 
00296 Called By: ippCommandParser::makeCommand
00297 
00298 Rules:
00299 1. There must be no arguments.
00300    MUST_HAVE_NO_ARGUMENTS
00301 
00302 Reference pages: 9 24 26 (42) [43] 99
00303 
00304 */
00305 
00306 ippCommandPtr ippCommandParser::makeAbortE()
00307 {
00308   if (_argCount != 0) {
00309     _errorCode = MUST_HAVE_NO_ARGUMENTS;
00310   }
00311   return ((_errorCode != OK) ? 0 : new ippCommand(_tag, AbortE));
00312 }
00313 
00314 /*******************************************************************/
00315 
00316 /* ippCommandParser::makeAlignPart
00317 
00318 Returned Value: An AlignPartCommand as described by the command text, or NULL.
00319 
00320 Called By: ippCommandParser::makeCommand
00321 
00322 Rules:
00323 1. There must be 7 or 14 arguments.
00324    MUST_HAVE_7_OR_14_ARGUMENTS
00325 2. The arguments must all be numbers.
00326    BAD_ARGUMENTS
00327 3. Commas must separate the arguments.
00328    BAD_ARGUMENTS
00329 
00330 Reference pages: 24 28 63 (95) 105
00331 
00332 */
00333 
00334 ippCommandPtr ippCommandParser::makeAlignPart()
00335 {
00336   if (_argCount == 13 ) { 
00337     if (!match(_argTypes,"#,#,#,#,#,#,#")) {
00338       _errorCode = BAD_ARGUMENTS;
00339     }
00340   } else if ( _argCount == 27 ) {   
00341     if (!match(_argTypes,"#,#,#,#,#,#,#,#,#,#,#,#,#,#")) {
00342       _errorCode = BAD_ARGUMENTS;
00343     }
00344   } else {
00345     _errorCode = MUST_HAVE_7_OR_14_ARGUMENTS;
00346   }
00347    
00348   return ((_errorCode != OK) ? NULL:
00349       (_argCount == 13) ?
00350       new ippAlignPartCommand(_tag, 
00351                getValue(0), getValue(2), getValue(4),
00352                getValue(6), getValue(8), getValue(10),
00353                getValue(12)) :
00354       new ippAlignPartCommand(_tag, 
00355                getValue(0),  getValue(2),  getValue(4),
00356                getValue(6),  getValue(8),  getValue(10),
00357                getValue(12), getValue(14), getValue(16),
00358                getValue(18), getValue(20), getValue(22),
00359                getValue(24), getValue(26)));
00360 }
00361 
00362 /*******************************************************************/
00363 
00364 /* ippCommandParser::makeAlignTool
00365 
00366 Returned Value: An AlignToolCommand as described by the command text, or NULL.
00367 
00368 Called By: ippCommandParser::makeCommand
00369 
00370 Rules:
00371 1. There must be 4 or 8 arguments.
00372    MUST_HAVE_4_OR_8_ARGUMENTS
00373 2. The arguments must all be numbers.
00374    BAD_ARGUMENTS
00375 3. Commas must separate the arguments.
00376    BAD_ARGUMENTS
00377 
00378 Reference pages: 24 27 29 (55) 66 70 102 107
00379 
00380 */
00381 
00382 ippCommandPtr ippCommandParser::makeAlignTool()
00383 {
00384 
00385   if (_argCount == 7 ) { 
00386     if (!match(_argTypes,"#,#,#,#")) {
00387       _errorCode = BAD_ARGUMENTS;
00388     }
00389   } else if ( _argCount == 15 ) {   
00390     if (!match(_argTypes,"#,#,#,#,#,#,#,#")) {
00391       _errorCode = BAD_ARGUMENTS;
00392     }
00393   } else {
00394     _errorCode = MUST_HAVE_4_OR_8_ARGUMENTS;
00395   }
00396   return ((_errorCode != OK) ? NULL:
00397     (_argCount == 7) ?
00398     new ippAlignToolCommand(_tag,  getValue(0), getValue(2),
00399              getValue(4), getValue(6)) :
00400     new ippAlignToolCommand(_tag, getValue(0), getValue(2),
00401              getValue(4), getValue(6),
00402              getValue(8), getValue(10),
00403              getValue(12), getValue(14)));
00404 }
00405 
00406 /*******************************************************************/
00407 
00408 /* ippCommandParser::makeCenterPart
00409 
00410 Returned Value: A CenterPartCommand as described by the command text, or NULL.
00411 
00412 Called By: ippCommandParser::makeCommand
00413 
00414 Rules:
00415 1. There must be 4 arguments.
00416    MUST_HAVE_4_ARGUMENTS
00417 2. The arguments must all be numbers.
00418    BAD_ARGUMENTS
00419 3. Commas must separate the arguments.
00420    BAD_ARGUMENTS
00421 
00422 Reference pages: 24 27 (96) 102
00423 
00424 */
00425 
00426 ippCommandPtr ippCommandParser::makeCenterPart()
00427 {
00428   if (_argCount != 7) {
00429     _errorCode = MUST_HAVE_4_ARGUMENTS;
00430   }
00431   if (!match(_argTypes,"#,#,#,#")) {
00432     _errorCode = BAD_ARGUMENTS;
00433   }
00434   return ((_errorCode != OK) ? NULL:
00435     new ippCenterPartCommand(_tag, getValue(0), getValue(2),
00436         getValue(4), getValue(6)));
00437 }
00438 
00439 /*******************************************************************/
00440 
00441 /* ippCommandParser::makeChangeTool
00442 
00443 Returned Value: A ChangeToolCommand as described by the command text, or NULL.
00444 
00445 Called By: ippCommandParser::makeCommand
00446 
00447 Rules:
00448 1. There must be one argument.
00449    MUST_HAVE_ONE_ARGUMENT
00450 2. The argument must be a string.
00451    ARGUMENT_MUST_BE_STRING
00452 
00453 Reference pages: 24 27 29 (54) (57) (58) (78) 98 102 106
00454 
00455 */
00456 
00457 ippCommandPtr ippCommandParser::makeChangeTool()
00458 {
00459   if (_argCount != 1)
00460     _errorCode = MUST_HAVE_ONE_ARGUMENT;
00461   else if (_argTypes[0] != ARGSTRING)
00462     _errorCode = ARGUMENT_MUST_BE_STRING;
00463   return ((_errorCode != OK) ? NULL :
00464     (new ippChangeToolCommand(_tag, _argStrings[0].c_str())));
00465 }
00466 
00467 /*******************************************************************/
00468 
00469 /* ippCommandParser::makeClearAllErrors
00470 
00471 Returned Value: A ippCommand of commandNameType ClearAllErrors as described
00472   by the command text, or NULL.
00473 
00474 Called By: ippCommandParser::makeCommand
00475 
00476 Rules:
00477 1. There must be no arguments.
00478    MUST_HAVE_NO_ARGUMENTS
00479 
00480 Reference pages: 24 26 [38] (40) (41) (42) (43) [44] (47) (75) 76 99
00481 
00482 */
00483 
00484 ippCommandPtr ippCommandParser::makeClearAllErrors()
00485 {
00486   if (_argCount != 0)
00487     _errorCode = MUST_HAVE_NO_ARGUMENTS;
00488   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, ClearAllErrors)));
00489 }
00490 
00491 /*******************************************************************/
00492 
00493 /* ippCommandParser::makeDisableUser
00494 
00495 Returned Value: A ippCommand of commandNameType DisableUser as described
00496   by the command text, or NULL.
00497 
00498 Called By: ippCommandParser::makeCommand
00499 
00500 Rules:
00501 1. There must be no arguments.
00502    MUST_HAVE_NO_ARGUMENTS
00503 
00504 Reference pages: 24 27 (48) (51) (53) 102
00505 
00506 */
00507 
00508 ippCommandPtr ippCommandParser::makeDisableUser()
00509 {
00510   if (_argCount != 0)
00511     _errorCode = MUST_HAVE_NO_ARGUMENTS;
00512   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, DisableUser)));
00513 }
00514 
00515 /*******************************************************************/
00516 
00517 /* ippCommandParser::makeEnableUser
00518 
00519 Returned Value: A ippCommand of commandNameType EnableUser as described by
00520   the command text, or NULL.
00521 
00522 Called By: ippCommandParser::makeCommand
00523 
00524 Rules:
00525 1. There must be no arguments.
00526    MUST_HAVE_NO_ARGUMENTS
00527 
00528 Reference pages: 24 27 [39] (48) (51) 102
00529 
00530 */
00531 
00532 ippCommandPtr ippCommandParser::makeEnableUser()
00533 {
00534   if (_argCount != 0)
00535     _errorCode = MUST_HAVE_NO_ARGUMENTS;
00536   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, EnableUser)));
00537 }
00538 
00539 /*******************************************************************/
00540 
00541 /* ippCommandParser::makeEndSession
00542 
00543 Returned Value: A ippCommand of commandNameType EndSession as described by
00544   the command text, or NULL.
00545 
00546 Called By: ippCommandParser::makeCommand
00547 
00548 Rules:
00549 1. There must be no arguments
00550    MUST_HAVE_NO_ARGUMENTS
00551 
00552 Reference pages: 18 20 24 26 (41) (77) 99
00553 
00554 */
00555 
00556 ippCommandPtr ippCommandParser::makeEndSession()
00557 {
00558   if (_argCount != 0)
00559     _errorCode = MUST_HAVE_NO_ARGUMENTS;
00560   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, EndSession)));
00561 }
00562 
00563 /*******************************************************************/
00564 
00565 /* ippCommandParser::makeEnumAllProp
00566 
00567 Returned Value: An EnumAllPropCommand as described by the command text,
00568   or NULL.
00569 
00570 Called By: ippCommandParser::makeCommand
00571 
00572 Rules:
00573 1. There must be one argument.
00574    BAD_ARGUMENTS
00575 2. The argument must have one of the following patterns.
00576    key1()
00577    key1.key2()
00578    key1.key2.key3()
00579    key1.key2.key3.key4()
00580 3. key1 must be FoundTool or Tool 
00581    ARGUMENT_FIRST_PART_MUST_BE_TOOL_OR_FOUNDTOOL
00582 4. key2 must be GoToPar or PtMeasPar.
00583    ARGUMENT_SECOND_PART_MUST_BE_GOTOPAR_OR_PTMEASPAR
00584 5. If key2 is GoToPar, key3 must be Speed or Accel.
00585    If key2 is PtMeasPar, key3 must be one of
00586    Speed, Accel, Approach, Retract, or Search.
00587    ARGUMENT_THIRD_PART_BAD
00588 6. If there is a key4, it must be Act, Def, Max, or Min.
00589    ARGUMENT_FOURTH_PART_BAD
00590 7. The dots must be placed as shown in rule 2.
00591    BAD_DOTS
00592 8. The empty parentheses must be placed as shown in rule 2.
00593    ARGUMENT_MUST_END_WITH_EMPTY_PARENTHESES
00594 
00595 Reference pages: 24 26 45 (46) [74] 99
00596 
00597 See the documentation of ippCommandParser::makeGetProp.
00598 
00599 This is not allowing Alignment, CollisionVolume, Name, or Id, since
00600 the spec allows them only with GetProp.
00601 
00602 */
00603 
00604 ippCommandPtr ippCommandParser::makeEnumAllProp()
00605 {
00606 
00607   ippOtherKeyType key1 = EmptyKey;
00608   ippOtherKeyType key2 = EmptyKey;
00609   ippOtherKeyType key3 = EmptyKey;
00610   ippOtherKeyType key4 = EmptyKey;
00611 
00612   if (_argCount == 2 && match(_argTypes,"kE")) {
00613     key1 = _argKeywords[0];
00614   } else if (_argCount == 4 && match(_argTypes,"k.kE")) { 
00615     key1 = _argKeywords[0];
00616     key2 = _argKeywords[2];
00617   } else if (_argCount == 6 && match(_argTypes,"k.k.kE")) { 
00618     key1 = _argKeywords[0];
00619     key2 = _argKeywords[2];
00620     key3 = _argKeywords[4];
00621   } else if (_argCount == 8 && match(_argTypes,"k.k.k.kE")) { 
00622     key1 = _argKeywords[0];
00623     key2 = _argKeywords[2];
00624     key3 = _argKeywords[4];
00625     key4 = _argKeywords[6];
00626   } else {
00627     _errorCode =  BAD_ARGUMENTS;
00628     return 0;
00629 
00630   }
00631   ippProp prop(key1,key2,key3,key4);
00632   if (!IsObjectOrProperty(prop)) {
00633     _errorCode =  BAD_ARGUMENTS;
00634     return 0;
00635   }
00636 
00637   ippEnumAllPropCommandPtr command = new ippEnumAllPropCommand(_tag,prop);
00638 
00639   return command;
00640 }
00641 
00642 /*******************************************************************/
00643 
00644 /* ippCommandParser::makeEnumProp
00645 
00646 Returned Value: An EnumPropCommand as described by the command text,
00647   or NULL.
00648 
00649 Called By: ippCommandParser::makeCommand
00650 
00651 Rules:
00652 1. There must be one argument.
00653    BAD_ARGUMENTS
00654 2. The argument must have one of the following patterns.
00655    key1()
00656    key1.key2()
00657    key1.key2.key3()
00658    key1.key2.key3.key4()
00659 3. key1 must be FoundTool or Tool.
00660    ARGUMENT_FIRST_PART_MUST_BE_TOOL_OR_FOUNDTOOL
00661 4. If there is a key2, it must be GoToPar or PtMeasPar.
00662    ARGUMENT_SECOND_PART_MUST_BE_GOTOPAR_OR_PTMEASPAR
00663 5. If key2 is GoToPar and there is a key3, key3 must be Speed or MaxAccel.
00664    If key2 is PtMeasPar and there is a key3, key3 must be one of
00665    Speed, Accel, Approach, Retract, or Search.
00666    ARGUMENT_THIRD_PART_BAD
00667 6. If there is a key4, it must be Act, Def, Max, or Min.
00668    ARGUMENT_FOURTH_PART_BAD
00669 7. The dots must be placed as shown in rule 1.
00670    BAD_DOTS
00671 8. The empty parentheses must be placed as shown in rule 1.
00672    ARGUMENT_MUST_END_WITH_EMPTY_PARENTHESES
00673 
00674 Reference pages: 24 26 29 (45) [73] 99 108 109 110 111 
00675 
00676 See the documentation of ippCommandParser::makeGetProp.
00677 
00678 This is not allowing Alignment, CollisionVolume, Name, or Id, since
00679 the spec allows them only with GetProp.
00680 
00681 */
00682 
00683 ippCommandPtr ippCommandParser::makeEnumProp()
00684 {
00685 
00686   ippOtherKeyType key1 = EmptyKey;
00687   ippOtherKeyType key2 = EmptyKey;
00688   ippOtherKeyType key3 = EmptyKey;
00689   ippOtherKeyType key4 = EmptyKey;
00690 
00691   if (_argCount == 2 && match(_argTypes,"kE")) {
00692     key1 = _argKeywords[0];
00693   } else if (_argCount == 4 && match(_argTypes,"k.kE")) { 
00694     key1 = _argKeywords[0];
00695     key2 = _argKeywords[2];
00696   } else if (_argCount == 6 && match(_argTypes,"k.k.kE")) { 
00697     key1 = _argKeywords[0];
00698     key2 = _argKeywords[2];
00699     key3 = _argKeywords[4];
00700   } else if (_argCount == 8 && match(_argTypes,"k.k.k.kE")) { 
00701     key1 = _argKeywords[0];
00702     key2 = _argKeywords[2];
00703     key3 = _argKeywords[4];
00704     key4 = _argKeywords[6];
00705   } else {
00706     _errorCode =  BAD_ARGUMENTS;
00707     return 0;
00708 
00709   }
00710   ippProp prop(key1,key2,key3,key4);
00711   if (!IsObjectOrProperty(prop)) {
00712     _errorCode =  BAD_ARGUMENTS;
00713     return 0;
00714   }
00715   ippEnumPropCommandPtr command = new ippEnumPropCommand(_tag,prop);
00716   return command;
00717 
00718 }
00719 
00720 /*******************************************************************/
00721 
00722 /* ippCommandParser::makeEnumTools
00723 
00724 Returned Value: A ippCommand of commandNameType EnumTools as described by
00725   the command text, or NULL.
00726 
00727 Called By: ippCommandParser::makeCommand
00728 
00729 Rules:
00730 1. There must be no arguments.
00731    MUST_HAVE_NO_ARGUMENTS
00732 
00733 Reference pages: 24 29 (53) (54) (56) 106
00734 
00735 */
00736 
00737 ippCommandPtr ippCommandParser::makeEnumTools()
00738 {
00739   if (_argCount != 0)
00740     _errorCode = MUST_HAVE_NO_ARGUMENTS;
00741   return ((_errorCode != OK) ? NULL : (new ippEnumToolsCommand(_tag)));
00742 }
00743 
00744 /*******************************************************************/
00745 
00746 /* ippCommandParser::makeFindTool
00747 
00748 Returned Value: A FindToolCommand as described by the command text,
00749   or NULL.
00750 
00751 Called By: ippCommandParser::makeCommand
00752 
00753 Rules:
00754 1. There must be one argument.
00755    MUST_HAVE_ONE_ARGUMENT
00756 2. The argument must be a string.
00757    ARGUMENT_MUST_BE_STRING
00758 
00759 Reference pages: 24 27 29 (54) [74] 102 106
00760 
00761 */
00762 
00763 ippCommandPtr ippCommandParser::makeFindTool()
00764 {
00765   if (_argCount != 1)
00766     _errorCode = MUST_HAVE_ONE_ARGUMENT;
00767   else if (_argTypes[0] != ARGSTRING)
00768     _errorCode = ARGUMENT_MUST_BE_STRING;
00769   return((_errorCode != OK) ? NULL: (new ippFindToolCommand(_tag, _argStrings[0].c_str())));
00770 }
00771 
00772 /*******************************************************************/
00773 
00774 /* ippCommandParser::makeGet
00775 
00776 Returned Value: A GetCommand as described by the command text, or NULL.
00777 
00778 Called By: ippCommandParser::makeCommand
00779 
00780 Rules:
00781 1. There must be one to seven arguments.
00782    BAD_ARGUMENTS
00783 2. Each argument must be R(), X(), Y(), Z(), Tool.A(), Tool.B() or Tool.C(),
00784    which may appear in any order.
00785    BAD_ARGUMENTS
00786 3. Each allowed argument must appear at most once.
00787    R_ARGUMENT_USED_TWICE
00788    X_ARGUMENT_USED_TWICE
00789    Y_ARGUMENT_USED_TWICE
00790    Z_ARGUMENT_USED_TWICE
00791    TOOL_A_ARGUMENT_USED_TWICE
00792    TOOL_B_ARGUMENT_USED_TWICE
00793    TOOL_C_ARGUMENT_USED_TWICE
00794 4. Commas must separate the arguments if there are two or more.
00795    BAD_ARGUMENTS
00796 
00797 Reference pages: 24 27 [38] [44] (49) (51) 57 (61) (63) (66) (81) 102
00798 
00799 Tool properties that can be set directly are intended to be obtained
00800 by GetProp, not by Get.
00801 
00802 This function is similar to makeGoTo.
00803 
00804 This function is messy because it takes a variable number of arguments
00805 and the arguments may have different numbers of components, e.g., "X()"
00806 has 2 components while "Tool.A()" has 4.
00807 
00808 The check (((n + 2) < _argCount) && ((n + 3) == _argCount)) is to detect
00809 the case of a comma at the end of the argument list, which will otherwise
00810 slip by. The (((n + 4) < _argCount) && ((n + 5) == _argCount)) does the
00811 same thing.
00812 
00813 */
00814 
00815 ippCommandPtr ippCommandParser::makeGet()
00816 {
00817   bool hasR = false;
00818   bool hasX = false;
00819   bool hasY = false;
00820   bool hasZ = false;
00821   bool hasToolA = false;
00822   bool hasToolB = false;
00823   bool hasToolC = false;
00824 
00825   if (_argCount < 2) {
00826     _errorCode = BAD_ARGUMENTS;
00827   }
00828   int n =0;
00829 
00830   while (n < _argCount && _errorCode == OK) {
00831     int old_n=n;
00832     CheckOptionalArgument(n,hasR    ,_R   ,       R_ARGUMENT_USED_TWICE);
00833     CheckOptionalArgument(n,hasX    ,_X   ,       X_ARGUMENT_USED_TWICE);
00834     CheckOptionalArgument(n,hasY    ,_Y   ,       Y_ARGUMENT_USED_TWICE);
00835     CheckOptionalArgument(n,hasZ    ,_Z   ,       Z_ARGUMENT_USED_TWICE);
00836     CheckOptionalArgument(n,hasToolA,Tool,_A,TOOL_A_ARGUMENT_USED_TWICE);
00837     CheckOptionalArgument(n,hasToolB,Tool,_B,TOOL_B_ARGUMENT_USED_TWICE);
00838     CheckOptionalArgument(n,hasToolC,Tool,_C,TOOL_C_ARGUMENT_USED_TWICE);    
00839     if (old_n == n) { 
00840       // the argument has not been recognized:
00841       _errorCode = BAD_ARGUMENTS;
00842     } 
00843   }
00844   return ((_errorCode != OK) ? NULL:
00845     (new ippGetCommand(_tag, hasR, hasX, hasY, hasZ,
00846         hasToolA, hasToolB, hasToolC)));
00847 }
00848 
00849 /*******************************************************************/
00850 
00851 /* ippCommandParser::makeGetChangeToolAction
00852 
00853 Returned Value: A GetChangeToolActionCommand as described by the command
00854   text, or NULL.
00855 
00856 Called By: ippCommandParser::makeCommand
00857 
00858 Rules:
00859 1. There must be one argument.
00860    MUST_HAVE_ONE_ARGUMENT
00861 2. The argument must be a string.
00862    ARGUMENT_MUST_BE_STRING
00863 
00864 Reference pages: 24 27 29 (57-58) 102 106
00865 
00866 */
00867 
00868 ippCommandPtr ippCommandParser::makeGetChangeToolAction()
00869 {
00870   if (_argCount != 1) {
00871     _errorCode = MUST_HAVE_ONE_ARGUMENT;
00872   } else if (_argTypes[0] != ARGSTRING) {
00873     _errorCode = ARGUMENT_MUST_BE_STRING;
00874   }
00875   return ((_errorCode != OK) ? NULL :
00876     (new ippGetChangeToolActionCommand(_tag, _argStrings[0].c_str())));
00877 }
00878 
00879 /*******************************************************************/
00880 
00881 /* ippCommandParser::makeGetCoordSystem
00882 
00883 Returned Value: A ippCommand of commandNameType GetCoordSystem as described by
00884   the command text, or NULL.
00885 
00886 Called By: ippCommandParser::makeCommand
00887 
00888 Rules:
00889 1. There must be no arguments.
00890    MUST_HAVE_NO_ARGUMENTS
00891 
00892 Reference pages: 24 28 (59) 103
00893 
00894 */
00895 
00896 ippCommandPtr ippCommandParser::makeGetCoordSystem()
00897 {
00898   if (_argCount != 0)  {
00899     _errorCode = MUST_HAVE_NO_ARGUMENTS;
00900   }
00901   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, GetCoordSystem)));
00902 }
00903 
00904 /*******************************************************************/
00905 
00906 /* ippCommandParser::makeGetCsyTransformation
00907 
00908 Returned Value: A GetCsyTransformationCommand as described by the command
00909   text, or NULL.
00910 
00911 Called By: ippCommandParser::makeCommand
00912 
00913 Rules:
00914 1. There must be one argument.
00915    MUST_HAVE_ONE_ARGUMENT
00916 2. The argument must be one of: JogDisplayCsy, JogMoveCsy, MoveableMachineCsy,
00917    MultipleArmCsy, PartCsy, SensorCsy.
00918    BAD_ARGUMENTS
00919 
00920 Reference pages: 24 28 (60) (80) 103
00921 
00922 */
00923 
00924 ippCommandPtr ippCommandParser::makeGetCsyTransformation()
00925 {
00926   if (_argCount != 1)
00927     _errorCode = MUST_HAVE_ONE_ARGUMENT;
00928   else if ((_argTypes[0] != ARGKEYWORD) ||
00929      ((_argKeywords[0] != JogDisplayCsy) &&
00930       (_argKeywords[0] != JogMoveCsy) &&
00931       (_argKeywords[0] != MoveableMachineCsy) &&
00932       (_argKeywords[0] != MultipleArmCsy) &&
00933       (_argKeywords[0] != PartCsy) &&
00934       (_argKeywords[0] != SensorCsy)))
00935     _errorCode = BAD_ARGUMENTS;
00936   return ((_errorCode != OK) ? NULL :
00937     (new ippGetCsyTransformationCommand(_tag, (ippCoordSysType)_argKeywords[0])));
00938 }
00939 
00940 /*******************************************************************/
00941 
00942 /* ippCommandParser::makeGetDMEVersion
00943 
00944 Returned Value: A ippCommand of commandNameType GetDMEVersion as
00945 described by the command text, or NULL.
00946 
00947 Called By: ippCommandParser::makeCommand
00948 
00949 Rules:
00950 1. There must be no arguments.
00951    MUST_HAVE_NO_ARGUMENTS
00952 
00953 Reference pages: 24 26 (46) [47] 99
00954 
00955 */
00956 
00957 ippCommandPtr ippCommandParser::makeGetDMEVersion()
00958 {
00959   if (_argCount != 0)
00960     _errorCode = MUST_HAVE_NO_ARGUMENTS;
00961   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, GetDMEVersion)));
00962 }
00963 
00964 /*******************************************************************/
00965 
00966 /* ippCommandParser::makeGetErrorInfo
00967 
00968 Returned Value: A GetErrorInfoCommand as described by the command
00969   text, or NULL.
00970 
00971 Called By: ippCommandParser::makeCommand
00972 
00973 Rules:
00974 1. There must be one argument.
00975    MUST_HAVE_ONE_ARGUMENT
00976 2. The argument must be an integer.
00977    ARGUMENT_MUST_BE_INTEGER
00978 
00979 Reference pages: 19 24 26 (43) 76 99
00980 Page 76 does not mention the command but gives allowable error numbers.
00981 
00982 For GetErrorInfo, the value of the argument is stored as a double
00983 even though it must be an integer. This is so that argument reading
00984 does not require the context of knowing the command. Here it is
00985 checked that the double has an integer value.
00986 
00987 */
00988 
00989 ippCommandPtr ippCommandParser::makeGetErrorInfo()
00990 {
00991   if (_argCount != 1){
00992     _errorCode =  MUST_HAVE_ONE_ARGUMENT;      
00993   } else if ((_argTypes[0] != ARGDOUBLE) || !IsInteger(getValue(0))){
00994     _errorCode = ARGUMENT_MUST_BE_INTEGER; 
00995   }
00996   return ((_errorCode != OK) ? NULL :
00997     (new  ippGetErrorInfoCommand(_tag, Convert2ippErrorNameType(getValue(0)))));
00998 }
00999 
01000 /*******************************************************************/
01001 
01002 /* ippCommandParser::makeGetErrStatusE
01003 
01004 Returned Value: A ippCommand of commandNameType GetErrStatusE as described by
01005   the command text, or NULL.
01006 
01007 Called By: ippCommandParser::makeCommand
01008 
01009 Rules:
01010 1. There must be no arguments.
01011    MUST_HAVE_NO_ARGUMENTS
01012 
01013 Reference pages: 24 27 (50) 102
01014 
01015 */
01016 
01017 ippCommandPtr ippCommandParser::makeGetErrStatusE()
01018 {
01019   if (_argCount != 0)
01020     _errorCode = MUST_HAVE_NO_ARGUMENTS;
01021   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, GetErrStatusE)));
01022 }
01023 
01024 /*******************************************************************/
01025 
01026 /* ippCommandParser::makeGetMachineClass
01027 
01028 Returned Value: A ippCommand of commandNameType GetMachineClass as described by
01029   the command text, or NULL.
01030 
01031 Called By: ippCommandParser::makeCommand
01032 
01033 Rules:
01034 1. There must be no arguments.
01035    MUST_HAVE_NO_ARGUMENTS
01036 
01037 Reference pages: 18 24 27 (50) 102
01038 
01039 */
01040 
01041 ippCommandPtr ippCommandParser::makeGetMachineClass()
01042 {
01043   if (_argCount != 0)
01044     _errorCode = MUST_HAVE_NO_ARGUMENTS;
01045   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, GetMachineClass)));
01046 }
01047 
01048 /*******************************************************************/
01049 
01050 /* ippCommandParser::makeGetProp
01051 
01052 Returned Value: A GetPropCommand as described by the command text, or NULL.
01053 
01054 Called By: ippCommandParser::makeCommand
01055 
01056 Rules:
01057 1. There must be at least one argument, and each argument must have one of
01058    the three patterns:
01059    key1.key2() -- four components in _argCount
01060    key1.key2.key3() -- six components in _argCount
01061    key1.key2.key3.key4() -- eight components in _argCount
01062    and all arguments except the last must be followed by a comma.
01063    BAD_ARGUMENTS
01064    ARGUMENT_SECOND_PART_BAD
01065 2. key1 must be FoundTool or Tool.
01066    ARGUMENT_FIRST_PART_MUST_BE_TOOL_OR_FOUNDTOOL
01067 3. If the pattern is key1.key2():
01068    If key1 is Tool, key2 must be Alignment, CollisionVolume, Name, or Id.
01069    If key1 is FoundTool, key2 must be Name, or Id.
01070    ARGUMENT_SECOND_PART_BAD
01071 4. If key2 is GoToPar, key3 must be Speed or Accel.
01072    If key2 is PtMeasPar, key3 must be one of
01073    Speed, Accel, Approach, Retract, or Search.
01074    ARGUMENT_THIRD_PART_BAD
01075 5. If there is a key4, it must be Act, Def, Max, or Min.
01076    ARGUMENT_FOURTH_PART_BAD
01077 6. The dots must be placed where shown in rule 1.
01078    BAD_DOTS
01079 7. The empty parentheses must be placed where shown in rule 1.
01080    ARGUMENT_MUST_END_WITH_EMPTY_PARENTHESES
01081 
01082 Reference pages: 24 26 29 (45) 66 67 [68] [69] 70 [73] [74] 77 79 99 108
01083 
01084 The spec is not clear about what should be allowed as arguments.  Here
01085 we assume that only primitive types (string, bool, number) can be
01086 obtained, so the arguments must refer to something whose type is
01087 primitive. For example, GetProp(Tool.PtMeasPar.Speed()) is OK, but
01088 GetProp(Tool.PtMeasPar()) is not OK since the value of PtMeasPar is an
01089 object, not a primitive type.
01090 
01091 The spec implies, without being explicit, that key3() and key3.Act()
01092 are both allowed and mean the same thing.
01093 
01094 The spec states that GetProp may be used to query settable properties.
01095 It says explicitly that Speed.Max cannot be queried using GetProp.
01096 NIST has raised an issue against only allowing settable properties.
01097 This function allows querying Speed.Max.
01098 
01099 The spec is also not clear about whether CanChange, CanChangeSpeed, and
01100 CanChangeAccel are allowable keywords. These are included on pages 29,
01101 109, and 110 for GoToPars, PtMeasPars, and Param. None of the examples
01102 of GetProp uses either of them. We are assuming they are not allowed.
01103 
01104 We are assuming here that the properties (other than CanChange) of
01105 "param" objects defined on pages 29, 109 and 110 are intended to be
01106 accessible. These properties are not mentioned in section 6 and are
01107 not included in any examples of GetProp. In a telephone conversation
01108 with Josef Resch, however, he said Speed.Max should be used rather
01109 than MaxSpeed.
01110 
01111 The forms MaxSpeed, MinSpeed, MaxAccel, and MinAccel appear on pages
01112 9, 29, 109, and 110, but not in section 6. They are not allowed here.
01113 
01114 The spec on page 66 does not allow FoundTool.Name() or FoundTool.Id(),
01115 but this appears to be an oversight and NIST has submitted a comment
01116 suggesting FoundTool should be allowed. This function allows FoundTool.
01117 
01118 The _argCount is a count of components of arguments, not a count of
01119 arguments.
01120 
01121 The [(_argCount + 1) / 5] size for the keys arrays is used because this
01122 is the smallest number that is sure to be at least as large as the
01123 number of arguments. Each argument must have at least four components,
01124 and the arguments are separated by commas (which are added into _argCount).
01125 
01126 */
01127 
01128 
01129 ippCommandPtr ippCommandParser::makeGetProp()
01130 {
01131   // syntax analysis
01132   ippGetPropCommandPtr command;
01133   if ( _commandName == GetProp ) { 
01134     command = new ippGetPropCommand(_tag);
01135   } else if(_commandName == GetPropE ) { 
01136     command = new ippGetPropECommand(_tag);
01137   }
01138 
01139 
01140   for (int n = 0; ((n < _argCount) && (_errorCode == OK));n++)  {
01141   
01142     ippOtherKeyType key1 = ippOtherKeyType_INVALID;
01143     ippOtherKeyType key2 = EmptyKey;
01144     ippOtherKeyType key3 = EmptyKey;
01145     ippOtherKeyType key4 = EmptyKey;
01146 
01147     if (match(_argTypes,"k.k.k.kE",n))  {
01148       key1 = _argKeywords[n];
01149       key2 = _argKeywords[n+2];
01150       key3 = _argKeywords[n+4];
01151       key4 = _argKeywords[n+6];
01152       n += 8;
01153 
01154     } else if (match(_argTypes,"k.k.kE",n)) { 
01155       key1 = _argKeywords[n];
01156       key2 = _argKeywords[n+2];
01157       key3 = _argKeywords[n+4];
01158       n += 6;
01159     } else if (match(_argTypes,"k.kE",n)) { 
01160       key1 = _argKeywords[n];
01161       key2 = _argKeywords[n+2];
01162       n += 4;
01163     } else if (match(_argTypes,"kE",n)) { 
01164       key1 = _argKeywords[n];
01165       n += 2;
01166     } else {
01167       _errorCode = BAD_ARGUMENTS;
01168     }
01169     if (n < _argCount && _argTypes[n] != ARGCOMMA) {
01170       _errorCode = BAD_ARGUMENTS;
01171     }
01172     if(_errorCode == OK ) { 
01173       ippProp prop(key1,key2,key3,key4);
01174       if (PropertyIsAllowed(prop)) { 
01175         command->addProp(prop);
01176       } else {
01177        _errorCode = BAD_ARGUMENTS;
01178      }
01179     }
01180   }
01181   if (_errorCode != OK) {
01182     return 0;
01183   }
01184   return command;
01185 }
01186 
01187 
01188 /*******************************************************************/
01189 
01190 /* ippCommandParser::makeGetPropE
01191 
01192 Returned Value: A GetPropECommand as described by the command text, or NULL.
01193 
01194 This is identical to ippCommandParser::makeGetProp except that GetProp is changed
01195 to GetPropE (and GETPROP to GETPROPE).
01196 See the documentation there.
01197 
01198 */
01199 ippCommandPtr ippCommandParser::makeGetPropE()
01200 {
01201   // same as GetProp : so delegate !
01202   return makeGetProp();
01203 }
01204 
01205 
01206 
01207 /*******************************************************************/
01208 
01209 /* ippCommandParser::makeGetXtdErrStatus
01210 
01211 Returned Value: A ippCommand of commandNameType GetXtdErrStatus as described by
01212   the command text, or NULL.
01213 
01214 Called By: ippCommandParser::makeCommand
01215 
01216 Rules:
01217 1. There must be no arguments.
01218    MUST_HAVE_NO_ARGUMENTS
01219 
01220 Reference pages: 24 27 (50) 102
01221 
01222 */
01223 
01224 ippCommandPtr ippCommandParser::makeGetXtdErrStatus()
01225 {
01226   if (_argCount != 0)
01227     _errorCode = MUST_HAVE_NO_ARGUMENTS;
01228   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, GetXtdErrStatus)));
01229 }
01230 
01231 /*******************************************************************/
01232 
01233 /* ippCommandParser::makeGoTo
01234 
01235 Returned Value: A GoToCommand as described by the command text, or NULL.
01236 
01237 Called By: ippCommandParser::makeCommand
01238 
01239 Rules:
01240 1. There must be one to six arguments.
01241    BAD_ARGUMENTS
01242 2. Each argument must be X(<number>), Y(<number>), Z(<number>),
01243    Tool.A(<number>), Tool.B(<number>) or Tool.C(<number>),
01244    which may appear in any order.
01245    BAD_ARGUMENTS
01246 3. Each allowed argument must appear at most once.
01247    X_ARGUMENT_USED_TWICE
01248    Y_ARGUMENT_USED_TWICE
01249    Z_ARGUMENT_USED_TWICE
01250    TOOL_A_ARGUMENT_USED_TWICE
01251    TOOL_B_ARGUMENT_USED_TWICE
01252    TOOL_C_ARGUMENT_USED_TWICE
01253 4. Commas must separate the arguments if there are two or more.
01254    BAD_ARGUMENTS
01255 
01256 Reference pages: 24 27 [38] [43] (51 - 53) (58) (62) [71] [72] (78) (98) 102
01257 
01258 This function is similar to makeGet.
01259 
01260 */
01261 
01262 ippCommandPtr ippCommandParser::makeGoTo()
01263 {
01264 
01265   bool hasX = false;
01266   bool hasY = false;
01267   bool hasZ = false;
01268   double x = 0;
01269   double y = 0;
01270   double z = 0;
01271   bool hasToolA = false;
01272   bool hasToolB = false;
01273   bool hasToolC = false;
01274   double toolA = 0;
01275   double toolB = 0;
01276   double toolC = 0;
01277 
01278   if (_argCount < 2) {
01279     _errorCode = BAD_ARGUMENTS;
01280   }
01281   int n =0;
01282 
01283   while (n < _argCount && _errorCode == OK) {
01284     int old_n=n;
01285     CheckOptionalArgumentValue(n,hasX    ,_X   ,       X_ARGUMENT_USED_TWICE, X_NOT_FOLLOWED_BY_NUMBER_IN_PARENS, x);
01286     CheckOptionalArgumentValue(n,hasY    ,_Y   ,       Y_ARGUMENT_USED_TWICE, Y_NOT_FOLLOWED_BY_NUMBER_IN_PARENS, y);
01287     CheckOptionalArgumentValue(n,hasZ    ,_Z   ,       Z_ARGUMENT_USED_TWICE, Z_NOT_FOLLOWED_BY_NUMBER_IN_PARENS, z);
01288     CheckOptionalArgumentValue(n,hasToolA,Tool,_A,TOOL_A_ARGUMENT_USED_TWICE, TOOL_A_NOT_FOLLOWED_BY_NUMBER_IN_PARENS, toolA);
01289     CheckOptionalArgumentValue(n,hasToolB,Tool,_B,TOOL_B_ARGUMENT_USED_TWICE, TOOL_B_NOT_FOLLOWED_BY_NUMBER_IN_PARENS, toolB);
01290     CheckOptionalArgumentValue(n,hasToolC,Tool,_C,TOOL_C_ARGUMENT_USED_TWICE, TOOL_C_NOT_FOLLOWED_BY_NUMBER_IN_PARENS, toolC);    
01291     if (old_n == n) { 
01292       // the argument has not been recognized:
01293       _errorCode = BAD_ARGUMENTS;
01294     } 
01295   }
01296 
01297   return ((_errorCode != OK) ? NULL:
01298     (new ippGoToCommand(_tag, hasX, hasY, hasZ, x, y, z, hasToolA,
01299          hasToolB, hasToolC, toolA, toolB, toolC)));
01300 }
01301 
01302 /*******************************************************************/
01303 
01304 /* ippCommandParser::makeHome
01305 
01306 Returned Value: A ippCommand of commandNameType Home as described by
01307   the command text, or NULL.
01308 
01309 Called By: ippCommandParser::makeCommand
01310 
01311 Rules:
01312 1. There must be no arguments.
01313    MUST_HAVE_NO_ARGUMENTS
01314 
01315 Reference pages: 24 27 [38] (48) 102
01316 
01317 */
01318 
01319 ippCommandPtr ippCommandParser::makeHome()
01320 {
01321   if (_argCount != 0)
01322     _errorCode = MUST_HAVE_NO_ARGUMENTS;
01323   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, Home)));
01324 }
01325 
01326 /*******************************************************************/
01327 
01328 /* ippCommandParser::makeIsHomed
01329 
01330 Returned Value: A ippCommand of commandNameType IsHomed as described by
01331   the command text, or NULL.
01332 
01333 Called By: ippCommandParser::makeCommand
01334 
01335 Rules:
01336 1. There must be no arguments.
01337    MUST_HAVE_NO_ARGUMENTS
01338 
01339 Reference pages: 24 27 (48) 102 111
01340 
01341 */
01342 
01343 ippCommandPtr ippCommandParser::makeIsHomed()
01344 {
01345   if (_argCount != 0)
01346     _errorCode = MUST_HAVE_NO_ARGUMENTS;
01347   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, IsHomed)));
01348 }
01349 
01350 /*******************************************************************/
01351 
01352 /* ippCommandParser::makeIsUserEnabled
01353 
01354 Returned Value: A ippCommand of commandNameType IsUserEnabled as described by
01355   the command text, or NULL.
01356 
01357 Called By: ippCommandParser::makeCommand
01358 
01359 Rules:
01360 1. There must be no arguments.
01361    MUST_HAVE_NO_ARGUMENTS
01362 
01363 Reference pages: 24 27 (49) 102
01364 
01365 */
01366 
01367 ippCommandPtr ippCommandParser::makeIsUserEnabled()
01368 {
01369   if (_argCount != 0)
01370     _errorCode = MUST_HAVE_NO_ARGUMENTS;
01371   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, IsUserEnabled)));
01372 }
01373 
01374 /*******************************************************************/
01375 
01376 /* ippCommandParser::makeLockAxis
01377 
01378 Returned Value: A LockAxisCommand as described by the command text,
01379   or NULL.
01380 
01381 Called By: ippCommandParser::makeCommand
01382 
01383 Rules:
01384 1. There must be one to nine arguments.
01385    BAD_ARGUMENTS
01386 2. Each argument must be C(), Phi(), R(), X(), Y(), Z(),
01387    which may appear in any order.
01388    BAD_ARGUMENTS
01389 3. Each allowed argument must appear at most once.
01390    C_ARGUMENT_USED_TWICE
01391    PHI_ARGUMENT_USED_TWICE
01392    R_ARGUMENT_USED_TWICE
01393    X_ARGUMENT_USED_TWICE
01394    Y_ARGUMENT_USED_TWICE
01395    Z_ARGUMENT_USED_TWICE
01396 4. Commas must separate the arguments if there are two or more.
01397    BAD_ARGUMENTS
01398 
01399 Reference pages: 24 (97-98)
01400 
01401 The spec does not forbid having no arguments, but here there must be
01402 at least one argument.
01403 
01404 It is not necessary to check for too many arguments, because if there
01405 were too many, at least one would be duplicated, and a check for
01406 duplicates is made.
01407 
01408 */
01409 
01410 ippCommandPtr ippCommandParser::makeLockAxis()
01411 {
01412   bool hasC = false;
01413   bool hasPhi = false;
01414   bool hasR = false;
01415   bool hasX = false;
01416   bool hasY = false;
01417   bool hasZ = false;
01418 
01419   if (_argCount < 2) {
01420     _errorCode = BAD_ARGUMENTS;
01421   }
01422   int n =0; // index for components of command arguments
01423   while (n < _argCount && _errorCode == OK) {
01424     int old_n=n;
01425     CheckOptionalArgument(n,hasC    ,_C   ,  C_ARGUMENT_USED_TWICE);
01426     CheckOptionalArgument(n,hasPhi  ,Phi  ,PHI_ARGUMENT_USED_TWICE);
01427     CheckOptionalArgument(n,hasR    ,_R   ,  R_ARGUMENT_USED_TWICE);
01428     CheckOptionalArgument(n,hasX    ,_X   ,  X_ARGUMENT_USED_TWICE);
01429     CheckOptionalArgument(n,hasY    ,_Y   ,  Y_ARGUMENT_USED_TWICE);
01430     CheckOptionalArgument(n,hasZ    ,_Z   ,  Z_ARGUMENT_USED_TWICE);
01431     if (old_n == n) { 
01432       // the argument has not been recognized:
01433       _errorCode = BAD_ARGUMENTS;
01434     } 
01435   }
01436   return ((_errorCode != OK) ? NULL :
01437     (new ippLockAxisCommand(_tag, hasC, hasPhi, hasR, hasX, hasY, hasZ)));
01438 }
01439 
01440 /*******************************************************************/
01441 
01442 /* ippCommandParser::makeOnMoveReportE
01443 
01444 Returned Value: An OnMoveReportECommand as described by the command text,
01445   or NULL.
01446 
01447 Called By: ippCommandParser::makeCommand
01448 
01449 Rules:
01450 1. There must be zero to nine arguments.
01451    BAD_ARGUMENTS
01452 2. Each argument must be one of R(), X(), Y(), Z(), Tool.A(), Tool.B(),
01453    Tool.C(), Dis(<number>), or Time(<number>), which may appear in any order.
01454    DIS_MUST_BE_FOLLOWED_BY_NUMBER_IN_PARENS
01455    TIME_MUST_BE_FOLLOWED_BY_NUMBER_IN_PARENS
01456 3. Each allowed argument must appear at most once.
01457    R_ARGUMENT_USED_TWICE
01458    X_ARGUMENT_USED_TWICE
01459    Y_ARGUMENT_USED_TWICE
01460    Z_ARGUMENT_USED_TWICE
01461    TOOL_A_ARGUMENT_USED_TWICE
01462    TOOL_B_ARGUMENT_USED_TWICE
01463    TOOL_C_ARGUMENT_USED_TWICE
01464    DIS_ARGUMENT_USED_TWICE
01465    TIME_ARGUMENT_USED_TWICE
01466 4. Commas must separate the arguments if there are two or more.
01467    BAD_ARGUMENTS
01468 
01469 Reference pages: 19 24 27 [39] (49 - 50) 102
01470 This is referenced as "OnReport" on pages 56, 57, 61, 63, and 66.
01471 
01472 Much of this function is identical to the makeGet function. The differences
01473 are that in this function it is OK to have no arguments, and in this
01474 function Dis(<number>) and Time(<number>) are allowed as arguments.
01475 
01476 It is not necessary to check for too many arguments, because if there
01477 were too many, at least one would be duplicated, and a check for
01478 duplicates is made.
01479 
01480 */
01481 
01482 ippCommandPtr ippCommandParser::makeOnMoveReportE()
01483 {
01484   int n;
01485   bool hasR = false;
01486   bool hasX = false;
01487   bool hasY = false;
01488   bool hasZ = false;
01489   bool hasToolA = false;
01490   bool hasToolB = false;
01491   bool hasToolC = false;
01492   bool hasDis = false;
01493   bool hasTime = false;
01494   double theDis = 100.0;
01495   double theTime = 100.0;
01496   
01497   n = 0;
01498   while (n < _argCount && _errorCode == OK) {
01499     int old_n=n;
01500     CheckOptionalArgument(n,hasR    ,_R   ,       R_ARGUMENT_USED_TWICE);
01501     CheckOptionalArgument(n,hasX    ,_X   ,       X_ARGUMENT_USED_TWICE);
01502     CheckOptionalArgument(n,hasY    ,_Y   ,       Y_ARGUMENT_USED_TWICE);
01503     CheckOptionalArgument(n,hasZ    ,_Z   ,       Z_ARGUMENT_USED_TWICE);
01504 
01505     CheckOptionalArgument(n,hasToolA,Tool,_A,TOOL_A_ARGUMENT_USED_TWICE);
01506     CheckOptionalArgument(n,hasToolB,Tool,_B,TOOL_B_ARGUMENT_USED_TWICE);
01507     CheckOptionalArgument(n,hasToolC,Tool,_C,TOOL_C_ARGUMENT_USED_TWICE);
01508 
01509     CheckOptionalArgumentValue(n,hasTime,Time,TIME_ARGUMENT_USED_TWICE,TIME_MUST_BE_FOLLOWED_BY_NUMBER_IN_PARENS,theTime);
01510     CheckOptionalArgumentValue(n,hasDis ,Dis , DIS_ARGUMENT_USED_TWICE, DIS_MUST_BE_FOLLOWED_BY_NUMBER_IN_PARENS,theDis);
01511     if (old_n == n) { 
01512       // the argument has not been recognized:
01513       _errorCode = BAD_ARGUMENTS;
01514     }
01515   }
01516 
01517   return ((_errorCode != OK) ? NULL:
01518     (new ippOnMoveReportECommand(_tag, hasR, hasX, hasY, hasZ, hasToolA,
01519            hasToolB, hasToolC, hasDis, hasTime, theDis, theTime)));
01520 }
01521 
01522 /*******************************************************************/
01523 
01524 /* ippCommandParser::makeOnPtMeasReport
01525 
01526 Returned Value: An OnPtMeasReportCommand as described by the command text,
01527   or NULL.
01528 
01529 Called By: ippCommandParser::makeCommand
01530 
01531 Rules:
01532 1. There must be one to nine arguments.
01533    BAD_ARGUMENTS
01534 2. Each argument must be ER(), IJK(), R(), X(), Y(), Z(), Tool.A(),
01535    Tool.B() or Tool.C(), which may appear in any order.
01536    BAD_ARGUMENTS
01537 3. Each allowed argument must appear at most once.
01538    ER_ARGUMENT_USED_TWICE
01539    IJK_ARGUMENT_USED_TWICE
01540    R_ARGUMENT_USED_TWICE
01541    X_ARGUMENT_USED_TWICE
01542    Y_ARGUMENT_USED_TWICE
01543    Z_ARGUMENT_USED_TWICE
01544    TOOL_A_ARGUMENT_USED_TWICE
01545    TOOL_B_ARGUMENT_USED_TWICE
01546    TOOL_C_ARGUMENT_USED_TWICE
01547 4. Commas must separate the arguments if there are two or more.
01548    BAD_ARGUMENTS
01549 
01550 Reference pages: 24 27 (41) (49) (52) (53) 61 [71] [72] (78) 102
01551 This is referenced as "OnReport" on pages 56, 57, 61, 63, and 66.
01552 
01553 The body of the function is similar to the body of makeGet.
01554 See documentation of makeGet.
01555 
01556 The spec forbids having no arguments.
01557 
01558 It is not necessary to check for too many arguments, because if there
01559 were too many, at least one would be duplicated, and a check for
01560 duplicates is made.
01561 
01562 */
01563 
01564 /*
01565  * check if the next argument is of the specified type
01566  * if the argument has not been found yet ( hasArgument = false in entry ) 
01567  * and if the argument is found the method returns true.
01568  * 
01569  */
01570 bool ippCommandParser::CheckOptionalArgument(
01571   int& n,
01572   bool& hasArgument,
01573   ippOtherKeyType type,
01574   ippParserCmdErrorId errorIfDuplicated
01575   )
01576 {
01577   if (_errorCode != OK) return false;
01578   if (_argCount < n+2)  return false;
01579 
01580   if (_argTypes[n] != ARGKEYWORD ) { 
01581     return false;
01582   }
01583 
01584   if (_argKeywords[n] != type) { 
01585     return false; // ignore ,not for us
01586   } else {
01587     if (hasArgument ) { 
01588       _errorCode = errorIfDuplicated;      
01589     } else {
01590       hasArgument = true;
01591       if (_argTypes[n+1] != ARGPARENEMPTY) { 
01592         _errorCode = BAD_ARGUMENTS;
01593         return false;
01594       }
01595       if ( n+2 < _argCount && _argTypes[n+2] != ARGCOMMA ) { 
01596         _errorCode = BAD_ARGUMENTS;
01597         return false;
01598       }
01599     }
01600     n +=3;
01601   }
01602   if (_errorCode == OK ) {
01603     return true;
01604   } 
01605   return false;
01606 }
01607 bool ippCommandParser::CheckOptionalArgument(
01608   int& n,
01609   bool& hasArgument,
01610   ippOtherKeyType type1,
01611   ippOtherKeyType type2,
01612   ippParserCmdErrorId errorIfDuplicated
01613   )
01614 {
01615   if (_errorCode != OK)  {  return false; }
01616   if (_argCount < n+3) { return false;}
01617 
01618   if (_argTypes[n] != ARGKEYWORD ||_argTypes[n+1]!=ARGDOT ||_argTypes[n+2] != ARGKEYWORD) {
01619     return false;
01620   }
01621 
01622   if (_argKeywords[n] != type1 || _argKeywords[n+2] != type2) { 
01623     return false; // ignore ,not for us
01624   } else {
01625     if (hasArgument ) { 
01626       _errorCode = errorIfDuplicated;      
01627     } else {
01628       hasArgument = true;
01629     }
01630     if (_argTypes[n+3] != ARGPARENEMPTY ) { 
01631       _errorCode = BAD_ARGUMENTS;
01632       return false;
01633     }
01634     if ( n+4 < _argCount && _argTypes[n+4] != ARGCOMMA ) { 
01635       _errorCode = BAD_ARGUMENTS;
01636       return false;
01637     }
01638     n +=5;
01639   }
01640   if (_errorCode == OK ) {
01641     return true;
01642   } 
01643   return false;
01644 }
01645 
01646 
01647 
01648 
01649 ippCommandPtr ippCommandParser::makeOnPtMeasReport()
01650 {
01651   int n; // index for components of command arguments
01652   bool hasER = false;
01653   bool hasIJK = false;
01654   bool hasIJKAct = false;
01655   bool hasQ = false;
01656   bool hasR = false;
01657   bool hasX = false;
01658   bool hasY = false;
01659   bool hasZ = false;
01660   bool hasToolA = false;
01661   bool hasToolB = false;
01662   bool hasToolC = false;
01663 
01664   if (_argCount <2  ) { 
01665     _errorCode = BAD_ARGUMENTS;
01666   }
01667   n = 0;
01668   while (n < _argCount && _errorCode == OK) {
01669     int old_n=n;
01670     CheckOptionalArgument(n,hasER   ,ER  ,      ER_ARGUMENT_USED_TWICE);
01671     CheckOptionalArgument(n,hasIJK  ,_IJK ,     IJK_ARGUMENT_USED_TWICE);
01672     CheckOptionalArgument(n,hasIJKAct,_IJKAct,  IJKACT_ARGUMENT_USED_TWICE);
01673     CheckOptionalArgument(n,hasQ    ,Q   ,       Q_ARGUMENT_USED_TWICE);
01674     CheckOptionalArgument(n,hasR    ,_R   ,       R_ARGUMENT_USED_TWICE);
01675     CheckOptionalArgument(n,hasX    ,_X   ,       X_ARGUMENT_USED_TWICE);
01676     CheckOptionalArgument(n,hasY    ,_Y   ,       Y_ARGUMENT_USED_TWICE);
01677     CheckOptionalArgument(n,hasZ    ,_Z   ,       Z_ARGUMENT_USED_TWICE);
01678     CheckOptionalArgument(n,hasToolA,Tool,_A,TOOL_A_ARGUMENT_USED_TWICE);
01679     CheckOptionalArgument(n,hasToolB,Tool,_B,TOOL_B_ARGUMENT_USED_TWICE);
01680     CheckOptionalArgument(n,hasToolC,Tool,_C,TOOL_C_ARGUMENT_USED_TWICE);
01681 
01682     if (old_n == n) { 
01683       // the argument has not been recognized:
01684       _errorCode = BAD_ARGUMENTS;
01685     }
01686   }
01687   return ((_errorCode != OK) ? NULL :
01688     (new ippOnPtMeasReportCommand(_tag, hasER, hasIJK,hasQ, hasR, hasX, hasY,
01689              hasZ,hasToolA, hasToolB, hasToolC,hasIJKAct)));
01690 }
01691 
01692 
01693 
01694 
01695 /*
01696  *! ippCommandParser::makeOnScanReport
01697  * Returned Value: An OnScanReportCommand as described by the command text or NULL.
01698  * Called By: ippCommandParser::makeCommand
01699 
01700 Rules:
01701 1. There must be one to eight arguments.
01702    BAD_ARGUMENTS
01703 
01704 2. Each argument must be Q(), R(), X(), Y(), or Z(), Tool.A(), Tool.B(),
01705    or Tool.C(), which may appear in any order.
01706    ipp 1.5: can also  IJK(),IJKAct(),ER() are also possible
01707    
01708    BAD_ARGUMENTS
01709 3. Each allowed argument must appear at most once.
01710    ER_ARGUMENT_USED_TWICE
01711    IJK_ARGUMENT_USED_TWICE
01712    Q_ARGUMENT_USED_TWICE
01713    R_ARGUMENT_USED_TWICE
01714    X_ARGUMENT_USED_TWICE
01715    Y_ARGUMENT_USED_TWICE
01716    Z_ARGUMENT_USED_TWICE
01717    TOOL_A_ARGUMENT_USED_TWICE
01718    TOOL_B_ARGUMENT_USED_TWICE
01719    TOOL_C_ARGUMENT_USED_TWICE
01720 4. Commas must separate the arguments if there are two or more.
01721    BAD_ARGUMENTS
01722 
01723 Reference pages: 24 27 (41) (81) 82 83 84 86 87 88 90 91 [93] 103
01724 
01725 The body of the function is similar to the body of makeOnPtMeasReport,
01726 except that Q is added and the names of the error codes are
01727 different.
01728 
01729 It is not necessary to check for too many arguments, because if there
01730 were too many, at least one would be duplicated, and a check for
01731 duplicates is made.
01732 
01733 Although the spec is not specific, this does not allow no arguments.
01734 
01735 */
01736 
01737 ippCommandPtr ippCommandParser::makeOnScanReport()
01738 {
01739   int n; // index for components of command arguments
01740   bool hasER = false;
01741   bool hasIJK = false;
01742   bool hasIJKAct = false;
01743   bool hasQ = false;
01744   bool hasR = false;
01745   bool hasX = false;
01746   bool hasY = false;
01747   bool hasZ = false;
01748   bool hasToolA = false;
01749   bool hasToolB = false;
01750   bool hasToolC = false;
01751 
01752   /*
01753     These record the order of the reported items
01754   */
01755 
01756   if (_argCount <2  ) { 
01757     _errorCode = BAD_ARGUMENTS;
01758   }
01759   n = 0;
01760 
01761   ippOnScanReportCommandPtr cmd  = new ippOnScanReportCommand(_tag);
01762 
01763   while (n < _argCount && _errorCode == OK) {
01764     int old_n=n;
01765 
01766     if (CheckOptionalArgument(n,hasER   ,ER  ,      ER_ARGUMENT_USED_TWICE)) {
01767       cmd->append(ippOnScanReportCommand::ER);
01768     }
01769     
01770     if(CheckOptionalArgument(n,hasIJK  ,_IJK ,     IJK_ARGUMENT_USED_TWICE)) {
01771       cmd->append(ippOnScanReportCommand::IJK);
01772     }
01773     
01774     if (CheckOptionalArgument(n,hasQ    ,Q   ,       Q_ARGUMENT_USED_TWICE)) {
01775       cmd->append(ippOnScanReportCommand::Q);
01776     }
01777     
01778     if (CheckOptionalArgument(n,hasR    ,_R   ,       R_ARGUMENT_USED_TWICE)) {
01779       cmd->append(ippOnScanReportCommand::R);
01780     }
01781     
01782     if (CheckOptionalArgument(n,hasX    ,_X   ,       X_ARGUMENT_USED_TWICE)) {
01783       cmd->append(ippOnScanReportCommand::X);
01784     }
01785     
01786     if (CheckOptionalArgument(n,hasY    ,_Y   ,       Y_ARGUMENT_USED_TWICE)) {
01787       cmd->append(ippOnScanReportCommand::Y);
01788     }
01789     
01790     if (CheckOptionalArgument(n,hasZ    ,_Z   ,       Z_ARGUMENT_USED_TWICE)) {
01791       cmd->append(ippOnScanReportCommand::Z);
01792     }
01793     
01794     if (CheckOptionalArgument(n,hasToolA,Tool,_A,TOOL_A_ARGUMENT_USED_TWICE)) {
01795       cmd->append(ippOnScanReportCommand::ToolA);
01796     }
01797     
01798     if (CheckOptionalArgument(n,hasToolB,Tool,_B,TOOL_B_ARGUMENT_USED_TWICE)) {
01799       cmd->append(ippOnScanReportCommand::ToolB);
01800     }
01801     
01802     if (CheckOptionalArgument(n,hasToolC,Tool,_C,TOOL_C_ARGUMENT_USED_TWICE)) {
01803       cmd->append(ippOnScanReportCommand::ToolC);
01804     }
01805     
01806     if(CheckOptionalArgument(n,hasIJKAct,_IJKAct,  IJKACT_ARGUMENT_USED_TWICE)) {
01807       cmd->append(ippOnScanReportCommand::IJKAct);
01808     }
01809 
01810     if (old_n == n) { 
01811       // the argument has not been recognized:
01812       _errorCode = BAD_ARGUMENTS;
01813     } 
01814   }
01815   return (_errorCode != OK) ? NULL :cmd;
01816 }
01817 
01818 
01819 
01820 bool ippCommandParser::CheckOptionalArgumentValue(
01821   int& n,
01822   bool& hasArgument,
01823   ippOtherKeyType type,
01824   ippParserCmdErrorId errorIfDuplicated,
01825   ippParserCmdErrorId errorIfNotFollowedByNumberInParens,
01826   double& value
01827   )
01828 {
01829   if (_errorCode != OK) return false;
01830   if (_argCount < n+2)  return false;
01831 
01832   if (_argTypes[n] != ARGKEYWORD ) { 
01833     return false;
01834   }
01835 
01836   if (_argKeywords[n] != type) { 
01837     return false; // ignore ,not for us
01838   } else {
01839     if (hasArgument ) { 
01840       _errorCode = errorIfDuplicated;      
01841     } else {
01842       hasArgument = true;
01843       if (_argTypes[n+1] != ARGPARENDOUBLE) { 
01844         _errorCode = errorIfNotFollowedByNumberInParens;
01845         return false;
01846       }
01847       if ( n+2 < _argCount && _argTypes[n+2] != ARGCOMMA ) { 
01848         _errorCode = BAD_ARGUMENTS;
01849         return false;
01850       }
01851       value = getValue(n+1);
01852     }
01853     n +=3;
01854   }
01855   if (_errorCode == OK ) {
01856     return true;
01857   } 
01858   return false;
01859 }
01860 
01861 bool ippCommandParser::CheckOptionalArgumentValue(
01862   int& n,
01863   bool& hasArgument,
01864   ippOtherKeyType type1,
01865   ippOtherKeyType type2,
01866   ippParserCmdErrorId errorIfDuplicated,
01867   ippParserCmdErrorId errorIfNotFollowedByNumberInParens,
01868   double& value
01869   )
01870 {
01871   if (_errorCode != OK) return false;
01872   if (_argCount < n+4)  return false;
01873 
01874   if (_argTypes[n] != ARGKEYWORD ) { 
01875     return false;
01876   }
01877   if (_argTypes[n+1] != ARGDOT ) { 
01878     return false;
01879   }
01880   if (_argTypes[n+2] != ARGKEYWORD ) { 
01881     return false;
01882   }
01883 
01884   if (_argKeywords[n] != type1 ||_argKeywords[n+2] != type2) { 
01885     return false; // ignore ,not for us
01886   } else {
01887     if (hasArgument ) { 
01888       _errorCode = errorIfDuplicated;      
01889     } else {
01890       hasArgument = true;
01891       if (_argTypes[n+3] != ARGPARENDOUBLE) { 
01892         _errorCode = errorIfNotFollowedByNumberInParens;
01893         return false;
01894       }
01895       if ( n+4 < _argCount && _argTypes[n+4] != ARGCOMMA ) { 
01896         _errorCode = BAD_ARGUMENTS;
01897         return false;
01898       }
01899       value = getValue(n+3);
01900     }
01901     n +=5;
01902   }
01903   if (_errorCode == OK ) {
01904     return true;
01905   } 
01906   return false;
01907 }
01908 bool ippCommandParser::CheckOptionalArgumentValue(
01909   int& n,
01910   bool& hasArgument,
01911   ippOtherKeyType type,
01912   ippParserCmdErrorId errorIfDuplicated,
01913   ippParserCmdErrorId errorIfNotFollowedByBooleanInParens,
01914   bool& value
01915   )
01916 {
01917   if (_errorCode != OK) return false;
01918   if (_argCount < n+2)  return false;
01919 
01920   if (_argTypes[n] != ARGKEYWORD ) { 
01921     return false;
01922   }
01923   if (_argKeywords[n] != type ) { 
01924     return false; // ignore ,not for us
01925   } else {
01926     if (hasArgument ) { 
01927       _errorCode = errorIfDuplicated;      
01928     } else {
01929       hasArgument = true;
01930       if (_argTypes[n+1] != ARGPARENDOUBLE) { 
01931         _errorCode = errorIfNotFollowedByBooleanInParens;
01932         return false;
01933       }
01934       if ( n+2 < _argCount && _argTypes[n+2] != ARGCOMMA ) { 
01935         _errorCode = BAD_ARGUMENTS;
01936         return false;
01937       }
01938       if (getValue(n+1) != 0 && getValue(n+1) !=1 ){ 
01939         _errorCode =errorIfNotFollowedByBooleanInParens;
01940         return false;
01941       }
01942       value = (getValue(n+1) == 1.0)?true:false ;
01943     }
01944     n +=3;
01945   }
01946   if (_errorCode == OK ) {
01947     return true;
01948   } 
01949   return false;
01950 }
01951 
01952 bool ippCommandParser::CheckOptionalArgumentValue(
01953   int& n,
01954   bool& hasArgument,
01955   ippOtherKeyType type,
01956   ippParserCmdErrorId errorIfDuplicated,
01957   ippParserCmdErrorId errorIfNotFollowedByNumberInParens,
01958   double& valueI,
01959   double& valueJ,
01960   double& valueK
01961   )
01962 {
01963   if (_errorCode != OK) return false;
01964   if (_argCount < n+3)  {
01965     return false;
01966   }
01967 
01968   if (_argTypes[n] != ARGKEYWORD ) { 
01969     return false;
01970   }
01971 
01972   if (_argKeywords[n] != type) { 
01973     return false; // ignore ,not for us
01974   } else {
01975     if (hasArgument ) { 
01976       _errorCode = errorIfDuplicated;      
01977     } else {
01978       hasArgument = true;
01979       if (_argTypes[n+1] != ARGIJK || _argTypes[n+2] != ARGIJK|| _argTypes[n+3] != ARGIJK) { 
01980         _errorCode = errorIfNotFollowedByNumberInParens;
01981         return false;
01982       }
01983       if ( n+4 < _argCount && _argTypes[n+4] != ARGCOMMA ) { 
01984         _errorCode = BAD_ARGUMENTS;
01985         return false;
01986       }
01987       valueI = getValue(n+1);
01988       valueJ = getValue(n+2);
01989       valueK = getValue(n+3);
01990     }
01991     n +=5;
01992   }
01993   if (_errorCode == OK ) {
01994     return true;
01995   } 
01996   return false;
01997 }
01998 
01999 /*******************************************************************/
02000 
02001 /* ippCommandParser::makePtMeas
02002 
02003 Returned Value: A PtMeasCommand as described by the command text, or NULL.
02004 
02005 Called By: ippCommandParser::makeCommand
02006 
02007 Rules:
02008 1. There must be one, two, three, or four arguments.
02009    BAD_ARGUMENTS
02010 2. Each argument must be one of X(<number>), Y(<number>), Z(<number>),
02011    or IJK(<number>,<number>,<number>), which may appear in any order.
02012    X_NOT_FOLLOWED_BY_NUMBER_IN_PARENS
02013    Y_NOT_FOLLOWED_BY_NUMBER_IN_PARENS
02014    Z_NOT_FOLLOWED_BY_NUMBER_IN_PARENS
02015    IJK_NOT_FOLLOWED_BY_ARGIJK
02016 3. At least one of X(), Y(), or Z() must appear.
02017    X_Y_Z_ALL_MISSING
02018 4. Each allowed argument must appear at most once.
02019    X_ARGUMENT_USED_TWICE
02020    Y_ARGUMENT_USED_TWICE
02021    Z_ARGUMENT_USED_TWICE
02022    IJK_ARGUMENT_USED_TWICE
02023 5. Commas must separate the arguments if there are two or more.
02024    BAD_ARGUMENTS
02025 
02026 Reference pages: 9 24 27 (41) (49) (52 - 53) (62) [71] [72] (78) 83 84 86
02027                  87 89 90 91 102
02028 
02029 */
02030 
02031 ippCommandPtr ippCommandParser::makePtMeas()
02032 {
02033   int n;
02034   bool hasX = false;
02035   bool hasY = false;
02036   bool hasZ = false;
02037   bool hasIJK = false;
02038   double x = 0.0;
02039   double y = 0.0;
02040   double z = 0.0;
02041   double i = 0.0;
02042   double j = 0.0;
02043   double k = 0.0;
02044  
02045   n = 0;
02046   while (n < _argCount && _errorCode == OK) {
02047     int old_n=n;
02048     CheckOptionalArgumentValue(n,hasX,_X,X_ARGUMENT_USED_TWICE,X_NOT_FOLLOWED_BY_NUMBER_IN_PARENS,x);
02049     CheckOptionalArgumentValue(n,hasY,_Y,Y_ARGUMENT_USED_TWICE,Y_NOT_FOLLOWED_BY_NUMBER_IN_PARENS,y);
02050     CheckOptionalArgumentValue(n,hasZ,_Z,Z_ARGUMENT_USED_TWICE,Z_NOT_FOLLOWED_BY_NUMBER_IN_PARENS,z);
02051     CheckOptionalArgumentValue(n,hasIJK,_IJK,IJK_ARGUMENT_USED_TWICE,IJK_NOT_FOLLOWED_BY_ARGIJK,i,j,k);
02052     if (old_n == n) {
02053       // the argument has not been recognized:
02054       _errorCode = BAD_ARGUMENTS;
02055     }
02056   }
02057   if ((_errorCode == OK)&&(hasX == false) && (hasY == false) && (hasZ == false)) {
02058     _errorCode = X_Y_Z_ALL_MISSING;
02059   }
02060   return ((_errorCode != OK) ? NULL:
02061     (new ippPtMeasCommand(_tag, hasX, hasY, hasZ, hasIJK, x, y, z,i,j,k)));
02062 }
02063 
02064 /*******************************************************************/
02065 
02066 /* ippCommandParser::makeReQualify
02067 
02068 Returned Value: A ippCommand of commandNameType ReQualify as described by
02069   the command text, or NULL.
02070 
02071 Called By: ippCommandParser::makeCommand
02072 
02073 Rules:
02074 1. There must be no arguments.
02075    MUST_HAVE_NO_ARGUMENTS
02076 
02077 Reference pages: 24 29 (64) 106 107
02078 [This is called Qualify on pages 29 106 107]
02079 
02080 */
02081 
02082 ippCommandPtr ippCommandParser::makeReQualify()
02083 {
02084   if (_argCount != 0)
02085     _errorCode = MUST_HAVE_NO_ARGUMENTS;
02086   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, ReQualify)));
02087 }
02088 
02089 /*******************************************************************/
02090 
02091 /* ippCommandParser::makeScanInCylEndIsPlane
02092 
02093 Returned Value: A ScanInCylEndIsPlaneCommand as described by the command
02094   text, or NULL.
02095 
02096 Called By: ippCommandParser::makeCommand
02097 
02098 Rules:
02099 1. There must be 26 arguments.
02100    BAD_ARGUMENTS
02101 2. All of the arguments must be numbers.
02102    BAD_ARGUMENTS
02103 3. The number of throughs must be a positive integer.
02104    NUMBER_THROUGH_MUST_BE_POSITIVE
02105    NUMBER_THROUGH_MUST_BE_INTEGER
02106 4. StepW must be positive.
02107    STEPW_MUST_BE_POSITIVE
02108 5. Commas must separate the arguments.
02109    BAD_ARGUMENTS
02110 
02111 Reference pages: 24 27 (90 - 91) 103
02112 
02113 */
02114 
02115 ippCommandPtr ippCommandParser::makeScanInCylEndIsPlane()
02116 {
02117   int n;
02118   
02119   if (_argCount != 51) {
02120     _errorCode = BAD_ARGUMENTS;
02121     return 0;
02122   } 
02123   //                                      1                   2
02124   //                    1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 
02125   if (!match(_argTypes,"#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#")) {
02126     _errorCode = BAD_ARGUMENTS;
02127     return 0;
02128   }
02129 
02130   if (getValue(30) <= 0) {
02131     _errorCode = STEPW_MUST_BE_POSITIVE;
02132     return 0;
02133   }
02134   if (getValue(44) <= 0) {
02135     _errorCode = NUMBER_THROUGH_MUST_BE_POSITIVE;
02136     return 0;
02137   }
02138  
02139   if (!IsInteger(getValue(44))) {
02140     _errorCode = NUMBER_THROUGH_MUST_BE_INTEGER;
02141     return 0;
02142   }
02143 
02144   for (n = 0; ((n < 25) && (_errorCode == OK)); n++) {
02145     if ((_argTypes[2*n] != ARGDOUBLE) || (_argTypes[(2*n)+1] != ARGCOMMA)) {
02146        _errorCode = BAD_ARGUMENTS;
02147        return 0;
02148     } 
02149   }
02150   return ((_errorCode != OK) ? NULL:
02151     (new ippScanInCylEndIsPlaneCommand
02152      (_tag,
02153       getValue(0),  getValue(2),  getValue(4),  getValue(6),
02154       getValue(8),  getValue(10), getValue(12), getValue(14),
02155       getValue(16), getValue(18), getValue(20), getValue(22),
02156       getValue(24), getValue(26), getValue(28), getValue(30),
02157       getValue(32), getValue(34), getValue(36), getValue(38),
02158       getValue(40), getValue(42), AsInteger(getValue(44)),
02159       getValue(46), getValue(48), getValue(50))));
02160 }
02161 
02162 /*******************************************************************/
02163 
02164 /* ippCommandParser::makeScanInCylEndIsSphere
02165 
02166 Returned Value: A ScanInCylEndIsSphereCommand as described by the command
02167   text, or NULL.
02168 
02169 Called By: ippCommandParser::makeCommand
02170 
02171 Rules:
02172 1. There must be 23 arguments.
02173    BAD_ARGUMENTS
02174 2. All of the arguments must be numbers.
02175    BAD_ARGUMENTS
02176 3. The diameter of the sphere must be positive.
02177    DIAMETER_MUST_BE_POSITIVE
02178 4. StepW must be positive.
02179    STEPW_MUST_BE_POSITIVE
02180 5. Commas must separate the arguments.
02181    BAD_ARGUMENTS
02182 
02183 Reference pages: 24 27 (89 - 90) 103
02184 
02185 */
02186 
02187 ippCommandPtr ippCommandParser::makeScanInCylEndIsSphere()
02188 {  
02189   if (_argCount != 47) {
02190     _errorCode = BAD_ARGUMENTS;
02191   }
02192   //                                      1                   2
02193   //                    1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
02194   if (!match(_argTypes,"#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#")) {
02195     _errorCode = BAD_ARGUMENTS;
02196     return 0;
02197   }
02198 
02199   if (getValue(30) <= 0) { 
02200     _errorCode = STEPW_MUST_BE_POSITIVE;
02201     return 0;
02202   } 
02203   if (getValue(38) <= 0) {
02204     _errorCode = DIAMETER_MUST_BE_POSITIVE;
02205     return 0;
02206   }
02207   if (getValue(40) <= 0)
02208     _errorCode = NUMBER_THROUGH_MUST_BE_POSITIVE;
02209   else if ( !IsInteger(getValue(40)))
02210     _errorCode = NUMBER_THROUGH_MUST_BE_INTEGER;
02211 
02212   return ((_errorCode != OK) ? NULL:
02213     (new ippScanInCylEndIsSphereCommand
02214      (_tag,
02215       getValue(0),  getValue(2),  getValue(4), 
02216       getValue(6),  getValue(8),  getValue(10), 
02217       getValue(12), getValue(14),  getValue(16), 
02218       getValue(18), getValue(20), getValue(22),
02219       getValue(24), getValue(26), getValue(28),
02220       getValue(30), // StepW
02221       getValue(32), getValue(34), getValue(36),
02222       getValue(38), // Dia
02223       int(getValue(40)), // n
02224       getValue(42), getValue(44), getValue(46))));
02225 }
02226 
02227 /*******************************************************************/
02228 
02229 /* ippCommandParser::makeScanInPlaneEndIsCyl
02230 
02231 Returned Value: A ScanInPlaneEndIsCylCommand as described by the command
02232   text, or NULL.
02233 
02234 Called By: ippCommandParser::makeCommand
02235 
02236 Rules:
02237 1. There must be 21 arguments.
02238    BAD_ARGUMENTS
02239 2. All of the arguments must be numbers.
02240    BAD_ARGUMENTS
02241 3. The number of throughs must be a positive integer.
02242    NUMBER_THROUGH_MUST_BE_POSITIVE
02243    NUMBER_THROUGH_MUST_BE_INTEGER
02244 4. StepW must be positive.
02245    STEPW_MUST_BE_POSITIVE
02246 5. The diameter of the cylinder must be positive.
02247    DIAMETER_MUST_BE_POSITIVE
02248 6. Commas must separate the arguments.
02249    BAD_ARGUMENTS
02250 
02251 Reference pages: 24 27 (88 - 89) 103
02252 
02253 */
02254 
02255 ippCommandPtr ippCommandParser::makeScanInPlaneEndIsCyl()
02256 {
02257   
02258   if (_argCount != 47) {
02259     _errorCode = BAD_ARGUMENTS;
02260     return 0;
02261   }
02262   //                                      1                   2
02263   //                    1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
02264   if (!match(_argTypes,"#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#")) {
02265     _errorCode = BAD_ARGUMENTS;
02266     return 0;
02267   }
02268   
02269   if (getValue(24) <= 0)
02270     _errorCode = STEPW_MUST_BE_POSITIVE;
02271   else if (getValue(38) <= 0)
02272     _errorCode = DIAMETER_MUST_BE_POSITIVE;
02273   else if (getValue(40) <= 0)
02274     _errorCode = NUMBER_THROUGH_MUST_BE_POSITIVE;
02275   else if ( !IsInteger(getValue(40)))
02276     _errorCode = NUMBER_THROUGH_MUST_BE_INTEGER;
02277 
02278 
02279   return ((_errorCode != OK) ? NULL:
02280     (new ippScanInPlaneEndIsCylCommand
02281      (_tag,
02282       getValue(0),  getValue(2),  getValue(4), 
02283       getValue(6),  getValue(8),  getValue(10),
02284       getValue(12), getValue(14), getValue(16), 
02285       getValue(18), getValue(20), getValue(22),
02286       getValue(24), // StepW
02287       getValue(26), getValue(28), getValue(30),
02288       getValue(32), getValue(34), getValue(36),
02289       getValue(38), // dia
02290       int(getValue(40)), // n
02291       getValue(42), getValue(44), getValue(46)
02292       )));
02293 }
02294 
02295 /*******************************************************************/
02296 
02297 /* ippCommandParser::makeScanInPlaneEndIsPlane
02298 
02299 Returned Value: A ScanInPlaneEndIsPlaneCommand as described by the command
02300   text, or NULL.
02301 
02302 Called By: ippCommandParser::makeCommand
02303 
02304 Rules:
02305 1. There must be 20 arguments.
02306    BAD_ARGUMENTS
02307 2. All of the arguments must be numbers.
02308    BAD_ARGUMENTS
02309 3. The number of throughs must be a positive integer.
02310    NUMBER_THROUGH_MUST_BE_POSITIVE
02311    NUMBER_THROUGH_MUST_BE_INTEGER
02312 4. StepW must be positive.
02313    STEPW_MUST_BE_POSITIVE
02314 5. Commas must separate the arguments.
02315    BAD_ARGUMENTS
02316 
02317 Reference pages: 24 27 (86 - 87) 103
02318 
02319 */ 
02320 
02321 ippCommandPtr ippCommandParser::makeScanInPlaneEndIsPlane()
02322 {
02323   if (_argCount != 45) {
02324     _errorCode = BAD_ARGUMENTS;
02325     return 0;
02326   }
02327   //                                      1                   2
02328   //                    1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
02329   if (!match(_argTypes,"#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#")) {
02330     _errorCode = BAD_ARGUMENTS;
02331     return 0;
02332   }
02333   
02334   if (getValue(24) <= 0)
02335     _errorCode = STEPW_MUST_BE_POSITIVE;
02336   else if (getValue(38) <= 0)
02337     _errorCode = NUMBER_THROUGH_MUST_BE_POSITIVE;
02338   else if (!IsInteger(getValue(38)) != 0)
02339     _errorCode = NUMBER_THROUGH_MUST_BE_INTEGER;
02340 
02341   return ((_errorCode != OK) ? NULL:
02342     (new ippScanInPlaneEndIsPlaneCommand
02343      (_tag,
02344       getValue(0),  getValue(2),  getValue(4),
02345       getValue(6),  getValue(8),  getValue(10), 
02346       getValue(12), getValue(14), getValue(16),
02347       getValue(18), getValue(20), getValue(22),
02348       getValue(24), // StepW
02349       getValue(26), getValue(28), getValue(30),
02350       getValue(32), getValue(34), getValue(36),
02351       int(getValue(38)), //n
02352       getValue(40), getValue(42), getValue(44)
02353       )));
02354 }
02355 
02356 /*******************************************************************/
02357 
02358 /* ippCommandParser::makeScanInPlaneEndIsSphere
02359 
02360 Returned Value: A ScanInPlaneEndIsSphereCommand as described by the command
02361   text, or NULL.
02362 
02363 Called By: ippCommandParser::makeCommand
02364 
02365 Rules:
02366 1. There must be 17 arguments.
02367    BAD_ARGUMENTS
02368 2. All of the arguments must be numbers.
02369    BAD_ARGUMENTS
02370 3. StepW must be positive.
02371    STEPW_MUST_BE_POSITIVE
02372 4. The diameter of the sphere must be positive.
02373    DIAMETER_MUST_BE_POSITIVE
02374 5. Commas must separate the arguments.
02375    BAD_ARGUMENTS
02376 
02377 Reference pages: 24 27 (85 - 86) [94] 103
02378 
02379 */
02380 
02381 ippCommandPtr ippCommandParser::makeScanInPlaneEndIsSphere()
02382 {
02383   
02384   if (_argCount != 41) {
02385     _errorCode = BAD_ARGUMENTS;
02386   }
02387   //                                      1                   2                   3
02388   //                    1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0  
02389   if (!match(_argTypes,"#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#")) {
02390     _errorCode = BAD_ARGUMENTS;
02391     return 0;
02392   }
02393 
02394    if (getValue(24) <= 0)
02395     _errorCode = STEPW_MUST_BE_POSITIVE;
02396   else if (getValue(32) <= 0)
02397     _errorCode = DIAMETER_MUST_BE_POSITIVE;
02398   else if (!IsInteger(getValue(34)) != 0)
02399     _errorCode = NUMBER_THROUGH_MUST_BE_INTEGER;
02400 
02401   return ((_errorCode != OK) ? NULL:
02402     (new ippScanInPlaneEndIsSphereCommand
02403      (_tag,
02404       getValue(0),  getValue(2),  getValue(4), 
02405       getValue(6),  getValue(8),  getValue(10),
02406       getValue(12), getValue(14), getValue(16),
02407       getValue(18), getValue(20), getValue(22),
02408       getValue(24), // stepW
02409       getValue(26), getValue(28), getValue(30),
02410       getValue(32), // diameter
02411       int(getValue(34)), // n
02412       getValue(36),getValue(38),getValue(40)
02413      )));
02414 }
02415 
02416 /*******************************************************************/
02417 
02418 /* ippCommandParser::makeScanOnCircle
02419 
02420 Returned Value: A ScanOnCircleCommand as described by the command
02421   text, or NULL.
02422 
02423 Called By: ippCommandParser::makeCommand
02424 
02425 Rules:
02426 1. There must be 12 arguments.
02427    BAD_ARGUMENTS
02428 2. All of the arguments must be numbers.
02429    BAD_ARGUMENTS
02430 3. Commas must separate the arguments.
02431    BAD_ARGUMENTS
02432 
02433 Reference pages: 24 27 (82 - 83) [93] 103
02434 
02435 It would be good to add a rule requiring StepW to have the same sign as
02436 delta.
02437 
02438 */
02439 
02440 ippCommandPtr ippCommandParser::makeScanOnCircle()
02441 {
02442   
02443   if (_argCount != 23) {
02444     _errorCode = BAD_ARGUMENTS;
02445   }
02446   //                                      1                   2
02447   //                    1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 
02448   if (!match(_argTypes,"#,#,#,#,#,#,#,#,#,#,#,#")) {
02449     _errorCode = BAD_ARGUMENTS;
02450     return 0;
02451   }
02452 
02453   return ((_errorCode != OK) ? NULL:
02454     (new ippScanOnCircleCommand
02455      (_tag,
02456       getValue(0),  getValue(2),  getValue(4),  getValue(6),
02457       getValue(8),  getValue(10), getValue(12), getValue(14),
02458       getValue(16), getValue(18), getValue(20), getValue(22))));
02459 }
02460 
02461 /*******************************************************************/
02462 
02463 /* ippCommandParser::makeScanOnCircleHint
02464 
02465 Returned Value: A ScanOnCircleHintCommand as described by the command
02466   text, or NULL.
02467 
02468 Called By: ippCommandParser::makeCommand
02469 
02470 Rules:
02471 1. There must be two arguments.
02472    BAD_ARGUMENTS
02473 2. Both arguments must be non-negative numbers.
02474    BAD_ARGUMENTS
02475 3. A comma must separate the arguments.
02476    BAD_ARGUMENTS
02477 
02478 Reference pages: 24 27 (82) [93] 103
02479 
02480 */
02481 
02482 ippCommandPtr ippCommandParser::makeScanOnCircleHint()
02483 {
02484 
02485   if ((_argCount != 3) || !match(_argTypes,"#,#")) {
02486     _errorCode = BAD_ARGUMENTS;
02487     return 0;
02488   }
02489 
02490   if (getValue(0) < 0 || getValue(2) < 0) {
02491     _errorCode = BAD_ARGUMENTS;
02492     return 0;
02493   }
02494 
02495   return ((_errorCode != OK) ? NULL:
02496     (new ippScanOnCircleHintCommand(_tag, getValue(0), getValue(2))));
02497 }
02498 
02499 /*******************************************************************/
02500 
02501 /* ippCommandParser::makeScanOnLine
02502 
02503 Returned Value: A ScanOnLineCommand as described by the command text, or NULL.
02504 
02505 Called By: ippCommandParser::makeCommand
02506 
02507 Rules:
02508 1. There must be 10 arguments.
02509    BAD_ARGUMENTS
02510 2. All of the arguments must be numbers.
02511    BAD_ARGUMENTS
02512 3. StepW must be positive.
02513    STEPW_MUST_BE_POSITIVE
02514 4. Commas must separate the arguments.
02515    BAD_ARGUMENTS
02516 
02517 Reference pages: 24 27 (83 - 84) 103
02518 
02519 */
02520 
02521 ippCommandPtr ippCommandParser::makeScanOnLine()
02522 {
02523 
02524   if (_argCount != 19) {
02525     _errorCode = BAD_ARGUMENTS;
02526     return 0;
02527   }
02528   
02529   //                                      1                   2
02530   //                    1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 
02531   if (!match(_argTypes,"#,#,#,#,#,#,#,#,#,#")) {
02532     _errorCode = BAD_ARGUMENTS;
02533     return 0;
02534   }
02535 
02536   if (getValue(18) <= 0) {
02537     _errorCode = STEPW_MUST_BE_POSITIVE;
02538   }
02539 
02540   return ((_errorCode != OK) ? NULL:
02541     (new ippScanOnLineCommand
02542      (_tag,
02543       getValue(0),  getValue(2),  getValue(4),  getValue(6),
02544       getValue(8),  getValue(10), getValue(12), getValue(14),
02545       getValue(16), getValue(18))));
02546 }
02547 
02548 /*******************************************************************/
02549 
02550 /* ippCommandParser::makeScanOnLineHint
02551 
02552 Returned Value: A ScanOnLineHintCommand as described by the command
02553   text, or NULL.
02554 
02555 Called By: ippCommandParser::makeCommand
02556 
02557 Rules:
02558 1. There must be two arguments separated by a comma, and both arguments
02559    must be non-negative numbers.
02560    BAD_ARGUMENTS
02561 
02562 Reference pages: 24 27 (83) 103
02563 
02564 */
02565 
02566 ippCommandPtr ippCommandParser::makeScanOnLineHint()
02567 {
02568   if ((_argCount != 3) || !match(_argTypes,"#,#")) {
02569     _errorCode = BAD_ARGUMENTS;
02570     return 0;
02571   }
02572 
02573   if (getValue(0) < 0 || getValue(2) < 0) {
02574     _errorCode = BAD_ARGUMENTS;
02575     return 0;
02576   }
02577   return ((_errorCode != OK) ? NULL:
02578     (new ippScanOnLineHintCommand(_tag, getValue(0), getValue(2))));
02579 }
02580 
02581 /*******************************************************************/
02582 
02583 /* ippCommandParser::makeScanUnknownHint
02584 
02585 Returned Value: A ScanUnknownHintCommand as described by the command
02586   text, or NULL.
02587 
02588 Called By: ippCommandParser::makeCommand
02589 
02590 Rules:
02591 1. There must be one argument.
02592    MUST_HAVE_ONE_ARGUMENT
02593 2. The argument must be a number.
02594    ARGUMENT_MUST_BE_A_NUMBER
02595 3. The number must be positive.
02596    ARGUMENT_MUST_BE_POSITIVE
02597 
02598 Reference pages: 24 27 (85) [93] 103
02599 
02600 */
02601 
02602 ippCommandPtr ippCommandParser::makeScanUnknownHint()
02603 {
02604   if (_argCount != 1)
02605     _errorCode = MUST_HAVE_ONE_ARGUMENT;
02606   else if (_argTypes[0] != ARGDOUBLE)
02607     _errorCode = ARGUMENT_MUST_BE_A_NUMBER;
02608   else if (getValue(0) <= 0)
02609     _errorCode = ARGUMENT_MUST_BE_POSITIVE;
02610   return ((_errorCode != OK) ? NULL:
02611     (new ippScanUnknownHintCommand(_tag, getValue(0))));
02612 }
02613 
02614 /*******************************************************************/
02615 
02616 /* ippCommandParser::makeSetCoordSystem
02617 
02618 Returned Value: A SetCoordSystemCommand as described by the command
02619   text, or NULL.
02620 
02621 Called By: ippCommandParser::makeCommand
02622 
02623 Rules:
02624 1. There must be one argument.
02625    MUST_HAVE_ONE_ARGUMENT
02626 2. The argument must be one of:
02627    MachineCsy, MultipleArmCsy, PartCsy, or MoveableMachineCsy.
02628    BAD_ARGUMENTS
02629 
02630 Reference pages: 24 28 58 (59) (67) [71] [72] 103
02631 
02632 These rules are as given in the spec. Note that JogDisplayCsy, JogMoveCsy,
02633 and SensorCsy are not included. It is not clear whether omitting these
02634 is intentional or inadvertent.
02635 
02636 */
02637 
02638 ippCommandPtr ippCommandParser::makeSetCoordSystem()
02639 {
02640   if (_argCount != 1)
02641     _errorCode = MUST_HAVE_ONE_ARGUMENT;
02642   else if ((_argTypes[0] != ARGKEYWORD) ||
02643      ((_argKeywords[0] != MachineCsy) &&
02644       (_argKeywords[0] != MultipleArmCsy) &&
02645       (_argKeywords[0] != PartCsy) &&
02646       (_argKeywords[0] != MoveableMachineCsy)))
02647     _errorCode = BAD_ARGUMENTS;
02648   return ((_errorCode != OK) ? NULL :
02649     (new ippSetCoordSystemCommand(_tag, (ippCoordSysType)_argKeywords[0])));
02650 }
02651 
02652 /*******************************************************************/
02653 
02654 /* ippCommandParser::makeSetCsyTransformation
02655 
02656 Returned Value: A SetCsyTransformationCommand as described by the command
02657   text, or NULL.
02658 
02659 Called By: ippCommandParser::makeCommand
02660 
02661 Rules:
02662 1. There must be seven arguments.
02663    MUST_HAVE_7_ARGUMENTS
02664 2. The first argument must be JogDisplayCsy, JogMoveCsy, MoveableMachineCsy,
02665    MultipleArmCsy, PartCsy, or SensorCsy.
02666    BAD_FIRST_ARGUMENT
02667 3. All the other arguments must be numbers.
02668    BAD_ARGUMENTS
02669 4. Theta, the fourth numeric argument, must be in the range 0 to 180.
02670    THETA_OUT_OF_RANGE
02671 5. Commas must separate the arguments.
02672    BAD_ARGUMENTS
02673 
02674 Reference pages: 24 28 59 (60) 67 [71] [72] (80) 103
02675 
02676 */
02677 
02678 ippCommandPtr ippCommandParser::makeSetCsyTransformation()
02679 {
02680   if (_argCount != 13) {
02681     _errorCode = MUST_HAVE_7_ARGUMENTS;
02682     return 0;
02683   } 
02684 
02685   if (!match(_argTypes,"k,#,#,#,#,#,#")) {
02686     _errorCode = BAD_ARGUMENTS;
02687     return 0;
02688   }
02689 
02690   ippCoordSysType type = (ippCoordSysType)_argKeywords[0]; 
02691   if (( type!= JogDisplayCsy) &&
02692      (type != JogMoveCsy) &&
02693      (type != MoveableMachineCsy) &&
02694      (type != MultipleArmCsy) &&
02695      (type != PartCsy) &&
02696      (type != SensorCsy)) {
02697     _errorCode = BAD_FIRST_ARGUMENT;
02698   }
02699   
02700   if ((getValue(8) < 0) || (getValue(8) > 180)) {
02701     _errorCode = THETA_OUT_OF_RANGE;
02702   }
02703 
02704   return ((_errorCode != OK) ? NULL :
02705     (new ippSetCsyTransformationCommand(_tag, type,
02706              getValue(2),  getValue(4),
02707              getValue(6),  getValue(8),
02708              getValue(10), getValue(12))));
02709 }
02710 
02711 /*******************************************************************/
02712 
02713 /* ippCommandParser::makeSetProp
02714 
02715 Returned Value: A SetPropCommand as described by the command text, or NULL.
02716 
02717 Called By: ippCommandParser::makeCommand
02718 
02719 Rules:
02720 1. There must be at least one argument, and each argument must have one of
02721    the two patterns:
02722    key1.key2.key3(val) -- six components in _argCount
02723    key1.key2.key3.key4(val) -- eight components in _argCount
02724    and all arguments except the last must be followed by a comma.
02725    BAD_ARGUMENTS
02726 2. key1 must be FoundTool or Tool or part
02727    ARGUMENT_FIRST_PART_MUST_BE_TOOL_OR_FOUNDTOOL
02728 3. key2 must be GoToPar or PtMeasPar.
02729    ARGUMENT_SECOND_PART_MUST_BE_GOTOPAR_OR_PTMEASPAR
02730 4. If key2 is GoToPar, key3 must be either Speed or Accel. If key2 is
02731    PtMeasPar, key3 must be one of Speed, Accel, Approach, Retract, or Search.
02732    ARGUMENT_THIRD_PART_BAD
02733 5. If there is a key4, it must be Actual.
02734    ARGUMENT_FOURTH_PART_MUST_BE_ACT
02735 6. The dots must be placed where shown in rule 1.
02736    BAD_DOTS
02737 7. The number in parentheses must be placed where shown in rule 1.
02738    ARGUMENT_MUST_END_WITH_NUMBER_IN_PARENTHESES
02739 
02740 Reference pages: 24 26 29 (45) 65 [73] 77 (78) 99 108
02741 Also see the reference pages for GetProp, since several of those imply
02742 that certain properties cannot be set directly.
02743 
02744 The spec is not explicit about what is allowed to be set using SetProp
02745 and what is not. For the most part, we believe this function does what
02746 the spec intends. For PtMeasPars, the spec (page 65) states that only the
02747 Act value can be set by the client, so here, key4 must be ACT if it is
02748 used. The spec does not explicitly rule out setting DEF for GoToPars, but
02749 it appears by implication not to be allowed, so it is not allowed here.
02750 
02751 The [(_argCount + 1) / 7] size for the keys arrays and the values array
02752 is used because this is the smallest number that is sure to be at
02753 least as large as the number of arguments. Each argument must have at
02754 least six components, and the arguments are separated by commas (which
02755 are added into _argCount).
02756 
02757 */
02758 ippCommandPtr ippCommandParser::makeSetProp()
02759 {
02760   ippSetPropCommandPtr command = new ippSetPropCommand(_tag);
02761   for (int n = 0; ((n < _argCount) && (_errorCode == OK));n++)  {
02762   
02763     ippOtherKeyType key1 = ippOtherKeyType_INVALID;
02764     ippOtherKeyType key2 = EmptyKey;
02765     ippOtherKeyType key3 = EmptyKey;
02766     ippOtherKeyType key4 = EmptyKey;
02767     double value = 0;
02768     if (match(_argTypes,"k.k.k.kD",n))  {
02769       key1 = _argKeywords[n];
02770       key2 = _argKeywords[n+2];
02771       key3 = _argKeywords[n+4];
02772       key4 = _argKeywords[n+6];
02773       value = getValue(n+7);
02774       n += 8;
02775 
02776     } else if (match(_argTypes,"k.k.kD",n)) { 
02777       key1 = _argKeywords[n];
02778       key2 = _argKeywords[n+2];
02779       key3 = _argKeywords[n+4];
02780       value = getValue(n+5);
02781       n += 6;
02782     } else if (match(_argTypes,"k.kD",n)) { 
02783       key1 = _argKeywords[n];
02784       key2 = _argKeywords[n+2];
02785       value = getValue(n+3);
02786       n += 4;
02787     } else if (match(_argTypes,"kD",n)) { 
02788       key1 = _argKeywords[n];
02789       value = getValue(n+1);
02790       n += 2;
02791     } else {
02792       _errorCode = BAD_ARGUMENTS;
02793     }
02794     if (n < _argCount && _argTypes[n] != ARGCOMMA) {
02795       _errorCode = BAD_ARGUMENTS;
02796     }
02797     if(_errorCode == OK ) { 
02798       ippProp prop(key1,key2,key3,key4);
02799       if (PropertyIsAllowedAndWritable(prop)) { 
02800         command->addPropValue(prop,value);
02801       } else {
02802        _errorCode = BAD_ARGUMENTS;
02803      }
02804     }
02805   }
02806   if (_errorCode != OK) {
02807     return 0;
02808   }
02809   return command;
02810 
02811 }
02812 
02813 
02814 
02815 /*******************************************************************/
02816 
02817 /* ippCommandParser::makeSetTool
02818 
02819 Returned Value: A SetToolCommand as described by the command text, or NULL.
02820 
02821 Called By: ippCommandParser::makeCommand
02822 
02823 Rules:
02824 1. There must be one argument.
02825    MUST_HAVE_ONE_ARGUMENT
02826 2. The argument must be a string.
02827    ARGUMENT_MUST_BE_STRING
02828 
02829 Reference pages: 24 27 29 (54 - 55) 102 106
02830 
02831 */
02832 
02833 ippCommandPtr ippCommandParser::makeSetTool()
02834 {
02835   if (_argCount != 1)
02836     _errorCode = MUST_HAVE_ONE_ARGUMENT;
02837   else if (_argTypes[0] != ARGSTRING)
02838     _errorCode = ARGUMENT_MUST_BE_STRING;
02839   return((_errorCode != OK) ? NULL: (new ippSetToolCommand(_tag, _argStrings[0].c_str())));
02840 }
02841 
02842 /*******************************************************************/
02843 /* ippCommandParser::makeStartSession
02844 Returned Value: A ippCommand of commandNameType StartSession as described by
02845   the command text, or NULL.
02846 Called By: ippCommandParser::makeCommand
02847 Rules:
02848 1. There must be no arguments.
02849    MUST_HAVE_NO_ARGUMENTS
02850 Reference pages: 18 20 24 26 (38) (41) 49 [71] (77) 81 99
02851 */
02852 
02853 ippCommandPtr ippCommandParser::makeStartSession()
02854 {
02855   if (_argCount != 0) {
02856     _errorCode = MUST_HAVE_NO_ARGUMENTS;
02857   }
02858   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, StartSession)));
02859 }
02860 
02861 /*******************************************************************/
02862 
02863 /* ippCommandParser::makeStopAllDaemons
02864 
02865 Returned Value: A ippCommand of commandNameType StopAllDaemons as described by
02866   the command text, or NULL.
02867 
02868 Called By: ippCommandParser::makeCommand
02869 
02870 Rules:
02871 1. There must be no arguments.
02872    MUST_HAVE_NO_ARGUMENTS
02873 
02874 Reference pages: 24 26 (42) (50) 99
02875 
02876 */
02877 
02878 ippCommandPtr ippCommandParser::makeStopAllDaemons()
02879 {
02880   if (_argCount != 0)
02881     _errorCode = MUST_HAVE_NO_ARGUMENTS;
02882   return ((_errorCode != OK) ? NULL : (new ippCommand(_tag, StopAllDaemons)));
02883 }
02884 
02885 /*******************************************************************/
02886 
02887 /* ippCommandParser::makeStopDaemon
02888 
02889 Returned Value: A StopDaemonCommand as described by the command text, or NULL.
02890 
02891 Called By: ippCommandParser::makeCommand
02892 
02893 Rules:
02894 1. There must be one argument.
02895    MUST_HAVE_ONE_ARGUMENT
02896 2. The argument must be an event _tag.
02897    ARGUMENT_MUST_BE_EVENT_TAG
02898 
02899 Reference pages: 19 (22) 24 26 [40] (42) (50) 99
02900 
02901 */
02902 
02903 ippCommandPtr ippCommandParser::makeStopDaemon()
02904 {
02905   if (_argCount != 1)
02906     _errorCode = MUST_HAVE_ONE_ARGUMENT;
02907   else if (_argTypes[0] != ARGETAG)
02908     _errorCode = ARGUMENT_MUST_BE_EVENT_TAG;
02909   return((_errorCode != OK) ? NULL: (new ippStopDaemonCommand(_tag, _argInt)));
02910 }
02911 
02912 /*******************************************************************/
02913 
02914 /* ippCommandParser::makeTiltCenterPart
02915 
02916 Returned Value: A TiltCenterPartCommand as described by the command text,
02917                 or NULL.
02918 
02919 Called By: ippCommandParser::makeCommand
02920 
02921 Rules:
02922 1. There must be 7 arguments.
02923    MUST_HAVE_7_ARGUMENTS
02924 2. The arguments must all be numbers.
02925    BAD_ARGUMENTS
02926 3. Commas must separate the arguments.
02927    BAD_ARGUMENTS
02928 
02929 Reference pages: 24 27 (97) 102
02930 
02931 */
02932 
02933 ippCommandPtr ippCommandParser::makeTiltCenterPart()
02934 {
02935   if (_argCount != 13) {
02936     _errorCode = MUST_HAVE_7_ARGUMENTS;
02937   }
02938   
02939   if (!match(_argTypes,"#,#,#,#,#,#,#")) {
02940     _errorCode = BAD_ARGUMENTS;
02941   }
02942 
02943   return ((_errorCode != OK) ? NULL:
02944     new ippTiltCenterPartCommand(_tag, getValue(0), getValue(2),
02945             getValue(4), getValue(6),
02946             getValue(8), getValue(10),
02947             getValue(12)));
02948 }
02949 
02950 /*******************************************************************/
02951 
02952 /* ippCommandParser::makeTiltPart
02953 
02954 Returned Value: A TiltPartCommand as described by the command text, or NULL.
02955 
02956 Called By: ippCommandParser::makeCommand
02957 
02958 Rules:
02959 1. There must be 4 arguments.
02960    MUST_HAVE_4_ARGUMENTS
02961 2. The arguments must all be numbers.
02962    BAD_ARGUMENTS
02963 3. Commas must separate the arguments.
02964    BAD_ARGUMENTS
02965 
02966 Reference pages: 24 27 (97) 102
02967 
02968 */
02969 
02970 ippCommandPtr ippCommandParser::makeTiltPart()
02971 {
02972   if (_argCount != 7) {
02973     _errorCode = MUST_HAVE_4_ARGUMENTS;
02974   } else if (!match(_argTypes,"#,#,#,#")) {
02975     _errorCode = BAD_ARGUMENTS;
02976   }
02977 
02978   return ((_errorCode != OK) ? NULL:
02979     new ippTiltPartCommand(_tag, getValue(0), getValue(2),
02980         getValue(4), getValue(6)));
02981 }
02982 
02983 
02984 
02985 ippCommandPtr ippCommandParser::makeEnumToolCollection()
02986 {
02987   if (_argCount != 1)
02988     _errorCode = MUST_HAVE_ONE_ARGUMENT;
02989   else if (_argTypes[0] != ARGSTRING)
02990     _errorCode = ARGUMENT_MUST_BE_STRING;
02991   return ((_errorCode != OK) ? NULL :
02992     (new ippEnumToolCollectionCommand(_tag, _argStrings[0].c_str())));
02993 }
02994 
02995 ippCommandPtr ippCommandParser::makeEnumAllToolCollections()
02996 {
02997   if (_argCount != 1)
02998     _errorCode = MUST_HAVE_ONE_ARGUMENT;
02999   else if (_argTypes[0] != ARGSTRING)
03000     _errorCode = ARGUMENT_MUST_BE_STRING;
03001   return ((_errorCode != OK) ? NULL :
03002     (new ippEnumAllToolCollectionsCommand(_tag, _argStrings[0].c_str())));
03003 }
03004 
03005 ippCommandPtr ippCommandParser::makeOpenToolCollection()
03006 {
03007   if (_argCount != 1)
03008     _errorCode = MUST_HAVE_ONE_ARGUMENT;
03009   else if (_argTypes[0] != ARGSTRING)
03010     _errorCode = ARGUMENT_MUST_BE_STRING;
03011   return ((_errorCode != OK) ? NULL :
03012     (new ippOpenToolCollectionCommand(_tag, _argStrings[0].c_str())));
03013 }
03014 
03015 
03016 ippCommandPtr ippCommandParser::makeSaveActiveCoordSystem()
03017 {
03018   if (_argCount != 1)
03019     _errorCode = MUST_HAVE_ONE_ARGUMENT;
03020   else if (_argTypes[0] != ARGSTRING)
03021     _errorCode = ARGUMENT_MUST_BE_STRING;
03022   return ((_errorCode != OK) ? NULL :
03023     (new ippSaveActiveCoordSystemCommand(_tag, _argStrings[0].c_str())));
03024 }
03025 
03026 ippCommandPtr ippCommandParser::makeLoadCoordSystem()
03027 {
03028   if (_argCount != 1)
03029     _errorCode = MUST_HAVE_ONE_ARGUMENT;
03030   else if (_argTypes[0] != ARGSTRING)
03031     _errorCode = ARGUMENT_MUST_BE_STRING;
03032   return ((_errorCode != OK) ? NULL :
03033     (new ippLoadCoordSystemCommand(_tag, _argStrings[0].c_str())));
03034 }
03035 
03036 ippCommandPtr ippCommandParser::makeDeleteCoordSystem()
03037 {
03038   if (_argCount != 1)
03039     _errorCode = MUST_HAVE_ONE_ARGUMENT;
03040   else if (_argTypes[0] != ARGSTRING)
03041     _errorCode = ARGUMENT_MUST_BE_STRING;
03042   return ((_errorCode != OK) ? NULL :
03043     (new ippDeleteCoordSystemCommand(_tag, _argStrings[0].c_str())));
03044 }
03045 
03046 ippCommandPtr ippCommandParser::makeEnumCoordSystems()
03047 {
03048   if (_argCount != 0)
03049     _errorCode = MUST_HAVE_NO_ARGUMENTS;
03050   return ((_errorCode != OK) ? NULL :
03051     (new ippEnumCoordSystemsCommand(_tag)));
03052 }
03053 
03054 ippCommandPtr ippCommandParser::makeGetNamedCsyTransformation()
03055 {
03056   if (_argCount != 1)
03057     _errorCode = MUST_HAVE_ONE_ARGUMENT;
03058   else if (_argTypes[0] != ARGSTRING)
03059     _errorCode = ARGUMENT_MUST_BE_STRING;
03060   return ((_errorCode != OK) ? NULL :
03061     (new ippGetNamedCsyTransformationCommand(_tag, _argStrings[0].c_str())));
03062   return 0;
03063 }
03064 
03065 ippCommandPtr ippCommandParser::makeSaveNamedCsyTransformation()
03066 {
03067   double x0=0;
03068   double y0=0;
03069   double z0=0;
03070   double theta=0;
03071   double phi=0;
03072   double psi=0;
03073 
03074   if (_argCount != 13) {
03075     _errorCode = MUST_HAVE_7_ARGUMENTS;
03076     return 0;
03077   } 
03078   if (!match(_argTypes,"s,#,#,#,#,#,#")) {
03079     _errorCode = BAD_ARGUMENTS;
03080     return 0;
03081   }
03082   x0 = getValue(2);
03083   y0 = getValue(4);
03084   z0 = getValue(6);
03085   theta = getValue(8);
03086   phi = getValue(10);
03087   psi = getValue(12);
03088   return ((_errorCode != OK) ? NULL :
03089     (new ippSaveNamedCsyTransformationCommand(_tag,
03090       _argStrings[0].c_str(),x0,y0,z0,theta,phi,psi)));
03091   return 0;
03092 }
03093 
03094 /*
03095 Returned Value: A ScanOnCurveHint as described by the command
03096   text, or NULL.
03097 
03098 Called By: ippCommandParser::makeCommand
03099 
03100 Rules:
03101 1. There must be two argument.
03102    BAD_ARGUMENTS
03103 2. The argument must be a number.
03104    BAD_ARGUMENTS
03105 3. The number must be positive.
03106    DENSITY_MUST_BE_POSITIVE
03107    MINIMUM_RADIUS_OF_CURVATURE_MUST_BE_POSITIVE
03108 
03109 */ippCommandPtr ippCommandParser::makeScanOnCurveHint()
03110 {
03111   if (!match(_argTypes,"#,#")) {
03112     _errorCode = BAD_ARGUMENTS;
03113     return 0;
03114   }
03115   double density = getValue(0);
03116   double minRadiusOfCurvature = getValue(2);
03117   if ( density <=0 ) { 
03118     _errorCode = DENSITY_MUST_BE_POSITIVE;
03119   }
03120   if (minRadiusOfCurvature<=0){ 
03121     _errorCode = MINIMUM_RADIUS_OF_CURVATURE_MUST_BE_POSITIVE;
03122   }
03123   return ((_errorCode != OK) ? NULL :
03124     (new ippScanOnCurveHintCommand(_tag,density,minRadiusOfCurvature)));
03125 }
03126 
03127 /*
03128 Returned Value: ScanOnCurveDensity as described by the command
03129   text, or NULL.
03130 
03131 Called By: ippCommandParser::makeCommand
03132 
03133 Rules:
03134 
03135 */
03136 ippCommandPtr ippCommandParser::makeScanOnCurveDensity()
03137 {
03138   bool hasDis = false;
03139   bool hasAngle = false;
03140   bool hasAtNominals = false;
03141   double dis =0.1;
03142   double angle = 0.0;
03143   bool atNominals = false;
03144   int n = 0;
03145   while (n < _argCount && _errorCode == OK) {
03146     int old_n=n;
03147     CheckOptionalArgumentValue(n,hasDis,Dis,DIS_ARGUMENT_USED_TWICE,DIS_MUST_BE_FOLLOWED_BY_NUMBER_IN_PARENS,dis);
03148     CheckOptionalArgumentValue(n,hasAngle,Angle,ANGLE_ARGUMENT_USED_TWICE,ANGLE_MUST_BE_FOLLOWED_BY_NUMBER_IN_PARENS,angle);
03149     CheckOptionalArgumentValue(n,hasAtNominals,AtNominals,ATNOMINALS_ARGUMENT_USED_TWICE,Z_NOT_FOLLOWED_BY_NUMBER_IN_PARENS,atNominals);
03150     if (old_n == n) {
03151       // the argument has not been recognized:
03152       _errorCode = BAD_ARGUMENTS;
03153     }
03154   } 
03155   if ((_errorCode == OK)&&(hasDis == false) && (hasAngle == false) && (hasAtNominals == false)) {
03156     _errorCode = BAD_ARGUMENTS;
03157   }
03158   return ((_errorCode != OK) ? NULL:
03159     (new ippScanOnCurveDensityCommand(_tag, dis, hasAngle, angle,atNominals)));
03160 }
03161 ippCommandPtr ippCommandParser::makeScanUnknownDensity()
03162 {
03163   bool hasDis = false;
03164   bool hasAngle = false;
03165   bool hasAtNominals = false;
03166   double dis =0.1;
03167   double angle = 0.0;
03168   int n = 0;
03169   while (n < _argCount && _errorCode == OK) {
03170     int old_n=n;
03171     CheckOptionalArgumentValue(n,hasDis,Dis,DIS_ARGUMENT_USED_TWICE,DIS_MUST_BE_FOLLOWED_BY_NUMBER_IN_PARENS,dis);
03172     CheckOptionalArgumentValue(n,hasAngle,Angle,ANGLE_ARGUMENT_USED_TWICE,ANGLE_MUST_BE_FOLLOWED_BY_NUMBER_IN_PARENS,angle);
03173     if (old_n == n) {
03174       // the argument has not been recognized:
03175       _errorCode = BAD_ARGUMENTS;
03176     }
03177   } 
03178   if ((_errorCode == OK)&&(hasDis == false) && (hasAngle == false) && (hasAtNominals == false)) {
03179     _errorCode = BAD_ARGUMENTS;
03180   }
03181   return ((_errorCode != OK) ? NULL:
03182     (new ippScanUnknownDensityCommand(_tag, dis, hasAngle, angle)));
03183 }
03184 
03185 
03186 ippCommandPtr ippCommandParser::makeScanOnCurve()
03187 {
03188 
03189   int n1 = _argDoubles.size();
03190   int n2 = _argTypes.size();
03191   int n3 = _argKeywords.size();
03192   int n4 = _argStrings.size();
03193 
03194   IPP_ASSERT(_argDoubles.size()  >=_argCount);
03195   IPP_ASSERT(_argTypes.size()    >=_argCount);
03196   IPP_ASSERT(_argKeywords.size() >=_argCount);
03197 
03198   //ScanOnCurve(Closed(1|0), Format(X(),Y(),Z(),IJK(),tag[,pi,pj,pk[,si,sj,sk]]),
03199   //    Data(P1x,P1y,P1z,i1,j1,k1,tag1[,pi1,pj1,pk1[,si1,sj1,sk1]]
03200   //
03201   //  ,Pnx,Pny,Pnz,in,jn,jn,tagn[,pin,pjn,pkn[,sin,sjn,skn]]))
03202 
03203   bool bClose = false;
03204 
03205   if (!match(_argTypes,"kD,kD,k")) {    
03206     _errorCode = BAD_ARGUMENTS;
03207     return 0;
03208   }
03209   if ( _argKeywords[0] != Closed ) { 
03210     _errorCode = BAD_ARGUMENTS;
03211     return 0;
03212   }
03213   if (!IsBoolean(getValue(1))) { 
03214     _errorCode = BAD_ARGUMENTS; // must be 0 or 1
03215     return 0;
03216   }
03217   bClose = AsBoolean(getValue(1));
03218   if ( _argKeywords[3] != Format ) { 
03219     _errorCode = BAD_ARGUMENTS;
03220     return 0;
03221   }
03222   if ( _argKeywords[6] != Data ) { 
03223     _errorCode = BAD_ARGUMENTS;
03224     return 0;
03225   }
03226   ippScanOnCurveCommand::FormatType type = ippScanOnCurveCommand::FormatType((int)getValue(4));
03227   int nb_per_point = 0;
03228   switch(type) {
03229     case ippScanOnCurveCommand::Type1: nb_per_point = 7;  break;
03230     case ippScanOnCurveCommand::Type2: nb_per_point = 10; break;
03231     case ippScanOnCurveCommand::Type3: nb_per_point = 13; break;
03232     default: IPP_ASSERT(0);
03233   }
03234   int n=7;
03235   int count = 0;
03236   ippScanOnCurveCommandPtr command = new ippScanOnCurveCommand(_tag,bClose,type);
03237   while (_argTypes[n] == ARGIJK && n<_argCount) {
03238     count++; n++;
03239   }
03240   if  ( ( count % nb_per_point ) != 0 )  { 
03241     // invalid number of data;
03242     _errorCode = BAD_NUMBER_OF_ARGUMENT_FOR_DATA_IN_SCANONCURVE;
03243     return 0;
03244   }
03245 
03246   n = count/nb_per_point;
03247   int k=7;
03248   for (int i=0;i<n;i++) {
03249     if (!IsInteger(getValue(k+6)))  {
03250       _errorCode = ARGUMENT_MUST_BE_INTEGER;
03251     }
03252     switch(type) {
03253     case ippScanOnCurveCommand::Type1: 
03254       command->addPoint(getValue(k),getValue(k+1),getValue(k+2),
03255                         getValue(k+3),getValue(k+4),getValue(k+5),AsInteger(getValue(k+6))
03256                         );
03257       break;
03258     case ippScanOnCurveCommand::Type2: 
03259       command->addPoint(getValue(k),getValue(k+1),getValue(k+2),
03260                         getValue(k+3),getValue(k+4),getValue(k+5),AsInteger(getValue(k+6)),
03261                         getValue(k+7),getValue(k+8),getValue(k+9)
03262                         );
03263       break;
03264     case ippScanOnCurveCommand::Type3: 
03265       command->addPoint(getValue(k),getValue(k+1),getValue(k+2),
03266                         getValue(k+3),getValue(k+4),getValue(k+5),AsInteger(getValue(k+6)),
03267                         getValue(k+7),getValue(k+8),getValue(k+9),
03268                         getValue(k+10),getValue(k+11),getValue(k+12)
03269                         );
03270       break;
03271     }
03272     k+=nb_per_point;
03273   }
03274 
03275   return (_errorCode == OK) ? command : NULL;
03276 }
03277 
03278 ippCommandPtr ippCommandParser::makeScanOnHelix()
03279 {
03280   if (_argCount != 25) {
03281     _errorCode = BAD_ARGUMENTS;
03282     return 0;
03283   }
03284   
03285   //                                      1                   2
03286   //                    1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 
03287   if (!match(_argTypes,"#,#,#,#,#,#,#,#,#,#,#,#,#")) {
03288     _errorCode = BAD_ARGUMENTS;
03289     return 0;
03290   }
03291 
03292   if (getValue(22) <= 0) {
03293     _errorCode = STEPW_MUST_BE_POSITIVE;
03294   }
03295 
03296   return ((_errorCode != OK) ? NULL:
03297     (new ippScanOnHelixCommand
03298      (_tag,
03299       getValue(0),  getValue(2),  getValue(4),  getValue(6),
03300       getValue(8),  getValue(10), getValue(12), getValue(14),
03301       getValue(16), getValue(18), getValue(20), getValue(22),
03302       getValue(24) )));
03303 }
03304 
03305 ippCommandPtr ippCommandParser::makePtMeasSelfCenter()
03306 {
03307   bool hasX = false;
03308   bool hasY = false;
03309   bool hasZ = false;
03310   bool hasIJK = false;
03311   double x = 0;
03312   double y = 0;
03313   double z = 0;
03314   double i = 0;
03315   double j = 0;
03316   double k = 0;
03317 
03318   int n=0;
03319   while (n < _argCount && _errorCode == OK) {
03320     int old_n=n;
03321     CheckOptionalArgumentValue(n,hasX    ,_X   ,       X_ARGUMENT_USED_TWICE, X_NOT_FOLLOWED_BY_NUMBER_IN_PARENS, x);
03322     CheckOptionalArgumentValue(n,hasY    ,_Y   ,       Y_ARGUMENT_USED_TWICE, Y_NOT_FOLLOWED_BY_NUMBER_IN_PARENS, y);
03323     CheckOptionalArgumentValue(n,hasZ    ,_Z   ,       Z_ARGUMENT_USED_TWICE, Z_NOT_FOLLOWED_BY_NUMBER_IN_PARENS, z);
03324     CheckOptionalArgumentValue(n,hasIJK  ,_IJK  ,     IJK_ARGUMENT_USED_TWICE,IJK_NOT_FOLLOWED_BY_ARGIJK, i,j,k);
03325     if (old_n == n) { 
03326       // the argument has not been recognized:
03327       _errorCode = BAD_ARGUMENTS;
03328     } 
03329   }
03330   if (!hasX || !hasY || !hasZ || !hasIJK ) {
03331     // all part of the required enumeration must have been found
03332     _errorCode = BAD_ARGUMENTS;
03333   }
03334   return (_errorCode != OK) ? NULL:
03335     new ippPtMeasSelfCenterCommand(_tag, x, y, z,   ippTargetVector(i,j,k) );
03336 }
03337 
03338 ippCommandPtr ippCommandParser::makePtMeasSelfCenterLocked()
03339 {
03340   bool hasX = false;
03341   bool hasY = false;
03342   bool hasZ = false;
03343   bool hasIJK = false;
03344   bool hasLMN = false;
03345   double x = 0;
03346   double y = 0;
03347   double z = 0;
03348   double i1 = 0;
03349   double j1 = 0;
03350   double k1 = 0;
03351   double i2 = 0;
03352   double j2 = 0;
03353   double k2 = 0;
03354 
03355   int n=0;
03356   while (n < _argCount && _errorCode == OK) {
03357     int old_n=n;
03358     CheckOptionalArgumentValue(n,hasX    ,_X   ,       X_ARGUMENT_USED_TWICE, X_NOT_FOLLOWED_BY_NUMBER_IN_PARENS, x);
03359     CheckOptionalArgumentValue(n,hasY    ,_Y   ,       Y_ARGUMENT_USED_TWICE, Y_NOT_FOLLOWED_BY_NUMBER_IN_PARENS, y);
03360     CheckOptionalArgumentValue(n,hasZ    ,_Z   ,       Z_ARGUMENT_USED_TWICE, Z_NOT_FOLLOWED_BY_NUMBER_IN_PARENS, z);
03361     CheckOptionalArgumentValue(n,hasIJK  ,_IJK  ,     IJK_ARGUMENT_USED_TWICE, IJK_NOT_FOLLOWED_BY_ARGIJK, i1,j1,k1);
03362     CheckOptionalArgumentValue(n,hasLMN  ,_LMN  ,     LMN_ARGUMENT_USED_TWICE, IJK_NOT_FOLLOWED_BY_ARGIJK, i2,j2,k2);
03363     if (old_n == n) { 
03364       // the argument has not been recognized:
03365       _errorCode = BAD_ARGUMENTS;
03366     } 
03367   }
03368   if (!hasX || !hasY || !hasZ || !hasIJK ||!hasLMN ) {
03369     // all part of the required enumeration must have been found
03370     _errorCode = BAD_ARGUMENTS;
03371   }
03372   return (_errorCode != OK) ? NULL:
03373     new ippPtMeasSelfCenterLockedCommand(_tag, x, y, z,   ippTargetVector(i1,j1,k1) ,ippTargetVector(i2,j2,k2));}
03374 
03375 
03376 
03377 /*******************************************************************/
03378 
03379 /* ippCommandParser::makeCommand
03380 
03381 Returned Value: A ippCommand of the appropriate type or NULL.
03382 
03383 Called By: ippCommandParser::parseCommand
03384 
03385 Rules: None.
03386 
03387 This just calls the makeXXX function for the command type whose name
03388 is in the _commandName data member of the parser.
03389 
03390 */
03391 
03392 
03393 ippCommandPtr ippCommandParser::makeCommand()
03394 {
03395   switch(_commandName)
03396   {
03397     // this code is equivalent to 
03398     //  case IsHome : return makeIsHomed();
03399     // for all values defined in he COMMAND enumeration
03400 
03401 #define ENUM(value,function) case ipp::value: return IPP_CONCAT(make,value)();
03402     COMMAND_ENUMERATION
03403 #undef ENUM
03404 
03405     default: 
03406       return makeAbortE();
03407   }
03408 }
03409 
03410 /*******************************************************************/
03411 
03412 /* ippCommandParser::parseCommand
03413 
03414 Returned Value: A ippCommand of the appropriate type or NULL.
03415 
03416 Called By:
03417    external functions
03418    main (in stand-alone command parser and stand-alone command checker)
03419 
03420 Rules:
03421 1. <13><10><0> must immediately follow the close parentheses at the
03422    end of the command.
03423    BAD_CHARACTER_AFTER_COMMAND_END
03424 2. If the command is an event command, the _tag must be an event _tag.
03425    EVENT_COMMAND_MUST_HAVE_EVENT_TAG
03426 3. If the command is not an event command, the _tag must not be an event _tag.
03427    NON_EVENT_COMMAND_MUST_NOT_HAVE_EVENT_TAG
03428 
03429 The setInput function copies a command string into the parser's
03430 _inputArray, stopping at the first NULL, so the rule above is reasonable.
03431 
03432 parseTag sets the _errorCode to OK if the _tag is OK syntactically.
03433 
03434 */
03435 
03436 //=============================================================================
03437 ippCommandPtr ippCommandParser::parseCommand()
03438 //-----------------------------------------------------------------------------
03439 {
03440   ippCommandPtr aCommand = 0;
03441 
03442   _commandName =ippCommandNameType_INVALID;
03443   
03444   parseTag();
03445   
03446   if (_errorCode == OK)  {
03447     unSpaceInputArray();
03448   }
03449 
03450   if (_errorCode == OK) {
03451     parseCmdName();
03452   }
03453   if (_errorCode == OK) {
03454     parseCmdArguments();
03455   }
03456 
03457   if ((_errorCode == OK) &&
03458       ((_inputArray[_arrayIndex] != 13) ||
03459        (_inputArray[_arrayIndex + 1] != 10) ||
03460        (_inputArray[_arrayIndex + 2] != 0))) 
03461  {
03462     _errorCode = BAD_CHARACTER_AFTER_COMMAND_END;
03463   }
03464  
03465   if (_errorCode == OK) {
03466      if (   (_commandName == AbortE) || 
03467             (_commandName == GetErrStatusE) || 
03468             (_commandName == GetPropE) || 
03469             (_commandName == OnMoveReportE)
03470         )       {
03471           if (!_isEvent) {
03472             _errorCode = EVENT_COMMAND_MUST_HAVE_EVENT_TAG;
03473           }
03474       } else  {
03475         if (_isEvent) {
03476           _errorCode = NON_EVENT_COMMAND_MUST_NOT_HAVE_EVENT_TAG;
03477         }
03478       }
03479   }
03480   if (_errorCode == OK) {
03481     aCommand = makeCommand();
03482   }
03483 
03484  // Added by ER to fix potential leak
03485  if (_errorCode != OK ) {
03486    if (aCommand) {     
03487     aCommand = 0;
03488    }
03489  }
03490  return ((_errorCode != OK) ? NULL : aCommand);
03491 }
03492 
03493 /*******************************************************************/
03494 
03495 /* ippCommandParser::parseCmdArguments
03496 
03497 Returned Value: None.
03498 
03499 Called By: ippCommandParser::parseCommand
03500 
03501 Rules:
03502 1. If an argument component starts with a left parenthesis and is followed
03503    by a number, but is not preceded by the IJK keyword, then a right
03504    parenthesis must follow the number.
03505    BAD_COMMAND_ARGUMENTS
03506 2. The argument component being parsed does not start the way any known
03507    argument component starts.
03508    BAD_COMMAND_ARGUMENTS
03509 
03510 Each turn around the "for" loop parses one argument component.
03511 
03512 This decides what subordinate function to call to do the parsing
03513 depending on how the argument component starts.
03514 
03515 When this is called, _arrayIndex points at the first character after the
03516 left parenthesis that starts the argument list. On subsequent turns
03517 around the for loop, _arrayIndex points at the first character of an
03518 argument component. Since _arrayIndex++ is executed at the end of each turn
03519 around the loop, any function this calls must leave _arrayIndex pointing
03520 at the last character it reads.
03521 
03522 Spaces outside of strings are removed before this runs, so spaces
03523 are not dealt with outside strings.
03524 
03525 A dot may appear either before a capital letter (as in Tool.PtMeasPar)
03526 or at the beginning of a number (as in .123). In the first case it is
03527 an argument list component. In the second case it is part of the number.
03528 
03529 If the right parentheses after the arguments is missing, that will be
03530 caught either here (on the second BAD_COMMAND_ARGUMENTS line) or in one
03531 of the functions this calls.
03532 
03533 */
03534 
03535 void ippCommandParser::parseCmdArguments()
03536 {
03537   char c;
03538   char d;
03539 
03540   
03541   
03542   for (_argCount = 0; ((c = _inputArray[_arrayIndex]) != ')' ); _argCount++) {
03543       
03544      if (_argCount +3 >= _argSize) {
03545           makeArraysBigger();
03546      }
03547 
03548      d = _inputArray[_arrayIndex + 1];
03549 
03550      if (c == ',') {
03551         
03552         _argTypes[_argCount] = ARGCOMMA;
03553          
03554      }  else if ((c == '.') && ( d >= 'A') && (d <= 'Z' )) { /* dot before upper letter */
03555        
03556        _argTypes[_argCount] = ARGDOT; 
03557      
03558      }  else if ((c == '(') && (d == ')')) {
03559 
03560         _arrayIndex++;
03561         _argTypes[_argCount] = ARGPARENEMPTY;
03562 
03563      } else if ((c == '(') &&  ((d == '-') ||(d == '+') ||(d == '.') || isdigit(d)))    {
03564 
03565 
03566         _arrayIndex++;
03567         if ((_argTypes[_argCount - 1] == ARGKEYWORD) &&  
03568             (_argKeywords[_argCount - 1] == Data)  ) {
03569           // special case for the Data keyword that accepts a variable number of argument
03570           parseData();
03571 
03572         } else  if ((_argTypes[_argCount - 1] == ARGKEYWORD) &&  
03573             (_argKeywords[_argCount - 1] == _IJK ||_argKeywords[_argCount - 1] == _LMN ) ) {
03574            // special case for the IJK or the LMN keyword that expect 3 values 
03575            // i.e IJK(#,#,#) 
03576            parseData();
03577  
03578         } else  {
03579           // in all other cases the argument is followed by a single value in parenthesis
03580           parseNumber(ARGDOUBLE);// _argDoubles, _argCount);
03581 
03582           if (_errorCode != OK) {
03583              ;// what shall we do here ?
03584           } else if (_inputArray[_arrayIndex + 1] == ')') {
03585             _arrayIndex++;
03586             _argTypes[_argCount] = ARGPARENDOUBLE;
03587 
03588           }  else {
03589              _errorCode = BAD_COMMAND_ARGUMENTS;
03590 
03591           }
03592         }
03593     }  else if (c == '"') {  /* open quote */
03594 
03595         parseString();
03596     
03597     }  else if ((c == '-') || (c == '+') || (c == '.') || isdigit(c)) {
03598      
03599        parseNumber(ARGDOUBLE);
03600     
03601     }  else if ((c >= 'A') && (c <= 'Z')) {
03602     
03603       parseKeyword();
03604     
03605     } else {
03606     
03607       _errorCode = BAD_COMMAND_ARGUMENTS;
03608     
03609     }
03610     if (_errorCode != OK) {
03611       break;
03612     }
03613     
03614     _arrayIndex++; /* move to character after end of argument just parsed */
03615   }
03616   _arrayIndex++; /* move to character after the close parenthesis */
03617 
03618 }
03619 
03620 /*******************************************************************/
03621 
03622 /* ippCommandParser::parseCmdName
03623 
03624 Returned Value: None.
03625 
03626 Called By: ippCommandParser::parseCommand
03627 
03628 Rules:
03629 1. The command name must be a known command name.
03630    BAD_COMMAND_NAME
03631 
03632 This reads the command name from the _inputArray and sets _commandName.
03633 If the name is not the name of an I++ command, or if the name is not
03634 followed immediately by a left parenthesis, _commandName is set to -1.
03635 
03636 The _arrayIndex is left set to index the character following the left
03637 parenthesis after the command name.
03638 
03639 */
03640 
03641 
03642 ippCommandHashTable::ippCommandHashTable()
03643 {
03644   for (int i=0; i<ippCOMMANDNAMETYPE_MAXIMUM;i++)
03645   {
03646 #define ENUM(a,b) _map.insert(_Pair(b,a));
03647     COMMAND_ENUMERATION
03648 #undef ENUM
03649   }
03650 }
03651 ippCommandNameType ippCommandHashTable::find(const std::string& name)
03652 {
03653   _Iter i = _map.find((name));
03654   if (i == _map.end()) { 
03655     return ippCommandNameType_INVALID;
03656   }
03657   return i->second;
03658 }
03659 
03660 void ippCommandParser::parseCmdName()
03661 {  
03662   // the command name should start at character 6
03663   const char * name = (_inputArray + 6);
03664 
03665   // we first try to locate the opening paren : 
03666   const char* paren = strstr(name,"(");
03667   if (!paren) { 
03668     _errorCode = BAD_COMMAND_NAME;
03669     return;
03670   }
03671   int cmdLength = (paren-name);
03672 
03673   // query the command hash table to find out the enum
03674   // value of the command.
03675   _errorCode = OK;
03676   _commandName =  g_command_hash.find(std::string(name,cmdLength));
03677   
03678   if (_commandName == ippCommandNameType_INVALID) {
03679     _errorCode = BAD_COMMAND_NAME;
03680   }
03681 
03682   // set arrayIndex to point at character after left paren 
03683   _arrayIndex = ( paren - _inputArray) +1;
03684 }
03685 
03686 
03687 
03688 
03689 
03690 class ippKeyWordHashTable
03691 {
03692   typedef std::map<std::string,ippOtherKeyType>   Map;
03693   typedef std::map<std::string,ippOtherKeyType>::const_iterator  _Iter;
03694   typedef std::pair <std::string, ippOtherKeyType> _Pair;
03695   Map _map;
03696 public:
03697   ippKeyWordHashTable();
03698   ippOtherKeyType find(const std::string& string);
03699 } g_keyword_hash;
03700 
03701 ippKeyWordHashTable::ippKeyWordHashTable()
03702 {
03703   for (int i=0; i<ippOTHERKEYTYPE_MAXIMUM;i++)
03704   {
03705 #define ENUM(a,b) _map.insert(_Pair(b,a));
03706     KEYWORD_ENUMERATION
03707 #undef ENUM
03708   }
03709 }
03710 ippOtherKeyType ippKeyWordHashTable::find(const std::string& name)
03711 {
03712   _Iter i = _map.find((name));
03713   if (i == _map.end()) { 
03714     return ippOtherKeyType_INVALID;
03715   }
03716   return i->second;
03717 }
03718 
03719 
03720 /*******************************************************************/
03721 
03722 /* ippCommandParser::parseKeyword
03723 
03724 Returned Value: None.
03725 
03726 Called By: ippCommandParser::parseCmdArguments
03727 
03728 Rules:
03729 1. The character after a keyword must be a period, a comma, or a left or
03730    right parenthesis
03731    BAD_CHARACTER_AFTER_KEYWORD
03732 2. The characters being parsed must form either an event _tag or a
03733    known keyword.
03734    BAD_KEYWORD
03735 
03736 This parses event tags as well as keywords.
03737 
03738 This is called only if the character at _inputArray[_arrayIndex] is an
03739 upper case letter.
03740 
03741 If there are extra letters after a valid keyword, rule 1 will be violated,
03742 so the extra letters will be detected.
03743 
03744 Spaces may be legal in the command itself, but spaces have been
03745 removed before this function is called.
03746 
03747 If one keyword is the same as the beginning of another keyword, a check
03748 for the longer keyword must be made first. The only cases of that are
03749 A, C, and R.
03750 
03751 When the keyword is a single letter, it is not necessary to use a
03752 check like [if (strncmp(keyword, "A", 1) == 0)] since that is already
03753 known from the case statement to be true, but those checks are
03754 included just to keep the code looking consistent.
03755 
03756 This is parsing some keywords (MoveMan, OBB, etc.) that cannot occur
03757 in commands, but there is no harm in that. Inappropriate keywords will
03758 be detected elsewhere.
03759 
03760 */
03761 ippOtherKeyType getFromString(const std::string& keyword )
03762 {
03763   return g_keyword_hash.find(std::string(keyword));
03764 }
03765 
03766 void ippCommandParser::parseKeyword()
03767 {
03768 
03769   _argKeywords[_argCount] = ippOtherKeyType_INVALID;
03770   const char* keyword = (_inputArray + _arrayIndex);// pointer to start of word
03771   
03772   // we first try to locate the end of the key workd paren : 
03773   const char* endkeyword = keyword;
03774   while(isalpha(*endkeyword++));
03775   
03776   int keywordLength = (endkeyword-keyword)-1;
03777 
03778   // query the command hash table to find out the enum
03779   // value of the command.
03780   _errorCode = OK;
03781 
03782   if (keyword[0] == 'E') {
03783     if (isdigit(keyword[1]) && isdigit(keyword[2]) &&
03784         isdigit(keyword[3]) && isdigit(keyword[4]))
03785     {
03786       _argKeywords[_argCount] = TagKey;
03787       _argInt = (unsigned int)((1000*(keyword[1]-'0'))+
03788                                (100 *(keyword[2]-'0'))+
03789                                (10  *(keyword[3]-'0')) +
03790                                (1   *(keyword[4]-'0')));
03791       _arrayIndex+=4;
03792       keywordLength = 1;
03793    }
03794   }
03795 
03796   if(ippOtherKeyType_INVALID == _argKeywords[_argCount]) { 
03797     _argKeywords[_argCount] =   getFromString(std::string(keyword,keywordLength));
03798     if (ippOtherKeyType_INVALID== _argKeywords[_argCount]) {
03799       _errorCode = BAD_KEYWORD;
03800       return;
03801     }
03802   }  
03803   // special treatment for the  "Format" keyword
03804   if (_argKeywords[_argCount] == Format ) { 
03805 
03806     // there is only 3 possibilities for the Format portion of the ScanOnCurve
03807     // command. 
03808     // I wonder why the I++ commity made this so complicated : 
03809     //   -> it uses a second nested level  ScanOnCuve(..,Format(Stuf(),....)
03810     //   -> it uses no conventional keyworks:  tag,pi,pj,pk,si,sj, and sk
03811     //      -> they don't take arguments whereas X,Y,Z,and IJK do
03812     //      -> They are the only keyword in the specs athat do not strat with a upper letter !
03813     //
03814     // this code substute the complex Format command by an ellispis so that 
03815     // the existing parser can work easily :
03816     // Format[(...](1) for the first form
03817     // Format[(...](2) for the second form
03818     // Format[(...](3) for the third form
03819     // 
03820     static const char* type1= ippScanOnCurveCommand::getFormatString(ippScanOnCurveCommand::Type1);
03821     static int type1_length = strlen(type1);
03822     static const char* type2= ippScanOnCurveCommand::getFormatString(ippScanOnCurveCommand::Type2);
03823     static int type2_length = strlen(type2);
03824     static const char* type3= ippScanOnCurveCommand::getFormatString(ippScanOnCurveCommand::Type3);
03825     static int type3_length = strlen(type3);
03826     
03827     int l = strlen(keyword);
03828     if (strncmp(keyword,type1,type1_length) == 0 ) { 
03829       _inputArray[_arrayIndex+type1_length-3] = '(';
03830       _inputArray[_arrayIndex+type1_length-2] = '1';
03831       keywordLength = type1_length-3;
03832 
03833     } else if (strncmp(keyword,type2,type2_length) == 0 ){
03834       _inputArray[_arrayIndex+type2_length-3] = '(';
03835       _inputArray[_arrayIndex+type2_length-2] = '2';
03836       keywordLength = type2_length-3;
03837 
03838     } else if (strncmp(keyword,type3,type3_length) == 0 ){ 
03839       _inputArray[_arrayIndex+type3_length-3] = '(';
03840       _inputArray[_arrayIndex+type3_length-2] = '3';
03841       keywordLength = type3_length-3;
03842     } else {
03843       _errorCode = BAD_SYNTAX_FOR_FORMAT_IN_SCANONCURVE;
03844       return;
03845    }
03846 
03847   }
03848 
03849   _arrayIndex = (_arrayIndex + keywordLength ) -1;
03850   if ((_inputArray[_arrayIndex + 1] == '.') ||
03851       (_inputArray[_arrayIndex + 1] == ',') ||
03852       (_inputArray[_arrayIndex + 1] == '(') ||
03853       (_inputArray[_arrayIndex + 1] == ')')) 
03854   {
03855      _argTypes[_argCount] = ((_argKeywords[_argCount] == TagKey) ? ARGETAG : ARGKEYWORD);
03856   } else {
03857      _errorCode = BAD_CHARACTER_AFTER_KEYWORD;
03858   }
03859 }
03860 
03861 /*******************************************************************/
03862 
03863 /* ippCommandParser::parseNumber
03864 
03865 Returned Value: None.
03866 
03867 Called By:
03868   ippCommandParser::parseCmdArguments
03869   ippCommandParser::parseIJK
03870 
03871 Rules:
03872 1. A number must not have two decimal points.
03873    BAD_NUMBER_TWO_DECIMAL_POINTS
03874 2. A number must have at least one digit.
03875    BAD_NUMBER_NO_DIGITS
03876 3. A number must not have more than 16 digits.
03877    BAD_NUMBER_MORE_THAN_16_DIGITS
03878 4. The exponent of a number must have 1, 2, or 3 digits.
03879    BAD_E_NUMBER_EXPONENT_MUST_HAVE_ONE_TWO_OR_THREE_DIGITS
03880 
03881 Reference pages: (33 - 34)
03882 
03883 In natural language, the definition of a number is: An optional sign
03884 followed by one to sixteen digits (optionally with a decimal point
03885 before the digits, between two digits, or after the last digit)
03886 followed optionally by an exponent. An exponent is an upper case E or
03887 a lower case e followed by an optional sign, followed by one, two, or
03888 three digits.  This definition is given in the spec on page 33 in
03889 natural language and on page 34 using a production language.
03890 
03891 This parses all numbers as doubles. If a number is required to be an
03892 integer by the syntax of command XXX, the makeXXX function checks that
03893 it has the value of an integer.
03894 
03895 When this starts up, _arrayIndex is set to indicate the first character
03896 of what should be a number (a plus or minus sign, a digit, or a
03897 decimal point). When this finishes, _arrayIndex is set to indicate the
03898 last character that could be part of the number.
03899 
03900 The parsed number is placed in the store argument.
03901 
03902 */
03903 double ippCommandParser::getValue(int index) const
03904 {
03905   IPP_ASSERT(index >=0 && index<=_argDoubles.size());
03906   IPP_ASSERT(_argTypes[index] == ARGDOUBLE || _argTypes[index] == ARGIJK  || _argTypes[index] == ARGPARENDOUBLE);
03907   return _argDoubles[index];
03908 }
03909 
03910 void ippCommandParser::parseNumber(ippArgItemType argType)
03911 {
03912   IPP_ASSERT(argType == ARGDOUBLE || argType == ARGIJK);
03913   IPP_ASSERT_MSG(_errorCode == OK,"Parser in error state !");
03914 
03915   int sign = 0; // set to 1 if first character is '+' or '-'
03916   int dot = 0;  // set to 1 if a decimal point is found
03917   int k;        // index for _inputArray
03918   int j;        // counts digits of exponent
03919   char save;
03920 
03921   if ((_inputArray[_arrayIndex] == '-') || (_inputArray[_arrayIndex] == '+')) {
03922     sign = 1;
03923   }
03924 
03925   for (k = (_arrayIndex + sign);((_errorCode == OK) &&((_inputArray[k] == '.') || ((_inputArray[k] > 47) && (_inputArray[k] < 58)))); k++) {
03926     if (_inputArray[k] == '.') {
03927       if (dot == 0) {
03928         dot = 1;
03929       } else {
03930         _errorCode = BAD_NUMBER_TWO_DECIMAL_POINTS;
03931       }
03932     }   
03933   }
03934 
03935   if ((_errorCode == OK) && ((_arrayIndex + sign + dot) == k)) {
03936     _errorCode = BAD_NUMBER_NO_DIGITS;
03937   }
03938   if ((_errorCode == OK) && ((k - (_arrayIndex + sign + dot)) > 16)) {
03939     _errorCode = BAD_NUMBER_MORE_THAN_16_DIGITS;
03940   }
03941   if ((_errorCode == OK) && ((_inputArray[k] == 'E') || (_inputArray[k] == 'e'))) {
03942     k++;
03943     if ((_inputArray[k] == '+') || (_inputArray[k] == '-')) {
03944       k++;
03945     }
03946     for (j = 0; ((_inputArray[k] > 47) && (_inputArray[k] < 58)); j++) {
03947       k++;
03948     }
03949     if ((j < 1) || (j > 3)) {
03950       _errorCode = BAD_E_NUMBER_EXPONENT_MUST_HAVE_ONE_TWO_OR_THREE_DIGITS;
03951     }
03952   }
03953 
03954   if (_errorCode == OK) {
03955    save = _inputArray[k];
03956    _inputArray[k] = 0; //put in temporary null terminator
03957    double value =0;
03958    sscanf((_inputArray + _arrayIndex), "%lf", &value);
03959 
03960    if (_argCount +3 >= _argSize) {
03961         makeArraysBigger();
03962    }
03963 
03964    IPP_ASSERT(_argDoubles.size() > _argCount);
03965    IPP_ASSERT(_argTypes.size()   > _argCount);
03966 
03967    _argDoubles[_argCount] = value;
03968    _argTypes[_argCount]= argType;
03969    
03970    _inputArray[k] = save; // put char back
03971    _arrayIndex = (k - 1); // set _arrayIndex to end of number
03972   }
03973 }
03974 
03975 /*******************************************************************/
03976 
03977 /* ippCommandParser::parseString
03978 
03979 Returned Value: None.
03980 
03981 Called By: ippCommandParser::parseCmdArguments
03982 
03983 Rules:
03984 1. There must be a terminating double-quote (ASCII 34), and all characters
03985    between the double quotes must be in the range ASCII 32 to 126.
03986    BAD_STRING
03987 2. A string must have at least one character in it.
03988    BAD_STRING
03989 
03990 Reference pages: 10 (33) 34 35 43 46 66 73 99 102 106 107 108 109
03991 These references are only those where string is the data type of a
03992 component of a command or a response. The word string is used in other
03993 places to refer to an entire command or response.
03994 
03995 A String starts with a double quote (ASCII 34) and ends at the
03996 next double quote. A double quote cannot be inside a string.
03997 When this function starts, _arrayIndex is indicating the opening
03998 double quote.
03999 
04000 */
04001 
04002 void ippCommandParser::parseString()
04003 {
04004   int start;
04005   char c;
04006 
04007   _arrayIndex++; // skip starting quote
04008   
04009   start = _arrayIndex;
04010 
04011   for (; ((c = _inputArray[_arrayIndex]) != 34); _arrayIndex++){
04012     if ((c < 32) || (c > 126)) {
04013       _errorCode = BAD_STRING;
04014       break;
04015     }
04016   }
04017   if (start == _arrayIndex) {
04018     _errorCode = BAD_STRING;
04019   }
04020   if (_errorCode == OK) {
04021       _inputArray[_arrayIndex] = 0; // set temporary null terminator
04022       _argStrings[_argCount] = _inputArray + start; // hook copy in
04023       _inputArray[_arrayIndex] = 34; // restore quote at end
04024       _argTypes[_argCount] = ARGSTRING;
04025   }
04026 }
04027 
04028 /*******************************************************************/
04029 
04030 /* ippCommandParser::parseTag
04031 
04032 Returned Value: None.
04033 
04034 Called By: ippCommandParser::parseCommand
04035 
04036 Rules:
04037 1. A _tag must have five characters, the first of which is a digit or E,
04038    and the rest of which are digits.
04039    BAD_TAG_CHARACTER
04040 2. The sixth input character (which should follow the last _tag character)
04041    must be a space.
04042    SPACE_MISSING_AFTER_TAG
04043 3. If the first character is a digit, the number formed by the five digits
04044    must be in the range 1 - 99999. Since there are only five digits,
04045    the upper limit does not need testing, so the only check is for 0.
04046    TAG_NUMBER_OUT_OF_RANGE_FOR_COMMAND_TAG
04047 4. If the first character is E, the number formed by the four digits must
04048    be in the range 1 - 9999. Since there are only four digits, the upper
04049    limit does not need checking, so the only check is for 0.
04050    TAG_NUMBER_OUT_OF_RANGE_FOR_EVENT_TAG
04051 
04052 Reference pages: (21) (22) 26-30 (34-42) (47) (49) (50) (75) (77) 99-113
04053 
04054 There should be a _tag at the beginning of the _inputArray. This function
04055 reads that _tag.
04056 
04057 In responses, the event _tag E0000 is allowed, but this is a command parser,
04058 so it is not allowed here.
04059 
04060 */
04061 
04062 
04063 void ippCommandParser::parseTag()
04064 {
04065   _errorCode = OK;
04066   if ((_inputArray[1] < 48) ||
04067       (_inputArray[1] > 57) ||
04068       (_inputArray[2] < 48) ||
04069       (_inputArray[2] > 57) ||
04070       (_inputArray[3] < 48) ||
04071       (_inputArray[3] > 57) ||
04072       (_inputArray[4] < 48) ||
04073       (_inputArray[4] > 57)) {
04074 
04075     _errorCode = BAD_TAG_CHARACTER;
04076 
04077 
04078   }  else if (_inputArray[5] != 32) {
04079 
04080     _errorCode = SPACE_MISSING_AFTER_TAG;
04081 
04082   } else if (_inputArray[0] == 'E') {
04083     
04084     _isEvent = true;
04085     sscanf((_inputArray + 1), "%d", &_tag);
04086     if (_tag == 0) {
04087       _errorCode = TAG_NUMBER_OUT_OF_RANGE_FOR_EVENT_TAG;
04088     }
04089 
04090   } else if ( isdigit(_inputArray[0]) ) {
04091     
04092     _isEvent = false;
04093     sscanf(_inputArray, "%d", &_tag);
04094     if (_tag == 0) {
04095       _errorCode = TAG_NUMBER_OUT_OF_RANGE_FOR_COMMAND_TAG;
04096     }
04097   
04098   } else {
04099     _errorCode = BAD_TAG_CHARACTER;
04100   }
04101 }
04102 
04103 /*******************************************************************/
04104 
04105 /* ippCommandParser::parseIJK
04106 
04107 Returned Value: None.
04108 
04109 Called By: ippCommandParser::parseCmdArguments
04110 
04111 Rules:
04112 1. A comma must follow the first and second numbers.
04113    BAD_IJK_NUMBERS
04114 2. Each of the three numbers must start with a plus sign, minus
04115    sign, decimal point, or digit.
04116    BAD_IJK_NUMBERS
04117 3. The third number must be followed by a right parenthesis.
04118    BAD_IJK_NUMBERS
04119 
04120 Reference pages: 27 28 (49) (52 - 53) (61) (62) (78) (81) 103 104
04121 These reference pages include all uses of IJK, not just the use
04122 that is is parsed by this function.
04123 
04124 This is called only if arguments are being parsed, a left parenthesis
04125 has been found, the keyword IJK precedes the left parenthesis, and the
04126 character after the left parenthesis could be part of a number. Three
04127 numbers separated by commas and followed by a right parenthesis are
04128 expected.  The numbers are placed in the _argDoubles array.
04129 
04130 When this starts, _arrayIndex is set to indicate the beginning of the
04131 first number. When this finishes, _arrayIndex is set to indicate the
04132 closing right parenthesis.
04133 
04134 */
04135 
04136 void ippCommandParser::parseData()
04137 {
04138   char c;
04139   int n =0;
04140   while(_errorCode == OK) {
04141     if (_inputArray[_arrayIndex+1] == ')') { 
04142       _argCount--;
04143       break;
04144     }
04145     if (n > 0) {
04146       _arrayIndex++;
04147       if (_inputArray[_arrayIndex] != ',') {
04148         _errorCode = BAD_IJK_NUMBERS;
04149         break;
04150       } else {
04151         _arrayIndex++;
04152       }
04153     }
04154    
04155     c = _inputArray[_arrayIndex];
04156     if ((c == '-') || (c == '+') ||(c == '.') || isdigit(c)) {
04157       parseNumber(ARGIJK);
04158       //xx _argTypes[_argCount] = ARGIJK;
04159       _argCount++;
04160     } else{
04161       _errorCode = BAD_IJK_NUMBERS;
04162       break;
04163     }
04164     n++;
04165   } // end while
04166 
04167   if (_errorCode == OK) {
04168     _arrayIndex++;
04169     if (_inputArray[_arrayIndex] != ')') {
04170       _errorCode = BAD_IJK_NUMBERS;
04171     }
04172   }
04173 
04174 
04175 }
04176 
04177 
04214 bool UnSpaceInputArray(char* _inputArray,int start)
04215 {
04216   bool result =true;
04217   char c;
04218   int n;
04219   int gap = 0;
04220   bool stringing = false;
04221   bool spaceBefore = false;
04222   bool puncBefore = false;
04223 
04224   for (n = start; _inputArray[n-1] != NULL; n++){
04225    
04226     c = _inputArray[n];
04227     if (stringing){
04228       if (c == '"') { stringing = false; }
04229     }  else if (c == ' ') {
04230       gap++;
04231       if (!puncBefore) {spaceBefore = true;}
04232       continue;
04233     } else if (spaceBefore) {
04234       
04235       if ((c == '(') || (c == ')') || (c == ',')) {
04236         spaceBefore = false;
04237         puncBefore = true;
04238       } else {
04239         result = false;
04240         break;
04241       }
04242     } else if ((c == '(') || (c == ')') || (c == ',')) {
04243        puncBefore = true; 
04244     } else {
04245       puncBefore = false;
04246       if (c == '"') {
04247          stringing = true;
04248       }
04249     }
04250     _inputArray[n - gap] = c;
04251   }
04252   return result;
04253 
04254 }
04255 
04256 void ippCommandParser::unSpaceInputArray()
04257 {
04258   if(!::UnSpaceInputArray(_inputArray,6)) {
04259     _errorCode =ILLEGAL_SPACE;
04260   }
04261 }

Generated on Wed Nov 8 00:20:05 2006 for IPPDME by  doxygen 1.4.1