--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core/src/script_command.cpp Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,376 @@
+// script_command.cpp
+//
+// Copyright (c) 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Accenture - Initial contribution
+//
+#include "script_command.h"
+#include "fshell.h" // For KScriptArgCount etc
+#include <fshell/descriptorutils.h>
+
+using namespace IoUtils;
+using namespace LtkUtils;
+
+CScriptCommand* CScriptCommand::NewLC(const TDesC& aScriptPath, TIoHandleSet& aIoHandles)
+ {
+ CScriptCommand* self = new(ELeave) CScriptCommand;
+ CleanupStack::PushL(self);
+ self->ConstructL(aScriptPath, aIoHandles);
+ return self;
+ }
+
+const TDesC& CScriptCommand::Name() const
+ {
+ return iName;
+ }
+
+void CScriptCommand::DoRunL()
+ {
+ // Never actually runs
+ __DEBUGGER();
+ }
+
+CScriptCommand::CScriptCommand()
+ : CCommandBase()
+ {
+ }
+
+void CScriptCommand::ConstructL(const TDesC& aScriptPath, TIoHandleSet& aIoHandles)
+ {
+ BaseConstructL();
+
+ // Duplicate some handles in case we need to display the script's help text.
+ IoSession().SetHandle(aIoHandles.IoSession().Handle());
+ User::LeaveIfError(IoSession().Duplicate(RThread(), EOwnerThread));
+ Stdout().CreateL(IoSession());
+ Stdout().Duplicate(aIoHandles.Stdout());
+ Stderr().CreateL(IoSession());
+ Stderr().Duplicate(aIoHandles.Stderr());
+
+ iScriptPath = aScriptPath.AllocL();
+ iName.Set(TParsePtrC(*iScriptPath).NameAndExt());
+ RFs fs; // Can't use FsL(), that needs an env set up
+ CleanupClosePushL(fs);
+ User::LeaveIfError(fs.Connect());
+
+ iOwnedCif = CCommandInfoFile::NewL(fs, *iScriptPath); // A script file is also its own cif
+
+ if (iOwnedCif->Name().Length() == 0)
+ {
+ // No cif data - fall back to just creating a basic array of args (for converting into $1 $2 etc)
+ iArguments.AppendStringL(iNonCifScriptArguments, _L("args"), _L("Arguments for the script. These are converted to the environment variables C<$1>, C<$2> etc."), KValueTypeFlagOptional);
+ delete iOwnedCif;
+ iOwnedCif = NULL;
+ }
+ else
+ {
+ SetCif(*iOwnedCif); // SetCif doesn't take ownership (which is what iOwnedCif is for)
+
+ // Now go through and make up "member variables" to correspond to everything in the CIF so we can fool CCommandBase into
+ // doing the parsing work for us
+ const TInt argCount = iOwnedCif->Arguments().Count();
+ for (TInt i = 0; i < argCount; i++)
+ {
+ SetupArgumentL(iOwnedCif->Arguments()[i]);
+ }
+
+ const TInt optCount = iOwnedCif->Options().Count();
+ for (TInt i = 0; i < optCount; i++)
+ {
+ const TCommandOption& opt = iOwnedCif->Options()[i];
+ SetupOptionL(opt);
+ }
+
+ iOwnedCif->AssignL(iArguments, iOptions);
+ }
+
+ iOptions.AppendBoolL(iDisplayHelp, 'h', _L("help"), _L("Display help.")); // Always support --help (cannot do this before the call to CCommandInfoFile::AssignL())
+
+ // Our argument data structures should now be fully constructed
+ CleanupStack::PopAndDestroy(&fs);
+ }
+
+TInt StorageSizeForType(TUint aType)
+ {
+ TInt size = sizeof(TInt);
+ switch (aType)
+ {
+ case KValueTypeReal:
+ size = sizeof(TReal); break;
+ case KValueTypeFileName:
+ size = sizeof(TFileName2); break;
+ case KValueTypeUint64:
+ case KValueTypeInt64:
+ size = sizeof(TInt64); break;
+ default:
+ break;
+ }
+ return size;
+ }
+
+void CScriptCommand::SetupArgumentL(const TValue& aValue)
+ {
+ if (aValue.AcceptsMultiple()) StaticLeaveIfErr(KErrArgument, _L("Arguments with the 'multiple' attribute are not supported for scripts"));
+
+ const TUint type = aValue.Type();
+ void* valptr = User::AllocZL(StorageSizeForType(type));
+ CleanupStack::PushL(valptr);
+
+ TPtrC name = aValue.Name();
+ switch (type)
+ {
+ case KValueTypeInt:
+ iArguments.AppendIntL(*(TInt*)valptr, name);
+ break;
+ case KValueTypeUint:
+ iArguments.AppendUintL(*(TUint*)valptr, name);
+ break;
+ case KValueTypeString:
+ iArguments.AppendStringL(*(HBufC**)valptr, name);
+ break;
+ case KValueTypeFileName:
+ new (valptr) TFileName2; // We only AllocZL'd, we didn't initialise it
+ iArguments.AppendFileNameL(*(TFileName2*)valptr, name);
+ break;
+ case KValueTypeEnum:
+ iArguments.AppendEnumL(*(TInt*)valptr, name);
+ break;
+ case KValueTypeReal:
+ iArguments.AppendRealL(*(TReal*)valptr, name);
+ break;
+ case KValueTypeUint64:
+ iArguments.AppendUintL(*(TUint64*)valptr, name);
+ break;
+ case KValueTypeInt64:
+ iArguments.AppendIntL(*(TInt64*)valptr, name);
+ break;
+ default:
+ StaticLeaveIfErr(KErrArgument, _L("Script argument '%S' is of unsupported type %d"), &name, aValue.Type());
+ break;
+ }
+ CleanupStack::Pop(valptr);
+ }
+
+void CScriptCommand::SetupOptionL(const IoUtils::TValue& aValue)
+ {
+ if (aValue.AcceptsMultiple()) StaticLeaveIfErr(KErrArgument, _L("Options with the 'multiple' attribute are not supported for scripts"));
+
+ const TUint type = aValue.Type();
+ void* valptr = User::AllocZL(StorageSizeForType(type));
+ CleanupStack::PushL(valptr);
+
+ TPtrC name = aValue.Name();
+ switch (type)
+ {
+ case KValueTypeBool:
+ iOptions.AppendBoolL(*(TBool*)valptr, name);
+ break;
+ case KValueTypeInt:
+ iOptions.AppendIntL(*(TInt*)valptr, name);
+ break;
+ case KValueTypeUint:
+ iOptions.AppendUintL(*(TUint*)valptr, name);
+ break;
+ case KValueTypeString:
+ iOptions.AppendStringL(*(HBufC**)valptr, name);
+ break;
+ case KValueTypeFileName:
+ new (valptr) TFileName2; // We only AllocZL'd, we didn't initialise it
+ iOptions.AppendFileNameL(*(TFileName2*)valptr, name);
+ break;
+ case KValueTypeEnum:
+ iOptions.AppendEnumL(*(TInt*)valptr, name);
+ break;
+ case KValueTypeReal:
+ iOptions.AppendRealL(*(TReal*)valptr, name);
+ break;
+ case KValueTypeUint64:
+ iOptions.AppendUintL(*(TUint64*)valptr, name);
+ break;
+ case KValueTypeInt64:
+ iOptions.AppendIntL(*(TInt64*)valptr, name);
+ break;
+ default:
+ StaticLeaveIfErr(KErrArgument, _L("Script argument '%S' is of unsupported type %d"), &name, aValue.Type());
+ break;
+ }
+ CleanupStack::Pop(valptr);
+ }
+
+CScriptCommand::~CScriptCommand()
+ {
+ if (iOwnedCif)
+ {
+ // We set all these up, we need to delete them
+ for (TInt i = 0; i < iArguments.Count(); i++)
+ {
+ const TCommandArgument& arg = ((const RCommandArgumentList&)iArguments)[i];
+ if (arg.Type() == KValueTypeString) delete *(HBufC**)arg.ValuePtr();
+ delete arg.ValuePtr();
+ }
+ for (TInt i = 0; i < iOptions.Count(); i++)
+ {
+ const TCommandOption& opt = ((const RCommandOptionList&)iOptions)[i];
+ if (opt.ValuePtr() != &iDisplayHelp)
+ {
+ if (opt.Type() == KValueTypeString) delete *(HBufC**)opt.ValuePtr();
+ delete opt.ValuePtr();
+ }
+ }
+ }
+
+ delete iScriptPath;
+ delete iOwnedCif;
+ iNonCifScriptArguments.ResetAndDestroy();
+ Stderr().Close();
+ Stdout().Close();
+ IoSession().Close();
+ }
+
+void CScriptCommand::ParseCommandLineArgsL(const TDesC& aArgs, CEnvironment& aEnv, RPointerArray<HBufC>* aAdditionalPrefixArguments)
+ {
+ 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
+
+ if (aAdditionalPrefixArguments && aAdditionalPrefixArguments->Count())
+ {
+ // 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)
+ LtkUtils::RLtkBuf argsBuf;
+ CleanupClosePushL(argsBuf);
+ TInt c = aAdditionalPrefixArguments->Count();
+ while (c--)
+ {
+ argsBuf.AppendL(_L("placeholder "));
+ }
+ argsBuf.AppendL(aArgs);
+ ParseCommandLineL(argsBuf);
+ CleanupStack::PopAndDestroy(&argsBuf);
+ }
+ else
+ {
+ ParseCommandLineL(aArgs);
+ }
+
+ if (!iArguments.AllSet())
+ {
+ User::Leave(KErrArgument);
+ }
+
+ // Everything is filled in now, just have to setup aEnv with the results
+ TInt argCount = iArguments.Count();
+ if (iOwnedCif)
+ {
+ for (TInt i = 0; i < argCount; i++)
+ {
+ const TCommandArgument& arg = ((const RCommandArgumentList&)iArguments)[i];
+ SetEnvironmentVariableFromValueL(aEnv, arg);
+ }
+
+ // Now check for overrides from aAdditionalPrefixArguments
+ if (aAdditionalPrefixArguments)
+ {
+ for (TInt i = 0; i < aAdditionalPrefixArguments->Count(); i++)
+ {
+ 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[]
+ aEnv.SetL(arg.Name(), *(*aAdditionalPrefixArguments)[i]);
+ }
+ }
+ for (TInt i = 0; i < iOptions.Count(); i++)
+ {
+ const TCommandOption& opt = ((const RCommandOptionList&)iOptions)[i];
+ if (opt.ValuePtr() != &iDisplayHelp) SetEnvironmentVariableFromValueL(aEnv, opt);
+ }
+ }
+ else
+ {
+ // Just set $1, $2 etc
+ argCount = iNonCifScriptArguments.Count();
+ for (TInt i = 0; i < argCount; i++)
+ {
+ TBuf<16> varname;
+ varname.AppendNum(i+1);
+ aEnv.SetLocalL(varname);
+ if (aAdditionalPrefixArguments && i < aAdditionalPrefixArguments->Count())
+ {
+ aEnv.SetL(varname, *(*aAdditionalPrefixArguments)[i]);
+ }
+ else
+ {
+ aEnv.SetL(varname, *iNonCifScriptArguments[i]);
+ }
+ }
+ }
+
+ aEnv.SetLocalL(KScriptArgCount);
+ aEnv.SetL(KScriptArgCount, argCount);
+ }
+
+void CScriptCommand::DisplayScriptHelpL()
+ {
+ const CTextBuffer* helpText = GetHelpTextL();
+ CleanupStack::PushL(const_cast<CTextBuffer*>(helpText));
+ PageL(*helpText);
+ CleanupStack::PopAndDestroy(const_cast<CTextBuffer*>(helpText));
+ }
+
+void CScriptCommand::SetEnvironmentVariableFromValueL(IoUtils::CEnvironment& aEnv, const IoUtils::TValue& aValue)
+ {
+ const TPtrC name(aValue.Name());
+ aEnv.SetLocalL(name);
+ void* valptr = aValue.ValuePtr();
+
+ switch (aValue.Type())
+ {
+ case KValueTypeBool:
+ if (*(TBool*)valptr)
+ {
+ aEnv.SetL(name, 1);
+ }
+ break;
+ case KValueTypeInt:
+ aEnv.SetL(name, *(TInt*)valptr);
+ break;
+ case KValueTypeUint:
+ iTempStr.Num(*(TUint*)valptr, EDecimal);
+ aEnv.SetL(name, iTempStr);
+ break;
+ case KValueTypeString:
+ {
+ HBufC* val = *(HBufC**)valptr;
+ if (val) aEnv.SetL(name, *val);
+ break;
+ }
+ case KValueTypeFileName:
+ aEnv.SetL(name, *(TFileName2*)valptr);
+ break;
+ case KValueTypeEnum:
+ {
+ TEnum enumObj(aValue.EnumValueList());
+ aEnv.SetL(name, enumObj.GetString(*(TInt*)valptr));
+ break;
+ }
+ case KValueTypeReal:
+ {
+ _LIT(KRealFormat, "%g");
+ iTempStr.Format(KRealFormat, *(TReal*)valptr);
+ aEnv.SetL(name, iTempStr);
+ break;
+ }
+ case KValueTypeUint64:
+ iTempStr.Num(*(TUint64*)valptr, EDecimal);
+ aEnv.SetL(name, iTempStr);
+ break;
+ case KValueTypeInt64:
+ iTempStr.Num(*(TInt64*)valptr);
+ aEnv.SetL(name, iTempStr);
+ break;
+ default:
+ StaticLeaveIfErr(KErrArgument, _L("Script argument '%S' is of unsupported type %d"), &name, aValue.Type());
+ break;
+ }
+ }
+