Fluxul complet bin->text->edit->bin pentru .vcx/.scx (faza 1; .mnx/.frx raman read-only): regenerare+compilare in staging unic per rulare, guard-uri (COMUN cu -AllowComun, staleness, binar lipsa, folder foxbin2prg), fidelity check pe octeti inainte de orice copiere, copiere .vct->.vcx cu restaurare la esec partial, refresh cache. Harta de extensii extrasa in vfp_filemap.ps1, dot-sourced si de vcx2txt.ps1 (comportament identic). Invoke-FoxBin2PrgSafe: wrapper cu timeout+taskkill pentru toate invocarile exe-ului - la text stricat Prg2Bin intoarce ErrorLevel 0 dar binarul corupt poate ridica MessageBox modal VFP nesuprimabil la reconversie. test_roundtrip.ps1: faze fidelitate/editare/smoke siblings/negativ+guard-uri, 41 PASS pe ROAGEST + smoke ROAIMOB/ROAACNPRO. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
131 lines
11 KiB
Markdown
131 lines
11 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## What this is
|
|
|
|
A local shared copy of **FoxBin2Prg** (the VFPX tool by Fernando D. Bozzo, maintained by Lutz Scheffler): a Visual FoxPro 9 program that converts VFP binary files to PRG-style text and back. Supported conversions: `PJX↔PJ2`, `SCX↔SC2`, `VCX↔VC2`, `FRX↔FR2`, `LBX↔LB2`, `DBC↔DC2`, `DBF↔DB2`, `MNX↔MN2`.
|
|
|
|
This directory is a git clone with two remotes:
|
|
|
|
- **`origin`** = `https://github.com/fdbozzo/foxbin2prg.git` (upstream, read-only). `master` tracks `origin/master` and stays a pristine mirror.
|
|
- **`romfast`** = `git@gitea.romfast.ro:romfast/foxbin2prg.git` (our fork on Gitea, SSH). Working branch **`romfast`** (default on Gitea) = upstream `master` + the ROA additions committed (`vcx2txt.ps1`, `PROMPT_cautare_vfp.md`, `CLAUDE.md`, `git_svn_parallel_init_prompt.md`). The pre-git local state is kept on branch `local-snapshot-v1.21.04`.
|
|
|
|
Update flow (sync fork from upstream): `git fetch origin` → `git checkout master && git merge --ff-only origin/master` → `git checkout romfast && git merge master` → `git push romfast romfast master`. After any update, regenerate binaries/EXE in VFP9 with `DO ReCreate_FoxBin2Prg.prg` (an error about `TESTS\FXUResults.db2` is expected). Text caches live outside this folder (`D:\ROA\_vfp_textcache\`, see below) so `ReCreate` never touches them; compiled binaries are kept out of git via the upstream `.gitignore` plus `.git/info/exclude` (which also still ignores any stray local `_textcache*`).
|
|
|
|
It serves two purposes:
|
|
|
|
1. Upstream tool source (for occasional patches to FoxBin2Prg itself).
|
|
2. A **shared search tool for the ROA VFP projects** (`D:\ROA\ROAGEST`, `D:\ROA\ROAIMOB`, `D:\ROA\ROAACNPRO`, …) via the local additions below.
|
|
|
|
## Local additions (ROA-specific, not part of upstream)
|
|
|
|
- **`vcx2txt.ps1`** — PowerShell script that converts the VFP binaries of a project (read from its `.pjx`) into text under a cache folder, so the code inside `.vcx/.scx/.frx/.mnx/.dbc` binaries becomes greppable. Incremental (skips up-to-date files), does not need the VFP IDE open (uses the compiled `FoxBin2Prg.EXE`).
|
|
- **`txt2vcx.ps1`** — the write-back counterpart: regenerates `.vcx/.scx` binaries from edited `.vc2/.sc2` cache text and copies them back into the project (see "Golden rule" below for scope/limits).
|
|
- **`vfp_filemap.ps1`** — shared bin↔memo↔text extension map (`.vcx`/`.vct`/`.vc2`, `.scx`/`.sct`/`.sc2`, …), dot-sourced by both `vcx2txt.ps1` and `txt2vcx.ps1` so the mapping stays in one place.
|
|
- **`test_roundtrip.ps1`** — standalone fidelity/regression test for the bin→text→bin→text roundtrip and for `txt2vcx.ps1`'s guard rails (staleness, COMUN, missing binary, negative/corrupt input, multi-file runs). See examples below.
|
|
- **Text caches** live **outside this folder**, under `D:\ROA\_vfp_textcache\` (one subfolder per project: `roacnpro`, `roagest`, `roaimob`) — per-project regenerable text caches. Safe to delete; never version them. **They must stay outside `foxbin2prg`**: `ReCreate_FoxBin2Prg.prg` does a recursive `Prg2Bin` over the whole tool folder (`get_FilesFromDirectory` recurses into every subfolder, foxbin2prg.prg:6135) and would reconvert any `.??2` under it back into stray binaries.
|
|
- **`PROMPT_cautare_vfp.md`** — reusable prompt (Romanian) explaining how to set up this search flow in any VFP project. Read it before working on VFP code search.
|
|
|
|
**Golden rule:** the text cache is for searching, and — for `.vcx`/`.scx` only — for making real code edits via `txt2vcx.ps1`. Caveats:
|
|
|
|
- The generated text format is **position-sensitive**: don't reformat or reflow lines when editing; preserve the exact line layout.
|
|
- Properties/methods are emitted **alphabetically sorted** — a newly added property must be inserted in alphabetical order, not appended.
|
|
- `.mnx`/`.frx` remain **read-only** (write-back not supported): menus still need GENMENU in the IDE to produce `.mpr`, and the `.frx` report format is too fragile for round-trip write-back. Edit those in the VFP IDE as before.
|
|
- Targets under `COMUN\` require `-AllowComun` **and** explicit approval — a change there affects every ROA app.
|
|
- **After any VFP IDE session** (even one that only opened a class/form), re-run `vcx2txt.ps1` to refresh the cache before editing text — otherwise `txt2vcx.ps1`'s staleness check will (correctly) refuse to write back over unseen IDE changes.
|
|
- **Encoding**: `.vc2`/`.sc2` files declare `CPID="1252"` in their header, but for ROAGEST at least the Romanian-diacritics bytes are actually **cp1250** (`0xE3`=ă, `0xBA`=ş, etc.) — the header lies. Don't decode/re-encode the text with a codepage inferred from the header; treat it byte-preserving (read/write/copy as raw bytes, compare on bytes) and this doesn't matter in practice — it only bites if a script tries to interpret the text as a specific codepage string.
|
|
- **Corrupt text can trigger a modal VFP dialog, not just a nonzero exit code**: if `.vc2`/`.sc2` text is malformed, `Prg2Bin` can return `ErrorLevel 0` while producing a corrupt binary — the real error only surfaces on a subsequent bin→text pass, sometimes as a **native VFP MessageBox that blocks headlessly** (not suppressible via parameters/`.cfg`). Any automated invocation of `FoxBin2Prg.EXE` must go through the `Invoke-FoxBin2PrgSafe` wrapper in `vfp_filemap.ps1` (default 60s timeout + `taskkill` on hang) rather than calling the exe directly — and treat the **fidelity check** (bin→text→compare), not the exe's `ErrorLevel`, as the real backstop against corrupt/malformed text.
|
|
|
|
```powershell
|
|
# Populate/refresh a project's text cache (incremental)
|
|
& 'D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1' -Project 'D:\ROA\ROAGEST\roagest.pjx' -ProjectRoot 'D:\ROA\ROAGEST' -CacheRoot 'D:\ROA\_vfp_textcache\roagest'
|
|
|
|
# Include reports/menus too: -Types vcx,scx,frx,mnx
|
|
# One-off conversion of a file/folder not in the project: -Source 'path\to\lib.vcx'
|
|
# Other flags: -Force (reconvert all), -Clean (wipe cache first)
|
|
```
|
|
|
|
Then search the cache with Grep (e.g. `PROCEDURE do_salvare`), citing `file:line` from the cache.
|
|
|
|
Write back an edited `.vc2`/`.sc2` (after reviewing the diff on text):
|
|
|
|
```powershell
|
|
& 'D:\ROA\UTIL\foxbin2prg\txt2vcx.ps1' -TextFile 'D:\ROA\_vfp_textcache\roagest\Clase\oavize.vc2' -ProjectRoot 'D:\ROA\ROAGEST' -CacheRoot 'D:\ROA\_vfp_textcache\roagest'
|
|
|
|
# Preview only, no files touched in the project: add -DryRun
|
|
# Target under COMUN\: add -AllowComun (needs approval)
|
|
# Skip the staleness check (IDE binary is known up to date some other way): -Force
|
|
# Skip the fidelity re-check after regen (not recommended): -NoVerify
|
|
```
|
|
|
|
Run the regression/fidelity test suite (no Pester, standalone):
|
|
|
|
```powershell
|
|
& 'D:\ROA\UTIL\foxbin2prg\test_roundtrip.ps1' -ProjectRoot 'D:\ROA\ROAGEST' -CacheRoot 'D:\ROA\_vfp_textcache\roagest' -Phase all
|
|
|
|
# Run a single phase: -Phase fidelity|edit|negative|smoke
|
|
```
|
|
|
|
## Commands
|
|
|
|
All FoxBin2Prg commands run inside VFP 9 (or via the compiled `FoxBin2Prg.EXE`).
|
|
|
|
```foxpro
|
|
* After clone/pull: regenerate all binaries from text and compile the EXEs.
|
|
* NEVER run foxbin2prg.prg directly for this — it uses a special config.
|
|
DO ReCreate_FoxBin2Prg.prg
|
|
|
|
* Convert a single file (direction inferred from extension)
|
|
DO FOXBIN2PRG.PRG WITH "<path>\file.scx" && binary -> text (.sc2)
|
|
DO FOXBIN2PRG.PRG WITH "<path>\file.sc2" && text -> binary (.scx)
|
|
|
|
* Convert a whole directory
|
|
DO FOXBIN2PRG.PRG WITH "<path>","Bin2Prg"
|
|
DO FOXBIN2PRG.PRG WITH "<path>","Prg2Bin"
|
|
|
|
* Config templates
|
|
DO FOXBIN2PRG.PRG WITH "-c","template.cfg" && default settings
|
|
DO FOXBIN2PRG.PRG WITH "-C","config.cfg" && active settings
|
|
DO FOXBIN2PRG.PRG WITH "-t","table.dbf.cfg" && per-table template
|
|
|
|
* Interactive help / option list
|
|
DO FOXBIN2PRG.PRG WITH "?"
|
|
```
|
|
|
|
### Tests
|
|
|
|
Unit tests live in `TESTS/` and use **FoxUnit** (path configured in `TESTS/foxunit_path.txt`). Files: `ut__foxbin2prg__<class>__<method>.prg` (unit) and `ft__foxbin2prg__<class>.prg` (functional). Run them from VFP via FoxUnit; test fixtures live in `TESTS/DATOS_READONLY/`.
|
|
|
|
## Architecture
|
|
|
|
Nearly everything is in one ~34,000-line file: **`foxbin2prg.prg`**. Key class hierarchy inside it:
|
|
|
|
- **`c_foxbin2prg` (As Session)** — entry point / public API. Parameter parsing, config resolution (`evaluateConfiguration`), file dispatch, progress UI, error logging. Also usable as COM-ish object (`CREATEOBJECT('c_foxbin2prg')`, `.execute(...)`), which is how the `.vbs` helpers and SCM integrations drive it.
|
|
- **`c_conversor_base`** — shared conversion logic (backup handling, timestamps, comment/property parsing, exclusion blocks).
|
|
- **`c_conversor_bin_a_prg`** and per-type subclasses (`c_conversor_vcx_a_prg`, `c_conversor_scx_a_prg`, `c_conversor_pjx_a_prg`, `c_conversor_dbf_a_prg`, …) — binary → text.
|
|
- **`c_conversor_prg_a_bin`** and per-type subclasses — text → binary.
|
|
- **`CL_*` model classes** (`CL_CLASE`, `CL_PROJECT`, `CL_DBC*`, `CL_DBF_*`, `CL_MENU*`, …) — object model the text files are parsed into / generated from.
|
|
- **`CL_CFG` / `CL_DBF_CFG`** — config file handling (`FOXBIN2PRG.CFG` with directory inheritance, per-table `.dbf.cfg`).
|
|
- **`CL_LANG`** — localization (EN/ES/FR/DE), auto-selected.
|
|
|
|
Supporting files: `foxbin2prg_keywords.dbf/.cdx` (VFP keyword table used during generation — has its own `.db2` text form), `props_*.txt` (per-control default property lists used to suppress default values in output), `Create_FoxBin2Prg.cfg` (the special self-conversion config), `Fb2P_Diff/` and `FileName_Caps/` (companion sub-projects, built by `ReCreate_FoxBin2Prg.prg`), `BuildProcess/` (VFPXDeployment build hooks), `ThorUpdater/` (Thor/VFPX release plumbing).
|
|
|
|
**Text format is position-sensitive:** the generated `.??2` files look like PRG/XML but are parsed line by line; structure and line layout must be preserved when editing them. Properties/methods are emitted alphabetically sorted.
|
|
|
|
## Upstream contribution conventions (from `.github/CONTRIBUTING.md`)
|
|
|
|
If patching FoxBin2Prg itself:
|
|
|
|
- Two version constants at the top of `foxbin2prg.prg`: bump only the minor part of `DC_FB2PRG_VERSION_REAL` (e.g. `'1.21.04'`); do **not** change `DN_FB2PRG_VERSION` (`1.21`) — it's written into every text file and forces mass recommits.
|
|
- Add the change to the history section at the top of `foxbin2prg.prg` and to `docs/ChangeLog.md`; update the version in `README.md`.
|
|
- Style: mixed-case keywords, tab indentation, spaces around operators and after list items; do not run BeautifyX with mDots insertion.
|
|
- After changes, regenerate text with `DO Create_FoxBin2Prg.prg` and compile in **VFP9 SP2**.
|
|
|
|
## Documentation
|
|
|
|
- `docs/FoxBin2Prg_Internals.md` — settings reference and internals (ZOrder, timestamps, class-per-file, DBF export hooks, API).
|
|
- `docs/FoxBin2Prg_Run.md` — full command-line/parameter reference.
|
|
- `docs/FoxBin2Prg_git.md`, `docs/FoxBin2Prg_SCM.md` — SCM integration.
|
|
- Spanish docs in `Documentacion/` are unmaintained.
|