v1.0.6.4-alpha — What changed
bc -x exact rational matrices. Small matrices of exact rationals, opt-in via the same --exact flag that gates the rest of the exact tier. Literals use bracketed-list syntax ([[a, b], [c, d]]) and entries can be any Rational: [[1/2, 1/3], [1/4, 1/5]] stays exact through every operation. Arithmetic + - * is dimension-checked at runtime; scalar multiplication and division broadcast a Rational across all entries. Built-ins: det (cofactor expansion), transpose, inverse (Gauss-Jordan over rationals — produces a rational matrix, not a numerical approximation), mget / mset (0-indexed; mset is functional — returns a new matrix), and rows / cols for shape introspection. Structural equality; ordering raises since matrices have no total order. m * inverse(m) evaluates to the identity bit-exactly — no float fuzz, even when the inverse contains entries like 3/5 or -7/10. Limits up front: no LU/QR/SVD, no eigenvalues, no symbolic dimensions, and cofactor-expansion slows past ~6×6.
Error-channel cleanup. DisplayErrorToConsole was reading m_ShellCommandError directly, decoupled from the dispatcher's scpi.sce state — a built-in could set scpi.sce = success after printing its own error to suppress the generic follow-on, and the generic message would still fire. Switched to scpi.sce, cleaning up bc/dc double-print noise. RunExternalCommand's PATH-exhausted path restored to return cmdnotfound instead of generic failure.
Tests. 42 new assertions in test_bc_matrix.cshw + a new test_python_interop.cshw suite documenting the Python shell-out pattern for floating-point linear algebra (skipped cleanly when no Python is present). Full suite: 79 / 79.
v1.0.6.3-alpha — What changed
bc -c — complex-number arithmetic. Opt-in via --complex. The constructor and accessors are lowercase functions because BCL's base-36 number lexer eats I as the digit value 18: use cplx(re, im) to construct, re(z) / im(z) to extract parts, conj(z) for the conjugate, abs(z) for the magnitude. All four arithmetic operators (+ - * /) work, with mixed real/complex lifting automatically. sqrt(cplx(-4, 0)) returns 2i. Output is the natural a+bi form with zero-terms dropped (5i, 3+i, 3-4i). Equality (== !=) is structural; ordering (< > <= >=) raises a runtime error since complex numbers have no total order. Composes with -x.
bc ^ precision at low scale. Pre-1.0.6.3 cshw rounded intermediate ^ multiplications at the active scale, which silently mangled compound-interest math: bc "scale=2; 10000 * (1.05)^30" returned 43200.00, off by $19.42 from the correct 43219.42… over 30 years. Now BclValue::pow boosts the internal scale to scale_a * |b| around the BCL call so the value is full-precision; users still trim for display with r / 1. The fix flows through to dc's ^ too.
POSIX dc gaps closed. The conditional-macro operators (<R, >R, =R, plus the negated !<R, !>R, !=R) had the comparison direction REVERSED from POSIX/GNU dc — cshw's old <r fired when next-to-top < top; POSIX says fire when top < next-to-top. The textbook recursive factorial [d 1- d 1<f *]sf silently produced wrong results (5! came out as 20 instead of 120). Fixed. Also added the POSIX register-array operators :R (store at index) and ;R (load at index), with sparse storage and unset cells reading as 0.
Chapter 12 draft. book/Chapter_bc_dc.md shipped as a draft: quick-taste hook, @ vs bc motivation, bc tour, bc-as-language, compound-interest (rewritten now that ^ is fixed), bc -x exact tier, bc -c complex tier, dc tour, picking-the-right-tool table, honest limits. Examples spot-checked against the live binary.
v1.0.6.2-alpha — What changed
bc -x — the exact-arithmetic tier. Opt-in via --exact. Integer literals become Rational(n, 1) at parse time; rational arithmetic preserves p/q in lowest terms (auto-reduced via Euclidean gcd); sqrt carries as Power(base, exp) symbolically. So 1/3 + 1/6 = 1/2 (not .4999…), 5/15 = 1/3 (auto-reduced), (1/2)^2 = 1/4, 2^10 = 1024, sqrt(2) * sqrt(2) = 2. Anything that can't stay exact (sum of unlike radicals, transcendentals, etc.) falls through to BCL's scaled-decimal — the contract is "exact when possible," not "always exact." Variables, function bodies, and the REPL all preserve exact form. Non-exact bc behavior is byte-identical to 1.0.6.1.
v1.0.6.1-alpha — What changed
Stability fixes. Five real bugs that surfaced under heavier coroutine + scripting load: a heap-corruption in the history deque from concurrent push_backs by worker threads (fixed with a recursive_mutex + an early-return so coroutine threads don't touch interactive history at all, matching bash/zsh/tcsh); a kill -15 gap where pure console processes (no top-level window) didn't terminate (added a CTRL_C_EVENT broadcast via AttachConsole fallback); a lexer bug splitting .foo1 into . + foo1 so redirects like sed … > .foo1 opened the current directory for writing instead of the dotfile; the dispatcher's m_scpi data race between worker threads and main thread that occasionally leaked one command's -help into a sibling command's dispatch (fixed by hoisting to static thread_local); and a cowait timeout flake under full-suite load (same race as the help-leak).
Settings cascade. A per-key resolver: %APPDATA%\cshw\settings.csh > HKCU\Software\Tropibyte\cshw > HKLM\Software\Tropibyte\cshw > built-in default. Power users own the .csh file; IT can deploy machine-wide defaults via Group Policy under HKLM; users override per-machine. Known keys: history_max, pipemode, bcscale, atfloatprec, texteditor.
v1.0.6.0-alpha — What changed
bc — the full POSIX bc language. Not a "calls out to bc.exe" wrapper — an actual hand-written lexer / parser / tree-walking interpreter, with Gavin Howard's BCL (BSD 2-clause) embedded as a static library for the arbitrary-precision math backend. The language surface includes scalars, sparse arrays, scoped functions with auto locals and recursion, if/else, while, for, break/continue, the eight assignment operators (= += -= *= /= %= ^=) with right-associative chaining, pre/post increment/decrement, print with C-style string escapes, and quit/halt. Default scale is 20; the user can override per-statement.
The standard math library loads automatically — Gavin's lib.bc verbatim (e, l, s, c, a, j: exp, natural log, sin, cos, arctan, Bessel of the first kind), plus a cshw-side alias layer giving the friendly names users actually remember: sin, cos, tan, exp, ln, log, log10, log2, atan, atan2(y,x), pi(). No -l flag required.
dc — bc's reverse-Polish sibling. Stack VM, single-character commands, same arbitrary-precision math backend. Full POSIX surface: arithmetic (+ - * / % ^ v), stack ops (c d r z), prints (p n f), registers (sR lR), macros ([body] x), conditional macro execution (<R >R =R + negations), scale/base controls (k K i I o O), and base-aware output. The conditional-macro direction got a POSIX-correctness fix in 1.0.6.3 — pre-1.0.6.3, the comparison was reversed.
200 test assertions cover the entire surface: 101 for bc (arithmetic + precedence + associativity, control flow, recursion, math library, error paths, CLI), 51 for dc (the full command vocabulary including the canonical recursive-macro factorial), plus the 48-assertion @ suite from 1.0.5 still green. Two parser bugs surfaced while writing the suites and were fixed: bc's unary minus precedence (so -2^2 is now -4, matching POSIX) and dc's digit set (narrowed to A-F so single-letter commands K/I/O/Q aren't eaten as numbers).
v1.0.5.0-alpha — What changed
@ now does floating-point. The arithmetic evaluator behind @ was integer-only across the 1.0.x line — bit ops, shifts and integer division like the C-shell tradition expects. 1.0.5 keeps that surface intact (a % b stays integer, 10 / 3 still truncates to 3) but adds a parallel double path: a float literal (1.5, 2.5e-3) or a math primitive promotes the whole expression to floating point. @ x = 7.0 / 2 now gives 3.5, not 3. Bitwise ops, modulo and shifts remain integer-only by design — coerce inputs at the call site if you need them.
Math primitives. Function-call syntax (name(arg [, arg ...])) joins the expression grammar. 24 primitives plug in directly from <cmath>:
trig (sin cos tan, asin acos atan, atan2(y,x)),
hyperbolic (sinh cosh tanh),
logs and exp (log ≈ ln, log10 log2 exp),
powers (sqrt cbrt pow(b,e) hypot(a,b), plus root(x,n) as the nth-root sugar for pow(x, 1/n) — so root(256, 4) == 4),
rounding (floor ceil round trunc — these return integer because that's what the user means — and fmod(a,b) for floating remainder), and
a small misc set (abs sign min max) that preserves integer-ness when all inputs are integer.
Constants. pi, e, and tau resolve as bare names with full IEEE-754 precision. They aren't shell variables — can't be shadowed, can't be unset, no surprises.
Float formatting. Doubles render with %.15g: enough precision to preserve the value through a round-trip, but trailing zeros stripped (no more 0.500000 for 0.5). Whole-valued floats keep a trailing .0 so the type signal isn't lost — sin(pi/2) shows as 1.0, not 1. NaN, ±Inf, and signed zero spell themselves out.
v1.0.4.5-alpha — What changed
chmod — real ACLs, not just the read-only bit. Symbolic chmod +w / chmod -w still flip the NTFS read-only attribute (Tier 1, what most Windows tools mean by "chmod"). Octal modes — chmod 644, chmod 750, chmod 444 — now do the real thing: cshw rebuilds the file’s DACL with three explicit ACEs (owner / primary group / Everyone) sized from the octal triplets, strips inheritance with PROTECTED_DACL_SECURITY_INFORMATION, and writes it back via SetNamedSecurityInfoW. icacls confirms the round-trip. The semantics are as faithful as Windows ACLs can express: chmod 750 on Windows really is owner-modify + group-RX + nobody-else.
Unix → Windows path map. Long-standing csh muscle memory like cd /tmp, cd /home/$USER, cp x /mnt/c/temp, or which gcc /usr/local/bin/gcc now resolves transparently, with no $1/(): Event not found-style detours. Paths get rewritten before the lexer can mistake /X for a switch. Defaults ship with /tmp → %TEMP%, /home/$USER → %USERPROFILE%, /mnt/c → C:, /usr/local/bin → first-of (%LOCALAPPDATA%\Programs, C:\Program Files, C:\Program Files (x86)), /etc → C:\ProgramData, and a few more.
The map is yours. A new pathmap builtin manages it interactively: pathmap list, pathmap add /opt "D:\opt", pathmap del /opt, pathmap clear. In-memory by default; pathmap write /opt "D:\opt" adds an entry and appends to the persistent file, pathmap save flushes everything, pathmap reload re-sources it. pathmap edit opens the file in $texteditor (falls through to $EDITOR, then $VISUAL, then notepad), and pathmap path prints where it lives. Persistence file: %APPDATA%\cshw\pathmap.csh (user) or the shipped pathmap.csh next to cshw.exe if the user copy is absent — same source-on-startup model as cshrc.
v1.0.4.4-alpha — What changed
tcsh filename modifiers. $path:h (dirname), $path:t (basename), $path:r (root, strip extension), $path:e (extension only), plus :q :u :l, and they chain ($p:h:t). cshw didn’t recognize any of them before this release — $filepath:t literally returned the string "$filepath:t", and any script walking up a path with :h per iteration looped forever. YottaDB’s remove_port.csh was a textbook example.
Paren-context array assignment. set arr = (`cmd`) now produces an N-element array whose elements are the whitespace-separated words of the command’s output — the canonical csh "array from output" form. Previously the parens were silently discarded at lex time and the whole capture became a single scalar, so the Rosetta Code Sieve of Eratosthenes (initialized via set prime = (`repeat $N echo 1`)) emitted every integer as "prime" because every cell looked truthy. Now it emits real primes.
Real-world script audit. 67 csh scripts pulled from EDA tools (alliance, cvfpu, v2k-top), neuroscience (FreeSurfer), climate sim (NCAR CM1, ROMS, CMAQ), genomics (UCSC Kent, surpi), particle physics (sPHENIX), and packaging (mamba, TBB) drove this release’s fixes. 35 of the 67 run cleanly on cshw; the rest are mostly env-dependent (missing perl, cvs, etc.) rather than cshw bugs.
v1.0.4.3-alpha — What changed
retshell / retproc / return triad. Three new builtins for clean control-flow:
retshell [N] exits a sourced script (or cshw script.csh subshell) with status N without terminating the calling interactive shell — the precision tool for the cshrc / sourced-setup workflow.
retproc [VALUE] always pops one procedure frame, publishing $result.
return [N] is the smart variant: pops a proc if you’re in one, otherwise behaves as retshell (matches bash ergonomics without colliding with cshw’s existing proc-return path). exit still terminates the whole shell when you want that.
v1.0.4.2-alpha — What changed
Real-world csh script compatibility, round one. Seven parser / lexer / dispatcher fixes after running cshw against the Burkardt csh examples and a dvtalk gist:
@ var += val compound assignment (lexer split the operator);
foreach x (`cmd`) backtick value lists (parser stored backticks verbatim);
"\!" double-quoted history escape;
$argv populated from script CLI args (was only $1/$2/...);
ls -1 and other -<digit> short flags (the dash pre-pass only rejoined alpha flags);
backtick capture of a child cshw (handle inheritance + UTF-16LE auto-detect);
and multi-line cshw -c '...' with foreach/while spanning newlines.
A further round (set NAME with no value, unset A B C, while($cond) / if($cond) tight-paren forms, foreach (${ARR}) per-element expansion, $?VAR / $#VAR in if expressions, real shift implementation, indexed set arr[N] = X with variable indices, inline if (cond) cmd, egrep / fgrep aliases, GNU tar cvzf form, and kill -15 / -TERM signal flags) landed alongside.
v1.0.4.1-alpha — What changed
Text built-ins now read external pipe input. Commands like tasklist | head -5, netstat | grep LISTEN, and cmd /c dir | sort silently produced zero output before this fix — the line reader expected cshw's internal UTF-16LE pipe format and gave up on raw ANSI bytes from external commands. The new slurp-and-decode path auto-detects either form. Affects head, tail, awk, sed, sort, uniq, cut, rev, and genai. A regression suite (ten new tests across cmd /c "echo …" piped into each builtin) was added so this stays fixed.
Bigger pipeline buffer. The sequential-pipeline buffer grew from 20 MiB to 64 MiB. Long log files, deep find output, and verbose netstat -an dumps no longer get clipped mid-pipe.
v1.0.4-alpha — What changed
Heredocs. The classic command << DELIM form is in. In a script the body is the lines up to the delimiter; at the interactive prompt a modal editor — with cut/copy/paste and load-from-file — collects it. Either way it’s fed to the command as standard input.
New file built-ins. readfile and writefile move a file’s contents in and out of a shell variable. fileblob and unfileblob encode any file as a single line of text and back — useful for embedding a binary in a script or sending it through a text-only channel.
Fixes & tuning. Single-quoted arguments passed to a procedure are no longer variable-expanded inside the procedure’s scope. The pipeline buffer grew from 1 MiB to 20 MiB, so large command output no longer gets clipped mid-pipe.
v1.0.3-alpha — What changed
One self-contained binary. cshw now links the C/C++ runtime and every third-party library (PCRE2, zlib, libzip, bzip2) statically. The installer drops a single cshw.exe with no DLLs beside it and no Visual C++ Redistributable to install first — the prerequisite that tripped up early testers is gone.
New built-ins: the Unix utility set. basename, dirname, realpath, and splitpath for path surgery; printf for C-style formatted output; test (and its [ alias) for conditional expressions; and xargs for turning input into command-line arguments. Each ships with a man page.
Fixes. An intermittent crash during coroutine teardown — a worker thread could be freed while it was still finishing — is resolved. And cshw -c no longer drops double-quoted arguments, so chained one-liners like cshw -c 'test -f x && echo "found it"' behave correctly.
v1.0.2-alpha — What changed
In-line cursor editing. The prompt-line editor now has a real cursor. ←/→ move within the line. Home/End jump to the ends. Delete forward-deletes. Backspace works mid-line. Typed characters insert at the cursor (or overwrite, see below). Previously you could only edit by appending or backspacing from the end — an alpha-day oversight surfaced by a user’s very first feedback.
Insert key toggles overwrite. Press Insert to flip between insert mode (the default) and overwrite mode (typed chars replace the char under the cursor without changing line length). Press again to flip back.
↑/↓ history polish. If you start typing a command, then press ↑ to look at history, pressing ↓ past the most-recent entry now restores what you were typing rather than clearing the line. Matches bash/zsh behavior.
v1.0.1-alpha — What changed
New: bugreport command. Type bugreport at the prompt and a small dialog opens to gather a subject and details; click Compose and your default mail client opens with everything pre-filled (cshw version, Windows version, last shell error). Review and click Send. Or skip the dialog: bugreport "summary" "details" goes straight to the composer.
Version display fix. The version and ver commands were reporting a stale version string from a shadow define in the Visual Studio resource header. The reported version now matches the binary’s file resource (1.0.1).