Integra il parser esatto del .asm nella GUI (fase 4 e 5)
AsmRecordReader (spostato da scripts/CreoBom.cs nel progetto principale, unica fonte di verita' condivisa con lo script via #:project) sostituisce AssemblyComponentScanner in Form1.RisolviAlberoComponenti (fase "Trova componenti referenziati") e AssiemeCompleto (fase "Verifica completezza"): legge esattamente la sezione "members" del binario invece di contare occorrenze testuali, eliminando i falsi positivi/negativi noti dell'euristica (riferimenti fantasma, placement senza suffisso, ecc.). Se un file non rispetta il formato validato (InvalidDataException, coperto solo dagli 8 campioni usati per il reverse engineering) Form1 ripiega sull'euristica di AssemblyComponentScanner, che resta quindi come fallback e come fonte di verita' per gli script BomViaDb.cs/ExtractCreoStrings.cs. Aggiunti test per AsmRecordReader (fixture binarie costruite a mano: lettura membri, risoluzione ConfigName, conteggio disallineato, sezione assente). Aggiornata la documentazione (CLAUDE.md, docs/architettura.md, docs/formato-asm.md, docs/formato-asm-record.md) di conseguenza. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
60dfd26e8b
commit
cce377a091
8 files changed
+363
-163
No files matched your search
+21
-11
@@ -79,14 +79,26 @@ Distinta (.xls/.xml) → CSV (componente;descrizione) → raw/ (CAD copiati
|
||||
`ROW_NUMBER() OVER (...)`, non self-join+`GROUP BY` per evitare tempi quasi quadratici su
|
||||
~200k righe).
|
||||
|
||||
## Scansione binaria dei `.asm`
|
||||
## Lettura dei componenti referenziati in un `.asm`
|
||||
|
||||
`Form1.EstraiCodiciReferenziati` (usata da `RisolviAlberoComponenti`, fase 4, e da
|
||||
`AssiemeCompleto` dentro `VerificaCompletezzaAssiemi`, fase 5) prova prima
|
||||
`AsmRecordReader.EstraiCodiciReferenziati` e ripiega su
|
||||
`AssemblyComponentScanner.EstraiCodiciReferenziati` solo se il primo lancia
|
||||
`InvalidDataException` (file che non rispetta il formato validato dal reverse engineering).
|
||||
|
||||
- **AsmRecordReader.cs** — legge esattamente la sezione `members` del binario `.asm` (id/tipo/
|
||||
nome dei componenti diretti, con risoluzione del nome istanza di family table dal parametro
|
||||
`ConfigName`): nessuna euristica, struttura a record. Lancia `InvalidDataException` se il
|
||||
file non ha una sezione `members` o se il conteggio dichiarato non torna. Dettagli in
|
||||
`docs/formato-asm-record.md`. Condivisa con `scripts/CreoBom.cs` via `#:project`.
|
||||
- **AssemblyComponentScanner.cs** — estrae euristicamente i codici componente referenziati
|
||||
dentro un `.asm` (formato per lo più binario, codici come stringhe ASCII leggibili al suo
|
||||
interno). Due strategie: codici numerici Pro-E riconosciuti da soli via regex (come nei nomi
|
||||
file), e nomi alfabetici di parti commerciali tokenizzati genericamente e validati contro
|
||||
l'elenco di codici noti del DB (altrimenti il rumore binario sarebbe ingestibile). Dettagli
|
||||
sul formato, l'euristica e i falsi positivi noti in `docs/formato-asm.md`.
|
||||
contando le occorrenze di stringhe candidate nel testo binario. Due strategie: codici
|
||||
numerici Pro-E riconosciuti da soli via regex (come nei nomi file), e nomi alfabetici di
|
||||
parti commerciali tokenizzati genericamente e validati contro l'elenco di codici noti del DB
|
||||
(altrimenti il rumore binario sarebbe ingestibile). Dettagli sull'euristica e i falsi
|
||||
positivi noti in `docs/formato-asm.md`. Resta il fallback per i file che il parser esatto
|
||||
non copre, e la fonte di verità per `ExtractCreoStrings.cs`/`BomViaDb.cs`.
|
||||
|
||||
## Import distinta base
|
||||
|
||||
@@ -151,11 +163,9 @@ dipendenze extra con `#:package Nome@versione` in testa al file):
|
||||
Pro-E).
|
||||
- **BomViaDb.cs** — come sopra ma con la tokenizzazione generica validata contro il DB, per
|
||||
intercettare anche i nomi alfabetici delle parti commerciali.
|
||||
- **CreoBom.cs** — indipendente dagli altri: legge esattamente la struttura a record del
|
||||
binario `.asm` (sezione `members` + parametro `ConfigName`, vedi
|
||||
`docs/formato-asm-record.md`) invece di contare occorrenze di codici nel testo. Risolve i
|
||||
sottoassiemi cercandoli in cartelle locali (`-p`), non contro `cad_index.db`. Non sostituisce
|
||||
l'euristica di `AssemblyComponentScanner` nella GUI né negli altri script.
|
||||
- **CreoBom.cs** — usa `AsmRecordReader` (stesso lettore esatto della GUI, fase 4/5, via
|
||||
`#:project`) invece dell'euristica testuale. Risolve i sottoassiemi cercandoli in cartelle
|
||||
locali (`-p`), non contro `cad_index.db` come `ExtractCreoStrings.cs`/`BomViaDb.cs`.
|
||||
- **Analyze.cs** — dump del contesto testo/hex attorno a un pattern in un file binario, per
|
||||
investigare a mano nuovi falsi positivi prima di toccare la regex di
|
||||
`AssemblyComponentScanner`.
|
||||
|
||||
@@ -7,7 +7,11 @@ l'euristica testuale ("codice che compare almeno due volte") descritta in
|
||||
[`formato-asm.md`](formato-asm.md): quella era una statistica sui nomi, questa legge la
|
||||
struttura effettiva dei record.
|
||||
|
||||
Implementazione: [`scripts/CreoBom.cs`](../scripts/CreoBom.cs).
|
||||
Implementazione: lettura in [`PrepStep/AsmRecordReader.cs`](../PrepStep/AsmRecordReader.cs)
|
||||
(condivisa con la GUI, `Form1.EstraiCodiciReferenziati` in fase "Trova componenti
|
||||
referenziati"/"Verifica completezza" - con fallback su `AssemblyComponentScanner` per i file
|
||||
che non rispettano il formato validato), resa in formato BOM e ricorsione sui sottoassiemi
|
||||
in [`scripts/CreoBom.cs`](../scripts/CreoBom.cs) (via `#:project`).
|
||||
|
||||
**Stato della validazione.** Durante il reverse engineering, il livello 1 estratto da 3
|
||||
assiemi con BOM Creo di riferimento coincideva **esattamente**: stesse voci, stesso nome
|
||||
@@ -75,7 +79,7 @@ conteggio dei membri: con la lettura a 1 byte fisso i campioni grandi si
|
||||
disallineavano. Non è confermata da una specifica; regge sui campioni
|
||||
disponibili al momento del reverse engineering.
|
||||
|
||||
In `CreoBom.cs` è `CreoAsm.AsInt`, applicata al testo decodificato Latin1 (ogni `char`
|
||||
In `CreoBom.cs` è `AsmRecordReader.AsInt`, applicata al testo decodificato Latin1 (ogni `char`
|
||||
della stringa corrisponde 1:1 a un byte, quindi indicizzare la stringa o l'array di byte
|
||||
originale dà lo stesso offset).
|
||||
|
||||
@@ -128,15 +132,15 @@ codici distinti: una parte montata 4 volte conta 4 e compare in 4 record con id
|
||||
diversi. Il conteggio va usato come controllo di correttezza: se i record
|
||||
trovati non sono esattamente `N`, la lettura si è disallineata e va segnalata
|
||||
un'eccezione invece di restituire un risultato parziale silenzioso — vedi
|
||||
`CreoAsm.LeggiMembri`, che lancia `InvalidDataException` in questo caso.
|
||||
`AsmRecordReader.LeggiMembri`, che lancia `InvalidDataException` in questo caso.
|
||||
|
||||
La sezione termina a `\xf4\x04#\n#MdlStatus\n`.
|
||||
|
||||
### 3.1 Come lo legge `CreoAsm.LeggiMembri`
|
||||
### 3.1 Come lo legge `AsmRecordReader.LeggiMembri`
|
||||
|
||||
Il parser non ricostruisce lo schema completo (servirebbe decodificare le
|
||||
matrici). Si ancora invece al pattern `\xe3 <int> <int> <stringa>\0 <stringa>\0`
|
||||
(`CreoAsm.MemberRegex`, una regex .NET sul testo Latin1 del file) e salta il
|
||||
(`AsmRecordReader.MemberRegex`, una regex .NET sul testo Latin1 del file) e salta il
|
||||
resto del record fino al `\xe3` successivo che soddisfa il pattern.
|
||||
La doppia stringa terminata da `\0` rende i falsi positivi improbabili, e il
|
||||
conteggio dichiarato `N` fa da rete di sicurezza.
|
||||
@@ -172,14 +176,14 @@ Il collegamento sta in un record di **parametro** applicato al membro:
|
||||
linea), poi è omesso.
|
||||
- `\x82\x7b` — costante (= 635) identica su tutte le occorrenze di tutti i
|
||||
campioni. Significato ignoto, presumibilmente attributi/flag del parametro.
|
||||
`CreoAsm.ConfigNameRegex` la usa come ancora di fine record; se un campione
|
||||
`AsmRecordReader.ConfigNameRegex` la usa come ancora di fine record; se un campione
|
||||
futuro avesse un valore diverso, il match salterebbe silenziosamente (nessun
|
||||
contatore di sicurezza analogo a quello di `members` copre questo caso).
|
||||
|
||||
`ConfigName` compare **esattamente** per i membri che sono istanze, e per
|
||||
nessun altro. L'algoritmo è quindi: leggere `members`, costruire la mappa
|
||||
`id membro → nome istanza` dai record `ConfigName`
|
||||
(`CreoAsm.LeggiMembri`, dizionario `istanze`), e sostituire il nome dove la
|
||||
(`AsmRecordReader.LeggiMembri`, dizionario `istanze`), e sostituire il nome dove la
|
||||
mappa ha una voce. Il generico resta disponibile come `Membro.File`.
|
||||
|
||||
> **Avvertenza.** `ConfigName` sta in mezzo a parametri palesemente aziendali
|
||||
@@ -218,7 +222,7 @@ primo record `objname` del file:
|
||||
```
|
||||
|
||||
La **prima** occorrenza è il modello stesso; quelle successive sono altri
|
||||
oggetti referenziati (disegni, modelli citati). `CreoAsm.NomeProprio` cerca
|
||||
oggetti referenziati (disegni, modelli citati). `AsmRecordReader.NomeProprio` cerca
|
||||
solo la prima occorrenza (`Regex.Match`, non `Matches`), verificato su tutti i
|
||||
campioni disponibili durante il reverse engineering.
|
||||
|
||||
@@ -297,7 +301,7 @@ Elencato esplicitamente per non far passare per dimostrato ciò che non lo è:
|
||||
situazione divergerebbe.
|
||||
- **La costante `\x82\x7b`** nei record `ConfigName`.
|
||||
- **I campi numerici dell'header** dopo `ASSEMBLY`.
|
||||
- **Occorrenze multiple di `members`.** `CreoAsm.LeggiMembri` prende la prima.
|
||||
- **Occorrenze multiple di `members`.** `AsmRecordReader.LeggiMembri` prende la prima.
|
||||
Sui campioni disponibili funziona, ma non è stato verificato se le
|
||||
rappresentazioni semplificate (simplified rep) generino sezioni `members`
|
||||
aggiuntive.
|
||||
|
||||
+17
-16
@@ -1,23 +1,24 @@
|
||||
# Come leggere un .asm Creo per dedurne i componenti
|
||||
|
||||
Il file `.asm` di Pro/ENGINEER-Creo è un formato binario proprietario, non
|
||||
documentato pubblicamente. Questo documento descrive l'euristica testuale usata da
|
||||
`AssemblyComponentScanner.cs` (GUI, fase "Trova componenti referenziati"/"Verifica
|
||||
completezza") e dagli script che risolvono l'albero componenti contro `cad_index.db`
|
||||
(`ExtractCreoStrings.cs`, `BomViaDb.cs`): conta le occorrenze di stringhe candidate nel
|
||||
testo binario, validata a mano confrontando l'output con l'albero reale mostrato da Creo.
|
||||
Riassume cosa si è osservato e i suoi limiti, in particolare i falsi positivi che
|
||||
un conteggio testuale non può escludere con certezza (riferimenti fantasma, componenti
|
||||
soppressi con placement residuo — vedi sotto).
|
||||
documentato pubblicamente. Questo documento descrive l'euristica testuale di
|
||||
`AssemblyComponentScanner.cs`: conta le occorrenze di stringhe candidate nel testo binario,
|
||||
validata a mano confrontando l'output con l'albero reale mostrato da Creo. Riassume cosa si
|
||||
è osservato e i suoi limiti, in particolare i falsi positivi che un conteggio testuale non
|
||||
può escludere con certezza (riferimenti fantasma, componenti soppressi con placement
|
||||
residuo — vedi sotto).
|
||||
|
||||
Un reverse engineering successivo ha invece decodificato la **struttura a record** del
|
||||
file (non solo pattern testuali): legge esattamente la sezione `members` di un assieme,
|
||||
senza contare occorrenze né rischiare i falsi positivi descritti in questo documento.
|
||||
Implementato in [`scripts/CreoBom.cs`](../scripts/CreoBom.cs), documentato in
|
||||
[`formato-asm-record.md`](formato-asm-record.md). Resta però uno script di analisi
|
||||
indipendente: legge solo `.asm` locali dato un percorso di ricerca esplicito (non
|
||||
`cad_index.db`), e non è integrato in `AssemblyComponentScanner`/nella GUI, che
|
||||
continuano a usare l'euristica descritta qui.
|
||||
Un reverse engineering successivo ha decodificato la **struttura a record** del file (non
|
||||
solo pattern testuali): legge esattamente la sezione `members` di un assieme, senza contare
|
||||
occorrenze né rischiare i falsi positivi descritti in questo documento. Implementato in
|
||||
`PrepStep/AsmRecordReader.cs`, documentato in [`formato-asm-record.md`](formato-asm-record.md).
|
||||
È il metodo **preferito** in GUI (fase "Trova componenti referenziati"/"Verifica
|
||||
completezza", `Form1.EstraiCodiciReferenziati`) e nello script `CreoBom.cs`:
|
||||
`AssemblyComponentScanner` (l'euristica di questo documento) resta come **fallback**, usato
|
||||
solo quando `AsmRecordReader` lancia `InvalidDataException` (file che non rispetta il
|
||||
formato validato dal reverse engineering — copertura limitata agli 8 campioni disponibili al
|
||||
momento), e come fonte di verità per gli script `ExtractCreoStrings.cs`/`BomViaDb.cs`, che
|
||||
risolvono l'albero contro `cad_index.db` invece che tramite un percorso di ricerca locale.
|
||||
|
||||
## Struttura osservata
|
||||
|
||||
|
||||
Reference in new issue
Block a user