mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-31 07:17:27 +00:00 
			
		
		
		
	 521527e0b6
			
		
	
	
		521527e0b6
		
	
	
	
	
		
			
			AppPkg/Applications/Python: Deleted obsolete and incomplete PyMod-2.7.1. Changes to enable compilation using GCC 4.4 on both Windows and Linux hosts. Signed-off-by: daryl.mcdaniel@intel.com Reviewed-by: jaben.carsey@intel.com git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13147 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			726 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			726 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|     Return the initial module search path.
 | |
| 
 | |
|     Search in specified locations for the associated Python libraries.
 | |
| 
 | |
|     Py_GetPath returns module_search_path.
 | |
|     Py_GetPrefix returns PREFIX
 | |
|     Py_GetExec_Prefix returns PREFIX
 | |
|     Py_GetProgramFullPath returns the full path to the python executable.
 | |
| 
 | |
|     These are built dynamically so that the proper volume name can be prefixed
 | |
|     to the paths.
 | |
| 
 | |
|     For the EDK II, UEFI, implementation of Python, PREFIX and EXEC_PREFIX
 | |
|     are set as follows:
 | |
|       PREFIX      = /Efi/StdLib
 | |
|       EXEC_PREFIX = PREFIX
 | |
| 
 | |
|     The following final paths are assumed:
 | |
|       /Efi/Tools/Python.efi                     The Python executable.
 | |
|       /Efi/StdLib/lib/python.VERSION            The platform independent Python modules.
 | |
|       /Efi/StdLib/lib/python.VERSION/dynalib    Dynamically loadable Python extension modules.
 | |
| 
 | |
|     Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
 | |
|     This program and the accompanying materials are licensed and made available under
 | |
|     the terms and conditions of the BSD License that accompanies this distribution.
 | |
|     The full text of the license may be found at
 | |
|     http://opensource.org/licenses/bsd-license.
 | |
| 
 | |
|     THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|     WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| **/
 | |
| #include <Python.h>
 | |
| #include <osdefs.h>
 | |
| #include  <ctype.h>
 | |
| 
 | |
| #ifdef __cplusplus
 | |
|  extern "C" {
 | |
| #endif
 | |
| 
 | |
| /* VERSION must be at least two characters long. */
 | |
| #ifndef VERSION
 | |
|   #define VERSION     "27"
 | |
| #endif
 | |
| 
 | |
| #ifndef VPATH
 | |
|   #define VPATH       "."
 | |
| #endif
 | |
| 
 | |
| /* Search path entry delimiter */
 | |
| #ifdef DELIM
 | |
|   #define sDELIM        ";"
 | |
| #endif
 | |
| 
 | |
| #ifndef PREFIX
 | |
|   #define PREFIX      "/Efi/StdLib"
 | |
| #endif
 | |
| 
 | |
| #ifndef EXEC_PREFIX
 | |
|   #define EXEC_PREFIX PREFIX
 | |
| #endif
 | |
| 
 | |
| #ifndef   LIBPYTHON
 | |
|   #define   LIBPYTHON     "lib/python." VERSION
 | |
| #endif
 | |
| 
 | |
| #ifndef PYTHONPATH
 | |
|   #ifdef HAVE_ENVIRONMENT_OPS
 | |
|     #define PYTHONPATH  PREFIX LIBPYTHON sDELIM \
 | |
|                         EXEC_PREFIX LIBPYTHON "/lib-dynload"
 | |
|   #else
 | |
|     #define PYTHONPATH  LIBPYTHON
 | |
|   #endif
 | |
| #endif
 | |
| 
 | |
| #ifndef LANDMARK
 | |
| #define LANDMARK    "os.py"
 | |
| #endif
 | |
| 
 | |
| static char   prefix[MAXPATHLEN+1];
 | |
| static char   exec_prefix[MAXPATHLEN+1];
 | |
| static char   progpath[MAXPATHLEN+1];
 | |
| static char  *module_search_path          = NULL;
 | |
| static char   lib_python[]                = LIBPYTHON;
 | |
| static char   volume_name[32]             = { 0 };
 | |
| 
 | |
| /** Determine if "ch" is a separator character.
 | |
| 
 | |
|     @param[in]  ch      The character to test.
 | |
| 
 | |
|     @retval     TRUE    ch is a separator character.
 | |
|     @retval     FALSE   ch is NOT a separator character.
 | |
| **/
 | |
| static int
 | |
| is_sep(char ch)
 | |
| {
 | |
| #ifdef ALTSEP
 | |
|   return ch == SEP || ch == ALTSEP;
 | |
| #else
 | |
|   return ch == SEP;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /** Reduce a path by its last element.
 | |
| 
 | |
|     The last element (everything to the right of the last separator character)
 | |
|     in the path, dir, is removed from the path.  Parameter dir is modified in place.
 | |
| 
 | |
|     @param[in,out]    dir   Pointer to the path to modify.
 | |
| **/
 | |
| static void
 | |
| reduce(char *dir)
 | |
| {
 | |
|     size_t i = strlen(dir);
 | |
|     while (i > 0 && !is_sep(dir[i]))
 | |
|         --i;
 | |
|     dir[i] = '\0';
 | |
| }
 | |
| 
 | |
| #ifndef UEFI_C_SOURCE
 | |
| /** Does filename point to a file and not directory?
 | |
| 
 | |
|     @param[in]    filename    The fully qualified path to the object to test.
 | |
| 
 | |
|     @retval       0     Filename was not found, or is a directory.
 | |
|     @retval       1     Filename refers to a regular file.
 | |
| **/
 | |
| static int
 | |
| isfile(char *filename)
 | |
| {
 | |
|     struct stat buf;
 | |
|     if (stat(filename, &buf) != 0) {
 | |
|       return 0;
 | |
|     }
 | |
|     //if (!S_ISREG(buf.st_mode))
 | |
|     if (S_ISDIR(buf.st_mode)) {
 | |
|       return 0;
 | |
|     }
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| /** Determine if filename refers to a Python module.
 | |
| 
 | |
|     A Python module is indicated if the file exists, or if the file with
 | |
|     'o' or 'c' appended exists.
 | |
| 
 | |
|     @param[in]    filename    The fully qualified path to the object to test.
 | |
| 
 | |
|     @retval       0
 | |
| **/
 | |
| static int
 | |
| ismodule(char *filename)
 | |
| {
 | |
|   if (isfile(filename)) {
 | |
|     //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: file = \"%s\"\n", __func__, __LINE__, filename);
 | |
|     return 1;
 | |
|   }
 | |
| 
 | |
|     /* Check for the compiled version of prefix. */
 | |
|     if (strlen(filename) < MAXPATHLEN) {
 | |
|         strcat(filename, Py_OptimizeFlag ? "o" : "c");
 | |
|         if (isfile(filename)) {
 | |
|           return 1;
 | |
|         }
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| /** Does filename point to a directory?
 | |
| 
 | |
|     @param[in]    filename    The fully qualified path to the object to test.
 | |
| 
 | |
|     @retval       0     Filename was not found, or is not a regular file.
 | |
|     @retval       1     Filename refers to a directory.
 | |
| **/
 | |
| static int
 | |
| isdir(char *filename)
 | |
| {
 | |
|     struct stat buf;
 | |
| 
 | |
|     if (stat(filename, &buf) != 0)
 | |
|         return 0;
 | |
| 
 | |
|     if (!S_ISDIR(buf.st_mode))
 | |
|         return 0;
 | |
| 
 | |
|     return 1;
 | |
| }
 | |
| #endif  /* UEFI_C_SOURCE */
 | |
| 
 | |
| /** Determine if a path is absolute, or not.
 | |
|     An absolute path consists of a volume name, "VOL:", followed by a rooted path,
 | |
|     "/path/elements".  If both of these components are present, the path is absolute.
 | |
| 
 | |
|     Let P be a pointer to the path to test.
 | |
|     Let A be a pointer to the first ':' in P.
 | |
|     Let B be a pointer to the first '/' or '\\' in P.
 | |
| 
 | |
|     If A and B are not NULL
 | |
|       If (A-P+1) == (B-P) then the path is absolute.
 | |
|     Otherwise, the path is NOT absolute.
 | |
| 
 | |
|     @param[in]  path    The path to test.
 | |
| 
 | |
|     @retval     -1      Path is absolute but lacking volume name.
 | |
|     @retval      0      Path is NOT absolute.
 | |
|     @retval      1      Path is absolute.
 | |
| */
 | |
| static int
 | |
| is_absolute(char *path)
 | |
| {
 | |
|   char  *A;
 | |
|   char  *B;
 | |
| 
 | |
|   A = strchr(path, ':');
 | |
|   B = strpbrk(path, "/\\");
 | |
| 
 | |
|   if(B != NULL) {
 | |
|     if(A == NULL) {
 | |
|       if(B == path) {
 | |
|         return -1;
 | |
|       }
 | |
|     }
 | |
|     else {
 | |
|       if(((A - path) + 1) == (B - path)) {
 | |
|         return 1;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| /** Add a path component, by appending stuff to buffer.
 | |
|     buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
 | |
|     NUL-terminated string with no more than MAXPATHLEN characters (not counting
 | |
|     the trailing NUL).  It's a fatal error if it contains a string longer than
 | |
|     that (callers must be careful!).  If these requirements are met, it's
 | |
|     guaranteed that buffer will still be a NUL-terminated string with no more
 | |
|     than MAXPATHLEN characters at exit.  If stuff is too long, only as much of
 | |
|     stuff as fits will be appended.
 | |
| 
 | |
|     @param[in,out]    buffer    The path to be extended.
 | |
|     @param[in]        stuff     The stuff to join onto the path.
 | |
| */
 | |
| static void
 | |
| joinpath(char *buffer, char *stuff)
 | |
| {
 | |
|   size_t n, k;
 | |
| 
 | |
|   k = 0;
 | |
|   if (is_absolute(stuff) == 1) {
 | |
|     n = 0;
 | |
|   }
 | |
|   else {
 | |
|     n = strlen(buffer);
 | |
|     if(n == 0) {
 | |
|       strncpy(buffer, volume_name, MAXPATHLEN);
 | |
|       n = strlen(buffer);
 | |
|     }
 | |
|     /* We must not use an else clause here because we want to test n again.
 | |
|         volume_name may have been empty.
 | |
|     */
 | |
|     if (n > 0 && n < MAXPATHLEN) {
 | |
|       if(!is_sep(buffer[n-1])) {
 | |
|         buffer[n++] = SEP;
 | |
|       }
 | |
|       if(is_sep(stuff[0]))   ++stuff;
 | |
|     }
 | |
|   }
 | |
|   if (n > MAXPATHLEN)
 | |
|     Py_FatalError("buffer overflow in getpath.c's joinpath()");
 | |
|   k = strlen(stuff);
 | |
|   if (n + k > MAXPATHLEN)
 | |
|     k = MAXPATHLEN - n;
 | |
|   strncpy(buffer+n, stuff, k);
 | |
|   buffer[n+k] = '\0';
 | |
| }
 | |
| 
 | |
| /** Is filename an executable file?
 | |
| 
 | |
|     An executable file:
 | |
|       1) exists
 | |
|       2) is a file, not a directory
 | |
|       3) has a name ending with ".efi"
 | |
|       4) Only has a single '.' in the name.
 | |
| 
 | |
|     If basename(filename) does not contain a '.', append ".efi" to filename
 | |
|     If filename ends in ".efi", it is executable, else it isn't.
 | |
| 
 | |
|     This routine is used to when searching for the file named by argv[0].
 | |
|     As such, there is no need to search for extensions other than ".efi".
 | |
| 
 | |
|     @param[in]    filename      The name of the file to test.  It may, or may not, have an extension.
 | |
| 
 | |
|     @retval       0     filename already has a path other than ".efi", or it doesn't exist, or is a directory.
 | |
|     @retval       1     filename refers to an executable file.
 | |
| **/
 | |
| static int
 | |
| isxfile(char *filename)
 | |
| {
 | |
|     struct stat  buf;
 | |
|     char        *bn;
 | |
|     char        *newbn;
 | |
|     int          bnlen;
 | |
| 
 | |
|     bn = basename(filename);            // Separate off the file name component
 | |
|     reduce(filename);                   // and isolate the path component
 | |
|     bnlen = strlen(bn);
 | |
|     newbn = strrchr(bn, '.');           // Does basename contain a period?
 | |
|     if(newbn == NULL) {                   // Does NOT contain a period.
 | |
|       newbn = &bn[bnlen];
 | |
|       strncpyX(newbn, ".efi", MAXPATHLEN - bnlen);    // append ".efi" to basename
 | |
|       bnlen += 4;
 | |
|     }
 | |
|     else if(strcmp(newbn, ".efi") != 0) {
 | |
|       return 0;                         // File can not be executable.
 | |
|     }
 | |
|     joinpath(filename, bn);             // Stitch path and file name back together
 | |
| 
 | |
|     if (stat(filename, &buf) != 0) {    // Now, verify that file exists
 | |
|       return 0;
 | |
|     }
 | |
|     if(S_ISDIR(buf.st_mode)) {          // And it is not a directory.
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| /** Copy p into path, ensuring that the result is an absolute path.
 | |
| 
 | |
|     copy_absolute requires that path be allocated at least
 | |
|     MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes.
 | |
| 
 | |
|     @param[out]     path    Destination to receive the absolute path.
 | |
|     @param[in]      p       Path to be tested and possibly converted.
 | |
| **/
 | |
| static void
 | |
| copy_absolute(char *path, char *p)
 | |
| {
 | |
|   if (is_absolute(p) == 1)
 | |
|         strcpy(path, p);
 | |
|   else {
 | |
|     if (!getcwd(path, MAXPATHLEN)) {
 | |
|       /* unable to get the current directory */
 | |
|       if(volume_name[0] != 0) {
 | |
|         strcpy(path, volume_name);
 | |
|         joinpath(path, p);
 | |
|       }
 | |
|       else
 | |
|         strcpy(path, p);
 | |
|       return;
 | |
|     }
 | |
|     if (p[0] == '.' && is_sep(p[1]))
 | |
|         p += 2;
 | |
|     joinpath(path, p);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /** Modify path so that the result is an absolute path.
 | |
|     absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes.
 | |
| 
 | |
|     @param[in,out]    path    The path to be made absolute.
 | |
| */
 | |
| static void
 | |
| absolutize(char *path)
 | |
| {
 | |
|     char buffer[MAXPATHLEN + 1];
 | |
| 
 | |
|     if (is_absolute(path) == 1)
 | |
|         return;
 | |
|     copy_absolute(buffer, path);
 | |
|     strcpy(path, buffer);
 | |
| }
 | |
| 
 | |
| /** Extract the volume name from a path.
 | |
| 
 | |
|     @param[out]   Dest    Pointer to location in which to store the extracted volume name.
 | |
|     @param[in]    path    Pointer to the path to extract the volume name from.
 | |
| **/
 | |
| static void
 | |
| set_volume(char *Dest, char *path)
 | |
| {
 | |
|   size_t    VolLen;
 | |
| 
 | |
|   if(is_absolute(path)) {
 | |
|     VolLen = strcspn(path, "/\\:");
 | |
|     if((VolLen != 0) && (path[VolLen] == ':')) {
 | |
|       (void) strncpyX(Dest, path, VolLen + 1);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /** Determine paths.
 | |
| 
 | |
|     Two directories must be found, the platform independent directory
 | |
|     (prefix), containing the common .py and .pyc files, and the platform
 | |
|     dependent directory (exec_prefix), containing the shared library
 | |
|     modules.  Note that prefix and exec_prefix are the same directory
 | |
|     for UEFI installations.
 | |
| 
 | |
|     Separate searches are carried out for prefix and exec_prefix.
 | |
|     Each search tries a number of different locations until a ``landmark''
 | |
|     file or directory is found.  If no prefix or exec_prefix is found, a
 | |
|     warning message is issued and the preprocessor defined PREFIX and
 | |
|     EXEC_PREFIX are used (even though they may not work); python carries on
 | |
|     as best as is possible, but some imports may fail.
 | |
| 
 | |
|     Before any searches are done, the location of the executable is
 | |
|     determined.  If argv[0] has one or more slashes in it, it is used
 | |
|     unchanged.  Otherwise, it must have been invoked from the shell's path,
 | |
|     so we search %PATH% for the named executable and use that.  If the
 | |
|     executable was not found on %PATH% (or there was no %PATH% environment
 | |
|     variable), the original argv[0] string is used.
 | |
| 
 | |
|     Finally, argv0_path is set to the directory containing the executable
 | |
|     (i.e. the last component is stripped).
 | |
| 
 | |
|     With argv0_path in hand, we perform a number of steps.  The same steps
 | |
|     are performed for prefix and for exec_prefix, but with a different
 | |
|     landmark.
 | |
| 
 | |
|     The prefix landmark will always be lib/python.VERSION/os.py and the
 | |
|     exec_prefix will always be lib/python.VERSION/dynaload, where VERSION
 | |
|     is Python's version number as defined at the beginning of this file.
 | |
| 
 | |
|     First. See if the %PYTHONHOME% environment variable points to the
 | |
|     installed location of the Python libraries.  If %PYTHONHOME% is set, then
 | |
|     it points to prefix and exec_prefix.  %PYTHONHOME% can be a single
 | |
|     directory, which is used for both, or the prefix and exec_prefix
 | |
|     directories separated by the DELIM character.
 | |
| 
 | |
|     Next. Search the directories pointed to by the preprocessor variables
 | |
|     PREFIX and EXEC_PREFIX.  These paths are prefixed with the volume name
 | |
|     extracted from argv0_path.  The volume names correspond to the UEFI
 | |
|     shell "map" names.
 | |
| 
 | |
|     That's it!
 | |
| 
 | |
|     Well, almost.  Once we have determined prefix and exec_prefix, the
 | |
|     preprocessor variable PYTHONPATH is used to construct a path.  Each
 | |
|     relative path on PYTHONPATH is prefixed with prefix.  Then the directory
 | |
|     containing the shared library modules is appended.  The environment
 | |
|     variable $PYTHONPATH is inserted in front of it all.  Finally, the
 | |
|     prefix and exec_prefix globals are tweaked so they reflect the values
 | |
|     expected by other code, by stripping the "lib/python$VERSION/..." stuff
 | |
|     off.  This seems to make more sense given that currently the only
 | |
|     known use of sys.prefix and sys.exec_prefix is for the ILU installation
 | |
|     process to find the installed Python tree.
 | |
| 
 | |
|     The final, fully resolved, paths should look something like:
 | |
|       fs0:/Efi/Tools/python.efi
 | |
|       fs0:/Efi/StdLib/lib/python27
 | |
|       fs0:/Efi/StdLib/lib/python27/dynaload
 | |
| 
 | |
| **/
 | |
| static void
 | |
| calculate_path(void)
 | |
| {
 | |
|     extern char *Py_GetProgramName(void);
 | |
| 
 | |
|     static char delimiter[2] = {DELIM, '\0'};
 | |
|     static char separator[2] = {SEP, '\0'};
 | |
|     char *pythonpath = PYTHONPATH;
 | |
|     char *rtpypath = Py_GETENV("PYTHONPATH");
 | |
|     //char *home = Py_GetPythonHome();
 | |
|     char *path = getenv("PATH");
 | |
|     char *prog = Py_GetProgramName();
 | |
|     char argv0_path[MAXPATHLEN+1];
 | |
|     char zip_path[MAXPATHLEN+1];
 | |
|     char *buf;
 | |
|     size_t bufsz;
 | |
|     size_t prefixsz;
 | |
|     char *defpath;
 | |
| 
 | |
| 
 | |
| /* ###########################################################################
 | |
|       Determine path to the Python.efi binary.
 | |
|       Produces progpath, argv0_path, and volume_name.
 | |
| ########################################################################### */
 | |
| 
 | |
|     /* If there is no slash in the argv0 path, then we have to
 | |
|      * assume python is on the user's $PATH, since there's no
 | |
|      * other way to find a directory to start the search from.  If
 | |
|      * $PATH isn't exported, you lose.
 | |
|      */
 | |
|     if (strchr(prog, SEP))
 | |
|             strncpy(progpath, prog, MAXPATHLEN);
 | |
|     else if (path) {
 | |
|       while (1) {
 | |
|         char *delim = strchr(path, DELIM);
 | |
| 
 | |
|         if (delim) {
 | |
|                 size_t len = delim - path;
 | |
|                 if (len > MAXPATHLEN)
 | |
|                         len = MAXPATHLEN;
 | |
|                 strncpy(progpath, path, len);
 | |
|                 *(progpath + len) = '\0';
 | |
|         }
 | |
|         else
 | |
|                 strncpy(progpath, path, MAXPATHLEN);
 | |
| 
 | |
|         joinpath(progpath, prog);
 | |
|         if (isxfile(progpath))
 | |
|                 break;
 | |
| 
 | |
|         if (!delim) {
 | |
|                 progpath[0] = '\0';
 | |
|                 break;
 | |
|         }
 | |
|         path = delim + 1;
 | |
|       }
 | |
|     }
 | |
|     else
 | |
|             progpath[0] = '\0';
 | |
|     if ( (!is_absolute(progpath)) && (progpath[0] != '\0') )
 | |
|             absolutize(progpath);
 | |
|     strncpy(argv0_path, progpath, MAXPATHLEN);
 | |
|     argv0_path[MAXPATHLEN] = '\0';
 | |
|     set_volume(volume_name, argv0_path);
 | |
| 
 | |
|     reduce(argv0_path);
 | |
|     /* At this point, argv0_path is guaranteed to be less than
 | |
|        MAXPATHLEN bytes long.
 | |
|     */
 | |
| 
 | |
| /* ###########################################################################
 | |
|       Build the FULL prefix string, including volume name.
 | |
|       This is the full path to the platform independent libraries.
 | |
| ########################################################################### */
 | |
| 
 | |
|         strncpy(prefix, volume_name, MAXPATHLEN);
 | |
|         joinpath(prefix, PREFIX);
 | |
|         joinpath(prefix, lib_python);
 | |
| 
 | |
| /* ###########################################################################
 | |
|       Build the FULL path to the zipped-up Python library.
 | |
| ########################################################################### */
 | |
| 
 | |
|     strncpy(zip_path, prefix, MAXPATHLEN);
 | |
|     zip_path[MAXPATHLEN] = '\0';
 | |
|     reduce(zip_path);
 | |
|     joinpath(zip_path, "python00.zip");
 | |
|     bufsz = strlen(zip_path);   /* Replace "00" with version */
 | |
|     zip_path[bufsz - 6] = VERSION[0];
 | |
|     zip_path[bufsz - 5] = VERSION[1];
 | |
| 
 | |
| /* ###########################################################################
 | |
|       Build the FULL path to dynamically loadable libraries.
 | |
| ########################################################################### */
 | |
| 
 | |
|         strncpy(exec_prefix, volume_name, MAXPATHLEN);
 | |
|         joinpath(exec_prefix, EXEC_PREFIX);
 | |
|         joinpath(exec_prefix, lib_python);
 | |
|         joinpath(exec_prefix, "lib-dynload");
 | |
| 
 | |
| /* ###########################################################################
 | |
|       Build the module search path.
 | |
| ########################################################################### */
 | |
| 
 | |
|     /* Reduce prefix and exec_prefix to their essence,
 | |
|      * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
 | |
|      * If we're loading relative to the build directory,
 | |
|      * return the compiled-in defaults instead.
 | |
|      */
 | |
|     reduce(prefix);
 | |
|     reduce(prefix);
 | |
|     /* The prefix is the root directory, but reduce() chopped
 | |
|      * off the "/". */
 | |
|     if (!prefix[0]) {
 | |
|       strcpy(prefix, volume_name);
 | |
|     }
 | |
|     bufsz = strlen(prefix);
 | |
|     if(prefix[bufsz-1] == ':') {
 | |
|       prefix[bufsz] = SEP;
 | |
|       prefix[bufsz+1] = 0;
 | |
|     }
 | |
| 
 | |
|     /* Calculate size of return buffer.
 | |
|      */
 | |
|     defpath = pythonpath;
 | |
|     bufsz = 0;
 | |
| 
 | |
|     if (rtpypath)
 | |
|         bufsz += strlen(rtpypath) + 1;
 | |
| 
 | |
|     prefixsz = strlen(prefix) + 1;
 | |
| 
 | |
|     while (1) {
 | |
|         char *delim = strchr(defpath, DELIM);
 | |
| 
 | |
|         if (is_absolute(defpath) == 0)
 | |
|             /* Paths are relative to prefix */
 | |
|             bufsz += prefixsz;
 | |
| 
 | |
|         if (delim)
 | |
|             bufsz += delim - defpath + 1;
 | |
|         else {
 | |
|             bufsz += strlen(defpath) + 1;
 | |
|             break;
 | |
|         }
 | |
|         defpath = delim + 1;
 | |
|     }
 | |
| 
 | |
|     bufsz += strlen(zip_path) + 1;
 | |
|     bufsz += strlen(exec_prefix) + 1;
 | |
| 
 | |
|     /* This is the only malloc call in this file */
 | |
|     buf = (char *)PyMem_Malloc(bufsz);
 | |
| 
 | |
|     if (buf == NULL) {
 | |
|         /* We can't exit, so print a warning and limp along */
 | |
|         fprintf(stderr, "Not enough memory for dynamic PYTHONPATH.\n");
 | |
|         fprintf(stderr, "Using default static PYTHONPATH.\n");
 | |
|         module_search_path = PYTHONPATH;
 | |
|     }
 | |
|     else {
 | |
|         /* Run-time value of $PYTHONPATH goes first */
 | |
|         if (rtpypath) {
 | |
|             strcpy(buf, rtpypath);
 | |
|             strcat(buf, delimiter);
 | |
|         }
 | |
|         else
 | |
|             buf[0] = '\0';
 | |
| 
 | |
|         /* Next is the default zip path */
 | |
|         strcat(buf, zip_path);
 | |
|         strcat(buf, delimiter);
 | |
| 
 | |
|         /* Next goes merge of compile-time $PYTHONPATH with
 | |
|          * dynamically located prefix.
 | |
|          */
 | |
|         defpath = pythonpath;
 | |
|         while (1) {
 | |
|             char *delim = strchr(defpath, DELIM);
 | |
| 
 | |
|             if (is_absolute(defpath) != 1) {
 | |
|                 strcat(buf, prefix);
 | |
|                 strcat(buf, separator);
 | |
|             }
 | |
| 
 | |
|             if (delim) {
 | |
|                 size_t len = delim - defpath + 1;
 | |
|                 size_t end = strlen(buf) + len;
 | |
|                 strncat(buf, defpath, len);
 | |
|                 *(buf + end) = '\0';
 | |
|             }
 | |
|             else {
 | |
|                 strcat(buf, defpath);
 | |
|                 break;
 | |
|             }
 | |
|             defpath = delim + 1;
 | |
|         }
 | |
|         strcat(buf, delimiter);
 | |
| 
 | |
|         /* Finally, on goes the directory for dynamic-load modules */
 | |
|         strcat(buf, exec_prefix);
 | |
| 
 | |
|         /* And publish the results */
 | |
|         module_search_path = buf;
 | |
|     }
 | |
|         /*  At this point, exec_prefix is set to VOL:/Efi/StdLib/lib/python.27/dynalib.
 | |
|             We want to get back to the root value, so we have to remove the final three
 | |
|             segments to get VOL:/Efi/StdLib.  Because we don't know what VOL is, and
 | |
|             EXEC_PREFIX is also indeterminate, we just remove the three final segments.
 | |
|         */
 | |
|         reduce(exec_prefix);
 | |
|         reduce(exec_prefix);
 | |
|         reduce(exec_prefix);
 | |
|         if (!exec_prefix[0]) {
 | |
|           strcpy(exec_prefix, volume_name);
 | |
|         }
 | |
|         bufsz = strlen(exec_prefix);
 | |
|         if(exec_prefix[bufsz-1] == ':') {
 | |
|           exec_prefix[bufsz] = SEP;
 | |
|           exec_prefix[bufsz+1] = 0;
 | |
|         }
 | |
|     if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: module_search_path = \"%s\"\n", __func__, __LINE__, module_search_path);
 | |
|     if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: prefix             = \"%s\"\n", __func__, __LINE__, prefix);
 | |
|     if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: exec_prefix        = \"%s\"\n", __func__, __LINE__, exec_prefix);
 | |
|     if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: progpath           = \"%s\"\n", __func__, __LINE__, progpath);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* External interface */
 | |
| 
 | |
| char *
 | |
| Py_GetPath(void)
 | |
| {
 | |
|     if (!module_search_path)
 | |
|         calculate_path();
 | |
|     return module_search_path;
 | |
| }
 | |
| 
 | |
| char *
 | |
| Py_GetPrefix(void)
 | |
| {
 | |
|     if (!module_search_path)
 | |
|         calculate_path();
 | |
|     return prefix;
 | |
| }
 | |
| 
 | |
| char *
 | |
| Py_GetExecPrefix(void)
 | |
| {
 | |
|     if (!module_search_path)
 | |
|         calculate_path();
 | |
|     return exec_prefix;
 | |
| }
 | |
| 
 | |
| char *
 | |
| Py_GetProgramFullPath(void)
 | |
| {
 | |
|     if (!module_search_path)
 | |
|         calculate_path();
 | |
|     return progpath;
 | |
| }
 | |
| 
 | |
| 
 | |
| #ifdef __cplusplus
 | |
| }
 | |
| #endif
 | |
| 
 |