pycparser 3.1__tar.gz → 3.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pycparser-3.1/pycparser.egg-info → pycparser-3.11}/PKG-INFO +1 -1
- {pycparser-3.1 → pycparser-3.11}/pycparser/__init__.py +1 -1
- {pycparser-3.1 → pycparser-3.11}/pycparser/_c_ast.cfg +17 -0
- {pycparser-3.1 → pycparser-3.11}/pycparser/ast_transforms.py +20 -14
- {pycparser-3.1 → pycparser-3.11}/pycparser/c_ast.py +49 -0
- {pycparser-3.1 → pycparser-3.11}/pycparser/c_generator.py +50 -15
- {pycparser-3.1 → pycparser-3.11}/pycparser/c_lexer.py +42 -37
- {pycparser-3.1 → pycparser-3.11}/pycparser/c_parser.py +124 -45
- {pycparser-3.1 → pycparser-3.11/pycparser.egg-info}/PKG-INFO +1 -1
- {pycparser-3.1 → pycparser-3.11}/pycparser.egg-info/SOURCES.txt +1 -0
- {pycparser-3.1 → pycparser-3.11}/pyproject.toml +1 -1
- {pycparser-3.1 → pycparser-3.11}/tests/c_files/c11.c +31 -2
- {pycparser-3.1 → pycparser-3.11}/tests/test_c_generator.py +242 -4
- {pycparser-3.1 → pycparser-3.11}/tests/test_c_lexer.py +47 -0
- {pycparser-3.1 → pycparser-3.11}/tests/test_c_parser.py +454 -9
- {pycparser-3.1 → pycparser-3.11}/tests/test_general.py +9 -1
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/_fake_defines.h +2 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/_fake_typedefs.h +10 -0
- pycparser-3.11/utils/fake_libc_include/xcb/xcb.h +2 -0
- {pycparser-3.1 → pycparser-3.11}/LICENSE +0 -0
- {pycparser-3.1 → pycparser-3.11}/MANIFEST.in +0 -0
- {pycparser-3.1 → pycparser-3.11}/README.rst +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/c-to-c.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/c_files/basic.c +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/c_files/funky.c +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/c_files/hash.c +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/c_files/memmgr.c +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/c_files/memmgr.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/c_files/pragmas.c +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/c_files/year.c +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/c_json.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/cdecl.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/construct_ast_from_scratch.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/dump_ast.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/explore_ast.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/func_calls.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/func_defs.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/func_defs_add_param.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/rewrite_ast.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/serialize_ast.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/typed_usage.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/using_cpp_libc.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/examples/using_gcc_E_libc.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/pycparser/_ast_gen.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/pycparser.egg-info/dependency_links.txt +0 -0
- {pycparser-3.1 → pycparser-3.11}/pycparser.egg-info/top_level.txt +0 -0
- {pycparser-3.1 → pycparser-3.11}/setup.cfg +0 -0
- {pycparser-3.1 → pycparser-3.11}/setup.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/tests/__init__.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/tests/c_files/cppd_with_stdio_h.c +0 -0
- {pycparser-3.1 → pycparser-3.11}/tests/c_files/empty.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/tests/c_files/example_c_file.c +0 -0
- {pycparser-3.1 → pycparser-3.11}/tests/c_files/hdir/9/inc.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/tests/c_files/memmgr.c +0 -0
- {pycparser-3.1 → pycparser-3.11}/tests/c_files/memmgr.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/tests/c_files/memmgr_with_h.c +0 -0
- {pycparser-3.1 → pycparser-3.11}/tests/c_files/simplemain.c +0 -0
- {pycparser-3.1 → pycparser-3.11}/tests/c_files/year.c +0 -0
- {pycparser-3.1 → pycparser-3.11}/tests/test_c_ast.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/tests/test_examples.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/tests/test_util.py +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/X11/Intrinsic.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/X11/Xlib.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/X11/_X11_fake_defines.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/X11/_X11_fake_typedefs.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/_ansi.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/_syslist.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/aio.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/alloca.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/ar.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/argz.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/arpa/inet.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/asm-generic/int-ll64.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/assert.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/complex.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/cpio.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/ctype.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/dirent.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/dlfcn.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/emmintrin.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/endian.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/envz.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/errno.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/fastmath.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/fcntl.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/features.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/fenv.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/float.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/fmtmsg.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/fnmatch.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/ftw.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/getopt.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/glob.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/grp.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/iconv.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/ieeefp.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/immintrin.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/inttypes.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/iso646.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/langinfo.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/libgen.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/libintl.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/limits.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/linux/socket.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/linux/version.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/locale.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/malloc.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/math.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/mir_toolkit/client_types.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/monetary.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/mqueue.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/ndbm.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/net/if.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/netdb.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/netinet/in.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/netinet/tcp.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/newlib.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/nl_types.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/openssl/err.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/openssl/evp.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/openssl/hmac.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/openssl/ssl.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/openssl/x509v3.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/paths.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/poll.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/process.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/pthread.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/pwd.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/reent.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/regdef.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/regex.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sched.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/search.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/semaphore.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/setjmp.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/signal.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/smmintrin.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/spawn.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/stdalign.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/stdarg.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/stdatomic.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/stdbool.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/stddef.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/stdint.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/stdio.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/stdlib.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/stdnoreturn.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/string.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/strings.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/stropts.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/ioctl.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/ipc.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/mman.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/msg.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/poll.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/resource.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/select.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/sem.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/shm.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/socket.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/stat.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/statvfs.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/sysctl.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/time.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/times.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/types.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/uio.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/un.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/utsname.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/sys/wait.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/syslog.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/tar.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/termios.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/tgmath.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/threads.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/time.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/trace.h +0 -0
- /pycparser-3.1/utils/fake_libc_include/ulimit.h → /pycparser-3.11/utils/fake_libc_include/uchar.h +0 -0
- /pycparser-3.1/utils/fake_libc_include/unctrl.h → /pycparser-3.11/utils/fake_libc_include/ulimit.h +0 -0
- /pycparser-3.1/utils/fake_libc_include/unistd.h → /pycparser-3.11/utils/fake_libc_include/unctrl.h +0 -0
- /pycparser-3.1/utils/fake_libc_include/utime.h → /pycparser-3.11/utils/fake_libc_include/unistd.h +0 -0
- /pycparser-3.1/utils/fake_libc_include/utmp.h → /pycparser-3.11/utils/fake_libc_include/utime.h +0 -0
- /pycparser-3.1/utils/fake_libc_include/utmpx.h → /pycparser-3.11/utils/fake_libc_include/utmp.h +0 -0
- /pycparser-3.1/utils/fake_libc_include/wchar.h → /pycparser-3.11/utils/fake_libc_include/utmpx.h +0 -0
- /pycparser-3.1/utils/fake_libc_include/wctype.h → /pycparser-3.11/utils/fake_libc_include/wchar.h +0 -0
- /pycparser-3.1/utils/fake_libc_include/wordexp.h → /pycparser-3.11/utils/fake_libc_include/wctype.h +0 -0
- /pycparser-3.1/utils/fake_libc_include/xcb/xcb.h → /pycparser-3.11/utils/fake_libc_include/wordexp.h +0 -0
- {pycparser-3.1 → pycparser-3.11}/utils/fake_libc_include/zlib.h +0 -0
|
@@ -50,6 +50,8 @@ Compound: [block_items**]
|
|
|
50
50
|
CompoundLiteral: [type*, init*]
|
|
51
51
|
|
|
52
52
|
# type: int, char, float, string, etc.
|
|
53
|
+
# value: source spelling. A string may retain adjacent quoted fragments to
|
|
54
|
+
# preserve escape boundaries, e.g. "\x1" "a".
|
|
53
55
|
#
|
|
54
56
|
Constant: [type, value]
|
|
55
57
|
|
|
@@ -125,6 +127,18 @@ FuncDecl: [args*, type*]
|
|
|
125
127
|
#
|
|
126
128
|
FuncDef: [decl*, param_decls**, body*]
|
|
127
129
|
|
|
130
|
+
# One association in a C11 generic selection.
|
|
131
|
+
# type: Typename, or None for the default association
|
|
132
|
+
# expr: the result expression for this association
|
|
133
|
+
#
|
|
134
|
+
GenericAssociation: [type*, expr*]
|
|
135
|
+
|
|
136
|
+
# A C11 _Generic expression. All associations are preserved in source order.
|
|
137
|
+
# expr: the controlling expression (not evaluated by C)
|
|
138
|
+
# associations: a nonempty sequence of GenericAssociation nodes
|
|
139
|
+
#
|
|
140
|
+
GenericSelection: [expr*, associations**]
|
|
141
|
+
|
|
128
142
|
Goto: [name]
|
|
129
143
|
|
|
130
144
|
ID: [name]
|
|
@@ -156,6 +170,9 @@ PtrDecl: [quals, type*]
|
|
|
156
170
|
|
|
157
171
|
Return: [expr*]
|
|
158
172
|
|
|
173
|
+
# A static assertion declaration. The condition is preserved without evaluation.
|
|
174
|
+
# message: a string Constant, or None for the message-less extension
|
|
175
|
+
#
|
|
159
176
|
StaticAssert: [cond*, message*]
|
|
160
177
|
|
|
161
178
|
# name: struct tag name
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
# License: BSD
|
|
8
8
|
# ------------------------------------------------------------------------------
|
|
9
9
|
|
|
10
|
+
from copy import deepcopy
|
|
10
11
|
from typing import Any, cast
|
|
11
12
|
|
|
12
13
|
from . import c_ast
|
|
@@ -111,8 +112,8 @@ def _extract_nested_case(
|
|
|
111
112
|
|
|
112
113
|
|
|
113
114
|
def fix_atomic_specifiers(
|
|
114
|
-
decl: c_ast.Decl | c_ast.Typedef,
|
|
115
|
-
) -> c_ast.Decl | c_ast.Typedef:
|
|
115
|
+
decl: c_ast.Decl | c_ast.Typedef | c_ast.Typename,
|
|
116
|
+
) -> c_ast.Decl | c_ast.Typedef | c_ast.Typename:
|
|
116
117
|
"""Atomic specifiers like _Atomic(type) are unusually structured,
|
|
117
118
|
conferring a qualifier upon the contained type.
|
|
118
119
|
|
|
@@ -127,17 +128,16 @@ def fix_atomic_specifiers(
|
|
|
127
128
|
if not found:
|
|
128
129
|
break
|
|
129
130
|
|
|
130
|
-
#
|
|
131
|
-
#
|
|
132
|
-
#
|
|
131
|
+
# Match the declaration's qualifiers to the innermost TypeDecl, as for
|
|
132
|
+
# ordinary declarations. Qualifiers moved onto pointers belong only on
|
|
133
|
+
# those PtrDecl nodes. Also restore the name lost with the wrapper TypeDecl.
|
|
133
134
|
typ: Any = decl
|
|
134
135
|
while not isinstance(typ, c_ast.TypeDecl):
|
|
135
136
|
try:
|
|
136
137
|
typ = typ.type
|
|
137
138
|
except AttributeError:
|
|
138
139
|
return decl
|
|
139
|
-
|
|
140
|
-
decl.quals.append("_Atomic")
|
|
140
|
+
decl.quals = typ.quals[:]
|
|
141
141
|
if typ.declname is None:
|
|
142
142
|
typ.declname = decl.name
|
|
143
143
|
|
|
@@ -145,8 +145,8 @@ def fix_atomic_specifiers(
|
|
|
145
145
|
|
|
146
146
|
|
|
147
147
|
def _fix_atomic_specifiers_once(
|
|
148
|
-
decl: c_ast.Decl | c_ast.Typedef,
|
|
149
|
-
) -> tuple[c_ast.Decl | c_ast.Typedef, bool]:
|
|
148
|
+
decl: c_ast.Decl | c_ast.Typedef | c_ast.Typename,
|
|
149
|
+
) -> tuple[c_ast.Decl | c_ast.Typedef | c_ast.Typename, bool]:
|
|
150
150
|
"""Performs one 'fix' round of atomic specifiers.
|
|
151
151
|
Returns (modified_decl, found) where found is True iff a fix was made.
|
|
152
152
|
"""
|
|
@@ -168,11 +168,17 @@ def _fix_atomic_specifiers_once(
|
|
|
168
168
|
|
|
169
169
|
assert isinstance(parent, c_ast.TypeDecl)
|
|
170
170
|
assert grandparent is not None
|
|
171
|
-
|
|
171
|
+
# Declaration specifiers are shared by comma-separated declarators. Copy
|
|
172
|
+
# the contained type before attaching qualifiers, coordinates, and a name.
|
|
173
|
+
typ = deepcopy(node.type)
|
|
174
|
+
if typ.coord is None:
|
|
172
175
|
# Preserve the declarator coord for _Atomic(T) so TypeDecl doesn't lose
|
|
173
176
|
# its location when we replace the wrapper Typename.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
177
|
+
typ.coord = parent.coord
|
|
178
|
+
# Qualifiers outside _Atomic(T) apply to T itself. In particular, const in
|
|
179
|
+
# const _Atomic(int *) qualifies the pointer, not the pointed-to int.
|
|
180
|
+
typ.quals = parent.quals + typ.quals
|
|
181
|
+
if "_Atomic" not in typ.quals:
|
|
182
|
+
typ.quals.append("_Atomic")
|
|
183
|
+
cast(Any, grandparent).type = typ
|
|
178
184
|
return decl, True
|
|
@@ -831,6 +831,55 @@ class FuncDef(Node):
|
|
|
831
831
|
attr_names = ()
|
|
832
832
|
|
|
833
833
|
|
|
834
|
+
class GenericAssociation(Node):
|
|
835
|
+
__slots__ = ("type", "expr", "coord", "__weakref__")
|
|
836
|
+
|
|
837
|
+
def __init__(self, type, expr, coord=None):
|
|
838
|
+
self.type = type
|
|
839
|
+
self.expr = expr
|
|
840
|
+
self.coord = coord
|
|
841
|
+
|
|
842
|
+
def children(self):
|
|
843
|
+
nodelist = []
|
|
844
|
+
if self.type is not None:
|
|
845
|
+
nodelist.append(("type", self.type))
|
|
846
|
+
if self.expr is not None:
|
|
847
|
+
nodelist.append(("expr", self.expr))
|
|
848
|
+
return tuple(nodelist)
|
|
849
|
+
|
|
850
|
+
def __iter__(self):
|
|
851
|
+
if self.type is not None:
|
|
852
|
+
yield self.type
|
|
853
|
+
if self.expr is not None:
|
|
854
|
+
yield self.expr
|
|
855
|
+
|
|
856
|
+
attr_names = ()
|
|
857
|
+
|
|
858
|
+
|
|
859
|
+
class GenericSelection(Node):
|
|
860
|
+
__slots__ = ("expr", "associations", "coord", "__weakref__")
|
|
861
|
+
|
|
862
|
+
def __init__(self, expr, associations, coord=None):
|
|
863
|
+
self.expr = expr
|
|
864
|
+
self.associations = associations
|
|
865
|
+
self.coord = coord
|
|
866
|
+
|
|
867
|
+
def children(self):
|
|
868
|
+
nodelist = []
|
|
869
|
+
if self.expr is not None:
|
|
870
|
+
nodelist.append(("expr", self.expr))
|
|
871
|
+
for i, child in enumerate(self.associations or []):
|
|
872
|
+
nodelist.append((f"associations[{i}]", child))
|
|
873
|
+
return tuple(nodelist)
|
|
874
|
+
|
|
875
|
+
def __iter__(self):
|
|
876
|
+
if self.expr is not None:
|
|
877
|
+
yield self.expr
|
|
878
|
+
yield from self.associations or []
|
|
879
|
+
|
|
880
|
+
attr_names = ()
|
|
881
|
+
|
|
882
|
+
|
|
834
883
|
class Goto(Node):
|
|
835
884
|
__slots__ = ("name", "coord", "__weakref__")
|
|
836
885
|
|
|
@@ -70,6 +70,17 @@ class CGenerator:
|
|
|
70
70
|
args = self.visit(n.args) if n.args is not None else ""
|
|
71
71
|
return fref + "(" + args + ")"
|
|
72
72
|
|
|
73
|
+
def visit_GenericSelection(self, n: c_ast.GenericSelection) -> str:
|
|
74
|
+
# The controlling and association expressions are assignment-expressions:
|
|
75
|
+
# preserve parentheses around comma expressions with _visit_expr.
|
|
76
|
+
expr = self._visit_expr(n.expr)
|
|
77
|
+
associations = ", ".join(self.visit(a) for a in n.associations)
|
|
78
|
+
return f"_Generic({expr}, {associations})"
|
|
79
|
+
|
|
80
|
+
def visit_GenericAssociation(self, n: c_ast.GenericAssociation) -> str:
|
|
81
|
+
typ = self.visit(n.type) if n.type is not None else "default"
|
|
82
|
+
return f"{typ}: {self._visit_expr(n.expr)}"
|
|
83
|
+
|
|
73
84
|
def visit_UnaryOp(self, n: c_ast.UnaryOp) -> str:
|
|
74
85
|
match n.op:
|
|
75
86
|
case "sizeof":
|
|
@@ -170,10 +181,13 @@ class CGenerator:
|
|
|
170
181
|
return self.visit(n)
|
|
171
182
|
|
|
172
183
|
def visit_Decl(self, n: c_ast.Decl, no_type: bool = False) -> str:
|
|
173
|
-
#
|
|
174
|
-
#
|
|
175
|
-
|
|
176
|
-
|
|
184
|
+
# Later declarations in a DeclList omit the shared specifiers, but
|
|
185
|
+
# still need their own pointer, array, and function declarator parts.
|
|
186
|
+
s = (
|
|
187
|
+
self._generate_type(n.type, emit_base_type=False)
|
|
188
|
+
if no_type
|
|
189
|
+
else self._generate_decl(n)
|
|
190
|
+
)
|
|
177
191
|
if n.bitsize:
|
|
178
192
|
s += " : " + self.visit(n.bitsize)
|
|
179
193
|
if n.init:
|
|
@@ -327,7 +341,7 @@ class CGenerator:
|
|
|
327
341
|
s = "_Static_assert("
|
|
328
342
|
s += self.visit(n.cond)
|
|
329
343
|
if n.message:
|
|
330
|
-
s += ","
|
|
344
|
+
s += ", "
|
|
331
345
|
s += self.visit(n.message)
|
|
332
346
|
s += ")"
|
|
333
347
|
return s
|
|
@@ -451,10 +465,11 @@ class CGenerator:
|
|
|
451
465
|
| c_ast.Typedef()
|
|
452
466
|
| c_ast.ExprList()
|
|
453
467
|
| c_ast.CompoundLiteral()
|
|
468
|
+
| c_ast.GenericSelection()
|
|
469
|
+
| c_ast.StaticAssert()
|
|
454
470
|
):
|
|
455
|
-
# These
|
|
456
|
-
#
|
|
457
|
-
#
|
|
471
|
+
# These visitors leave the semicolon to the enclosing context,
|
|
472
|
+
# so they can also be used in expressions or for clauses.
|
|
458
473
|
return indent + self.visit(n) + ";\n"
|
|
459
474
|
case c_ast.Compound():
|
|
460
475
|
# No extra indentation required before the opening brace of a
|
|
@@ -475,7 +490,7 @@ class CGenerator:
|
|
|
475
490
|
if n.storage:
|
|
476
491
|
s += " ".join(n.storage) + " "
|
|
477
492
|
if n.align:
|
|
478
|
-
s += self.visit(n.align
|
|
493
|
+
s += " ".join(self.visit(align) for align in n.align) + " "
|
|
479
494
|
s += self._generate_type(n.type)
|
|
480
495
|
return s
|
|
481
496
|
|
|
@@ -484,11 +499,14 @@ class CGenerator:
|
|
|
484
499
|
n: c_ast.Node,
|
|
485
500
|
modifiers: list[c_ast.Node] | None = None,
|
|
486
501
|
emit_declname: bool = True,
|
|
502
|
+
emit_base_type: bool = True,
|
|
487
503
|
) -> str:
|
|
488
504
|
"""Recursive generation from a type node. n is the type node.
|
|
489
505
|
modifiers collects the PtrDecl, ArrayDecl and FuncDecl modifiers
|
|
490
506
|
encountered on the way down to a TypeDecl, to allow proper
|
|
491
507
|
generation from it.
|
|
508
|
+
emit_base_type controls whether the shared type specifier and its
|
|
509
|
+
qualifiers are emitted, independently of the declarator parts.
|
|
492
510
|
"""
|
|
493
511
|
if modifiers is None:
|
|
494
512
|
modifiers = []
|
|
@@ -497,9 +515,10 @@ class CGenerator:
|
|
|
497
515
|
match n:
|
|
498
516
|
case c_ast.TypeDecl():
|
|
499
517
|
s = ""
|
|
500
|
-
if
|
|
501
|
-
|
|
502
|
-
|
|
518
|
+
if emit_base_type:
|
|
519
|
+
if n.quals:
|
|
520
|
+
s += " ".join(n.quals) + " "
|
|
521
|
+
s += self.visit(n.type)
|
|
503
522
|
|
|
504
523
|
nstr = n.declname if n.declname and emit_declname else ""
|
|
505
524
|
# Resolve modifiers.
|
|
@@ -533,18 +552,27 @@ class CGenerator:
|
|
|
533
552
|
nstr = f"* {quals}{suffix}"
|
|
534
553
|
else:
|
|
535
554
|
nstr = "*" + nstr
|
|
555
|
+
if not emit_base_type:
|
|
556
|
+
return nstr
|
|
536
557
|
if nstr:
|
|
537
558
|
s += " " + nstr
|
|
538
559
|
return s
|
|
539
560
|
case c_ast.Decl():
|
|
540
561
|
return self._generate_decl(n.type)
|
|
541
562
|
case c_ast.Typename():
|
|
542
|
-
return self._generate_type(
|
|
563
|
+
return self._generate_type(
|
|
564
|
+
n.type,
|
|
565
|
+
emit_declname=emit_declname,
|
|
566
|
+
emit_base_type=emit_base_type,
|
|
567
|
+
)
|
|
543
568
|
case c_ast.IdentifierType():
|
|
544
569
|
return " ".join(n.names) + " "
|
|
545
570
|
case c_ast.ArrayDecl() | c_ast.PtrDecl() | c_ast.FuncDecl():
|
|
546
571
|
return self._generate_type(
|
|
547
|
-
n.type,
|
|
572
|
+
n.type,
|
|
573
|
+
modifiers + [n],
|
|
574
|
+
emit_declname=emit_declname,
|
|
575
|
+
emit_base_type=emit_base_type,
|
|
548
576
|
)
|
|
549
577
|
case _:
|
|
550
578
|
return self.visit(n)
|
|
@@ -571,5 +599,12 @@ class CGenerator:
|
|
|
571
599
|
"""
|
|
572
600
|
return isinstance(
|
|
573
601
|
n,
|
|
574
|
-
(
|
|
602
|
+
(
|
|
603
|
+
c_ast.Constant,
|
|
604
|
+
c_ast.ID,
|
|
605
|
+
c_ast.ArrayRef,
|
|
606
|
+
c_ast.StructRef,
|
|
607
|
+
c_ast.FuncCall,
|
|
608
|
+
c_ast.GenericSelection,
|
|
609
|
+
),
|
|
575
610
|
)
|
|
@@ -425,6 +425,7 @@ _keywords: tuple[str, ...] = (
|
|
|
425
425
|
"__INT128",
|
|
426
426
|
"_BOOL",
|
|
427
427
|
"_COMPLEX",
|
|
428
|
+
"_GENERIC",
|
|
428
429
|
"_NORETURN",
|
|
429
430
|
"_THREAD_LOCAL",
|
|
430
431
|
"_STATIC_ASSERT",
|
|
@@ -472,51 +473,55 @@ _bad_octal_constant = "0[0-7]*[89]"
|
|
|
472
473
|
_unsupported_c_style_comment = r"\/\*"
|
|
473
474
|
_unsupported_cxx_style_comment = r"\/\/"
|
|
474
475
|
|
|
475
|
-
#
|
|
476
|
-
# Note: a-zA-Z and '.-~^_!=&;,' are allowed as escape chars to support #line
|
|
477
|
-
# directives with Windows paths as filenames (..\..\dir\file)
|
|
478
|
-
# For the same reason, decimal_escape allows all digit sequences. We want to
|
|
479
|
-
# parse all correct code, even if it means to sometimes parse incorrect
|
|
480
|
-
# code.
|
|
476
|
+
# Character constants and escape sequences.
|
|
481
477
|
#
|
|
482
|
-
#
|
|
483
|
-
#
|
|
478
|
+
# Tokens preserve their source spelling; the lexer does not decode escapes or
|
|
479
|
+
# validate Unicode code points. Each complete escape must match as one character
|
|
480
|
+
# in _cconst_char, which is used for both single and multicharacter constants.
|
|
481
|
+
# Matching is deliberately permissive: simple escapes accept extra letters and
|
|
482
|
+
# punctuation, and numeric escapes accept decimal digits, not just octal digits.
|
|
484
483
|
#
|
|
485
|
-
#
|
|
486
|
-
#
|
|
487
|
-
#
|
|
488
|
-
#
|
|
489
|
-
#
|
|
490
|
-
#
|
|
491
|
-
#
|
|
492
|
-
#
|
|
493
|
-
|
|
494
|
-
#
|
|
495
|
-
#
|
|
496
|
-
|
|
497
|
-
#
|
|
498
|
-
#
|
|
499
|
-
#
|
|
500
|
-
#
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
_simple_escape = r"""([a-wyzA-Z._~!=&\^\-\\?'"]|x(?![0-9a-fA-F]))"""
|
|
484
|
+
# _cconst_char is also repeated in the error patterns. If an escape can match in
|
|
485
|
+
# several ways, long malformed constants can cause exponential backtracking
|
|
486
|
+
# (https://github.com/eliben/pycparser/issues/61). The lookaheads prevent this:
|
|
487
|
+
# - Decimal and hexadecimal escapes consume the whole run of digits. For
|
|
488
|
+
# example, \123 cannot be split into \1 followed by the characters 2 and 3.
|
|
489
|
+
# - A simple \x escape is allowed only when no hexadecimal digit follows it.
|
|
490
|
+
# - A complete Unicode escape cannot fall back to a simple \u or \U escape.
|
|
491
|
+
# _bad_escape also excludes all decimal digits to agree with this permissiveness.
|
|
492
|
+
|
|
493
|
+
# Universal character names consume exactly four hex digits after u or eight
|
|
494
|
+
# after U. A following hex digit is a separate character, unlike with \x.
|
|
495
|
+
_unicode_escape = r"(u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})"
|
|
496
|
+
# This lookahead runs immediately after the backslash. If a complete Unicode
|
|
497
|
+
# escape follows, only _unicode_escape may match it: \u00e9 cannot be read as
|
|
498
|
+
# \u followed by 0, 0, e, 9. Incomplete forms retain the permissive behavior
|
|
499
|
+
# of simple escapes.
|
|
500
|
+
_simple_escape = (
|
|
501
|
+
rf"(?!{_unicode_escape})"
|
|
502
|
+
r"""([a-wyzA-Z._~!=&\^\-\\?'"]|x(?![0-9a-fA-F]))"""
|
|
503
|
+
)
|
|
507
504
|
_decimal_escape = r"""(\d+)(?!\d)"""
|
|
508
505
|
_hex_escape = r"""(x[0-9a-fA-F]+)(?![0-9a-fA-F])"""
|
|
509
506
|
_bad_escape = r"""([\\][^a-zA-Z._~^!=&\^\-\\?'"x0-9])"""
|
|
510
507
|
|
|
511
508
|
_escape_sequence = (
|
|
512
|
-
r"""(\\("""
|
|
509
|
+
r"""(\\("""
|
|
510
|
+
+ _simple_escape
|
|
511
|
+
+ "|"
|
|
512
|
+
+ _decimal_escape
|
|
513
|
+
+ "|"
|
|
514
|
+
+ _hex_escape
|
|
515
|
+
+ "|"
|
|
516
|
+
+ _unicode_escape
|
|
517
|
+
+ "))"
|
|
513
518
|
)
|
|
514
519
|
|
|
515
|
-
#
|
|
516
|
-
#
|
|
517
|
-
#
|
|
518
|
-
#
|
|
519
|
-
|
|
520
|
+
# Strings do not need to count the characters represented by escapes. Match
|
|
521
|
+
# just the backslash and a permitted following character; _string_char consumes
|
|
522
|
+
# any remaining numeric or Unicode digits as ordinary text. This avoids matching
|
|
523
|
+
# complete escape sequences repeatedly. The permissive spellings also support
|
|
524
|
+
# Windows paths in #line filenames, which are matched with _string_literal.
|
|
520
525
|
_escape_sequence_start_in_string = r"""(\\[0-9a-zA-Z._~!=&\^\-\\?'"])"""
|
|
521
526
|
|
|
522
527
|
_cconst_char = r"""([^'\\\n]|""" + _escape_sequence + ")"
|
|
@@ -531,7 +536,7 @@ _bad_char_const = (
|
|
|
531
536
|
r"""('""" + _cconst_char + """[^'\n]+')|('')|('""" + _bad_escape + r"""[^'\n]*')"""
|
|
532
537
|
)
|
|
533
538
|
|
|
534
|
-
#
|
|
539
|
+
# String literals, including wide and Unicode prefixes.
|
|
535
540
|
_string_char = r"""([^"\\\n]|""" + _escape_sequence_start_in_string + ")"
|
|
536
541
|
_string_literal = '"' + _string_char + '*"'
|
|
537
542
|
_wstring_literal = "L" + _string_literal
|