[commit] r2517 - Add access to VM arguments to Mac. Make Windows, Mac and Unix consistent:

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[commit] r2517 - Add access to VM arguments to Mac. Make Windows, Mac and Unix consistent:

commits-3
 
Author: eliot
Date: 2011-11-28 11:07:44 -0800 (Mon, 28 Nov 2011)
New Revision: 2517

Removed:
   branches/Cog/platforms/win32/vm/sqWin32Args.c
   branches/Cog/platforms/win32/vm/sqWin32Args.h
Modified:
   branches/Cog/platforms/Cross/vm/sqSCCSVersion.h
   branches/Cog/platforms/Mac OS/vm/sqMacUnixCommandLineInterface.c
   branches/Cog/platforms/unix/vm/sqUnixMain.c
   branches/Cog/platforms/win32/vm/sqWin32.h
   branches/Cog/platforms/win32/vm/sqWin32Intel.c
Log:
Add access to VM arguments to Mac.  Make Windows, Mac and Unix consistent:
        Smalltalk getSystemAttribute:
                -1 => executable name
                -2 .. -n => VM arguments *including* image (if explicitly supplied).
Replace win32 command line parsing with unixesque code using CommandLineToArgvW.



Property changes on: branches/Cog/platforms/Cross/vm/sqSCCSVersion.h
___________________________________________________________________
Modified: checkindate
   - Fri Nov 18 10:11:32 PST 2011
   + Mon Nov 28 11:03:00 PST 2011

Modified: branches/Cog/platforms/Mac OS/vm/sqMacUnixCommandLineInterface.c
===================================================================
--- branches/Cog/platforms/Mac OS/vm/sqMacUnixCommandLineInterface.c 2011-11-23 19:43:53 UTC (rev 2516)
+++ branches/Cog/platforms/Mac OS/vm/sqMacUnixCommandLineInterface.c 2011-11-28 19:07:44 UTC (rev 2517)
@@ -63,14 +63,14 @@
 char *unixArgcInterfaceGetParm(int n) {
  int actual;
 
- if (n < 0)
- actual = -n;
- else
+ if (n < 0) {
+ actual = -1 - n;
+ return actual < vmArgCnt ? vmArgVec[actual] : nil;
+ }
+ else {
  actual = n - 2;
-
- if (actual < squeakArgCnt)
- return squeakArgVec[actual];
- return nil;
+ return actual < squeakArgCnt ? squeakArgVec[actual] : nil;
+ }
 }
 
 void unixArgcInterface(int argc, char **argv, char **envp) {

Modified: branches/Cog/platforms/unix/vm/sqUnixMain.c
===================================================================
--- branches/Cog/platforms/unix/vm/sqUnixMain.c 2011-11-23 19:43:53 UTC (rev 2516)
+++ branches/Cog/platforms/unix/vm/sqUnixMain.c 2011-11-28 19:07:44 UTC (rev 2517)
@@ -434,12 +434,12 @@
 #endif
 
 static char *
-getAttribute(sqInt id)
+GetAttributeString(sqInt id)
 {
   if (id < 0) /* VM argument */
     {
-      if (-id  < vmArgCnt)
- return vmArgVec[-id];
+      if (-id  <= vmArgCnt)
+ return vmArgVec[-id - 1];
     }
   else
     switch (id)
@@ -492,13 +492,13 @@
 
 sqInt attributeSize(sqInt id)
 {
-  return strlen(getAttribute(id));
+  return strlen(GetAttributeString(id));
 }
 
 sqInt getAttributeIntoLength(sqInt id, sqInt byteArrayIndex, sqInt length)
 {
   if (length > 0)
-    strncpy(pointerForOop(byteArrayIndex), getAttribute(id), length);
+    strncpy(pointerForOop(byteArrayIndex), GetAttributeString(id), length);
   return 0;
 }
 
@@ -1633,7 +1633,8 @@
 # define mtfsfi(fpscr)
 #endif
 
-int main(int argc, char **argv, char **envp)
+int
+main(int argc, char **argv, char **envp)
 {
   fldcw(0x12bf); /* signed infinity, round to nearest, REAL8, disable intrs, disable signals */
   mtfsfi(0); /* disable signals, IEEE mode, round to nearest */

Modified: branches/Cog/platforms/win32/vm/sqWin32.h
===================================================================
--- branches/Cog/platforms/win32/vm/sqWin32.h 2011-11-23 19:43:53 UTC (rev 2516)
+++ branches/Cog/platforms/win32/vm/sqWin32.h 2011-11-28 19:07:44 UTC (rev 2517)
@@ -210,7 +210,7 @@
 /* The main() function used by NT services */
 int sqServiceMain(void);
 /* The generic main() function for starting squeak */
-int sqMain(char *lpCmdLine, int nCmdShow);
+int sqMain(int argc, char *argv[]);
 #endif
 
 /********************************************************/

Deleted: branches/Cog/platforms/win32/vm/sqWin32Args.c
===================================================================
--- branches/Cog/platforms/win32/vm/sqWin32Args.c 2011-11-23 19:43:53 UTC (rev 2516)
+++ branches/Cog/platforms/win32/vm/sqWin32Args.c 2011-11-28 19:07:44 UTC (rev 2517)
@@ -1,242 +0,0 @@
-/****************************************************************************
-*   PROJECT: Squeak port for Win32 (NT / Win95)
-*   FILE:    sqWin32Args.c
-*   CONTENT: Command line processing
-*
-*   AUTHOR:  Andreas Raab (ar)
-*   ADDRESS: University of Magdeburg, Germany
-*   EMAIL:   [hidden email]
-*   RCSID:   $Id: sqWin32Args.c 400 2002-05-26 18:52:10Z andreasraab $
-*
-*   NOTES:
-*
-*****************************************************************************/
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include "sq.h"
-#include "sqWin32Args.h"
-
-static int IsImage(char *name) {
-  int magic;
-  int byteSwapped(int);
-  sqImageFile fp;
-
-  fp = sqImageFileOpen(name,"rb");
-  if(!fp) return 0; /* not an image */
-  if(sqImageFileRead(&magic, 1, sizeof(magic), fp) != sizeof(magic)) {
-    sqImageFileClose(fp);
-    return 0;
-  }
-  if(readableFormat(magic) || readableFormat(byteSwapped(magic))) {
-    sqImageFileClose(fp);
-    return true;
-  }
-  
-  /* no luck at beginning of file, seek to 512 and try again */
-  sqImageFileSeek( fp, 512);
-  if(sqImageFileRead(&magic, 1, sizeof(magic), fp) != sizeof(magic)) {
-    sqImageFileClose(fp);
-    return 0;
-  }
-  sqImageFileClose(fp);
-  return readableFormat(magic) || readableFormat(byteSwapped(magic));
-}
-
-/* parse a possibly quoted string argument */
-static char *parseStringArg(char *src, char **argPtr)
-{
-  while(*src && *src == ' ') src++; /* skip blanks */
-  if(*src == '"') /* double quoted string */
-    {
-      (*argPtr)++;
-      do {
-        src++;
-        while(*src && *src != '"') src++;
-      } while(*src && *(src-1) == '\\');
-    }
-  else /* not quoted */
-    {
-      while(*src && *src != ' ') src++;
-    }
-  if(*src) *(src++) = 0;
-  return src;
-}
-
-/* parse an unsigned integer argument */
-static char *parseUnsignedArg(char *src, unsigned *dst)
-{ char buf[50];
-  char *tmp = buf;
-  unsigned multiplier = 1;
-
-  while(*src && *src == ' ') src++; /* skip blanks */
-  while(isdigit(*src)) *(tmp++) = *(src++);
-  if(*src && *src != ' ') { /* suffix or strange chars at end */
-    switch (*src) {
-    case 'k': case 'K':
-      multiplier = 1024;
-      break;
-    case 'm': case 'M':
-      multiplier = 1024*1024;
-      break;
- default:
-      return NULL;
-    }
-  }
-  if(tmp == buf) /* no numbers found */
-    return NULL;
-  *dst = atol(buf) * multiplier;
-  if(*src) *(src++) = 0;
-  return src;
-}
-
-/* parse a (possibly signed) integer argument */
-static char *parseSignedArg(char *src, int *dst)
-{
-  int negative;
-  unsigned value;
-
-  while(*src && *src == ' ') src++; /* skip blanks */
-  negative = *src == '-';
-  if(negative) src++;
-  src = parseUnsignedArg(src, &value);
-  if(!src) return NULL;
-  if(negative) *dst = 0-(int)value;
-  else *dst = (int) value;
-  return src;
-}
-
-/* parse all arguments meaningful to the VM */
-static char* parseVMArgs(char *string, vmArg args[])
-{ vmArg *arg;
-  int arglen;
-
-  while(1)
-    {
-      if(numOptionsVM >= MAX_OPTIONS)
-        return NULL; /* too many args */
-      while(*string && *string == ' ') string++; /* skip blanks */
-      if(*string != '-') return string; /* image name */
-      vmOptions[numOptionsVM++] = string;
-
-      /* search args list */
-      arg = args;
-      while(arg->type != ARG_NONE)
-        {
-          arglen = strlen(arg->name);
-          if(strncmp(arg->name, string, strlen(arg->name)) == 0)
-            break;
-          arg++;
-        }
-      if(arg->type == ARG_NONE)
-        return string; /* done */
-
-      string += arglen;
-  /* can't just bash the string; if we have -breaksel:at:put: this would
-   * truncate breaksel to t:put:.
-   */
-      if (*string)
- if (*string == ' ')
- *(string++) = 0;
- else {
- char save = *string;
- *string = 0;
- vmOptions[numOptionsVM - 1] = strdup(vmOptions[numOptionsVM - 1]);
- *string = save;
- }
-
-      while(*string && *string == ' ') string++; /* skip blanks */
-
-      switch(arg->type) {
-        case ARG_FLAG:
-          *(int*)arg->value = 1;
-          break;
-
-        case ARG_STRING:
-        case ARG_STRING_FUNC: {
-  char *theValue;
-          vmOptions[numOptionsVM++] = theValue = string;
-          string = parseStringArg(string, &theValue);
-  if (arg->type == ARG_STRING)
-            *(char**) arg->value = theValue;
-  else
- ((void (*)(char *))(arg->value))(theValue);
-          if(!string) return NULL;
-          break;
- }
-
-        case ARG_INT_FUNC: {
-  int dummy;
-          vmOptions[numOptionsVM++] = string;
-          string = parseSignedArg(string, &dummy);
-          ((void (*)(int))(arg->value))(dummy);
-          if(!string) return NULL;
-          break;
- }
-        case ARG_INT:
-          vmOptions[numOptionsVM++] = string;
-          *(char**) arg->value = string;
-          string = parseSignedArg(string, (int*)arg->value);
-          if(!string) return NULL;
-          break;
-
-        case ARG_UINT:
-          vmOptions[numOptionsVM++] = string;
-          *(char**) arg->value = string;
-          string = parseUnsignedArg(string, (unsigned int*)arg->value);
-          if(!string) return NULL;
-          break;
-
-        case ARG_NULL:
-          return NULL;
-
-        default:
-          fprintf(stderr,"Unknown option encountered!\n");
-          return NULL;
-       };
-    }
-}
-
-/* parse all arguments starting with the image name */
-static char *parseGenericArgs(char *string)
-{ char *tmpImageName;
-
-  while(*string && *string == ' ') string++; /* skip blanks */
-  /* now get the image name */
-  tmpImageName = string;
-  string = parseStringArg(string, &tmpImageName);
-  if(!string) return NULL; /* parse error */
-  if(*imageName == 0) {
- /* only attempt to use image name if none is provided */
- if(*tmpImageName && IsImage(tmpImageName))
-      strcpy(imageName, tmpImageName);
-  } else {
-  /* provide image name as second argument if implicitly specified */
-  imageOptions[numOptionsImage++] = imageName;
-  }
-  imageOptions[numOptionsImage++] = tmpImageName;
-  while(string && *string)
-    {
-      if(numOptionsImage > MAX_OPTIONS) return string; /* too many args */
-      while(*string && *string == ' ') string++; /* skip blanks */
-      imageOptions[numOptionsImage++] = string;
-      string = parseStringArg(string, &(imageOptions[numOptionsImage-1]));
-      if(!string) return NULL;
-    }
-  return string;
-}
-
-int parseArguments(char *cmdLine, vmArg args[])
-{
-  /* argv[0] = executable name */
-  vmOptions[numOptionsVM++] = cmdLine;
-  cmdLine = parseStringArg(cmdLine, &(vmOptions[numOptionsVM-1]));
-  if(!cmdLine) return 0;
-  /* parse VM options */
-  cmdLine = parseVMArgs(cmdLine, args);
-  if(cmdLine == NULL) return 0;
-  /* parse image and generic args */
-  cmdLine = parseGenericArgs(cmdLine);
-  return cmdLine != NULL;
-}

Deleted: branches/Cog/platforms/win32/vm/sqWin32Args.h
===================================================================
--- branches/Cog/platforms/win32/vm/sqWin32Args.h 2011-11-23 19:43:53 UTC (rev 2516)
+++ branches/Cog/platforms/win32/vm/sqWin32Args.h 2011-11-28 19:07:44 UTC (rev 2517)
@@ -1,50 +0,0 @@
-#ifndef __SQ_ARGS_H
-#define __SQ_ARGS_H
-
-/* Squeak command line parsing helpers */
-
-#define MAX_OPTIONS 1024
-
-extern int numOptionsVM;
-extern char *(vmOptions[MAX_OPTIONS]);
-extern int numOptionsImage;
-extern char *(imageOptions[MAX_OPTIONS]);
-
-/* this goes separately so that we can insert the "hidden" name */
-extern char imageName[];
-
-#define ARG_NONE        0
-#define ARG_FLAG        1
-#define ARG_STRING      2
-#define ARG_INT         3
-#define ARG_UINT        4
-#define ARG_STRING_FUNC 5
-#define ARG_INT_FUNC    6
-#define ARG_NULL 7
-
-typedef struct vmArg{
-  int   type;
-  void *value;
-  char *name;
-} vmArg;
-
-/* use like:
-
-  int headlessFlag;
-  char *logFilename;
-  unsigned int memorySize;
-
-  sqArg args[] = {
-    { ARG_FLAG,   &headlessFlag, "-headless" },
-    { ARG_STRING, &logFilename, "-log:" },
-    { ARG_UINT,    &memorySize, "-memory:"},
-    { ARG_NULL,    0, "--help"},
-    { ARG_NONE, NULL, NULL }
-  };
-*/
-
-
-int parseArguments(char *cmdLine, vmArg args[]);
-
-#endif /* sqArgs.h */
-

Modified: branches/Cog/platforms/win32/vm/sqWin32Intel.c
===================================================================
--- branches/Cog/platforms/win32/vm/sqWin32Intel.c 2011-11-23 19:43:53 UTC (rev 2516)
+++ branches/Cog/platforms/win32/vm/sqWin32Intel.c 2011-11-28 19:07:44 UTC (rev 2517)
@@ -19,7 +19,6 @@
 #include <float.h>
 #include <ole2.h>
 #include "sq.h"
-#include "sqWin32Args.h"
 #include "sqWin32Backtrace.h"
 #if COGVM
 # include "cogmethod.h"
@@ -52,11 +51,13 @@
 static void printCrashDebugInformation(LPEXCEPTION_POINTERS exp);
 
 /*** Variables -- command line */
-char *initialCmdLine;
-int  numOptionsVM = 0;
-char *(vmOptions[MAX_OPTIONS]);
-int  numOptionsImage = 0;
-char *(imageOptions[MAX_OPTIONS]);
+static char *initialCmdLine;
+static int  numOptionsVM = 0;
+static char **vmOptions;
+static int  numOptionsImage = 0;
+static char **imageOptions;
+static int clargc; /* the Unix-style command line, saved for GetImageOption */
+static char **clargv;
 
 /* console buffer */
 TCHAR consoleBuffer[4096];
@@ -1187,62 +1188,22 @@
 extern sqInt minBackwardJumpCountForCompile;
 #endif /* COGVM */
 
-static vmArg args[] = {
-  { ARG_NULL, 0, "--help" }, /* the name of a service */
-  { ARG_STRING, &installServiceName, "-service:" }, /* the name of a service */
-  { ARG_FLAG, &fHeadlessImage, "-headless" },       /* do we run headless? */
-  { ARG_STRING, &logName, "-log:" },                /* VM log file */
-  { ARG_UINT, &dwMemorySize, "-memory:" },          /* megabyte of memory to use */
-#ifdef  VISTA_SECURITY /* IE7/Vista protected mode support */
-  { ARG_FLAG, &fLowRights, "-lowRights" }, /* started with low rights,
- use alternate untrustedUserDirectory */
-#endif /* VISTA_SECURITY */
-#if (STACKVM || NewspeakVM) && !COGVM
-  { ARG_FLAG, &sendTrace, "-sendtrace"},
-#endif
-#if STACKVM || NewspeakVM
-  { ARG_STRING_FUNC, setBreakSelector, "-breaksel:"}, /* break-point selector string */
-  { ARG_INT_FUNC, ioSetMaxExtSemTableSize, "-numextsems:"}, /* set num external semaphores */
-#endif /* STACKVM || NewspeakVM */
-#if STACKVM
-  { ARG_UINT, &checkForLeaks, "-leakcheck:"}, /* leak check on GC */
-  { ARG_UINT, &desiredEdenBytes, "-eden:" },        /* bytes of eden to use */
-  { ARG_UINT, &desiredNumStackPages, "-stackpages:"}, /* n stack pages to use */
-  { ARG_FLAG, &suppressHeartbeatFlag, "-noheartbeat"}, /* no heartbeat for dbg */
-#endif /* STACKVM */
-#if COGVM
-  { ARG_UINT, &desiredCogCodeSize, "-codesize:"}, /* machine code memory to use */
-  { ARG_UINT, &traceLinkedSends, "-sendtrace:" },  /* trace sends in log */
-  { ARG_INT, &traceLinkedSends, "-trace:" },  /* trace sends in log */
-  { ARG_FLAG, &traceStores, "-tracestores" },     /* assert-check stores */
-  { ARG_UINT, &debugPrimCallStackOffset, "-dpcso:"}, /* debug prim call stack offset */
-  { ARG_UINT, &maxLiteralCountForCompile, "-cogmaxlits:"}, /* max # of literals for a method to be compiled to machine code */
-  { ARG_UINT, &minBackwardJumpCountForCompile, "-cogminjumps:"}, /* max # of literals for a method to be compiled to machine code */
-#endif /* COGVM */
 
-  /* NOTE: the following flags are "undocumented" */
-  { ARG_INT, &browserWindow, "-browserWindow:"},    /* The web browser window we run in */
-
-  /* service support on 95 */
-  { ARG_FLAG, &fRunService, "-service95" },           /* do we start as service? */
-  { ARG_FLAG, &fBroadcastService95, "-broadcast95" }, /* should we notify services of a user logon? */
-  { ARG_NONE, NULL, NULL }
-};
-
 /* sqMain:
-   This is common entry point regardless of whether we're running
-   as a normal app or as a service. Note that a number of things
-   may have been set up before coming here. In particular,
-   * fRunService - to determine whether we're running as NT service
-   However, the command line must always contain all parameters necessary.
-   In other words, even though the logName may have been set before,
-   the command line has to include the -log: switch.
+ This is common entry point regardless of whether we're running as a normal
+ app or as a service. Note that a number of things may have been set up
+ before coming here. In particular,
+ * fRunService - to determine whether we're running as NT service
+ However, the command line must always contain all parameters necessary.
+ In other words, even though the logName may have been set before,
+ the command line has to include the -log switch.
 */
-int sqMain(char *lpCmdLine, int nCmdShow)
+static int parseArguments(int argc, char *argv[]);
+
+int
+sqMain(int argc, char *argv[])
 {
   int virtualMemory;
-  WCHAR *cmdLineW;
-  char *cmdLineA;
   int sz;
 
   /* set default fpu control word */
@@ -1250,12 +1211,6 @@
 
   LoadPreferences();
 
-  /* Fetch the command line */
-  cmdLineW = GetCommandLineW();
-  sz = WideCharToMultiByte(CP_UTF8, 0, cmdLineW, -1, NULL, 0, NULL, NULL);
-  cmdLineA = calloc(sz, sizeof(char));
-  WideCharToMultiByte(CP_UTF8, 0, cmdLineW, -1, cmdLineA, sz, NULL, NULL);
-
   /* If running as single app, find the previous instance */
   if(fRunSingleApp) {
     HWND win = GetTopWindow(0);
@@ -1267,6 +1222,7 @@
     }
 
     if(win) {
+  WCHAR *cmdLineW = GetCommandLineW();
       /* An instance is running already. Inform it about the app. */
       int bytes = (wcslen(cmdLineW)+1) * sizeof(WCHAR);
       HANDLE h = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, bytes);
@@ -1287,7 +1243,7 @@
   }
 
   /* parse command line args */
-  if(!parseArguments(cmdLineA, args))
+  if(!parseArguments(argc, argv))
     return printUsage(1);
 
   /* a quick check if we have any argument at all */
@@ -1458,10 +1414,9 @@
 /****************************************************************************/
 /*                        WinMain                                           */
 /****************************************************************************/
-int WINAPI WinMain (HINSTANCE hInst,
-                    HINSTANCE hPrevInstance,
-                    LPSTR  lpCmdLine,
-                    int    nCmdShow)
+
+int WINAPI
+WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
 {
   /* a few things which need to be done first */
   gatherSystemInfo();
@@ -1478,6 +1433,29 @@
     GetModuleFileNameW(hInst, vmNameW, MAX_PATH);
     WideCharToMultiByte(CP_UTF8, 0, vmNameW, -1, vmName, MAX_PATH, NULL, NULL);
   }
+ /* parse the command line into the unix-style argc, argv, converting to
+ * UTF-8 on the way. */
+  { LPWSTR *argList = CommandLineToArgvW(GetCommandLineW(), &clargc);
+ int i;
+
+ clargv = calloc(clargc + 1, sizeof(char *));
+ vmOptions = calloc(clargc + 1, sizeof(char *));
+ imageOptions = calloc(clargc + 1, sizeof(char *));
+ if (!clargv || !vmOptions || !imageOptions) {
+ fprintf(stderr,"out of memory for command line?!\n");
+ return 1;
+ }
+ for (i = 0; i < clargc; i++) {
+     int n = WideCharToMultiByte(CP_UTF8, 0, argList[i], -1, 0, 0, 0, 0);
+ if (!(clargv[i] = malloc(n))) {
+ fprintf(stderr,"out of memory for command line?!\n");
+ return 1;
+ }
+     WideCharToMultiByte(CP_UTF8, 0, argList[i], -1, clargv[i], n, 0, 0);
+ }
+ LocalFree(argList);
+  }
+
   /* open all streams in binary mode */
   _fmode  = _O_BINARY;
 
@@ -1518,11 +1496,257 @@
   }
 
   /* start the non-service version */
-  sqMain(lpCmdLine, nCmdShow);
+  sqMain(clargc, clargv);
   return 0;
 }
 
+static int
+strtobkm(const char *str)
+{
+ char *suffix;
+ int value = strtol(str, &suffix, 10);
+ switch (*suffix) {
+ case 'k': case 'K': value *= 1024; break;
+ case 'm': case 'M': value *= 1024*1024; break;
+ }
+ return value;
+}
+
+static int
+parseVMArgument(int argc, char *argv[])
+{
+ /* flags */
+ if      (!strcmp(argv[0], "-help")) {
+ printUsage(1);
+ return 1; }
+ else if (!strcmp(argv[0], "-headless")) { fHeadlessImage = true; return 1; }
+ else if (!strcmp(argv[0], "-headfull")) { fHeadlessImage = false; return 1;}
+#ifdef  VISTA_SECURITY /* IE7/Vista protected mode support */
+ /* started with low rights, use alternate untrustedUserDirectory */
+ else if (!strcmp(argv[0], "-lowRights")) { fLowRights = true; return 1; }
+#endif /* VISTA_SECURITY */
+#if (STACKVM || NewspeakVM) && !COGVM
+ else if (!strcmp(argv[0], "-sendtrace"))
+ { extern sqInt sendTrace; sendTrace = 1; return 1; }
+#endif
+
+ /* parameters */
+ else if (argc > 1 && !strcmp(argv[0], "-service")) {
+ installServiceName = argv[1];
+ return 2;
+ }
+ else if (!strncmp(argv[0], "-service:", 9)) {
+ installServiceName = argv[0] + 9;
+ return 1;
+ }
+ else if (argc > 1 && !strcmp(argv[0], "-log")) {
+ logName = argv[1];
+ return 2;
+ }
+ else if (!strncmp(argv[0], "-log:", 5)) {
+ logName = argv[0] + 5;
+ return 1;
+ }
+ else if (argc > 1 && !strcmp(argv[0], "-memory")) {
+ dwMemorySize = strtobkm(argv[1]);
+ return 2;
+ }
+ else if (!strncmp(argv[0], "-memory:", 8)) {
+ dwMemorySize = strtobkm(argv[0] + 8);
+ return 1;
+ }
+#if STACKVM || NewspeakVM
+ else if (argc > 1 && !strcmp(argv[0], "-breaksel")) {
+ extern void setBreakSelector(char *);
+ setBreakSelector(argv[1]);
+ return 2; }
+ else if (!strncmp(argv[0], "-breaksel:", 10)) {
+ extern void setBreakSelector(char *);
+ setBreakSelector(argv[0] + 10);
+ return 1; }
+ else if (argc > 1 && !strcmp(argv[0], "-numextsems")) {
+ ioSetMaxExtSemTableSize(atoi(argv[1]));
+ return 2; }
+ else if (!strncmp(argv[0], "-numextsems:", 12)) {
+ ioSetMaxExtSemTableSize(atoi(argv[1]+12));
+ return 1; }
+#endif /* STACKVM || NewspeakVM */
+#if STACKVM
+ else if (argc > 1 && !strcmp(argv[0], "-eden")) {
+ extern sqInt desiredEdenBytes;
+ desiredEdenBytes = strtobkm(argv[1]);
+ return 2; }
+ else if (!strncmp(argv[0], "-eden:", 6)) {
+ extern sqInt desiredEdenBytes;
+ desiredEdenBytes = strtobkm(argv[0]+6);
+ return 2; }
+ else if (argc > 1 && !strcmp(argv[0], "-leakcheck")) {
+ extern sqInt checkForLeaks;
+ checkForLeaks = atoi(argv[1]);
+ return 2; }
+ else if (!strncmp(argv[0], "-leakcheck:", 11)) {
+ extern sqInt checkForLeaks;
+ checkForLeaks = atoi(argv[0]+11);
+ return 2; }
+ else if (argc > 1 && !strcmp(argv[0], "-stackpages")) {
+ extern sqInt desiredNumStackPages;
+ desiredNumStackPages = atoi(argv[1]);
+ return 2; }
+ else if (!strncmp(argv[0], "-stackpages:", 12)) {
+ extern sqInt desiredNumStackPages;
+ desiredNumStackPages = atoi(argv[0]+12);
+ return 2; }
+ else if (!strcmp(argv[0], "-noheartbeat")) {
+ extern sqInt suppressHeartbeatFlag;
+ suppressHeartbeatFlag = 1;
+ return 1; }
+#endif /* STACKVM */
 #if COGVM
+ else if (!strcmp(argv[0], "-codesize")) {
+ extern sqInt desiredCogCodeSize;
+ desiredCogCodeSize = strtobkm(argv[1]);
+ return 2; }
+# define TLSLEN (sizeof("-sendtrace")-1)
+ else if (!strncmp(argv[0], "-sendtrace", TLSLEN)) {
+ extern int traceLinkedSends;
+ char *equalsPos = strchr(argv[0],'=');
+
+ if (!equalsPos) {
+ traceLinkedSends = 1;
+ return 1;
+ }
+ if (equalsPos - argv[0] != TLSLEN
+  || (equalsPos[1] != '-' && !isdigit(equalsPos[1])))
+ return 0;
+
+ traceLinkedSends = atoi(equalsPos + 1);
+ return 1; }
+ else if (!strcmp(argv[0], "-tracestores")) {
+ extern sqInt traceStores;
+ traceStores = 1;
+ return 1; }
+ else if (!strcmp(argv[0], "-dpcso")) {
+ extern unsigned long debugPrimCallStackOffset;
+ debugPrimCallStackOffset = (unsigned long)strtobkm(argv[1]);
+ return 2; }
+ else if (argc > 1 && !strcmp(argv[0], "-cogmaxlits")) {
+ extern sqInt maxLiteralCountForCompile;
+ maxLiteralCountForCompile = strtobkm(argv[1]);
+ return 2; }
+ else if (!strncmp(argv[0], "-cogmaxlits:", 12)) {
+ extern sqInt maxLiteralCountForCompile;
+ maxLiteralCountForCompile = strtobkm(argv[0]+12);
+ return 2; }
+ else if (argc > 1 && !strcmp(argv[0], "-cogminjumps")) {
+ extern sqInt minBackwardJumpCountForCompile;
+ minBackwardJumpCountForCompile = strtobkm(argv[1]);
+ return 2; }
+ else if (!strncmp(argv[0], "-cogminjumps:",13)) {
+ extern sqInt minBackwardJumpCountForCompile;
+ minBackwardJumpCountForCompile = strtobkm(argv[0]+13);
+ return 2; }
+#endif /* COGVM */
+
+  /* NOTE: the following flags are "undocumented" */
+ else if (argc > 1 && !strcmp(argv[0], "-browserWindow")) {
+ browserWindow = (HWND)atoi(argv[1]);
+ return 2; }
+ else if (!strncmp(argv[0], "-browserWindow:", 15)) {
+ browserWindow = (HWND)atoi(argv[0]+15);
+ return 1; }
+
+ /* service support on 95 */
+ else if (!strcmp(argv[0], "-service95")) { fRunService = true; return 1; }
+ else if (!strcmp(argv[0], "-broadcast95")) { fBroadcastService95 = true; return 1; }
+
+ return 0; /* option not recognised */
+}
+
+/* parse all arguments meaningful to the VM; answer index of last VM arg + 1 */
+static int
+parseVMArgs(int argc, char *argv[])
+{ int n, i = 0, j;
+
+ while (++i < argc && *argv[i] == '-' && strcmp(argv[i],"--")) {
+        if ((n = parseVMArgument(argc - i, argv + i))) {
+ for (j = 0; j < n; j++)
+ vmOptions[numOptionsVM++] = argv[i+j];
+ }
+ else {
+          fprintf(stderr,"Unknown option encountered!\n");
+          return i;
+ }
+ }
+ return i;
+}
+
+static int
+IsImage(char *name)
+{
+ int magic;
+ int byteSwapped(int);
+ sqImageFile fp;
+
+ fp = sqImageFileOpen(name,"rb");
+ if(!fp) return 0; /* not an image */
+ if(sqImageFileRead(&magic, 1, sizeof(magic), fp) != sizeof(magic)) {
+ sqImageFileClose(fp);
+ return 0;
+ }
+ if(readableFormat(magic) || readableFormat(byteSwapped(magic))) {
+ sqImageFileClose(fp);
+ return true;
+ }
+
+ /* no luck at beginning of file, seek to 512 and try again */
+ sqImageFileSeek( fp, 512);
+ if(sqImageFileRead(&magic, 1, sizeof(magic), fp) != sizeof(magic)) {
+ sqImageFileClose(fp);
+ return 0;
+ }
+ sqImageFileClose(fp);
+ return readableFormat(magic) || readableFormat(byteSwapped(magic));
+}
+
+/* parse all arguments starting with the image name */
+static int
+parseGenericArgs(int argc, char *argv[])
+{ int i;
+
+ if (argc < 1)
+ return 0;
+
+ if (*imageName == 0) { /* only try to use image name if none is provided */
+ if (*argv[0] && IsImage(argv[0])) {
+ strcpy(imageName, argv[0]);
+ /* if provided, the image is a vm argument. */
+ vmOptions[numOptionsVM++] = argv[0];
+ }
+ }
+ else /* provide image name as second argument if implicitly specified */
+ imageOptions[numOptionsImage++] = imageName;
+
+ imageOptions[numOptionsImage++] = argv[0];
+ for (i = 1; i < argc; i++)
+ imageOptions[numOptionsImage++] = argv[i];
+
+  return 1;
+}
+
+static int
+parseArguments(int argc, char *argv[])
+{
+ int nvmargs;
+
+ /* argv[0] = executable name */
+ vmOptions[numOptionsVM++] = argv[0];
+ /* parse VM options */
+ nvmargs = parseVMArgs(argc, argv);
+ /* parse image and generic args */
+ return parseGenericArgs(argc - nvmargs, argv + nvmargs);
+}
+
+#if COGVM
 /*
  * Support code for Cog.
  * a) Answer whether the C frame pointer is in use, for capture of the C stack