summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/perl/symbian/PerlApp.cpp
diff options
context:
space:
mode:
authormillert <millert@openbsd.org>2008-09-29 17:17:50 +0000
committermillert <millert@openbsd.org>2008-09-29 17:17:50 +0000
commit850e275390052b330d93020bf619a739a3c277ac (patch)
treedb372d287586cf504a5ead4801f6c6cf7eb31449 /gnu/usr.bin/perl/symbian/PerlApp.cpp
parentmore updates on which args do and do not mix (doc only, this time): (diff)
downloadwireguard-openbsd-850e275390052b330d93020bf619a739a3c277ac.tar.xz
wireguard-openbsd-850e275390052b330d93020bf619a739a3c277ac.zip
import perl 5.10.0 from CPAN
Diffstat (limited to 'gnu/usr.bin/perl/symbian/PerlApp.cpp')
-rw-r--r--gnu/usr.bin/perl/symbian/PerlApp.cpp546
1 files changed, 546 insertions, 0 deletions
diff --git a/gnu/usr.bin/perl/symbian/PerlApp.cpp b/gnu/usr.bin/perl/symbian/PerlApp.cpp
new file mode 100644
index 00000000000..ffca7afc52c
--- /dev/null
+++ b/gnu/usr.bin/perl/symbian/PerlApp.cpp
@@ -0,0 +1,546 @@
+/* Copyright (c) 2004-2005 Nokia. All rights reserved. */
+
+/* The PerlApp application is licensed under the same terms as Perl itself.
+ *
+ * Note that this PerlApp is for Symbian/Series 60/80/UIQ smartphones
+ * and it has nothing whatsoever to do with the ActiveState PerlApp. */
+
+#include "PerlApp.h"
+
+#include <apparc.h>
+#include <e32base.h>
+#include <e32cons.h>
+#include <eikenv.h>
+#include <bautils.h>
+#include <eikappui.h>
+#include <utf.h>
+#include <f32file.h>
+
+#include <coemain.h>
+
+#ifndef PerlAppMinimal
+
+#include "PerlApp.hrh"
+
+#endif //#ifndef PerlAppMinimal
+
+#define PERL_GLOBAL_STRUCT
+#define PERL_GLOBAL_STRUCT_PRIVATE
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#include "PerlBase.h"
+#include "PerlUtil.h"
+
+#define symbian_get_vars() Dll::Tls() // Not visible from perlXYZ.lib?
+
+const TUid KPerlAppUid = {
+#ifdef PerlAppMinimalUid
+ PerlAppMinimalUid
+#else
+ 0x102015F6
+#endif
+};
+
+_LIT(KDefaultScript, "default.pl");
+
+#ifdef PerlAppMinimalName
+_LIT_NO_L(KAppName, PerlAppMinimalName);
+#else
+_LIT(KAppName, "PerlApp");
+#endif
+
+#ifndef PerlAppMinimal
+
+_LIT_NO_L(KFlavor, PERL_SYMBIANSDK_FLAVOR);
+_LIT(KAboutFormat,
+ "Perl %d.%d.%d, Symbian port %d.%d.%d, built for %S SDK %d.%d");
+_LIT(KCopyrightFormat,
+ "Copyright 1987-2005 Larry Wall and others, Symbian port Copyright Nokia 2004-2005");
+_LIT(KInboxPrefix, "\\System\\Mail\\");
+_LIT(KScriptPrefix, "\\Perl\\");
+
+_LIT8(KModulePrefix, SITELIB); // SITELIB from Perl config.h
+
+typedef TBuf<256> TMessageBuffer;
+typedef TBuf8<256> TPeekBuffer;
+typedef TBuf8<256> TFileName8;
+
+#endif // #ifndef PerlAppMinimal
+
+static void DoRunScriptL(TFileName aScriptName);
+
+TUid CPerlAppApplication::AppDllUid() const
+{
+ return KPerlAppUid;
+}
+
+enum TPerlAppPanic
+{
+ EPerlAppCommandUnknown = 1
+};
+
+void Panic(TPerlAppPanic aReason)
+{
+ User::Panic(KAppName, aReason);
+}
+
+#ifndef PerlAppMinimal
+
+// The isXXX() come from the Perl headers.
+#define FILENAME_IS_ABSOLUTE(n) \
+ (isALPHA(((n)[0])) && ((n)[1]) == ':' && ((n)[2]) == '\\')
+
+static TBool IsInPerl(TFileName aFileName)
+{
+ TInt offset = aFileName.FindF(KScriptPrefix);
+ return ((offset == 0 && // \foo
+ aFileName[0] == '\\')
+ ||
+ (offset == 2 && // x:\foo
+ FILENAME_IS_ABSOLUTE(aFileName)));
+}
+
+static TBool IsInInbox(TFileName aFileName)
+{
+ TInt offset = aFileName.FindF(KInboxPrefix);
+ return ((offset == 0 && // \foo
+ aFileName[0] == '\\')
+ ||
+ (offset == 2 && // x:\foo
+ FILENAME_IS_ABSOLUTE(aFileName)));
+}
+
+static TBool IsPerlModule(TParsePtrC aParsed)
+{
+ return aParsed.Ext().CompareF(_L(".pm")) == 0;
+}
+
+static TBool IsPerlScript(TParsePtrC aParsed)
+{
+ return aParsed.Ext().CompareF(_L(".pl")) == 0;
+}
+
+static void CopyFromInboxL(RFs aFs, const TFileName& aSrc, const TFileName& aDst)
+{
+ TBool proceed = ETrue;
+ TMessageBuffer message;
+
+ message.Format(_L("%S is untrusted. Install only if you trust provider."), &aDst);
+ if (CPerlUi::OkCancelDialogL(message)) {
+ message.Format(_L("Install as %S?"), &aDst);
+ if (CPerlUi::OkCancelDialogL(message)) {
+ if (BaflUtils::FileExists(aFs, aDst)) {
+ message.Format(_L("Replace old %S?"), &aDst);
+ if (!CPerlUi::OkCancelDialogL(message))
+ proceed = EFalse;
+ }
+ if (proceed) {
+ // Create directory?
+ TInt err = BaflUtils::CopyFile(aFs, aSrc, aDst);
+ if (err == KErrNone) {
+ message.Format(_L("Installed %S"), &aDst);
+ CPerlUi::InformationNoteL(message);
+ }
+ else {
+ message.Format(_L("Failure %d installing %S"), err, &aDst);
+ CPerlUi::WarningNoteL(message);
+ }
+ }
+ }
+ }
+}
+
+static TBool FindPerlPackageName(TPeekBuffer aPeekBuffer, TInt aOff, TFileName& aFn)
+{
+ aFn.SetMax();
+ TInt m = aFn.MaxLength();
+ TInt n = aPeekBuffer.Length();
+ TInt i = 0;
+ TInt j = aOff;
+
+ aFn.SetMax();
+ // The following is a little regular expression
+ // engine that matches Perl package names.
+ if (j < n && isSPACE(aPeekBuffer[j])) {
+ while (j < n && isSPACE(aPeekBuffer[j])) j++;
+ if (j < n && isALPHA(aPeekBuffer[j])) {
+ while (j < n && isALNUM(aPeekBuffer[j])) {
+ while (j < n &&
+ isALNUM(aPeekBuffer[j]) &&
+ i < m)
+ aFn[i++] = aPeekBuffer[j++];
+ if (j + 1 < n &&
+ aPeekBuffer[j ] == ':' &&
+ aPeekBuffer[j + 1] == ':' &&
+ i < m) {
+ aFn[i++] = '\\';
+ j += 2;
+ if (j < n &&
+ isALPHA(aPeekBuffer[j])) {
+ while (j < n &&
+ isALNUM(aPeekBuffer[j]) &&
+ i < m)
+ aFn[i++] = aPeekBuffer[j++];
+ }
+ }
+ }
+ while (j < n && isSPACE(aPeekBuffer[j])) j++;
+ if (j < n && aPeekBuffer[j] == ';' && i + 3 < m) {
+ aFn.SetLength(i);
+ aFn.Append(_L(".pm"));
+ return ETrue;
+ }
+ }
+ }
+ return EFalse;
+}
+
+static void GuessPerlModule(TFileName& aGuess, TPeekBuffer aPeekBuffer, TParse aDrive)
+{
+ TInt offset = aPeekBuffer.Find(_L8("package"));
+ if (offset != KErrNotFound) {
+ const TInt KPackageLen = 7;
+ TFileName q;
+
+ if (!FindPerlPackageName(aPeekBuffer, offset + KPackageLen, q))
+ return;
+
+ TFileName8 p;
+ p.Copy(aDrive.Drive());
+ p.Append(KModulePrefix);
+
+ aGuess.SetMax();
+ if (p.Length() + 1 + q.Length() < aGuess.MaxLength()) {
+ TInt i = 0, j;
+
+ for (j = 0; j < p.Length(); j++)
+ aGuess[i++] = p[j];
+ aGuess[i++] = '\\';
+ for (j = 0; j < q.Length(); j++)
+ aGuess[i++] = q[j];
+ aGuess.SetLength(i);
+ }
+ else
+ aGuess.SetLength(0);
+ }
+}
+
+static TBool LooksLikePerlL(TPeekBuffer aPeekBuffer)
+{
+ return aPeekBuffer.Left(2).Compare(_L8("#!")) == 0 &&
+ aPeekBuffer.Find(_L8("perl")) != KErrNotFound;
+}
+
+static TBool InstallStuffL(const TFileName &aSrc, TParse aDrive, TParse aFile, TPeekBuffer aPeekBuffer, RFs aFs)
+{
+ TFileName aDst;
+ TPtrC drive = aDrive.Drive();
+ TPtrC namext = aFile.NameAndExt();
+
+ aDst.Format(_L("%S%S%S"), &drive, &KScriptPrefix, &namext);
+ if (!IsPerlScript(aDst) && !LooksLikePerlL(aPeekBuffer)) {
+ aDst.SetLength(0);
+ if (IsPerlModule(aDst))
+ GuessPerlModule(aDst, aPeekBuffer, aDrive);
+ }
+ if (aDst.Length() > 0) {
+ CopyFromInboxL(aFs, aSrc, aDst);
+ return ETrue;
+ }
+
+ return EFalse;
+}
+
+static TBool RunStuffL(const TFileName& aScriptName, TPeekBuffer aPeekBuffer)
+{
+ TBool isModule = EFalse;
+
+ if (IsInPerl(aScriptName) &&
+ (IsPerlScript(aScriptName) ||
+ (isModule = IsPerlModule(aScriptName)) ||
+ LooksLikePerlL(aPeekBuffer))) {
+ TMessageBuffer message;
+
+ if (isModule)
+ message.Format(_L("Really run module %S?"), &aScriptName);
+ else
+ message.Format(_L("Run %S?"), &aScriptName);
+ if (CPerlUi::YesNoDialogL(message))
+ DoRunScriptL(aScriptName);
+ return ETrue;
+ }
+
+ return EFalse;
+}
+
+void CPerlAppAppUi::InstallOrRunL(const TFileName& aFileName)
+{
+ TParse aFile;
+ TParse aDrive;
+ TMessageBuffer message;
+
+ aFile.Set(aFileName, NULL, NULL);
+ if (FILENAME_IS_ABSOLUTE(aFileName)) {
+ aDrive.Set(aFileName, NULL, NULL);
+ } else {
+ TFileName appName =
+ CEikonEnv::Static()->EikAppUi()->Application()->AppFullName();
+ aDrive.Set(appName, NULL, NULL);
+ }
+ if (!iFs)
+ iFs = &CEikonEnv::Static()->FsSession();
+ RFile f;
+ TInt err = f.Open(*iFs, aFileName, EFileRead);
+ if (err == KErrNone) {
+ TPeekBuffer aPeekBuffer;
+ err = f.Read(aPeekBuffer);
+ f.Close(); // Release quickly.
+ if (err == KErrNone) {
+ if (!(IsInInbox(aFileName) ?
+ InstallStuffL(aFileName, aDrive, aFile, aPeekBuffer, *iFs) :
+ RunStuffL(aFileName, aPeekBuffer))) {
+ message.Format(_L("Failed for file %S"), &aFileName);
+ CPerlUi::WarningNoteL(message);
+ }
+ } else {
+ message.Format(_L("Error %d reading %S"), err, &aFileName);
+ CPerlUi::WarningNoteL(message);
+ }
+ } else {
+ message.Format(_L("Error %d opening %S"), err, &aFileName);
+ CPerlUi::WarningNoteL(message);
+ }
+ if (iDoorObserver)
+ delete CEikonEnv::Static()->EikAppUi();
+ else
+ Exit();
+}
+
+#endif /* #ifndef PerlAppMinimal */
+
+CPerlAppAppUi::~CPerlAppAppUi()
+{
+ if (iAppView) {
+ iEikonEnv->RemoveFromStack(iAppView);
+ delete iAppView;
+ iAppView = NULL;
+ }
+ if (iFs) {
+ delete iFs;
+ iFs = NULL;
+ }
+ if (iDoorObserver) // Otherwise the embedding application waits forever.
+ iDoorObserver->NotifyExit(MApaEmbeddedDocObserver::EEmpty);
+}
+
+static void DoRunScriptL(TFileName aScriptName)
+{
+ CPerlBase* perl = CPerlBase::NewInterpreterLC();
+ TRAPD(error, perl->RunScriptL(aScriptName));
+#ifndef PerlAppMinimal
+ if (error != KErrNone) {
+ TMessageBuffer message;
+ message.Format(_L("Error %d"), error);
+ CPerlUi::YesNoDialogL(message);
+ }
+#endif // #ifndef PerlAppMinimal
+ CleanupStack::PopAndDestroy(perl);
+}
+
+#ifndef PerlAppMinimal
+
+void CPerlAppAppUi::OpenFileL(const TDesC& aFileName)
+{
+ InstallOrRunL(aFileName);
+ return;
+}
+
+#endif // #ifndef PerlAppMinimal
+
+TBool CPerlAppAppUi::ProcessCommandParametersL(TApaCommand aCommand, TFileName& /* aDocumentName */, const TDesC8& /* aTail */)
+{
+ if (aCommand == EApaCommandRun) {
+ TFileName appName = Application()->AppFullName();
+ TParse p;
+ p.Set(KDefaultScript, &appName, NULL);
+ TEntry aEntry;
+ RFs aFs;
+ aFs.Connect();
+ if (aFs.Entry(p.FullName(), aEntry) == KErrNone) {
+ DoRunScriptL(p.FullName());
+ Exit();
+ }
+ }
+ return aCommand == EApaCommandOpen ? ETrue : EFalse;
+}
+
+#ifndef PerlAppMinimal
+
+void CPerlAppAppUi::SetFs(const RFs& aFs)
+{
+ iFs = (RFs*) &aFs;
+}
+
+#endif // #ifndef PerlAppMinimal
+
+void CPerlAppAppUi::DoHandleCommandL(TInt aCommand) {
+#ifndef PerlAppMinimal
+ TMessageBuffer message;
+#endif // #ifndef PerlAppMinimal
+
+ switch(aCommand)
+ {
+#ifndef PerlAppMinimal
+ case EPerlAppCommandAbout:
+ {
+ message.Format(KAboutFormat,
+ PERL_REVISION,
+ PERL_VERSION,
+ PERL_SUBVERSION,
+ PERL_SYMBIANPORT_MAJOR,
+ PERL_SYMBIANPORT_MINOR,
+ PERL_SYMBIANPORT_PATCH,
+ &KFlavor,
+ PERL_SYMBIANSDK_MAJOR,
+ PERL_SYMBIANSDK_MINOR
+ );
+ CPerlUi::InformationNoteL(message);
+ }
+ break;
+ case EPerlAppCommandTime:
+ {
+ CPerlBase* perl = CPerlBase::NewInterpreterLC();
+ const char *const argv[] =
+ { "perl", "-le",
+ "print 'Running in ', $^O, \"\\n\", scalar localtime" };
+ perl->ParseAndRun(sizeof(argv)/sizeof(char*), (char **)argv, 0);
+ CleanupStack::PopAndDestroy(perl);
+ }
+ break;
+#ifndef __UIQ__
+ case EPerlAppCommandRunFile:
+ {
+ TFileName aScriptUtf16;
+ aScriptUtf16.Copy(_L("C:\\"));
+ if (CPerlUi::FileQueryDialogL(aScriptUtf16))
+ DoRunScriptL(aScriptUtf16);
+ }
+ break;
+#endif
+ case EPerlAppCommandOneLiner:
+ {
+#ifdef __SERIES60__
+ _LIT(prompt, "Oneliner:");
+#endif /* #ifdef __SERIES60__ */
+#if defined(__SERIES80__) || defined(__SERIES90__) || defined(__UIQ__)
+ _LIT(prompt, "Code:"); // The title has "Oneliner" already.
+#endif /* #if defined(__SERIES80__) || defined(__SERIES90__) || defined(__UIQ__) */
+ CPerlAppAppUi* cAppUi =
+ static_cast<CPerlAppAppUi*>(CEikonEnv::Static()->EikAppUi());
+ if (CPerlUi::TextQueryDialogL(_L("Oneliner"),
+ prompt,
+ cAppUi->iOneLiner,
+ KPerlUiOneLinerSize)) {
+ const TUint KPerlUiUtf8Multi = 3; // Expansion multiplier.
+ TBuf8<KPerlUiUtf8Multi * KPerlUiOneLinerSize> utf8;
+
+ CnvUtfConverter::ConvertFromUnicodeToUtf8(utf8,
+ cAppUi->iOneLiner);
+ CPerlBase* perl = CPerlBase::NewInterpreterLC();
+#ifdef __SERIES90__
+ int argc = 5;
+#else
+ int argc = 3;
+#endif
+ char **argv = (char**) malloc(argc * sizeof(char *));
+ User::LeaveIfNull(argv);
+
+ TCleanupItem argvCleanupItem = TCleanupItem(free, argv);
+ CleanupStack::PushL(argvCleanupItem);
+ argv[0] = (char *) "perl";
+ argv[1] = (char *) "-le";
+#ifdef __SERIES90__
+ argv[2] = (char *) "unshift @INC, 'C:/Mydocs';";
+ argv[3] = (char *) "-e";
+ argv[4] = (char *) utf8.PtrZ();
+#else
+ argv[2] = (char *) utf8.PtrZ();
+#endif
+ perl->ParseAndRun(argc, argv);
+ CleanupStack::PopAndDestroy(2, perl);
+ }
+ }
+ break;
+ case EPerlAppCommandCopyright:
+ {
+ message.Format(KCopyrightFormat);
+ CPerlUi::InformationNoteL(message);
+ }
+ break;
+ case EPerlAppCommandAboutCopyright:
+ {
+ TMessageBuffer m1;
+ TMessageBuffer m2;
+ m1.Format(KAboutFormat,
+ PERL_REVISION,
+ PERL_VERSION,
+ PERL_SUBVERSION,
+ PERL_SYMBIANPORT_MAJOR,
+ PERL_SYMBIANPORT_MINOR,
+ PERL_SYMBIANPORT_PATCH,
+ &KFlavor,
+ PERL_SYMBIANSDK_MAJOR,
+ PERL_SYMBIANSDK_MINOR
+ );
+ CPerlUi::InformationNoteL(m1);
+ User::After((TTimeIntervalMicroSeconds32) (1000*1000)); // 1 sec.
+ m2.Format(KCopyrightFormat);
+ CPerlUi::InformationNoteL(m2);
+ }
+ break;
+#endif // #ifndef PerlAppMinimal
+ default:
+ Panic(EPerlAppCommandUnknown);
+ }
+}
+
+CApaDocument* CPerlAppApplication::CreateDocumentL()
+{
+ CPerlAppDocument* cDoc = new (ELeave) CPerlAppDocument(*this);
+ return cDoc;
+}
+
+CEikAppUi* CPerlAppDocument::CreateAppUiL()
+{
+ CPerlAppAppUi* cAppUi = new (ELeave) CPerlAppAppUi();
+ return cAppUi;
+}
+
+
+#ifndef PerlAppMinimal
+
+CFileStore* CPerlAppDocument::OpenFileL(TBool aDoOpen, const TDesC& aFileName, RFs& aFs)
+{
+ CPerlAppAppUi* cAppUi =
+ static_cast<CPerlAppAppUi*>(CEikonEnv::Static()->EikAppUi());
+ cAppUi->SetFs(aFs);
+ if (aDoOpen)
+ cAppUi->OpenFileL(aFileName);
+ return NULL;
+}
+
+#endif // #ifndef PerlAppMinimal
+
+EXPORT_C CApaApplication* NewApplication()
+{
+ return new CPerlAppApplication;
+}
+
+GLDEF_C TInt E32Dll(TDllReason /*aReason*/)
+{
+ return KErrNone;
+}
+