chore: directory structure
This commit is contained in:
4
pycdc/scripts/.gitignore
vendored
Normal file
4
pycdc/scripts/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
tarballs/
|
||||
Python-*/
|
||||
Python-*.conf.log
|
||||
Python-*.build.log
|
42
pycdc/scripts/Dockerfile.pybuild
Normal file
42
pycdc/scripts/Dockerfile.pybuild
Normal file
@@ -0,0 +1,42 @@
|
||||
#
|
||||
# This will generate a local container with the specified version of Python.
|
||||
#
|
||||
# Note: This assumes the the tarball for the particular version you'd like to build has already been downloaded,
|
||||
# unpacked, and patched appropriately.
|
||||
#
|
||||
# To build:
|
||||
# docker build --build-arg python_version=PYTHON-VERSION \
|
||||
# --build-arg install_target=INSTALL-TARGET \
|
||||
# -f Dockerfile.pybuild \
|
||||
# -t python:PYTHON-VERSION
|
||||
#
|
||||
# PYTHON-VERSION full version of Python to build (ex. 3.0.1)
|
||||
# INSTALL-TARGET the target to make for installing (fullinstall for 3.0.1, install otherwise)
|
||||
#
|
||||
# Example for 3.0.1:
|
||||
# docker build --build-arg python_version=3.0.1 \
|
||||
# --build-arg install_target=fullinstall \
|
||||
# -f Dockerfile.pybuild \
|
||||
# -t python:3.0.1
|
||||
#
|
||||
|
||||
FROM debian:buster
|
||||
|
||||
ARG python_version
|
||||
ARG install_target
|
||||
|
||||
RUN mkdir -p /pybuild/ &&\
|
||||
apt-get update && \
|
||||
apt-get upgrade -y && \
|
||||
apt-get install -y build-essential libncurses-dev libz-dev libbz2-dev libreadline-dev
|
||||
|
||||
COPY Python-$python_version /pybuild/
|
||||
|
||||
RUN cd pybuild &&\
|
||||
./configure && \
|
||||
make && \
|
||||
make $install_target && \
|
||||
cd / && \
|
||||
apt-get remove -y build-essential libncurses-dev libz-dev libbz2-dev libreadline-dev && \
|
||||
apt autoremove -y && \
|
||||
rm -rf /pybuild
|
357
pycdc/scripts/pymultic
Normal file
357
pycdc/scripts/pymultic
Normal file
@@ -0,0 +1,357 @@
|
||||
#!/usr/bin/env python3
|
||||
# PyMultiC - Python Multiple Compiler
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import shutil
|
||||
import re
|
||||
|
||||
PYVERS = {
|
||||
'1.0': '1.0.1',
|
||||
'1.1': '1.1',
|
||||
'1.2': '1.2',
|
||||
'1.3': '1.3',
|
||||
'1.4': '1.4',
|
||||
'1.5': '1.5.2',
|
||||
'1.6': '1.6.1',
|
||||
'2.0': '2.0.1',
|
||||
'2.1': '2.1.3',
|
||||
'2.2': '2.2.3',
|
||||
'2.3': '2.3.7',
|
||||
'2.4': '2.4.6',
|
||||
'2.5': '2.5.6',
|
||||
'2.6': '2.6.9',
|
||||
'2.7': '2.7.18',
|
||||
'3.0': '3.0.1',
|
||||
'3.1': '3.1.5',
|
||||
'3.2': '3.2.6',
|
||||
'3.3': '3.3.7',
|
||||
'3.4': '3.4.10',
|
||||
'3.5': '3.5.10',
|
||||
'3.6': '3.6.15',
|
||||
'3.7': '3.7.17',
|
||||
'3.8': '3.8.18',
|
||||
'3.9': '3.9.18',
|
||||
'3.10': '3.10.13',
|
||||
'3.11': '3.11.6',
|
||||
'3.12': '3.12.0',
|
||||
}
|
||||
|
||||
OLD_PYTHONS = ('1.0', '1.1', '1.2', '1.3', '1.4', '1.5')
|
||||
OLD_PYURL = 'https://legacy.python.org/download/releases/src'
|
||||
PYURL = 'https://www.python.org/ftp/python'
|
||||
|
||||
# Not all versions of Python have an official container.
|
||||
PYVER_CONTAINERS = {
|
||||
'2.7',
|
||||
'3.2',
|
||||
'3.3',
|
||||
'3.4',
|
||||
'3.5',
|
||||
'3.6',
|
||||
'3.7',
|
||||
'3.8',
|
||||
'3.9',
|
||||
'3.10',
|
||||
'3.11',
|
||||
'3.12',
|
||||
}
|
||||
CONTAINER_EXES = ['podman', 'docker']
|
||||
CONTAINER_EXE_EXTRA_ARGS = {
|
||||
'podman': [],
|
||||
'docker': ['-u', '{}:{}'.format(os.getuid(), os.getgid())], # Docker requires extra magic for permissions.
|
||||
}
|
||||
|
||||
|
||||
def get_container_exe():
|
||||
container_exe = None
|
||||
for ce in CONTAINER_EXES:
|
||||
if shutil.which(ce) is not None:
|
||||
container_exe = ce
|
||||
break
|
||||
|
||||
if container_exe is None:
|
||||
print('Cannot find {} in $PATH'.format(' or '.join(CONTAINER_EXES)))
|
||||
return sys.exit(1)
|
||||
|
||||
return container_exe
|
||||
|
||||
|
||||
def fetch_python(snekdir, version):
|
||||
realver = PYVERS[version]
|
||||
if version in ('1.0', '1.1'):
|
||||
tarball = 'python{}.tar.gz'.format(realver)
|
||||
url = '{}/{}'.format(OLD_PYURL, tarball)
|
||||
elif version in ('1.2', '1.3', '1.4', '1.5'):
|
||||
tarball = 'python-{}.tar.gz'.format(realver)
|
||||
url = '{}/{}'.format(OLD_PYURL, tarball)
|
||||
elif version == '1.6':
|
||||
tarball = 'Python-{}.tar.gz'.format(realver)
|
||||
url = None
|
||||
else:
|
||||
tarball = 'Python-{}.tgz'.format(realver)
|
||||
url = '{}/{}/{}'.format(PYURL, realver, tarball)
|
||||
|
||||
pyver_dir = os.path.join(snekdir, 'Python-{}'.format(realver))
|
||||
if os.path.exists(pyver_dir):
|
||||
return
|
||||
|
||||
tb_dir = os.path.join(snekdir, 'tarballs')
|
||||
if not os.path.exists(tb_dir):
|
||||
os.makedirs(tb_dir)
|
||||
tarfile = os.path.join(tb_dir, tarball)
|
||||
if not os.path.exists(tarfile):
|
||||
if version == '1.6':
|
||||
print('Python 1.6.1 cannot be downloaded automatically due to a license agreement')
|
||||
print('which must be manually accepted.')
|
||||
print('Please download it from https://www.python.org/download/releases/1.6.1/download/')
|
||||
print('and place the tarball in {}'.format(tb_dir))
|
||||
sys.exit(1)
|
||||
|
||||
print('Downloading Python {}...'.format(realver))
|
||||
if subprocess.call(['curl', '-LfO#', url], cwd=tb_dir) != 0:
|
||||
sys.exit(1)
|
||||
|
||||
print('Extracting Python {}...'.format(realver))
|
||||
if subprocess.call(['tar', 'xaf', tarfile], cwd=snekdir) != 0:
|
||||
sys.exit(1)
|
||||
|
||||
if os.path.exists(os.path.join(snekdir, 'python-{}'.format(realver))) \
|
||||
and not os.path.exists(pyver_dir):
|
||||
# The dual check prevents useless renames on case-insensitive
|
||||
# file systems
|
||||
os.rename(os.path.join(snekdir, 'python-{}'.format(realver)), pyver_dir)
|
||||
|
||||
patch_file = os.path.join(snekdir, 'python-builds', 'Python-{}.patch'.format(realver))
|
||||
if os.path.exists(patch_file):
|
||||
if subprocess.call(['patch', '-p1', '-i', patch_file], cwd=pyver_dir) != 0:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def build_python(snekdir, version):
|
||||
realver = PYVERS[version]
|
||||
snek = 'Python-{}'.format(realver)
|
||||
builddir = os.path.join(snekdir, snek)
|
||||
|
||||
# NOTE: This has only been tested on a Debian 10 x86_64 system -- it is
|
||||
# probably not as robust as it should be...
|
||||
print('Configuring Python {}...'.format(realver))
|
||||
logfile = os.path.join(snekdir, '{}.conf.log'.format(snek))
|
||||
with open(logfile, 'wb') as log:
|
||||
if subprocess.call(['./configure'], stdout=log, stderr=log, cwd=builddir) != 0:
|
||||
print('... Configuration failed. See {} for details'.format(logfile))
|
||||
sys.exit(1)
|
||||
|
||||
print('Building Python {}...'.format(realver))
|
||||
logfile = os.path.join(snekdir, '{}.build.log'.format(snek))
|
||||
with open(logfile, 'wb') as log:
|
||||
if subprocess.call(['make'], stdout=log, stderr=log, cwd=builddir) != 0:
|
||||
print('... Build failed. See {} for details'.format(logfile))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def acquire_python(snekdir, version):
|
||||
snek = 'Python-{}'.format(PYVERS[version])
|
||||
pyexe = os.path.join(snekdir, snek, 'python')
|
||||
if not os.path.exists(pyexe):
|
||||
fetch_python(snekdir, version)
|
||||
build_python(snekdir, version)
|
||||
return pyexe
|
||||
|
||||
|
||||
def build_python_container(snekdir, version):
|
||||
realver = PYVERS[version]
|
||||
snek = 'Python-{}'.format(realver)
|
||||
builddir = os.path.join(snekdir, snek)
|
||||
container_exe = get_container_exe()
|
||||
py_container_tag = 'python:{}'.format(realver)
|
||||
|
||||
if subprocess.call([container_exe, 'image', 'inspect', py_container_tag],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL) == 0:
|
||||
return
|
||||
|
||||
fetch_python(snekdir, version)
|
||||
|
||||
print('Building Python {} container...'.format(realver))
|
||||
logfile = os.path.join(snekdir, '{}.build.log'.format(snek))
|
||||
install_target = 'fullinstall' if version == '3.0' else 'install'
|
||||
with open(logfile, 'wb') as log:
|
||||
if subprocess.call([container_exe, 'build',
|
||||
'--build-arg', 'python_version={}'.format(realver),
|
||||
'--build-arg', 'install_target={}'.format(install_target),
|
||||
'-f', os.path.join(snekdir, 'Dockerfile.pybuild'),
|
||||
'-t', py_container_tag, snekdir], stdout=log, stderr=log) != 0:
|
||||
print('...Container build failed. See {} for details'.format(logfile))
|
||||
sys.exit(1)
|
||||
|
||||
shutil.rmtree(builddir)
|
||||
|
||||
|
||||
def local_compile(snekdir, ver, infile):
|
||||
pyexe = acquire_python(snekdir, ver)
|
||||
proc = subprocess.Popen([pyexe, '-c', 'import sys; print(sys.version)'],
|
||||
stdout=subprocess.PIPE)
|
||||
out, _ = proc.communicate()
|
||||
if proc.returncode != 0:
|
||||
print('Could not determine Python version for {}'.format(ver))
|
||||
return None
|
||||
|
||||
bcver = str(out, 'iso-8859-1').split(' ', 1)[0]
|
||||
if not bcver.startswith(ver):
|
||||
print('Python {} reported itself as version {}!'.format(ver, bcver))
|
||||
return None
|
||||
|
||||
if infile.endswith('.py'):
|
||||
outfile = os.path.basename(infile)[:-3]
|
||||
else:
|
||||
outfile = os.path.basename(infile)
|
||||
outfile += '.{}.pyc'.format(ver)
|
||||
if os.path.exists(outfile):
|
||||
os.unlink(outfile)
|
||||
|
||||
print('*** Compiling for Python {}'.format(bcver))
|
||||
if ver in {'1.0', '1.1', '1.2', '1.3', '1.4'}:
|
||||
# The hard way -- hope your code is safe...
|
||||
srcdir = os.path.dirname(os.path.realpath(infile))
|
||||
comptmp = os.path.join(srcdir, 'pymc_temp.py')
|
||||
if os.path.exists(comptmp):
|
||||
os.unlink(comptmp)
|
||||
shutil.copyfile(infile, comptmp)
|
||||
cwdsave = os.getcwd()
|
||||
os.chdir(srcdir)
|
||||
proc = subprocess.Popen([pyexe, '-c', 'import pymc_temp'])
|
||||
proc.communicate()
|
||||
os.chdir(cwdsave)
|
||||
if os.path.exists(comptmp + 'o'):
|
||||
shutil.copyfile(comptmp + 'o', outfile)
|
||||
os.unlink(comptmp + 'o')
|
||||
elif os.path.exists(comptmp + 'c'):
|
||||
shutil.copyfile(comptmp + 'c', outfile)
|
||||
os.unlink(comptmp + 'c')
|
||||
os.unlink(comptmp)
|
||||
else:
|
||||
# The easy way
|
||||
proc = subprocess.Popen([pyexe, '-c',
|
||||
"import py_compile; py_compile.compile('{}', '{}')" \
|
||||
.format(infile, outfile)])
|
||||
proc.communicate()
|
||||
|
||||
return outfile
|
||||
|
||||
|
||||
def container_compile(snekdir, ver, infile):
|
||||
if ver not in PYVER_CONTAINERS:
|
||||
build_python_container(snekdir, ver)
|
||||
|
||||
container_exe = get_container_exe()
|
||||
fullver = PYVERS[ver]
|
||||
indir = os.path.dirname(os.path.abspath(infile))
|
||||
infile_full_path = infile
|
||||
infile = os.path.basename(infile)
|
||||
|
||||
if infile.endswith('.py'):
|
||||
outfile = infile[:-3]
|
||||
else:
|
||||
outfile = infile
|
||||
outfile += '.{}.pyc'.format(ver)
|
||||
if os.path.exists(outfile):
|
||||
os.unlink(outfile)
|
||||
|
||||
print('*** Compiling for Python {}'.format(fullver))
|
||||
if ver in {'1.0', '1.1', '1.2', '1.3', '1.4'}:
|
||||
# The hard way -- hope your code is safe...
|
||||
comptmp = os.path.join(indir, 'pymc_temp.py')
|
||||
if os.path.exists(comptmp):
|
||||
os.unlink(comptmp)
|
||||
shutil.copyfile(infile_full_path, comptmp)
|
||||
proc = subprocess.Popen([container_exe, 'run'] + CONTAINER_EXE_EXTRA_ARGS[container_exe] +
|
||||
['--rm', '--name', outfile,
|
||||
'-v', '{}:/indir:Z'.format(indir),
|
||||
'-v', '{}:/outdir:Z'.format(os.getcwd()), '-w', '/outdir',
|
||||
'-w', '/indir',
|
||||
'python:{}'.format(fullver),
|
||||
'python', '-c',
|
||||
"import pymc_temp"])
|
||||
proc.communicate()
|
||||
if os.path.exists(comptmp + 'o'):
|
||||
shutil.copyfile(comptmp + 'o', outfile)
|
||||
os.unlink(comptmp + 'o')
|
||||
elif os.path.exists(comptmp + 'c'):
|
||||
shutil.copyfile(comptmp + 'c', outfile)
|
||||
os.unlink(comptmp + 'c')
|
||||
os.unlink(comptmp)
|
||||
else:
|
||||
# The easy way
|
||||
proc = subprocess.Popen([container_exe, 'run'] + CONTAINER_EXE_EXTRA_ARGS[container_exe] +
|
||||
['--rm', '--name', outfile,
|
||||
'-v', '{}:/indir:Z'.format(indir),
|
||||
'-v', '{}:/outdir:Z'.format(os.getcwd()), '-w', '/outdir',
|
||||
'python:{}'.format(fullver),
|
||||
'python', '-c',
|
||||
"import py_compile; py_compile.compile('/indir/{}', '{}')".format(infile, outfile)])
|
||||
proc.communicate()
|
||||
|
||||
return outfile
|
||||
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print('Usage: {} [-c] [versions] input.py'.format(sys.argv[0]))
|
||||
print('Compile input.py for one or more python versions')
|
||||
print()
|
||||
print('-c\tuse prebuilt containers for running different versions of Python')
|
||||
print('\t(not available for all versions)')
|
||||
print()
|
||||
print('Output is written to input.<version>.pyc for each version successfully compiled')
|
||||
print()
|
||||
print('Version is X.Y (e.g. 3.4), not including the patch version')
|
||||
sys.exit(1)
|
||||
|
||||
RE_PYVER = re.compile(r'\d\.\d')
|
||||
|
||||
pythons = []
|
||||
infile = None
|
||||
use_containers = False
|
||||
for arg in sys.argv[1:]:
|
||||
if RE_PYVER.match(arg):
|
||||
if arg in PYVERS.keys():
|
||||
pythons.append(arg)
|
||||
else:
|
||||
print('Unknown Python version: {}'.format(arg))
|
||||
sys.exit(1)
|
||||
elif arg == '-c':
|
||||
use_containers = True
|
||||
elif arg.startswith('-'):
|
||||
print("WARNING: Unrecognized argument '{}'".format(arg))
|
||||
else:
|
||||
infile = arg
|
||||
|
||||
if infile is None:
|
||||
print('No input file specified')
|
||||
sys.exit(1)
|
||||
elif not os.path.exists(infile):
|
||||
print('Error: Input file {} does not exist'.format(infile))
|
||||
sys.exit(1)
|
||||
|
||||
if len(pythons) == 0:
|
||||
print('At least one Python version is required')
|
||||
sys.exit(1)
|
||||
|
||||
snekdir = os.path.dirname(os.path.realpath(__file__))
|
||||
result = 0
|
||||
for ver in pythons:
|
||||
compile_with_container = use_containers
|
||||
if use_containers and ver not in PYVER_CONTAINERS:
|
||||
print('Warning: No officially supported container for {} - using locally built one'.format(ver))
|
||||
|
||||
outfile = None
|
||||
if compile_with_container:
|
||||
outfile = container_compile(snekdir, ver, infile)
|
||||
else:
|
||||
outfile = local_compile(snekdir, ver, infile)
|
||||
|
||||
if outfile is None or not os.path.exists(outfile):
|
||||
result = 1
|
||||
|
||||
sys.exit(result)
|
40
pycdc/scripts/python-builds/Python-1.0.1.patch
Normal file
40
pycdc/scripts/python-builds/Python-1.0.1.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
|
||||
index e79a671..b1bd74e 100644
|
||||
--- a/Objects/fileobject.c
|
||||
+++ b/Objects/fileobject.c
|
||||
@@ -336,7 +336,7 @@ file_read(f, args)
|
||||
*/
|
||||
|
||||
static object *
|
||||
-getline(f, n)
|
||||
+_py_getline(f, n)
|
||||
fileobject *f;
|
||||
int n;
|
||||
{
|
||||
@@ -458,7 +458,7 @@ filegetline(f, n)
|
||||
}
|
||||
if (((fileobject*)f)->f_fp == NULL)
|
||||
return err_closed();
|
||||
- return getline((fileobject *)f, n);
|
||||
+ return _py_getline((fileobject *)f, n);
|
||||
}
|
||||
|
||||
/* Python method */
|
||||
@@ -483,7 +483,7 @@ file_readline(f, args)
|
||||
}
|
||||
}
|
||||
|
||||
- return getline(f, n);
|
||||
+ return _py_getline(f, n);
|
||||
}
|
||||
|
||||
static object *
|
||||
@@ -501,7 +501,7 @@ file_readlines(f, args)
|
||||
if ((list = newlistobject(0)) == NULL)
|
||||
return NULL;
|
||||
for (;;) {
|
||||
- line = getline(f, 0);
|
||||
+ line = _py_getline(f, 0);
|
||||
if (line != NULL && getstringsize(line) == 0) {
|
||||
DECREF(line);
|
||||
break;
|
8870
pycdc/scripts/python-builds/Python-1.1.patch
Normal file
8870
pycdc/scripts/python-builds/Python-1.1.patch
Normal file
File diff suppressed because it is too large
Load Diff
9008
pycdc/scripts/python-builds/Python-1.2.patch
Normal file
9008
pycdc/scripts/python-builds/Python-1.2.patch
Normal file
File diff suppressed because it is too large
Load Diff
8910
pycdc/scripts/python-builds/Python-1.3.patch
Normal file
8910
pycdc/scripts/python-builds/Python-1.3.patch
Normal file
File diff suppressed because it is too large
Load Diff
9594
pycdc/scripts/python-builds/Python-1.4.patch
Normal file
9594
pycdc/scripts/python-builds/Python-1.4.patch
Normal file
File diff suppressed because it is too large
Load Diff
40
pycdc/scripts/python-builds/Python-1.5.2.patch
Normal file
40
pycdc/scripts/python-builds/Python-1.5.2.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
|
||||
index b0eb332..e1aa559 100644
|
||||
--- a/Objects/fileobject.c
|
||||
+++ b/Objects/fileobject.c
|
||||
@@ -587,7 +587,7 @@ file_readinto(f, args)
|
||||
*/
|
||||
|
||||
static PyObject *
|
||||
-getline(f, n)
|
||||
+_py_getline(f, n)
|
||||
PyFileObject *f;
|
||||
int n;
|
||||
{
|
||||
@@ -709,7 +709,7 @@ PyFile_GetLine(f, n)
|
||||
}
|
||||
if (((PyFileObject*)f)->f_fp == NULL)
|
||||
return err_closed();
|
||||
- return getline((PyFileObject *)f, n);
|
||||
+ return _py_getline((PyFileObject *)f, n);
|
||||
}
|
||||
|
||||
/* Python method */
|
||||
@@ -729,7 +729,7 @@ file_readline(f, args)
|
||||
return PyString_FromString("");
|
||||
if (n < 0)
|
||||
n = 0;
|
||||
- return getline(f, n);
|
||||
+ return _py_getline(f, n);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
@@ -823,7 +823,7 @@ file_readlines(f, args)
|
||||
goto error;
|
||||
if (sizehint > 0) {
|
||||
/* Need to complete the last line */
|
||||
- PyObject *rest = getline(f, 0);
|
||||
+ PyObject *rest = _py_getline(f, 0);
|
||||
if (rest == NULL) {
|
||||
Py_DECREF(line);
|
||||
goto error;
|
34
pycdc/scripts/python-builds/Python-2.3.7.patch
Normal file
34
pycdc/scripts/python-builds/Python-2.3.7.patch
Normal file
@@ -0,0 +1,34 @@
|
||||
diff -rupN a/Include/objimpl.h b/Include/objimpl.h
|
||||
--- a/Include/objimpl.h 2003-04-17 10:29:22.000000000 -0700
|
||||
+++ b/Include/objimpl.h 2019-09-30 15:42:32.012660303 -0700
|
||||
@@ -245,6 +245,20 @@ PyAPI_FUNC(PyVarObject *) _PyObject_GC_R
|
||||
/* for source compatibility with 2.2 */
|
||||
#define _PyObject_GC_Del PyObject_GC_Del
|
||||
|
||||
+/*
|
||||
+ * Former over-aligned definition of PyGC_Head, used to compute the size of the
|
||||
+ * padding for the new version below.
|
||||
+ */
|
||||
+union _gc_head;
|
||||
+union _gc_head_old {
|
||||
+ struct {
|
||||
+ union _gc_head_old *gc_next;
|
||||
+ union _gc_head_old *gc_prev;
|
||||
+ int gc_refs;
|
||||
+ } gc;
|
||||
+ long double dummy;
|
||||
+};
|
||||
+
|
||||
/* GC information is stored BEFORE the object structure. */
|
||||
typedef union _gc_head {
|
||||
struct {
|
||||
@@ -252,7 +266,8 @@ typedef union _gc_head {
|
||||
union _gc_head *gc_prev;
|
||||
int gc_refs;
|
||||
} gc;
|
||||
- long double dummy; /* force worst-case alignment */
|
||||
+ double dummy; /* Force at least 8-byte alignment. */
|
||||
+ char dummy_padding[sizeof(union _gc_head_old)];
|
||||
} PyGC_Head;
|
||||
|
||||
extern PyGC_Head *_PyGC_generation0;
|
34
pycdc/scripts/python-builds/Python-2.4.6.patch
Normal file
34
pycdc/scripts/python-builds/Python-2.4.6.patch
Normal file
@@ -0,0 +1,34 @@
|
||||
diff -rupN a/Include/objimpl.h b/Include/objimpl.h
|
||||
--- a/Include/objimpl.h 2003-04-17 10:29:22.000000000 -0700
|
||||
+++ b/Include/objimpl.h 2019-09-30 15:42:32.012660303 -0700
|
||||
@@ -245,6 +245,20 @@ PyAPI_FUNC(PyVarObject *) _PyObject_GC_R
|
||||
/* for source compatibility with 2.2 */
|
||||
#define _PyObject_GC_Del PyObject_GC_Del
|
||||
|
||||
+/*
|
||||
+ * Former over-aligned definition of PyGC_Head, used to compute the size of the
|
||||
+ * padding for the new version below.
|
||||
+ */
|
||||
+union _gc_head;
|
||||
+union _gc_head_old {
|
||||
+ struct {
|
||||
+ union _gc_head_old *gc_next;
|
||||
+ union _gc_head_old *gc_prev;
|
||||
+ int gc_refs;
|
||||
+ } gc;
|
||||
+ long double dummy;
|
||||
+};
|
||||
+
|
||||
/* GC information is stored BEFORE the object structure. */
|
||||
typedef union _gc_head {
|
||||
struct {
|
||||
@@ -252,7 +266,8 @@ typedef union _gc_head {
|
||||
union _gc_head *gc_prev;
|
||||
int gc_refs;
|
||||
} gc;
|
||||
- long double dummy; /* force worst-case alignment */
|
||||
+ double dummy; /* Force at least 8-byte alignment. */
|
||||
+ char dummy_padding[sizeof(union _gc_head_old)];
|
||||
} PyGC_Head;
|
||||
|
||||
extern PyGC_Head *_PyGC_generation0;
|
83
pycdc/scripts/python-builds/Python-2.5.6.patch
Normal file
83
pycdc/scripts/python-builds/Python-2.5.6.patch
Normal file
@@ -0,0 +1,83 @@
|
||||
diff -rupN a/Include/objimpl.h b/Include/objimpl.h
|
||||
--- a/Include/objimpl.h 2006-04-14 20:22:46.000000000 -0700
|
||||
+++ b/Include/objimpl.h 2019-09-30 15:52:15.197269278 -0700
|
||||
@@ -241,6 +241,20 @@ PyAPI_FUNC(PyVarObject *) _PyObject_GC_R
|
||||
/* for source compatibility with 2.2 */
|
||||
#define _PyObject_GC_Del PyObject_GC_Del
|
||||
|
||||
+/*
|
||||
+ * Former over-aligned definition of PyGC_Head, used to compute the size of the
|
||||
+ * padding for the new version below.
|
||||
+ */
|
||||
+union _gc_head;
|
||||
+union _gc_head_old {
|
||||
+ struct {
|
||||
+ union _gc_head_old *gc_next;
|
||||
+ union _gc_head_old *gc_prev;
|
||||
+ Py_ssize_t gc_refs;
|
||||
+ } gc;
|
||||
+ long double dummy;
|
||||
+};
|
||||
+
|
||||
/* GC information is stored BEFORE the object structure. */
|
||||
typedef union _gc_head {
|
||||
struct {
|
||||
@@ -248,7 +262,8 @@ typedef union _gc_head {
|
||||
union _gc_head *gc_prev;
|
||||
Py_ssize_t gc_refs;
|
||||
} gc;
|
||||
- long double dummy; /* force worst-case alignment */
|
||||
+ double dummy; /* Force at least 8-byte alignment. */
|
||||
+ char dummy_padding[sizeof(union _gc_head_old)];
|
||||
} PyGC_Head;
|
||||
|
||||
extern PyGC_Head *_PyGC_generation0;
|
||||
diff -rupN a/Makefile.pre.in b/Makefile.pre.in
|
||||
--- a/Makefile.pre.in 2008-09-21 17:22:44.000000000 -0700
|
||||
+++ b/Makefile.pre.in 2019-09-30 15:50:47.804578897 -0700
|
||||
@@ -458,7 +458,7 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \
|
||||
$(SIGNAL_OBJS) \
|
||||
$(MODOBJS) \
|
||||
$(srcdir)/Modules/getbuildinfo.c
|
||||
- $(CC) -c $(PY_CFLAGS) -DSVNVERSION=\"`LC_ALL=C $(SVNVERSION)`\" -o $@ $(srcdir)/Modules/getbuildinfo.c
|
||||
+ $(CC) -c $(PY_CFLAGS) -DSVNVERSION="\"`LC_ALL=C $(SVNVERSION)`\"" -o $@ $(srcdir)/Modules/getbuildinfo.c
|
||||
|
||||
Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile
|
||||
$(CC) -c $(PY_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \
|
||||
diff -rupN a/setup.py b/setup.py
|
||||
--- a/setup.py 2008-10-16 11:58:19.000000000 -0700
|
||||
+++ b/setup.py 2019-09-30 15:50:47.808578930 -0700
|
||||
@@ -296,7 +296,8 @@ class PyBuildExt(build_ext):
|
||||
# if a file is found in one of those directories, it can
|
||||
# be assumed that no additional -I,-L directives are needed.
|
||||
lib_dirs = self.compiler.library_dirs + [
|
||||
- '/lib64', '/usr/lib64',
|
||||
+ '/usr/lib/x86_64-linux-gnu',
|
||||
+ '/lib/x86_64-linux-gnu',
|
||||
'/lib', '/usr/lib',
|
||||
]
|
||||
inc_dirs = self.compiler.include_dirs + ['/usr/include']
|
||||
@@ -711,9 +712,9 @@ class PyBuildExt(build_ext):
|
||||
|
||||
# check lib directories parallel to the location of the header
|
||||
db_dirs_to_check = [
|
||||
- os.path.join(db_incdir, '..', 'lib64'),
|
||||
+ os.path.join(db_incdir, '..', 'lib/x86_64-linux-gnu'),
|
||||
os.path.join(db_incdir, '..', 'lib'),
|
||||
- os.path.join(db_incdir, '..', '..', 'lib64'),
|
||||
+ os.path.join(db_incdir, '..', '..', 'lib/x86_64-linux-gnu'),
|
||||
os.path.join(db_incdir, '..', '..', 'lib'),
|
||||
]
|
||||
db_dirs_to_check = filter(os.path.isdir, db_dirs_to_check)
|
||||
@@ -800,9 +801,9 @@ class PyBuildExt(build_ext):
|
||||
|
||||
if sqlite_incdir:
|
||||
sqlite_dirs_to_check = [
|
||||
- os.path.join(sqlite_incdir, '..', 'lib64'),
|
||||
+ os.path.join(sqlite_incdir, '..', 'lib/x86_64-linux-gnu'),
|
||||
os.path.join(sqlite_incdir, '..', 'lib'),
|
||||
- os.path.join(sqlite_incdir, '..', '..', 'lib64'),
|
||||
+ os.path.join(sqlite_incdir, '..', '..', 'lib/x86_64-linux-gnu'),
|
||||
os.path.join(sqlite_incdir, '..', '..', 'lib'),
|
||||
]
|
||||
sqlite_libfile = self.compiler.find_library_file(
|
68
pycdc/scripts/python-builds/Python-2.6.9.patch
Normal file
68
pycdc/scripts/python-builds/Python-2.6.9.patch
Normal file
@@ -0,0 +1,68 @@
|
||||
diff -rupN a/Include/objimpl.h b/Include/objimpl.h
|
||||
--- a/Include/objimpl.h 2013-10-29 08:04:37.000000000 -0700
|
||||
+++ b/Include/objimpl.h 2019-09-30 16:18:58.318197021 -0700
|
||||
@@ -241,6 +241,20 @@ PyAPI_FUNC(PyVarObject *) _PyObject_GC_R
|
||||
/* for source compatibility with 2.2 */
|
||||
#define _PyObject_GC_Del PyObject_GC_Del
|
||||
|
||||
+/*
|
||||
+ * Former over-aligned definition of PyGC_Head, used to compute the size of the
|
||||
+ * padding for the new version below.
|
||||
+ */
|
||||
+union _gc_head;
|
||||
+union _gc_head_old {
|
||||
+ struct {
|
||||
+ union _gc_head_old *gc_next;
|
||||
+ union _gc_head_old *gc_prev;
|
||||
+ Py_ssize_t gc_refs;
|
||||
+ } gc;
|
||||
+ long double dummy;
|
||||
+};
|
||||
+
|
||||
/* GC information is stored BEFORE the object structure. */
|
||||
typedef union _gc_head {
|
||||
struct {
|
||||
@@ -248,7 +262,8 @@ typedef union _gc_head {
|
||||
union _gc_head *gc_prev;
|
||||
Py_ssize_t gc_refs;
|
||||
} gc;
|
||||
- long double dummy; /* force worst-case alignment */
|
||||
+ double dummy; /* Force at least 8-byte alignment. */
|
||||
+ char dummy_padding[sizeof(union _gc_head_old)];
|
||||
} PyGC_Head;
|
||||
|
||||
extern PyGC_Head *_PyGC_generation0;
|
||||
diff -rupN a/setup.py b/setup.py
|
||||
--- a/setup.py 2013-10-29 08:04:39.000000000 -0700
|
||||
+++ b/setup.py 2019-09-30 16:19:09.146284481 -0700
|
||||
@@ -408,7 +408,8 @@ class PyBuildExt(build_ext):
|
||||
# if a file is found in one of those directories, it can
|
||||
# be assumed that no additional -I,-L directives are needed.
|
||||
lib_dirs = self.compiler.library_dirs + [
|
||||
- '/lib64', '/usr/lib64',
|
||||
+ '/usr/lib/x86_64-linux-gnu',
|
||||
+ '/lib/x86_64-linux-gnu',
|
||||
'/lib', '/usr/lib',
|
||||
]
|
||||
inc_dirs = self.compiler.include_dirs + ['/usr/include']
|
||||
@@ -922,7 +923,7 @@ class PyBuildExt(build_ext):
|
||||
|
||||
# check lib directories parallel to the location of the header
|
||||
db_dirs_to_check = [
|
||||
- db_incdir.replace("include", 'lib64'),
|
||||
+ db_incdir.replace("include", 'lib/x86_64-linux-gnu'),
|
||||
db_incdir.replace("include", 'lib'),
|
||||
]
|
||||
|
||||
@@ -1034,9 +1035,9 @@ class PyBuildExt(build_ext):
|
||||
|
||||
if sqlite_incdir:
|
||||
sqlite_dirs_to_check = [
|
||||
- os.path.join(sqlite_incdir, '..', 'lib64'),
|
||||
+ os.path.join(sqlite_incdir, '..', 'lib', 'x86_64-linux-gnu'),
|
||||
os.path.join(sqlite_incdir, '..', 'lib'),
|
||||
- os.path.join(sqlite_incdir, '..', '..', 'lib64'),
|
||||
+ os.path.join(sqlite_incdir, '..', '..', 'lib', 'x86_64-linux-gnu'),
|
||||
os.path.join(sqlite_incdir, '..', '..', 'lib'),
|
||||
]
|
||||
sqlite_libfile = self.compiler.find_library_file(
|
39
pycdc/scripts/python-builds/Python-3.0.1.patch
Normal file
39
pycdc/scripts/python-builds/Python-3.0.1.patch
Normal file
@@ -0,0 +1,39 @@
|
||||
diff --git a/Makefile.pre.in b/Makefile.pre.in
|
||||
index 4485a81..54a7e8d 100644
|
||||
--- a/Makefile.pre.in
|
||||
+++ b/Makefile.pre.in
|
||||
@@ -499,7 +499,7 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \
|
||||
$(SIGNAL_OBJS) \
|
||||
$(MODOBJS) \
|
||||
$(srcdir)/Modules/getbuildinfo.c
|
||||
- $(CC) -c $(PY_CFLAGS) -DSVNVERSION=\"`LC_ALL=C $(SVNVERSION)`\" -o $@ $(srcdir)/Modules/getbuildinfo.c
|
||||
+ $(CC) -c $(PY_CFLAGS) -DSVNVERSION="\"`LC_ALL=C $(SVNVERSION)`\"" -o $@ $(srcdir)/Modules/getbuildinfo.c
|
||||
|
||||
Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile
|
||||
$(CC) -c $(PY_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \
|
||||
diff --git a/setup.py b/setup.py
|
||||
index e1d5984..9051d09 100644
|
||||
--- a/setup.py
|
||||
+++ b/setup.py
|
||||
@@ -357,7 +357,8 @@ class PyBuildExt(build_ext):
|
||||
# if a file is found in one of those directories, it can
|
||||
# be assumed that no additional -I,-L directives are needed.
|
||||
lib_dirs = self.compiler.library_dirs + [
|
||||
- '/lib64', '/usr/lib64',
|
||||
+ '/lib/x86_64-linux-gnu',
|
||||
+ '/usr/lib/x86_64-linux-gnu',
|
||||
'/lib', '/usr/lib',
|
||||
]
|
||||
inc_dirs = self.compiler.include_dirs + ['/usr/include']
|
||||
@@ -725,9 +726,9 @@ class PyBuildExt(build_ext):
|
||||
|
||||
if sqlite_incdir:
|
||||
sqlite_dirs_to_check = [
|
||||
- os.path.join(sqlite_incdir, '..', 'lib64'),
|
||||
+ os.path.join(sqlite_incdir, '..', 'lib', 'x86_64-linux-gnu'),
|
||||
os.path.join(sqlite_incdir, '..', 'lib'),
|
||||
- os.path.join(sqlite_incdir, '..', '..', 'lib64'),
|
||||
+ os.path.join(sqlite_incdir, '..', '..', 'lib', 'x86_64-linux-gnu'),
|
||||
os.path.join(sqlite_incdir, '..', '..', 'lib'),
|
||||
]
|
||||
sqlite_libfile = self.compiler.find_library_file(
|
16
pycdc/scripts/python-builds/Python-3.1.5.patch
Normal file
16
pycdc/scripts/python-builds/Python-3.1.5.patch
Normal file
@@ -0,0 +1,16 @@
|
||||
diff --git a/Makefile.pre.in b/Makefile.pre.in
|
||||
index e01cd2745a..dcf465e30e 100644
|
||||
--- a/Makefile.pre.in
|
||||
+++ b/Makefile.pre.in
|
||||
@@ -817,6 +817,11 @@ bininstall: altbininstall
|
||||
else true; \
|
||||
fi
|
||||
(cd $(DESTDIR)$(BINDIR); $(LN) python$(VERSION)$(EXE) $(PYTHON)3$(EXE))
|
||||
+ -if test -f $(DESTDIR)$(BINDIR)/$(PYTHON)$(EXE) -o -h $(DESTDIR)$(BINDIR)/$(PYTHON)$(EXE); \
|
||||
+ then rm -f $(DESTDIR)$(BINDIR)/$(PYTHON)$(EXE); \
|
||||
+ else true; \
|
||||
+ fi
|
||||
+ (cd $(DESTDIR)$(BINDIR); $(LN) python$(VERSION)$(EXE) $(PYTHON)$(EXE))
|
||||
-rm -f $(DESTDIR)$(BINDIR)/python3-config
|
||||
(cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)-config python3-config)
|
||||
-rm -f $(DESTDIR)$(LIBPC)/python3.pc
|
270
pycdc/scripts/token_dump
Normal file
270
pycdc/scripts/token_dump
Normal file
@@ -0,0 +1,270 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Compare two python source files by tokens, ignoring whitespace (other than
|
||||
# indentation) and comments
|
||||
|
||||
import sys
|
||||
import re
|
||||
|
||||
|
||||
class PyToken:
|
||||
INDENT = 1
|
||||
OUTDENT = 2
|
||||
ENDLINE = 3
|
||||
WORD = 100
|
||||
INT = 101
|
||||
FLOAT = 102
|
||||
STRING = 103
|
||||
|
||||
def __init__(self, type, n_line):
|
||||
self.type = type
|
||||
self.n_line = n_line
|
||||
|
||||
def __str__(self):
|
||||
if self.type == PyToken.INDENT:
|
||||
return '<INDENT>'
|
||||
if self.type == PyToken.OUTDENT:
|
||||
return '<OUTDENT>'
|
||||
if self.type == PyToken.ENDLINE:
|
||||
return '<EOL>'
|
||||
return str(self.type)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.type == other.type
|
||||
|
||||
|
||||
class WordToken(PyToken):
|
||||
# We don't need to distinguish between keywords and other words, so
|
||||
# we just lump them together in a single token type...
|
||||
def __init__(self, word, n_line):
|
||||
super().__init__(PyToken.WORD, n_line)
|
||||
self.word = word
|
||||
|
||||
def __str__(self):
|
||||
return self.word
|
||||
|
||||
def __eq__(self, other):
|
||||
if not super().__eq__(other):
|
||||
return False
|
||||
return self.word == other.word
|
||||
|
||||
|
||||
class IntToken(PyToken):
|
||||
def __init__(self, value, n_line):
|
||||
super().__init__(PyToken.INT, n_line)
|
||||
try:
|
||||
self.value = int(value.replace('_', ''), 0)
|
||||
except ValueError:
|
||||
# Support Python 2.x octal literals
|
||||
if value.startswith('0'):
|
||||
self.value = int(value.replace('_', ''), 8)
|
||||
else:
|
||||
raise
|
||||
|
||||
def __str__(self):
|
||||
return str(self.value)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not super().__eq__(other):
|
||||
return False
|
||||
return self.value == other.value
|
||||
|
||||
|
||||
class FloatToken(PyToken):
|
||||
def __init__(self, value, n_line):
|
||||
super().__init__(PyToken.FLOAT, n_line)
|
||||
self.value = float(value.replace('_', ''))
|
||||
|
||||
def __str__(self):
|
||||
return str(self.value)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not super().__eq__(other):
|
||||
return False
|
||||
# TODO: Might need some fuzz
|
||||
return self.value == other.value
|
||||
|
||||
|
||||
class StringToken(PyToken):
|
||||
def __init__(self, prefix, content, n_line):
|
||||
super().__init__(PyToken.STRING, n_line)
|
||||
|
||||
# Normalize prefix for comparison
|
||||
self.prefix = ''.join(sorted(prefix.lower()))
|
||||
|
||||
# Normalize special characters for comparison
|
||||
self.content = content.replace("\\'", "'").replace("'", "\\'") \
|
||||
.replace('\\"', '"').replace('\t', '\\t') \
|
||||
.replace('\n', '\\n').replace('\r', '\\r')
|
||||
|
||||
def __str__(self):
|
||||
return "{}'{}'".format(self.prefix, self.content)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not super().__eq__(other):
|
||||
return False
|
||||
return self.prefix == other.prefix and self.content == other.content
|
||||
|
||||
|
||||
RE_WHITESPACE = re.compile(r'\s+')
|
||||
RE_WORD = re.compile(r'[A-Za-z_][A-Za-z0-9_]*')
|
||||
RE_INT = re.compile(r'[0-9][0-9_]*|0[Xx][0-9A-Fa-f_]+|0[Bb][0-1_]+|0[Oo][0-7_]+')
|
||||
RE_FLOAT = re.compile(r'(([0-9][0-9_]*)?\.[0-9][0-9_]*|[0-9][0-9_]*\.)([eE][+-]?[0-9][0-9_]*)?')
|
||||
RE_START_STRING = re.compile(r'([rR][fFbB]?|[uU]|[fF][rR]?|[bB][rR]?)?(\'\'\'|\'|"""|")')
|
||||
|
||||
# Note, tokens sharing a common prefix should be entered in order from
|
||||
# longest to shortest, so we don't mismatch a long token as a sequence
|
||||
# of shorter tokens
|
||||
SYMBOLIC_TOKENS = (
|
||||
'<<=', '>>=', '**=', '//=', '...', '.',
|
||||
'+=', '-=', '*=', '@=', '/=', '%=', '&=', '|=', '^=',
|
||||
'<>', '<<', '<=', '<', '>>', '>=', '>', '!=', '==', '=',
|
||||
',', ';', ':=', ':', '->', '~', '`',
|
||||
'+', '-', '**', '*', '@', '//', '/', '%', '&', '|', '^',
|
||||
'(', ')', '{', '}', '[', ']',
|
||||
)
|
||||
def symbolic_token(line, n_line):
|
||||
for tok in SYMBOLIC_TOKENS:
|
||||
if line.startswith(tok):
|
||||
return PyToken(tok, n_line)
|
||||
return None
|
||||
|
||||
|
||||
def string_token(line, n_line, pysrc):
|
||||
match = RE_START_STRING.match(line)
|
||||
if not match:
|
||||
return None
|
||||
|
||||
# Look for the end of the string
|
||||
prefix = match.group(1)
|
||||
if prefix is None:
|
||||
prefix = ''
|
||||
quotes = match.group(2)
|
||||
start = len(prefix) + len(quotes)
|
||||
content = ''
|
||||
while True:
|
||||
end = line.find(quotes, start)
|
||||
if end > 0 and line[end - 1] == '\\':
|
||||
content += line[start:end + 1]
|
||||
start = end + 1
|
||||
continue
|
||||
elif end >= 0:
|
||||
content += line[start:end]
|
||||
break
|
||||
|
||||
# Read in a new line
|
||||
content += line[start:]
|
||||
line = pysrc.readline()
|
||||
n_line += 1
|
||||
start = 0
|
||||
if not line:
|
||||
raise RuntimeError('Reached EOF while looking for {}'.format(repr(quotes)))
|
||||
|
||||
token = StringToken(prefix, content, n_line)
|
||||
token.rem_line = line[end + len(quotes):]
|
||||
token.end_line = n_line
|
||||
return token
|
||||
|
||||
|
||||
def read_tokens(pysrc):
|
||||
indent_stack = [0]
|
||||
context_stack = []
|
||||
n_line = 0
|
||||
|
||||
while True:
|
||||
line = pysrc.readline()
|
||||
n_line += 1
|
||||
if not line:
|
||||
break
|
||||
|
||||
if not line.strip() or line.lstrip().startswith('#'):
|
||||
continue
|
||||
|
||||
# Look for indentation changes
|
||||
if len(context_stack) == 0:
|
||||
indent = len(line) - len(line.lstrip())
|
||||
if indent > indent_stack[-1]:
|
||||
indent_stack.append(indent)
|
||||
yield PyToken(PyToken.INDENT, n_line)
|
||||
while indent < indent_stack[-1]:
|
||||
indent_stack.pop()
|
||||
yield PyToken(PyToken.OUTDENT, n_line)
|
||||
if indent != indent_stack[-1]:
|
||||
raise RuntimeError('Incorrect indentation on line {}'.format(n_line))
|
||||
|
||||
while True:
|
||||
line = line.lstrip()
|
||||
if not line:
|
||||
break
|
||||
if line[0] == '#':
|
||||
# The rest of this line is a comment
|
||||
break
|
||||
|
||||
token = symbolic_token(line, n_line)
|
||||
if token:
|
||||
if token.type in {'(', '{', '['}:
|
||||
context_stack.append(token.type)
|
||||
elif token.type == ')':
|
||||
if len(context_stack) == 0 or context_stack[-1] != '(':
|
||||
raise RuntimeError('Mismatched token at {} on line {}'.format(line, n_line))
|
||||
context_stack.pop()
|
||||
elif token.type == '}':
|
||||
if len(context_stack) == 0 or context_stack[-1] != '{':
|
||||
raise RuntimeError('Mismatched token at {} on line {}'.format(line, n_line))
|
||||
context_stack.pop()
|
||||
elif token.type == ']':
|
||||
if len(context_stack) == 0 or context_stack[-1] != '[':
|
||||
raise RuntimeError('Mismatched token at {} on line {}'.format(line, n_line))
|
||||
context_stack.pop()
|
||||
yield token
|
||||
line = line[len(token.type):]
|
||||
continue
|
||||
|
||||
match = RE_FLOAT.match(line)
|
||||
if match:
|
||||
yield FloatToken(match.group(), n_line)
|
||||
line = line[match.end():]
|
||||
continue
|
||||
|
||||
match = RE_INT.match(line)
|
||||
if match:
|
||||
yield IntToken(match.group(), n_line)
|
||||
line = line[match.end():]
|
||||
continue
|
||||
|
||||
token = string_token(line, n_line, pysrc)
|
||||
if token:
|
||||
line = token.rem_line
|
||||
n_line = token.end_line
|
||||
yield token
|
||||
continue
|
||||
|
||||
match = RE_WORD.match(line)
|
||||
if match:
|
||||
yield WordToken(match.group(), n_line)
|
||||
line = line[match.end():]
|
||||
continue
|
||||
|
||||
raise RuntimeError('Error: Unrecognized tokens: "{}" at line {}'.format(line, n_line))
|
||||
|
||||
if len(context_stack) == 0:
|
||||
yield PyToken(PyToken.ENDLINE, n_line)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if '--help' in sys.argv:
|
||||
print('Usage: token_dump <file>.py')
|
||||
sys.exit(0)
|
||||
|
||||
if len(sys.argv) >= 2:
|
||||
pysrc = open(sys.argv[1], 'r')
|
||||
else:
|
||||
pysrc = sys.stdin
|
||||
|
||||
for tok in read_tokens(pysrc):
|
||||
if tok.type in {PyToken.ENDLINE, PyToken.INDENT, PyToken.OUTDENT}:
|
||||
print(tok)
|
||||
else:
|
||||
print(tok, end=' ')
|
||||
|
||||
pysrc.close()
|
Reference in New Issue
Block a user