Files
foxbin2prg/CLAUDE.md
Marius Mutu f36a26a9c6 Adauga write-back text->binar VFP: txt2vcx.ps1 + vfp_filemap.ps1 + test_roundtrip.ps1
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>
2026-07-09 18:30:21 +03:00

11 KiB

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 origingit checkout master && git merge --ff-only origin/mastergit checkout romfast && git merge mastergit 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.
# 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):

& '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):

& '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).

* 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.