134 lines
6.9 KiB
Markdown
134 lines
6.9 KiB
Markdown
# Progreso
|
|
|
|
## Estado actual
|
|
|
|
- **Fase 2**: buffer dinámico. La Fase 1 está cerrada en Fedora y en Windows
|
|
(2026-10-05).
|
|
- 2026-10-06 (Fedora): antes del 2.3b, repaso de punteros. Le costaba qué
|
|
viaja a una función, `*` frente a `->`, la pila frente al montón y restar en
|
|
hex. Se creó `docs/02-pointers-visual.html` (interactivo). Pendiente de que
|
|
conteste: A) por qué `&buffer_a - &buffer` da 4; B) cuántos bytes copia su
|
|
`append` actual con `data_b`.
|
|
- Paso actual: 2.3b. `hello.c` ya usa bien `goto cleanup` (punteros a `NULL`
|
|
uno por línea, `result`, un solo `return`), sin avisos con gcc ni clang, y
|
|
Valgrind limpio. Falta `escpos_buffer_append`: el parámetro con la cantidad,
|
|
`const`, reservar `len + cantidad`, `memcpy` y el comentario de la cabecera.
|
|
Ahora copia 1 byte (`sizeof *byte`).
|
|
- Máquinas: sobremesa con Windows (MSYS2 UCRT64) y portátil con Fedora 42
|
|
(gcc 15.2, clang 20, make 4.4, gdb 17, valgrind 3.26). Ver "Pendiente por
|
|
máquina".
|
|
|
|
## Pendiente por máquina
|
|
|
|
### Windows (sobremesa)
|
|
|
|
- Hay gcc, gdb y make en `C:\msys64`. Faltan clang y `xxd` (opcionales:
|
|
`pacman -S mingw-w64-ucrt-x86_64-clang vim`; mientras, `hexdump -C`).
|
|
- Fase 1 cerrada: `make`, `make run` y `Nothing to be done` funcionan sin
|
|
`EXE` gracias a la emulación de `.exe` de MSYS2 (ver docs/06-make.md). El
|
|
`ifeq ($(OS),Windows_NT)` se pospone a la Fase 4, cuando haga falta
|
|
`-lws2_32`.
|
|
- Probar en VS Code: terminal nueva (debe abrir UCRT64), Ctrl+Shift+B y F5.
|
|
- El 2.3b se puede avanzar aquí; la comprobación de memoria queda para Fedora.
|
|
|
|
### Fedora (portátil)
|
|
|
|
- Validar con valgrind el 2.3b cuando esté hecho (y con ASan/UBSan antes de
|
|
cerrar la Fase 2).
|
|
- Tras el `git pull` del 2026-10-05, comprobar que `make` y F5 siguen igual
|
|
(se ha tocado `.vscode/` y se han añadido `.gitattributes` y `.gitignore`).
|
|
Los binarios de Go ya no se versionan: recompilarlos con `go build` si hacen
|
|
falta.
|
|
|
|
## Hecho
|
|
|
|
- `include/escpos.h` + `src/escpos.c` con `escpos_version()`, y `hello.c` que
|
|
la usa. Compila y enlaza a mano en Windows y en Fedora.
|
|
- `samples/hello_world.bin`: ESC @, texto, LF, ESC d 5, GS V 0.
|
|
- Emulador ESC/POS en Go (`emulator/`) para probar sin gastar papel.
|
|
- Makefile con regla patrón, `clean` y `.PHONY`. Compila desde un clon limpio y
|
|
sin avisos con gcc y con clang.
|
|
- 2.1: `escpos_buffer_new` / `escpos_buffer_free` con tipo opaco. Valgrind
|
|
limpio, y fuga provocada a propósito para leer el informe.
|
|
- 2.2: `escpos_buffer_append_byte` con `realloc`: 64 bytes al principio, luego
|
|
el doble. Comprobado con 100 bytes (crece de 64 a 128). Valgrind limpio.
|
|
Sin el `free`, Valgrind da 24 `definitely` + 128 `indirectly`.
|
|
- 2.3a: crecimiento extraído a `static int buffer_reserve(buffer, min_cap)`:
|
|
arranca en 64 o en `cap` y dobla hasta que cabe; un único `realloc`.
|
|
|
|
## Conceptos de C aprendidos
|
|
|
|
- Etapas de compilación, unidades de traducción, cabeceras, *include guards*,
|
|
`static` para encapsular, `nm` y errores del enlazador.
|
|
- Cadenas terminadas en `'\0'`, `const char *`, `'A'` frente a `"A"`.
|
|
- Memoria virtual de un proceso, modo usuario y modo núcleo. `VmSize` frente a
|
|
`VmRSS`, *overcommit* y OOM killer.
|
|
- Make: reglas, dependencias por fechas, variables, regla patrón con
|
|
`$@ $< $^`, `.PHONY`.
|
|
- Pila y montón, `malloc`/`free`/`realloc`, `NULL`, propiedad de punteros,
|
|
tipo opaco, `typedef`, `->`, `uint8_t`/`size_t`, qué tipo usar.
|
|
- Liberar en caminos de error sin `defer`: patrón `goto cleanup`.
|
|
- Depuración: *segfault* (139), `free(): invalid pointer` (134), gdb básico,
|
|
y leer errores e informes de fugas en Valgrind.
|
|
|
|
## Forma de trabajar
|
|
|
|
- Desde el 2026-10-02: sin *vibecoding*. Enunciado y pruebas, predicción antes
|
|
de compilar, y pistas por niveles solo si las pide. Ante un error, primero su
|
|
diagnóstico.
|
|
|
|
## Decisiones de diseño
|
|
|
|
- Prefijo `escpos_` para toda la API pública.
|
|
- `escpos_buffer` es un tipo opaco: declarado en `escpos.h` y definido en
|
|
`src/buffer.c`. Campos `uint8_t *data`, `size_t len` y `size_t cap`.
|
|
- Crecimiento del buffer: 64 bytes al principio y luego el doble.
|
|
- Por ahora, las funciones que pueden fallar devuelven `int`: `0` si va bien y
|
|
`-1` si no hay memoria. Pendiente de cambiar a códigos de error propios.
|
|
- Estilo: nombres en `snake_case` y llave de apertura en línea aparte (estilo
|
|
Allman) en funciones, structs y bloques.
|
|
- Lo generado va en `build/`, que se crea en las recetas con `mkdir -p` y no se
|
|
versiona. Tampoco se versionan ejecutables ni volcados (`vgcore.*`).
|
|
- Dos máquinas transparentes: `.gitattributes` fuerza LF en todo y marca
|
|
`*.bin` como binario (git no toca los bytes ESC/POS). En Windows, VS Code usa
|
|
la shell UCRT64 de MSYS2 para la terminal y las tareas, así que `make`,
|
|
`mkdir -p` y `rm -rf` funcionan igual que en Fedora.
|
|
|
|
## Pendiente / puntos débiles
|
|
|
|
- Fase 1: probar el Makefile en Windows (MSYS2), con el sufijo `.exe`.
|
|
- Make: le costó entender que va hacia atrás desde el objetivo y que una regla
|
|
patrón es una plantilla. Repasar con `docs/06-make.md`.
|
|
- Punteros: le cuesta saber cuándo hace falta `*` y cuándo no, y distinguir la
|
|
dirección del bloque (`data`) de una casilla (`data[i]`). Le funciona la
|
|
analogía de papel y casa. Reforzar con ejemplos de su propio código.
|
|
- Tipos: usó `uint8_t` para un código de retorno. Repasar la tabla "Qué tipo
|
|
usar" de `docs/08-structs.md`.
|
|
- Valorar añadir `-Wconversion` a `CFLAGS`: detecta conversiones con pérdida
|
|
que gcc no avisa por defecto.
|
|
- Bucles: en `buffer_reserve` calculaba cada vuelta a partir de un valor que no
|
|
cambiaba (`buffer->cap`) o que empezaba en 0, y eso daba bucles infinitos.
|
|
Lo resolvió siguiendo los valores vuelta a vuelta. Seguir pidiéndole trazas
|
|
a mano.
|
|
- Declaraciones múltiples: escribió `escpos_buffer *a, *b, *c = NULL;` creyendo
|
|
que las tres valían `NULL` (solo la última). Lo detectó clang con
|
|
`-Wsometimes-uninitialized`. Ahora declara una variable por línea.
|
|
- Variables locales sin inicializar: creía que valían `NULL` como en Go.
|
|
- `sizeof`: el 2026-10-06 dijo que `sizeof buffer` (un puntero) da 1 byte; da
|
|
8 en 64 bits. Y lo veía como algo que "va a la casa" mientras se ejecuta,
|
|
cuando se calcula al compilar a partir del tipo.
|
|
- Hexadecimal: no sabe restar direcciones (`0xd210 - 0xd1f0`). Se le enseñó
|
|
a hacerlo con `p` en gdb y con las potencias de 16. Pide ayuda con
|
|
"ni idea": darle herramientas para medir, no la cuenta hecha.
|
|
- Se salta la predicción: el 2026-10-06 miró gdb sin predecir tres veces
|
|
seguidas. Insistir en que la escriba antes de ejecutar.
|
|
- Impresoras físicas: sin registrar marca y modelo.
|
|
- Confunde puntero colgante ("se pierde") con fuga. Tampoco tenía claro por qué
|
|
el slice viejo es seguro en Go tras `append` (el GC no libera el array viejo,
|
|
no es por la copia). Repasar con la tabla de docs/07-dynamic-memory.md.
|
|
|
|
## Otros
|
|
|
|
- `goescpos/`: equivalente en Go idiomático (`bytes.Buffer`) de lo hecho hasta
|
|
ahora, para comparar.
|