# Căutare în codul din librăriile/formele VFP (`.vcx`/`.vct`, `.scx`/`.sct`, ...) Partajat între proiectele ROA* (companion narativ la `PROMPT_cautare_vfp.md` din acest folder — varianta "prompt de copiat" — acest fișier e ghidul de referință complet, cu exemple). Căutare de cod-sursă (proceduri, metode, parametri) care **nu** stă în `.prg`, ci în interiorul binarelor VFP: librării de clase (`.vcx`+`.vct`), forme (`.scx`+`.sct`), rapoarte (`.frx`+`.frt`), meniuri (`.mnx`+`.mnt`), baze de date (`.dbc`+`.dct`). ## De ce e nevoie de asta Un `.vcx` e o **tabelă DBF**: codul metodelor stă în câmpuri memo în `.vct`. `grep` direct pe `.vct` găsește textul dar ca binar (octeți `\0` între linii), fără numere de linie și greu de citit. Soluția: convertim binarul în reprezentarea lui **TEXT** (`.vc2`, `.sc2`, …) — PRG-style lizibil, metode sortate alfabetic — și căutăm în text cu `grep`/`Grep`. > **Regula de aur:** textul generat e **doar pentru citire/căutare**, CU O EXCEPȚIE: pentru > `.vcx`/`.scx` se poate și edita pe text, cu write-back în binar (`txt2vcx.ps1`) — vezi > `PROMPT_cautare_vfp.md` pasul 3 (ordine obligatorie, encoding, fidelity check). Pentru > `.frx`/`.mnx`/`.dbc` nu există write-back — modificările se fac tot în **IDE-ul VFP**. ## Unelte disponibile (verificate) | Unealtă | Cale | Rol | Recomandare | |---|---|---|---| | **FoxBin2Prg** | `D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE` | Binar VFP ⇄ text bidirecțional (`.vc2/.sc2/.fr2/.mn2/.dc2/.lb2`) | **De folosit.** Fidel, include corpul metodelor, parametri, comentarii | | vcx2prg | `D:\ROA\UTIL\vcx2prg\x2prg.prg` | Doar `.vcx` → `.prg` compilabil | Alternativă mai veche, doar clase, necesită IDE VFP deschis | | prgtovcx | `D:\ROA\UTIL\prgtovcx\prgtovcx.PRG` | Invers: `.prg` → `.vcx` | **Nu** pentru căutare (direcție opusă) | FoxBin2Prg e prima alegere: rulează din linia de comandă fără IDE deschis (EXE compilat), acoperă toate tipurile de container, text mai fidel decât vcx2prg. > Dacă `FoxBin2Prg.EXE` lipsește: deschide `D:\ROA\UTIL\foxbin2prg\foxbin2prg.pj2` în VFP 9 și > *Build > Build Executable*. Lângă EXE trebuie să existe `filename_caps.exe` și `props*.txt` > (deja în folder). ## Mod recomandat: scriptul `vcx2txt.ps1` `D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1` copiază binarul + memo-ul într-un **cache** care oglindește structura proiectului (nu murdărește arborele SVN), rulează FoxBin2Prg, păstrează doar textul. **Incremental** (sare peste ce e deja la zi). ```powershell # DOAR fișierele proiectului curent (recomandat, rapid) -> cache text propriu powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 ` -Project '\.pjx' -ProjectRoot '' ` -CacheRoot 'D:\ROA\_vfp_textcache\' # include și rapoartele (.frx) și meniurile (.mnx) powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 ` -Project '\.pjx' -ProjectRoot '' ` -CacheRoot 'D:\ROA\_vfp_textcache\' -Types vcx,scx,frx,mnx # conversie punctuală a unui fișier/folder (chiar dacă NU e în proiect, ex. o clasă din COMUN) powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source '\COMUN\clase\caut.vcx' # rebuild curat (șterge cache-ul întâi) / forțează reconversia powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 ` -Project '\.pjx' -ProjectRoot '' ` -CacheRoot 'D:\ROA\_vfp_textcache\' -Clean ``` Exemplu (ROAAUTO): ```powershell powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 ` -Project D:\ROA\ROAAUTO\roaauto.pjx -ProjectRoot D:\ROA\ROAAUTO ` -CacheRoot D:\ROA\_vfp_textcache\roaauto ``` > Cache-ul trebuie să stea **în afara** folderului `D:\ROA\UTIL\foxbin2prg`: `ReCreate_FoxBin2Prg.prg` > face `Prg2Bin` recursiv pe tot folderul uneltei și ar reconverti `.??2`-urile din cache în binare > rătăcite. Rezultatul ajunge în cache, cu aceeași structură de directoare ca proiectul (ex.: `roaauto\Clase\odevize.vc2`, `roaauto\comun\clase\_frm_base.vc2`). Apoi: ```bash grep -rn "PROCEDURE do_calcul_tarife" "D:\ROA\_vfp_textcache\" grep -rln "factura_salvare" "D:\ROA\_vfp_textcache\" # ce clase ating subiectul ``` Flux tipic: rulează scriptul o dată (populează cache-ul), apoi caută cu `Grep` în cache. La sesiuni următoare rescrie doar ce s-a schimbat (incremental). Pentru o librărie din `COMUN\` care nu e în proiect, convertește-o punctual cu `-Source`. ## Indexul de simboluri: `vfp_symbols.ps1` `grep` spune *unde* e textul, nu *în ce metodă*. Într-un `.vc2` asta contează: fișierele au uzual zeci de mii de linii, din care ~2/3 sunt proprietăți și metadata (nu cod), iar antetul clasei poate fi cu mii de linii deasupra potrivirii. `D:\ROA\UTIL\foxbin2prg\vfp_symbols.ps1` reține intervalul de linii al fiecărei clase/metode/proceduri — din cache-ul text **și** din `.prg`-urile proiectului — și etichetează rezultatele. ```powershell $s = 'D:\ROA\UTIL\foxbin2prg\vfp_symbols.ps1' $c = @('-CacheRoot', 'D:\ROA\_vfp_textcache\', '-ProjectRoot', '') # căutare etichetată cu clasa.metoda; -CodeOnly taie potrivirile din metadata/proprietăți powershell -ExecutionPolicy Bypass -File $s @c -Grep '' -CodeOnly powershell -ExecutionPolicy Bypass -File $s @c -Where '.vc2:' # cine deține linia powershell -ExecutionPolicy Bypass -File $s @c -Find '' # unde e DEFINIT powershell -ExecutionPolicy Bypass -File $s @c -Class '' # moștenire + metode ``` Exemplu (ROAACNPRO — parametrii impliciți ai scriptului țintesc deja acest proiect): ``` > vfp_symbols.ps1 -Grep 'calcul_cheiaj' -CodeOnly clase\oacnpro.vc2:14937: [frm_tranzit.do_executa] llSucces = calcul_cheiaj(m.lcVyeIds) > vfp_symbols.ps1 -Class oApp oApp (roaacnpro.prg:88) -> RoaApp (roa.prg:1) -> Custom (clasă de bază VFP) ``` Când merită în locul unui `grep` direct: - **înainte de o editare cu `txt2vcx.ps1`** — `-Where`/`-Class` dau intervalul exact al metodei. Într-un `.vc2` cu 15 clase, `Init`, `Show`, `do_adauga`, `do_executa2` există în aproape fiecare; fără interval e ușor să nimerești metoda cu același nume din altă clasă; - **rezultate multe** — `-CodeOnly` arată doar codul (pe `goExecutor` în ROAACNPRO: 1401 potriviri de cod din 1505, restul metadata); - **„definit sau doar apelat?"** — `-Find` dă doar definiția, `grep` dă tot; - **moștenire** — `-Class` arată lanțul cu fișier:linie, deci se vede dacă o metodă e suprascrisă local sau vine din `COMUN`. Indexul (`_symbols.tsv`, în rădăcina cache-ului) se reconstruiește singur când cache-ul e mai nou (~4 s pentru ~200 de fișiere); e regenerabil, se poate șterge oricând. Rulează întâi `vcx2txt.ps1`: indexul e derivat din cache, deci nu poate ști de modificări făcute în IDE și neconvertite. Limite: nu rezolvă apelurile indirecte (`EVALUATE`, `SET CLASSLIB`) — dă candidații, nu certitudinea. Clasele de bază VFP (`form`, `custom`) apar ca neindexate: normal, n-au sursă în proiect. Copiile vechi de `.prg` din subfoldere (ex. `COMUN\programe\roa\`) sunt excluse implicit prin `-ExcludePrg`; dă `-ExcludePrg ''` ca să vezi tot. ## Alternativă manuală (fără script) FoxBin2Prg scrie textul **lângă sursă**. Ca să nu murdărești folderul de clase al proiectului, copiază perechea binar+memo într-un folder temporar și convertește acolo: ```powershell # .vcx -> .vc2 (cType gol = extensia decide direcția BIN2PRG) Copy-Item D:\ROA\\Clase\odevize.vcx, D:\ROA\\Clase\odevize.vct D:\tmp\ & 'D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE' 'D:\tmp\odevize.vcx' '' '' '' '1' '0' '1' # => D:\tmp\odevize.vc2 ``` Poziții parametri: `fișier, cType, cTextName, lGenText, cDontShowErrors=1, cDebug=0, cDontShowProgress=1`. **Lasă `cType` gol** — extensia (`.vcx`) determină direcția. (Nu da explicit `"BIN2PRG"` pentru un singur fișier: în acel mod EXE-ul așteaptă un *director*.) Detalii complete de parametri: `D:\ROA\UTIL\foxbin2prg\docs\FoxBin2Prg_Run.md`. ## Soluție rapidă „murdară" (un singur fișier, fără conversie) Pentru „există metoda X undeva în librărie?", `grep` merge direct pe `.vct` (îl vede ca binar, dar găsește potrivirile): ```bash grep -c "PROCEDURE" "D:\ROA\\Clase\odevize.VCT" grep -a -o "PROCEDURE [a-zA-Z0-9_]*" "D:\ROA\\Clase\odevize.VCT" ``` Bun pentru „da/nu" și nume de metode; pentru corp/context, folosește conversia în text. ## Corespondență extensii binar → text | Container | Binar (+memo) | Text | |---|---|---| | Librărie clase | `.vcx` + `.vct` | `.vc2` | | Formă | `.scx` + `.sct` | `.sc2` | | Raport | `.frx` + `.frt` | `.fr2` | | Etichetă | `.lbx` + `.lbt` | `.lb2` | | Meniu | `.mnx` + `.mnt` | `.mn2` | | Bază de date | `.dbc` + `.dct` | `.dc2` | ## Note - Codul aplicației stă mai ales în `Clase\*.vcx`; multe `.vcx`-uri sunt în `COMUN\` (framework partajat între toate aplicațiile ROA — vezi `CLAUDE.md` per proiect). - Cache-ul text e regenerabil, în afara arborelui SVN/git al proiectului — poate fi șters oricând. - Conversia **nu** necesită IDE-ul VFP deschis (folosește EXE-ul compilat). - Vezi și [conventie_encoding_cp1252.md](conventie_encoding_cp1252.md) — capcană de encoding la editarea `.sc2`/`.vc2` (nu doar la căutare).