4 * Copyright (c) Nokia 2004-2005. All rights reserved.
5 * This code is licensed under the same terms as Perl itself.
9 #define SYMBIAN_UTILS_CPP
12 #include <textresolver.h>
22 EXPORT_C int symbian_sys_init(int *argcp, char ***argvp)
24 #ifdef PERL_GLOBAL_STRUCT /* Avoid unused variable warning. */
27 (void)times(&PL_timesbase);
30 EXPORT_C SSize_t symbian_read_stdin(const int fd, char *b, int n)
32 #ifdef PERL_GLOBAL_STRUCT /* Avoid unused variable warning. */
35 return ((CPerlBase*)PL_appctx)->ConsoleRead(fd, b, n);
37 EXPORT_C SSize_t symbian_write_stdout(const int fd, const char *b, int n)
39 #ifdef PERL_GLOBAL_STRUCT /* Avoid unused variable warning. */
42 return ((CPerlBase*)PL_appctx)->ConsoleWrite(fd, b, n);
44 static const char NullErr[] = "";
45 EXPORT_C char* symbian_get_error_string(const TInt error)
49 return strerror(error);
50 CTextResolver* textResolver = CTextResolver::NewL();
51 CleanupStack::PushL(textResolver);
52 TBuf<KErrorResolverMaxTextLength> buf16;
53 TBuf8<KErrorResolverMaxTextLength> buf8;
54 if (error != KErrNone)
55 buf16 = textResolver->ResolveError(error);
57 if (CnvUtfConverter::ConvertFromUnicodeToUtf8(buf8, buf16) !=
59 CleanupStack::PopAndDestroy(textResolver);
60 return (char*)NullErr;
63 SV* sv = Perl_get_sv(aTHX_ "\005", TRUE); /* $^E or ${^OS_ERROR} */
65 return (char*)NullErr;
66 sv_setpv(sv, (const char *)buf8.PtrZ());
68 CleanupStack::PopAndDestroy(textResolver);
69 return SvPV_nolen(sv);
71 EXPORT_C void symbian_sleep_usec(const long usec)
73 User::After((TTimeIntervalMicroSeconds32) usec);
75 #define PERL_SYMBIAN_CLK_TCK 100
76 EXPORT_C int symbian_get_cpu_time(long* sec, long* usec)
78 // The RThread().GetCpuTime() does not seem to work?
79 // (it always returns KErrNotSupported)
80 // TTimeIntervalMicroSeconds ti;
81 // TInt err = me.GetCpuTime(ti);
83 TInt periodus; /* tick period in microseconds */
84 if (HAL::Get(HALData::ESystemTickPeriod, periodus) != KErrNone)
86 TUint tick = User::TickCount();
87 if (PL_timesbase.tms_utime == 0) {
88 PL_timesbase.tms_utime = tick;
89 PL_clocktick = PERL_SYMBIAN_CLK_TCK;
91 tick -= PL_timesbase.tms_utime;
92 TInt64 tickus = TInt64(tick) * TInt64(periodus);
93 TInt64 tmps = tickus / 1000000;
94 if (sec) *sec = tmps.Low();
95 if (usec) *usec = tickus.Low() - tmps.Low() * 1000000;
98 EXPORT_C int symbian_usleep(unsigned int usec)
100 if (usec >= 1000000) {
104 symbian_sleep_usec((const long) usec);
107 #define SEC_USEC_TO_CLK_TCK(s, u) \
108 (((s) * PERL_SYMBIAN_CLK_TCK) + (u / (1000000 / PERL_SYMBIAN_CLK_TCK)))
109 EXPORT_C clock_t symbian_times(struct tms *tmsbuf)
112 if (symbian_get_cpu_time(&s, &u) == -1) {
116 tmsbuf->tms_utime = SEC_USEC_TO_CLK_TCK(s, u);
117 tmsbuf->tms_stime = 0;
118 tmsbuf->tms_cutime = 0;
119 tmsbuf->tms_cstime = 0;
120 return tmsbuf->tms_utime;
123 class CE32ProcessWait : public CActive
126 CE32ProcessWait() : CActive(EPriorityStandard) {
127 CActiveScheduler::Add(this);
130 TInt Wait(RThread& aProcess)
132 TInt Wait(RProcess& aProcess)
135 aProcess.Logon(iStatus);
138 CActiveScheduler::Start();
139 return iStatus.Int();
144 CActiveScheduler::Stop();
146 CActiveSchedulerWait iWait;
148 class CSpawnIoRedirect : public CBase
152 // NOTE: there is no real implementation of I/O redirection yet.
156 CSpawnIoRedirect::CSpawnIoRedirect()
160 ESpawnNone = 0x00000000,
161 ESpawnWait = 0x00000001
163 static int symbian_spawn(const TDesC& aFilename,
164 const TDesC& aCommand,
165 const TSpawnFlag aFlag,
166 const CSpawnIoRedirect& aIoRedirect) {
167 TInt error = KErrNone;
169 const TInt KStackSize = 0x1000;
170 const TInt KHeapMin = 0x1000;
171 const TInt KHeapMax = 0x100000;
174 HBufC* command = aCommand.Alloc();
175 error = lib.Load(aFilename);
176 if (error == KErrNone) {
177 TThreadFunction func = (TThreadFunction)(lib.Lookup(1));
179 error = proc.Create(aFilename,
189 error = KErrNotFound;
196 error = proc.Create(aFilename, aCommand);
198 if (error == KErrNone) {
199 if ((TInt)aFlag & (TInt)ESpawnWait) {
200 CE32ProcessWait* w = new CE32ProcessWait();
202 error = w->Wait(proc);
205 error = KErrNoMemory;
212 static int symbian_spawner(const char *command, TSpawnFlag aFlags)
214 TBuf<KMaxFileName> aFilename;
215 TBuf<KMaxFileName> aCommand;
216 TSpawnFlag aSpawnFlags = ESpawnWait;
217 CSpawnIoRedirect iord;
218 char *p = (char*)command;
220 // The recognized syntax is: "cmd [args] [&]". Since one
221 // cannot pass more than (an argv[0] and) an argv[1] to a
222 // Symbian process anyway, not much is done to the cmd or
223 // the args, only backslash quoting.
225 // Strip leading whitespace.
226 while (*p && isspace(*p)) p++;
229 while (*p && !isspace(*p) && *p != '&') {
232 aFilename.Append(p[1]);
238 aFilename.Append(*p);
243 // Skip whitespace between argv[0] and argv[1].
244 while(*p && isspace(*p)) p++;
251 if (isspace(b[-1])) {
253 while (b > a && isspace(*b)) b--;
256 if (b > a && b[-1] == '&') {
257 // Parse backgrounding in any case,
258 // but turn it off only if wanted.
259 if ((aFlags & ESpawnWait))
261 (TSpawnFlag) (aSpawnFlags & ~ESpawnWait);
263 if (isspace(b[-1])) {
265 while (b > a && isspace(*b)) b--;
269 for (p = a; p < b; p++) {
272 aCommand.Append(p[1]);
279 // NOTE: I/O redirection is not yet done.
280 // Implementing that may require a separate server.
283 int spawned = symbian_spawn(aFilename, aCommand, aSpawnFlags, iord);
284 return spawned == KErrNone ? 0 : -1;
286 EXPORT_C int symbian_do_spawn(const char *command)
288 return symbian_spawner(command, ESpawnWait);
290 EXPORT_C int symbian_do_spawn_nowait(const char *command)
292 return symbian_spawner(command, ESpawnNone);
294 EXPORT_C int symbian_do_aspawn(void* vreally, void* vmark, void* sp)