freedos-micro-python 0.1.0__py3-none-any.whl
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.
- freedos_micro_python/__init__.py +8 -0
- freedos_micro_python/cli.py +106 -0
- freedos_micro_python/gen_qstrdefs.py +275 -0
- freedos_micro_python/port/arch/bpstruct.h +2 -0
- freedos_micro_python/port/arch/cc.h +4 -0
- freedos_micro_python/port/arch/epstruct.h +1 -0
- freedos_micro_python/port/base64_uc386dos.c +164 -0
- freedos_micro_python/port/file_uc386dos.c +228 -0
- freedos_micro_python/port/lib/axtls/crypto/crypto.h +45 -0
- freedos_micro_python/port/lwip-arch-cc.h +46 -0
- freedos_micro_python/port/lwip_uc386dos.c +248 -0
- freedos_micro_python/port/lwipopts.h +117 -0
- freedos_micro_python/port/math_gamma.c +63 -0
- freedos_micro_python/port/modtime_uc386dos.c +60 -0
- freedos_micro_python/port/modtls_axtls_uc386dos.c +461 -0
- freedos_micro_python/port/mpconfigport.h +358 -0
- freedos_micro_python/port/mphal_uc386dos.c +103 -0
- freedos_micro_python/port/mphalport.h +11 -0
- freedos_micro_python/port/os_uc386dos.c +264 -0
- freedos_micro_python/port/path_uc386dos.c +307 -0
- freedos_micro_python/port/pktdrv_uc386dos.c +650 -0
- freedos_micro_python/port/qstrdefsport.h +2 -0
- freedos_micro_python/port/shutil_uc386dos.c +111 -0
- freedos_micro_python/port/tempfile_uc386dos.c +129 -0
- freedos_micro_python/port/time_real_uc386dos.c +77 -0
- freedos_micro_python/port/uc386_net_uc386dos.c +126 -0
- freedos_micro_python/port/urllib_parse_uc386dos.c +360 -0
- freedos_micro_python/port/urllib_uc386dos.c +29 -0
- freedos_micro_python/scripts/build.sh +641 -0
- freedos_micro_python/scripts/build_port.sh +241 -0
- freedos_micro_python/scripts/fetch.sh +238 -0
- freedos_micro_python-0.1.0.dist-info/METADATA +131 -0
- freedos_micro_python-0.1.0.dist-info/RECORD +37 -0
- freedos_micro_python-0.1.0.dist-info/WHEEL +5 -0
- freedos_micro_python-0.1.0.dist-info/entry_points.txt +2 -0
- freedos_micro_python-0.1.0.dist-info/licenses/LICENSE +25 -0
- freedos_micro_python-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,641 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Per-file triage of the upstream/py/ core sources through uc386.
|
|
3
|
+
#
|
|
4
|
+
# This is NOT a full build (yet) — MicroPython needs a port shim
|
|
5
|
+
# (mp_hal_stdout_tx_*, mp_hal_delay_*, a fixed-region heap for GC,
|
|
6
|
+
# argv plumbing) before it can produce a runnable image. Today this
|
|
7
|
+
# script answers the prerequisite question: how many of the ~50
|
|
8
|
+
# platform-independent .c files in py/ compile cleanly through
|
|
9
|
+
# uc386 → NASM-ready .asm? An error histogram surfaces the top
|
|
10
|
+
# blockers as concrete tickets.
|
|
11
|
+
#
|
|
12
|
+
# Outputs:
|
|
13
|
+
# build/<name>.asm — for every PASS
|
|
14
|
+
# build/<name>.err — uc386 stderr for every FAIL
|
|
15
|
+
# build/triage.txt — per-source PASS/FAIL summary
|
|
16
|
+
# build/errors.txt — first-line error histogram (sorted by count)
|
|
17
|
+
set -eu
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if [ ! -d upstream ]; then
|
|
21
|
+
echo "micropython: run ./fetch.sh first." >&2
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# See build_port.sh header for the dual-invocation contract.
|
|
26
|
+
if [ -z "${UC386_LIB_INCLUDE:-}" ]; then
|
|
27
|
+
REPO="$(cd ../../.. && pwd)"
|
|
28
|
+
UC386_LIB_INCLUDE="$REPO/src/uc386/lib/include"
|
|
29
|
+
fi
|
|
30
|
+
if [ -n "${PYTHON:-}" ]; then
|
|
31
|
+
:
|
|
32
|
+
elif [ -n "${REPO:-}" ] && [ -x "$REPO/.venv/bin/python" ]; then
|
|
33
|
+
PYTHON="$REPO/.venv/bin/python"
|
|
34
|
+
else
|
|
35
|
+
PYTHON="$(command -v python3.12 || command -v python3 || command -v python)"
|
|
36
|
+
fi
|
|
37
|
+
INCLUDE="$UC386_LIB_INCLUDE"
|
|
38
|
+
SRC_DIR="upstream/py"
|
|
39
|
+
PORT_DIR="upstream/ports/minimal" # supplies mpconfigport.h + mphalport.h
|
|
40
|
+
|
|
41
|
+
mkdir -p build build/genhdr
|
|
42
|
+
|
|
43
|
+
# Stub the upstream-generated headers that py/*.c expects. A real
|
|
44
|
+
# build runs upstream/py/makeqstrdefs.py + makemoduledefs.py to
|
|
45
|
+
# emit these from the source tree; for triage we ship empty stubs
|
|
46
|
+
# so the preprocessor finds them and we see compile-class failures
|
|
47
|
+
# (uc386 limitations) instead of a wall of missing-header errors.
|
|
48
|
+
# Patch upstream/extmod/modtime.c so its `#include MICROPY_PY_TIME_INCLUDEFILE`
|
|
49
|
+
# becomes a literal include of our port shim. uc386's preprocessor
|
|
50
|
+
# doesn't support macro-name-in-#include (the GCC/Clang feature
|
|
51
|
+
# where the preprocessor expands the macro and then re-tokenizes).
|
|
52
|
+
# Idempotent: checks for the already-patched literal before
|
|
53
|
+
# re-applying.
|
|
54
|
+
if grep -q '^#include MICROPY_PY_TIME_INCLUDEFILE$' upstream/extmod/modtime.c; then
|
|
55
|
+
# Bare filename — found via build_port.sh's `-I uc386-dos` search path.
|
|
56
|
+
sed -i.bak \
|
|
57
|
+
's|^#include MICROPY_PY_TIME_INCLUDEFILE$|#include "modtime_uc386dos.c"|' \
|
|
58
|
+
upstream/extmod/modtime.c
|
|
59
|
+
rm -f upstream/extmod/modtime.c.bak
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# Patch upstream/ports/minimal/main.c so its stub `mp_import_stat`
|
|
63
|
+
# and `mp_lexer_new_from_file` don't collide with the real
|
|
64
|
+
# implementations our port provides in `uc386-dos/file_uc386dos.c`.
|
|
65
|
+
# The minimal port hardcodes "no filesystem" responses; we overrride
|
|
66
|
+
# with INT 21h-backed file I/O via uc386's libc. Idempotent: checks
|
|
67
|
+
# for the already-patched marker before re-applying.
|
|
68
|
+
if grep -q "^mp_import_stat_t mp_import_stat" upstream/ports/minimal/main.c; then
|
|
69
|
+
sed -i.bak \
|
|
70
|
+
-e 's|^mp_lexer_t \*mp_lexer_new_from_file(qstr filename) {|static mp_lexer_t *_unused_mp_lexer_new_from_file(qstr filename) { (void)filename;|' \
|
|
71
|
+
-e 's|^mp_import_stat_t mp_import_stat(const char \*path) {|static mp_import_stat_t _unused_mp_import_stat(const char *path) { (void)path;|' \
|
|
72
|
+
upstream/ports/minimal/main.c
|
|
73
|
+
rm -f upstream/ports/minimal/main.c.bak
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# Patch upstream/ports/minimal/main.c to initialize sys.argv as an
|
|
77
|
+
# empty list right after mp_init(). MICROPY_PY_SYS_ARGV expects the
|
|
78
|
+
# `mp_sys_argv_obj` root pointer to hold a real list object — without
|
|
79
|
+
# this init, sys.argv reads back as a half-initialized struct and
|
|
80
|
+
# crashes on `len(sys.argv)`. Idempotent: only inserts if not already
|
|
81
|
+
# present.
|
|
82
|
+
if ! grep -q "mp_obj_list_init.*mp_sys_argv_obj" upstream/ports/minimal/main.c; then
|
|
83
|
+
sed -i.bak \
|
|
84
|
+
's|^ mp_init();$| mp_init();\n mp_obj_list_init((mp_obj_list_t *)\&MP_STATE_VM(mp_sys_argv_obj), 0);|' \
|
|
85
|
+
upstream/ports/minimal/main.c
|
|
86
|
+
rm -f upstream/ports/minimal/main.c.bak
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Patch upstream/ports/minimal/main.c to wire up `MICROPY_STACK_CHECK`.
|
|
90
|
+
# `mp_stack_ctrl_init()` captures the real stack top from a local
|
|
91
|
+
# stack variable; `mp_stack_set_limit(LIMIT)` sets the recursion-
|
|
92
|
+
# depth cap. Without these calls, every `mp_stack_check()` fires
|
|
93
|
+
# immediately (stack_top is NULL → mp_stack_usage returns a huge
|
|
94
|
+
# value → recursion-depth raise infinite-loops on its own setup).
|
|
95
|
+
# 0xC0000 = 768 KB, leaving 256 KB margin in dos_emu's 1 MB stack.
|
|
96
|
+
# Idempotent: only inserts if not already present.
|
|
97
|
+
if ! grep -q "mp_stack_ctrl_init" upstream/ports/minimal/main.c; then
|
|
98
|
+
sed -i.bak \
|
|
99
|
+
's|^ mp_init();$| mp_stack_ctrl_init();\n mp_stack_set_limit(0xC0000);\n mp_init();|' \
|
|
100
|
+
upstream/ports/minimal/main.c
|
|
101
|
+
rm -f upstream/ports/minimal/main.c.bak
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# Patch upstream/py/formatfloat.c so the DOUBLE-mode `repr()` doesn't
|
|
105
|
+
# request more digits than uc386's double-precision FPU can deliver.
|
|
106
|
+
# Default is `MAX_MANTISSA_DIGITS=19` (designed for the EXACT formatter
|
|
107
|
+
# that runs on long double, ~80-bit). uc386 lowers double through the
|
|
108
|
+
# x87 FPU but stores `long double` as 8 bytes (= double), so the
|
|
109
|
+
# APPROX formatter at 19 digits surfaces the last 3 noise digits as
|
|
110
|
+
# wrong values: `print(4.0)` becomes `3.99999999999999382` instead of
|
|
111
|
+
# `4.0`. Lower the request to SAFE_MANTISSA_DIGITS=16 (already
|
|
112
|
+
# defined adjacent in the file). Idempotent: checks for the
|
|
113
|
+
# already-patched value before re-applying.
|
|
114
|
+
if grep -q "^#define MAX_MANTISSA_DIGITS (19)$" upstream/py/formatfloat.c; then
|
|
115
|
+
sed -i.bak 's/^#define MAX_MANTISSA_DIGITS (19)$/#define MAX_MANTISSA_DIGITS (16) \/\/ uc386: long double == double, cap at SAFE/' upstream/py/formatfloat.c
|
|
116
|
+
rm -f upstream/py/formatfloat.c.bak
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
# Patch upstream/py/parsenum.c to neutralize the
|
|
120
|
+
# `assert(sizeof(mp_large_float_t) > sizeof(mp_float_t))` in
|
|
121
|
+
# `mp_decimal_exp`. uc386 stores long double as 8 bytes (= double),
|
|
122
|
+
# so the assert fires at runtime on the first compile-time-evaluated
|
|
123
|
+
# float. The algorithm still works — just at double precision —
|
|
124
|
+
# and the verify-retry loop in formatfloat.c delivers correctness
|
|
125
|
+
# regardless. Idempotent: leaves the assert commented after first
|
|
126
|
+
# patch.
|
|
127
|
+
if grep -q "^ assert(sizeof(mp_large_float_t) > sizeof(mp_float_t));$" upstream/py/parsenum.c; then
|
|
128
|
+
sed -i.bak \
|
|
129
|
+
's|^ assert(sizeof(mp_large_float_t) > sizeof(mp_float_t));$| /* uc386: removed — long double == double, see mpconfigport.h */|' \
|
|
130
|
+
upstream/py/parsenum.c
|
|
131
|
+
rm -f upstream/py/parsenum.c.bak
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
if [ ! -f build/genhdr/qstrdefs.generated.h ]; then
|
|
135
|
+
# Emit a triage qstr table by grep over upstream/py/ +
|
|
136
|
+
# upstream/shared/. Real builds use upstream's
|
|
137
|
+
# tools/makeqstrdefs.py which preprocesses each TU to find
|
|
138
|
+
# MP_QSTR_x macro uses; for triage we approximate with a grep
|
|
139
|
+
# over the source tree, which over-includes (any string that
|
|
140
|
+
# parses as an identifier becomes a qstr) but keeps the mapping
|
|
141
|
+
# complete enough that the enum in py/qstr.h covers every
|
|
142
|
+
# reference downstream code (py/, shared/runtime, etc.) makes.
|
|
143
|
+
#
|
|
144
|
+
# The first entry (MP_QSTRnull) goes in the static pool as
|
|
145
|
+
# QDEF0; everything else goes in the main pool as QDEF1.
|
|
146
|
+
# Reason: `mp_qstr_const_pool` (the main pool) has
|
|
147
|
+
# `is_sorted = true` and the binary search in
|
|
148
|
+
# `qstr_find_strn` does `pool->len - 1` as its upper bound —
|
|
149
|
+
# which underflows to 0xFFFFFFFF when `pool->len == 0`,
|
|
150
|
+
# then loops the binary search into out-of-bounds reads.
|
|
151
|
+
# A real upstream build always has at least one QDEF1 entry,
|
|
152
|
+
# so the empty-main-pool case never happens. We avoid it by
|
|
153
|
+
# routing every grep'd qstr to QDEF1.
|
|
154
|
+
{
|
|
155
|
+
# MP_QSTRnull (id 0) is the null/sentinel qstr. The rest of
|
|
156
|
+
# the static + unsorted qstrs (`__add__`, `print`, `__name__`,
|
|
157
|
+
# ...) are emitted by gen_qstrdefs.py from upstream's
|
|
158
|
+
# `static_qstr_list` + `unsorted_qstr_list` so they get
|
|
159
|
+
# ids < 256 — required for the byte-stored
|
|
160
|
+
# `mp_binary_op_method_name` table at py/objtype.c:483.
|
|
161
|
+
echo "QDEF0(MP_QSTRnull, 0, 0, \"\")"
|
|
162
|
+
# `MP_QSTR_<name>` — skip the 8-char `MP_QSTR_` prefix (M-P-_-Q-S-T-R-_)
|
|
163
|
+
# to recover the actual qstr string. Earlier the prefix-strip used 7
|
|
164
|
+
# chars and left a stray leading underscore (`__repl_print__` came
|
|
165
|
+
# out as `___repl_print__`), making LOAD_NAME for builtins fail and
|
|
166
|
+
# value-print compile crash inside mp_obj_equal_not_equal.
|
|
167
|
+
#
|
|
168
|
+
# Emit `length(name)` as the third QDEF1 field. qstr_find_strn's
|
|
169
|
+
# post-binary-search linear sweep checks lengths[at] == str_len
|
|
170
|
+
# before doing memcmp. Length 0 (the previous heuristic) made
|
|
171
|
+
# every static qstr fail the length check, causing
|
|
172
|
+
# `qstr_find_strn("__name__")` to return MP_QSTRnull even
|
|
173
|
+
# though the qstr was in the pool — so the bytecode compiler
|
|
174
|
+
# invented a fresh dynamic qstr for every identifier and
|
|
175
|
+
# LOAD_NAME against the static-init dict_main key (whose qstr
|
|
176
|
+
# id is the static 67) would never match.
|
|
177
|
+
# gen_qstrdefs.py reverse-mangles each `MP_QSTR_<sanitized>`
|
|
178
|
+
# macro back to its source string (e.g. `MP_QSTR__0x0a_` →
|
|
179
|
+
# `"\n"`, `MP_QSTR__lt_stdin_gt_` → `"<stdin>"`) using
|
|
180
|
+
# upstream's own codepoint2name table for fidelity, then emits
|
|
181
|
+
# QDEF1 lines sorted by the *original* string in ASCII order.
|
|
182
|
+
#
|
|
183
|
+
# Sort key matters: qstr_find_strn does
|
|
184
|
+
# `strncmp(probe, pool->qstrs[mid], n)` against the 4th QDEF1
|
|
185
|
+
# field (the un-escaped string). The pool's `is_sorted=true`
|
|
186
|
+
# invariant therefore requires sort-by-original. Earlier we
|
|
187
|
+
# used `LC_ALL=C sort -u` over macro names, which coincided
|
|
188
|
+
# for pure-identifier qstrs (`print`, `__name__`) but broke
|
|
189
|
+
# for escaped ones — `MP_QSTR__0x0a_` lex-orders near `_`,
|
|
190
|
+
# while its actual byte (0x0A) would sort first. With the
|
|
191
|
+
# macro-name-as-payload heuristic, escaped qstrs also rendered
|
|
192
|
+
# the *macro tail* as their string content, so `print()`'s
|
|
193
|
+
# trailing `\n` showed up as the literal text `_0x0a_`.
|
|
194
|
+
# `--bytes-hash 2` matches MICROPY_QSTR_BYTES_IN_HASH at
|
|
195
|
+
# ROM_LEVEL_EXTRA_FEATURES (uc386-dos/mpconfigport.h sets
|
|
196
|
+
# ROM_LEVEL=EXTRA, which makes BYTES_IN_HASH=2). Required:
|
|
197
|
+
# qstr_find_strn's post-binary-search filter does
|
|
198
|
+
# `pool->hashes[at] == str_hash` before memcmp at any
|
|
199
|
+
# non-zero MICROPY_QSTR_BYTES_IN_HASH — a stale `--bytes-hash 1`
|
|
200
|
+
# gen would emit 8-bit hashes and the runtime would
|
|
201
|
+
# truncate the lookup hash to 16 bits, mismatching every
|
|
202
|
+
# entry.
|
|
203
|
+
#
|
|
204
|
+
# The grep also pulls in X-macro NAMES from moderrno.c's
|
|
205
|
+
# MICROPY_PY_ERRNO_LIST so the `MP_QSTR_##e` token paste
|
|
206
|
+
# in moderrno.c's globals table resolves at compile time.
|
|
207
|
+
# Without this, enabling MICROPY_PY_ERRNO would fail with
|
|
208
|
+
# `__static_moderrno__errorcode_table.value: float init must
|
|
209
|
+
# be a constant expression (got Identifier)` because uc386
|
|
210
|
+
# can't resolve `MP_QSTR_EPERM` etc. as enum constants.
|
|
211
|
+
# Translate `X(NAME)` lines into `MP_QSTR_NAME` lines that
|
|
212
|
+
# gen_qstrdefs.py treats identically to a regular reference.
|
|
213
|
+
{
|
|
214
|
+
grep -rhoE "MP_QSTR_[A-Za-z_][A-Za-z0-9_]*" \
|
|
215
|
+
upstream/py/ upstream/shared/ upstream/extmod/ \
|
|
216
|
+
uc386-dos/
|
|
217
|
+
# POSIX `[[:space:]]` rather than `\s` — macOS's BSD
|
|
218
|
+
# `sed -E` doesn't honor PCRE shorthand in BRE/ERE.
|
|
219
|
+
grep -hoE "^[[:space:]]*X\([A-Z][A-Z0-9_]*\)" \
|
|
220
|
+
upstream/py/moderrno.c \
|
|
221
|
+
| sed -E 's/^[[:space:]]*X\(([A-Z][A-Z0-9_]*)\)/MP_QSTR_\1/'
|
|
222
|
+
} | "$PYTHON" gen_qstrdefs.py --bytes-hash 2
|
|
223
|
+
} > build/genhdr/qstrdefs.generated.h
|
|
224
|
+
fi
|
|
225
|
+
# Always regenerate moduledefs.h — it's small and the cache turned
|
|
226
|
+
# stealth-stale when we added new UCDOS_MOD_ENTRY_* entries below
|
|
227
|
+
# without touching the file's mtime, so the new module didn't
|
|
228
|
+
# register and its `import` raised at runtime.
|
|
229
|
+
cat > build/genhdr/moduledefs.h <<'EOF'
|
|
230
|
+
// Hand-rolled equivalent of `upstream/py/makemoduledefs.py`'s output,
|
|
231
|
+
// covering the modules our uc386-dos port supports at the
|
|
232
|
+
// CORE_FEATURES ROM level. A real upstream build runs
|
|
233
|
+
// `tools/makeqstrdefs.py cat module` to preprocess each TU and
|
|
234
|
+
// extract MP_REGISTER_MODULE invocations after `#if` filtering, then
|
|
235
|
+
// pipes the result through makemoduledefs.py. We approximate by
|
|
236
|
+
// emitting each entry under the same `#if` gate the module's source
|
|
237
|
+
// file uses, so flipping `MICROPY_PY_<X>` in mpconfigport.h adds or
|
|
238
|
+
// drops the entry consistently.
|
|
239
|
+
//
|
|
240
|
+
// Modules NOT registered here:
|
|
241
|
+
// - cmath — requires MICROPY_PY_CMATH; we have float math
|
|
242
|
+
// via the x87 FPU but no complex-number support
|
|
243
|
+
// today.
|
|
244
|
+
// - _thread — requires MICROPY_PY_THREAD (single-threaded
|
|
245
|
+
// DOS, no need today).
|
|
246
|
+
// - weakref — requires MICROPY_PY_WEAKREF (off at CORE).
|
|
247
|
+
// - io — requires MICROPY_PY_IO + a VFS implementation;
|
|
248
|
+
// the port has no VFS today so `open()` is a
|
|
249
|
+
// no-op. Pre-set MICROPY_PY_IO=0 in
|
|
250
|
+
// mpconfigport.h to skip.
|
|
251
|
+
|
|
252
|
+
// All modules registered as regular (non-extensible). Extensible
|
|
253
|
+
// only matters with a VFS so users can override built-ins with .py
|
|
254
|
+
// files; the port has no VFS so the distinction is moot.
|
|
255
|
+
|
|
256
|
+
extern const struct _mp_obj_module_t mp_module_builtins;
|
|
257
|
+
extern const struct _mp_obj_module_t mp_module_sys;
|
|
258
|
+
extern const struct _mp_obj_module_t mp_module___main__;
|
|
259
|
+
|
|
260
|
+
#if MICROPY_PY_GC
|
|
261
|
+
extern const struct _mp_obj_module_t mp_module_gc;
|
|
262
|
+
#define UCDOS_MOD_ENTRY_GC { MP_ROM_QSTR(MP_QSTR_gc), MP_ROM_PTR(&mp_module_gc) },
|
|
263
|
+
#else
|
|
264
|
+
#define UCDOS_MOD_ENTRY_GC
|
|
265
|
+
#endif
|
|
266
|
+
|
|
267
|
+
#if MICROPY_PY_MATH
|
|
268
|
+
extern const struct _mp_obj_module_t mp_module_math;
|
|
269
|
+
#define UCDOS_MOD_ENTRY_MATH { MP_ROM_QSTR(MP_QSTR_math), MP_ROM_PTR(&mp_module_math) },
|
|
270
|
+
#else
|
|
271
|
+
#define UCDOS_MOD_ENTRY_MATH
|
|
272
|
+
#endif
|
|
273
|
+
|
|
274
|
+
#if MICROPY_PY_MICROPYTHON
|
|
275
|
+
extern const struct _mp_obj_module_t mp_module_micropython;
|
|
276
|
+
#define UCDOS_MOD_ENTRY_MICROPYTHON { MP_ROM_QSTR(MP_QSTR_micropython), MP_ROM_PTR(&mp_module_micropython) },
|
|
277
|
+
#else
|
|
278
|
+
#define UCDOS_MOD_ENTRY_MICROPYTHON
|
|
279
|
+
#endif
|
|
280
|
+
|
|
281
|
+
#if MICROPY_PY_ARRAY
|
|
282
|
+
extern const struct _mp_obj_module_t mp_module_array;
|
|
283
|
+
#define UCDOS_MOD_ENTRY_ARRAY { MP_ROM_QSTR(MP_QSTR_array), MP_ROM_PTR(&mp_module_array) },
|
|
284
|
+
#else
|
|
285
|
+
#define UCDOS_MOD_ENTRY_ARRAY
|
|
286
|
+
#endif
|
|
287
|
+
|
|
288
|
+
#if MICROPY_PY_COLLECTIONS
|
|
289
|
+
extern const struct _mp_obj_module_t mp_module_collections;
|
|
290
|
+
#define UCDOS_MOD_ENTRY_COLLECTIONS { MP_ROM_QSTR(MP_QSTR_collections), MP_ROM_PTR(&mp_module_collections) },
|
|
291
|
+
#else
|
|
292
|
+
#define UCDOS_MOD_ENTRY_COLLECTIONS
|
|
293
|
+
#endif
|
|
294
|
+
|
|
295
|
+
#if MICROPY_PY_ERRNO
|
|
296
|
+
extern const struct _mp_obj_module_t mp_module_errno;
|
|
297
|
+
#define UCDOS_MOD_ENTRY_ERRNO { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_errno) },
|
|
298
|
+
#else
|
|
299
|
+
#define UCDOS_MOD_ENTRY_ERRNO
|
|
300
|
+
#endif
|
|
301
|
+
|
|
302
|
+
#if MICROPY_PY_STRUCT
|
|
303
|
+
extern const struct _mp_obj_module_t mp_module_struct;
|
|
304
|
+
#define UCDOS_MOD_ENTRY_STRUCT { MP_ROM_QSTR(MP_QSTR_struct), MP_ROM_PTR(&mp_module_struct) },
|
|
305
|
+
#else
|
|
306
|
+
#define UCDOS_MOD_ENTRY_STRUCT
|
|
307
|
+
#endif
|
|
308
|
+
|
|
309
|
+
#if MICROPY_PY_TIME
|
|
310
|
+
extern const struct _mp_obj_module_t mp_module_time;
|
|
311
|
+
#define UCDOS_MOD_ENTRY_TIME { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_module_time) },
|
|
312
|
+
#else
|
|
313
|
+
#define UCDOS_MOD_ENTRY_TIME
|
|
314
|
+
#endif
|
|
315
|
+
|
|
316
|
+
#if MICROPY_PY_UCTYPES
|
|
317
|
+
extern const struct _mp_obj_module_t mp_module_uctypes;
|
|
318
|
+
#define UCDOS_MOD_ENTRY_UCTYPES { MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) },
|
|
319
|
+
#else
|
|
320
|
+
#define UCDOS_MOD_ENTRY_UCTYPES
|
|
321
|
+
#endif
|
|
322
|
+
|
|
323
|
+
#if MICROPY_PY_RANDOM
|
|
324
|
+
extern const struct _mp_obj_module_t mp_module_random;
|
|
325
|
+
#define UCDOS_MOD_ENTRY_RANDOM { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mp_module_random) },
|
|
326
|
+
#else
|
|
327
|
+
#define UCDOS_MOD_ENTRY_RANDOM
|
|
328
|
+
#endif
|
|
329
|
+
|
|
330
|
+
#if MICROPY_PY_BINASCII
|
|
331
|
+
extern const struct _mp_obj_module_t mp_module_binascii;
|
|
332
|
+
#define UCDOS_MOD_ENTRY_BINASCII { MP_ROM_QSTR(MP_QSTR_binascii), MP_ROM_PTR(&mp_module_binascii) },
|
|
333
|
+
#else
|
|
334
|
+
#define UCDOS_MOD_ENTRY_BINASCII
|
|
335
|
+
#endif
|
|
336
|
+
|
|
337
|
+
#if MICROPY_PY_HASHLIB
|
|
338
|
+
extern const struct _mp_obj_module_t mp_module_hashlib;
|
|
339
|
+
#define UCDOS_MOD_ENTRY_HASHLIB { MP_ROM_QSTR(MP_QSTR_hashlib), MP_ROM_PTR(&mp_module_hashlib) },
|
|
340
|
+
#else
|
|
341
|
+
#define UCDOS_MOD_ENTRY_HASHLIB
|
|
342
|
+
#endif
|
|
343
|
+
|
|
344
|
+
#if MICROPY_PY_RE
|
|
345
|
+
extern const struct _mp_obj_module_t mp_module_re;
|
|
346
|
+
#define UCDOS_MOD_ENTRY_RE { MP_ROM_QSTR(MP_QSTR_re), MP_ROM_PTR(&mp_module_re) },
|
|
347
|
+
#else
|
|
348
|
+
#define UCDOS_MOD_ENTRY_RE
|
|
349
|
+
#endif
|
|
350
|
+
|
|
351
|
+
#if MICROPY_PY_CMATH
|
|
352
|
+
extern const struct _mp_obj_module_t mp_module_cmath;
|
|
353
|
+
#define UCDOS_MOD_ENTRY_CMATH { MP_ROM_QSTR(MP_QSTR_cmath), MP_ROM_PTR(&mp_module_cmath) },
|
|
354
|
+
#else
|
|
355
|
+
#define UCDOS_MOD_ENTRY_CMATH
|
|
356
|
+
#endif
|
|
357
|
+
|
|
358
|
+
// `os` is the custom uc386-dos shim from `uc386-dos/os_uc386dos.c`
|
|
359
|
+
// (mkdir/rmdir/unlink/rename/chdir/getcwd/listdir backed by INT 21h
|
|
360
|
+
// via uc386's libc). Always registered — there's no MICROPY_PY_OS
|
|
361
|
+
// gate on our shim.
|
|
362
|
+
extern const struct _mp_obj_module_t mp_module_os;
|
|
363
|
+
#define UCDOS_MOD_ENTRY_OS { MP_ROM_QSTR(MP_QSTR_os), MP_ROM_PTR(&mp_module_os) },
|
|
364
|
+
|
|
365
|
+
#if MICROPY_PY_HEAPQ
|
|
366
|
+
extern const struct _mp_obj_module_t mp_module_heapq;
|
|
367
|
+
#define UCDOS_MOD_ENTRY_HEAPQ { MP_ROM_QSTR(MP_QSTR_heapq), MP_ROM_PTR(&mp_module_heapq) },
|
|
368
|
+
#else
|
|
369
|
+
#define UCDOS_MOD_ENTRY_HEAPQ
|
|
370
|
+
#endif
|
|
371
|
+
|
|
372
|
+
#if MICROPY_PY_DEFLATE
|
|
373
|
+
extern const struct _mp_obj_module_t mp_module_deflate;
|
|
374
|
+
#define UCDOS_MOD_ENTRY_DEFLATE { MP_ROM_QSTR(MP_QSTR_deflate), MP_ROM_PTR(&mp_module_deflate) },
|
|
375
|
+
#else
|
|
376
|
+
#define UCDOS_MOD_ENTRY_DEFLATE
|
|
377
|
+
#endif
|
|
378
|
+
|
|
379
|
+
#if MICROPY_PY_IO
|
|
380
|
+
extern const struct _mp_obj_module_t mp_module_io;
|
|
381
|
+
#define UCDOS_MOD_ENTRY_IO { MP_ROM_QSTR(MP_QSTR_io), MP_ROM_PTR(&mp_module_io) },
|
|
382
|
+
#else
|
|
383
|
+
#define UCDOS_MOD_ENTRY_IO
|
|
384
|
+
#endif
|
|
385
|
+
|
|
386
|
+
#if MICROPY_PY_JSON
|
|
387
|
+
extern const struct _mp_obj_module_t mp_module_json;
|
|
388
|
+
#define UCDOS_MOD_ENTRY_JSON { MP_ROM_QSTR(MP_QSTR_json), MP_ROM_PTR(&mp_module_json) },
|
|
389
|
+
#else
|
|
390
|
+
#define UCDOS_MOD_ENTRY_JSON
|
|
391
|
+
#endif
|
|
392
|
+
|
|
393
|
+
#if MICROPY_PY_PLATFORM
|
|
394
|
+
extern const struct _mp_obj_module_t mp_module_platform;
|
|
395
|
+
#define UCDOS_MOD_ENTRY_PLATFORM { MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&mp_module_platform) },
|
|
396
|
+
#else
|
|
397
|
+
#define UCDOS_MOD_ENTRY_PLATFORM
|
|
398
|
+
#endif
|
|
399
|
+
|
|
400
|
+
// `base64`, `shutil`, `tempfile` — port-supplied modules in
|
|
401
|
+
// uc386-dos/{base64,shutil,tempfile}_uc386dos.c. No upstream
|
|
402
|
+
// gates; always registered.
|
|
403
|
+
extern const struct _mp_obj_module_t mp_module_base64;
|
|
404
|
+
extern const struct _mp_obj_module_t mp_module_shutil;
|
|
405
|
+
extern const struct _mp_obj_module_t mp_module_tempfile;
|
|
406
|
+
#define UCDOS_MOD_ENTRY_BASE64 { MP_ROM_QSTR(MP_QSTR_base64), MP_ROM_PTR(&mp_module_base64) },
|
|
407
|
+
#define UCDOS_MOD_ENTRY_SHUTIL { MP_ROM_QSTR(MP_QSTR_shutil), MP_ROM_PTR(&mp_module_shutil) },
|
|
408
|
+
#define UCDOS_MOD_ENTRY_TEMPFILE { MP_ROM_QSTR(MP_QSTR_tempfile), MP_ROM_PTR(&mp_module_tempfile) },
|
|
409
|
+
|
|
410
|
+
// `lwip` + `socket` — both back the same `mp_module_lwip` from
|
|
411
|
+
// upstream's extmod/modlwip.c. The Python-level `socket` API uses
|
|
412
|
+
// the lwIP raw API via that module.
|
|
413
|
+
#if MICROPY_PY_LWIP
|
|
414
|
+
extern const struct _mp_obj_module_t mp_module_lwip;
|
|
415
|
+
#define UCDOS_MOD_ENTRY_LWIP { MP_ROM_QSTR(MP_QSTR_lwip), MP_ROM_PTR(&mp_module_lwip) },
|
|
416
|
+
#define UCDOS_MOD_ENTRY_SOCKET { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_module_lwip) },
|
|
417
|
+
#else
|
|
418
|
+
#define UCDOS_MOD_ENTRY_LWIP
|
|
419
|
+
#define UCDOS_MOD_ENTRY_SOCKET
|
|
420
|
+
#endif
|
|
421
|
+
|
|
422
|
+
// `urllib` + `urllib_parse` — port-supplied. Registered as a
|
|
423
|
+
// `urllib` package shim (with `parse` as an attribute, so
|
|
424
|
+
// `from urllib import parse` works) and a top-level `urllib_parse`
|
|
425
|
+
// (so `import urllib_parse` works). `import urllib.parse` resolves
|
|
426
|
+
// via MP's dotted-import path: it imports `urllib`, then reads the
|
|
427
|
+
// `parse` attribute. We don't register a dotted name in the
|
|
428
|
+
// builtin-modules table — the qstr-grep doesn't see the dotted
|
|
429
|
+
// form anyway since `.` can't appear in a C identifier.
|
|
430
|
+
extern const struct _mp_obj_module_t mp_module_urllib;
|
|
431
|
+
extern const struct _mp_obj_module_t mp_module_urllib_parse;
|
|
432
|
+
#define UCDOS_MOD_ENTRY_URLLIB { MP_ROM_QSTR(MP_QSTR_urllib), MP_ROM_PTR(&mp_module_urllib) },
|
|
433
|
+
#define UCDOS_MOD_ENTRY_URLLIB_PARSE { MP_ROM_QSTR(MP_QSTR_urllib_parse), MP_ROM_PTR(&mp_module_urllib_parse) },
|
|
434
|
+
|
|
435
|
+
// `uc386_net` — port-supplied. Control surface for the lwIP eth
|
|
436
|
+
// netif sitting on the INT 0x83 packet-driver shim. Always
|
|
437
|
+
// registered when LWIP is on (no separate config gate yet).
|
|
438
|
+
#if MICROPY_PY_LWIP
|
|
439
|
+
extern const struct _mp_obj_module_t mp_module_uc386_net;
|
|
440
|
+
#define UCDOS_MOD_ENTRY_UC386_NET { MP_ROM_QSTR(MP_QSTR_uc386_net), MP_ROM_PTR(&mp_module_uc386_net) },
|
|
441
|
+
#else
|
|
442
|
+
#define UCDOS_MOD_ENTRY_UC386_NET
|
|
443
|
+
#endif
|
|
444
|
+
|
|
445
|
+
// `select` — extmod/modselect.c. Provides `select.select()` and
|
|
446
|
+
// `select.poll()` over the stream-protocol's poll hook (which
|
|
447
|
+
// modlwip.c's socket type implements). Useful for non-blocking
|
|
448
|
+
// I/O multiplexing.
|
|
449
|
+
#if MICROPY_PY_SELECT
|
|
450
|
+
extern const struct _mp_obj_module_t mp_module_select;
|
|
451
|
+
#define UCDOS_MOD_ENTRY_SELECT { MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&mp_module_select) },
|
|
452
|
+
#else
|
|
453
|
+
#define UCDOS_MOD_ENTRY_SELECT
|
|
454
|
+
#endif
|
|
455
|
+
|
|
456
|
+
// `tls` (and the `ssl` alias) — extmod/modtls_axtls.c. Wraps a
|
|
457
|
+
// socket through axtls: SSLContext + wrap_socket -> SSLSocket
|
|
458
|
+
// implementing the standard stream protocol. The actual axtls
|
|
459
|
+
// library lives at upstream/lib/axtls/{ssl,crypto}/.
|
|
460
|
+
#if MICROPY_PY_SSL
|
|
461
|
+
extern const struct _mp_obj_module_t mp_module_tls;
|
|
462
|
+
#define UCDOS_MOD_ENTRY_TLS { MP_ROM_QSTR(MP_QSTR_tls), MP_ROM_PTR(&mp_module_tls) },
|
|
463
|
+
// Python's stdlib name is `ssl`; map it to the same object so user
|
|
464
|
+
// code written against CPython continues to work.
|
|
465
|
+
#define UCDOS_MOD_ENTRY_SSL { MP_ROM_QSTR(MP_QSTR_ssl), MP_ROM_PTR(&mp_module_tls) },
|
|
466
|
+
#else
|
|
467
|
+
#define UCDOS_MOD_ENTRY_TLS
|
|
468
|
+
#define UCDOS_MOD_ENTRY_SSL
|
|
469
|
+
#endif
|
|
470
|
+
|
|
471
|
+
#define MICROPY_REGISTERED_MODULES \
|
|
472
|
+
{ MP_ROM_QSTR(MP_QSTR_builtins), MP_ROM_PTR(&mp_module_builtins) }, \
|
|
473
|
+
{ MP_ROM_QSTR(MP_QSTR_sys), MP_ROM_PTR(&mp_module_sys) }, \
|
|
474
|
+
{ MP_ROM_QSTR(MP_QSTR___main__), MP_ROM_PTR(&mp_module___main__) }, \
|
|
475
|
+
UCDOS_MOD_ENTRY_GC \
|
|
476
|
+
UCDOS_MOD_ENTRY_MATH \
|
|
477
|
+
UCDOS_MOD_ENTRY_MICROPYTHON \
|
|
478
|
+
UCDOS_MOD_ENTRY_ARRAY \
|
|
479
|
+
UCDOS_MOD_ENTRY_COLLECTIONS \
|
|
480
|
+
UCDOS_MOD_ENTRY_ERRNO \
|
|
481
|
+
UCDOS_MOD_ENTRY_STRUCT \
|
|
482
|
+
UCDOS_MOD_ENTRY_TIME \
|
|
483
|
+
UCDOS_MOD_ENTRY_UCTYPES \
|
|
484
|
+
UCDOS_MOD_ENTRY_RANDOM \
|
|
485
|
+
UCDOS_MOD_ENTRY_BINASCII \
|
|
486
|
+
UCDOS_MOD_ENTRY_HASHLIB \
|
|
487
|
+
UCDOS_MOD_ENTRY_RE \
|
|
488
|
+
UCDOS_MOD_ENTRY_CMATH \
|
|
489
|
+
UCDOS_MOD_ENTRY_OS \
|
|
490
|
+
UCDOS_MOD_ENTRY_HEAPQ \
|
|
491
|
+
UCDOS_MOD_ENTRY_DEFLATE \
|
|
492
|
+
UCDOS_MOD_ENTRY_IO \
|
|
493
|
+
UCDOS_MOD_ENTRY_JSON \
|
|
494
|
+
UCDOS_MOD_ENTRY_PLATFORM \
|
|
495
|
+
UCDOS_MOD_ENTRY_BASE64 \
|
|
496
|
+
UCDOS_MOD_ENTRY_SHUTIL \
|
|
497
|
+
UCDOS_MOD_ENTRY_TEMPFILE \
|
|
498
|
+
UCDOS_MOD_ENTRY_URLLIB \
|
|
499
|
+
UCDOS_MOD_ENTRY_URLLIB_PARSE \
|
|
500
|
+
UCDOS_MOD_ENTRY_LWIP \
|
|
501
|
+
UCDOS_MOD_ENTRY_SOCKET \
|
|
502
|
+
UCDOS_MOD_ENTRY_UC386_NET \
|
|
503
|
+
UCDOS_MOD_ENTRY_SELECT \
|
|
504
|
+
UCDOS_MOD_ENTRY_TLS \
|
|
505
|
+
UCDOS_MOD_ENTRY_SSL
|
|
506
|
+
|
|
507
|
+
// Module attribute-access delegation table — modules whose attr
|
|
508
|
+
// loads/stores need to dispatch through a port-supplied function.
|
|
509
|
+
// Picks up `MP_REGISTER_MODULE_DELEGATION(mod, fun)` calls.
|
|
510
|
+
// Currently only `sys` registers one (modsys.c:412): the
|
|
511
|
+
// `mp_module_sys_attr` function which dispatches `sys.path` /
|
|
512
|
+
// `sys.ps1` / `sys.ps2` / `sys.tracebacklimit` reads and writes
|
|
513
|
+
// against `MP_STATE_VM(sys_mutable[])`.
|
|
514
|
+
#if MICROPY_PY_SYS_ATTR_DELEGATION
|
|
515
|
+
extern void mp_module_sys_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest);
|
|
516
|
+
#define MICROPY_MODULE_DELEGATIONS \
|
|
517
|
+
{ MP_ROM_PTR(&mp_module_sys), mp_module_sys_attr },
|
|
518
|
+
#endif
|
|
519
|
+
|
|
520
|
+
#define MICROPY_REGISTERED_EXTENSIBLE_MODULES
|
|
521
|
+
EOF
|
|
522
|
+
[ -f build/genhdr/mpversion.h ] || cat > build/genhdr/mpversion.h <<'EOF'
|
|
523
|
+
// Triage stub.
|
|
524
|
+
#define MICROPY_GIT_TAG "uc386-triage"
|
|
525
|
+
#define MICROPY_GIT_HASH "0000000"
|
|
526
|
+
#define MICROPY_BUILD_DATE "2026-05-01"
|
|
527
|
+
EOF
|
|
528
|
+
if [ ! -f build/genhdr/root_pointers.h ]; then
|
|
529
|
+
# Real builds run upstream/py/makeqstrdefs.py with mode=root_pointer
|
|
530
|
+
# to scan all C sources for `MP_REGISTER_ROOT_POINTER(<decl>);`
|
|
531
|
+
# declarations and emit them as struct fields of `_mp_state_vm_t`
|
|
532
|
+
# (via py/mpstate.h's `#include "genhdr/root_pointers.h"`). For
|
|
533
|
+
# triage we approximate with grep — the macro pattern is regular,
|
|
534
|
+
# we just take everything between the parens and emit it as a
|
|
535
|
+
# struct member terminated with a semicolon.
|
|
536
|
+
{
|
|
537
|
+
echo "// Triage stub. Real build emits MP_REGISTER_ROOT_POINTER entries here."
|
|
538
|
+
grep -rhE "^MP_REGISTER_ROOT_POINTER\(.*\);" \
|
|
539
|
+
upstream/py/ upstream/shared/ upstream/extmod/ \
|
|
540
|
+
| sed -E 's#^MP_REGISTER_ROOT_POINTER\((.*)\);# \1;#' \
|
|
541
|
+
| sort -u
|
|
542
|
+
} > build/genhdr/root_pointers.h
|
|
543
|
+
fi
|
|
544
|
+
|
|
545
|
+
# Triage stub: a one-line main() so uc386 (which requires a main
|
|
546
|
+
# function in every translation unit it compiles) accepts library
|
|
547
|
+
# .c files. We append it to each src on the fly. This answers
|
|
548
|
+
# "would this file compile if it were linked into a real port?"
|
|
549
|
+
# without the multi-file plumbing a real port needs.
|
|
550
|
+
TRIAGE_MAIN="build/_triage_main.c"
|
|
551
|
+
cat > "$TRIAGE_MAIN" <<'EOF'
|
|
552
|
+
// Synthetic main so uc386 has an entry-point during per-file triage.
|
|
553
|
+
// Real ports/<port>/main.c supplies its own main + mp_init/mp_deinit.
|
|
554
|
+
int main(int argc, char **argv) { (void)argc; (void)argv; return 0; }
|
|
555
|
+
EOF
|
|
556
|
+
|
|
557
|
+
TRIAGE="build/triage.txt"
|
|
558
|
+
ERR_HIST="build/errors.txt"
|
|
559
|
+
: > "$TRIAGE"
|
|
560
|
+
: > "$ERR_HIST"
|
|
561
|
+
|
|
562
|
+
PASS=0
|
|
563
|
+
FAIL=0
|
|
564
|
+
TOTAL=0
|
|
565
|
+
|
|
566
|
+
# Section accounting so the per-section pass/fail is visible.
|
|
567
|
+
PY_PASS=0; PY_FAIL=0; PY_TOTAL=0
|
|
568
|
+
SH_PASS=0; SH_FAIL=0; SH_TOTAL=0
|
|
569
|
+
|
|
570
|
+
triage_one() {
|
|
571
|
+
src="$1"
|
|
572
|
+
section="$2" # used only for the section-count update
|
|
573
|
+
name_prefix="$3" # disambiguates basenames between sections
|
|
574
|
+
[ -f "$src" ] || return 0
|
|
575
|
+
TOTAL=$((TOTAL + 1))
|
|
576
|
+
name="${name_prefix}$(basename "$src" .c)"
|
|
577
|
+
if "$PYTHON" -m uc386.main "$TRIAGE_MAIN" "$src" \
|
|
578
|
+
-o "build/${name}.asm" \
|
|
579
|
+
-I "$INCLUDE" \
|
|
580
|
+
-I "upstream" \
|
|
581
|
+
-I "$PORT_DIR" \
|
|
582
|
+
-I "build" \
|
|
583
|
+
> "build/${name}.out" 2> "build/${name}.err"; then
|
|
584
|
+
PASS=$((PASS + 1))
|
|
585
|
+
if [ "$section" = py ]; then PY_PASS=$((PY_PASS + 1)); PY_TOTAL=$((PY_TOTAL + 1)); fi
|
|
586
|
+
if [ "$section" = sh ]; then SH_PASS=$((SH_PASS + 1)); SH_TOTAL=$((SH_TOTAL + 1)); fi
|
|
587
|
+
echo "$name: OK" >> "$TRIAGE"
|
|
588
|
+
rm -f "build/${name}.err" "build/${name}.out"
|
|
589
|
+
else
|
|
590
|
+
FAIL=$((FAIL + 1))
|
|
591
|
+
if [ "$section" = py ]; then PY_FAIL=$((PY_FAIL + 1)); PY_TOTAL=$((PY_TOTAL + 1)); fi
|
|
592
|
+
if [ "$section" = sh ]; then SH_FAIL=$((SH_FAIL + 1)); SH_TOTAL=$((SH_TOTAL + 1)); fi
|
|
593
|
+
first_line="$(head -1 "build/${name}.err" 2>/dev/null || echo unknown)"
|
|
594
|
+
echo "$name: FAIL $first_line" >> "$TRIAGE"
|
|
595
|
+
# Strip filename + line numbers from the leading error so
|
|
596
|
+
# the histogram clusters by error class.
|
|
597
|
+
echo "$first_line" \
|
|
598
|
+
| sed -E 's#^[^:]+:[0-9]+:[0-9]+:?##; s#^[^:]+:[0-9]+:?##' \
|
|
599
|
+
| sed -E 's# +# #g; s#^ +##' \
|
|
600
|
+
>> "$ERR_HIST"
|
|
601
|
+
fi
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
# py/ — the platform-independent core (132 sources today).
|
|
605
|
+
for src in "$SRC_DIR"/*.c; do
|
|
606
|
+
triage_one "$src" py ""
|
|
607
|
+
done
|
|
608
|
+
|
|
609
|
+
# shared/{libc,readline,runtime,timeutils,netutils}/ — extra sources
|
|
610
|
+
# real ports pull in alongside py/. The minimal port uses the first
|
|
611
|
+
# three; richer ports (esp32, rp2, etc.) also pull in timeutils +
|
|
612
|
+
# netutils. Keeping them in the same triage answers "how close is a
|
|
613
|
+
# full port to compiling cleanly" not just "how clean is py/".
|
|
614
|
+
for shared_src in \
|
|
615
|
+
upstream/shared/libc/printf.c \
|
|
616
|
+
upstream/shared/libc/string0.c \
|
|
617
|
+
upstream/shared/libc/__errno.c \
|
|
618
|
+
upstream/shared/libc/abort_.c \
|
|
619
|
+
upstream/shared/readline/readline.c \
|
|
620
|
+
upstream/shared/runtime/pyexec.c \
|
|
621
|
+
upstream/shared/runtime/stdout_helpers.c \
|
|
622
|
+
upstream/shared/runtime/interrupt_char.c \
|
|
623
|
+
upstream/shared/runtime/sys_stdio_mphal.c \
|
|
624
|
+
upstream/shared/timeutils/timeutils.c \
|
|
625
|
+
upstream/shared/netutils/netutils.c \
|
|
626
|
+
upstream/shared/netutils/trace.c \
|
|
627
|
+
upstream/shared/netutils/dhcpserver.c; do
|
|
628
|
+
[ -f "$shared_src" ] || continue
|
|
629
|
+
# name_prefix=shared_ so e.g. shared/libc/printf.c doesn't collide
|
|
630
|
+
# with py/ — there is no collision today, but the prefix keeps
|
|
631
|
+
# the name space clean and makes the section visible in triage.txt.
|
|
632
|
+
triage_one "$shared_src" sh "shared_"
|
|
633
|
+
done
|
|
634
|
+
|
|
635
|
+
echo
|
|
636
|
+
echo "== triage: $PASS pass / $FAIL fail / $TOTAL total =="
|
|
637
|
+
echo " py/ $PY_PASS / $PY_TOTAL"
|
|
638
|
+
echo " shared/{libc,readline,runtime,timeutils,netutils}/ $SH_PASS / $SH_TOTAL"
|
|
639
|
+
echo
|
|
640
|
+
echo "Top error classes (count × class):"
|
|
641
|
+
sort "$ERR_HIST" | uniq -c | sort -rn | head -15
|