aboutsummaryrefslogtreecommitdiffstats
path: root/src/tools/3rdparty/iossim_1_8_2/iphonesimulator.mm
diff options
context:
space:
mode:
authorFawzi Mohamed <fawzi.mohamed@digia.com>2014-03-14 00:07:35 +0100
committerFawzi Mohamed <fawzi.mohamed@digia.com>2014-03-25 08:16:36 +0100
commit470f7973d297ff07d16a9f2a73706d868bb738e9 (patch)
tree27dbc0c9fadafc08d722c734023fb88b4053ce6d /src/tools/3rdparty/iossim_1_8_2/iphonesimulator.mm
parente8d4349c37567f2714d170cabebcb5dcbb3930ca (diff)
ios: simulator support for Xcode 5.13.0
update iossim to be based on version 1.9.0, so that we can support the new Xcode 5.1. Keep the old version around and use it with older Xcode. All the logic has been moved into iossim which does an exec of the older binary if needed (so that creator itself remains untouched) Task-number: QTCREATORBUG-11714 Change-Id: I4ad9f922f22367c8371b3be68eae5b6dfdf4df5c Reviewed-by: Fawzi Mohamed <fawzi.mohamed@digia.com>
Diffstat (limited to 'src/tools/3rdparty/iossim_1_8_2/iphonesimulator.mm')
-rw-r--r--src/tools/3rdparty/iossim_1_8_2/iphonesimulator.mm566
1 files changed, 566 insertions, 0 deletions
diff --git a/src/tools/3rdparty/iossim_1_8_2/iphonesimulator.mm b/src/tools/3rdparty/iossim_1_8_2/iphonesimulator.mm
new file mode 100644
index 0000000000..b06b54276d
--- /dev/null
+++ b/src/tools/3rdparty/iossim_1_8_2/iphonesimulator.mm
@@ -0,0 +1,566 @@
+/* Author: Landon Fuller <landonf@plausiblelabs.com>
+ * Copyright (c) 2008-2011 Plausible Labs Cooperative, Inc.
+ * All rights reserved.
+ *
+ * See the IOSSIM_LICENSE file in this directory for the license on the source code in this file.
+ */
+
+#import "iphonesimulator.h"
+#import "nsstringexpandpath.h"
+#import "nsprintf.h"
+#import <sys/types.h>
+#import <sys/stat.h>
+#import <objc/runtime.h>
+#import <AppKit/NSRunningApplication.h>
+
+NSString *simulatorPrefrencesName = @"com.apple.iphonesimulator";
+NSString *deviceProperty = @"SimulateDevice";
+NSString *deviceIphoneRetina3_5Inch = @"iPhone Retina (3.5-inch)";
+NSString *deviceIphoneRetina4_0Inch = @"iPhone Retina (4-inch)";
+NSString *deviceIphone = @"iPhone";
+NSString *deviceIpad = @"iPad";
+NSString *deviceIpadRetina = @"iPad (Retina)";
+
+/**
+ * A simple iPhoneSimulatorRemoteClient framework.
+ */
+@implementation iPhoneSimulator
+
+- (id)init {
+ self = [super init];
+ session = nil;
+ pidCheckingTimer = nil;
+ return self;
+}
+
+- (void)dealloc {
+ [session release];
+ [pidCheckingTimer release];
+ [super dealloc];
+}
+
+- (void)doExit:(int)errorCode {
+ nsprintf(@"<exit code=\"%d\"/>", errorCode);
+ nsprintf(@"</query_result>");
+ fflush(stdout);
+ fflush(stderr);
+ exit(errorCode);
+}
+
+- (void) printUsage {
+ fprintf(stdout, "<msg>Usage: iossim <command> <options> [--args ...]\n");
+ fprintf(stdout, "\n");
+ fprintf(stdout, "Commands:\n");
+ fprintf(stdout, " showsdks List the available iOS SDK versions\n");
+ fprintf(stdout, " launch <application path> Launch the application at the specified path on the iOS Simulator\n");
+ fprintf(stdout, " start Launch iOS Simulator without an app\n");
+ fprintf(stdout, "\n");
+ fprintf(stdout, "Options:\n");
+ fprintf(stdout, " --version Print the version of ios-sim\n");
+ fprintf(stdout, " --developer-path <developerDir> path to the developer directory (in Xcode)");
+ fprintf(stdout, " --help Show this help text\n");
+ fprintf(stdout, " --verbose Set the output level to verbose\n");
+ fprintf(stdout, " --exit Exit after startup\n");
+ fprintf(stdout, " --wait-for-debugger Wait for debugger to attach\n");
+ fprintf(stdout, " --debug Attach LLDB to the application on startup\n");
+ fprintf(stdout, " --use-gdb Use GDB instead of LLDB. (Requires --debug)\n");
+ fprintf(stdout, " --sdk <sdkversion> The iOS SDK version to run the application on (defaults to the latest)\n");
+ fprintf(stdout, " --family <device family> The device type that should be simulated (defaults to `iphone')\n");
+ fprintf(stdout, " --retina Start a retina device\n");
+ fprintf(stdout, " --tall In combination with --retina flag, start the tall version of the retina device (e.g. iPhone 5 (4-inch))\n");
+ fprintf(stdout, " --uuid <uuid> A UUID identifying the session (is that correct?)\n");
+ fprintf(stdout, " --env <environment file path> A plist file containing environment key-value pairs that should be set\n");
+ fprintf(stdout, " --setenv NAME=VALUE Set an environment variable\n");
+ fprintf(stdout, " --stdout <stdout file path> The path where stdout of the simulator will be redirected to (defaults to stdout of ios-sim)\n");
+ fprintf(stdout, " --stderr <stderr file path> The path where stderr of the simulator will be redirected to (defaults to stderr of ios-sim)\n");
+ fprintf(stdout, " --timeout <seconds> The timeout time to wait for a response from the Simulator. Default value: 30 seconds\n");
+ fprintf(stdout, " --args <...> All following arguments will be passed on to the application</msg>\n");
+ fflush(stdout);
+}
+
+
+- (int) showSDKs {
+ NSUInteger i;
+ id tClass = objc_getClass("DTiPhoneSimulatorSystemRoot");
+ if (tClass == nil) {
+ nsprintf(@"<msg>DTiPhoneSimulatorSystemRoot class is nil.</msg>");
+ return EXIT_FAILURE;
+ }
+ NSArray *roots = [tClass knownRoots];
+
+ nsprintf(@"<device_info>");
+ for (i = 0; i < [roots count]; ++i) {
+ DTiPhoneSimulatorSystemRoot *root = [roots objectAtIndex:i];
+ nsprintf(@"<item><key>sdk%d_name</key><value>%@</value></item>", i, [root sdkDisplayName]);
+ nsprintf(@"<item><key>sdk%d_version</key><value>%@</value></item>", i, [root sdkVersion]);
+ nsprintf(@"<item><key>sdk%d_sysroot</key><value>%@</value></item>", i, [root sdkRootPath]);
+ }
+ nsprintf(@"</device_info>");
+ return EXIT_SUCCESS;
+}
+
+
+- (void)session:(DTiPhoneSimulatorSession *)mySession didEndWithError:(NSError *)error {
+ if (verbose) {
+ nsprintf(@"<msg>Session did end with error %@</msg>", error);
+ }
+
+ if (stderrFileHandle != nil) {
+ NSString *stderrPath = [[mySession sessionConfig] simulatedApplicationStdErrPath];
+ [self removeStdioFIFO:stderrFileHandle atPath:stderrPath];
+ }
+
+ if (stdoutFileHandle != nil) {
+ NSString *stdoutPath = [[mySession sessionConfig] simulatedApplicationStdOutPath];
+ [self removeStdioFIFO:stdoutFileHandle atPath:stdoutPath];
+ }
+
+ if (error != nil)
+ [self doExit:EXIT_FAILURE];
+ else
+ [self doExit:EXIT_SUCCESS];
+}
+
+
+- (void)session:(DTiPhoneSimulatorSession *)mySession didStart:(BOOL)started withError:(NSError *)error {
+ if (startOnly && mySession) {
+ [NSTask launchedTaskWithLaunchPath:@"/usr/bin/osascript"
+ arguments:[NSArray arrayWithObjects:@"-e", @"tell application \"iPhone Simulator\" to activate", nil]];
+ nsprintf(@"<msg>Simulator started (no session)</msg>");
+ [self doExit:EXIT_SUCCESS];
+ return;
+ }
+ if (started) {
+ [NSTask launchedTaskWithLaunchPath:@"/usr/bin/osascript"
+ arguments:[NSArray arrayWithObjects:@"-e", @"tell application \"iPhone Simulator\" to activate", nil]];
+ if (shouldStartDebugger) {
+ char*args[4] = { NULL, NULL, (char*)[[[mySession simulatedApplicationPID] description] UTF8String], NULL };
+ if (useGDB) {
+ args[0] = strdup("gdb");
+ args[1] = strdup("program");
+ } else {
+ args[0] = strdup("lldb");
+ args[1] = strdup("--attach-pid");
+ }
+ // The parent process must live on to process the stdout/stderr fifos,
+ // so start the debugger as a child process.
+ pid_t child_pid = fork();
+ if (child_pid == 0) {
+ execvp(args[0], args);
+ } else if (child_pid < 0) {
+ nsprintf(@"<msg>Could not start debugger process: %@</msg>", errno);
+ [self doExit:EXIT_FAILURE];
+ return;
+ }
+ }
+ if (verbose) {
+ nsprintf(@"<msg>Session started</msg>");
+ }
+ nsprintf(@"<inferior_pid>%@</inferior_pid>", [session simulatedApplicationPID]);
+ fflush(stdout);
+ if (exitOnStartup) {
+ [self doExit:EXIT_SUCCESS];
+ return;
+ }
+ pidCheckingTimer = [[NSTimer scheduledTimerWithTimeInterval:5.0 target:self
+ selector:@selector(checkPid:) userInfo:nil repeats: TRUE] retain];
+ } else {
+ nsprintf(@"<msg>Session could not be started: %@</msg>", error);
+ [self doExit:EXIT_FAILURE];
+ }
+}
+
+- (void)stop {
+ if (session)
+ [session requestEndWithTimeout: 0.1];
+}
+
+- (void)checkPid:(NSTimer *)timer {
+ (void)timer;
+ if (session && [[session simulatedApplicationPID]intValue] > 0) {
+ if (kill((pid_t)[[session simulatedApplicationPID]intValue], 0) == -1) {
+ nsprintf(@"<msg>app stopped</msg>");
+ [self doExit:EXIT_SUCCESS];
+ return;
+ }
+ }
+}
+- (void)stdioDataIsAvailable:(NSNotification *)notification {
+ [[notification object] readInBackgroundAndNotify];
+ NSData *data = [[notification userInfo] valueForKey:NSFileHandleNotificationDataItem];
+ NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; /* dangerous if partially encoded data is at the boundary */
+ if (!alreadyPrintedData) {
+ if ([str length] == 0) {
+ return;
+ } else {
+ alreadyPrintedData = YES;
+ }
+ }
+ if ([notification object] == stdoutFileHandle) {
+ printf("<app_output>%s</app_output>\n", [str UTF8String]);
+ } else {
+ nsprintf(@"<app_output>%@</app_output>", str); // handle stderr differently?
+ }
+ fflush(stdout);
+}
+
+
+- (void)createStdioFIFO:(NSFileHandle **)fileHandle ofType:(NSString *)type atPath:(NSString **)path {
+ *path = [NSString stringWithFormat:@"%@/ios-sim-%@-pipe-%d", NSTemporaryDirectory(), type, (int)time(NULL)];
+ if (mkfifo([*path UTF8String], S_IRUSR | S_IWUSR) == -1) {
+ nsprintf(@"<msg>Unable to create %@ named pipe `%@'</msg>", type, *path);
+ [self doExit:EXIT_FAILURE];
+ } else {
+ if (verbose) {
+ nsprintf(@"<msg>Creating named pipe at `%@'</msg>", *path);
+ }
+ int fd = open([*path UTF8String], O_RDONLY | O_NDELAY);
+ *fileHandle = [[[NSFileHandle alloc] initWithFileDescriptor:fd] retain];
+ [*fileHandle readInBackgroundAndNotify];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(stdioDataIsAvailable:)
+ name:NSFileHandleReadCompletionNotification
+ object:*fileHandle];
+ }
+}
+
+
+- (void)removeStdioFIFO:(NSFileHandle *)fileHandle atPath:(NSString *)path {
+ if (verbose) {
+ nsprintf(@"<msg>Removing named pipe at `%@'</msg>", path);
+ }
+ [fileHandle closeFile];
+ [fileHandle release];
+ if (![[NSFileManager defaultManager] removeItemAtPath:path error:NULL]) {
+ nsprintf(@"<msg>Unable to remove named pipe `%@'</msg>", path);
+ }
+}
+
+
+- (int)launchApp:(NSString *)path withFamily:(NSString *)family
+ uuid:(NSString *)uuid
+ environment:(NSDictionary *)environment
+ stdoutPath:(NSString *)stdoutPath
+ stderrPath:(NSString *)stderrPath
+ timeout:(NSTimeInterval)timeout
+ args:(NSArray *)args {
+ DTiPhoneSimulatorApplicationSpecifier *appSpec;
+ DTiPhoneSimulatorSessionConfig *config;
+ NSError *error = 0;
+ id tClass;
+
+ NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
+ if (!startOnly && ![fileManager fileExistsAtPath:path]) {
+ nsprintf(@"<msg>Application path %@ doesn't exist!</msg>", path);
+ return EXIT_FAILURE;
+ }
+
+ /* Create the app specifier */
+ tClass = objc_getClass("DTiPhoneSimulatorApplicationSpecifier");
+ if (tClass == nil) {
+ nsprintf(@"<msg>DTiPhoneSimulatorApplicationSpecifier class is nil.</msg>");
+ return EXIT_FAILURE;
+ }
+ appSpec = startOnly ? nil : [tClass specifierWithApplicationPath:path];
+
+ if (verbose) {
+ nsprintf(@"<msg>App Spec: %@</msg>", appSpec);
+ nsprintf(@"SDK Root: %@", sdkRoot);
+
+ for (id key in environment) {
+ nsprintf(@"<msg>Env: %@ = %@</msg>", key, [environment objectForKey:key]);
+ }
+ }
+
+
+ NSString *sdkVersion = [sdkRoot sdkVersion];
+ NSString *appSupportDir = [NSString stringWithFormat:@"%@/Library/Application Support/iPhone Simulator/%@",
+ NSHomeDirectory(), sdkVersion];
+ NSMutableDictionary *mutableEnv = [NSMutableDictionary dictionaryWithDictionary:environment];
+ [mutableEnv setObject:appSupportDir forKey:@"CFFIXED_USER_HOME"];
+ [mutableEnv setObject:appSupportDir forKey:@"IPHONE_SHARED_RESOURCES_DIRECTORY"];
+ [mutableEnv setObject:appSupportDir forKey:@"HOME"];
+ [mutableEnv setObject:[sdkRoot sdkRootPath] forKey:@"IPHONE_SIMULATOR_ROOT"];
+ [mutableEnv setObject:[sdkRoot sdkRootPath] forKey:@"DYLD_ROOT_PATH"];
+ [mutableEnv setObject:[sdkRoot sdkRootPath] forKey:@"DYLD_FRAMEWORK_PATH"];
+ [mutableEnv setObject:[sdkRoot sdkRootPath] forKey:@"DYLD_LIBRARY_PATH"];
+ [mutableEnv setObject:@"YES" forKey:@"NSUnbufferedIO"];
+ environment = mutableEnv;
+
+ /* Set up the session configuration */
+ tClass = objc_getClass("DTiPhoneSimulatorSessionConfig");
+ if (tClass == nil) {
+ nsprintf(@"<msg>DTiPhoneSimulatorApplicationSpecifier class is nil.</msg>");
+ return EXIT_FAILURE;
+ }
+ config = [[[tClass alloc] init] autorelease];
+ [config setApplicationToSimulateOnStart:appSpec];
+ [config setSimulatedSystemRoot:sdkRoot];
+ [config setSimulatedApplicationShouldWaitForDebugger:shouldWaitDebugger];
+
+ [config setSimulatedApplicationLaunchArgs:args];
+ [config setSimulatedApplicationLaunchEnvironment:environment];
+
+ if (stderrPath) {
+ stderrFileHandle = nil;
+ } else if (!exitOnStartup) {
+ [self createStdioFIFO:&stderrFileHandle ofType:@"stderr" atPath:&stderrPath];
+ }
+ [config setSimulatedApplicationStdErrPath:stderrPath];
+
+ if (stdoutPath) {
+ stdoutFileHandle = nil;
+ } else if (!exitOnStartup) {
+ [self createStdioFIFO:&stdoutFileHandle ofType:@"stdout" atPath:&stdoutPath];
+ }
+ [config setSimulatedApplicationStdOutPath:stdoutPath];
+
+ [config setLocalizedClientName: @"iossim"];
+
+ // this was introduced in 3.2 of SDK
+ if ([config respondsToSelector:@selector(setSimulatedDeviceFamily:)]) {
+ if (family == nil) {
+ family = @"iphone";
+ }
+
+ if (verbose) {
+ nsprintf(@"using device family %@",family);
+ }
+
+ if ([family isEqualToString:@"ipad"]) {
+[config setSimulatedDeviceFamily:[NSNumber numberWithInt:2]];
+ } else{
+ [config setSimulatedDeviceFamily:[NSNumber numberWithInt:1]];
+ }
+ }
+
+ [self changeDeviceType:family retina:retinaDevice isTallDevice:tallDevice];
+
+ /* Start the session */
+ tClass = objc_getClass("DTiPhoneSimulatorSession");
+ if (tClass == nil) {
+ nsprintf(@"<msg>DTiPhoneSimulatorSession class is nil.</msg>");
+ return EXIT_FAILURE;
+ }
+ session = [[tClass alloc] init];
+ [session setDelegate:self];
+ if (uuid != nil){
+ [session setUuid:uuid];
+ }
+
+ if (![session requestStartWithConfig:config timeout:timeout error:&error]) {
+ nsprintf(@"<msg>Could not start simulator session: %@</msg>", error);
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+- (void) changeDeviceType:(NSString *)family retina:(BOOL)retina isTallDevice:(BOOL)isTallDevice {
+ NSString *devicePropertyValue;
+ if (retina) {
+ if (verbose) {
+ nsprintf(@"<msg>using retina</msg>");
+ }
+ if ([family isEqualToString:@"ipad"]) {
+ devicePropertyValue = deviceIpadRetina;
+ }
+ else {
+ if (isTallDevice) {
+ devicePropertyValue = deviceIphoneRetina4_0Inch;
+ } else {
+ devicePropertyValue = deviceIphoneRetina3_5Inch;
+ }
+ }
+ } else {
+ if ([family isEqualToString:@"ipad"]) {
+ devicePropertyValue = deviceIpad;
+ } else {
+ devicePropertyValue = deviceIphone;
+ }
+ }
+ CFPreferencesSetAppValue((CFStringRef)deviceProperty, (CFPropertyListRef)devicePropertyValue, (CFStringRef)simulatorPrefrencesName);
+ CFPreferencesAppSynchronize((CFStringRef)simulatorPrefrencesName);
+}
+
+
+/**
+ * Execute 'main'
+ */
+- (void)runWithArgc:(int)argc argv:(char **)argv {
+ if (argc < 2) {
+ [self printUsage];
+ exit(EXIT_FAILURE);
+ }
+
+ retinaDevice = NO;
+ tallDevice = NO;
+ exitOnStartup = NO;
+ alreadyPrintedData = NO;
+ startOnly = strcmp(argv[1], "start") == 0;
+ nsprintf(@"<query_result>");
+
+ if (strcmp(argv[1], "showsdks") == 0) {
+ [self doExit:[self showSDKs]];
+ return;
+ } else if (strcmp(argv[1], "launch") == 0 || startOnly) {
+ if (strcmp(argv[1], "launch") == 0 && argc < 3) {
+ nsprintf(@"<msg>Missing application path argument</msg>");
+ [self printUsage];
+ [self doExit:EXIT_FAILURE];
+ return;
+ }
+
+ NSString *appPath = nil;
+ int argOffset;
+ if (startOnly) {
+ argOffset = 2;
+ }
+ else {
+ argOffset = 3;
+ appPath = [[NSString stringWithUTF8String:argv[2]] expandPath];
+ }
+
+ NSString *family = nil;
+ NSString *uuid = nil;
+ NSString *stdoutPath = nil;
+ NSString *stderrPath = nil;
+ NSTimeInterval timeout = 30;
+ NSMutableDictionary *environment = [NSMutableDictionary dictionary];
+
+ int i = argOffset;
+ for (; i < argc; i++) {
+ if (strcmp(argv[i], "--version") == 0) {
+ printf("%s\n", IOS_SIM_VERSION);
+ exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "--help") == 0) {
+ [self printUsage];
+ exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "--verbose") == 0) {
+ verbose = YES;
+ } else if (strcmp(argv[i], "--exit") == 0) {
+ exitOnStartup = YES;
+ } else if (strcmp(argv[i], "--wait-for-debugger") == 0) {
+ shouldWaitDebugger = YES;
+ } else if (strcmp(argv[i], "--debug") == 0) {
+ shouldWaitDebugger = YES;
+ shouldStartDebugger = YES;
+ } else if (strcmp(argv[i], "--use-gdb") == 0) {
+ useGDB = YES;
+ } else if (strcmp(argv[i], "--developer-path") == 0) {
+ ++i;
+ } else if (strcmp(argv[i], "--timeout") == 0) {
+ if (i + 1 < argc) {
+ timeout = [[NSString stringWithUTF8String:argv[++i]] doubleValue];
+ NSLog(@"<msg>Timeout: %f second(s)</msg>", timeout);
+ }
+ }
+ else if (strcmp(argv[i], "--sdk") == 0) {
+ i++;
+ NSString* ver = [NSString stringWithCString:argv[i] encoding:NSUTF8StringEncoding];
+ id tClass = objc_getClass("DTiPhoneSimulatorSystemRoot");
+ NSArray *roots;
+ if (tClass == nil) {
+ nsprintf(@"<msg>DTiPhoneSimulatorSystemRoot class is nil.</msg>");
+ [self doExit:EXIT_FAILURE];
+ return;
+ }
+ roots = [tClass knownRoots];
+ for (DTiPhoneSimulatorSystemRoot *root in roots) {
+ NSString *v = [root sdkVersion];
+ if ([v isEqualToString:ver]) {
+ sdkRoot = root;
+ break;
+ }
+ }
+ if (sdkRoot == nil) {
+ fprintf(stdout,"<msg>Unknown or unsupported SDK version: %s</msg>\n",argv[i]);
+ [self showSDKs];
+ exit(EXIT_FAILURE);
+ }
+ } else if (strcmp(argv[i], "--family") == 0) {
+ i++;
+ family = [NSString stringWithUTF8String:argv[i]];
+ } else if (strcmp(argv[i], "--uuid") == 0) {
+ i++;
+ uuid = [NSString stringWithUTF8String:argv[i]];
+ } else if (strcmp(argv[i], "--setenv") == 0) {
+ i++;
+ NSArray *parts = [[NSString stringWithUTF8String:argv[i]] componentsSeparatedByString:@"="];
+ [environment setObject:[parts objectAtIndex:1] forKey:[parts objectAtIndex:0]];
+ } else if (strcmp(argv[i], "--env") == 0) {
+ i++;
+ NSString *envFilePath = [[NSString stringWithUTF8String:argv[i]] expandPath];
+ environment = [NSDictionary dictionaryWithContentsOfFile:envFilePath];
+ if (!environment) {
+ fprintf(stdout, "<msg>Could not read environment from file: %s</msg>\n", argv[i]);
+ [self printUsage];
+ exit(EXIT_FAILURE);
+ }
+ } else if (strcmp(argv[i], "--stdout") == 0) {
+ i++;
+ stdoutPath = [[NSString stringWithUTF8String:argv[i]] expandPath];
+ NSLog(@"stdoutPath: %@", stdoutPath);
+ } else if (strcmp(argv[i], "--stderr") == 0) {
+ i++;
+ stderrPath = [[NSString stringWithUTF8String:argv[i]] expandPath];
+ NSLog(@"stderrPath: %@", stderrPath);
+ } else if (strcmp(argv[i], "--retina") == 0) {
+ retinaDevice = YES;
+ } else if (strcmp(argv[i], "--tall") == 0) {
+ tallDevice = YES;
+ } else if (strcmp(argv[i], "--args") == 0) {
+ i++;
+ break;
+ } else {
+ printf("<msg>unrecognized argument:%s</msg>\n", argv[i]);
+ [self printUsage];
+ [self doExit:EXIT_FAILURE];
+ return;
+ }
+ }
+ NSMutableArray *args = [NSMutableArray arrayWithCapacity:MAX(argc - i,0)];
+ for (; i < argc; i++) {
+ [args addObject:[NSString stringWithUTF8String:argv[i]]];
+ }
+
+ if (sdkRoot == nil) {
+ id tClass = objc_getClass("DTiPhoneSimulatorSystemRoot");
+ if (tClass == nil) {
+ nsprintf(@"<msg>DTiPhoneSimulatorSystemRoot class is nil.</msg>");
+ [self doExit:EXIT_FAILURE];
+ return;
+ }
+ sdkRoot = [tClass defaultRoot];
+ }
+
+ /* Don't exit, adds to runloop */
+ int res = [self launchApp:appPath
+ withFamily:family
+ uuid:uuid
+ environment:environment
+ stdoutPath:stdoutPath
+ stderrPath:stderrPath
+ timeout:timeout
+ args:args];
+ nsprintf(@"<app_started status=\"%@\" />", ((res == 0) ? @"SUCCESS" : @"FAILURE"));
+ fflush(stdout);
+ fflush(stderr);
+ if (res != 0)
+ [self doExit:EXIT_FAILURE];
+ } else {
+ if (argc == 2 && strcmp(argv[1], "--help") == 0) {
+ [self printUsage];
+ [self doExit:EXIT_SUCCESS];
+ } else if (argc == 2 && strcmp(argv[1], "--version") == 0) {
+ printf("%s\n", IOS_SIM_VERSION);
+ [self doExit:EXIT_SUCCESS];
+ } else {
+ fprintf(stdout, "<msg>Unknown command</msg>\n");
+ [self printUsage];
+ [self doExit:EXIT_FAILURE];
+ }
+ }
+}
+
+@end