# Progreso ## Estado actual - **Fase 2**: buffer dinámico. La Fase 1 está cerrada en Fedora, pero falta probarla en Windows. - 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`). - Entorno: Fedora 42 nativo (gcc 15.2, clang 20, make 4.4, gdb 17, valgrind 3.26) y Windows con MSYS2 UCRT64. **Próxima sesión en Windows** (2026-10-05). ### Al llegar a Windows 1. `git pull` desde la terminal UCRT64 de MSYS2. 2. Comprobar que están las herramientas: `gcc --version`, `make --version`, `gdb --version`. Si falta algo: `pacman -S mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-gdb make`. 3. Cerrar la Fase 1 en Windows: `make` debe generar `build/hello.exe`. El Makefile todavía no añade `.exe` (falta el `ifeq ($(OS),Windows_NT)` de `docs/06-make.md`). Ojo: `mkdir -p` y `rm -rf` solo funcionan en la shell de MSYS2, no en `cmd` ni en PowerShell. 4. VS Code: `.vscode/launch.json` y `c_cpp_properties.json` ya tienen la configuración de Windows (`C:/msys64/ucrt64/bin/...`). Comprobar que la ruta de MSYS2 es esa. 5. Valgrind no existe en Windows. La parte portable se sigue validando en Fedora. En Windows se puede seguir avanzando con el 2.3b. ## 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. ## Pendiente / puntos débiles - Fase 1: probar el Makefile en Windows (MSYS2), con el sufijo `.exe`. - `.gitignore` creado. Siguen versionados `emulator/escpos-emu.exe` y `goruntime/goruntime.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. - 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.