# Come leggere un .asm Creo per dedurne i componenti Il file `.asm` di Pro/ENGINEER-Creo è un formato binario proprietario, non documentato pubblicamente. Non esiste un parser strutturale completo in questo progetto: l'estrazione dei componenti si basa su un'euristica testuale, validata a mano confrontando l'output con l'albero reale mostrato da Creo. Questo documento riassume cosa si è osservato e i suoi limiti. ## Struttura osservata Il file contiene, frammentate tra dati binari, molte coppie testuali del tipo ``` \x00\x00 ``` in encoding a 1 byte per carattere (Latin1/ASCII), es.: ``` 6d 6f 64 65 6c 5f 6e 61 6d 65 00 39 30 34 34 32 30 37 30 36 31 5f 43 30 31 23 41 46 30 00 m o d e l _ n a m e \0 9 0 4 4 2 0 7 0 6 1 _ C 0 1 # A F 0 \0 ``` I codici dei componenti (propri e sotto-componenti) compaiono come stringhe ASCII leggibili in diversi campi ricorrenti: - `model_name`, `generic_name`, `inst_name`, `gen_name`, `feat_name`, `family_name`, `name` — metadati associati a un modello referenziato. - `Componente ID N (.PRT|.ASM)` — riga di placement: `N` è un ID progressivo assegnato da Creo al componente posizionato nell'assieme. - `#AF0` — riferimento con suffisso di versione/configurazione. Un codice reale compare **più volte** nel file (una per feature/placement diverso); rumore binario che assomiglia casualmente a un codice compare quasi sempre una sola volta. Questa è la base del filtro in [`AssemblyComponentScanner.cs`](../CadSearchGui/AssemblyComponentScanner.cs) e in [`scripts/ExtractCreoStrings.cs`](../scripts/ExtractCreoStrings.cs): ``` regex: \b\d{8,12}(?:_[A-Za-z]\d{2,4}|[A-Za-z]{0,2})\b occorrenze: >= 2 ``` `scripts/ExtractCreoStrings.cs` ha una versione più raffinata della regex e un filtro aggiuntivo (vedi sotto), non ancora portati in `AssemblyComponentScanner.cs`: ``` regex: \b\d{8,12}[A-Za-z]{0,2}(?:_[A-Za-z]?\d{2,4})?\b ``` (lettera di revisione e suffisso "_..." possono comparire anche insieme, es. `9284200366A_C01`; il suffisso dopo "_" può essere puramente numerico, es. `2702220182_8188`, non solo lettera+cifre come `_C01`/`_D100`.) ## Falsi positivi noti **ID di viste salvate.** Il pattern `ModelView#` (es. `ModelView#1073741828`) genera candidati a 10 cifre indistinguibili da un codice reale per forma, ma sono ID interni di viste orientate salvate, non componenti. Si escludono con un lookbehind negativo sulla regex: `(?...)`/`Component id N (...)` (la stringa cambia con la localizzazione Creo con cui il file è stato salvato - osservate sia italiana sia inglese); un riferimento incidentale al nome di un altro assieme, anche se ripetuto più volte, non compare mai in quel contesto. `scripts/ExtractCreoStrings.cs` applica questa regola ai codici "nudi" (senza suffisso `_...` e senza bracket UNI - vedi sotto perché limitata a questi): un codice ripetuto ma mai trovato dentro un placement viene scartato. Questo NON copre i casi fantasma/soppressi sotto, che hanno un placement sintatticamente identico a uno vero e restano quindi indistinguibili a livello testuale. **Riferimenti fantasma a codici superati/rinominati.** Caso osservato: `9244207061.asm` contiene un riferimento a `9044207061` (stesso numero, prima di una rinumerazione) con la stessa identica struttura sintattica di un componente vero — `Componente ID 46 (9044207061.ASM)`, più i campi `model_name`/`generic_name` corrispondenti. Il codice `9044207061` esiste davvero nell'indice CAD (il file vecchio non è stato eliminato dalla share), quindi supera anche una validazione incrociata contro il DB. Non è però un componente realmente presente nell'albero mostrato da Creo per quell'assieme (confermato aprendo il file in Creo). Questo caso **non è distinguibile a livello testuale**: la sintassi è identica a quella di un placement reale. Nessuna euristica sulla stringa riesce a discriminarlo in modo affidabile senza rischiare di scartare componenti veri con pattern simili altrove. Se ricompare, l'unica verifica sicura resta l'apertura manuale in Creo del sotto-assieme sospetto. **Componenti soppressi/rimossi con placement residuo.** Stessa natura del caso precedente: capita che un codice compaia con un vero `Componente ID N (.PRT)`/`Component id N (.PRT)` - con un ID numerico nello stesso intervallo di quelli dei componenti realmente visibili nell'albero Creo, quindi non distinguibile per posizione o formato - ma il codice non compare nell'albero/BOM che Creo mostra per quell'assieme. Osservato su più assiemi in questa sessione (`9044207061` dentro `9244207061.asm`, e diversi codici dentro `9284208188_D200.asm`). Ipotesi più probabile: feature soppresse, cancellate o superate in una revisione successiva, il cui placement resta comunque nella storia binaria del file (Creo non riscrive da zero il file a ogni salvataggio, accumula stato). Nella pratica, quando compaiono, sono un numero ridotto di codici extra rispetto al reale (falsi positivi, non falsi negativi): la BOM generata resta un sovrainsieme sicuro dei componenti veri, mai un sottoinsieme. Nessuna euristica testuale può escluderli con certezza; se serve un elenco esatto l'unica verifica è aprire l'assieme in Creo e controllare a mano quali ID sono effettivamente presenti/attivi. **Placement senza il dettaglio del suffisso/bracket.** Il testo dentro `Componente ID N (...)` a volte riporta solo il nome generico/istanza, senza il suffisso di variante dimensionale o il bracket family-table, che compaiono invece solo altrove nei metadati dello stesso file (non vicino al placement). Osservato in due forme sullo stesso assieme (`9284208188_D200.asm`): `Component id 82 (R8--_-_U6592.PRT)` (nessun `` nel placement, pure presente nel file) e `Component id 150 (2702220182.PRT)` (nessun `_8188` nel placement, mentre la variante dimensionale reale `2702220182_8188` compare solo come stringa ripetuta altrove). Per questo il requisito del placement esplicito (caso sopra) si applica solo ai codici "nudi" (senza suffisso `_...` e senza bracket UNI): per le varianti con suffisso o family table il placement può mancare del dettaglio, quindi resta necessaria la sola euristica delle occorrenze ripetute - meno precisa, ma l'unica applicabile senza rischiare falsi negativi su casi come questi. ## Viti/dadi/rosette normalizzati (family table UNI) I componenti di minuteria standard (viti, dadi, rosette UNI) sono definiti in Creo come **family table**: un file generico (es. `uni6592.prt`) con tante righe/istanze quante sono le varianti dimensionali. Nel binario dell'assieme compaiono così: ``` Componente ID 28755 (R6--_-_U6592.PRT) ``` `R6--_-_U6592` è il nome della singola istanza (riga della family table), **non un file separato su disco** — sulla share esiste solo `uni6592.prt.` (verificato in `Unificati/`). Cercare l'istanza intera nell'indice fallisce sempre; va estratto solo il contenuto tra `<` e `>` (`UNI6592`), che coincide col nome del file generico realmente indicizzato: ``` regex aggiuntiva: (?<=<)UNI\d+(?=>) ``` Implementata sia in [`scripts/ExtractCreoStrings.cs`](../scripts/ExtractCreoStrings.cs) sia in [`AssemblyComponentScanner.cs`](../CadSearchGui/AssemblyComponentScanner.cs) (fase "Trova componenti referenziati" dell'app). ## Risoluzione ricorsiva dell'albero Un `.asm` referenzia solo i propri sotto-componenti diretti, non l'intero albero annidato. Per ricostruire la distinta base completa (non solo il primo livello) serve una BFS: 1. Estrarre i codici candidati dal file corrente (euristica sopra). 2. Per ogni codice, cercarlo nell'indice `cad_index.db` (`files_ultima_versione`) per sapere se è un `.prt` (foglia) o un `.asm` (da accodare alla coda per essere scansionato a sua volta). 3. Un codice non trovato nell'indice va scartato/segnalato: o è rumore binario, o è un componente non ancora indicizzato. Stessa logica di estrazione candidati in due punti del codice, con scopi diversi: - [`AssemblyComponentScanner.EstraiCodiciReferenziati`](../CadSearchGui/AssemblyComponentScanner.cs) — solo estrazione dei candidati da un file, usata dalla BFS in [`Form1.RisolviAlberoComponenti`](../CadSearchGui/Form1.cs) (fase "Trova componenti referenziati") e [`Form1.AssiemeCompleto`](../CadSearchGui/Form1.cs) (fase "Verifica completezza"). - [`scripts/ExtractCreoStrings.cs`](../scripts/ExtractCreoStrings.cs) — estrazione standalone da riga di comando, ma **un solo livello**: riporta solo i riferimenti diretti del file passato (come li mostra Creo per quell'assieme), senza scendere ricorsivamente nei sotto-assiemi. Usato per confrontare l'euristica contro l'albero Creo di un singolo file durante il reverse engineering; non genera una distinta base completa multi-livello. Nota: le query contro `files_ultima_versione` filtrano solo per `(cartella_radice, codice, tipo_file)` - se lo stesso codice esiste in più cartelle radice sulla share (duplicati/copie storiche), va sempre ordinato per `data_modifica DESC` e tenuta solo la riga più recente per tipo, altrimenti si rischia di risolvere un codice contro una copia diversa (e potenzialmente diversa nel contenuto) da quella realmente referenziata. ## Strumento di analisi manuale [`scripts/Analyze.cs`](../scripts/Analyze.cs) stampa il contesto testuale ed esadecimale attorno a ogni occorrenza di un pattern in un file binario — usato per tutte le osservazioni di questo documento: ```powershell dotnet run scripts/Analyze.cs -- raw/9244207061.asm.1 "9044207061" ``` Utile per verificare a mano un nuovo falso positivo prima di modificare la regex o l'esclusione nello script di estrazione.