cslice 0.1.2__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.
- cslice-0.1.2/Cargo.lock +242 -0
- cslice-0.1.2/Cargo.toml +3 -0
- cslice-0.1.2/LICENSE +21 -0
- cslice-0.1.2/PKG-INFO +128 -0
- cslice-0.1.2/README.md +108 -0
- cslice-0.1.2/crates/cslice-core/Cargo.toml +10 -0
- cslice-0.1.2/crates/cslice-core/src/lib.rs +1520 -0
- cslice-0.1.2/crates/cslice-py/Cargo.toml +14 -0
- cslice-0.1.2/crates/cslice-py/src/lib.rs +307 -0
- cslice-0.1.2/pyproject.toml +38 -0
- cslice-0.1.2/python/cslice/__init__.py +33 -0
- cslice-0.1.2/python/cslice/__init__.pyi +95 -0
- cslice-0.1.2/python/cslice/py.typed +0 -0
cslice-0.1.2/Cargo.lock
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "aho-corasick"
|
|
7
|
+
version = "1.1.5"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"memchr",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[[package]]
|
|
15
|
+
name = "cc"
|
|
16
|
+
version = "1.6.0"
|
|
17
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
18
|
+
checksum = "f74872d07caf508b30a21f6836e7d7016a2eaf7d9ff4f48deaa58cd8a0407630"
|
|
19
|
+
dependencies = [
|
|
20
|
+
"find-msvc-tools",
|
|
21
|
+
"shlex",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[[package]]
|
|
25
|
+
name = "cslice-core"
|
|
26
|
+
version = "0.1.0"
|
|
27
|
+
dependencies = [
|
|
28
|
+
"tree-sitter",
|
|
29
|
+
"tree-sitter-c",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[[package]]
|
|
33
|
+
name = "cslice-py"
|
|
34
|
+
version = "0.1.2"
|
|
35
|
+
dependencies = [
|
|
36
|
+
"cslice-core",
|
|
37
|
+
"pyo3",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[[package]]
|
|
41
|
+
name = "find-msvc-tools"
|
|
42
|
+
version = "0.1.14"
|
|
43
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
44
|
+
checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484"
|
|
45
|
+
|
|
46
|
+
[[package]]
|
|
47
|
+
name = "heck"
|
|
48
|
+
version = "0.5.0"
|
|
49
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
50
|
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
51
|
+
|
|
52
|
+
[[package]]
|
|
53
|
+
name = "libc"
|
|
54
|
+
version = "0.2.190"
|
|
55
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
56
|
+
checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78"
|
|
57
|
+
|
|
58
|
+
[[package]]
|
|
59
|
+
name = "memchr"
|
|
60
|
+
version = "2.8.3"
|
|
61
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
62
|
+
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
|
63
|
+
|
|
64
|
+
[[package]]
|
|
65
|
+
name = "once_cell"
|
|
66
|
+
version = "1.21.4"
|
|
67
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
68
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
69
|
+
|
|
70
|
+
[[package]]
|
|
71
|
+
name = "portable-atomic"
|
|
72
|
+
version = "1.15.0"
|
|
73
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
74
|
+
checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
|
|
75
|
+
|
|
76
|
+
[[package]]
|
|
77
|
+
name = "proc-macro2"
|
|
78
|
+
version = "1.0.107"
|
|
79
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
80
|
+
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
|
81
|
+
dependencies = [
|
|
82
|
+
"unicode-ident",
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
[[package]]
|
|
86
|
+
name = "pyo3"
|
|
87
|
+
version = "0.29.3"
|
|
88
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
89
|
+
checksum = "700d18fa267b73b9b521fd7e13580e2f446916f176cacee1ab63fcc8191f1655"
|
|
90
|
+
dependencies = [
|
|
91
|
+
"libc",
|
|
92
|
+
"once_cell",
|
|
93
|
+
"portable-atomic",
|
|
94
|
+
"pyo3-build-config",
|
|
95
|
+
"pyo3-ffi",
|
|
96
|
+
"pyo3-macros",
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
[[package]]
|
|
100
|
+
name = "pyo3-build-config"
|
|
101
|
+
version = "0.29.3"
|
|
102
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
103
|
+
checksum = "7b3fc0c4d08f6bb10e71fe39dfb9e2f59c6eb6854e22ec8092f50c69a4499adb"
|
|
104
|
+
dependencies = [
|
|
105
|
+
"target-lexicon",
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
[[package]]
|
|
109
|
+
name = "pyo3-ffi"
|
|
110
|
+
version = "0.29.3"
|
|
111
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
112
|
+
checksum = "dfc0b8e19df29aad7086cf977bb0c2a2f143e30567eb113e9cf72b62ca698330"
|
|
113
|
+
dependencies = [
|
|
114
|
+
"libc",
|
|
115
|
+
"pyo3-build-config",
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
[[package]]
|
|
119
|
+
name = "pyo3-macros"
|
|
120
|
+
version = "0.29.3"
|
|
121
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
122
|
+
checksum = "6100e8a4b5eba53afaa5ed078364851a0b2499c553a44c31026b929049b49dc6"
|
|
123
|
+
dependencies = [
|
|
124
|
+
"proc-macro2",
|
|
125
|
+
"pyo3-macros-backend",
|
|
126
|
+
"quote",
|
|
127
|
+
"syn",
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
[[package]]
|
|
131
|
+
name = "pyo3-macros-backend"
|
|
132
|
+
version = "0.29.3"
|
|
133
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
134
|
+
checksum = "6143877a16e82b5a727b7127ff4cd86858a24a28d745d72f43e6f227c7b1bdb3"
|
|
135
|
+
dependencies = [
|
|
136
|
+
"heck",
|
|
137
|
+
"proc-macro2",
|
|
138
|
+
"quote",
|
|
139
|
+
"syn",
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
[[package]]
|
|
143
|
+
name = "quote"
|
|
144
|
+
version = "1.0.47"
|
|
145
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
146
|
+
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
|
147
|
+
dependencies = [
|
|
148
|
+
"proc-macro2",
|
|
149
|
+
]
|
|
150
|
+
|
|
151
|
+
[[package]]
|
|
152
|
+
name = "regex"
|
|
153
|
+
version = "1.13.1"
|
|
154
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
155
|
+
checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d"
|
|
156
|
+
dependencies = [
|
|
157
|
+
"aho-corasick",
|
|
158
|
+
"memchr",
|
|
159
|
+
"regex-automata",
|
|
160
|
+
"regex-syntax",
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
[[package]]
|
|
164
|
+
name = "regex-automata"
|
|
165
|
+
version = "0.4.18"
|
|
166
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
167
|
+
checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2"
|
|
168
|
+
dependencies = [
|
|
169
|
+
"aho-corasick",
|
|
170
|
+
"memchr",
|
|
171
|
+
"regex-syntax",
|
|
172
|
+
]
|
|
173
|
+
|
|
174
|
+
[[package]]
|
|
175
|
+
name = "regex-syntax"
|
|
176
|
+
version = "0.8.11"
|
|
177
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
178
|
+
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
|
179
|
+
|
|
180
|
+
[[package]]
|
|
181
|
+
name = "shlex"
|
|
182
|
+
version = "2.0.1"
|
|
183
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
184
|
+
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
|
185
|
+
|
|
186
|
+
[[package]]
|
|
187
|
+
name = "streaming-iterator"
|
|
188
|
+
version = "0.1.9"
|
|
189
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
190
|
+
checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520"
|
|
191
|
+
|
|
192
|
+
[[package]]
|
|
193
|
+
name = "syn"
|
|
194
|
+
version = "2.0.119"
|
|
195
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
196
|
+
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
|
197
|
+
dependencies = [
|
|
198
|
+
"proc-macro2",
|
|
199
|
+
"quote",
|
|
200
|
+
"unicode-ident",
|
|
201
|
+
]
|
|
202
|
+
|
|
203
|
+
[[package]]
|
|
204
|
+
name = "target-lexicon"
|
|
205
|
+
version = "0.13.5"
|
|
206
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
207
|
+
checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|
208
|
+
|
|
209
|
+
[[package]]
|
|
210
|
+
name = "tree-sitter"
|
|
211
|
+
version = "0.24.7"
|
|
212
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
213
|
+
checksum = "a5387dffa7ffc7d2dae12b50c6f7aab8ff79d6210147c6613561fc3d474c6f75"
|
|
214
|
+
dependencies = [
|
|
215
|
+
"cc",
|
|
216
|
+
"regex",
|
|
217
|
+
"regex-syntax",
|
|
218
|
+
"streaming-iterator",
|
|
219
|
+
"tree-sitter-language",
|
|
220
|
+
]
|
|
221
|
+
|
|
222
|
+
[[package]]
|
|
223
|
+
name = "tree-sitter-c"
|
|
224
|
+
version = "0.23.4"
|
|
225
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
226
|
+
checksum = "afd2b1bf1585dc2ef6d69e87d01db8adb059006649dd5f96f31aa789ee6e9c71"
|
|
227
|
+
dependencies = [
|
|
228
|
+
"cc",
|
|
229
|
+
"tree-sitter-language",
|
|
230
|
+
]
|
|
231
|
+
|
|
232
|
+
[[package]]
|
|
233
|
+
name = "tree-sitter-language"
|
|
234
|
+
version = "0.1.8"
|
|
235
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
236
|
+
checksum = "ca0d1bf6fdd806e43ae5198f82f527056d359def39e54e67a0f478ac09dac081"
|
|
237
|
+
|
|
238
|
+
[[package]]
|
|
239
|
+
name = "unicode-ident"
|
|
240
|
+
version = "1.0.26"
|
|
241
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
242
|
+
checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954"
|
cslice-0.1.2/Cargo.toml
ADDED
cslice-0.1.2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alfred
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
cslice-0.1.2/PKG-INFO
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cslice
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Classifier: Development Status :: 4 - Beta
|
|
5
|
+
Classifier: Intended Audience :: Developers
|
|
6
|
+
Classifier: Programming Language :: C
|
|
7
|
+
Classifier: Programming Language :: Rust
|
|
8
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
9
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Summary: AST-based logical-block slicing for C functions (computation/branch/loop/case/preproc), powered by tree-sitter
|
|
12
|
+
Keywords: c,ast,tree-sitter,parser,slicing,requirements
|
|
13
|
+
Author: Alfred
|
|
14
|
+
License-Expression: MIT
|
|
15
|
+
Requires-Python: >=3.8
|
|
16
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
17
|
+
Project-URL: Issues, https://github.com/alfred-yu/cslice/issues
|
|
18
|
+
Project-URL: Repository, https://github.com/alfred-yu/cslice
|
|
19
|
+
|
|
20
|
+
# cslice — AST-based logical-block slicing for C functions
|
|
21
|
+
|
|
22
|
+
`cslice` parses C source code with [tree-sitter](https://tree-sitter.github.io/) and
|
|
23
|
+
splits each function body into **logical blocks** — the atomic, individually
|
|
24
|
+
describable pieces of behavior a function is made of. Each slice carries its line
|
|
25
|
+
range, block kind, extracted code text, and a semantic summary (conditions,
|
|
26
|
+
loop control, assignment/call/return behaviors) ready for downstream analysis:
|
|
27
|
+
reverse-engineered requirements (DO-178C style), code review checklists,
|
|
28
|
+
coverage mapping, or documentation.
|
|
29
|
+
|
|
30
|
+
The heavy lifting is a pure-Rust core compiled to a native Python extension
|
|
31
|
+
(PyO3) — no Python-side parsing, no external tools.
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install cslice # once published
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Build from source (requires Rust toolchain):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install maturin
|
|
43
|
+
maturin develop # inside a virtualenv, from the project root
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quick start
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import cslice
|
|
50
|
+
|
|
51
|
+
source = open("driver.c").read()
|
|
52
|
+
|
|
53
|
+
# 1) One call: plan every function in the file
|
|
54
|
+
for plan in cslice.slice_all(source):
|
|
55
|
+
print(plan.function.name, plan.function.signature)
|
|
56
|
+
for item in plan.items:
|
|
57
|
+
print(f" L{item.start_line}-L{item.end_line} [{item.kind}]")
|
|
58
|
+
print(f" {item.code_text!r}")
|
|
59
|
+
|
|
60
|
+
# 2) Or work function by function
|
|
61
|
+
funcs = cslice.parse_functions(source)
|
|
62
|
+
items = cslice.plan_function_slices(source, funcs[0].start_line, funcs[0].end_line)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Example output for a branch inside a loop:
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
Crc32 L1-L21 [static uint32_t Crc32(...)]
|
|
69
|
+
L3-L3 [computation] crc = 0xFFFFFFFFu;
|
|
70
|
+
L5-L5 [loop] for (i = 0u; i < len; i++)
|
|
71
|
+
L7-L7 [computation] crc ^= data[i];
|
|
72
|
+
L9-L9 [loop] for (k = 0; k < 8; k++)
|
|
73
|
+
L11-L14 [branch] if ((crc & 1u) != 0u) ...
|
|
74
|
+
L15-L18 [branch] else ...
|
|
75
|
+
L21-L21 [computation] return ~crc;
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## API
|
|
79
|
+
|
|
80
|
+
| Function | Description |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `parse_functions(source) -> list[FunctionDef]` | All function definitions in order (name, signature, 1-based line range). Fault-tolerant on syntax errors. |
|
|
83
|
+
| `plan_function_slices(source, start_line, end_line) -> list[SlicePlanItem] \| None` | Slice plan for the function whose range exactly matches; `None` if no match. |
|
|
84
|
+
| `slice_all(source) -> list[FunctionPlan]` | Convenience: plan every parsed function. |
|
|
85
|
+
| `extract_lines(source, start_line, end_line) -> str` | 1-based inclusive line snapshot (strips `\r`, no trailing newline). Raises `ValueError` out of range. |
|
|
86
|
+
|
|
87
|
+
Slice kinds (`cslice.KINDS`):
|
|
88
|
+
|
|
89
|
+
| kind | covers |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `computation` | Runs of simple statements (assign / call / return), initialized declarations |
|
|
92
|
+
| `branch` | One `if` / `else-if` / `else` arm each |
|
|
93
|
+
| `loop` | The loop **header only** — iteration control is its own behavior |
|
|
94
|
+
| `case` | One `switch` case / default each (switch head folds into the first case) |
|
|
95
|
+
| `preproc` | A conditional-compilation block as a whole |
|
|
96
|
+
|
|
97
|
+
`SlicePlanItem.summary` (a `BlockSummary`) carries the extracted facts:
|
|
98
|
+
`condition`, `is_else`, `case_value`, `loop_header`, `loop_init/cond/update`,
|
|
99
|
+
`preproc_directive`, `parent_loop_cond` (nested-slice context), and `behaviors` —
|
|
100
|
+
an ordered list of `Behavior` facts (`init`, `assign`, `compound_assign`,
|
|
101
|
+
`return`, `call`, `break`, `continue`).
|
|
102
|
+
|
|
103
|
+
## Slicing rules
|
|
104
|
+
|
|
105
|
+
- **Exact behavior boundaries**: signature lines, braces, comments and bare
|
|
106
|
+
declarations belong to no slice; a top-level `return` is always its own slice
|
|
107
|
+
(data preparation vs. observable result).
|
|
108
|
+
- **DO-178C-style atomicity**: nested control flow inside a loop body is split
|
|
109
|
+
recursively — loop header, nested branches/loops/switches and the statements
|
|
110
|
+
between them each get their own slice. Nested slices carry the parent loop
|
|
111
|
+
condition in `summary.parent_loop_cond`.
|
|
112
|
+
- Initialized declarations are standalone slices; bare declarations are skipped
|
|
113
|
+
(nothing to describe).
|
|
114
|
+
- Empty bodies and unparseable functions degrade to a single fallback slice.
|
|
115
|
+
|
|
116
|
+
## 中文说明
|
|
117
|
+
|
|
118
|
+
`cslice` 基于 tree-sitter 把 C 函数体切分为**逻辑块**(计算 / 分支 / 循环 /
|
|
119
|
+
case / 条件编译五类),每个切片带行范围、代码文本与语义摘要(条件表达式、
|
|
120
|
+
循环三段式、赋值/调用/返回等行为清单)。切片遵循"精确行为边界"与
|
|
121
|
+
"原子性"原则:签名行、大括号、注释、纯声明不归属任何片;顶层 return
|
|
122
|
+
独立成片;循环体内嵌套控制流递归拆分并携带父循环条件。适用于逆向需求
|
|
123
|
+
草稿生成(DO-178C 低层需求)、代码审查清单、覆盖映射等场景。
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
MIT
|
|
128
|
+
|
cslice-0.1.2/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# cslice — AST-based logical-block slicing for C functions
|
|
2
|
+
|
|
3
|
+
`cslice` parses C source code with [tree-sitter](https://tree-sitter.github.io/) and
|
|
4
|
+
splits each function body into **logical blocks** — the atomic, individually
|
|
5
|
+
describable pieces of behavior a function is made of. Each slice carries its line
|
|
6
|
+
range, block kind, extracted code text, and a semantic summary (conditions,
|
|
7
|
+
loop control, assignment/call/return behaviors) ready for downstream analysis:
|
|
8
|
+
reverse-engineered requirements (DO-178C style), code review checklists,
|
|
9
|
+
coverage mapping, or documentation.
|
|
10
|
+
|
|
11
|
+
The heavy lifting is a pure-Rust core compiled to a native Python extension
|
|
12
|
+
(PyO3) — no Python-side parsing, no external tools.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install cslice # once published
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Build from source (requires Rust toolchain):
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install maturin
|
|
24
|
+
maturin develop # inside a virtualenv, from the project root
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
import cslice
|
|
31
|
+
|
|
32
|
+
source = open("driver.c").read()
|
|
33
|
+
|
|
34
|
+
# 1) One call: plan every function in the file
|
|
35
|
+
for plan in cslice.slice_all(source):
|
|
36
|
+
print(plan.function.name, plan.function.signature)
|
|
37
|
+
for item in plan.items:
|
|
38
|
+
print(f" L{item.start_line}-L{item.end_line} [{item.kind}]")
|
|
39
|
+
print(f" {item.code_text!r}")
|
|
40
|
+
|
|
41
|
+
# 2) Or work function by function
|
|
42
|
+
funcs = cslice.parse_functions(source)
|
|
43
|
+
items = cslice.plan_function_slices(source, funcs[0].start_line, funcs[0].end_line)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Example output for a branch inside a loop:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
Crc32 L1-L21 [static uint32_t Crc32(...)]
|
|
50
|
+
L3-L3 [computation] crc = 0xFFFFFFFFu;
|
|
51
|
+
L5-L5 [loop] for (i = 0u; i < len; i++)
|
|
52
|
+
L7-L7 [computation] crc ^= data[i];
|
|
53
|
+
L9-L9 [loop] for (k = 0; k < 8; k++)
|
|
54
|
+
L11-L14 [branch] if ((crc & 1u) != 0u) ...
|
|
55
|
+
L15-L18 [branch] else ...
|
|
56
|
+
L21-L21 [computation] return ~crc;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## API
|
|
60
|
+
|
|
61
|
+
| Function | Description |
|
|
62
|
+
|---|---|
|
|
63
|
+
| `parse_functions(source) -> list[FunctionDef]` | All function definitions in order (name, signature, 1-based line range). Fault-tolerant on syntax errors. |
|
|
64
|
+
| `plan_function_slices(source, start_line, end_line) -> list[SlicePlanItem] \| None` | Slice plan for the function whose range exactly matches; `None` if no match. |
|
|
65
|
+
| `slice_all(source) -> list[FunctionPlan]` | Convenience: plan every parsed function. |
|
|
66
|
+
| `extract_lines(source, start_line, end_line) -> str` | 1-based inclusive line snapshot (strips `\r`, no trailing newline). Raises `ValueError` out of range. |
|
|
67
|
+
|
|
68
|
+
Slice kinds (`cslice.KINDS`):
|
|
69
|
+
|
|
70
|
+
| kind | covers |
|
|
71
|
+
|---|---|
|
|
72
|
+
| `computation` | Runs of simple statements (assign / call / return), initialized declarations |
|
|
73
|
+
| `branch` | One `if` / `else-if` / `else` arm each |
|
|
74
|
+
| `loop` | The loop **header only** — iteration control is its own behavior |
|
|
75
|
+
| `case` | One `switch` case / default each (switch head folds into the first case) |
|
|
76
|
+
| `preproc` | A conditional-compilation block as a whole |
|
|
77
|
+
|
|
78
|
+
`SlicePlanItem.summary` (a `BlockSummary`) carries the extracted facts:
|
|
79
|
+
`condition`, `is_else`, `case_value`, `loop_header`, `loop_init/cond/update`,
|
|
80
|
+
`preproc_directive`, `parent_loop_cond` (nested-slice context), and `behaviors` —
|
|
81
|
+
an ordered list of `Behavior` facts (`init`, `assign`, `compound_assign`,
|
|
82
|
+
`return`, `call`, `break`, `continue`).
|
|
83
|
+
|
|
84
|
+
## Slicing rules
|
|
85
|
+
|
|
86
|
+
- **Exact behavior boundaries**: signature lines, braces, comments and bare
|
|
87
|
+
declarations belong to no slice; a top-level `return` is always its own slice
|
|
88
|
+
(data preparation vs. observable result).
|
|
89
|
+
- **DO-178C-style atomicity**: nested control flow inside a loop body is split
|
|
90
|
+
recursively — loop header, nested branches/loops/switches and the statements
|
|
91
|
+
between them each get their own slice. Nested slices carry the parent loop
|
|
92
|
+
condition in `summary.parent_loop_cond`.
|
|
93
|
+
- Initialized declarations are standalone slices; bare declarations are skipped
|
|
94
|
+
(nothing to describe).
|
|
95
|
+
- Empty bodies and unparseable functions degrade to a single fallback slice.
|
|
96
|
+
|
|
97
|
+
## 中文说明
|
|
98
|
+
|
|
99
|
+
`cslice` 基于 tree-sitter 把 C 函数体切分为**逻辑块**(计算 / 分支 / 循环 /
|
|
100
|
+
case / 条件编译五类),每个切片带行范围、代码文本与语义摘要(条件表达式、
|
|
101
|
+
循环三段式、赋值/调用/返回等行为清单)。切片遵循"精确行为边界"与
|
|
102
|
+
"原子性"原则:签名行、大括号、注释、纯声明不归属任何片;顶层 return
|
|
103
|
+
独立成片;循环体内嵌套控制流递归拆分并携带父循环条件。适用于逆向需求
|
|
104
|
+
草稿生成(DO-178C 低层需求)、代码审查清单、覆盖映射等场景。
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
MIT
|