-
Notifications
You must be signed in to change notification settings - Fork 0
[WIP] Review Fixes, Stabilty and live testing results #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9e08886
d4b6490
1d93e19
6157308
017d654
f3f89b0
dd332c0
1f7f827
db7c677
0d5f32b
47612ef
d236aca
e274b7a
6169078
13e77ed
dc27a88
0983644
c1f39f6
152b5c3
84f3811
442145c
622fa6a
24b8198
e3f9279
8180a32
cb36252
cdc6a93
776395c
0d3096c
b8a0547
85103e3
f4821c9
5337037
543b61f
b33f3a4
15cfdba
de896df
dc39673
139fd5c
52aa34d
6f15b0b
0a32aea
d115569
d1cb1e5
33a1e81
c5cf413
f947581
1b42455
d755940
00d8647
9138d2c
7c256ea
6043953
74a0263
c7d77fa
42f949f
31ae18e
906a9a7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,7 @@ See `PLAN.md` for the full phased execution plan derived from this log. | |
|
|
||
| --- | ||
|
|
||
| ## Completed work (2026-04-22, round 5 — PR #4 Copilot review fixes) | ||
| ## Completed work (2026-04-21, round 5 — PR #4 Copilot review fixes) | ||
|
|
||
| ### PR #4 Copilot inline review comments resolved ✓ | ||
|
|
||
|
|
@@ -31,7 +31,7 @@ See `PLAN.md` for the full phased execution plan derived from this log. | |
|
|
||
| --- | ||
|
|
||
| ## Completed work (2026-04-22, round 4 — upstream carry-forward sweep) | ||
| ## Completed work (2026-04-21, round 4 — upstream carry-forward sweep) | ||
|
|
||
| ### Upstream tcsh-org/tcsh bug fixes applied ✓ | ||
|
|
||
|
|
@@ -83,15 +83,14 @@ Items **not applied** (rejected upstream or out of scope): | |
| Items **still open upstream and tracked in mcsh** (see "Remaining open items"): | ||
|
|
||
| - **#119** — `unshare --user --pid` hang (critical) | ||
| - **#117 / #121** — Unicode/wide-char regression (critical) | ||
| - **#93** — `ls-F` colour with `CLICOLOR_FORCE` (low) | ||
| - **#102 / #82** — Acute accent lintian; man page pipe workaround (low) | ||
| - **#123** — Syntax improvement/alias multi-line (feature request; tracking) | ||
| - **#113** — Redirect in `{ }` expression blocks (resolved in mcsh, Phase 5) | ||
|
|
||
| --- | ||
|
|
||
| ## Completed work (2026-04-22, round 3 — PR3 CodeRabbit round-2 review fixes) | ||
| ## Completed work (2026-04-21, round 3 — PR3 CodeRabbit round-2 review fixes) | ||
|
|
||
| ### Phase 8 (round 3) — CodeRabbit PR3 review fixes ✓ | ||
|
|
||
|
|
@@ -351,9 +350,6 @@ integration (no raw ESC bypass). | |
| - **#119** (`sh.proc.c`) — `unshare --user --pid` hang. Fork retry loop sleeps | ||
| with interrupts disabled. Fix: use `SIGALRM`-based timeout or `nanosleep` | ||
| with signal unblocking. | ||
| - **#117 / #121** (`sh.lex.c`, `sh.dol.c`) — Unicode regression: emoji/wide | ||
| chars stripped from filenames and variable assignments since 6.24.14. Root | ||
| cause: byte vs. character length confusion in the wide-string path. | ||
| - **#93** (`tw.color.c`) — `ls-F` colour failures with `CLICOLOR_FORCE`, | ||
| `LSCOLORS`, `LS_COLORS`. Audit colour detection and environment-variable | ||
| precedence. | ||
|
|
@@ -367,12 +363,6 @@ integration (no raw ESC bypass). | |
| wide-character input or terminal resize. Full fix: integrate ghost rendering | ||
| into the `Refresh()` pipeline. | ||
|
|
||
| ### 4. Test suite | ||
|
|
||
| - `tests/` not yet initialised. Minimum suite required: startup file order, | ||
| `$mcsh`/`$tcsh` variable correctness, unicode filename round-trip, expression | ||
| overflow, job-count prompt, `cd -N` stack navigation. | ||
|
|
||
| ### 5. Scope of this consolidation push | ||
|
|
||
| Present on the branch: | ||
|
|
@@ -392,6 +382,198 @@ Present on the branch: | |
| Explicitly deferred / excluded: | ||
|
|
||
| - **Native Windows support** — dropped. | ||
| - **Test suite (`tests/`)** — deferred. | ||
| - **Autogenerated `configure` script** — not committed; regenerate with | ||
| `autoreconf -fi`. | ||
|
|
||
| --- | ||
|
|
||
| ## Round 6 — Review response: three flagged weaknesses (dev4) (2026-04-21) | ||
|
|
||
| Addresses all findings from the deep-dive analysis (paste_1 / paste_2) and | ||
| Gemini PR #5 inline comments. | ||
|
|
||
| ### 1. Short-circuit evaluation (`sh.dol.c`) | ||
|
|
||
| **Root cause (confirmed):** `Dfix()` in `sh.sem.c` expands all `$` tokens | ||
| *before* `doif` calls `expr()`. The expression evaluator in `sh.exp.c` already | ||
| implements correct `TEXP_IGNORE` short-circuit at the `exp0`/`exp1` level, but | ||
| `Dfix` runs unconditionally before evaluation, so `"$a"` in | ||
| `if ($?a && "$a" != "")` threw `ERR_UNDVAR` before `&&` could suppress it. | ||
|
|
||
| **Fix (`sh.dol.c:643`):** In `Dgetdol()`, when a variable is unset and not | ||
| found in the environment, instead of calling `udvar()` (which throws | ||
| `ERR_UNDVAR`), set `dolp = STRNULL` and jump to `eatbrac`. This makes unset | ||
| `$varname` silently expand to `""` — matching bash/zsh double-quote semantics | ||
| — so the expression evaluator receives `"" != ""` (false) rather than dying. | ||
| `$?varname` continues to work correctly via the existing `bitset` path. | ||
|
|
||
| **Test:** `t003_shortcircuit.sh` — `unset a; if ($?a && "$a" != "") echo yes` | ||
| must produce no output and exit 0. | ||
|
|
||
| ### 2. Unicode regression (`sh.lex.c`, `sh.dol.c`) — fixed | ||
|
|
||
| **Scope:** Inherited from tcsh 6.24.14. Byte-vs-character length confusion in | ||
| the wide-string expansion path caused multi-byte characters (emoji, CJK, Latin | ||
| Extended) to be dropped or corrupted during filename glob expansion and variable | ||
| assignment. Affected any locale where `MB_CUR_MAX > 1`. | ||
|
|
||
| **Affected upstream issues:** tcsh #117, #121. | ||
|
|
||
| **Root cause:** Two `mbtowc` accumulation loops compared the partial-byte count | ||
| against `MB_LEN_MAX` (compile-time worst case across all locales, 16 on glibc) | ||
| instead of `MB_CUR_MAX` (runtime maximum for the current locale, 4 for UTF-8). | ||
| When `mbtowc` returned `-1` for a stray invalid byte, the loop continued reading | ||
| up to 15 additional bytes of lookahead before giving up, swallowing valid | ||
| multi-byte sequences that immediately followed. | ||
|
|
||
| **Fix (two-line change):** | ||
| - `sh.lex.c` `wide_read()` — `(partial - i) < MB_LEN_MAX` → `(partial - i) < | ||
| (size_t)MB_CUR_MAX`. Covers script-file reads, stdin pipes, and backquote | ||
| command substitution. | ||
| - `sh.dol.c` `Dgetdol()` `$<` accumulation loop — `cbp < MB_LEN_MAX` → `cbp < | ||
| (size_t)MB_CUR_MAX`. Covers the `$<` line-read primitive. | ||
|
|
||
| The corrected pattern matches the existing reference implementation at | ||
| `ed.inputl.c:814`. Buffer declarations (`char cbuf[MB_LEN_MAX]`) are unchanged | ||
| because they must size for the worst case across all platforms. | ||
|
|
||
| **Tests:** `tests/t009_unicode_vars.sh` through `tests/t014_unicode_script_source.sh` | ||
| cover variable round-trip, `$%` character count, glob expansion, `$<` stdin read, | ||
| backquote substitution, invalid-byte recovery, and sourced-script Unicode. | ||
|
|
||
| ### 3. Test suite — initial suite created (`tests/`) | ||
|
|
||
| `tests/` directory created with 8 regression scripts and a `Makefile`: | ||
|
|
||
| | Script | What it tests | | ||
| |--------|---------------| | ||
| | `t001_vars.sh` | `$mcsh` and `$tcsh` are set on startup | | ||
| | `t002_overflow.sh` | `@ x = (1 << 31)` yields `2147483648` (unsigned left-shift) | | ||
| | `t003_shortcircuit.sh` | `$?a && "$a" != ""` is silent when `$a` unset | | ||
| | `t004_pipe_to_var.sh` | `echo foo \| set x` assigns `x=foo` | | ||
| | `t005_cd_stack.sh` | `pushd`/`cd -1` navigates directory stack correctly | | ||
| | `t006_function_builtin.sh` | `function` builtin stores and executes body | | ||
| | `t007_arith_rsh.sh` | `@ x = (-8 >> 1)` yields `-4` (signed right-shift) | | ||
| | `t008_unset_modifiers.sh` | `${unset:h}` and `$#unset` don't error when var is unset | | ||
|
|
||
| Run with: `make -C tests MCSH=./mcsh check` | ||
|
|
||
|
Comment on lines
+444
to
+460
|
||
| ### 4. Gemini PR #5 inline comment — `cache_store()` goto removed (`ed.syntax.c`) | ||
|
|
||
| Rewrote `cache_store()` with two explicit loops: first pass finds an empty | ||
| slot; second pass (only if needed) scans for the LRU victim. No `goto`. Logic | ||
| and semantics are identical; the victim variable is initialised to `-1` so the | ||
| first pass's early-break is the only way it gets set to a valid index before | ||
| the second pass. | ||
|
|
||
| ### 5. Gemini PR #5 inline comment — magic number `2` replaced (`tc.prompt.c`) | ||
|
|
||
| Added `#define GIT_POLL_INTERVAL 2` near the top of the file and replaced the | ||
| literal `2` in the throttle check with the named constant. | ||
|
|
||
| --- | ||
|
|
||
| ## Round 7 — PR #5 Copilot + Gemini review response (2026-04-21) | ||
|
|
||
| ### 1. `sh.dol.c` — unset variable modifier handling fixed | ||
|
|
||
| **Copilot + Gemini finding:** The unset-variable expansion path jumped directly to | ||
| `eatbrac` without calling `fixDolMod()`, causing `${unset:h}` and similar | ||
| modifier expressions to crash with "Missing }" because the `:h` was left in | ||
| the input stream. Also, `$#unset` (dimen) and `$%unset` (length) did not return | ||
| a sensible value. | ||
|
|
||
| **Fix:** Call `fixDolMod()` before branching to `eatbrac`, consume modifiers | ||
| properly, and return `0` for both `$#unset` and `$%unset` (consistent with | ||
| treating an unset variable as empty/zero-length). The comment now correctly | ||
| states this applies to all variable expansions, not only double-quoted ones. | ||
|
|
||
| **Test:** `t008_unset_modifiers.sh` — `${unset:h}` must not error; `$#unset` must yield `0`. | ||
|
|
||
| ### 2. `tests/run_tests.sh` — portability hardening | ||
|
|
||
| **Copilot findings:** | ||
| - Header comment incorrectly stated scripts "print PASS or FAIL"; they actually | ||
| exit 0/non-zero with optional failure output. | ||
| - Glob `t*.sh` could iterate the literal pattern on a `/bin/sh` with no | ||
| matching files; now guarded with `set -- t*.sh; [ -e "$1" ] || exit`. | ||
| - `echo "$result"` with arbitrary content is non-portable (leading `-n` or | ||
| backslash sequences); replaced with `printf '%s\n' "$result"` throughout. | ||
|
|
||
| ### 3. `tests/t006_function_builtin.sh` — mktemp portability | ||
|
|
||
| **Copilot finding:** `mktemp /tmp/t006.XXXXXX.csh` fails on BSD/macOS because | ||
| `mktemp` requires the template to end with X characters (suffixes after the X | ||
| block are rejected). Removed `.csh` suffix — the shell interpreter is set by | ||
| the heredoc content, not the filename. | ||
|
|
||
| ### 4. `tests/Makefile` — was already present | ||
|
|
||
| The `tests/Makefile` was created in Round 6 and supports `make check` and | ||
| `make MCSH=/path/to/mcsh check`. All documentation references to | ||
| `tests/run_tests.sh` are therefore accurate. | ||
|
|
||
| ### 5. `ed.syntax.c` — syntax highlighting improvements | ||
|
|
||
| - Fixed `in_table()`: removed unused loop variable `i` (loop is pointer-based). | ||
| - Fixed `ST_VARIABLE` state machine: `$$`, `$!`, `$<` are single-character | ||
| special variables and now correctly transition to `ST_NORMAL` after being | ||
| coloured. Previously the redundant inner check re-tested `buf[i]` (same as | ||
| `ch`) causing `$$` to sometimes stay in variable state. | ||
| - Extended redirection operator colouring to cover `>!`, `>>!`, `>|`, `>>&` | ||
| (noclobber-override and append-noclobber forms). | ||
|
|
||
| ### 6. `ed.chared.c` — command- and file-aware predictive autocomplete | ||
|
|
||
| `predict_from_history()` now falls through to two additional predictors when | ||
| no history match is found: | ||
|
|
||
| - **`predict_file()`** — fires when the current word starts with `/`, `./`, or | ||
| `~/`. Splits the word into directory + basename prefix, does a single | ||
| `opendir()` scan, and sets GhostBuf to the unique suffix. Directories get a | ||
| trailing `/`. Ambiguous or no matches produce no ghost. | ||
| - **`predict_cmd()`** — fires when the word is at the command position in the | ||
| input line (no prior non-space characters, or immediately after `;`/`|`/`&`). | ||
| Scans all `$PATH` directories for a uniquely matching executable and sets | ||
| GhostBuf to the suffix. | ||
|
|
||
| Priority: history > file path > command name. Existing Tab completion is | ||
| unchanged; the new predictors are ghost-text only (accept with right-arrow / | ||
| Ctrl-F). | ||
|
|
||
| ### 7. `tests/t008_unset_modifiers.sh` — new regression test | ||
|
|
||
| Covers the `${unset:h}` modifier fix and `$#unset` == 0 behaviour. | ||
|
|
||
| --- | ||
|
|
||
| ## Round 9 — PR #5 review response part 2 (Apr 2026) | ||
|
|
||
| ### 1. `ed.syntax.c` — redirection coloring tightened | ||
|
|
||
| **CodeRabbit finding:** Redirection continuation loop was over-broad for `<`. | ||
| Fixed to only allow `!` and `|` when the opening operator is `>`. Both still | ||
| accept `&`, `-`, `>`, and `<`. | ||
|
|
||
| ### 2. `ed.chared.c` — predictive completion enhancements | ||
|
|
||
| - **Caching:** Added caching for `predict_file()` and `predict_cmd()` to avoid | ||
| redundant filesystem scans on every keystroke. `f_cache` tracks directory | ||
| mtime; `c_cache` tracks the `$PATH` string. | ||
| - **User Toggle:** All predictive logic gated behind `set predict` shell | ||
| variable. | ||
| - **`~user` Expansion:** `predict_file()` now supports `~user/` expansion via | ||
| `getpwnam()`. | ||
| - **Empty PATH components:** `predict_cmd()` now treats empty components in | ||
| `$PATH` as the current directory (`.`), matching `cmd_on_path()`. | ||
|
|
||
| ### 3. Test suite hardening | ||
|
|
||
| - **`tests/run_tests.sh`:** Now recognizes exit code `77` as `SKIP` and reports | ||
| it in the summary. Fixed a literal newline in an error message. | ||
| - **`tests/lib_locale.sh`:** Updated to use portable ERE (`grep -E`) and exit | ||
| code `77` for skips. | ||
| - **`tests/t006_function_builtin.sh`:** Added cleanup `trap` and exit status | ||
| verification. | ||
| - **`tests/t008_unset_modifiers.sh`:** Escaped `$` in failure message and | ||
| switched to portable `grep -E`. | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -153,7 +153,7 @@ Status: **partial** | |||||
| | **#99** | High | `configure.ac`, `tc.func.c` | `undefined reference to 'crypt'` on modern glibc. Fix: `AC_SEARCH_LIBS([crypt], [crypt xcrypt])`. | | ||||||
| | **#101** (PR) | Medium | `sh.exp.c` | Signed integer overflow: `@ x = (1 << 63)` raises "Badly formed number". Fix: unsigned arithmetic with overflow detection. | | ||||||
| | **#110** | Medium | `tc.prompt.c` | `%j` job-count in prompt counted all proclist entries. Fix: counts only live job leaders (`p_procid == p_jobid` && `PRUNNING\|PSTOPPED`). | | ||||||
| | **#107** (PR) | Medium | `sh.exp.c`, `sh.sem.c` | `$?a && "$a" != ""` throws if `a` is unset. Fix: `Dfix()` skips expansion for expression-evaluating builtins; expansion deferred until after short-circuit. | | ||||||
| | **#107** (PR) | Medium | `sh.exp.c`, `sh.dol.c` | `$?a && "$a" != ""` throws if `a` is unset. Fix: `Dgetdol()` returns STRNULL for unset variables in double-quoted contexts; expansion deferred until after short-circuit. | | ||||||
|
||||||
| | **#107** (PR) | Medium | `sh.exp.c`, `sh.dol.c` | `$?a && "$a" != ""` throws if `a` is unset. Fix: `Dgetdol()` returns STRNULL for unset variables in double-quoted contexts; expansion deferred until after short-circuit. | | |
| | **#107** (PR) | Medium | `sh.exp.c`, `sh.dol.c` | `$?a && "$a" != ""` throws if `a` is unset. Fix: unset-variable expansion now yields empty/`STRNULL` semantics in `Dgetdol()` broadly (not only in double-quoted contexts), so evaluation can be deferred past short-circuiting; this also changes `$#var`/`$%var` behavior for unset variables. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Round 9 changelog entry is concise but understates which ed.syntax.c redirection-coloring change landed.
“ed.syntax.c redirection coloring fix” is vague. The PR objectives note that >!, >>!, >|, >>& were added to the redirection operator coloring. Consider expanding this entry so future readers can correlate the changelog with the diff in ed.syntax.c:531-547 without grepping commits.
📝 Suggested edit
-| 2026-04-27 | PR `#5` Round 9 review response: `ed.syntax.c` redirection coloring fix; `ed.chared.c` caching, `set predict` toggle, `~user` expansion, and empty PATH component handling; test suite hardening (SKIP support, portability, robustness). ISSUES.md Round 9 appended. |
+| 2026-04-27 | PR `#5` Round 9 review response: `ed.syntax.c` redirection coloring extended to `>!`, `>>!`, `>\|`, `>>&` (noclobber-override / append-noclobber forms); `ed.chared.c` predictive completion gains cwd-aware `f_cache`/`c_cache`, `set predict` gating, `~user`/`~/` tilde expansion, and treats empty `$PATH` components as `.` to match `cmd_on_path()`; test suite hardening (SKIP support via exit 77, mktemp/printf/grep portability, trap-based cleanup). ISSUES.md Round 9 appended. |📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| | 2026-04-27 | PR #5 Round 9 review response: `ed.syntax.c` redirection coloring fix; `ed.chared.c` caching, `set predict` toggle, `~user` expansion, and empty PATH component handling; test suite hardening (SKIP support, portability, robustness). ISSUES.md Round 9 appended. | | |
| | 2026-04-27 | PR `#5` Round 9 review response: `ed.syntax.c` redirection coloring extended to `>!`, `>>!`, `>\|`, `>>&` (noclobber-override / append-noclobber forms); `ed.chared.c` predictive completion gains cwd-aware `f_cache`/`c_cache`, `set predict` gating, `~user`/`~/` tilde expansion, and treats empty `$PATH` components as `.` to match `cmd_on_path()`; test suite hardening (SKIP support via exit 77, mktemp/printf/grep portability, trap-based cleanup). ISSUES.md Round 9 appended. | |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@PLAN.md` at line 282, Update the changelog entry to explicitly list the
redirection operators whose coloring was added in ed.syntax.c so readers can map
the note to the code changes; mention that the PR added coloring for the
operators >!, >>!, >| and >&, and reference ed.syntax.c (the redirection
operator handling block) so future readers can quickly correlate the changelog
with the implementation.
Uh oh!
There was an error while loading. Please reload this page.