sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Common code useful to all crt0 variants. This is kept in the DLL to allow us to sl@0: // change it in future releases. sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include // for chdir sl@0: #include // for calloc sl@0: #include // for strdup sl@0: sl@0: const TInt KMaxArgC=25; sl@0: sl@0: static char* wcstombs_alloc (const wchar_t* aString) sl@0: { sl@0: if (aString==NULL) sl@0: return NULL; sl@0: sl@0: size_t size = wcstombs(0, aString, 0); sl@0: char* buf = (char*)malloc(size * sizeof(char)); sl@0: sl@0: size = wcstombs(buf, aString, size); sl@0: if (size == (size_t) -1) sl@0: { sl@0: free(buf); sl@0: return NULL; sl@0: } sl@0: buf = (char*)realloc(buf, (size+1) * sizeof(char)); sl@0: return buf; sl@0: } sl@0: sl@0: #ifdef EKA2 sl@0: sl@0: static wchar_t* allocCommandLine(const TDesC& aPath) sl@0: { sl@0: TInt cmdLength = User::CommandLineLength()+1; // for zero termination sl@0: TText16* cmdbuf = (TText16*)malloc(cmdLength*sizeof(TText16)); sl@0: if (cmdbuf==0) sl@0: return (wchar_t*)cmdbuf; // we are just doomed, so give up now sl@0: sl@0: TPtr16 cmdline(cmdbuf, cmdLength); sl@0: User::CommandLine(cmdline); sl@0: sl@0: // The .EXE recogniser supplies a command line which is the name of the file, sl@0: // followed by a space. This is usually not what's wanted, so remove the sl@0: // filename if it is an exact match for the start of the command line. sl@0: sl@0: if (cmdline.Find(aPath)==0) sl@0: { sl@0: cmdline.Delete(0, aPath.Length()); sl@0: } sl@0: cmdline.ZeroTerminate(); sl@0: return (wchar_t*)cmdbuf; sl@0: } sl@0: sl@0: #else//EKA2 sl@0: sl@0: static wchar_t* allocCommandLine(const TDesC& aPath) sl@0: { sl@0: RProcess me; sl@0: TInt cmdLength = me.CommandLineLength()+1; // for zero termination sl@0: TText16* cmdbuf = (TText16*)malloc(cmdLength*sizeof(TText16)); sl@0: if (cmdbuf==0) sl@0: return (wchar_t*)cmdbuf; // we are just doomed, so give up now sl@0: sl@0: TPtr16 cmdline(cmdbuf, cmdLength); sl@0: me.CommandLine(cmdline); sl@0: sl@0: // The .EXE recogniser supplies a command line which is the name of the file, sl@0: // followed by a space. This is usually not what's wanted, so remove the sl@0: // filename if it is an exact match for the start of the command line. sl@0: sl@0: if (cmdline.Find(aPath)==0) sl@0: { sl@0: cmdline.Delete(0, aPath.Length()); sl@0: } sl@0: cmdline.ZeroTerminate(); sl@0: return (wchar_t*)cmdbuf; sl@0: } sl@0: sl@0: #endif//EKA2 sl@0: sl@0: EXPORT_C void __crt0(int& argc, char**& argv, char**& envp) sl@0: { sl@0: // Find out the filename for argv[0] sl@0: sl@0: TBuf16 exepath(RProcess().FileName()); sl@0: sl@0: // Sort out argc/argv, creating an array of pointers into a copy of sl@0: // the commandline. sl@0: sl@0: wchar_t* cmdbuf = allocCommandLine(exepath); sl@0: char* cmd = wcstombs_alloc(cmdbuf); sl@0: free(cmdbuf); sl@0: char* filename = wcstombs_alloc((const wchar_t *)exepath.PtrZ()); sl@0: sl@0: argv = (char**)calloc(KMaxArgC, sizeof(char*)); sl@0: sl@0: // Check for memory allocation failures. sl@0: if (argv==0 || cmd==0 || filename== 0) sl@0: { sl@0: // Free any memory that could have been allocated before returning. sl@0: free(cmd); sl@0: free(filename); sl@0: return; // it's basically doomed at this point anyway sl@0: } sl@0: sl@0: // Split the command line into the separate arguments sl@0: // Follow the stdarg.c rules in the Win32 runtime, namely sl@0: // 1. space and tab are whitespace separators, except inside "..." pairs sl@0: // 2. strings of \ are literal unless followed by " (see below) sl@0: // 3. a pair of "" in a quoted string is a literal " sl@0: sl@0: const char KSpace= ' '; sl@0: const char KTab = '\t'; sl@0: const char KQuote= '"'; sl@0: const char KSlash= '\\'; sl@0: sl@0: argv[0]=filename; sl@0: argc = 1; sl@0: char *q = cmd; sl@0: const char* p = cmd; sl@0: FOREVER sl@0: { sl@0: char c; sl@0: TInt quoted=0; sl@0: sl@0: // skip leading whitespace sl@0: do sl@0: c=*p++; sl@0: while (c && (c==KSpace || c==KTab)); sl@0: sl@0: // update the argv,argc sl@0: if (c=='\0' || argc>=KMaxArgC) sl@0: break; sl@0: sl@0: argv[argc] = q; sl@0: argc++; sl@0: sl@0: // copy the argument from p to q sl@0: for (;c!='\0';c=*p++) sl@0: { sl@0: sl@0: // The UNC filenames format used, e.g. \\host\dir\file sl@0: // Hence the rather odd rules: for N>=0 sl@0: // 2N+1 slash + " => N slash + literal " sl@0: // 2N slash + " => N slash, start/end quoted substring sl@0: // N slash + ? => N slash + ? sl@0: sl@0: int slashcount=0; sl@0: while (c==KSlash) sl@0: { sl@0: *q++=c; // copy the slashes (might be too many) sl@0: slashcount++; sl@0: c=*p++; sl@0: } sl@0: if (c=='\0') sl@0: break; sl@0: if (c==KQuote) sl@0: { sl@0: q-=(slashcount-(slashcount/2)); // slashes followed by quote - adjust sl@0: if (slashcount&1) sl@0: { sl@0: *q++=c; // literal quote sl@0: continue; sl@0: } sl@0: if (quoted && *p==KQuote) sl@0: { sl@0: p++; sl@0: *q++=c; // "" inside quoted section = literal quote sl@0: continue; sl@0: } sl@0: quoted=!quoted; sl@0: continue; sl@0: } sl@0: if (!quoted && (c==KSpace || c==KTab)) sl@0: break; sl@0: *q++=c; sl@0: } sl@0: *q++='\0'; // terminate the copy sl@0: sl@0: if (c=='\0') sl@0: break; // end of command line sl@0: } sl@0: sl@0: // sort out the environment sl@0: sl@0: envp=0; sl@0: } sl@0: sl@0: EXPORT_C void __crt0(int& argc, wchar_t**& wargv, wchar_t**& wenvp) sl@0: { sl@0: // Find out the filename for argv[0] sl@0: sl@0: TBuf16 exepath(RProcess().FileName()); sl@0: sl@0: // Sort out argc/argv, creating an array of pointers into a copy of sl@0: // the commandline. sl@0: sl@0: wchar_t* cmd = allocCommandLine(exepath); sl@0: wchar_t* filename = wcsdup((const wchar_t *)exepath.PtrZ()); sl@0: wargv = (wchar_t**)calloc(KMaxArgC, sizeof(wchar_t*)); sl@0: sl@0: // Check for memory allocation failures. sl@0: if (wargv==0 || cmd==0 || filename== 0) sl@0: { sl@0: // Free any memory that could have been allocated before returning. sl@0: free(cmd); sl@0: free(filename); sl@0: return; // it's basically doomed at this point anyway sl@0: } sl@0: sl@0: // Split the command line into the separate arguments sl@0: // Follow the stdarg.c rules in the Win32 runtime, namely sl@0: // 1. space and tab are whitespace separators, except inside "..." pairs sl@0: // 2. strings of \ are literal unless followed by " (see below) sl@0: // 3. a pair of "" in a quoted string is a literal " sl@0: sl@0: const wchar_t KSpace= L' '; sl@0: const wchar_t KTab = L'\t'; sl@0: const wchar_t KQuote= L'"'; sl@0: const wchar_t KSlash= L'\\'; sl@0: sl@0: wargv[0]=filename; sl@0: argc = 1; sl@0: wchar_t *q = cmd; sl@0: wchar_t *p = cmd; sl@0: FOREVER sl@0: { sl@0: wchar_t c; sl@0: TInt quoted=0; sl@0: sl@0: // skip leading whitespace sl@0: do sl@0: c=*p++; sl@0: while (c && (c==KSpace || c==KTab)); sl@0: sl@0: // update the argv,argc sl@0: if (c=='\0' || argc>=KMaxArgC) sl@0: break; sl@0: sl@0: wargv[argc] = q; sl@0: argc++; sl@0: sl@0: // copy the argument from p to q sl@0: for (;c!=L'\0';c=*p++) sl@0: { sl@0: sl@0: // The UNC filenames format used, e.g. \\host\dir\file sl@0: // Hence the rather odd rules: for N>=0 sl@0: // 2N+1 slash + " => N slash + literal " sl@0: // 2N slash + " => N slash, start/end quoted substring sl@0: // N slash + ? => N slash + ? sl@0: sl@0: int slashcount=0; sl@0: while (c==KSlash) sl@0: { sl@0: *q++=c; // copy the slashes (might be too many) sl@0: slashcount++; sl@0: c=*p++; sl@0: } sl@0: if (c==L'\0') sl@0: break; sl@0: if (c==KQuote) sl@0: { sl@0: q-=(slashcount-(slashcount/2)); // slashes followed by quote - adjust sl@0: if (slashcount&1) sl@0: { sl@0: *q++=c; // literal quote sl@0: continue; sl@0: } sl@0: if (quoted && *p==KQuote) sl@0: { sl@0: p++; sl@0: *q++=c; // "" inside quoted section = literal quote sl@0: continue; sl@0: } sl@0: quoted=!quoted; sl@0: continue; sl@0: } sl@0: if (!quoted && (c==KSpace || c==KTab)) sl@0: break; sl@0: *q++=c; sl@0: } sl@0: *q++=L'\0'; // terminate the copy sl@0: sl@0: if (c==L'\0') sl@0: break; // end of command line sl@0: } sl@0: sl@0: // sort out the environment sl@0: sl@0: wenvp=0; sl@0: }