The DCU32INT utility by Alexei Hmelnov. Version 1.0 ---------------------------------------------------------------------------- E-Mail: alex@monster.icc.ru http://monster.icc.ru/~alex/DCU/ ---------------------------------------------------------------------------- Purpose. -------- Parse Delphi 2.0-5.0 units (DCU) and convert their information into the close to Pascal form. DCU32INT stands for DCU32 INTerface, because this program can't extract the complete Pascal source, but the extracted unit interface is almost correct (see Compiler Information Loss Limitations section for exceptions). This program is a by-product of the FlexT project (see http://monster.icc.ru/~alex/FlexT/ for details), but I have done my best to make it useful. Usage. ------ DCU32INT [] Destination file may contain * to be replaced by the unit name or name and extension. If * is the last char in the name, it will be replaced by .int, else - by . Destination file = "-" => write to stdout. Switches (start with "/" or "-"): -S* - Show flags (-S - show all), default: (+) - on, (-) - off I(+) - show Imported names T(-) - show Type table A(-) - show Address table D(-) - show Data block F(-) - show fixups V(-) - show auxiliary Values M(-) - don't resolve class methods C(-) - don't resolve constant values d(-) - show dot types v(-) - show VMT for objects and classes -I - interface part only -U = Unit directories -N = No Name Prefix ("%" - Scope char) -D = Dot Name Prefix ("%" - Scope char) The Scope char symbol will be replaced in the name by "T" for types "C" for constants and so on (see source for details). In general, there are two main ways to run the program: - without the -S switch - to produce the most close to the original Pascal source output without superfluous details; - with the -S switch to see a lot of additional information, which reflects the internal structure of the DCU file, e.g. the values of some fields of unknown purpose (You can try to guess what they mean), the data structures representing the VMT of classes, RTTI of data types or the table of addresses. Of course, You can always select only a subset of additional information using the -S. Validity. --------- The DCU32INT utility have passed successfully the "parse all .\LIB" test for all the supported by it Delphi versions, i.e. it have parsed all units in the \LIB directory with no errors reported. See alllib.bat files for examples of running the DCU32INT to parse all .\LIB (Drawback: it's a DOS BAT file, so the long unit names will be replaced by the corresponding 8.3 ones). This success doesn't mean, however, that the underlying DCU specification is absolutely correct. So, please, send me your bug reports (see the section "Home page" for details). The Compiler Information Loss Limitations. ------------------------------------------ There are two kinds of limitations of the DCU32INT program: 1. The ones caused by some disadvantages in its implementation, which can be overcome later; 2. The ones caused by information loss in DCU after compiling Pascal source, which are inevitable. Here we'll consider some of the latter limitations. While converting Pascal source into DCU, Delphi compiler extracts from source and stores into DCU only the information, which is necessary to produce later an executable file and also, if required, a debug information for this file. During this process the compiler performs some simplifications, which cause information loss. Examples: 1. Identifiers declared in implementation part and subroutines are discarded if the debug info checkbox doesn't checked. 2. Evaluation of expressions. Constant expressions are replaced by their values, so one can't determine, e.g. that CDM_FIRST = WM_USER+100, it will have the fixed value of $0464. 3. Resolution of rename types. The rename types (types, which are defined by declarations like THandle = integer), are replaced by their reference type, so all the references to the THandle type in the source code are replaced by the System.Integer type. 4. Merge of fields in the records with variants. The declaration like TVarRec = record case Byte of vtInteger: (VInteger: Integer; VType: Byte); vtBoolean: (VBoolean: Boolean); ----------------------------------------- end; Is stored as TVarRec{88,7F9FF4C2}=record VInteger: Integer{F:2 Ofs:0}; VType: Byte{F:2 Ofs:4}; VBoolean: Boolean{F:2 Ofs:0}; ---------------------------------- end; where Ofs:_ is a field offset information. Of course, we can group the fields into cases according to their order and offsets (future work), but the information about case labels is lost here completely, and it can't be used, e.g. to display safely (Delphi version independent) the Variant type value using the TVarRec definition. All the above mentioned limitations can be demonstrated by Delphi browser and evaluator (those utilities are also limited by them). So, the extracted Pascal code can cause some problems, if used in other version of Delphi, than that, which produced the DCU. Home page. ---------- The latest version of this program and all the related news will be available at http://monster.icc.ru/~alex/DCU/ Please, send me (e-mail: alex@monster.icc.ru) bug reports (including the units which were not parsed correctly), but first check: 1. that you have the latest version of DCU32INT, 2. that this bug was not already reported at http://monster.icc.ru/~alex/DCU/FAQ.htm (projected page name).