LCOV - code coverage report
Current view: | top level - Python - pathconfig.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 88 | 179 | 49.2 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 7 | 17 | 41.2 %
|  |  | Branches: | 48 | 154 | 31.2 %

               Branch data     Line data    Source code
           1                 :            : /* Path configuration like module_search_path (sys.path) */
           2                 :            :
           3                 :            : #include "Python.h"
           4                 :            : #include "marshal.h"              // PyMarshal_ReadObjectFromString
           5                 :            : #include "osdefs.h"               // DELIM
           6                 :            : #include "pycore_initconfig.h"
           7                 :            : #include "pycore_fileutils.h"
           8                 :            : #include "pycore_pathconfig.h"
           9                 :            : #include "pycore_pymem.h"         // _PyMem_SetDefaultAllocator()
          10                 :            : #include <wchar.h>
          11                 :            : #ifdef MS_WINDOWS
          12                 :            : #  include <windows.h>            // GetFullPathNameW(), MAX_PATH
          13                 :            : #  include <pathcch.h>
          14                 :            : #  include <shlwapi.h>
          15                 :            : #endif
          16                 :            :
          17                 :            : #ifdef __cplusplus
          18                 :            : extern "C" {
          19                 :            : #endif
          20                 :            :
          21                 :            :
          22                 :            : /* External interface */
          23                 :            :
          24                 :            : /* Stored values set by C API functions */
          25                 :            : typedef struct _PyPathConfig {
          26                 :            :     /* Full path to the Python program */
          27                 :            :     wchar_t *program_full_path;
          28                 :            :     wchar_t *prefix;
          29                 :            :     wchar_t *exec_prefix;
          30                 :            :     wchar_t *stdlib_dir;
          31                 :            :     /* Set by Py_SetPath */
          32                 :            :     wchar_t *module_search_path;
          33                 :            :     /* Set by _PyPathConfig_UpdateGlobal */
          34                 :            :     wchar_t *calculated_module_search_path;
          35                 :            :     /* Python program name */
          36                 :            :     wchar_t *program_name;
          37                 :            :     /* Set by Py_SetPythonHome() or PYTHONHOME environment variable */
          38                 :            :     wchar_t *home;
          39                 :            :     int _is_python_build;
          40                 :            : } _PyPathConfig;
          41                 :            :
          42                 :            : #  define _PyPathConfig_INIT \
          43                 :            :       {.module_search_path = NULL, ._is_python_build = 0}
          44                 :            :
          45                 :            :
          46                 :            : _PyPathConfig _Py_path_config = _PyPathConfig_INIT;
          47                 :            :
          48                 :            :
          49                 :            : const wchar_t *
          50                 :         25 : _PyPathConfig_GetGlobalModuleSearchPath(void)
          51                 :            : {
          52                 :         25 :     return _Py_path_config.module_search_path;
          53                 :            : }
          54                 :            :
          55                 :            :
          56                 :            : void
          57                 :         25 : _PyPathConfig_ClearGlobal(void)
          58                 :            : {
          59                 :            :     PyMemAllocatorEx old_alloc;
          60                 :         25 :     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
          61                 :            :
          62                 :            : #define CLEAR(ATTR) \
          63                 :            :     do { \
          64                 :            :         PyMem_RawFree(_Py_path_config.ATTR); \
          65                 :            :         _Py_path_config.ATTR = NULL; \
          66                 :            :     } while (0)
          67                 :            :
          68                 :         25 :     CLEAR(program_full_path);
          69                 :         25 :     CLEAR(prefix);
          70                 :         25 :     CLEAR(exec_prefix);
          71                 :         25 :     CLEAR(stdlib_dir);
          72                 :         25 :     CLEAR(module_search_path);
          73                 :         25 :     CLEAR(calculated_module_search_path);
          74                 :         25 :     CLEAR(program_name);
          75                 :         25 :     CLEAR(home);
          76                 :         25 :     _Py_path_config._is_python_build = 0;
          77                 :            :
          78                 :            : #undef CLEAR
          79                 :            :
          80                 :         25 :     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
          81                 :         25 : }
          82                 :            :
          83                 :            : PyStatus
          84                 :         71 : _PyPathConfig_ReadGlobal(PyConfig *config)
          85                 :            : {
          86                 :         71 :     PyStatus status = _PyStatus_OK();
          87                 :            :
          88                 :            : #define COPY(ATTR) \
          89                 :            :     do { \
          90                 :            :         if (_Py_path_config.ATTR && !config->ATTR) { \
          91                 :            :             status = PyConfig_SetString(config, &config->ATTR, _Py_path_config.ATTR); \
          92                 :            :             if (_PyStatus_EXCEPTION(status)) goto done; \
          93                 :            :         } \
          94                 :            :     } while (0)
          95                 :            :
          96                 :            : #define COPY2(ATTR, SRCATTR) \
          97                 :            :     do { \
          98                 :            :         if (_Py_path_config.SRCATTR && !config->ATTR) { \
          99                 :            :             status = PyConfig_SetString(config, &config->ATTR, _Py_path_config.SRCATTR); \
         100                 :            :             if (_PyStatus_EXCEPTION(status)) goto done; \
         101                 :            :         } \
         102                 :            :     } while (0)
         103                 :            :
         104                 :            : #define COPY_INT(ATTR) \
         105                 :            :     do { \
         106                 :            :         assert(_Py_path_config.ATTR >= 0); \
         107                 :            :         if ((_Py_path_config.ATTR >= 0) && (config->ATTR <= 0)) { \
         108                 :            :             config->ATTR = _Py_path_config.ATTR; \
         109                 :            :         } \
         110                 :            :     } while (0)
         111                 :            :
         112   [ -  +  -  -  :         71 :     COPY(prefix);
                       -  - ]
         113   [ -  +  -  -  :         71 :     COPY(exec_prefix);
                       -  - ]
         114   [ -  +  -  -  :         71 :     COPY(stdlib_dir);
                       -  - ]
         115   [ -  +  -  -  :         71 :     COPY(program_name);
                       -  - ]
         116   [ -  +  -  -  :         71 :     COPY(home);
                       -  - ]
         117   [ -  +  -  -  :         71 :     COPY2(executable, program_full_path);
                       -  - ]
         118   [ -  +  -  + ]:         71 :     COPY_INT(_is_python_build);
         119                 :            :     // module_search_path must be initialised - not read
         120                 :            : #undef COPY
         121                 :            : #undef COPY2
         122                 :            : #undef COPY_INT
         123                 :            :
         124                 :          0 : done:
         125                 :         71 :     return status;
         126                 :            : }
         127                 :            :
         128                 :            : PyStatus
         129                 :         50 : _PyPathConfig_UpdateGlobal(const PyConfig *config)
         130                 :            : {
         131                 :            :     PyMemAllocatorEx old_alloc;
         132                 :         50 :     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
         133                 :            :
         134                 :            : #define COPY(ATTR) \
         135                 :            :     do { \
         136                 :            :         if (config->ATTR) { \
         137                 :            :             PyMem_RawFree(_Py_path_config.ATTR); \
         138                 :            :             _Py_path_config.ATTR = _PyMem_RawWcsdup(config->ATTR); \
         139                 :            :             if (!_Py_path_config.ATTR) goto error; \
         140                 :            :         } \
         141                 :            :     } while (0)
         142                 :            :
         143                 :            : #define COPY2(ATTR, SRCATTR) \
         144                 :            :     do { \
         145                 :            :         if (config->SRCATTR) { \
         146                 :            :             PyMem_RawFree(_Py_path_config.ATTR); \
         147                 :            :             _Py_path_config.ATTR = _PyMem_RawWcsdup(config->SRCATTR); \
         148                 :            :             if (!_Py_path_config.ATTR) goto error; \
         149                 :            :         } \
         150                 :            :     } while (0)
         151                 :            :
         152                 :            : #define COPY_INT(ATTR) \
         153                 :            :     do { \
         154                 :            :         if (config->ATTR > 0) { \
         155                 :            :             _Py_path_config.ATTR = config->ATTR; \
         156                 :            :         } \
         157                 :            :     } while (0)
         158                 :            :
         159   [ +  -  -  + ]:         50 :     COPY(prefix);
         160   [ +  -  -  + ]:         50 :     COPY(exec_prefix);
         161   [ +  -  -  + ]:         50 :     COPY(stdlib_dir);
         162   [ +  -  -  + ]:         50 :     COPY(program_name);
         163   [ -  +  -  - ]:         50 :     COPY(home);
         164   [ +  -  -  + ]:         50 :     COPY2(program_full_path, executable);
         165         [ +  - ]:         50 :     COPY_INT(_is_python_build);
         166                 :            : #undef COPY
         167                 :            : #undef COPY2
         168                 :            : #undef COPY_INT
         169                 :            :
         170                 :         50 :     PyMem_RawFree(_Py_path_config.module_search_path);
         171                 :         50 :     _Py_path_config.module_search_path = NULL;
         172                 :         50 :     PyMem_RawFree(_Py_path_config.calculated_module_search_path);
         173                 :         50 :     _Py_path_config.calculated_module_search_path = NULL;
         174                 :            :
         175                 :            :     do {
         176                 :         50 :         size_t cch = 1;
         177         [ +  + ]:        200 :         for (Py_ssize_t i = 0; i < config->module_search_paths.length; ++i) {
         178                 :        150 :             cch += 1 + wcslen(config->module_search_paths.items[i]);
         179                 :            :         }
         180                 :            :
         181                 :         50 :         wchar_t *path = (wchar_t*)PyMem_RawMalloc(sizeof(wchar_t) * cch);
         182         [ -  + ]:         50 :         if (!path) {
         183                 :          0 :             goto error;
         184                 :            :         }
         185                 :         50 :         wchar_t *p = path;
         186         [ +  + ]:        200 :         for (Py_ssize_t i = 0; i < config->module_search_paths.length; ++i) {
         187                 :        150 :             wcscpy(p, config->module_search_paths.items[i]);
         188                 :        150 :             p = wcschr(p, L'\0');
         189                 :        150 :             *p++ = DELIM;
         190                 :        150 :             *p = L'\0';
         191                 :            :         }
         192                 :            :
         193                 :            :         do {
         194                 :        100 :             *p = L'\0';
         195   [ +  -  +  + ]:        100 :         } while (p != path && *--p == DELIM);
         196                 :         50 :         _Py_path_config.calculated_module_search_path = path;
         197                 :            :     } while (0);
         198                 :            :
         199                 :         50 :     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
         200                 :         50 :     return _PyStatus_OK();
         201                 :            :
         202                 :          0 : error:
         203                 :          0 :     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
         204                 :          0 :     return _PyStatus_NO_MEMORY();
         205                 :            : }
         206                 :            :
         207                 :            :
         208                 :            : static void _Py_NO_RETURN
         209                 :          0 : path_out_of_memory(const char *func)
         210                 :            : {
         211                 :          0 :     _Py_FatalErrorFunc(func, "out of memory");
         212                 :            : }
         213                 :            :
         214                 :            : void
         215                 :          0 : Py_SetPath(const wchar_t *path)
         216                 :            : {
         217         [ #  # ]:          0 :     if (path == NULL) {
         218                 :          0 :         _PyPathConfig_ClearGlobal();
         219                 :          0 :         return;
         220                 :            :     }
         221                 :            :
         222                 :            :     PyMemAllocatorEx old_alloc;
         223                 :          0 :     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
         224                 :            :
         225                 :          0 :     PyMem_RawFree(_Py_path_config.prefix);
         226                 :          0 :     PyMem_RawFree(_Py_path_config.exec_prefix);
         227                 :          0 :     PyMem_RawFree(_Py_path_config.stdlib_dir);
         228                 :          0 :     PyMem_RawFree(_Py_path_config.module_search_path);
         229                 :          0 :     PyMem_RawFree(_Py_path_config.calculated_module_search_path);
         230                 :            :
         231                 :          0 :     _Py_path_config.prefix = _PyMem_RawWcsdup(L"");
         232                 :          0 :     _Py_path_config.exec_prefix = _PyMem_RawWcsdup(L"");
         233                 :            :     // XXX Copy this from the new module_search_path?
         234         [ #  # ]:          0 :     if (_Py_path_config.home != NULL) {
         235                 :          0 :         _Py_path_config.stdlib_dir = _PyMem_RawWcsdup(_Py_path_config.home);
         236                 :            :     }
         237                 :            :     else {
         238                 :          0 :         _Py_path_config.stdlib_dir = _PyMem_RawWcsdup(L"");
         239                 :            :     }
         240                 :          0 :     _Py_path_config.module_search_path = _PyMem_RawWcsdup(path);
         241                 :          0 :     _Py_path_config.calculated_module_search_path = NULL;
         242                 :            :
         243                 :          0 :     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
         244                 :            :
         245         [ #  # ]:          0 :     if (_Py_path_config.prefix == NULL
         246         [ #  # ]:          0 :         || _Py_path_config.exec_prefix == NULL
         247         [ #  # ]:          0 :         || _Py_path_config.stdlib_dir == NULL
         248         [ #  # ]:          0 :         || _Py_path_config.module_search_path == NULL)
         249                 :            :     {
         250                 :          0 :         path_out_of_memory(__func__);
         251                 :            :     }
         252                 :            : }
         253                 :            :
         254                 :            :
         255                 :            : void
         256                 :          0 : Py_SetPythonHome(const wchar_t *home)
         257                 :            : {
         258   [ #  #  #  # ]:          0 :     int has_value = home && home[0];
         259                 :            :
         260                 :            :     PyMemAllocatorEx old_alloc;
         261                 :          0 :     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
         262                 :            :
         263                 :          0 :     PyMem_RawFree(_Py_path_config.home);
         264                 :          0 :     _Py_path_config.home = NULL;
         265                 :            :
         266         [ #  # ]:          0 :     if (has_value) {
         267                 :          0 :         _Py_path_config.home = _PyMem_RawWcsdup(home);
         268                 :            :     }
         269                 :            :
         270                 :          0 :     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
         271                 :            :
         272   [ #  #  #  # ]:          0 :     if (has_value && _Py_path_config.home == NULL) {
         273                 :          0 :         path_out_of_memory(__func__);
         274                 :            :     }
         275                 :          0 : }
         276                 :            :
         277                 :            :
         278                 :            : void
         279                 :          0 : Py_SetProgramName(const wchar_t *program_name)
         280                 :            : {
         281   [ #  #  #  # ]:          0 :     int has_value = program_name && program_name[0];
         282                 :            :
         283                 :            :     PyMemAllocatorEx old_alloc;
         284                 :          0 :     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
         285                 :            :
         286                 :          0 :     PyMem_RawFree(_Py_path_config.program_name);
         287                 :          0 :     _Py_path_config.program_name = NULL;
         288                 :            :
         289         [ #  # ]:          0 :     if (has_value) {
         290                 :          0 :         _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
         291                 :            :     }
         292                 :            :
         293                 :          0 :     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
         294                 :            :
         295   [ #  #  #  # ]:          0 :     if (has_value && _Py_path_config.program_name == NULL) {
         296                 :          0 :         path_out_of_memory(__func__);
         297                 :            :     }
         298                 :          0 : }
         299                 :            :
         300                 :            : void
         301                 :          0 : _Py_SetProgramFullPath(const wchar_t *program_full_path)
         302                 :            : {
         303   [ #  #  #  # ]:          0 :     int has_value = program_full_path && program_full_path[0];
         304                 :            :
         305                 :            :     PyMemAllocatorEx old_alloc;
         306                 :          0 :     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
         307                 :            :
         308                 :          0 :     PyMem_RawFree(_Py_path_config.program_full_path);
         309                 :          0 :     _Py_path_config.program_full_path = NULL;
         310                 :            :
         311         [ #  # ]:          0 :     if (has_value) {
         312                 :          0 :         _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
         313                 :            :     }
         314                 :            :
         315                 :          0 :     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
         316                 :            :
         317   [ #  #  #  # ]:          0 :     if (has_value && _Py_path_config.program_full_path == NULL) {
         318                 :          0 :         path_out_of_memory(__func__);
         319                 :            :     }
         320                 :          0 : }
         321                 :            :
         322                 :            :
         323                 :            : wchar_t *
         324                 :          0 : Py_GetPath(void)
         325                 :            : {
         326                 :            :     /* If the user has provided a path, return that */
         327         [ #  # ]:          0 :     if (_Py_path_config.module_search_path) {
         328                 :          0 :         return _Py_path_config.module_search_path;
         329                 :            :     }
         330                 :            :     /* If we have already done calculations, return the calculated path */
         331                 :          0 :     return _Py_path_config.calculated_module_search_path;
         332                 :            : }
         333                 :            :
         334                 :            :
         335                 :            : wchar_t *
         336                 :         25 : _Py_GetStdlibDir(void)
         337                 :            : {
         338                 :         25 :     wchar_t *stdlib_dir = _Py_path_config.stdlib_dir;
         339   [ +  -  +  - ]:         25 :     if (stdlib_dir != NULL && stdlib_dir[0] != L'\0') {
         340                 :         25 :         return stdlib_dir;
         341                 :            :     }
         342                 :          0 :     return NULL;
         343                 :            : }
         344                 :            :
         345                 :            :
         346                 :            : wchar_t *
         347                 :          0 : Py_GetPrefix(void)
         348                 :            : {
         349                 :          0 :     return _Py_path_config.prefix;
         350                 :            : }
         351                 :            :
         352                 :            :
         353                 :            : wchar_t *
         354                 :          0 : Py_GetExecPrefix(void)
         355                 :            : {
         356                 :          0 :     return _Py_path_config.exec_prefix;
         357                 :            : }
         358                 :            :
         359                 :            :
         360                 :            : wchar_t *
         361                 :          0 : Py_GetProgramFullPath(void)
         362                 :            : {
         363                 :          0 :     return _Py_path_config.program_full_path;
         364                 :            : }
         365                 :            :
         366                 :            :
         367                 :            : wchar_t*
         368                 :          0 : Py_GetPythonHome(void)
         369                 :            : {
         370                 :          0 :     return _Py_path_config.home;
         371                 :            : }
         372                 :            :
         373                 :            :
         374                 :            : wchar_t *
         375                 :          1 : Py_GetProgramName(void)
         376                 :            : {
         377                 :          1 :     return _Py_path_config.program_name;
         378                 :            : }
         379                 :            :
         380                 :            :
         381                 :            :
         382                 :            : /* Compute module search path from argv[0] or the current working
         383                 :            :    directory ("-m module" case) which will be prepended to sys.argv:
         384                 :            :    sys.path[0].
         385                 :            :
         386                 :            :    Return 1 if the path is correctly resolved and written into *path0_p.
         387                 :            :
         388                 :            :    Return 0 if it fails to resolve the full path. For example, return 0 if the
         389                 :            :    current working directory has been removed (bpo-36236) or if argv is empty.
         390                 :            :
         391                 :            :    Raise an exception and return -1 on error.
         392                 :            :    */
         393                 :            : int
         394                 :         25 : _PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
         395                 :            : {
         396                 :            :     assert(_PyWideStringList_CheckConsistency(argv));
         397                 :            :
         398         [ -  + ]:         25 :     if (argv->length == 0) {
         399                 :            :         /* Leave sys.path unchanged if sys.argv is empty */
         400                 :          0 :         return 0;
         401                 :            :     }
         402                 :            :
         403                 :         25 :     wchar_t *argv0 = argv->items[0];
         404                 :         25 :     int have_module_arg = (wcscmp(argv0, L"-m") == 0);
         405   [ +  +  +  + ]:         25 :     int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
         406                 :            :
         407                 :         25 :     wchar_t *path0 = argv0;
         408                 :         25 :     Py_ssize_t n = 0;
         409                 :            :
         410                 :            : #ifdef HAVE_REALPATH
         411                 :            :     wchar_t fullpath[MAXPATHLEN];
         412                 :            : #elif defined(MS_WINDOWS)
         413                 :            :     wchar_t fullpath[MAX_PATH];
         414                 :            : #endif
         415                 :            :
         416         [ +  + ]:         25 :     if (have_module_arg) {
         417                 :            : #if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
         418         [ -  + ]:          2 :         if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
         419                 :          0 :             return 0;
         420                 :            :         }
         421                 :          2 :         path0 = fullpath;
         422                 :            : #else
         423                 :            :         path0 = L".";
         424                 :            : #endif
         425                 :          2 :         n = wcslen(path0);
         426                 :            :     }
         427                 :            :
         428                 :            : #ifdef HAVE_READLINK
         429                 :            :     wchar_t link[MAXPATHLEN + 1];
         430                 :         25 :     int nr = 0;
         431                 :            :     wchar_t path0copy[2 * MAXPATHLEN + 1];
         432                 :            :
         433         [ +  + ]:         25 :     if (have_script_arg) {
         434                 :         22 :         nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
         435                 :            :     }
         436         [ -  + ]:         25 :     if (nr > 0) {
         437                 :            :         /* It's a symlink */
         438                 :          0 :         link[nr] = '\0';
         439         [ #  # ]:          0 :         if (link[0] == SEP) {
         440                 :          0 :             path0 = link; /* Link to absolute path */
         441                 :            :         }
         442         [ #  # ]:          0 :         else if (wcschr(link, SEP) == NULL) {
         443                 :            :             /* Link without path */
         444                 :            :         }
         445                 :            :         else {
         446                 :            :             /* Must join(dirname(path0), link) */
         447                 :          0 :             wchar_t *q = wcsrchr(path0, SEP);
         448         [ #  # ]:          0 :             if (q == NULL) {
         449                 :            :                 /* path0 without path */
         450                 :          0 :                 path0 = link;
         451                 :            :             }
         452                 :            :             else {
         453                 :            :                 /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
         454                 :          0 :                 wcsncpy(path0copy, path0, MAXPATHLEN);
         455                 :          0 :                 q = wcsrchr(path0copy, SEP);
         456                 :          0 :                 wcsncpy(q+1, link, MAXPATHLEN);
         457                 :          0 :                 q[MAXPATHLEN + 1] = L'\0';
         458                 :          0 :                 path0 = path0copy;
         459                 :            :             }
         460                 :            :         }
         461                 :            :     }
         462                 :            : #endif /* HAVE_READLINK */
         463                 :            :
         464                 :         25 :     wchar_t *p = NULL;
         465                 :            :
         466                 :            : #if SEP == '\\'
         467                 :            :     /* Special case for Microsoft filename syntax */
         468                 :            :     if (have_script_arg) {
         469                 :            :         wchar_t *q;
         470                 :            : #if defined(MS_WINDOWS)
         471                 :            :         /* Replace the first element in argv with the full path. */
         472                 :            :         wchar_t *ptemp;
         473                 :            :         if (GetFullPathNameW(path0,
         474                 :            :                            Py_ARRAY_LENGTH(fullpath),
         475                 :            :                            fullpath,
         476                 :            :                            &ptemp)) {
         477                 :            :             path0 = fullpath;
         478                 :            :         }
         479                 :            : #endif
         480                 :            :         p = wcsrchr(path0, SEP);
         481                 :            :         /* Test for alternate separator */
         482                 :            :         q = wcsrchr(p ? p : path0, '/');
         483                 :            :         if (q != NULL)
         484                 :            :             p = q;
         485                 :            :         if (p != NULL) {
         486                 :            :             n = p + 1 - path0;
         487                 :            :             if (n > 1 && p[-1] != ':')
         488                 :            :                 n--; /* Drop trailing separator */
         489                 :            :         }
         490                 :            :     }
         491                 :            : #else
         492                 :            :     /* All other filename syntaxes */
         493         [ +  + ]:         25 :     if (have_script_arg) {
         494                 :            : #if defined(HAVE_REALPATH)
         495         [ +  - ]:         22 :         if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
         496                 :         22 :             path0 = fullpath;
         497                 :            :         }
         498                 :            : #endif
         499                 :         22 :         p = wcsrchr(path0, SEP);
         500                 :            :     }
         501         [ +  + ]:         25 :     if (p != NULL) {
         502                 :         22 :         n = p + 1 - path0;
         503                 :            : #if SEP == '/' /* Special case for Unix filename syntax */
         504         [ +  - ]:         22 :         if (n > 1) {
         505                 :            :             /* Drop trailing separator */
         506                 :         22 :             n--;
         507                 :            :         }
         508                 :            : #endif /* Unix */
         509                 :            :     }
         510                 :            : #endif /* All others */
         511                 :            :
         512                 :         25 :     PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
         513         [ -  + ]:         25 :     if (path0_obj == NULL) {
         514                 :          0 :         return -1;
         515                 :            :     }
         516                 :            :
         517                 :         25 :     *path0_p = path0_obj;
         518                 :         25 :     return 1;
         519                 :            : }
         520                 :            :
         521                 :            :
         522                 :            : #ifdef __cplusplus
         523                 :            : }
         524                 :            : #endif

Generated by: LCOV version 1.14