Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Tools/c-analyzer/distutils/util.py
12 views
1
"""distutils.util
2
3
Miscellaneous utility functions -- anything that doesn't fit into
4
one of the other *util.py modules.
5
"""
6
7
import os
8
import re
9
import string
10
import sys
11
from distutils.errors import DistutilsPlatformError
12
13
def get_host_platform():
14
"""Return a string that identifies the current platform. This is used mainly to
15
distinguish platform-specific build directories and platform-specific built
16
distributions. Typically includes the OS name and version and the
17
architecture (as supplied by 'os.uname()'), although the exact information
18
included depends on the OS; eg. on Linux, the kernel version isn't
19
particularly important.
20
21
Examples of returned values:
22
linux-i586
23
linux-alpha (?)
24
solaris-2.6-sun4u
25
26
Windows will return one of:
27
win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
28
win32 (all others - specifically, sys.platform is returned)
29
30
For other non-POSIX platforms, currently just returns 'sys.platform'.
31
32
"""
33
if os.name == 'nt':
34
if 'amd64' in sys.version.lower():
35
return 'win-amd64'
36
if '(arm)' in sys.version.lower():
37
return 'win-arm32'
38
if '(arm64)' in sys.version.lower():
39
return 'win-arm64'
40
return sys.platform
41
42
# Set for cross builds explicitly
43
if "_PYTHON_HOST_PLATFORM" in os.environ:
44
return os.environ["_PYTHON_HOST_PLATFORM"]
45
46
if os.name != "posix" or not hasattr(os, 'uname'):
47
# XXX what about the architecture? NT is Intel or Alpha,
48
# Mac OS is M68k or PPC, etc.
49
return sys.platform
50
51
# Try to distinguish various flavours of Unix
52
53
(osname, host, release, version, machine) = os.uname()
54
55
# Convert the OS name to lowercase, remove '/' characters, and translate
56
# spaces (for "Power Macintosh")
57
osname = osname.lower().replace('/', '')
58
machine = machine.replace(' ', '_')
59
machine = machine.replace('/', '-')
60
61
if osname[:5] == "linux":
62
# At least on Linux/Intel, 'machine' is the processor --
63
# i386, etc.
64
# XXX what about Alpha, SPARC, etc?
65
return "%s-%s" % (osname, machine)
66
elif osname[:5] == "sunos":
67
if release[0] >= "5": # SunOS 5 == Solaris 2
68
osname = "solaris"
69
release = "%d.%s" % (int(release[0]) - 3, release[2:])
70
# We can't use "platform.architecture()[0]" because a
71
# bootstrap problem. We use a dict to get an error
72
# if some suspicious happens.
73
bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
74
machine += ".%s" % bitness[sys.maxsize]
75
# fall through to standard osname-release-machine representation
76
elif osname[:3] == "aix":
77
from _aix_support import aix_platform
78
return aix_platform()
79
elif osname[:6] == "cygwin":
80
osname = "cygwin"
81
rel_re = re.compile (r'[\d.]+', re.ASCII)
82
m = rel_re.match(release)
83
if m:
84
release = m.group()
85
elif osname[:6] == "darwin":
86
import _osx_support, sysconfig
87
osname, release, machine = _osx_support.get_platform_osx(
88
sysconfig.get_config_vars(),
89
osname, release, machine)
90
91
return "%s-%s-%s" % (osname, release, machine)
92
93
def get_platform():
94
if os.name == 'nt':
95
TARGET_TO_PLAT = {
96
'x86' : 'win32',
97
'x64' : 'win-amd64',
98
'arm' : 'win-arm32',
99
}
100
return TARGET_TO_PLAT.get(os.environ.get('VSCMD_ARG_TGT_ARCH')) or get_host_platform()
101
else:
102
return get_host_platform()
103
104
105
# Needed by 'split_quoted()'
106
_wordchars_re = _squote_re = _dquote_re = None
107
def _init_regex():
108
global _wordchars_re, _squote_re, _dquote_re
109
_wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace)
110
_squote_re = re.compile(r"'(?:[^'\\]|\\.)*'")
111
_dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"')
112
113
def split_quoted (s):
114
"""Split a string up according to Unix shell-like rules for quotes and
115
backslashes. In short: words are delimited by spaces, as long as those
116
spaces are not escaped by a backslash, or inside a quoted string.
117
Single and double quotes are equivalent, and the quote characters can
118
be backslash-escaped. The backslash is stripped from any two-character
119
escape sequence, leaving only the escaped character. The quote
120
characters are stripped from any quoted string. Returns a list of
121
words.
122
"""
123
124
# This is a nice algorithm for splitting up a single string, since it
125
# doesn't require character-by-character examination. It was a little
126
# bit of a brain-bender to get it working right, though...
127
if _wordchars_re is None: _init_regex()
128
129
s = s.strip()
130
words = []
131
pos = 0
132
133
while s:
134
m = _wordchars_re.match(s, pos)
135
end = m.end()
136
if end == len(s):
137
words.append(s[:end])
138
break
139
140
if s[end] in string.whitespace: # unescaped, unquoted whitespace: now
141
words.append(s[:end]) # we definitely have a word delimiter
142
s = s[end:].lstrip()
143
pos = 0
144
145
elif s[end] == '\\': # preserve whatever is being escaped;
146
# will become part of the current word
147
s = s[:end] + s[end+1:]
148
pos = end+1
149
150
else:
151
if s[end] == "'": # slurp singly-quoted string
152
m = _squote_re.match(s, end)
153
elif s[end] == '"': # slurp doubly-quoted string
154
m = _dquote_re.match(s, end)
155
else:
156
raise RuntimeError("this can't happen (bad char '%c')" % s[end])
157
158
if m is None:
159
raise ValueError("bad string (mismatched %s quotes?)" % s[end])
160
161
(beg, end) = m.span()
162
s = s[:beg] + s[beg+1:end-1] + s[end:]
163
pos = m.end() - 2
164
165
if pos >= len(s):
166
words.append(s)
167
break
168
169
return words
170
171
# split_quoted ()
172
173