/* Python interpreter main program */

#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <windows.h>
#include "uplaunch.h"
#include "osdefs.h"
#define CO_FUTURE_DIVISION    	0x2000
#define Py_GETENV(s) (*Py_IgnoreEnvironmentFlag ? NULL : getenv(s))

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef WIN32
#include <fcntl.h>
#endif

#if defined(PYOS_OS2) || defined(WIN32)
#define PYTHONHOMEHELP "<prefix>\\lib"
#else
#define PYTHONHOMEHELP "<prefix>/pythonX.X"
#endif

typedef struct {
	int cf_flags;
} PyCompilerFlags;

DECLVAR(int,Py_DebugFlag);
DECLVAR(int,Py_DivisionWarningFlag);
DECLVAR(int,_Py_QnewFlag);
DECLVAR(int,Py_InteractiveFlag);
DECLVAR(int,Py_OptimizeFlag);
DECLVAR(int,Py_NoSiteFlag);
DECLVAR(int,Py_IgnoreEnvironmentFlag);
DECLVAR(int,Py_TabcheckFlag);
DECLVAR(int,Py_VerboseFlag);
DECLVAR(int,Py_UnicodeFlag);
/*DECLPROC(int,_PyOS_GetOpt,(int,char**,char*));*/
/*DECLVAR(int,_PyOS_opterr);*/
/*DECLVAR(int,_PyOS_optind);*/
/*DECLVAR(char*,_PyOS_optarg);*/
DECLPROC(void,PySys_ResetWarnOptions,(void));
DECLPROC(void,Py_FatalError,(char*));
DECLPROC(void,PySys_AddWarnOption,(char*));
DECLPROC(int,Py_FdIsInteractive,(FILE*,char*));
DECLPROC(void,Py_SetProgramName,(char*));
DECLPROC(int,Py_Initialize,(void));
DECLPROC(int,Py_Finalize,(void));
DECLPROC(const char*,Py_GetVersion,(void));
DECLPROC(const char*,Py_GetPlatform,(void));
DECLPROC(int,PySys_SetArgv,(int,char**));
DECLPROC(PyObject*,PyImport_ImportModule,(char*));
DECLPROC(void,PyErr_Clear,(void));
DECLPROC(int,PyRun_SimpleStringFlags,(char*,PyCompilerFlags*));
DECLPROC(int,PyRun_SimpleFile,(FILE*,char*));
DECLPROC(int,PyRun_AnyFileExFlags,(FILE*,char*,int,PyCompilerFlags*));
DECLPROC(int,PyRun_AnyFileFlags,(FILE*,char*,PyCompilerFlags*));
DECLPROC(char*,Py_GetPath,(void));
DECLPROC(PyObject*, PyString_FromFormatV, (const char*,...));
DECLPROC(int, PyRun_SimpleString, (char *));
DECLPROC(char*, PyString_AsString, (PyObject *));
DECLPROC(void, Py_SetPythonHome, (char *));

#define COPYRIGHT \
    "Type \"help\", \"copyright\", \"credits\" or \"license\" " \
    "for more information."

/* For Py_GetArgcArgv(); set by main() */
static char **orig_argv;
static int  orig_argc;

/* command line options */
#define BASE_OPTS "c:dEhiOQ:StuUvVW:xX"

#ifndef RISCOS
#define PROGRAM_OPTS BASE_OPTS
#else /*RISCOS*/
/* extra option saying that we are running under a special task window
   frontend; especially my_readline will behave different */
#define PROGRAM_OPTS BASE_OPTS "w"
/* corresponding flag */
extern int Py_RISCOSWimpFlag;
#endif /*RISCOS*/

/* Short usage message (with %s for argv0) */
static char *usage_line =
"usage: %s [option] ... [-c cmd | file | -] [arg] ...\n";

/* Long usage message, split into parts < 512 bytes */
static char *usage_1 = "\
Options and arguments (and corresponding environment variables):\n\
-c cmd : program passed in as string (terminates option list)\n\
-d     : debug output from parser (also PYTHONDEBUG=x)\n\
-E     : ignore environment variables (such as PYTHONPATH)\n\
-h     : print this help message and exit\n\
-i     : inspect interactively after running script, (also PYTHONINSPECT=x)\n\
         and force prompts, even if stdin does not appear to be a terminal\n\
";
static char *usage_2 = "\
-O     : optimize generated bytecode (a tad; also PYTHONOPTIMIZE=x)\n\
-OO    : remove doc-strings in addition to the -O optimizations\n\
-Q arg : division options: -Qold (default), -Qwarn, -Qwarnall, -Qnew\n\
-S     : don't imply 'import site' on initialization\n\
-t     : issue warnings about inconsistent tab usage (-tt: issue errors)\n\
-u     : unbuffered binary stdout and stderr (also PYTHONUNBUFFERED=x)\n\
";
static char *usage_3 = "\
-v     : verbose (trace import statements) (also PYTHONVERBOSE=x)\n\
-V     : print the Python version number and exit\n\
-W arg : warning control (arg is action:message:category:module:lineno)\n\
-x     : skip first line of source, allowing use of non-Unix forms of #!cmd\n\
file   : program read from script file\n\
-      : program read from stdin (default; interactive mode if a tty)\n\
";
static char *usage_4 = "\
arg ...: arguments passed to program in sys.argv[1:]\n\
Other environment variables:\n\
PYTHONSTARTUP: file executed on interactive startup (no default)\n\
PYTHONPATH   : '%c'-separated list of directories prefixed to the\n\
               default module search path.  The result is sys.path.\n\
PYTHONHOME   : alternate <prefix> directory (or <prefix>%c<exec_prefix>).\n\
               The default module search path uses %s.\n\
PYTHONCASEOK : ignore case in 'import' statements (Windows).\n\
";

#include "_rl_startup.h"
static int _PyOS_optind = 1;
static int _PyOS_opterr = 1;
static char* _PyOS_optarg = NULL;
static int _PyOS_GetOpt(int argc, char **argv, char *optstring)
{
	static char *opt_ptr = "";
	char *ptr;
	int option;

	if (*opt_ptr == '\0') {

		if (_PyOS_optind >= argc || argv[_PyOS_optind][0] != '-' ||
		    argv[_PyOS_optind][1] == '\0' /* lone dash */ )
			return -1;

		else if (strcmp(argv[_PyOS_optind], "--") == 0) {
			++_PyOS_optind;
			return -1;
		}

		opt_ptr = &argv[_PyOS_optind++][1]; 
	}

	if ( (option = *opt_ptr++) == '\0')
		return -1;
	
	if ((ptr = strchr(optstring, option)) == NULL) {
		if (_PyOS_opterr)
			fprintf(stderr, "Unknown option: -%c\n", option);

		return '?';
	}

	if (*(ptr + 1) == ':') {
		if (*opt_ptr != '\0') {
			_PyOS_optarg  = opt_ptr;
			opt_ptr = "";
		}

		else {
			if (_PyOS_optind >= argc) {
				if (_PyOS_opterr)
					fprintf(stderr,
			    "Argument expected for the -%c option\n", option);
				return '?';
			}

			_PyOS_optarg = argv[_PyOS_optind++];
		}
	}

	return option;
}
static void usage(int exitcode, char* program)
{
	FILE *f = exitcode ? stderr : stdout;

	fprintf(f, usage_line, program);
	if (exitcode)
		fprintf(f, "Try `python -h' for more information.\n");
	else {
		fprintf(f, usage_1);
		fprintf(f, usage_2);
		fprintf(f, usage_3);
		fprintf(f, usage_4, DELIM, DELIM, PYTHONHOMEHELP);
	}
	exit(exitcode);
	/*NOTREACHED*/
}

int PyRun_Format(const char *format, ...)
{
	va_list vargs;
	PyObject* string;
	int	i = -1;

	va_start(vargs, format);
	string = PyString_FromFormatV(format, vargs);
	if(string){
		i = PyRun_SimpleString(PyString_AsString(string));
		Py_DECREF(string);
		}
	va_end(vargs);
	return i;
}

/* Main program */
static int Py_Main(int argc, char **argv, char *thisfile, char* homepath, char *project, int pyvers)
{
	int c;
	int sts;
	char *command = NULL;
	char *filename = NULL;
	FILE *fp = stdin;
	char *p;
	int inspect = 0;
	int unbuffered = 0;
	int skipfirstline = 0;
	int stdin_is_interactive = 0;
	int help = 0;
	int version = 0;
	int saw_inspect_flag = 0;
	int saw_unbuffered_flag = 0;
	PyCompilerFlags cf;
#ifndef NO_RL_PYZ_STARTUP
	char* pypath;
#endif
	int	orgNoSiteFlag;

	cf.cf_flags = 0;

	orig_argc = argc;	/* For Py_GetArgcArgv() */
	orig_argv = argv;

#ifdef RISCOS
	Py_RISCOSWimpFlag = 0;
#endif

	PySys_ResetWarnOptions();

	while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
		if (c == 'c') {
			/* -c is the last option; following arguments
			   that look like options are left for the
			   the command to interpret. */
			command = malloc(strlen(_PyOS_optarg) + 2);
			if (command == NULL)
				Py_FatalError(
				   "not enough memory to copy -c argument");
			strcpy(command, _PyOS_optarg);
			strcat(command, "\n");
			break;
		}

		switch (c) {

		case 'd':
			*Py_DebugFlag++;
			break;

		case 'Q':
			if (strcmp(_PyOS_optarg, "old") == 0) {
				*Py_DivisionWarningFlag = 0;
				break;
			}
			if (strcmp(_PyOS_optarg, "warn") == 0) {
				*Py_DivisionWarningFlag = 1;
				break;
			}
			if (strcmp(_PyOS_optarg, "warnall") == 0) {
				*Py_DivisionWarningFlag = 2;
				break;
			}
			if (strcmp(_PyOS_optarg, "new") == 0) {
				/* This only affects __main__ */
				cf.cf_flags |= CO_FUTURE_DIVISION;
				/* And this tells the eval loop to treat
				   BINARY_DIVIDE as BINARY_TRUE_DIVIDE */
				*_Py_QnewFlag = 1;
				break;
			}
			fprintf(stderr,
				"-Q option should be `-Qold', "
				"`-Qwarn', `-Qwarnall', or `-Qnew' only\n");
			usage(2, argv[0]);
			/* NOTREACHED */

		case 'i':
			inspect++;
			saw_inspect_flag = 1;
			*Py_InteractiveFlag++;
			break;

		case 'O':
			*Py_OptimizeFlag++;
			break;

		case 'S':
			*Py_NoSiteFlag++;
			break;

		case 'E':
			*Py_IgnoreEnvironmentFlag++;
			break;

		case 't':
			*Py_TabcheckFlag++;
			break;

		case 'u':
			unbuffered++;
			saw_unbuffered_flag = 1;
			break;

		case 'v':
			*Py_VerboseFlag++;
			break;

#ifdef RISCOS
		case 'w':
			*Py_RISCOSWimpFlag = 1;
			break;
#endif

		case 'x':
			skipfirstline = 1;
			break;

		case 'U':
			*Py_UnicodeFlag++;
			break;
		case 'h':
			help++;
			break;
		case 'V':
			version++;
			break;

		case 'W':
			PySys_AddWarnOption(_PyOS_optarg);
			break;

		/* This space reserved for other options */

		default:
			usage(2, argv[0]);
			/*NOTREACHED*/

		}
	}

	if (help)
		usage(0, argv[0]);

	if (version) {
		fprintf(stderr, "RL Python%d\n", pyvers);
		exit(0);
	}

	if (!saw_inspect_flag &&
	    (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
		inspect = 1;
	if (!saw_unbuffered_flag &&
	    (p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
		unbuffered = 1;

	if (command == NULL && _PyOS_optind < argc &&
	    strcmp(argv[_PyOS_optind], "-") != 0)
	{
		filename = argv[_PyOS_optind];
		if (filename != NULL) {
			if ((fp = fopen(filename, "r")) == NULL) {
				fprintf(stderr, "%s: can't open file '%s'\n",
					argv[0], filename);
				exit(2);
			}
			else if (skipfirstline) {
				int ch;
				/* Push back first newline so line numbers
				   remain the same */
				while ((ch = getc(fp)) != EOF) {
					if (ch == '\n') {
						(void)ungetc(ch, fp);
						break;
					}
				}
			}
		}
	}

	stdin_is_interactive = Py_FdIsInteractive(stdin, (char *)0);

	if (unbuffered) {
#ifdef WIN32
		_setmode(fileno(stdin), O_BINARY);
		_setmode(fileno(stdout), O_BINARY);
#endif
#ifndef MPW
#ifdef HAVE_SETVBUF
		setvbuf(stdin,  (char *)NULL, _IONBF, BUFSIZ);
		setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
		setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ);
#else /* !HAVE_SETVBUF */
		setbuf(stdin,  (char *)NULL);
		setbuf(stdout, (char *)NULL);
		setbuf(stderr, (char *)NULL);
#endif /* !HAVE_SETVBUF */
#else /* MPW */
		/* On MPW (3.2) unbuffered seems to hang */
		setvbuf(stdin,  (char *)NULL, _IOLBF, BUFSIZ);
		setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
		setvbuf(stderr, (char *)NULL, _IOLBF, BUFSIZ);
#endif /* MPW */
	}
	else if (*Py_InteractiveFlag) {
#ifdef WIN32
		/* Doesn't have to have line-buffered -- use unbuffered */
		/* Any set[v]buf(stdin, ...) screws up Tkinter :-( */
		setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
#else /* !WIN32 */
#ifdef HAVE_SETVBUF
		setvbuf(stdin,  (char *)NULL, _IOLBF, BUFSIZ);
		setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
#endif /* HAVE_SETVBUF */
#endif /* !WIN32 */
		/* Leave stderr alone - it should be unbuffered anyway. */
  	}

	VS("Setting Python vars\n");
	orgNoSiteFlag = *Py_NoSiteFlag;
	*Py_NoSiteFlag = 1;
	Py_SetProgramName(argv[0]);
	VS("Initializing Python\n");	
	Py_Initialize();
	Py_GetPath();
	VS("Setting up sys.path\n");
	{
	char *fmt="def __rl_sys_path(thisfile,homepath):\n\
	import sys,os\n\
	sys.prefix=sys.exec_prefix=homepath\n\
	sys.argv=[thisfile]\n\
	thisfile=os.path.dirname(thisfile.lower())\n\
	homepath=homepath.lower()\n\
	sys.path = filter(lambda x: x.startswith(homepath) or x.startswith(thisfile) or not x,map(str.lower,sys.path))\n\
	if homepath not in sys.path: sys.path.insert(0,homepath)\n\
	if thisfile not in sys.path: sys.path.insert(0,thisfile)\n\
__rl_sys_path(r'%s',r'%s')\n\
del __rl_sys_path\n";
	int	hpe = strlen(homepath)-1;
	char c=homepath[hpe];
	if(c=='\\') homepath[hpe] = 0;
	PyRun_Format(fmt,thisfile,homepath);
	if(c=='\\') homepath[hpe] = '\\';
	}
#ifndef NO_RL_PYZ_STARTUP
	VS("Installing import hooks\n");
	pypath = malloc(strlen(_rl_startup)+strlen(homepath)+100);
	sprintf(pypath,_rl_startup,homepath);
	if(PyRun_SimpleStringFlags(pypath, &cf)){
		FATALERROR("Cannot start up importing.\n");
		return -1;
		}
	free(pypath);
#endif
	if(!orgNoSiteFlag){
		VS("Importing module site\n");
		*Py_NoSiteFlag = 0;
		PyRun_SimpleStringFlags("import site;" _RL_RESTORE_PYZ, &cf);
		}

	if (*Py_VerboseFlag ||
	    (command == NULL && filename == NULL && stdin_is_interactive))
		fprintf(stderr, "Python %s on %s\n%s\n",
			Py_GetVersion(), Py_GetPlatform(), COPYRIGHT);

	
	if (command != NULL) {
		/* Backup _PyOS_optind and force sys.argv[0] = '-c' */
		_PyOS_optind--;
		argv[_PyOS_optind] = "-c";
	}

	PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);

	if ((inspect || (command == NULL && filename == NULL)) &&
	    isatty(fileno(stdin))) {
		PyObject *v;
		v = PyImport_ImportModule("readline");
		if (v == NULL)
			PyErr_Clear();
		else
			Py_DECREF(v);
	}

	if (command) {
		sts = PyRun_SimpleStringFlags(command, &cf) != 0;
		free(command);
	}
	else {
		if (filename == NULL && stdin_is_interactive) {
			char *startup = Py_GETENV("PYTHONSTARTUP");
			if (startup != NULL && startup[0] != '\0') {
				FILE *fp = fopen(startup, "r");
				if (fp != NULL) {
					(void) PyRun_SimpleFile(fp, startup);
					PyErr_Clear();
					fclose(fp);
				}
			}
		}
		/* XXX */
		sts = PyRun_AnyFileExFlags(
			fp,
			filename == NULL ? "<stdin>" : filename,
			filename != NULL, &cf) != 0;
	}

	if (inspect && stdin_is_interactive &&
	    (filename != NULL || command != NULL))
		/* XXX */
		sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0;

	Py_Finalize();
#ifdef RISCOS
	if(Py_RISCOSWimpFlag)
                fprintf(stderr, "\x0cq\x0c"); /* make frontend quit */
#endif

#ifdef __INSURE__
	/* Insure++ is a memory analysis tool that aids in discovering
	 * memory leaks and other memory problems.  On Python exit, the
	 * interned string dictionary is flagged as being in use at exit
	 * (which it is).  Under normal circumstances, this is fine because
	 * the memory will be automatically reclaimed by the system.  Under
	 * memory debugging, it's a huge source of useless noise, so we
	 * trade off slower shutdown for less distraction in the memory
	 * reports.  -baw
	 */
	_Py_ReleaseInternedStrings();
#endif /* __INSURE__ */

	return sts;
}


/* Make the *original* argc/argv available to other modules.
   This is rare, but it is needed by the secureware extension. */

void
Py_GetArgcArgv(int *argc, char ***argv)
{
	*argc = orig_argc;
	*argv = orig_argv;
}

#if	0
static	void set_python_home_path(char *thisfile, char *homepath)
{
	char *pypath;
	int	i;
	pypath = (char*)malloc(2*strlen(homepath)+13+50);
	strcpy(pypath,"PYTHONHOME=");
	strcpy(pypath+11,homepath);
	i = strlen(pypath)-1;
	if(pypath[i]=='\\' || pypath[i]=='/') pypath[i]=0;
	VS1("Set %s\n",pypath);
	_putenv( pypath );
	strcpy(pypath,"PYTHONPATH=");
	strcpy(pypath+11,homepath);
	i = strlen(pypath)-1;
	if(pypath[i]=='\\' || pypath[i]=='/') pypath[i]=0;
	strcat(pypath,";");
	strcat(pypath,thisfile);
	i=strlen(pypath)-1;
	while(i){
		if(pypath[i]==';' || pypath[i]=='\\' || pypath[i]=='/'){
			pypath[i]=0;
			break;
			}
		i--;
		}
	_putenv( pypath );
	free(pypath);
}
#endif

HINSTANCE loadPython(int pyvers,char* homepath)
{
	HINSTANCE dll;
	char *dllpath = (char*)malloc(strlen(homepath)+20);
	VS("Loading python\n");
	sprintf(dllpath, "%sDLLs\\python%02d.dll", homepath, pyvers);
	VS(dllpath);VS("\n");
	dll = LoadLibraryEx(dllpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
	if(!dll){
		VS("Failed to load python dll\n");
		}
	else{
		/* Thomas Heller's code*/
		VS("Getting entry points\n");
		GETVAR(dll,int,Py_DebugFlag);
		GETVAR(dll,int,Py_DivisionWarningFlag);
		GETVAR(dll,int,_Py_QnewFlag);
		GETVAR(dll,int,Py_InteractiveFlag);
		GETVAR(dll,int,Py_OptimizeFlag);
		GETVAR(dll,int,Py_NoSiteFlag);
		GETVAR(dll,int,Py_IgnoreEnvironmentFlag);
		GETVAR(dll,int,Py_TabcheckFlag);
		GETVAR(dll,int,Py_VerboseFlag);
		GETVAR(dll,int,Py_UnicodeFlag);
		/*GETVAR(dll,int,_PyOS_opterr);*/
		/*GETVAR(dll,int,_PyOS_optind);*/
		/*GETVAR(dll,char*,_PyOS_optarg);*/
		/*GETPROC(dll,int,_PyOS_GetOpt,(int,char**,char*));*/
		GETPROC(dll,void,PySys_ResetWarnOptions,(void));
		GETPROC(dll,void,Py_FatalError,(char*));
		GETPROC(dll,void,PySys_AddWarnOption,(char*));
		GETPROC(dll,int,Py_FdIsInteractive,(FILE*,char*));
		GETPROC(dll,void,Py_SetProgramName,(char*));
		GETPROC(dll,int,Py_Initialize,(void));
		GETPROC(dll,int,Py_Finalize,(void));
		GETPROC(dll,const char*,Py_GetVersion,(void));
		GETPROC(dll,const char*,Py_GetPlatform,(void));
		GETPROC(dll,int,PySys_SetArgv,(int,char**));
		GETPROC(dll,PyObject*,PyImport_ImportModule,(char*));
		GETPROC(dll,void,PyErr_Clear,(void));
		GETPROC(dll,int,PyRun_SimpleStringFlags,(char*,PyCompilerFlags*));
		GETPROC(dll,int,PyRun_SimpleFile,(FILE*,char*));
		GETPROC(dll,int,PyRun_AnyFileExFlags,(FILE*,char*,int,PyCompilerFlags*));
		GETPROC(dll,int,PyRun_AnyFileFlags,(FILE*,char*,PyCompilerFlags*));
		GETPROC(dll,char*,Py_GetPath,(void));
		GETPROC(dll, PyObject* , PyString_FromFormatV, (const char*,...));
		GETPROC(dll, int, PyRun_SimpleString, (char *));
		GETPROC(dll, char*, PyString_AsString, (PyObject *));
		GETPROC(dll, void, Py_SetPythonHome, (char *));
		}
	free(dllpath);

	return dll;
}

static int getRegistryInstallPath(HKEY rootKey, char* id, char* homepath)
{
	HKEY	key=0;
	long	bufSize;
	int		n;
	char	*fmt="Software\\ReportLab\\%s";
	char	*regpath = malloc(strlen(id)+strlen(fmt)+1);

	sprintf(regpath, fmt, id);
	bufSize=_MAX_PATH;
	if((n=RegOpenKey(rootKey,regpath,&key))==ERROR_SUCCESS &&
		(n=RegQueryValueEx(key, "InstallPath",NULL,NULL, homepath, &bufSize))==ERROR_SUCCESS) n = 1;
	else{
		VS2("Can't Find Registry PYTHONHOME key=%8.8x err=%d\n",key,n);
		n = 0; /*error*/
		}
	if(key) RegCloseKey(key);
	if(regpath) free(regpath);
	return n;
}

int get_homepath(char* thisfile, char* homepath, char *project)
{
	char	*p, *q, *s;
	int		n;
	VS("Finding InstallPath\n");
	if(!getRegistryInstallPath(HKEY_LOCAL_MACHINE,project,homepath)
			&& !getRegistryInstallPath(HKEY_CURRENT_USER,project,homepath)){
		VS("Trying EXE for homepath\n");
		strcpy(homepath, thisfile);
		p = homepath+strlen(homepath);
		while(p>=homepath && *p!='/' && *p != '\\') p--;
		if(p>homepath) *++p = 0;
		else {
			FATALERROR("Can't Find PYTHONHOME\n");
			return -1;
			}
		}
	if(homepath[strlen(homepath)-1]!='\\') strcat(homepath,"\\");
	VS2("Found HOMEPATH=%s\nthisfile=%s\n", homepath,thisfile);
	/*adjust the path to include homepath/DLLs*/
	p = getenv("PATH");
	n = strlen(thisfile)+strlen(homepath)+11;	/*we add DLLs and PATH=*/
	if(p) n += strlen(p)+1;
	s = (char*)malloc(n);
	strcpy(s,"PATH=");
	strcpy(s+5,thisfile);
	q = s+strlen(s);
	while(q>=s && *q!='/' && *q != '\\') q--;
	*q = 0;
	strcat(s,";");
	strcat(s,homepath);
	strcat(s,"DLLs");
	if(p){
		strcat(s,";");
		strcat(s,p);
		}
	VS1("Adjusted %s\n",s);
	_putenv(s);
	return 0;
}

int openSelf(char* thisfile, char *homepath, char **project, int *pyvers)
{
	FILE*	fp;
	char	*p;
#	define RLP_MAGIC "RLP\02\04\03\014\015"
	typedef struct {
		unsigned short projectlen;
		unsigned short pyvers;
		char magic[8];
		} cookie;
	cookie	c;
	int	cs = sizeof(cookie);
	if (!GetModuleFileNameA(NULL, thisfile, _MAX_PATH)){
		FATALERROR("System error - unable to load!");
		return -1;
		}
	p = thisfile+strlen(thisfile)-4;
	VS1("Opening self=%s\n", thisfile);
	if (strnicmp(p, ".exe", 4) != 0) strcat(thisfile, ".exe");
	fp = fopen(thisfile, "rb");
	VS1("thisfile=%s\n",thisfile);
	if(fp == NULL){
		FATALERROR("Cannot open self: ");
		FATALERROR(thisfile);
		return -1;
		}
	fseek(fp, 0, SEEK_END);
	if (fseek(fp, -(int)cs, SEEK_END)){
L0:		FATALERROR("executable appears to be invalid");
		return -1;
		}
	fread(&c, sizeof(cookie), 1, fp);
	if (strncmp((char*)&c.magic, RLP_MAGIC, 8)){
#ifdef	_DEBUG
		int i;
		VS("RLP_MAGIC:");
		for(i=0;i<8;i++){
			VS1("%2.2X",RLP_MAGIC[i]);
			}
		VS("\nc.magic:");
		for(i=0;i<8;i++){
			VS1(" %2.2X",c.magic[i],);
			}
		VS("\n");
#endif
		FATALERROR("executable has bad magic - quitting!");
		return -1;
		}
	if (fseek(fp, -cs-(int)c.projectlen, SEEK_END)) goto L0;
	*project = malloc((size_t)c.projectlen + 1);
	fread(*project, (int)c.projectlen, 1, fp);
	(*project)[c.projectlen] = 0;
	VS2("projectlen=%d project='%s'\n",(int)c.projectlen,*project);
	if (get_homepath(thisfile,homepath,*project)) return -1;
	VS("closing self\n");
	fclose(fp);
	*pyvers = (int)c.pyvers;
	return 0;
}

static	char* PYTHONHOME;
#ifdef _CONSOLE
int main(int argc, char* argv[])
#else
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
#endif
{
	int rc = 0, pyvers;
	char* thisfile = (char*)malloc(_MAX_PATH+1);
	char* homepath = (char*)malloc(_MAX_PATH+1);
	char* project;
	VS("Start " STUBNAME "\n");

	VS("Opening self\n");
	if(openSelf(thisfile, homepath, &project,&pyvers)) return -1;
#if	0
	set_python_home_path(thisfile,homepath);
#endif
	if(!loadPython(pyvers,homepath)) return -1;
	PYTHONHOME=strdup(homepath);
	Py_SetPythonHome(PYTHONHOME);
#ifndef _CONSOLE
	rc = Py_Main(__argc, __argv, thisfile, homepath, project, pyvers);
#else
	rc = Py_Main(argc, argv, thisfile, homepath, project, pyvers);
#endif
	VS("homepath\n");
	free(homepath);
	VS("thisfile\n");
	free(thisfile);
	VS1("rc=%d\n",rc);
	return rc;
}
