Files
takana/crates
SergioandClaude Opus 5 ae6f0b45d9 qillqa: el awk propio — 3531 líneas, sólo libc, y CERO divergencias contra dos oráculos
«awk soberano» (usuario, 2026-09-22), que era la tercera opción del ADR pendiente
y la única que no adoptaba la semántica de otro: gawk es C con extensiones GNU,
goawk es Go y rompe la premisa de cadena de la Etapa C, frawk es otro dialecto.

Banco diferencial contra DOS oráculos a la vez —el awk de busybox 1.36.1 (el
applet que hoy viaja) y gawk 5.3.2 --posix— con 109 casos: campos y separadores,
el modelo de valores, aritmética, expresiones regulares, las funciones de cadena,
printf, control de flujo, arrays, funciones de usuario, E/S y los rincones del
parser. Resultado: 104 iguales a los dos, 0 divergencias, y 5 casos donde los
ORÁCULOS discrepan entre sí — que es justo para lo que sirve tener dos.

De esos 5, cuatro los tenemos del lado correcto por POSIX: `2^3^2` es 512 (la
potencia asocia a la derecha; busybox da 64), `index(s,"")` es 1, el `%*d` de
printf existe, y `length(array)` funciona. El quinto era nuestro y se arregló:
una coincidencia VACÍA pegada al final de la anterior no sustituye, así que
`gsub(/a*/,"-")` sobre "xax" da 3 y `-x-x-`, no 4 y `-x--x-`.

El motor de expresiones regulares es propio y esa es la razón de fondo para no
adoptar un crate: POSIX es leftmost-LONGEST y la familia Perl —el crate `regex`
en su modo por defecto— es leftmost-first. Para /a|ab/ sobre "ab", POSIX devuelve
`ab` y Perl devuelve `a`. En un awk eso decide qué borra un sub(), dónde parte un
split() y cuánto valen RSTART y RLENGTH. Construcción de Thompson con conjunto de
hilos: sin retroceso, así que `(a*)*b` contra sesenta `a` no explota.

Las cinco cosas que el banco destapó, todas dando resultados plausibles y ninguna
reventando —quedan como pruebas de regresión en tests/divergencias_medidas.rs:

  · leer NF no forzaba el partido en campos ⇒ `{print NF}` daba 0 hasta que
    alguien tocara un campo. El partido es perezoso a propósito (es lo que hace
    barato asignar a $0) y el precio es acordarse de forzarlo.
  · `length` sin paréntesis se leía como una VARIABLE llamada length, que vale
    vacío. Es el único builtin al que POSIX permite omitirlos.
  · los arrays se pasan por referencia, y eso se decide mirando si la función usa
    el parámetro como array — `a["k"]=1` tiene el nombre en el LUGAR de la
    asignación, y sólo se miraba el valor.
  · substr con inicio ≤ 0 recorta a 1 SIN ajustar el largo, y los no enteros se
    truncan. La lectura estricta de POSIX daría otra cosa; ni busybox ni gawk la
    hacen, y lo que hay que ejecutar son los guiones escritos contra ellos.
  · la regla del vacío en gsub, arriba.

Verificado además contra este repo: de los 61 programas awk únicos que usan sus
guiones y recetas, qillqa acepta los 59 reales (los 2 restantes son f-strings de
Python que mi extractor tomó por awk). 29 pruebas propias en verde.

El nombre es quechua («escritura») y sigue el precedente de simi: lo registra el
comentario de cabecera y lo DECIDE un ADR. El comando instalado será `awk` — eso
es contrato y lo llaman los configure de medio corpus.

⚠ Lo medido es el build NATIVO del hub. Falta la receta, el estático musl con zig
cc, y la prueba que de verdad decide: un `configure` de autotools con qillqa como
/usr/bin/awk. Es la lección de brush — pasó 56/57 casos POSIX y no construía una
sola receta.

Va también recipes/ncurses-tools.toml (clear, reset, tput, tset, infocmp, tic),
declarada en `base`: la canónica instala sólo lib y cabeceras, así que clear y
reset en una imagen eran el applet de busybox. Instala los binarios y NO la base
terminfo: resuelven con los --with-fallbacks compilados en la librería, que
cubren la consola del metal, QEMU y cualquier ssh moderno.

⚠ Y ncurses-tools selló DINÁMICO dos veces antes de salir bien: ncurses usa
`-static`/`-dynamic` como MARCADORES de tramo alrededor de las librerías —su
forma portable de -Wl,-Bstatic … -Wl,-Bdynamic—, no como decisión global. El
`-dynamic` llega al final de la línea de enlace y gana por orden. Se quita
sobreescribiendo LIBS_TIC y LIBS_TINFO en la línea de make. Tercer sabor del
agujero que documenta scripts/static-audit.sh.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 03:48:25 +00:00
..