testexecmgmt/ucc/Source/Uccs.v2/Core/UCCS_CCommandDecoder.cpp
changeset 0 3da2a79470a7
equal deleted inserted replaced
-1:000000000000 0:3da2a79470a7
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 * Filename: UCCS_CCommandDecoder.cpp
       
    16 * System Includes
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 
       
    22 #include <stdio.h>
       
    23 #include <string.h>
       
    24 #include <time.h>
       
    25 #include <stdlib.h>
       
    26 #include <iostream.h>
       
    27 #include <assert.h>
       
    28 #include <STDDEF.H>
       
    29 #include <sys/types.h>
       
    30 #include <sys/stat.h>
       
    31 #include <ctype.h>
       
    32 
       
    33 /***********************************************************************************
       
    34  *
       
    35  * Local Includes
       
    36  *
       
    37  **********************************************************************************/
       
    38 #include "UCCS_CCommandDecoder.h"
       
    39 
       
    40 
       
    41 /***********************************************************************************
       
    42  *
       
    43  * Macro Functions
       
    44  *
       
    45  **********************************************************************************/
       
    46 #define IS_WHITESPACE(c)				((c == '\t')||(c == ' ')||(c == '\n'))
       
    47 #define NOT_IS_WHITESPACE_OR_TERM(c)	((IS_WHITESPACE(c) == 0)&&(c != 0))
       
    48 #define IS_NAME_CHAR(c)					(isdigit(c)||isalpha(c)||(c == '_'))
       
    49 
       
    50 /***********************************************************************************
       
    51  *
       
    52  * Definitions
       
    53  *
       
    54  **********************************************************************************/
       
    55 #define TA_FILENAME			1
       
    56 #define TA_ASSIGNEDVALUE	2
       
    57 #define TA_INTEGERLITERAL	4
       
    58 #define TA_STRINGLITERAL	8
       
    59 
       
    60 //--------------------------------------------------------------------------------------------------
       
    61 //
       
    62 // Construction
       
    63 //
       
    64 //--------------------------------------------------------------------------------------------------
       
    65 CCommandDecoder::CCommandDecoder( CDataRecord *aEnvironment )
       
    66 {
       
    67 	iEnvironment = aEnvironment;
       
    68 	iLastReply = NULL;
       
    69 }
       
    70 
       
    71 CCommandDecoder::~CCommandDecoder()
       
    72 {
       
    73 }
       
    74 
       
    75 
       
    76 //--------------------------------------------------------------------------------------------------
       
    77 //
       
    78 // Parse commands here and store as a list of field descriptions 
       
    79 //
       
    80 //--------------------------------------------------------------------------------------------------
       
    81 int CCommandDecoder::ParseCommand( char* aCommandstring, TFieldDesc *aFieldList, int aListLength )
       
    82 {
       
    83 	char *start_name;
       
    84 	char *start_value;
       
    85 	int element_attributes;
       
    86 	char *end_value;
       
    87 	int i;
       
    88 	int err;
       
    89 
       
    90 	// if the command string is null then there is nothing to do
       
    91 	if( aCommandstring == NULL ) 
       
    92 		return UCCS_OK;
       
    93 
       
    94 	// process the entire string
       
    95 	start_name = aCommandstring;
       
    96 	for( i = 0; (i < aListLength) && (*start_name != 0); i++ ) {
       
    97 
       
    98 		// init the vars
       
    99 		element_attributes = 0;
       
   100 
       
   101 		// skip over any whitespace to the next start
       
   102 		for( start_name; IS_WHITESPACE(*start_name); start_name++ )
       
   103 			;
       
   104 
       
   105 		// if we are at NULL then exit
       
   106 		if( *start_name == 0 ) {
       
   107 			continue;
       
   108 		}
       
   109 
       
   110 		// if the character is not alpha then exit
       
   111 		if( isalpha(*start_name) == 0 ) {
       
   112 			return UCCS_PARSERFAILEDTOSTOREVALUE;
       
   113 		}
       
   114 
       
   115 		// otherwise this is the start of the token, look for the '=', only alpha, digit, and '_'
       
   116 		// characters are allowed in names
       
   117 		for( start_value = start_name; (start_value != NULL) && IS_NAME_CHAR(*start_value); start_value++ )
       
   118 			;
       
   119 		if( start_value == NULL ) {
       
   120 			break;
       
   121 		}
       
   122 		if( *start_value != '=' ) {
       
   123 			return UCCS_PARSERFAILEDTOSTOREVALUE;
       
   124 		}
       
   125 		*start_value = 0;
       
   126 		start_value++;
       
   127 
       
   128 		// if the character at start_value is alpha then this is an assigned value
       
   129 		if( isalpha(*start_value) ) {
       
   130 			element_attributes |= TA_ASSIGNEDVALUE;
       
   131 		}
       
   132 
       
   133 		// if the character at the start is numeric then this is an integer literal
       
   134 		if( isdigit(*start_value) ) {
       
   135 			element_attributes |= TA_INTEGERLITERAL;
       
   136 		}
       
   137 
       
   138 		// if the character at the start is '"' then this is a string literal
       
   139 		if( *start_value == '"' ) {
       
   140 			element_attributes |= TA_STRINGLITERAL;
       
   141 		}
       
   142 
       
   143 		// if the character is whitespace then this is an error
       
   144 		if( IS_WHITESPACE(*start_value) ) {
       
   145 			return UCCS_PARSERFAILEDTOSTOREVALUE;
       
   146 		}
       
   147 
       
   148 		// if the character at start_value is '"' then this is a string literal that may include
       
   149 		// whitespace and escaped '\' and '"' characters. At the end of this the start_value should
       
   150 		// point to a null terminated string that is what we want
       
   151 		if( *start_value == '"' ) {
       
   152 			end_value = FindEndOfDoubleQuotes( start_value );
       
   153 			if( end_value == NULL ) {
       
   154 				continue;
       
   155 			}
       
   156 			start_value++;
       
   157 		} else {
       
   158 			end_value = start_value;
       
   159 			for( end_value; NOT_IS_WHITESPACE_OR_TERM(*end_value); end_value++ )
       
   160 				;
       
   161 		}
       
   162 
       
   163 		// terminate the value
       
   164 		*end_value = 0;
       
   165 
       
   166 		// remove the escape sequences - eg. \" to "
       
   167 		if(DecodeEscapeSequences(start_value)) {
       
   168             Cleanup( aFieldList, aListLength );
       
   169             return UCCS_PARSERFAILEDTOSTOREVALUE;
       
   170         }
       
   171 
       
   172 		// save the new value
       
   173 		err = StoreNextValue( start_name, start_value, element_attributes, aFieldList, i );
       
   174 		if( err != 0 ) {
       
   175 			Cleanup( aFieldList, aListLength );
       
   176 			return UCCS_PARSERFAILEDTOSTOREVALUE;
       
   177 		}
       
   178 
       
   179 		// now move to the next potential token
       
   180 		start_name = end_value + 1;
       
   181 	}
       
   182 
       
   183 	// done
       
   184 	return UCCS_OK;
       
   185 }
       
   186 
       
   187 
       
   188 //--------------------------------------------------------------------------------------------------
       
   189 //
       
   190 // Parse commands here and store as a data record
       
   191 //
       
   192 //--------------------------------------------------------------------------------------------------
       
   193 int CCommandDecoder::ParseCommandToRecord( char *aCommandstring, CDataRecord *aRecord )
       
   194 {
       
   195 	int err;
       
   196 	int i;
       
   197 	TFieldDesc iFieldList[MAXFIELDCOUNT];
       
   198 
       
   199 	// Check params 
       
   200 	assert( aRecord != NULL );
       
   201 
       
   202 	// clear the field descriptions
       
   203 	memset( iFieldList, 0, sizeof(TFieldDesc)*MAXFIELDCOUNT );
       
   204 
       
   205 	// Parse the command into buffers
       
   206 	err = ParseCommand( aCommandstring, iFieldList, MAXFIELDCOUNT );
       
   207 	if( err != UCCS_OK ) {
       
   208 		return err;
       
   209 	}
       
   210 
       
   211 	// Now add all the fields to the record	
       
   212 	for( i = 0; (iFieldList[i].iName != NULL) && (i < MAXFIELDCOUNT); i++ ) {
       
   213 		if( iFieldList[i].iLength == 0 ) {
       
   214 			err = aRecord->NewField( iFieldList[i].iName, iFieldList[i].iValue );
       
   215 			assert( err == UCCS_OK );
       
   216 		} else {
       
   217 			err = aRecord->NewField( iFieldList[i].iName, iFieldList[i].iValue, iFieldList[i].iLength );
       
   218 			assert( err == UCCS_OK );
       
   219 		}
       
   220 		free( iFieldList[i].iName );
       
   221 		free( iFieldList[i].iValue );
       
   222 		iFieldList[i].iName = 0;
       
   223 		iFieldList[i].iValue = 0;
       
   224 		iFieldList[i].iLength = 0;
       
   225 	}
       
   226 
       
   227 	//done
       
   228 	return UCCS_OK;
       
   229 }
       
   230 
       
   231 
       
   232 /***********************************************************************************
       
   233  *
       
   234  * PUBLIC METHOD: SetLastReply - set the last reply to be used in parsing
       
   235  *
       
   236  **********************************************************************************/
       
   237 void CCommandDecoder::SetLastReply( CDataRecord *aLastReply )
       
   238 {
       
   239 	iLastReply = aLastReply;
       
   240 }
       
   241 
       
   242 
       
   243 //--------------------------------------------------------------------------------------------------
       
   244 //
       
   245 // PRIVATE METHODS
       
   246 //
       
   247 //--------------------------------------------------------------------------------------------------
       
   248 
       
   249 //--------------------------------------------------------------------------------------------------
       
   250 //
       
   251 // Store the value
       
   252 //
       
   253 //--------------------------------------------------------------------------------------------------
       
   254 int CCommandDecoder::StoreNextValue( char *aName, char *aValue, int aAttributes, TFieldDesc *aFieldList, int aIndex )
       
   255 {
       
   256 	int namelength;
       
   257 	int valuelength;
       
   258 //	int filesize;
       
   259 	int err;
       
   260 	int variable_found = 0;
       
   261 	char *aAssignedValue;
       
   262 
       
   263 	// check params
       
   264 	assert( aName != NULL );
       
   265 	assert( aValue != NULL );
       
   266 	assert( aFieldList != NULL );
       
   267 	assert( aFieldList[aIndex].iName == NULL );
       
   268 	assert( aFieldList[aIndex].iValue == NULL );
       
   269 
       
   270 	// store the name
       
   271 	_strupr( aName );
       
   272 	namelength = strlen( aName );
       
   273 	(aFieldList[aIndex].iName) = (char*)malloc( namelength + 1 );
       
   274 	assert( (aFieldList[aIndex].iName) != NULL );
       
   275 	strcpy( (aFieldList[aIndex].iName), aName );
       
   276 
       
   277 	// if the assigned values attribute is set then we: value = environment[value'] -- value = lastreply[value']
       
   278 	if( aAttributes & TA_ASSIGNEDVALUE ) {
       
   279 
       
   280 		// change the variable name to upper case to remove all case sensitivity
       
   281 		_strupr( aValue );
       
   282 
       
   283 		// look in the environment first
       
   284 		if( iEnvironment != NULL ) {
       
   285 			err = iEnvironment->GetFieldAsString( aValue, &aAssignedValue );
       
   286 			if( err == UCCS_OK ) {
       
   287 				aValue = aAssignedValue;
       
   288 				variable_found = 1;
       
   289 			}
       
   290 		}
       
   291 
       
   292 		// look in the last reply
       
   293 		if( (iLastReply != NULL) && (variable_found == 0) ) {
       
   294 			err = iLastReply->GetFieldAsString( aValue, &aAssignedValue );
       
   295 			if( err == UCCS_OK ) {
       
   296 				aValue = aAssignedValue;
       
   297 				variable_found = 1;
       
   298 			}
       
   299 		}
       
   300 
       
   301 		// if variable wasn't found then return error
       
   302 		if( variable_found == 0 ) {
       
   303 			return -1;
       
   304 		}
       
   305 	}
       
   306 
       
   307 	// store non-file values 
       
   308 	if( (aAttributes & TA_FILENAME) == 0 ) {
       
   309 		valuelength = strlen( aValue );
       
   310 		(aFieldList[aIndex].iValue) = (char*)malloc( valuelength + 1 );
       
   311 		assert( (aFieldList[aIndex].iValue) != NULL );
       
   312 		strcpy( (aFieldList[aIndex].iValue), aValue );
       
   313 	}
       
   314 
       
   315 	// store file value
       
   316 #ifdef OLDSTYLE
       
   317 	if( aAttributes & TA_FILENAME ) {
       
   318 
       
   319 		// get the size of the file
       
   320 		filesize = GetFileSize( aValue );
       
   321 		if( filesize == -1 ) {
       
   322 			free( (aFieldList[aIndex].iName) );
       
   323 			(aFieldList[aIndex].iName) = NULL;
       
   324 			return -1;
       
   325 		}
       
   326 
       
   327 		// allocate the memory to hold the file
       
   328 		(aFieldList[aIndex].iValue) = (char*)malloc( filesize );
       
   329 		assert( (aFieldList[aIndex].iValue) != NULL );
       
   330 
       
   331 		// set the size
       
   332 		aFieldList[aIndex].iLength = filesize;
       
   333 
       
   334 		// read the file into memory
       
   335 		err = ReadFileIntoBuffer( aValue, (aFieldList[aIndex].iValue), filesize );
       
   336 		if( err != 0 ) {
       
   337 			free( (aFieldList[aIndex].iName) );
       
   338 			(aFieldList[aIndex].iName) = NULL;
       
   339 			free( (aFieldList[aIndex].iValue) );
       
   340 			(aFieldList[aIndex].iValue) = NULL;
       
   341 			return -1;
       
   342 		}
       
   343 	}
       
   344 #endif
       
   345 
       
   346 	// done
       
   347 	return 0;
       
   348 }
       
   349 
       
   350 
       
   351 //--------------------------------------------------------------------------------------------------
       
   352 //
       
   353 // FindEndOfDoubleQuotes -- given a string starting with '"' it returns a pointer to the character
       
   354 // matching '"'. It deals with escaped chars.
       
   355 //
       
   356 //--------------------------------------------------------------------------------------------------
       
   357 char *CCommandDecoder::FindEndOfDoubleQuotes( char *aString )
       
   358 {
       
   359 	char *str;
       
   360 
       
   361 	// the first char MUST be '"'
       
   362 	if( aString[0] != '"' ) {
       
   363 		return NULL;
       
   364 	}
       
   365 
       
   366 	// now look for a non-escaped '"'
       
   367 	str = aString + 1;
       
   368 	while( 1 ) {
       
   369 		str = strchr( str, '"' );
       
   370 		if( str == NULL ) {
       
   371 			return NULL;
       
   372 		}
       
   373 		if( str[-1] != '\\' ) {
       
   374 			return str;
       
   375 		}
       
   376 		str++;
       
   377 	}
       
   378 
       
   379 	// done
       
   380 	assert( !"INVALID CODE PATH" );
       
   381 	return NULL;
       
   382 }
       
   383 //--------------------------------------------------------------------------------------------------
       
   384 
       
   385 
       
   386 //--------------------------------------------------------------------------------------------------
       
   387 //
       
   388 // GetFileSize -- return the size of a file
       
   389 //
       
   390 //--------------------------------------------------------------------------------------------------
       
   391 int CCommandDecoder::GetFileSize( char *aFilename )
       
   392 {
       
   393 	struct _stat sinfo;
       
   394 	int err;
       
   395 	err = _stat( aFilename, &sinfo );
       
   396 	if( err != 0 ) {
       
   397 		return -1;
       
   398 	}
       
   399 	return sinfo.st_size;
       
   400 }
       
   401 
       
   402 
       
   403 //--------------------------------------------------------------------------------------------------
       
   404 //
       
   405 // GetFileSize -- return the size of a file
       
   406 //
       
   407 //--------------------------------------------------------------------------------------------------
       
   408 int CCommandDecoder::ReadFileIntoBuffer( char *aFilename, char *aBuff, int aBuffSize )
       
   409 {
       
   410 	FILE *fp;
       
   411 	int err;
       
   412 	int i;
       
   413 
       
   414 	// open the file
       
   415 	fp = fopen( aFilename, "rb" );
       
   416 	if( fp == NULL ) {
       
   417 		return -1;
       
   418 	}
       
   419 
       
   420 	// read in the bytes
       
   421 	for( i = 0; i < aBuffSize; i++ ) {
       
   422 		err = fread( &(aBuff[i]), 1, 1, fp );
       
   423 		if( err != 1 ) {
       
   424 			fclose( fp );
       
   425 			return -1;
       
   426 		}
       
   427 	}
       
   428 
       
   429 	// done
       
   430 	fclose( fp );
       
   431 	return 0;
       
   432 }
       
   433 
       
   434 
       
   435 //--------------------------------------------------------------------------------------------------
       
   436 //
       
   437 // Cleanup
       
   438 //
       
   439 //--------------------------------------------------------------------------------------------------
       
   440 void CCommandDecoder::Cleanup( TFieldDesc *aFieldList, int aLen )
       
   441 {
       
   442 	int i;
       
   443 	for( i = 0; i < aLen; i++ ) {
       
   444 		if( (aFieldList[i].iName) != NULL ) {
       
   445 			free( (aFieldList[i].iName) );
       
   446 			(aFieldList[i].iName) = NULL;
       
   447 		}
       
   448 		if( (aFieldList[i].iValue) != NULL ) {
       
   449 			free( (aFieldList[i].iName) );
       
   450 			(aFieldList[i].iName) = NULL;
       
   451 		}
       
   452 	}
       
   453 }
       
   454 
       
   455 
       
   456 //--------------------------------------------------------------------------------------------------
       
   457 //
       
   458 // DecodeEscapeSequences - change \" to " and \\ to \
       
   459 //
       
   460 //--------------------------------------------------------------------------------------------------
       
   461 // decode escape sequence
       
   462 // - deliberately chose not to use sscanf's parser; more complicated, performance overhead, & requirement for a seperate string
       
   463 int CCommandDecoder::DecodeEscapeSequences(char *start_value)
       
   464 {
       
   465 	int result = 0, read_pos = 0, write_pos = 0;
       
   466 
       
   467 	// remove the escape char
       
   468 	while (start_value[read_pos] != 0)
       
   469     {
       
   470 		if (start_value[read_pos++] == '\\') 
       
   471         {
       
   472             char decodedChar = 0;
       
   473             switch (start_value[read_pos++]) 
       
   474             {
       
   475             case 'a':  decodedChar = '\a'; break;
       
   476             case 'b':  decodedChar = '\b'; break;
       
   477             case 'f':  decodedChar = '\f'; break;
       
   478             case 'n':  decodedChar = '\n'; break;
       
   479             case 'r':  decodedChar = '\r'; break;
       
   480             case 't':  decodedChar = '\t'; break;
       
   481             case 'v':  decodedChar = '\v'; break;
       
   482             case '\\': decodedChar = '\\'; break;
       
   483             case '?':  decodedChar = '\?'; break;
       
   484             case '\'': decodedChar = '\''; break;
       
   485             case '\"': decodedChar = '\"'; break;
       
   486             // case '\x"': decodedChar = '\"'; break; - not supported, since this could overrun the char array
       
   487             // case '\o"': decodedChar = '\"'; break; - not supported, functionality not needed
       
   488             default:
       
   489                 // unknown
       
   490                 result = -1;
       
   491                 return result;
       
   492             }
       
   493             start_value[write_pos++] = decodedChar;
       
   494         }
       
   495         else
       
   496 			start_value[write_pos++] = start_value[read_pos - 1];
       
   497 	}
       
   498 
       
   499 	// re-insert the null char
       
   500 	start_value[write_pos] = 0;
       
   501 
       
   502     return result;
       
   503 }