core/src/script_command.cpp
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // script_command.cpp
       
     2 // 
       
     3 // Copyright (c) 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "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 // Accenture - Initial contribution
       
    11 //
       
    12 #include "script_command.h"
       
    13 #include "fshell.h" // For KScriptArgCount etc
       
    14 #include <fshell/descriptorutils.h>
       
    15 
       
    16 using namespace IoUtils;
       
    17 using namespace LtkUtils;
       
    18 
       
    19 CScriptCommand* CScriptCommand::NewLC(const TDesC& aScriptPath, TIoHandleSet& aIoHandles)
       
    20 	{
       
    21 	CScriptCommand* self = new(ELeave) CScriptCommand;
       
    22 	CleanupStack::PushL(self);
       
    23 	self->ConstructL(aScriptPath, aIoHandles);
       
    24 	return self;
       
    25 	}
       
    26 
       
    27 const TDesC& CScriptCommand::Name() const
       
    28 	{
       
    29 	return iName;
       
    30 	}
       
    31 
       
    32 void CScriptCommand::DoRunL()
       
    33 	{
       
    34 	// Never actually runs
       
    35 	__DEBUGGER();
       
    36 	}
       
    37 
       
    38 CScriptCommand::CScriptCommand()
       
    39 	: CCommandBase()
       
    40 	{
       
    41 	}
       
    42 
       
    43 void CScriptCommand::ConstructL(const TDesC& aScriptPath, TIoHandleSet& aIoHandles)
       
    44 	{
       
    45 	BaseConstructL();
       
    46 
       
    47 	// Duplicate some handles in case we need to display the script's help text.
       
    48 	IoSession().SetHandle(aIoHandles.IoSession().Handle());
       
    49 	User::LeaveIfError(IoSession().Duplicate(RThread(), EOwnerThread));
       
    50 	Stdout().CreateL(IoSession());
       
    51 	Stdout().Duplicate(aIoHandles.Stdout());
       
    52 	Stderr().CreateL(IoSession());
       
    53 	Stderr().Duplicate(aIoHandles.Stderr());
       
    54 	
       
    55 	iScriptPath = aScriptPath.AllocL();
       
    56 	iName.Set(TParsePtrC(*iScriptPath).NameAndExt());
       
    57 	RFs fs; // Can't use FsL(), that needs an env set up
       
    58 	CleanupClosePushL(fs);
       
    59 	User::LeaveIfError(fs.Connect());
       
    60 
       
    61 	iOwnedCif = CCommandInfoFile::NewL(fs, *iScriptPath); // A script file is also its own cif
       
    62 
       
    63 	if (iOwnedCif->Name().Length() == 0)
       
    64 		{
       
    65 		// No cif data - fall back to just creating a basic array of args (for converting into $1 $2 etc)
       
    66 		iArguments.AppendStringL(iNonCifScriptArguments, _L("args"), _L("Arguments for the script. These are converted to the environment variables C<$1>, C<$2> etc."), KValueTypeFlagOptional);
       
    67 		delete iOwnedCif;
       
    68 		iOwnedCif = NULL;
       
    69 		}
       
    70 	else
       
    71 		{
       
    72 		SetCif(*iOwnedCif); // SetCif doesn't take ownership (which is what iOwnedCif is for)
       
    73 
       
    74 		// Now go through and make up "member variables" to correspond to everything in the CIF so we can fool CCommandBase into
       
    75 		// doing the parsing work for us
       
    76 		const TInt argCount = iOwnedCif->Arguments().Count();
       
    77 		for (TInt i = 0; i < argCount; i++)
       
    78 			{
       
    79 			SetupArgumentL(iOwnedCif->Arguments()[i]);
       
    80 			}
       
    81 		
       
    82 		const TInt optCount = iOwnedCif->Options().Count();
       
    83 		for (TInt i = 0; i < optCount; i++)
       
    84 			{
       
    85 			const TCommandOption& opt = iOwnedCif->Options()[i];
       
    86 			SetupOptionL(opt);
       
    87 			}
       
    88 
       
    89 		iOwnedCif->AssignL(iArguments, iOptions);
       
    90 		}
       
    91 
       
    92 	iOptions.AppendBoolL(iDisplayHelp, 'h', _L("help"), _L("Display help.")); // Always support --help (cannot do this before the call to CCommandInfoFile::AssignL())
       
    93 
       
    94 	// Our argument data structures should now be fully constructed
       
    95 	CleanupStack::PopAndDestroy(&fs);
       
    96 	}
       
    97 
       
    98 TInt StorageSizeForType(TUint aType)
       
    99 	{
       
   100 	TInt size = sizeof(TInt);
       
   101 	switch (aType)
       
   102 		{
       
   103 		case KValueTypeReal:
       
   104 			size = sizeof(TReal); break;
       
   105 		case KValueTypeFileName:
       
   106 			size = sizeof(TFileName2); break;
       
   107 		case KValueTypeUint64:
       
   108 		case KValueTypeInt64:
       
   109 			size = sizeof(TInt64); break;
       
   110 		default:
       
   111 			break;
       
   112 		}
       
   113 	return size;
       
   114 	}
       
   115 
       
   116 void CScriptCommand::SetupArgumentL(const TValue& aValue)
       
   117 	{
       
   118 	if (aValue.AcceptsMultiple()) StaticLeaveIfErr(KErrArgument, _L("Arguments with the 'multiple' attribute are not supported for scripts"));
       
   119 
       
   120 	const TUint type = aValue.Type();
       
   121 	void* valptr = User::AllocZL(StorageSizeForType(type));
       
   122 	CleanupStack::PushL(valptr);
       
   123 
       
   124 	TPtrC name = aValue.Name();
       
   125 	switch (type)
       
   126 		{
       
   127 	case KValueTypeInt:
       
   128 		iArguments.AppendIntL(*(TInt*)valptr, name);
       
   129 		break;
       
   130 	case KValueTypeUint:
       
   131 		iArguments.AppendUintL(*(TUint*)valptr, name);
       
   132 		break;
       
   133 	case KValueTypeString:
       
   134 		iArguments.AppendStringL(*(HBufC**)valptr, name);
       
   135 		break;
       
   136 	case KValueTypeFileName:
       
   137 		new (valptr) TFileName2; // We only AllocZL'd, we didn't initialise it
       
   138 		iArguments.AppendFileNameL(*(TFileName2*)valptr, name);
       
   139 		break;
       
   140 	case KValueTypeEnum:
       
   141 		iArguments.AppendEnumL(*(TInt*)valptr, name);
       
   142 		break;
       
   143 	case KValueTypeReal:
       
   144 		iArguments.AppendRealL(*(TReal*)valptr, name);
       
   145 		break;
       
   146 	case KValueTypeUint64:
       
   147 		iArguments.AppendUintL(*(TUint64*)valptr, name);
       
   148 		break;
       
   149 	case KValueTypeInt64:
       
   150 		iArguments.AppendIntL(*(TInt64*)valptr, name);
       
   151 		break;
       
   152 	default:
       
   153 		StaticLeaveIfErr(KErrArgument, _L("Script argument '%S' is of unsupported type %d"), &name, aValue.Type());
       
   154 		break;
       
   155 		}
       
   156 	CleanupStack::Pop(valptr);
       
   157 	}
       
   158 
       
   159 void CScriptCommand::SetupOptionL(const IoUtils::TValue& aValue)
       
   160 	{
       
   161 	if (aValue.AcceptsMultiple()) StaticLeaveIfErr(KErrArgument, _L("Options with the 'multiple' attribute are not supported for scripts"));
       
   162 
       
   163 	const TUint type = aValue.Type();
       
   164 	void* valptr = User::AllocZL(StorageSizeForType(type));
       
   165 	CleanupStack::PushL(valptr);
       
   166 
       
   167 	TPtrC name = aValue.Name();
       
   168 	switch (type)
       
   169 		{
       
   170 	case KValueTypeBool:
       
   171 		iOptions.AppendBoolL(*(TBool*)valptr, name);
       
   172 		break;
       
   173 	case KValueTypeInt:
       
   174 		iOptions.AppendIntL(*(TInt*)valptr, name);
       
   175 		break;
       
   176 	case KValueTypeUint:
       
   177 		iOptions.AppendUintL(*(TUint*)valptr, name);
       
   178 		break;
       
   179 	case KValueTypeString:
       
   180 		iOptions.AppendStringL(*(HBufC**)valptr, name);
       
   181 		break;
       
   182 	case KValueTypeFileName:
       
   183 		new (valptr) TFileName2; // We only AllocZL'd, we didn't initialise it
       
   184 		iOptions.AppendFileNameL(*(TFileName2*)valptr, name);
       
   185 		break;
       
   186 	case KValueTypeEnum:
       
   187 		iOptions.AppendEnumL(*(TInt*)valptr, name);
       
   188 		break;
       
   189 	case KValueTypeReal:
       
   190 		iOptions.AppendRealL(*(TReal*)valptr, name);
       
   191 		break;
       
   192 	case KValueTypeUint64:
       
   193 		iOptions.AppendUintL(*(TUint64*)valptr, name);
       
   194 		break;
       
   195 	case KValueTypeInt64:
       
   196 		iOptions.AppendIntL(*(TInt64*)valptr, name);
       
   197 		break;
       
   198 	default:
       
   199 		StaticLeaveIfErr(KErrArgument, _L("Script argument '%S' is of unsupported type %d"), &name, aValue.Type());
       
   200 		break;
       
   201 		}
       
   202 	CleanupStack::Pop(valptr);
       
   203 	}
       
   204 
       
   205 CScriptCommand::~CScriptCommand()
       
   206 	{
       
   207 	if (iOwnedCif)
       
   208 		{
       
   209 		// We set all these up, we need to delete them
       
   210 		for (TInt i = 0; i < iArguments.Count(); i++)
       
   211 			{
       
   212 			const TCommandArgument& arg = ((const RCommandArgumentList&)iArguments)[i];
       
   213 			if (arg.Type() == KValueTypeString) delete *(HBufC**)arg.ValuePtr();
       
   214 			delete arg.ValuePtr();
       
   215 			}
       
   216 		for (TInt i = 0; i < iOptions.Count(); i++)
       
   217 			{
       
   218 			const TCommandOption& opt = ((const RCommandOptionList&)iOptions)[i];
       
   219 			if (opt.ValuePtr() != &iDisplayHelp)
       
   220 				{
       
   221 				if (opt.Type() == KValueTypeString) delete *(HBufC**)opt.ValuePtr();
       
   222 				delete opt.ValuePtr();
       
   223 				}
       
   224 			}
       
   225 		}
       
   226 
       
   227 	delete iScriptPath;
       
   228 	delete iOwnedCif;
       
   229 	iNonCifScriptArguments.ResetAndDestroy();
       
   230 	Stderr().Close();
       
   231 	Stdout().Close();
       
   232 	IoSession().Close();
       
   233 	}
       
   234 
       
   235 void CScriptCommand::ParseCommandLineArgsL(const TDesC& aArgs, CEnvironment& aEnv, RPointerArray<HBufC>* aAdditionalPrefixArguments)
       
   236 	{
       
   237 	CreateEnvironmentL(&aEnv); // This sets aEnv as our environment. Doesn't copy or take ownership. ParseCommandLineL needs access to the env for things like the escape char setting
       
   238 
       
   239 	if (aAdditionalPrefixArguments && aAdditionalPrefixArguments->Count())
       
   240 		{
       
   241 		// Must be a nicer way of doing this... prefix onto aArgs some args that couldn't possibly require escaping (this way we don't have to worry if anything in aAdditionalPrefixArguments actually does need escaping)
       
   242 		LtkUtils::RLtkBuf argsBuf;
       
   243 		CleanupClosePushL(argsBuf);
       
   244 		TInt c = aAdditionalPrefixArguments->Count();
       
   245 		while (c--)
       
   246 			{
       
   247 			argsBuf.AppendL(_L("placeholder "));
       
   248 			}
       
   249 		argsBuf.AppendL(aArgs);
       
   250 		ParseCommandLineL(argsBuf);
       
   251 		CleanupStack::PopAndDestroy(&argsBuf);
       
   252 		}
       
   253 	else
       
   254 		{
       
   255 		ParseCommandLineL(aArgs);
       
   256 		}	
       
   257 
       
   258 	if (!iArguments.AllSet())
       
   259 		{
       
   260 		User::Leave(KErrArgument);
       
   261 		}
       
   262 
       
   263 	// Everything is filled in now, just have to setup aEnv with the results
       
   264 	TInt argCount = iArguments.Count();
       
   265 	if (iOwnedCif)
       
   266 		{
       
   267 		for (TInt i = 0; i < argCount; i++)
       
   268 			{
       
   269 			const TCommandArgument& arg = ((const RCommandArgumentList&)iArguments)[i];
       
   270 			SetEnvironmentVariableFromValueL(aEnv, arg);
       
   271 			}
       
   272 
       
   273 		// Now check for overrides from aAdditionalPrefixArguments
       
   274 		if (aAdditionalPrefixArguments)
       
   275 			{
       
   276 			for (TInt i = 0; i < aAdditionalPrefixArguments->Count(); i++)
       
   277 				{
       
   278 				const TCommandArgument& arg = ((const RCommandArgumentList&)iArguments)[i]; // This const cast shouldn't be needed, I don't think, to make sure that we use the const operator[]
       
   279 				aEnv.SetL(arg.Name(), *(*aAdditionalPrefixArguments)[i]);
       
   280 				}
       
   281 			}
       
   282 		for (TInt i = 0; i < iOptions.Count(); i++)
       
   283 			{
       
   284 			const TCommandOption& opt = ((const RCommandOptionList&)iOptions)[i];
       
   285 			if (opt.ValuePtr() != &iDisplayHelp) SetEnvironmentVariableFromValueL(aEnv, opt);
       
   286 			}
       
   287 		}
       
   288 	else
       
   289 		{
       
   290 		// Just set $1, $2 etc
       
   291 		argCount = iNonCifScriptArguments.Count();
       
   292 		for (TInt i = 0; i < argCount; i++)
       
   293 			{
       
   294 			TBuf<16> varname;
       
   295 			varname.AppendNum(i+1);
       
   296 			aEnv.SetLocalL(varname);
       
   297 			if (aAdditionalPrefixArguments && i < aAdditionalPrefixArguments->Count())
       
   298 				{
       
   299 				aEnv.SetL(varname, *(*aAdditionalPrefixArguments)[i]);
       
   300 				}
       
   301 			else
       
   302 				{
       
   303 				aEnv.SetL(varname, *iNonCifScriptArguments[i]);
       
   304 				}
       
   305 			}
       
   306 		}
       
   307 
       
   308 	aEnv.SetLocalL(KScriptArgCount);
       
   309 	aEnv.SetL(KScriptArgCount, argCount);
       
   310 	}
       
   311 
       
   312 void CScriptCommand::DisplayScriptHelpL()
       
   313 	{
       
   314 	const CTextBuffer* helpText = GetHelpTextL();
       
   315 	CleanupStack::PushL(const_cast<CTextBuffer*>(helpText));
       
   316 	PageL(*helpText);
       
   317 	CleanupStack::PopAndDestroy(const_cast<CTextBuffer*>(helpText));
       
   318 	}
       
   319 
       
   320 void CScriptCommand::SetEnvironmentVariableFromValueL(IoUtils::CEnvironment& aEnv, const IoUtils::TValue& aValue)
       
   321 	{
       
   322 	const TPtrC name(aValue.Name());
       
   323 	aEnv.SetLocalL(name);
       
   324 	void* valptr = aValue.ValuePtr();
       
   325 
       
   326 	switch (aValue.Type())
       
   327 		{
       
   328 	case KValueTypeBool:
       
   329 		if (*(TBool*)valptr)
       
   330 			{	
       
   331 			aEnv.SetL(name, 1);
       
   332 			}
       
   333 		break;
       
   334 	case KValueTypeInt:
       
   335 		aEnv.SetL(name, *(TInt*)valptr);
       
   336 		break;
       
   337 	case KValueTypeUint:
       
   338 		iTempStr.Num(*(TUint*)valptr, EDecimal);
       
   339 		aEnv.SetL(name, iTempStr);
       
   340 		break;
       
   341 	case KValueTypeString:
       
   342 		{
       
   343 		HBufC* val = *(HBufC**)valptr;
       
   344 		if (val) aEnv.SetL(name, *val);
       
   345 		break;
       
   346 		}
       
   347 	case KValueTypeFileName:
       
   348 		aEnv.SetL(name, *(TFileName2*)valptr);
       
   349 		break;
       
   350 	case KValueTypeEnum:
       
   351 		{
       
   352 		TEnum enumObj(aValue.EnumValueList());
       
   353 		aEnv.SetL(name, enumObj.GetString(*(TInt*)valptr));
       
   354 		break;
       
   355 		}
       
   356 	case KValueTypeReal:
       
   357 		{
       
   358 		_LIT(KRealFormat, "%g");
       
   359 		iTempStr.Format(KRealFormat, *(TReal*)valptr);
       
   360 		aEnv.SetL(name, iTempStr);
       
   361 		break;
       
   362 		}
       
   363 	case KValueTypeUint64:
       
   364 		iTempStr.Num(*(TUint64*)valptr, EDecimal);
       
   365 		aEnv.SetL(name, iTempStr);
       
   366 		break;
       
   367 	case KValueTypeInt64:
       
   368 		iTempStr.Num(*(TInt64*)valptr);
       
   369 		aEnv.SetL(name, iTempStr);
       
   370 		break;
       
   371 	default:
       
   372 		StaticLeaveIfErr(KErrArgument, _L("Script argument '%S' is of unsupported type %d"), &name, aValue.Type());
       
   373 		break;
       
   374 		}
       
   375 	}
       
   376