mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-10-31 04:01:28 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			2718 lines
		
	
	
		
			79 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			2718 lines
		
	
	
		
			79 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| {
 | |
|  ***************************************************************************
 | |
|  *                                                                         *
 | |
|  *   This source is free software; you can redistribute it and/or modify   *
 | |
|  *   it under the terms of the GNU General Public License as published by  *
 | |
|  *   the Free Software Foundation; either version 2 of the License, or     *
 | |
|  *   (at your option) any later version.                                   *
 | |
|  *                                                                         *
 | |
|  *   This code is distributed in the hope that it will be useful, but      *
 | |
|  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 | |
|  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 | |
|  *   General Public License for more details.                              *
 | |
|  *                                                                         *
 | |
|  *   A copy of the GNU General Public License is available on the World    *
 | |
|  *   Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also      *
 | |
|  *   obtain it by writing to the Free Software Foundation,                 *
 | |
|  *   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.        *
 | |
|  *                                                                         *
 | |
|  ***************************************************************************
 | |
| 
 | |
|   Author: Mattias Gaertner
 | |
| 
 | |
|   Abstract:
 | |
|     Functions and classes to read ppu streams (Free Pascal compiled units)
 | |
|     of various versions. For example reading 2.3.1 ppus compiled for 64bit
 | |
|     with a lazarus compiled with fpc 2.2.2 i386.
 | |
| }
 | |
| unit PPUParser;
 | |
| 
 | |
| {$mode objfpc}{$H+}
 | |
| 
 | |
| {off $DEFINE VerbosePPUParser}
 | |
| 
 | |
| interface
 | |
| 
 | |
| uses
 | |
|   Classes, SysUtils, contnrs, FileProcs, LazFileUtils, lazutf8classes;
 | |
| 
 | |
| const
 | |
|   PPUIsEndianBig = {$IFDEF ENDIAN_BIG}True{$ELSE}False{$ENDIF};
 | |
| 
 | |
| // from ppu.pas
 | |
| const
 | |
| {ppu entries}
 | |
|   mainentryid         = 1;
 | |
|   subentryid          = 2;
 | |
|   {special}
 | |
|   iberror             = 0;
 | |
|   ibstartdefs         = 248;
 | |
|   ibenddefs           = 249;
 | |
|   ibstartsyms         = 250;
 | |
|   ibendsyms           = 251;
 | |
|   ibendinterface      = 252;
 | |
|   ibendimplementation = 253;
 | |
|   ibendbrowser        = 254;
 | |
|   ibend               = 255;
 | |
|   {general}
 | |
|   ibmodulename           = 1;
 | |
|   ibsourcefiles          = 2;
 | |
|   ibloadunit             = 3;
 | |
|   ibinitunit             = 4;
 | |
|   iblinkunitofiles       = 5;
 | |
|   iblinkunitstaticlibs   = 6;
 | |
|   iblinkunitsharedlibs   = 7;
 | |
|   iblinkotherofiles      = 8;
 | |
|   iblinkotherstaticlibs  = 9;
 | |
|   iblinkothersharedlibs  = 10;
 | |
|   ibImportSymbols        = 11;
 | |
|   ibsymref               = 12;
 | |
|   ibdefref               = 13;
 | |
|   ibendsymtablebrowser   = 14;
 | |
|   ibbeginsymtablebrowser = 15;
 | |
|   ibusedmacros           = 16;
 | |
|   ibderefdata            = 17;
 | |
|   ibexportedmacros       = 18;
 | |
|   ibderefmap             = 19;
 | |
|   {syms}
 | |
|   ibtypesym        = 20;
 | |
|   ibprocsym        = 21;
 | |
|   ibstaticvarsym   = 22;
 | |
|   ibconstsym       = 23;
 | |
|   ibenumsym        = 24;
 | |
|   ibtypedconstsym  = 25;
 | |
|   ibabsolutevarsym = 26;
 | |
|   ibpropertysym    = 27;
 | |
|   ibfieldvarsym    = 28;
 | |
|   ibunitsym        = 29;
 | |
|   iblabelsym       = 30;
 | |
|   ibsyssym         = 31;
 | |
|   ibrttisym        = 32;
 | |
|   iblocalvarsym    = 33;
 | |
|   ibparavarsym     = 34;
 | |
|   ibmacrosym       = 35;
 | |
|   {definitions}
 | |
|   iborddef         = 40;
 | |
|   ibpointerdef     = 41;
 | |
|   ibarraydef       = 42;
 | |
|   ibprocdef        = 43;
 | |
|   ibshortstringdef = 44;
 | |
|   ibrecorddef      = 45;
 | |
|   ibfiledef        = 46;
 | |
|   ibformaldef      = 47;
 | |
|   ibobjectdef      = 48;
 | |
|   ibenumdef        = 49;
 | |
|   ibsetdef         = 50;
 | |
|   ibprocvardef     = 51;
 | |
|   ibfloatdef       = 52;
 | |
|   ibclassrefdef    = 53;
 | |
|   iblongstringdef  = 54;
 | |
|   ibansistringdef  = 55;
 | |
|   ibwidestringdef  = 56;
 | |
|   ibvariantdef     = 57;
 | |
|   ibundefineddef   = 58;
 | |
|   ibunicodestringdef = 59; // svn rev 9382
 | |
|   {implementation/ObjData}
 | |
|   ibnodetree       = 80;
 | |
|   ibasmsymbols     = 81;
 | |
|   ibresources      = 82;  // svn rev 7515   ppu version 80
 | |
|   ibcreatedobjtypes = 83; // svn rev 12341  ppu version 95
 | |
|   ibwpofile         = 84; // svn rev 12341  ppu version 95
 | |
|   ibmoduleoptions   = 85; // svn rev 14767  ppu version 114
 | |
| 
 | |
|   ibmainname       = 90;  // svn rev 10406
 | |
|   ibsymtableoptions = 91; // svn rev 17328  ppu version 128
 | |
|   ibrecsymtableoptions = 91; // svn rev 18114
 | |
|   { target-specific things }
 | |
|   iblinkotherframeworks = 100; // svn rev 8344
 | |
|   ibjvmnamespace = 101; // svn rec 21069
 | |
| 
 | |
|   { unit flags }
 | |
|   uf_init                = $000001; { unit has initialization section }
 | |
|   uf_finalize            = $000002; { unit has finalization section   }
 | |
|   uf_big_endian          = $000004;
 | |
|   //uf_has_browser         = $000010;
 | |
|   uf_in_library          = $000020; { is the file in another file than <ppufile>.* ? }
 | |
|   uf_smart_linked        = $000040; { the ppu can be smartlinked }
 | |
|   uf_static_linked       = $000080; { the ppu can be linked static }
 | |
|   uf_shared_linked       = $000100; { the ppu can be linked shared }
 | |
|   //uf_local_browser       = $000200;
 | |
|   uf_no_link             = $000400; { unit has no .o generated, but can still have external linking! }
 | |
|   uf_has_resourcestrings = $000800; { unit has resource string section }
 | |
|   uf_little_endian       = $001000;
 | |
|   uf_release             = $002000; { unit was compiled with -Ur option }
 | |
|   uf_threadvars          = $004000; { unit has threadvars }
 | |
|   uf_fpu_emulation       = $008000; { this unit was compiled with fpu emulation on }
 | |
|   uf_has_stabs_debuginfo = $010000; { this unit has stabs debuginfo generated }
 | |
|   uf_local_symtable      = $020000; { this unit has a local symtable stored }
 | |
|   uf_uses_variants       = $040000; { this unit uses variants }
 | |
|   uf_has_resourcefiles   = $080000; { this unit has external resources (using $R directive)}
 | |
|   uf_has_exports         = $100000; { this module or a used unit has exports }
 | |
|   uf_has_dwarf_debuginfo = $200000; { this unit has dwarf debuginfo generated }
 | |
|   uf_wideinits           = $400000; { this unit has winlike widestring typed constants }
 | |
|   uf_classinits          = $800000; { this unit has class constructors/destructors }
 | |
|   uf_resstrinits        = $1000000; { svn rev 18968: this unit has string consts referencing resourcestrings }
 | |
|   uf_i8086_far_code     = $2000000; { svn rev 25365: this unit uses an i8086 memory model with far code (i.e. medium, large or huge) }
 | |
|   uf_i8086_far_data     = $4000000; { svn rev 25365: this unit uses an i8086 memory model with far data (i.e. compact or large) }
 | |
|   uf_i8086_huge_data    = $8000000; { svn rev 25365: this unit uses an i8086 memory model with huge data (i.e. huge) }
 | |
|   uf_i8086_cs_equals_ds = $10000000; { svn rev 27516: this unit uses an i8086 memory model with CS=DS (i.e. tiny) }
 | |
| 
 | |
| // from systems.inc
 | |
| type
 | |
|    tsystemcpu=
 | |
|     (
 | |
|           cpu_no,                       { 0 }
 | |
|           cpu_i386,                     { 1 }
 | |
|           cpu_m68k,                     { 2 }
 | |
|           cpu_alpha,                    { 3 }
 | |
|           cpu_powerpc,                  { 4 }
 | |
|           cpu_sparc,                    { 5 }
 | |
|           cpu_vm,                       { 6 }
 | |
|           cpu_iA64,                     { 7 }
 | |
|           cpu_x86_64,                   { 8 }
 | |
|           cpu_mipseb,                   { 9 }
 | |
|           cpu_arm,                      { 10 }
 | |
|           cpu_powerpc64,                { 11 }
 | |
|           cpu_avr,                      { 12 }
 | |
|           cpu_mipsel,                   { 13 }
 | |
|           cpu_jvm,                      { 14 }
 | |
|           cpu_i8086,                    { 15 }
 | |
|           cpu_aarch64                   { 16 }
 | |
|     );
 | |
| 
 | |
| const
 | |
|   PPU_CPUNames : array[tsystemcpu] of string[9]=
 | |
|     ('none',
 | |
|      'i386',
 | |
|      'm68k',
 | |
|      'alpha',
 | |
|      'powerpc',
 | |
|      'sparc',
 | |
|      'vis',
 | |
|      'ia64',
 | |
|      'x86_64',
 | |
|      'mips',
 | |
|      'arm',
 | |
|      'powerpc64',
 | |
|      'avr',
 | |
|      'mipsel',
 | |
|      'jvm',
 | |
|      'i8086',
 | |
|      'a64'
 | |
|      );
 | |
| 
 | |
| // from ppu.pas
 | |
|   { We need to use the correct size of aint and pint for
 | |
|   the target CPU }
 | |
| const
 | |
|   CpuAddrBitSize : array[tsystemcpu] of longint =
 | |
|     (
 | |
|     {  0 } 32 {'none'},
 | |
|     {  1 } 32 {'i386'},
 | |
|     {  2 } 32 {'m68k'},
 | |
|     {  3 } 32 {'alpha'},
 | |
|     {  4 } 32 {'powerpc'},
 | |
|     {  5 } 32 {'sparc'},
 | |
|     {  6 } 32 {'vis'},
 | |
|     {  7 } 64 {'ia64'},
 | |
|     {  8 } 64 {'x86_64'},
 | |
|     {  9 } 32 {'mipseb'},
 | |
|     { 10 } 32 {'arm'},
 | |
|     { 11 } 64 {'powerpc64'},
 | |
|     { 12 } 16 {'avr'},
 | |
|     { 13 } 32 {'mipsel'},
 | |
|     { 14 } 32 {'jvm'},
 | |
|     { 15 } 16 {'i8086'},
 | |
|     { 16 } 64 {'aarch64'}
 | |
|     );
 | |
|   CpuAluBitSize : array[tsystemcpu] of longint =
 | |
|     (
 | |
|     {  0 } 32 {'none'},
 | |
|     {  1 } 32 {'i386'},
 | |
|     {  2 } 32 {'m68k'},
 | |
|     {  3 } 32 {'alpha'},
 | |
|     {  4 } 32 {'powerpc'},
 | |
|     {  5 } 32 {'sparc'},
 | |
|     {  6 } 32 {'vis'},
 | |
|     {  7 } 64 {'ia64'},
 | |
|     {  8 } 64 {'x86_64'},
 | |
|     {  9 } 32 {'mipseb'},
 | |
|     { 10 } 32 {'arm'},
 | |
|     { 11 } 64 {'powerpc64'},
 | |
|     { 12 }  8 {'avr'},
 | |
|     { 13 } 32 {'mipsel'},
 | |
|     { 14 } 64 {'jvm'},
 | |
|     { 15 } 16 {'i8086'},
 | |
|     { 16 } 64 {'aarch64'}
 | |
|     );
 | |
| 
 | |
| type
 | |
|   // from globtype.pas
 | |
|   tproccalloption=(
 | |
|     pocall_none,
 | |
|     { procedure uses C styled calling }
 | |
|     pocall_cdecl,
 | |
|     { C++ calling conventions }
 | |
|     pocall_cppdecl,
 | |
|     { Far16 for OS/2 }
 | |
|     pocall_far16,
 | |
|     { Old style FPC default calling }
 | |
|     pocall_oldfpccall,
 | |
|     { Procedure has compiler magic}
 | |
|     pocall_internproc,
 | |
|     { procedure is a system call, applies e.g. to MorphOS and PalmOS }
 | |
|     pocall_syscall,
 | |
|     { pascal standard left to right }
 | |
|     pocall_pascal,
 | |
|     { procedure uses register (fastcall) calling }
 | |
|     pocall_register,
 | |
|     { safe call calling conventions }
 | |
|     pocall_safecall,
 | |
|     { procedure uses stdcall call }
 | |
|     pocall_stdcall,
 | |
|     { Special calling convention for cpus without a floating point
 | |
|       unit. Floating point numbers are passed in integer registers
 | |
|       instead of floating point registers. Depending on the other
 | |
|       available calling conventions available for the cpu
 | |
|       this replaces either pocall_fastcall or pocall_stdcall.
 | |
|     }
 | |
|     pocall_softfloat,
 | |
|     { Metrowerks Pascal. Special case on Mac OS (X): passes all }
 | |
|     { constant records by reference.                            }
 | |
|     pocall_mwpascal
 | |
|   );
 | |
|   tproccalloptions = set of tproccalloption;
 | |
| 
 | |
|   // from symconst.pas
 | |
|   tproctypeoption=(
 | |
|     potype_none,
 | |
|     potype_proginit,     { Program initialization }
 | |
|     potype_unitinit,     { unit initialization }
 | |
|     potype_unitfinalize, { unit finalization }
 | |
|     potype_constructor,  { Procedure is a constructor }
 | |
|     potype_destructor,   { Procedure is a destructor }
 | |
|     potype_operator,     { Procedure defines an operator }
 | |
|     potype_procedure,
 | |
|     potype_function,
 | |
|     potype_class_constructor, { class constructor }
 | |
|     potype_class_destructor   { class destructor  }
 | |
|   );
 | |
|   tproctypeoptions = set of tproctypeoption;
 | |
|   
 | |
|   tprocoption=(po_none,
 | |
|     po_classmethod,       { class method }
 | |
|     po_virtualmethod,     { Procedure is a virtual method }
 | |
|     po_abstractmethod,    { Procedure is an abstract method }
 | |
|     po_finalmethod,       { Procedure is a final method }
 | |
|     po_staticmethod,      { static method }
 | |
|     po_overridingmethod,  { method with override directive }
 | |
|     po_methodpointer,     { method pointer, only in procvardef, also used for 'with object do' }
 | |
|     po_interrupt,         { Procedure is an interrupt handler }
 | |
|     po_iocheck,           { IO checking should be done after a call to the procedure }
 | |
|     po_assembler,         { Procedure is written in assembler }
 | |
|     po_msgstr,            { method for string message handling }
 | |
|     po_msgint,            { method for int message handling }
 | |
|     po_exports,           { Procedure has export directive (needed for OS/2) }
 | |
|     po_external,          { Procedure is external (in other object or lib)}
 | |
|     po_overload,          { procedure is declared with overload directive }
 | |
|     po_varargs,           { printf like arguments }
 | |
|     po_internconst,       { procedure has constant evaluator intern }
 | |
|     { flag that only the address of a method is returned and not a full methodpointer }
 | |
|     po_addressonly,
 | |
|     { procedure is exported }
 | |
|     po_public,
 | |
|     { calling convention is specified explicitly }
 | |
|     po_hascallingconvention,
 | |
|     { reintroduce flag }
 | |
|     po_reintroduce,
 | |
|     { location of parameters is given explicitly as it is necessary for some syscall
 | |
|       conventions like that one of MorphOS }
 | |
|     po_explicitparaloc,
 | |
|     { no stackframe will be generated, used by lowlevel assembler like get_frame }
 | |
|     po_nostackframe,
 | |
|     po_has_mangledname,
 | |
|     po_has_public_name,
 | |
|     po_forward,
 | |
|     po_global,
 | |
|     po_has_inlininginfo, // deleted in PPUVersion 167
 | |
|     { The different kind of syscalls on MorphOS }
 | |
|     po_syscall_legacy,
 | |
|     po_syscall_sysv,
 | |
|     po_syscall_basesysv,
 | |
|     po_syscall_sysvbase,
 | |
|     po_syscall_r12base,
 | |
|     { Used to record the fact that a symbol is asociated to this syscall }
 | |
|     po_syscall_has_libsym,
 | |
|     { Procedure can be inlined }
 | |
|     po_inline,
 | |
|     { Procedure is used for internal compiler calls }
 | |
|     po_compilerproc,
 | |
|     { importing }
 | |
|     po_has_importdll,
 | |
|     po_has_importname,
 | |
|     po_kylixlocal,
 | |
|     po_dispid,
 | |
|     { weakly linked (i.e., may or may not exist at run time) }
 | |
|     po_weakexternal,
 | |
|     { Objective-C method }
 | |
|     po_objc,
 | |
|     { enumerator support }
 | |
|     po_enumerator_movenext,
 | |
|     { optional Objective-C protocol method }
 | |
|     po_optional,
 | |
|     { nested procedure that uses Delphi-style calling convention for passing
 | |
|       the frame pointer (pushed on the stack, always the last parameter,
 | |
|       removed by the caller). Required for nested procvar compatibility,
 | |
|       because such procvars can hold both regular and nested procedures
 | |
|       (when calling a regular procedure using the above convention, it will
 | |
|        simply not see the frame pointer parameter, and since the caller cleans
 | |
|        up the stack will also remain balanced) }
 | |
|     po_delphi_nested_cc,
 | |
|     { allows the routine's RawByteString var/out parameters to accept parameters
 | |
|       that do not match exactly (without typeconversion) }
 | |
|     po_rtlproc,
 | |
|     { Non-virtual method of a Java class that has been transformed into a
 | |
|       "virtual; final;" method for JVM-implementation reasons }
 | |
|     po_java_nonvirtual,
 | |
|     { automatically inherited routine from parent class, ignore for resolving
 | |
|       overloads (on the JVM target, constructors are not automatically
 | |
|       inherited, so we explicitly have to add the constructors of the parent
 | |
|       class to the child class; this influences the overload resolution logic
 | |
|       though, so ignore them there) }
 | |
|     po_ignore_for_overload_resolution,
 | |
|     { the visibility of of this procdef was raised automatically by the
 | |
|       compiler, e.g. because it was designated as a getter/setter for a property
 | |
|       with a higher visibility on the JVM target }
 | |
|     po_auto_raised_visibility,
 | |
|     { procedure is far (x86 only) }
 | |
|     po_far,
 | |
|     { the procedure never returns, this information is usefull for dfa }
 | |
|     po_noreturn
 | |
|   );
 | |
|   tprocoptions = set of tprocoption;
 | |
| 
 | |
|   { options that should not trigger the recompilation of a unit if they change
 | |
|     between the interface and the implementation }
 | |
|   timplprocoption = (
 | |
|     { the routine contains no code }
 | |
|     pio_empty,
 | |
|     { the inline body of this routine is available }
 | |
|     pio_has_inlininginfo
 | |
|   );
 | |
|   timplprocoptions = set of timplprocoption;
 | |
| 
 | |
| const
 | |
|   proccalloptionNames : array[tproccalloption] of string[14]=('',
 | |
|      'CDecl',
 | |
|      'CPPDecl',
 | |
|      'Far16',
 | |
|      'OldFPCCall',
 | |
|      'InternProc',
 | |
|      'SysCall',
 | |
|      'Pascal',
 | |
|      'Register',
 | |
|      'SafeCall',
 | |
|      'StdCall',
 | |
|      'SoftFloat',
 | |
|      'MWPascal'
 | |
|    );
 | |
|   proctypeoptionNames : array[tproctypeoption] of string[20]=(
 | |
|      'none',
 | |
|      'ProgInit',
 | |
|      'UnitInit',
 | |
|      'UnitFinalize',
 | |
|      'Constructor',
 | |
|      'Destructor',
 | |
|      'Operator',
 | |
|      'Procedure',
 | |
|      'Function',
 | |
|      'Class Constructor',
 | |
|      'Class Destructor'
 | |
|   );
 | |
|   procoptionNames : array[tprocoption] of string[30]=(
 | |
|     'none',
 | |
|     'classmethod',       { class method }
 | |
|     'virtualmethod',     { Procedure is a virtual method }
 | |
|     'abstractmethod',    { Procedure is an abstract method }
 | |
|     'finalmethod',       { Procedure is a final method }
 | |
|     'staticmethod',      { static method }
 | |
|     'overridingmethod',  { method with override directive }
 | |
|     'methodpointer',     { method pointer, only in procvardef, also used for 'with object do' }
 | |
|     'interrupt',         { Procedure is an interrupt handler }
 | |
|     'iocheck',           { IO checking should be done after a call to the procedure }
 | |
|     'assembler',         { Procedure is written in assembler }
 | |
|     'msgstr',            { method for string message handling }
 | |
|     'msgint',            { method for int message handling }
 | |
|     'exports',           { Procedure has export directive (needed for OS/2) }
 | |
|     'external',          { Procedure is external (in other object or lib)}
 | |
|     'overload',          { procedure is declared with overload directive }
 | |
|     'varargs',           { printf like arguments }
 | |
|     'internconst',       { procedure has constant evaluator intern }
 | |
|     { flag that only the address of a method is returned and not a full methodpointer }
 | |
|     'addressonly',
 | |
|     { procedure is exported }
 | |
|     'public',
 | |
|     { calling convention is specified explicitly }
 | |
|     'hascallingconvention',
 | |
|     { reintroduce flag }
 | |
|     'reintroduce',
 | |
|     { location of parameters is given explicitly as it is necessary for some syscall
 | |
|       conventions like that one of MorphOS }
 | |
|     'explicitparaloc',
 | |
|     { no stackframe will be generated', used by lowlevel assembler like get_frame }
 | |
|     'nostackframe',
 | |
|     'has_mangledname',
 | |
|     'has_public_name',
 | |
|     'forward',
 | |
|     'global',
 | |
|     'po_has_inlininginfo',
 | |
|     { The different kind of syscalls on MorphOS }
 | |
|     'syscall_legacy',
 | |
|     'syscall_sysv',
 | |
|     'syscall_basesysv',
 | |
|     'syscall_sysvbase',
 | |
|     'syscall_r12base',
 | |
|     { Used to record the fact that a symbol is asociated to this syscall }
 | |
|     'syscall_has_libsym',
 | |
|     { Procedure can be inlined }
 | |
|     'inline',
 | |
|     { Procedure is used for internal compiler calls }
 | |
|     'compilerproc',
 | |
|     { importing }
 | |
|     'has_importdll',
 | |
|     'has_importname',
 | |
|     'kylixlocal',
 | |
|     'dispid',
 | |
|     { weakly linked (i.e., may or may not exist at run time) }
 | |
|     'weakexternal',
 | |
|     { Objective-C method }
 | |
|     'objc',
 | |
|     { enumerator support }
 | |
|     'enumerator_movenext',
 | |
|     { optional Objective-C protocol method }
 | |
|     'optional',
 | |
|     { nested procedure that uses Delphi-style calling convention for passing
 | |
|       the frame pointer (pushed on the stack, always the last parameter,
 | |
|       removed by the caller). Required for nested procvar compatibility,
 | |
|       because such procvars can hold both regular and nested procedures
 | |
|       (when calling a regular procedure using the above convention, it will
 | |
|        simply not see the frame pointer parameter, and since the caller cleans
 | |
|        up the stack will also remain balanced) }
 | |
|     'delphi_nested_cc',
 | |
|     { allows the routine's RawByteString var/out parameters to accept parameters
 | |
|       that do not match exactly (without typeconversion) }
 | |
|     'rtlproc',
 | |
|     { Non-virtual method of a Java class that has been transformed into a
 | |
|       "virtual; final;" method for JVM-implementation reasons }
 | |
|     'java_nonvirtual',
 | |
|     { automatically inherited routine from parent class, ignore for resolving
 | |
|       overloads (on the JVM target, constructors are not automatically
 | |
|       inherited, so we explicitly have to add the constructors of the parent
 | |
|       class to the child class; this influences the overload resolution logic
 | |
|       though, so ignore them there) }
 | |
|     'ignore_for_overload_resolution',
 | |
|     { the visibility of of this procdef was raised automatically by the
 | |
|       compiler, e.g. because it was designated as a getter/setter for a property
 | |
|       with a higher visibility on the JVM target }
 | |
|     'auto_raised_visibility',
 | |
|     { procedure is far (x86 only) }
 | |
|     'far',
 | |
|     { the procedure never returns, this information is usefull for dfa }
 | |
|     'noreturn'
 | |
|   );
 | |
| 
 | |
| type
 | |
|   tsymoption=(
 | |
|     sp_none,
 | |
|     sp_public,
 | |
|     sp_private,
 | |
|     sp_published,
 | |
|     sp_protected,
 | |
|     sp_static,
 | |
|     sp_hint_deprecated,
 | |
|     sp_hint_platform,
 | |
|     sp_hint_library,
 | |
|     sp_hint_unimplemented,
 | |
|     sp_has_overloaded,
 | |
|     sp_internal  { internal symbol, not reported as unused }
 | |
|   );
 | |
|   tsymoptions=set of tsymoption;
 | |
| const
 | |
|   symoptionNames : array[tsymoption] of string[20]=(
 | |
|      '?',
 | |
|      'Public',
 | |
|      'Private',
 | |
|      'Published',
 | |
|      'Protected',
 | |
|      'Static',
 | |
|      'Hint Deprecated',
 | |
|      'Hint Platform',
 | |
|      'Hint Library',
 | |
|      'Hint Unimplemented',
 | |
|      'Has overloaded',
 | |
|      'Internal'
 | |
|   );
 | |
| 
 | |
| type
 | |
|   { flags for a definition }
 | |
|   tdefoption=(
 | |
|     df_none,
 | |
|     { type is unique, i.e. declared with type = type <tdef>; }
 | |
|     df_unique,
 | |
|     { type is a generic }
 | |
|     df_generic,
 | |
|     { type is a specialization of a generic type }
 | |
|     df_specialization,
 | |
|     df_genconstraint
 | |
|   );
 | |
|   tdefoptions=set of tdefoption;
 | |
| 
 | |
|   tdefstate=(
 | |
|     ds_none,
 | |
|     ds_vmt_written,
 | |
|     ds_rtti_table_used,
 | |
|     ds_init_table_used,
 | |
|     ds_rtti_table_written,
 | |
|     ds_init_table_written,
 | |
|     ds_dwarf_dbg_info_used,
 | |
|     ds_dwarf_dbg_info_written
 | |
|   );
 | |
|   tdefstates=set of tdefstate;
 | |
| 
 | |
|   { flags for generic type constraints }
 | |
|   tgenericconstraintflag=(gcf_none,
 | |
|     gcf_constructor,       { specialization type needs to have a constructor }
 | |
|     gcf_class,             { specialization type needs to be a class }
 | |
|     gcf_record             { specialization type needs to be a record type }
 | |
|   );
 | |
|   tgenericconstraintflags=set of tgenericconstraintflag;
 | |
| 
 | |
| const
 | |
|   defoptionNames : array[tdefoption] of string=(
 | |
|      '?',
 | |
|      'Unique Type',
 | |
|      'Generic',
 | |
|      'Specialization',
 | |
|      'Generic Constraint'
 | |
|   );
 | |
|   defstateNames : array[tdefstate] of string=(
 | |
|      '?',
 | |
|      'VMT Written',
 | |
|      'RTTITable Used',
 | |
|      'InitTable Used',
 | |
|      'RTTITable Written',
 | |
|      'InitTable Written',
 | |
|      'Dwarf DbgInfo Used',
 | |
|      'Dwarf DbgInfo Written'
 | |
|   );
 | |
| 
 | |
| type
 | |
|   TPPUPart = (
 | |
|     ppInterfaceHeader,
 | |
|     ppInterfaceDefinitions,
 | |
|     ppInterfaceSymbols,
 | |
|     ppInterfaceMacros,
 | |
|     ppImplementationHeader,
 | |
|     ppImplementationDefinitions,
 | |
|     ppImplementationSymbols
 | |
|   );
 | |
|   TPPUParts = set of TPPUPart;
 | |
|   
 | |
| const
 | |
|   PPUPartsAll = [low(TPPUPart)..high(TPPUPart)];
 | |
| 
 | |
| const
 | |
|   PPU_ID = 'PPU';
 | |
|   PPU_ID_Size = 3;
 | |
|   PPU_Ver_Size = 3;
 | |
| 
 | |
| type
 | |
|   TPPUHeader = packed record
 | |
|     id       : array[1..PPU_ID_Size] of char; { = 'PPU' }
 | |
|     ver      : array[1..PPU_Ver_Size] of char;
 | |
|     compiler : word;
 | |
|     cpu      : word;
 | |
|     target   : word;
 | |
|     flags    : longint;
 | |
|     size     : longint; { size of the ppufile without header }
 | |
|     checksum : cardinal; { checksum for this ppufile }
 | |
|     interface_checksum : cardinal;
 | |
|     deflistsize,
 | |
|     symlistsize : longint;
 | |
|     indirect_checksum: cardinal; // svn rev 14503
 | |
|   end;
 | |
| 
 | |
|   TPPUEntry = packed record
 | |
|     size : longint; // number of bytes following directly behind the entry
 | |
|     id   : byte;
 | |
|     nr   : byte;
 | |
|   end;
 | |
|   PPPUEntry = ^TPPUEntry;
 | |
| 
 | |
|   TPPU = class;
 | |
|   
 | |
|   { EPPUParserError }
 | |
| 
 | |
|   EPPUParserError = class(Exception)
 | |
|     Sender: TPPU;
 | |
|     constructor Create(ASender: TPPU; const AMessage: string);
 | |
|   end;
 | |
| 
 | |
|   TPPULinkedFile = class
 | |
|   public
 | |
|     ID: byte; // see iblinkunitofiles, iblink...
 | |
|     Filename: string;
 | |
|     Flags: Longint;
 | |
|   end;
 | |
| 
 | |
|   { TPPU }
 | |
| 
 | |
|   TPPU = class
 | |
|   private
 | |
|     FSizeOfAInt: integer;
 | |
|     FSizeOfASizeInt: integer;
 | |
|     fChangeEndian: boolean;
 | |
|     FHeader: TPPUHeader;
 | |
|     FEntry: TPPUEntry;
 | |
|     FEntryStart: integer;
 | |
|     FEntryPos: integer;
 | |
|     FEntryBuf: Pointer;
 | |
|     FEntryBufSize: integer;
 | |
|     FOwner: TObject;
 | |
|     FVersion: integer;
 | |
|     FDerefData: PByte;
 | |
|     FDerefDataSize: integer;
 | |
|     FData: Pointer;
 | |
|     FDataPos: integer;
 | |
|     FDataSize: integer;
 | |
|     FInterfaceHeaderPos: integer; // start of the interface header entries
 | |
|     FImplementationHeaderPos: integer; // start of the implementation header entries
 | |
|     FMainUsesSectionPos: integer;// start of the ibloadunit entry
 | |
|     FImplementationUsesSectionPos: integer;// start of the ibloadunit entry
 | |
|     FInitProcPos: integer;// start of the ibprocdef entry
 | |
|     FFinalProcPos: integer;// start of the ibprocdef entry
 | |
|     procedure ReadPPU(const Parts: TPPUParts);
 | |
|     procedure ReadHeader;
 | |
|     procedure ReadInterfaceHeader;
 | |
|     procedure ReadImplementationHeader;
 | |
|     function ReadEntry: byte;
 | |
|     function EndOfEntry: boolean;
 | |
|     procedure SkipUntilEntry(EntryNr: byte);
 | |
|     procedure ReadDataFromStream(s: TStream);
 | |
|     procedure ReadData(var Buf; Count: longint);
 | |
|     function ReadEntryByte: byte;
 | |
|     function ReadEntryByte(const Msg: string): byte;
 | |
|     function ReadEntryShortstring: shortstring;
 | |
|     function ReadEntryShortstring(const Msg: string): shortstring;
 | |
|     function ReadEntryAnsistring: ansistring;
 | |
|     function ReadEntryAnsistring(const Msg: string): ansistring;
 | |
|     function ReadEntryLongint: longint;
 | |
|     function ReadEntryLongint(const Msg: string): longint;
 | |
|     function ReadEntryDWord: cardinal;
 | |
|     function ReadEntryDWord(const Msg: string): cardinal;
 | |
|     function ReadEntryWord: word;
 | |
|     function ReadEntryWord(const Msg: string): word;
 | |
|     function ReadEntryInt64: int64;
 | |
|     function ReadEntryInt64(const Msg: string): int64;
 | |
|     function ReadEntryQWord: QWord;
 | |
|     function ReadEntryQWord(const Msg: string): QWord;
 | |
|     function ReadEntryAInt: int64;
 | |
|     function ReadEntryAInt(const Msg: string): int64;
 | |
|     function ReadEntryASizeInt: int64;
 | |
|     function ReadEntryASizeInt(const Msg: string): int64;
 | |
|     procedure ReadEntrySmallSet(out s);
 | |
|     procedure ReadEntryNormalSet(out s);
 | |
|     procedure ReadUsedUnits;
 | |
|     procedure ReadModuleOptions;
 | |
|     procedure ReadLinkContainer(aContainerType: byte);
 | |
|     procedure ReadResources;
 | |
|     procedure ReadImportSymbols;
 | |
|     procedure ReadDerefData;
 | |
|     procedure ReadDerefMap;
 | |
|     procedure ReadDereference;
 | |
|     procedure ReadPosInfo;
 | |
|     procedure ReadSymTableOptions;
 | |
|     procedure ReadDefinitions;
 | |
|     procedure ReadProcImplOptions(out ImplProcOptions: timplprocoptions);
 | |
|     procedure ReadSymbols;
 | |
|     procedure ReadNodeTree;
 | |
|     procedure ReadCommonDefinition;
 | |
|     procedure ReadAbstractProcDef(out proccalloption: tproccalloption;
 | |
|                                   out procoptions: tprocoptions;
 | |
|                                   out proctypeoption: tproctypeoption);
 | |
|     procedure ReadSymOptions;
 | |
|     procedure Skip(Count: integer);
 | |
|     procedure Error(const Msg: string);
 | |
|     
 | |
|     procedure GetUsesSection(StartPos: integer; var List: TStrings);
 | |
|     procedure SetDataPos(NewPos: integer);
 | |
|     function GetProcMangledName(ProcDefPos: integer): string;
 | |
|   public
 | |
|     constructor Create(TheOwner: TObject);
 | |
|     destructor Destroy; override;
 | |
|     procedure Clear;
 | |
|     procedure LoadFromStream(s: TStream; const Parts: TPPUParts = PPUPartsAll);
 | |
|     procedure LoadFromFile(const Filename: string; const Parts: TPPUParts = PPUPartsAll);
 | |
|     procedure Dump(const Prefix: string = '');
 | |
|     procedure DumpHeader(const Prefix: string = '');
 | |
|     procedure GetMainUsesSectionNames(var List: TStrings);
 | |
|     procedure GetImplementationUsesSectionNames(var List: TStrings);
 | |
|     procedure GetLinkedFiles(var ListOfTPPULinkedFile: TObjectList);
 | |
|     function GetInitProcName: string;
 | |
|     function GetFinalProcName: string;
 | |
|     property Version: integer read FVersion;
 | |
|     property Owner: TObject read FOwner;
 | |
|   end;
 | |
| 
 | |
| function PPUTargetToStr(w: longint): string;
 | |
| function PPUCpuToStr(w: longint): string;
 | |
| function PPUFlagsToStr(flags: longint): string;
 | |
| function PPUTimeToStr(t: longint): string;
 | |
| 
 | |
| function PPULinkContainerFlagToStr(Flags: longint): string;
 | |
| 
 | |
| function PPUEntryName(Entry: byte): string;
 | |
| 
 | |
| function ComparePPULinkedFiles(Item1, Item2: Pointer): integer;
 | |
| 
 | |
| implementation
 | |
| 
 | |
| function reverse_byte(b: byte): byte;
 | |
| const
 | |
|   reverse_nible: array[0..15] of 0..15 =
 | |
|     (%0000,%1000,%0100,%1100,%0010,%1010,%0110,%1110,
 | |
|      %0001,%1001,%0101,%1101,%0011,%1011,%0111,%1111);
 | |
| begin
 | |
|   Result:=(reverse_nible[b and $f] shl 4) or reverse_nible[b shr 4];
 | |
| end;
 | |
| 
 | |
| function PPUTargetToStr(w: longint): string;
 | |
| type
 | |
|        { taken from systems.pas }
 | |
|        ttarget =
 | |
|        (
 | |
|         system_none,               { 0 }
 | |
|         obsolete_system_i386_GO32V1,{ 1 }
 | |
|         system_i386_GO32V2,        { 2 }
 | |
|         system_i386_linux,         { 3 }
 | |
|         system_i386_OS2,           { 4 }
 | |
|         system_i386_Win32,         { 5 }
 | |
|         system_i386_freebsd,       { 6 }
 | |
|         system_m68k_Amiga,         { 7 }
 | |
|         system_m68k_Atari,         { 8 }
 | |
|         system_m68k_Mac,           { 9 }
 | |
|         system_m68k_linux,         { 10 }
 | |
|         system_m68k_PalmOS,        { 11 }
 | |
|         system_alpha_linux,        { 12 }
 | |
|         system_powerpc_linux,      { 13 }
 | |
|         system_powerpc_macos,      { 14 }
 | |
|         system_i386_solaris,       { 15 }
 | |
|         system_i386_beos,          { 16 }
 | |
|         system_i386_netbsd,        { 17 }
 | |
|         system_m68k_netbsd,        { 18 }
 | |
|         system_i386_Netware,       { 19 }
 | |
|         system_i386_qnx,           { 20 }
 | |
|         system_i386_wdosx,         { 21 }
 | |
|         system_sparc_solaris,      { 22 }
 | |
|         system_sparc_linux,        { 23 }
 | |
|         system_i386_openbsd,       { 24 }
 | |
|         system_m68k_openbsd,       { 25 }
 | |
|         system_x86_64_linux,       { 26 }
 | |
|         system_powerpc_darwin,     { 27 }
 | |
|         system_i386_emx,           { 28 }
 | |
|         system_powerpc_netbsd,     { 29 }
 | |
|         system_powerpc_openbsd,    { 30 }
 | |
|         system_arm_linux,          { 31 }
 | |
|         system_i386_watcom,        { 32 }
 | |
|         system_powerpc_MorphOS,    { 33 }
 | |
|         system_x86_64_freebsd,     { 34 }
 | |
|         system_i386_netwlibc,      { 35 }
 | |
|         system_powerpc_Amiga,      { 36 }
 | |
|         system_x86_64_win64,       { 37 }
 | |
|         system_arm_wince,          { 38 }
 | |
|         system_ia64_win64,         { 39 }
 | |
|         system_i386_wince,         { 40 }
 | |
|         system_x86_6432_linux,     { 41 }
 | |
|         system_arm_gba,            { 42 }
 | |
|         system_powerpc64_linux,    { 43 }
 | |
|         system_i386_darwin,        { 44 }
 | |
|         system_arm_palmos,         { 45 }
 | |
|         system_powerpc64_darwin,   { 46 }
 | |
|         system_arm_nds,            { 47 }
 | |
|         system_i386_embedded,      { 48 }
 | |
|         system_m68k_embedded,      { 49 }
 | |
|         system_alpha_embedded,     { 50 }
 | |
|         system_powerpc_embedded,   { 51 }
 | |
|         system_sparc_embedded,     { 52 }
 | |
|         system_vm_embedded,        { 53 }
 | |
|         system_iA64_embedded,      { 54 }
 | |
|         system_x86_64_embedded,    { 55 }
 | |
|         system_mips_embedded,      { 56 }
 | |
|         system_arm_embedded,       { 57 }
 | |
|         system_powerpc64_embedded, { 58 }
 | |
|         system_i386_symbian,       { 59 }
 | |
|         system_arm_symbian,        { 60 }
 | |
|         system_x86_64_darwin,      { 61 }
 | |
|         system_avr_embedded,       { 62 }
 | |
|         system_i386_haiku,         { 63 }
 | |
|         system_arm_darwin,         { 64 }
 | |
|         system_x86_64_solaris,     { 65 }
 | |
|         system_mips_linux,         { 66 }
 | |
|         system_mipsel_linux,       { 67 }
 | |
|         system_i386_nativent,      { 68 }
 | |
|         system_i386_iphonesim,     { 69 }
 | |
|         system_powerpc_wii,        { 70 }
 | |
|         system_x86_64_openbsd,     { 71 }
 | |
|         system_x86_64_netbsd,      { 72 }
 | |
|         system_powerpc_aix,        { 73 }
 | |
|         system_powerpc64_aix,      { 74 }
 | |
|         system_jvm_java32,         { 75 }
 | |
|         system_jvm_android32,      { 76 }
 | |
|         system_arm_android,        { 77 }
 | |
|         system_i386_android,       { 78 }
 | |
|         system_i8086_msdos,        { 79 }
 | |
|         system_mipsel_android,     { 80 }
 | |
|         system_mipseb_embedded,    { 81 }
 | |
|         system_mipsel_embedded,    { 82 }
 | |
|         system_i386_aros,          { 83 }
 | |
|         system_x86_64_aros,        { 84 }
 | |
|         system_x86_64_dragonfly,   { 85 }
 | |
|         system_aarch64_darwin,     { 85 }
 | |
|         system_x86_64_iphonesim    { 86 }
 | |
|       );
 | |
| const
 | |
|   // taken form ppudump.pp
 | |
|   Targets : array[ttarget] of string[18]=(
 | |
|   { 0 }   'none',
 | |
|   { 1 }   'GO32V1 (obsolete)',
 | |
|   { 2 }   'GO32V2',
 | |
|   { 3 }   'Linux-i386',
 | |
|   { 4 }   'OS/2',
 | |
|   { 5 }   'Win32',
 | |
|   { 6 }   'FreeBSD-i386',
 | |
|   { 7 }   'Amiga',
 | |
|   { 8 }   'Atari',
 | |
|   { 9 }   'MacOS-m68k',
 | |
|   { 10 }  'Linux-m68k',
 | |
|   { 11 }  'PalmOS-m68k',
 | |
|   { 12 }  'Linux-alpha',
 | |
|   { 13 }  'Linux-ppc',
 | |
|   { 14 }  'MacOS-ppc',
 | |
|   { 15 }  'Solaris-i386',
 | |
|   { 16 }  'BeOS-i386',
 | |
|   { 17 }  'NetBSD-i386',
 | |
|   { 18 }  'NetBSD-m68k',
 | |
|   { 19 }  'Netware-i386-clib',
 | |
|   { 20 }  'Qnx-i386',
 | |
|   { 21 }  'WDOSX-i386',
 | |
|   { 22 }  'Solaris-sparc',
 | |
|   { 23 }  'Linux-sparc',
 | |
|   { 24 }  'OpenBSD-i386',
 | |
|   { 25 }  'OpenBSD-m68k',
 | |
|   { 26 }  'Linux-x86-64',
 | |
|   { 27 }  'MacOSX-ppc',
 | |
|   { 28 }  'OS/2 via EMX',
 | |
|   { 29 }  'NetBSD-powerpc',
 | |
|   { 30 }  'OpenBSD-powerpc',
 | |
|   { 31 }  'Linux-arm',
 | |
|   { 32 }  'Watcom-i386',
 | |
|   { 33 }  'MorphOS-powerpc',
 | |
|   { 34 }  'FreeBSD-x86-64',
 | |
|   { 35 }  'Netware-i386-libc',
 | |
|   { 36 }  'Amiga-PowerPC',
 | |
|   { 37 }  'Win64-x64',
 | |
|   { 38 }  'WinCE-ARM',
 | |
|   { 39 }  'Win64-iA64',
 | |
|   { 40 }  'WinCE-i386',
 | |
|   { 41 }  'Linux-x64',
 | |
|   { 42 }  'GBA-arm',
 | |
|   { 43 }  'Linux-powerpc64',
 | |
|   { 44 }  'Darwin-i386',
 | |
|   { 45 }  'PalmOS-arm',
 | |
|   { 46 }  'MacOSX-powerpc64',
 | |
|   { 47 }  'NDS-arm',
 | |
|   { 48 }  'Embedded-i386',
 | |
|   { 49 }  'Embedded-m68k',
 | |
|   { 50 }  'Embedded-alpha',
 | |
|   { 51 }  'Embedded-powerpc',
 | |
|   { 52 }  'Embedded-sparc',
 | |
|   { 53 }  'Embedded-vm',
 | |
|   { 54 }  'Embedded-iA64',
 | |
|   { 55 }  'Embedded-x64',
 | |
|   { 56 }  'Embedded-mips',
 | |
|   { 57 }  'Embedded-arm',
 | |
|   { 58 }  'Embedded-powerpc64',
 | |
|   { 59 }  'Symbian-i386',
 | |
|   { 60 }  'Symbian-arm',
 | |
|   { 61 }  'MacOSX-x64',
 | |
|   { 62 }  'Embedded-avr',
 | |
|   { 63 }  'Haiku-i386',
 | |
|   { 64 }  'Darwin-ARM',
 | |
|   { 65 }  'Solaris-x86-64',
 | |
|   { 66 }  'Linux-MIPS',
 | |
|   { 67 }  'Linux-MIPSel',
 | |
|   { 68 }  'NativeNT-i386',
 | |
|   { 69 }  'iPhoneSim-i386',
 | |
|   { 70 }  'Wii-powerpc',
 | |
|   { 71 }  'OpenBSD-x86-64',
 | |
|   { 72 }  'NetBSD-x86-64',
 | |
|   { 73 }  'AIX-powerpc',
 | |
|   { 74 }  'AIX-powerpc64',
 | |
|   { 75 }  'Java-JVM',
 | |
|   { 76 }  'Android-JVM',
 | |
|   { 77 }  'Android-arm',
 | |
|   { 78 }  'Android-i386',
 | |
|   { 79 }  'MSDOS-i8086',
 | |
|   { 80 }  'Android-MIPSel',
 | |
|   { 81 }  'Embedded-mipseb',
 | |
|   { 82 }  'Embedded-mipsel',
 | |
|   { 83 }  'AROS-i386',
 | |
|   { 84 }  'AROS-x86-64',
 | |
|   { 85 }  'DragonFly-x86-64',
 | |
|   { 85 }  'Darwin-AArch64',
 | |
|   { 86 }  'iPhoneSim-x86-64'
 | |
|   );
 | |
| begin
 | |
|   if w<=ord(high(ttarget)) then
 | |
|     Result:=Targets[ttarget(w)]
 | |
|   else
 | |
|     Result:='<!! Unknown target value '+IntToStr(w)+'>';
 | |
| end;
 | |
| 
 | |
| function PPUCpuToStr(w:longint):string;
 | |
| begin
 | |
|   if w<=ord(high(tsystemcpu)) then
 | |
|     Result:=PPU_CPUNames[tsystemcpu(w)]
 | |
|   else
 | |
|     Result:='<!! Unknown cpu value '+IntToStr(w)+'>';
 | |
| end;
 | |
| 
 | |
| function PPUFlagsToStr(flags:longint):string;
 | |
| type
 | |
|   tflagopt=record
 | |
|     mask : longint;
 | |
|     str  : string[30];
 | |
|   end;
 | |
| const
 | |
|   flagopts=17;
 | |
|   flagopt : array[1..flagopts] of tflagopt=(
 | |
|     (mask: $1    ;str:'init'),
 | |
|     (mask: $2    ;str:'final'),
 | |
|     (mask: $4    ;str:'big_endian'),
 | |
|     (mask: $8    ;str:'dbx'),
 | |
| //    (mask: $10   ;str:'browser'),
 | |
|     (mask: $20   ;str:'in_library'),
 | |
|     (mask: $40   ;str:'smart_linked'),
 | |
|     (mask: $80   ;str:'static_linked'),
 | |
|     (mask: $100  ;str:'shared_linked'),
 | |
| //    (mask: $200  ;str:'local_browser'),
 | |
|     (mask: $400  ;str:'no_link'),
 | |
|     (mask: $800  ;str:'has_resources'),
 | |
|     (mask: $1000  ;str:'little_endian'),
 | |
|     (mask: $2000  ;str:'release'),
 | |
|     (mask: $4000  ;str:'local_threadvars'),
 | |
|     (mask: $8000  ;str:'fpu_emulation_on'),
 | |
|     (mask: $10000  ;str:'has_debug_info'),
 | |
|     (mask: $20000  ;str:'local_symtable'),
 | |
|     (mask: $40000  ;str:'uses_variants')
 | |
|   );
 | |
| var
 | |
|   i : longint;
 | |
|   first  : boolean;
 | |
|   s : string;
 | |
| begin
 | |
|   s:='';
 | |
|   if flags<>0 then
 | |
|    begin
 | |
|      first:=true;
 | |
|      for i:=1to flagopts do
 | |
|       if (flags and flagopt[i].mask)<>0 then
 | |
|        begin
 | |
|          if first then
 | |
|            first:=false
 | |
|          else
 | |
|            s:=s+', ';
 | |
|          s:=s+flagopt[i].str;
 | |
|        end;
 | |
|    end
 | |
|   else
 | |
|    s:='none';
 | |
|   Result:=s;
 | |
| end;
 | |
| 
 | |
| function L0(l: longint): shortstring;
 | |
| {
 | |
|   return the string of value l, if l<10 then insert a zero, so
 | |
|   the string is always at least 2 chars '01','02',etc
 | |
| }
 | |
| var
 | |
|   s : shortstring;
 | |
| begin
 | |
|   Str(l,s);
 | |
|   if l<10 then
 | |
|     s:='0'+s;
 | |
|   Result:=s;
 | |
| end;
 | |
| 
 | |
| function PPUTimeToStr(t: longint): string;
 | |
| {
 | |
|   convert dos datetime t to a string YY/MM/DD HH:MM:SS
 | |
| }
 | |
| var
 | |
|   DT: TDateTime;
 | |
|   hsec: word;
 | |
|   Year, Month, Day: Word;
 | |
|   hour, min, sec: word;
 | |
| begin
 | |
|   if t=-1 then
 | |
|   begin
 | |
|     Result := '<invalid time>';
 | |
|     exit;
 | |
|   end;
 | |
|   DT := FileDateToDateTimeDef(t);
 | |
|   DecodeTime(DT,hour,min,sec,hsec);
 | |
|   DecodeDate(DT,year,month,day);
 | |
|   Result := L0(Year)+'/'+L0(Month)+'/'+L0(Day)+' '+L0(Hour)+':'+L0(min)+':'+L0(sec);
 | |
| end;
 | |
| 
 | |
| function PPULinkContainerFlagToStr(Flags: longint): string;
 | |
| const
 | |
|   { link options }
 | |
|   //link_none    = $0;
 | |
|   link_always  = $1;
 | |
|   link_static  = $2;
 | |
|   link_smart   = $4;
 | |
|   link_shared  = $8;
 | |
| begin
 | |
|   Result:='';
 | |
|   if (Flags and link_always)<>0 then
 | |
|     Result:=Result+'always,';
 | |
|   if (Flags and link_static)<>0 then
 | |
|     Result:=Result+'static,';
 | |
|   if (Flags and link_smart)<>0 then
 | |
|     Result:=Result+'smart,';
 | |
|   if (Flags and link_shared)<>0 then
 | |
|     Result:=Result+'shared,';
 | |
|   if Result<>'' then Result:=copy(Result,1,length(Result)-1);
 | |
| end;
 | |
| 
 | |
| function PPUEntryName(Entry: byte): string;
 | |
| begin
 | |
|   case Entry of
 | |
|   iberror:             Result:='iberror';
 | |
|   ibstartdefs:         Result:='ibstartdefs';
 | |
|   ibenddefs:           Result:='ibenddefs';
 | |
|   ibstartsyms:         Result:='ibstartsyms';
 | |
|   ibendsyms:           Result:='ibendsyms';
 | |
|   ibendinterface:      Result:='ibendinterface';
 | |
|   ibendimplementation: Result:='ibendimplementation';
 | |
|   ibendbrowser:        Result:='ibendbrowser';
 | |
|   ibend:               Result:='ibend';
 | |
|   {general}
 | |
|   ibmodulename:           Result:='ibmodulename';
 | |
|   ibsourcefiles:          Result:='ibsourcefiles';
 | |
|   ibloadunit:             Result:='ibloadunit';
 | |
|   ibinitunit:             Result:='ibinitunit';
 | |
|   iblinkunitofiles:       Result:='iblinkunitofiles';
 | |
|   iblinkunitstaticlibs:   Result:='iblinkunitstaticlibs';
 | |
|   iblinkunitsharedlibs:   Result:='iblinkunitsharedlibs';
 | |
|   iblinkotherofiles:      Result:='iblinkotherofiles';
 | |
|   iblinkotherstaticlibs:  Result:='iblinkotherstaticlibs';
 | |
|   iblinkothersharedlibs:  Result:='iblinkothersharedlibs';
 | |
|   ibImportSymbols:        Result:='ibImportSymbols';
 | |
|   ibsymref:               Result:='ibsymref';
 | |
|   ibdefref:               Result:='ibdefref';
 | |
|   ibendsymtablebrowser:   Result:='ibendsymtablebrowser';
 | |
|   ibbeginsymtablebrowser: Result:='ibbeginsymtablebrowser';
 | |
|   ibusedmacros:           Result:='ibusedmacros';
 | |
|   ibderefdata:            Result:='ibderefdata';
 | |
|   ibexportedmacros:       Result:='ibexportedmacros';
 | |
|   ibderefmap:             Result:='ibderefmap';
 | |
|   {syms}
 | |
|   ibtypesym:        Result:='ibtypesym';
 | |
|   ibprocsym:        Result:='ibprocsym';
 | |
|   ibstaticvarsym:   Result:='ibstaticvarsym';
 | |
|   ibconstsym:       Result:='ibconstsym';
 | |
|   ibenumsym:        Result:='ibenumsym';
 | |
|   ibtypedconstsym:  Result:='ibtypedconstsym';
 | |
|   ibabsolutevarsym: Result:='ibabsolutevarsym';
 | |
|   ibpropertysym:    Result:='ibpropertysym';
 | |
|   ibfieldvarsym:    Result:='ibfieldvarsym';
 | |
|   ibunitsym:        Result:='ibunitsym';
 | |
|   iblabelsym:       Result:='iblabelsym';
 | |
|   ibsyssym:         Result:='ibsyssym';
 | |
|   ibrttisym:        Result:='ibrttisym';
 | |
|   iblocalvarsym:    Result:='iblocalvarsym';
 | |
|   ibparavarsym:     Result:='ibparavarsym';
 | |
|   ibmacrosym:       Result:='ibmacrosym';
 | |
|   {definitions}
 | |
|   iborddef:         Result:='iborddef';
 | |
|   ibpointerdef:     Result:='ibpointerdef';
 | |
|   ibarraydef:       Result:='ibarraydef';
 | |
|   ibprocdef:        Result:='ibprocdef';
 | |
|   ibshortstringdef: Result:='ibshortstringdef';
 | |
|   ibrecorddef:      Result:='ibrecorddef';
 | |
|   ibfiledef:        Result:='ibfiledef';
 | |
|   ibformaldef:      Result:='ibformaldef';
 | |
|   ibobjectdef:      Result:='ibobjectdef';
 | |
|   ibenumdef:        Result:='ibenumdef';
 | |
|   ibsetdef:         Result:='ibsetdef';
 | |
|   ibprocvardef:     Result:='ibprocvardef';
 | |
|   ibfloatdef:       Result:='ibfloatdef';
 | |
|   ibclassrefdef:    Result:='ibclassrefdef';
 | |
|   iblongstringdef:  Result:='iblongstringdef';
 | |
|   ibansistringdef:  Result:='ibansistringdef';
 | |
|   ibwidestringdef:  Result:='ibwidestringdef';
 | |
|   ibvariantdef:     Result:='ibvariantdef';
 | |
|   ibundefineddef:   Result:='ibundefineddef';
 | |
|   ibunicodestringdef: Result:='ibunicodestringdef';
 | |
|   {implementation/ObjData}
 | |
|   ibnodetree:       Result:='ibnodetree';
 | |
|   ibasmsymbols:     Result:='ibasmsymbols';
 | |
|   ibresources:      Result:='ibresources';
 | |
|   ibcreatedobjtypes:Result:='ibcreatedobjtypes';
 | |
|   ibwpofile:        Result:='ibwpofile';
 | |
|   ibmoduleoptions:  Result:='ibmoduleoptions';
 | |
| 
 | |
|   ibmainname:       Result:='ibmainname';
 | |
|   ibsymtableoptions:Result:='ibsymtableoptions';
 | |
|   //ibrecsymtableoptions: duplicate with ibsymtableoptions
 | |
|   { target-specific things }
 | |
|   iblinkotherframeworks: Result:='iblinkotherframeworks';
 | |
|   ibjvmnamespace:   Result:='ibjvmnamespace';
 | |
|   else Result:='unknown('+IntToStr(Entry)+')';
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| function ComparePPULinkedFiles(Item1, Item2: Pointer): integer;
 | |
| var
 | |
|   File1: TPPULinkedFile absolute Item1;
 | |
|   File2: TPPULinkedFile absolute Item2;
 | |
| begin
 | |
|   if File1.ID<File2.ID then exit(1)
 | |
|   else if File1.ID>File2.ID then exit(-1);
 | |
|   Result:=CompareFilenames(File1.Filename,File2.Filename);
 | |
|   if Result<>0 then exit;
 | |
|   if File1.Flags<File2.Flags then exit(1)
 | |
|   else if File1.Flags>File2.Flags then exit(-1);
 | |
|   Result:=0;
 | |
| end;
 | |
| 
 | |
| { EPPUParserError }
 | |
| 
 | |
| constructor EPPUParserError.Create(ASender: TPPU; const AMessage: string);
 | |
| begin
 | |
|   Sender:=ASender;
 | |
|   inherited Create(AMessage);
 | |
| end;
 | |
| 
 | |
| { TPPU }
 | |
| 
 | |
| procedure TPPU.ReadPPU(const Parts: TPPUParts);
 | |
| begin
 | |
|   ReadHeader;
 | |
| 
 | |
|   // interface header
 | |
|   if ppInterfaceHeader in Parts then
 | |
|     ReadInterfaceHeader
 | |
|   else
 | |
|     SkipUntilEntry(ibendinterface);
 | |
| 
 | |
|   if Version>=128 then
 | |
|     ReadSymTableOptions;
 | |
| 
 | |
|   // interface definitions
 | |
|   if ppInterfaceDefinitions in Parts then
 | |
|     ReadDefinitions
 | |
|   else
 | |
|     SkipUntilEntry(ibenddefs);
 | |
| 
 | |
|   // Interface Symbols
 | |
|   SkipUntilEntry(ibendsyms);
 | |
| 
 | |
|   // Interface Macros
 | |
|   if ReadEntry=ibexportedmacros then begin
 | |
|     if boolean(ReadEntryByte) then begin
 | |
|       // skip the definition section for macros (since they are never used)
 | |
|       SkipUntilEntry(ibenddefs);
 | |
|       // read the macro symbols
 | |
|       SkipUntilEntry(ibendsyms);
 | |
|     end;
 | |
|   end;
 | |
| 
 | |
|   // Implementation Header
 | |
|   if ppImplementationHeader in Parts then
 | |
|     ReadImplementationHeader
 | |
|   else
 | |
|     SkipUntilEntry(ibendimplementation);
 | |
| 
 | |
|   // Implementation Definitions and Symbols
 | |
|   if (FHeader.flags and uf_local_symtable)<>0 then begin
 | |
|     if Version>=128 then
 | |
|       ReadSymTableOptions;
 | |
|     if ppImplementationDefinitions in Parts then
 | |
|       ReadDefinitions
 | |
|     else
 | |
|       SkipUntilEntry(ibenddefs);
 | |
|     SkipUntilEntry(ibendsyms);
 | |
|   end else begin
 | |
|     // no definitions and no symbols
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadHeader;
 | |
| var
 | |
|   cpu: tsystemcpu;
 | |
| begin
 | |
|   fChangeEndian:=PPUIsEndianBig;
 | |
|   // read ID
 | |
|   ReadData(FHeader.id,PPU_ID_Size);
 | |
|   if String(FHeader.id)<>PPU_ID then
 | |
|     Error('This is not a PPU. Wrong ID.');
 | |
|   // read Version
 | |
|   ReadData(FHeader.ver,PPU_Ver_Size);
 | |
|   FVersion:=StrToIntDef(String(FHeader.ver),0);
 | |
|   if FVersion<16 then
 | |
|     Error('Old PPU versions (<16) are not supported.');
 | |
|   // read rest of header
 | |
|   ReadData(FHeader.compiler,SizeOf(TPPUHeader)-PPU_Ver_Size-PPU_ID_Size);
 | |
|   if fChangeEndian then begin
 | |
|     fHeader.compiler := swapendian(fHeader.compiler);
 | |
|     fHeader.cpu := swapendian(fHeader.cpu);
 | |
|     fHeader.target := swapendian(fHeader.target);
 | |
|     fHeader.flags := swapendian(fHeader.flags);
 | |
|     fHeader.size := swapendian(fHeader.size);
 | |
|     fHeader.checksum := swapendian(fHeader.checksum);
 | |
|     fHeader.interface_checksum := swapendian(fHeader.interface_checksum);
 | |
|     fHeader.deflistsize := swapendian(fHeader.deflistsize);
 | |
|     fHeader.symlistsize := swapendian(fHeader.symlistsize);
 | |
|   end;
 | |
|   fChangeEndian:=((FHeader.flags and uf_big_endian) = uf_big_endian)<>PPUIsEndianBig;
 | |
| 
 | |
|   FEntryPos:=0;
 | |
|   FillByte(FEntry,SizeOf(FEntry),0);
 | |
| 
 | |
|   {$R-}
 | |
|   cpu:=tsystemcpu(FHeader.cpu);
 | |
|   if (cpu<low(tsystemcpu)) or (cpu>high(tsystemcpu)) then
 | |
|     cpu:=tsystemcpu(FHeader.cpu);
 | |
|   {$R+}
 | |
|   FSizeOfAInt:=CpuAluBitSize[cpu] div 8;
 | |
|   FSizeOfASizeInt:=CpuAddrBitSize[cpu] div 8;
 | |
| 
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   DumpHeader('');
 | |
|   {$ENDIF}
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadInterfaceHeader;
 | |
| var
 | |
|   EntryNr: Byte;
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   ModuleName: ShortString;
 | |
|   Filename: ShortString;
 | |
|   FileTime: LongInt;
 | |
|   Conditional: ShortString;
 | |
|   DefinedAtStartUp: Boolean;
 | |
|   IsUsed: Boolean;
 | |
|   {$ENDIF}
 | |
| begin
 | |
|   FInterfaceHeaderPos:=FDataPos;
 | |
|   repeat
 | |
|     EntryNr:=ReadEntry;
 | |
|     {$IFDEF VerbosePPUParser}
 | |
|     DebugLn(['TPPU.ReadInterface EntryNr=',EntryNr,'=',PPUEntryName(EntryNr)]);
 | |
|     {$ENDIF}
 | |
|     case EntryNr of
 | |
|     
 | |
|     ibmodulename:
 | |
|       begin
 | |
|         {$IFDEF VerbosePPUParser}ModuleName:={$ENDIF}ReadEntryShortstring;
 | |
|         {$IFDEF VerbosePPUParser}
 | |
|         DebugLn(['TPPU.ReadInterfaceHeader ModuleName=',ModuleName]);
 | |
|         {$ENDIF}
 | |
|       end;
 | |
| 
 | |
|     ibmoduleoptions:
 | |
|       ReadModuleOptions;
 | |
|     
 | |
|     ibsourcefiles:
 | |
|       begin
 | |
|         while not EndOfEntry do
 | |
|         begin
 | |
|           {$IFDEF VerbosePPUParser}Filename:={$ENDIF}ReadEntryShortstring;// filename
 | |
|           {$IFDEF VerbosePPUParser}FileTime:={$ENDIF}ReadEntryLongint;// file time
 | |
|           {$IFDEF VerbosePPUParser}
 | |
|           DebugLn(['TPPU.ReadInterfaceHeader SourceFile=',Filename,' Time=',PPUTimeToStr(FileTime)]);
 | |
|           {$ENDIF}
 | |
|         end;
 | |
|       end;
 | |
|       
 | |
|     ibloadunit:
 | |
|       begin
 | |
|         FMainUsesSectionPos:=FEntryStart;
 | |
|         ReadUsedUnits;
 | |
|       end;
 | |
| 
 | |
|     iblinkunitofiles,iblinkunitstaticlibs,iblinkunitsharedlibs,
 | |
|     iblinkotherofiles,iblinkotherstaticlibs,iblinkothersharedlibs,
 | |
|     iblinkotherframeworks:
 | |
|       ReadLinkContainer(EntryNr);
 | |
| 
 | |
|     ibresources:
 | |
|       ReadResources;
 | |
|       
 | |
|     ibImportSymbols:
 | |
|       ReadImportSymbols;
 | |
| 
 | |
|     ibusedmacros:
 | |
|       begin
 | |
|         while not EndOfEntry do
 | |
|         begin
 | |
|           {$IFDEF VerbosePPUParser}Conditional:={$ENDIF}ReadEntryShortstring;
 | |
|           {$IFDEF VerbosePPUParser}DefinedAtStartUp:=boolean(ReadEntryByte){$ELSE}ReadEntryByte{$ENDIF};
 | |
|           {$IFDEF VerbosePPUParser}IsUsed:=boolean(ReadEntryByte){$ELSE}ReadEntryByte{$ENDIF};
 | |
|           {$IFDEF VerbosePPUParser}
 | |
|           DebugLn(['TPPU.ReadInterfaceHeader Macro=',Conditional,' DefinedAtStartUp=',DefinedAtStartUp,' Used=',IsUsed]);
 | |
|           {$ENDIF}
 | |
|         end;
 | |
|       end;
 | |
| 
 | |
|     ibderefdata:
 | |
|       ReadDerefData;
 | |
| 
 | |
|     ibderefmap:
 | |
|       ReadDerefMap;
 | |
| 
 | |
|     ibendinterface:
 | |
|       break;
 | |
|        
 | |
|     else
 | |
|       {$IFDEF VerbosePPUParser}
 | |
|       DebugLn(['TPPU.ReadInterfaceHeader Skipping unsupported entry ',EntryNr]);
 | |
|       {$ENDIF}
 | |
|       FEntryPos:=FEntry.size;
 | |
|     end;
 | |
|   until false;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadImplementationHeader;
 | |
| var
 | |
|   EntryNr: Byte;
 | |
| begin
 | |
|   FImplementationHeaderPos:=FDataPos;
 | |
|   repeat
 | |
|     EntryNr:=ReadEntry;
 | |
|     case EntryNr of
 | |
| 
 | |
|     // ToDo: ibasmsymbols
 | |
|     
 | |
|     ibloadunit:
 | |
|       begin
 | |
|         FImplementationUsesSectionPos:=FEntryStart;
 | |
|         ReadUsedUnits;
 | |
|       end;
 | |
| 
 | |
|     ibendimplementation:
 | |
|       break;
 | |
| 
 | |
|     else
 | |
|       {$IFDEF VerbosePPUParser}
 | |
|       DebugLn(['TPPU.ReadImplementationHeader Skipping unsupported entry ',EntryNr]);
 | |
|       {$ENDIF}
 | |
|       FEntryPos:=FEntry.size;
 | |
|     end;
 | |
|   until false;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadDefinitions;
 | |
| type
 | |
|   {
 | |
|   tsettype  = (normset,smallset,varset);
 | |
| 
 | |
|   tordtype = (
 | |
|     uvoid,
 | |
|     u8bit,u16bit,u32bit,u64bit,
 | |
|     s8bit,s16bit,s32bit,s64bit,
 | |
|     bool8bit,bool16bit,bool32bit,bool64bit,
 | |
|     uchar,uwidechar,scurrency
 | |
|   );
 | |
| 
 | |
|   tobjecttyp = (odt_none,
 | |
|     odt_class,
 | |
|     odt_object,
 | |
|     odt_interfacecom,
 | |
|     odt_interfacecorba,
 | |
|     odt_cppclass,
 | |
|     odt_dispinterface
 | |
|   );
 | |
| 
 | |
|   tvarianttype = (
 | |
|     vt_normalvariant,vt_olevariant
 | |
|   );
 | |
|   }
 | |
| 
 | |
|   tprocinfoflag=(
 | |
|     {# procedure uses asm }
 | |
|     pi_uses_asm,
 | |
|     {# procedure does a call }
 | |
|     pi_do_call,
 | |
|     {# procedure has a try statement = no register optimization }
 | |
|     pi_uses_exceptions,
 | |
|     {# procedure is declared as @var(assembler), don't optimize}
 | |
|     pi_is_assembler,
 | |
|     {# procedure contains data which needs to be finalized }
 | |
|     pi_needs_implicit_finally
 | |
|   );
 | |
|   //tprocinfoflags=set of tprocinfoflag;
 | |
| 
 | |
|   tsystemcpu=
 | |
|   (
 | |
|     cpu_no,                       { 0 }
 | |
|     cpu_i386,                     { 1 }
 | |
|     cpu_m68k,                     { 2 }
 | |
|     cpu_alpha,                    { 3 }
 | |
|     cpu_powerpc,                  { 4 }
 | |
|     cpu_sparc,                    { 5 }
 | |
|     cpu_vm,                       { 6 }
 | |
|     cpu_iA64,                     { 7 }
 | |
|     cpu_x86_64,                   { 8 }
 | |
|     cpu_mips,                     { 9 }
 | |
|     cpu_arm                       { 10 }
 | |
|   );
 | |
| var
 | |
|   EntryNr: Byte;
 | |
|   calloption: tproccalloption;
 | |
|   procoptions: tprocoptions;
 | |
|   procinfooptions : tprocinfoflag;
 | |
|   proctypeoption: tproctypeoption;
 | |
|   ImplProcOptions: timplprocoptions;
 | |
|   CurEntryStart: LongInt;
 | |
|   HasInliningInfo: Boolean;
 | |
| begin
 | |
|   EntryNr:=ReadEntry;
 | |
|   if EntryNr<>ibstartdefs then
 | |
|   begin
 | |
|     Error('expected ibstartdefs, but found '+PPUEntryName(EntryNr));
 | |
|   end;
 | |
|   repeat
 | |
|     EntryNr:=ReadEntry;
 | |
|     CurEntryStart:=FEntryStart;
 | |
|     case EntryNr of
 | |
|     
 | |
|     ibpointerdef:
 | |
|       begin
 | |
|         {$IFDEF VerbosePPUParser} DebugLn(['TPPU.ReadDefinitions Pointer definition:']); {$ENDIF}
 | |
|         ReadCommonDefinition;
 | |
|         {$IFDEF VerbosePPUParser} DebugLn(['TPPU.ReadDefinitions Pointed type:']); {$ENDIF}
 | |
|         ReadDereference;
 | |
|         ReadEntryByte{$IFDEF VerbosePPUParser}('IsFar='){$ENDIF}; // is Far
 | |
|       end;
 | |
|       
 | |
|     ibprocdef:
 | |
|       begin
 | |
|         {$IFDEF VerbosePPUParser} DebugLn(['TPPU.ReadDefinitions Procedure definition:']); {$ENDIF}
 | |
|         ReadCommonDefinition;
 | |
|         ReadAbstractProcDef(calloption,procoptions,proctypeoption);
 | |
|         if proctypeoption in [potype_proginit,potype_unitinit] then
 | |
|           FInitProcPos:=CurEntryStart;
 | |
|         if proctypeoption in [potype_unitfinalize] then
 | |
|           FFinalProcPos:=CurEntryStart;
 | |
|         if (po_has_mangledname in procoptions) then begin
 | |
|           ReadEntryShortstring{$IFDEF VerbosePPUParser}('     Mangled name : '){$ENDIF};
 | |
|         end;
 | |
|         ReadEntryWord{$IFDEF VerbosePPUParser}('           Number : '){$ENDIF};
 | |
|         ReadEntryByte{$IFDEF VerbosePPUParser}('            Level : '){$ENDIF};
 | |
|         {$IFDEF VerbosePPUParser}
 | |
|         dbgout('            Class : ');
 | |
|         {$ENDIF}
 | |
|         ReadDereference;
 | |
|         {$IFDEF VerbosePPUParser}
 | |
|         dbgout('          Procsym : ');
 | |
|         {$ENDIF}
 | |
|         ReadDereference;
 | |
|         {$IFDEF VerbosePPUParser}
 | |
|         dbgout('         File Pos : ');
 | |
|         {$ENDIF}
 | |
|         readposinfo;
 | |
|         {$IFDEF VerbosePPUParser}
 | |
|         dbgout('       SymOptions : ');
 | |
|         {$ENDIF}
 | |
|         ReadSymOptions;
 | |
|         if tsystemcpu(FHeader.cpu)=cpu_powerpc then begin
 | |
|           { library symbol for AmigaOS/MorphOS }
 | |
|           {$IFDEF VerbosePPUParser} dbgout('   Library symbol : '); {$ENDIF}
 | |
|           ReadDereference;
 | |
|         end;
 | |
|         if (po_has_importdll in procoptions) then
 | |
|           ReadEntryShortstring{$IFDEF VerbosePPUParser}('       Import DLL : '){$ENDIF};
 | |
|         if (po_has_importname in procoptions) then
 | |
|           ReadEntryShortstring{$IFDEF VerbosePPUParser}('      Import Name : '){$ENDIF};
 | |
|         ReadEntryWord{$IFDEF VerbosePPUParser}('        Import Nr : '){$ENDIF};
 | |
|         if (po_msgint in procoptions) then
 | |
|           ReadEntryLongint{$IFDEF VerbosePPUParser}('           MsgInt : '){$ENDIF};
 | |
|         if (po_msgstr in procoptions) then
 | |
|           ReadEntryShortstring{$IFDEF VerbosePPUParser}('           MsgStr : '){$ENDIF};
 | |
|         if (po_dispid in procoptions) then
 | |
|           ReadEntryLongint{$IFDEF VerbosePPUParser}('           DispID : '){$ENDIF};
 | |
|         if Version>=167 then
 | |
|           ReadProcImplOptions(ImplProcOptions);
 | |
| 
 | |
|         HasInliningInfo:=
 | |
|           ((Version<167) and (po_has_inlininginfo in procoptions))
 | |
|           or ((Version>=167) and (pio_has_inlininginfo in implprocoptions));
 | |
|         if HasInliningInfo then begin
 | |
|           {$IFDEF VerbosePPUParser} dbgout('       FuncretSym : '); {$ENDIF}
 | |
|           ReadDereference;
 | |
|           ReadEntrySmallSet(procinfooptions);
 | |
|           {$IFDEF VerbosePPUParser} debugln(['  ProcInfoOptions : ',dword(procinfooptions)]);{$ENDIF}
 | |
|         end;
 | |
|         // parast
 | |
|         if Version>=128 then
 | |
|           ReadSymTableOptions;
 | |
|         ReadDefinitions;
 | |
|         ReadSymbols;
 | |
|         // localst
 | |
|         if HasInliningInfo then
 | |
|         begin
 | |
|           ReadDefinitions;
 | |
|           ReadSymbols;
 | |
|         end;
 | |
|         if HasInliningInfo then
 | |
|           readnodetree;
 | |
|       end;
 | |
|       
 | |
|     ibenddefs:
 | |
|       break;
 | |
| 
 | |
|     else
 | |
|       {$IFDEF VerbosePPUParser} DebugLn(['TPPU.ReadDefinitions Skipping unsupported: ',EntryNr]); {$ENDIF}
 | |
|     end;
 | |
|     {$IFDEF VerbosePPUParser}
 | |
|     if not EndOfEntry then
 | |
|       DebugLn(['TPPU.ReadDefinitions: Warning: Entry has more information stored']);
 | |
|     {$ENDIF}
 | |
|   until false;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadProcImplOptions(out ImplProcOptions: timplprocoptions);
 | |
| begin
 | |
|   ReadEntrySmallSet(ImplProcOptions);
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadSymbols;
 | |
| {type
 | |
|   pguid = ^tguid;
 | |
|   tguid = packed record
 | |
|     D1: LongWord;
 | |
|     D2: Word;
 | |
|     D3: Word;
 | |
|     D4: array[0..7] of Byte;
 | |
|   end;
 | |
| 
 | |
|   absolutetyp = (
 | |
|     tovar,
 | |
|     toasm,
 | |
|     toaddr
 | |
|     );
 | |
|   tconsttyp = (
 | |
|     constnone,
 | |
|     constord,
 | |
|     conststring,
 | |
|     constreal,
 | |
|     constset,
 | |
|     constpointer,
 | |
|     constnil,
 | |
|     constresourcestring,
 | |
|     constwstring,
 | |
|     constguid
 | |
|     );}
 | |
| var
 | |
|   EntryNr: Byte;
 | |
| begin
 | |
|   if ReadEntry<>ibstartsyms then
 | |
|     Error('missing ibstartsyms');
 | |
|   ReadEntryLongint{$IFDEF VerbosePPUParser}('Symtable datasize : '){$ENDIF};
 | |
|   if FEntryPos<FEntry.size then
 | |
|     ReadEntryLongint{$IFDEF VerbosePPUParser}('Symtable alignment: '){$ENDIF};
 | |
|   repeat
 | |
|     EntryNr:=ReadEntry;
 | |
|     case EntryNr of
 | |
|     
 | |
|     ibendsyms:
 | |
|       break;
 | |
| 
 | |
|     else
 | |
|       {$IFDEF VerbosePPUParser}
 | |
|       DebugLn(['TPPU.ReadSymbols Skipping unsupported PPU Entry in Symbols: ',EntryNr]);
 | |
|       {$ENDIF}
 | |
|     end;
 | |
|     {$IFDEF VerbosePPUParser}
 | |
|     if not EndOfEntry then
 | |
|       DebugLn(['TPPU.ReadSymbols Entry has more information stored: ',EntryNr]);
 | |
|     {$ENDIF}
 | |
|   until false;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadNodeTree;
 | |
| begin
 | |
|   if ReadEntry<>ibnodetree then
 | |
|     Error('TPPU.ReadNodeTree missing ibnodetree');
 | |
|   FEntryPos:=FEntry.size;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadCommonDefinition;
 | |
| var
 | |
|   defoptions: tdefoptions;
 | |
|   defstates: tdefstates;
 | |
|   genconstr: tgenericconstraintflags;
 | |
|   len: Int64;
 | |
|   i: Integer;
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   defopt: tdefoption;
 | |
|   defstate: tdefstate;
 | |
|   TokenBuf: Pointer;
 | |
|   TokenBufSize: LongInt;
 | |
|   {$ENDIF}
 | |
| begin
 | |
|   ReadEntryLongint{$IFDEF VerbosePPUParser}('DefinitionID='){$ENDIF};
 | |
|   ReadDereference;
 | |
| 
 | |
|   ReadEntrySmallSet(defoptions);
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   if defoptions<>[] then begin
 | |
|     dbgout(' DefOptions:');
 | |
|     for defopt:=low(tdefoption) to high(tdefoption) do
 | |
|       if defopt in defoptions then
 | |
|         dbgout(' ',defoptionNames[defopt]);
 | |
|     debugln;
 | |
|   end;
 | |
|   {$ENDIF}
 | |
|   
 | |
|   ReadEntrySmallSet(defstates);
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   if defstates<>[] then begin
 | |
|     dbgout(' DefStates:');
 | |
|     for defstate:=low(tdefstate) to high(tdefstate) do
 | |
|       if defstate in defstates then
 | |
|         dbgout(' ',defstateNames[defstate]);
 | |
|     debugln;
 | |
|   end;
 | |
|   {$ENDIF}
 | |
| 
 | |
|   if df_genconstraint in defoptions then begin
 | |
|     // generic constraints
 | |
|     ReadEntrySmallSet(genconstr);
 | |
|     len:=ReadEntryASizeInt({$IFDEF VerbosePPUParser}'generic consstraints='{$ENDIF});
 | |
|     for i:=1 to len do begin
 | |
|       ReadDereference;
 | |
|     end;
 | |
|   end;
 | |
| 
 | |
|   if [df_generic,df_specialization]*defoptions<>[] then begin
 | |
|     // generic parameters
 | |
|     len:=ReadEntryLongint;
 | |
|     for i:=1 to len do begin
 | |
|       ReadDereference;
 | |
|     end;
 | |
|   end;
 | |
| 
 | |
|   if df_generic in defoptions then begin
 | |
|     {$IFDEF VerbosePPUParser}TokenBufSize:={$ENDIF}ReadEntryLongint;
 | |
|     {$IFDEF VerbosePPUParser}
 | |
|     TokenBuf:=allocmem(TokenBufSize);
 | |
|     try
 | |
|       System.Move(Pointer(FEntryBuf+FEntryPos)^,TokenBuf^,TokenBufSize);
 | |
|       inc(FEntryPos,TokenBufSize);
 | |
|       i:=0;
 | |
|       while i<TokenBufSize do begin
 | |
|         // The tokens depends on compiler Version
 | |
|         // ToDo: write tokens
 | |
|         inc(i);
 | |
|       end;
 | |
|     finally
 | |
|       FreeMem(TokenBuf);
 | |
|     end;
 | |
|     {$ENDIF}
 | |
|   end;
 | |
| 
 | |
|   if df_specialization in defoptions then
 | |
|   begin
 | |
|     ReadDereference;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadAbstractProcDef(out proccalloption: tproccalloption;
 | |
|   out procoptions: tprocoptions; out proctypeoption: tproctypeoption);
 | |
| var
 | |
|   i     : longint;
 | |
|   p: PByte;
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   po: tprocoption;
 | |
|   {$ENDIF}
 | |
| begin
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   dbgout('Return type: ');
 | |
|   {$ENDIF}
 | |
|   ReadDereference;
 | |
|   if Version<169 then
 | |
|     ReadEntryByte{$IFDEF VerbosePPUParser}('FPU='){$ENDIF};
 | |
|   proctypeoption:=tproctypeoption(ReadEntryByte);
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   debugln('Typeoptions: ',proctypeoptionNames[proctypeoption]);
 | |
|   {$ENDIF}
 | |
|   proccalloption:=tproccalloption(ReadEntryByte);
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   debugln('CallOption : ',proccalloptionNames[proccalloption]);
 | |
|   {$ENDIF}
 | |
|   ReadEntryNormalSet(procoptions);
 | |
|   if Version>=167 then begin
 | |
|     // po_has_inlininginfo was deleted in PPU version 167
 | |
|     p:=@PByte(@procoptions)[ord(po_has_inlininginfo)];
 | |
|     System.Move(p[0],p[1],ord(High(procoptions))-ord(po_has_inlininginfo));
 | |
|     p^:=0;
 | |
|   end;
 | |
| 
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   if procoptions<>[] then begin
 | |
|     dbgout('Options: ');
 | |
|     for po:=low(tprocoption) to high(tprocoption) do
 | |
|       if po in procoptions then
 | |
|         dbgout(' ',procoptionNames[po]);
 | |
|     debugln;
 | |
|   end;
 | |
|   {$ENDIF}
 | |
|   if (po_explicitparaloc in procoptions) then
 | |
|   begin
 | |
|     i:=ReadEntryByte;
 | |
|     inc(FEntryPos,i);
 | |
|   end;
 | |
|   if po_syscall_has_libsym in procoptions then
 | |
|     ReadDereference;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadSymOptions;
 | |
| var
 | |
|   symoptions : tsymoptions;
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   s: tsymoption;
 | |
|   {$ENDIF}
 | |
| begin
 | |
|   ReadEntrySmallSet(symoptions);
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   if symoptions<>[] then begin
 | |
|     for s:=Low(tsymoption) to high(tsymoption) do
 | |
|       if s in SymOptions then
 | |
|         dbgout(' ',symoptionNames[s]);
 | |
|   end;
 | |
|   debugln;
 | |
|   {$ENDIF}
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadDereference;
 | |
| type
 | |
|   tdereftype = (
 | |
|     deref_nil,
 | |
|     deref_unit,
 | |
|     deref_symid,
 | |
|     deref_defid
 | |
|   );
 | |
| var
 | |
|   DerefPos: LongInt;
 | |
|   pdata: PByte;
 | |
|   n: Byte;
 | |
|   i: Integer;
 | |
|   b: tdereftype;
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   idx: integer;
 | |
|   {$ENDIF}
 | |
| begin
 | |
|   DerefPos:=ReadEntryLongint;
 | |
|   if DerefPos=-1 then begin
 | |
|     {$IFDEF VerbosePPUParser}
 | |
|     dbgout(' Nil');
 | |
|     {$ENDIF}
 | |
|     exit;
 | |
|   end;
 | |
|   if DerefPos>FDerefDataSize then
 | |
|     Error('Invalid Deref, DerefPos>=FDerefDataSize');
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   dbgout('(',IntToStr(DerefPos),')');
 | |
|   {$ENDIF}
 | |
|   pdata:=@FDerefData[DerefPos];
 | |
|   n:=pdata^;
 | |
|   if n<1 then
 | |
|     Error('Invalid Deref, n<1');
 | |
|   i:=1;
 | |
|   while i<=n do begin
 | |
|     b:=tdereftype(pdata[i]);
 | |
|     inc(i);
 | |
|     case b of
 | |
|     deref_nil :
 | |
|       begin
 | |
|         {$IFDEF VerbosePPUParser}
 | |
|         dbgout(' Nil');
 | |
|         {$ENDIF}
 | |
|       end;
 | |
|     deref_symid :
 | |
|       begin
 | |
|         {$IFDEF VerbosePPUParser}
 | |
|         idx:=pdata[i] shl 24 or pdata[i+1] shl 16 or pdata[i+2] shl 8 or pdata[i+3];
 | |
|         dbgout(' SymId ',IntToStr(idx));
 | |
|         {$ENDIF}
 | |
|         inc(i,4);
 | |
|       end;
 | |
|     deref_defid :
 | |
|       begin
 | |
|         {$IFDEF VerbosePPUParser}
 | |
|         idx:=pdata[i] shl 24 or pdata[i+1] shl 16 or pdata[i+2] shl 8 or pdata[i+3];
 | |
|         dbgout(' DefId ',IntToStr(idx));
 | |
|         {$ENDIF}
 | |
|         inc(i,4);
 | |
|       end;
 | |
|     deref_unit :
 | |
|       begin
 | |
|         {$IFDEF VerbosePPUParser}
 | |
|         idx:=pdata[i] shl 8 or pdata[i+1];
 | |
|         dbgout(' Unit ',IntToStr(idx));
 | |
|         {$ENDIF}
 | |
|         inc(i,2);
 | |
|       end;
 | |
|     else
 | |
|       begin
 | |
|         Error('unsupported dereftyp: '+IntToStr(ord(b)));
 | |
|         break;
 | |
|       end;
 | |
|     end;
 | |
|   end;
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   debugln;
 | |
|   {$ENDIF}
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadPosInfo;
 | |
| var
 | |
|   info : byte;
 | |
|   fileindex,line,column : longint;
 | |
| begin
 | |
|   {
 | |
|      info byte layout in bits:
 | |
|      0-1 - amount of bytes for fileindex
 | |
|      2-3 - amount of bytes for line
 | |
|      4-5 - amount of bytes for column
 | |
|   }
 | |
|   fileindex:=0;
 | |
|   line:=0;
 | |
|   column:=0;
 | |
|   info:=ReadEntryByte;
 | |
|   case (info and $03) of
 | |
|     0 : fileindex:=ReadEntryByte;
 | |
|     1 : fileindex:=ReadEntryWord;
 | |
|     2 : fileindex:=(ReadEntryByte shl 16) or ReadEntryWord;
 | |
|     3 : fileindex:=ReadEntryLongint;
 | |
|   end;
 | |
|   case ((info shr 2) and $03) of
 | |
|     0 : line:=ReadEntryByte;
 | |
|     1 : line:=ReadEntryWord;
 | |
|     2 : line:=(ReadEntryByte shl 16) or ReadEntryWord;
 | |
|     3 : line:=ReadEntryLongint;
 | |
|   end;
 | |
|   case ((info shr 4) and $03) of
 | |
|     0 : column:=ReadEntryByte;
 | |
|     1 : column:=ReadEntryWord;
 | |
|     2 : column:=(ReadEntryByte shl 16) or ReadEntryWord;
 | |
|     3 : column:=ReadEntryLongint;
 | |
|   end;
 | |
|   if (fileindex<0) and (line<0) and (column<0) then ;
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   debugln(dbgs(fileindex),' (',dbgs(line),',',dbgs(column),')');
 | |
|   {$ENDIF}
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadSymTableOptions;
 | |
| var
 | |
|   Nr: Byte;
 | |
|   s: DWord;
 | |
| begin
 | |
|   Nr:=ReadEntry;
 | |
|   if Nr<>ibsymtableoptions then
 | |
|     Error('expected ibsymtableoptions, but found '+PPUEntryName(Nr));
 | |
|   ReadEntrySmallSet(s);
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntry: byte;
 | |
| 
 | |
|   procedure ErrorInvalidTypeID;
 | |
|   begin
 | |
|     Error('Invalid entry type-id '+IntToStr(FEntry.id));
 | |
|   end;
 | |
| 
 | |
| begin
 | |
|   FEntryPos:=0;
 | |
|   FEntryStart:=FDataPos;
 | |
|   ReadData(FEntry,SizeOf(FEntry));
 | |
|   if fChangeEndian then
 | |
|     FEntry.size:=SwapEndian(FEntry.size);
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   //DebugLn(['TPPU.ReadEntry nr=',FEntry.Nr,'=',PPUEntryName(FEntry.nr),' streampos=',FDataPos,' type-id=',FEntry.id]);
 | |
|   {$ENDIF}
 | |
|   if not (FEntry.id in [mainentryid,subentryid]) then
 | |
|     ErrorInvalidTypeID;
 | |
|   Result:=FEntry.nr;
 | |
|   if FEntryBufSize<FEntry.size then begin
 | |
|     FEntryBufSize:=FEntryBufSize*2;
 | |
|     if FEntryBufSize<FEntry.size then
 | |
|       FEntryBufSize:=FEntry.size;
 | |
|     ReAllocMem(FEntryBuf,FEntryBufSize);
 | |
|   end;
 | |
|   if FEntry.size>0 then
 | |
|     ReadData(FEntryBuf^,FEntry.size);
 | |
| end;
 | |
| 
 | |
| function TPPU.EndOfEntry: boolean;
 | |
| begin
 | |
|   Result:=FEntryPos>=FEntry.Size;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.SkipUntilEntry(EntryNr: byte);
 | |
| var
 | |
|   b: Byte;
 | |
| begin
 | |
|   repeat
 | |
|     b:=ReadEntry;
 | |
|   until (b=ibend) or ((b=EntryNr) and (FEntry.id=mainentryid));
 | |
|   if b<>EntryNr then
 | |
|     Error('TPPU.SkipUntilEntry not found: '+IntToStr(EntryNr));
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadDataFromStream(s: TStream);
 | |
| var
 | |
|   Entry: PPPUEntry;
 | |
| 
 | |
|   procedure Grow(Add: integer);
 | |
|   const InitialSize = 16384;
 | |
|   var
 | |
|     NewSize: Integer;
 | |
|   begin
 | |
|     NewSize:=FDataPos+Add;
 | |
|     if NewSize<=FDataSize then exit;
 | |
|     // need grow
 | |
|     if FDataSize<InitialSize then
 | |
|       FDataSize:=InitialSize
 | |
|     else
 | |
|       FDataSize:=FDataSize*2;
 | |
|     while FDataSize<NewSize do begin
 | |
|       if FDataSize>100000000 then
 | |
|         Error('ppu too big');
 | |
|       FDataSize:=FDataSize*2;
 | |
|     end;
 | |
|     ReAllocMem(FData,FDataSize);
 | |
|   end;
 | |
|   
 | |
|   function Read(Count: integer): Pointer;
 | |
|   var
 | |
|     ReadCount: LongInt;
 | |
|   begin
 | |
|     //DebugLn(['Read Count=',Count,' Pos=',FDataPos]);
 | |
|     // read and copy some more data to FData
 | |
|     Grow(Count);
 | |
|     Result:=Pointer(FData+FDataPos);
 | |
|     ReadCount:=s.Read(Result^,Count);
 | |
|     if ReadCount<Count then
 | |
|       Error('ppu too short, buggy ppu');
 | |
|     inc(FDataPos,Count);
 | |
|   end;
 | |
| 
 | |
|   function ReadEntryBlock: byte;
 | |
|   begin
 | |
|     Entry:=PPPUEntry(Read(SizeOf(FEntry)));
 | |
|     if not (Entry^.id in [mainentryid,subentryid]) then
 | |
|       Error('Invalid entry id '+IntToStr(Entry^.id));
 | |
|     Result:=Entry^.nr;
 | |
|     if fChangeEndian then
 | |
|       Entry^.Size:=SwapEndian(Entry^.Size);
 | |
|     if Entry^.Size<0 then
 | |
|       Error('entry has negative size');
 | |
|     Read(Entry^.Size);
 | |
|   end;
 | |
|   
 | |
|   function ReadUntilEntry(EntryNr: byte): boolean;
 | |
|   var
 | |
|     b: Byte;
 | |
|   begin
 | |
|     repeat
 | |
|       b:=ReadEntryBlock;
 | |
|       if b=ibend then exit(false);
 | |
|     until (b=EntryNr) and (Entry^.id=mainentryid);
 | |
|     Result:=true;
 | |
|   end;
 | |
| 
 | |
| var
 | |
|   p: Pointer;
 | |
| begin
 | |
|   fChangeEndian:=PPUIsEndianBig;
 | |
|   Entry:=nil;
 | |
|   
 | |
|   // read header
 | |
|   p:=Read(SizeOf(TPPUHeader));
 | |
|   System.Move(p^,FHeader,SizeOf(TPPUHeader));
 | |
|   
 | |
|   if String(FHeader.id)<>PPU_ID then
 | |
|     Error('This is not a PPU. Wrong ID.');
 | |
|   // read Version
 | |
|   FVersion:=StrToIntDef(String(FHeader.ver),0);
 | |
|   if FVersion<16 then
 | |
|     Error('Old PPU versions (<16) are not supported.');
 | |
|   // read rest of header
 | |
|   if fChangeEndian then begin
 | |
|     fHeader.compiler := swapendian(fHeader.compiler);
 | |
|     fHeader.cpu := swapendian(fHeader.cpu);
 | |
|     fHeader.target := swapendian(fHeader.target);
 | |
|     fHeader.flags := swapendian(fHeader.flags);
 | |
|     fHeader.size := swapendian(fHeader.size);
 | |
|     fHeader.checksum := swapendian(fHeader.checksum);
 | |
|     fHeader.interface_checksum := swapendian(fHeader.interface_checksum);
 | |
|     fHeader.deflistsize := swapendian(fHeader.deflistsize);
 | |
|     fHeader.symlistsize := swapendian(fHeader.symlistsize);
 | |
|   end;
 | |
|   fChangeEndian:=((FHeader.flags and uf_big_endian) = uf_big_endian)<>PPUIsEndianBig;
 | |
| 
 | |
|   // read entries
 | |
|   if not ReadUntilEntry(ibendinterface) then
 | |
|     Error('missing end of interface');
 | |
|   if not ReadUntilEntry(ibenddefs) then
 | |
|     Error('missing end of interface definitions');
 | |
|   if not ReadUntilEntry(ibendsyms) then
 | |
|     Error('missing end of interface symbols');
 | |
|   if ReadEntryBlock=ibexportedmacros then begin
 | |
|     if boolean(PByte(PByte(Entry)+SizeOf(TPPUEntry))^) then begin
 | |
|       if not ReadUntilEntry(ibenddefs) then
 | |
|         Error('missing end of macro definitions');
 | |
|       if not ReadUntilEntry(ibendsyms) then
 | |
|         Error('missing end of macro symbols');
 | |
|     end;
 | |
|   end;
 | |
|   if not ReadUntilEntry(ibendimplementation) then
 | |
|     Error('missing end of implementation');
 | |
|   if (FHeader.flags and uf_local_symtable)<>0 then begin
 | |
|     if not ReadUntilEntry(ibenddefs) then
 | |
|       Error('missing end of implementation definitions');
 | |
|     if not ReadUntilEntry(ibendsyms) then
 | |
|       Error('missing end of implementation symbols');
 | |
|   end;
 | |
|   
 | |
|   // shrink FData
 | |
|   FDataSize:=FDataPos;
 | |
|   ReAllocMem(FData,FDataSize);
 | |
|   FDataPos:=0;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadData(var Buf; Count: longint);
 | |
| begin
 | |
|   //DebugLn(['TPPU.ReadData Count=',Count,' Pos=',FDataPos]);
 | |
|   if FDataPos+Count>FDataSize then
 | |
|     Error('TPPU.ReadData: out of data');
 | |
|   System.Move(Pointer(FData+FDataPos)^,Buf,Count);
 | |
|   inc(FDataPos,Count);
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryByte: byte;
 | |
| begin
 | |
|   if FEntryPos>=FEntry.size then
 | |
|     Error('TPPU.ReadEntryByte: out of bytes');
 | |
|   Result:=PByte(FEntryBuf+FEntryPos)^;
 | |
|   inc(FEntryPos);
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryByte(const Msg: string): byte;
 | |
| begin
 | |
|   Result:=ReadEntryByte();
 | |
|   debugln([Msg,Result]);
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryShortstring: shortstring;
 | |
| var
 | |
|   l: byte;
 | |
|   s: shortstring;
 | |
| 
 | |
|   procedure ErrorOutOfBytes;
 | |
|   begin
 | |
|     Error('TPPU.ReadEntryShortstring: out of bytes. needed='+IntToStr(l)+', found='+IntToStr(FEntry.size-FEntryPos));
 | |
|   end;
 | |
| 
 | |
| begin
 | |
|   l:=ReadEntryByte;
 | |
|   s[0]:=chr(l);
 | |
|   if l>0 then begin
 | |
|     if FEntryPos+l>FEntry.size then
 | |
|       ErrorOutOfBytes;
 | |
|     System.Move(Pointer(FEntryBuf+FEntryPos)^,s[1],l);
 | |
|   end;
 | |
|   Result:=s;
 | |
|   inc(FEntryPos,l);
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryShortstring(const Msg: string): shortstring;
 | |
| begin
 | |
|   Result:=ReadEntryShortstring();
 | |
|   debugln([Msg,Result]);
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryAnsistring: ansistring;
 | |
| var
 | |
|   l: longint;
 | |
| 
 | |
|   procedure ErrorOutOfBytes;
 | |
|   begin
 | |
|     Error('TPPU.ReadEntryAnsistring: out of bytes. needed='+IntToStr(l)+', found='+IntToStr(FEntry.size-FEntryPos));
 | |
|   end;
 | |
| 
 | |
| begin
 | |
|   l:=ReadEntryLongint;
 | |
|   SetLength(Result,l);
 | |
|   if l>0 then begin
 | |
|     if FEntryPos+l>FEntry.size then
 | |
|       ErrorOutOfBytes;
 | |
|     System.Move(Pointer(FEntryBuf+FEntryPos)^,Result[1],l);
 | |
|   end;
 | |
|   inc(FEntryPos,l);
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryAnsistring(const Msg: string): ansistring;
 | |
| begin
 | |
|   Result:=ReadEntryAnsistring();
 | |
|   debugln([Msg,Result]);
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryLongint: longint;
 | |
| begin
 | |
|   if FEntryPos+SizeOf(Longint)>FEntry.size then
 | |
|     Error('TPPU.ReadEntryLongint: out of bytes');
 | |
|   Result:=PLongint(FEntryBuf+FEntryPos)^;
 | |
|   inc(FEntryPos,SizeOf(Longint));
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryLongint(const Msg: string): longint;
 | |
| begin
 | |
|   Result:=ReadEntryLongint();
 | |
|   debugln([Msg,Result]);
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryDWord: cardinal;
 | |
| begin
 | |
|   Result:=cardinal(ReadEntryLongint);
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryDWord(const Msg: string): cardinal;
 | |
| begin
 | |
|   Result:=cardinal(ReadEntryLongint(Msg));
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryWord: word;
 | |
| begin
 | |
|   if FEntryPos+SizeOf(Word)>FEntry.size then
 | |
|     Error('TPPU.ReadEntryLongint: out of bytes');
 | |
|   Result:=PWord(FEntryBuf+FEntryPos)^;
 | |
|   inc(FEntryPos,SizeOf(Word));
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryWord(const Msg: string): word;
 | |
| begin
 | |
|   Result:=ReadEntryWord();
 | |
|   debugln([Msg,Result]);
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryInt64: int64;
 | |
| begin
 | |
|   if FEntryPos+SizeOf(Int64)>FEntry.size then
 | |
|     Error('TPPU.ReadEntryInt64: out of bytes');
 | |
|   Result:=PInt64(FEntryBuf+FEntryPos)^;
 | |
|   inc(FEntryPos,SizeOf(Int64));
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryInt64(const Msg: string): int64;
 | |
| begin
 | |
|   Result:=ReadEntryInt64();
 | |
|   debugln([Msg,Result]);
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryQWord: QWord;
 | |
| begin
 | |
|   if FEntryPos+SizeOf(QWord)>FEntry.size then
 | |
|     Error('TPPU.ReadEntryQWord: out of bytes');
 | |
|   Result:=PQWord(FEntryBuf+FEntryPos)^;
 | |
|   inc(FEntryPos,SizeOf(QWord));
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryQWord(const Msg: string): QWord;
 | |
| begin
 | |
|   Result:=ReadEntryQWord();
 | |
|   debugln([Msg,Result]);
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryAInt: int64;
 | |
| begin
 | |
|   case FSizeOfAInt of
 | |
|     8: result:=ReadEntryInt64;
 | |
|     4: result:=ReadEntryLongint;
 | |
|     2: result:=smallint(ReadEntryWord);
 | |
|     1: result:=shortint(ReadEntryByte);
 | |
|   else
 | |
|     Result:=0;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryAInt(const Msg: string): int64;
 | |
| begin
 | |
|   Result:=ReadEntryAInt();
 | |
|   debugln([Msg,Result]);
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryASizeInt: int64;
 | |
| begin
 | |
|   case FSizeOfASizeInt of
 | |
|     8: result:=ReadEntryInt64;
 | |
|     4: result:=ReadEntryLongint;
 | |
|     2: result:=smallint(ReadEntryWord);
 | |
|     1: result:=shortint(ReadEntryByte);
 | |
|   else
 | |
|     Result:=0;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| function TPPU.ReadEntryASizeInt(const Msg: string): int64;
 | |
| begin
 | |
|   Result:=ReadEntryASizeInt();
 | |
|   debugln([Msg,Result]);
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadEntrySmallSet(out s);
 | |
| var
 | |
|   i: longint;
 | |
| begin
 | |
|   if FEntryPos+4>FEntry.size then
 | |
|     Error('TPPU.ReadEntryLongint: out of bytes');
 | |
|   System.Move(PByte(FEntryBuf+FEntryPos)^,s{%H-},4);
 | |
|   inc(FEntryPos,4);
 | |
|   if fChangeEndian then
 | |
|     for i:=0 to 3 do
 | |
|       Pbyte(@s)[i]:=reverse_byte(Pbyte(@s)[i]);
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadEntryNormalSet(out s);
 | |
| var
 | |
|   i: longint;
 | |
| begin
 | |
|   if FEntryPos+32>FEntry.size then
 | |
|     Error('TPPU.ReadEntryLongint: out of bytes');
 | |
|   System.Move(PByte(FEntryBuf+FEntryPos)^,s{%H-},32);
 | |
|   inc(FEntryPos,32);
 | |
|   if fChangeEndian then
 | |
|     for i:=0 to 31 do
 | |
|       Pbyte(@s)[i]:=reverse_byte(Pbyte(@s)[i]);
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadUsedUnits;
 | |
| {$IFDEF VerbosePPUParser}
 | |
| var
 | |
|   AUnitName: ShortString;
 | |
|   CRC: DWord;
 | |
|   IntfCRC: DWord;
 | |
|   IndirectCRC: DWord;
 | |
| {$ENDIF}
 | |
| begin
 | |
|   while not EndOfEntry do begin
 | |
|     {$IFDEF VerbosePPUParser}AUnitName:={$ENDIF}ReadEntryShortstring;
 | |
|     {$IFDEF VerbosePPUParser}CRC:={$ENDIF}ReadEntryDWord;
 | |
|     {$IFDEF VerbosePPUParser}IntfCRC:={$ENDIF}ReadEntryDWord;
 | |
|     if FVersion>=107 then begin
 | |
|       // svn rev 14503  ppu ver 107
 | |
|       {$IFDEF VerbosePPUParser}IndirectCRC:={$ENDIF}ReadEntryDWord;
 | |
|     end else begin
 | |
|       {$IFDEF VerbosePPUParser}IndirectCRC:=0;{$ENDIF}
 | |
|     end;
 | |
|     {$IFDEF VerbosePPUParser}
 | |
|     DebugLn(['TPPU.ReadUsedUnits Unit=',AUnitName,' CRC=',HexStr(cardinal(CRC),8),' IntfCRC=',HexStr(cardinal(IntfCRC),8),' IndCRC=',HexStr(cardinal(IndirectCRC),8)]);
 | |
|     {$ENDIF}
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadModuleOptions;
 | |
| type
 | |
|   tmoduleoption = (
 | |
|     mo_none,
 | |
|     mo_hint_deprecated,
 | |
|     mo_hint_platform,
 | |
|     mo_hint_library,
 | |
|     mo_hint_unimplemented,
 | |
|     mo_hint_experimental,
 | |
|     mo_has_deprecated_msg
 | |
|   );
 | |
|   tmoduleoptions = set of tmoduleoption;
 | |
| {$IFDEF VerbosePPUParser}
 | |
| type
 | |
|   tmoduleopt=record
 | |
|     mask : tmoduleoption;
 | |
|     str  : string[30];
 | |
|   end;
 | |
| const
 | |
|   moduleopts=6;
 | |
|   moduleopt : array[1..moduleopts] of tmoduleopt=(
 | |
|      (mask:mo_hint_deprecated;    str:'Hint Deprecated'),
 | |
|      (mask:mo_hint_platform;      str:'Hint Platform'),
 | |
|      (mask:mo_hint_library;       str:'Hint Library'),
 | |
|      (mask:mo_hint_unimplemented; str:'Hint Unimplemented'),
 | |
|      (mask:mo_hint_experimental;  str:'Hint Experimental'),
 | |
|      (mask:mo_has_deprecated_msg; str:'Has Deprecated Message')
 | |
|   );
 | |
| {$ENDIF}
 | |
| var
 | |
|   moduleoptions : tmoduleoptions;
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   i      : longint;
 | |
|   first  : boolean;
 | |
|   {$ENDIF}
 | |
| begin
 | |
|   ReadEntrySmallSet(moduleoptions);
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   if moduleoptions<>[] then
 | |
|   begin
 | |
|     first:=true;
 | |
|     for i:=1 to moduleopts do
 | |
|       if (moduleopt[i].mask in moduleoptions) then
 | |
|       begin
 | |
|         if first then
 | |
|           first:=false
 | |
|         else
 | |
|           dbgout(', ');
 | |
|         dbgout(moduleopt[i].str);
 | |
|       end;
 | |
|     debugln;
 | |
|   end;
 | |
|   {$ENDIF}
 | |
|   if mo_has_deprecated_msg in moduleoptions then begin
 | |
|     ReadEntryShortstring{$IFDEF VerbosePPUParser}('Deprecated : '){$ENDIF};
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadLinkContainer(aContainerType: byte);
 | |
| {$IFDEF VerbosePPUParser}
 | |
| var
 | |
|   Desc: String;
 | |
| var
 | |
|   Filename: ShortString;
 | |
|   Flags: LongInt;
 | |
| {$ENDIF}
 | |
| begin
 | |
|   {$IFNDEF VerbosePPUParser}
 | |
|   if aContainerType=0 then ;
 | |
|   {$ENDIF}
 | |
|   while not EndOfEntry do begin
 | |
|     {$IFDEF VerbosePPUParser}Filename:={$ENDIF}ReadEntryShortstring;
 | |
|     {$IFDEF VerbosePPUParser}Flags:={$ENDIF}ReadEntryLongint;
 | |
|     {$IFDEF VerbosePPUParser}
 | |
|     case Nr of
 | |
|     iblinkunitofiles:
 | |
|       Desc:='Link unit object file: ';
 | |
|     iblinkunitstaticlibs :
 | |
|       Desc:='Link unit static lib: ';
 | |
|     iblinkunitsharedlibs :
 | |
|       Desc:='Link unit shared lib: ';
 | |
|     iblinkotherofiles :
 | |
|       Desc:='Link other object file: ';
 | |
|     iblinkotherstaticlibs :
 | |
|       Desc:='Link other static lib: ';
 | |
|     iblinkothersharedlibs :
 | |
|       Desc:='Link other shared lib: ';
 | |
|     iblinkotherframeworks:
 | |
|       Desc:='Link framework: ';
 | |
|     end;
 | |
|     Desc:=Desc+Filename+' '+PPULinkContainerFlagToStr(Flags);
 | |
|     DebugLn(['TPPU.ReadLinkContainer ',Desc]);
 | |
|     {$ENDIF}
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadResources;
 | |
| {$IFDEF VerbosePPUParser}
 | |
| var
 | |
|   Filename: ShortString;
 | |
| {$ENDIF}
 | |
| begin
 | |
|   while not EndOfEntry do begin
 | |
|     {$IFDEF VerbosePPUParser}Filename:={$ENDIF}ReadEntryShortstring;
 | |
|     {$IFDEF VerbosePPUParser}
 | |
|     DebugLn(['TPPU.ReadResources file: '+Filename]);
 | |
|     {$ENDIF}
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadImportSymbols;
 | |
| var
 | |
|   SymbolCount: LongInt;
 | |
|   i: Integer;
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   LibName: ShortString;
 | |
|   SymbolName: ShortString;
 | |
|   SymbolOrdNr: LongInt;
 | |
|   SymbolIsVar: Boolean;
 | |
|   SymMangledName: String;
 | |
|   {$ENDIF}
 | |
| begin
 | |
|   while not EndOfEntry do begin
 | |
|     {$IFDEF VerbosePPUParser}LibName:={$ENDIF}ReadEntryShortstring;
 | |
|     SymbolCount:=ReadEntryLongint;
 | |
|     {$IFDEF VerbosePPUParser}
 | |
|     DebugLn(['TPPU.ReadImportSymbols External Library: ',LibName,' (',SymbolCount,' imports)']);
 | |
|     {$ENDIF}
 | |
|     for i:=0 to SymbolCount-1 do
 | |
|     begin
 | |
|       {$IFDEF VerbosePPUParser}SymbolName:={$ENDIF}ReadEntryShortstring;
 | |
|       if Version>130 then
 | |
|         {$IFDEF VerbosePPUParser}SymMangledName:={$ENDIF}ReadEntryShortstring
 | |
|       else
 | |
|         {$IFDEF VerbosePPUParser}SymMangledName:=SymbolName{$ENDIF};
 | |
|       {$IFDEF VerbosePPUParser}SymbolOrdNr:={$ENDIF}ReadEntryLongint;
 | |
|       {$IFDEF VerbosePPUParser}SymbolIsVar:=ReadEntryByte<>0{$ELSE}ReadEntryByte{$ENDIF};
 | |
|       {$IFDEF VerbosePPUParser}
 | |
|       DebugLn(['TPPU.ReadImportSymbols "',SymbolName,'" Mangled="',SymMangledName,'" (OrdNr: ',SymbolOrdNr,' IsVar: ',SymbolIsVar,')']);
 | |
|       {$ENDIF}
 | |
|     end;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadDerefData;
 | |
| begin
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   DebugLn(['TPPU.ReadDerefData Deref Data length: ',FEntry.size-FEntryPos]);
 | |
|   {$ENDIF}
 | |
|   FDerefDataSize:=FEntry.size-FEntryPos;
 | |
|   if FDerefDataSize>0 then begin
 | |
|     FDerefData:=AllocMem(FDerefDataSize);
 | |
|     System.Move(PByte(FEntryBuf+FEntryPos)^,FDerefData^,FDerefDataSize);
 | |
|     FEntryPos:=FEntry.size;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.ReadDerefMap;
 | |
| var
 | |
|   Count: LongInt;
 | |
|   i: Integer;
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   MapName: ShortString;
 | |
|   {$ENDIF}
 | |
| begin
 | |
|   Count:=ReadEntryLongint;
 | |
|   for i:=0 to Count-1 do begin
 | |
|     {$IFDEF VerbosePPUParser}MapName:={$ENDIF}ReadEntryShortstring;
 | |
|     {$IFDEF VerbosePPUParser}
 | |
|     DebugLn(['TPPU.ReadDerefMap ',i,' ',MapName]);
 | |
|     {$ENDIF}
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.Skip(Count: integer);
 | |
| begin
 | |
|   if FDataPos+Count>FDataSize then
 | |
|     Error('TPPU.Skip: out of data');
 | |
|   inc(FDataPos,Count);
 | |
| end;
 | |
| 
 | |
| procedure TPPU.Error(const Msg: string);
 | |
| begin
 | |
|   {$IFDEF VerbosePPUParser}
 | |
|   CTDumpStack;
 | |
|   {$ENDIF}
 | |
|   raise EPPUParserError.Create(Self,Msg);
 | |
| end;
 | |
| 
 | |
| procedure TPPU.GetUsesSection(StartPos: integer; var List: TStrings);
 | |
| var
 | |
|   AUnitName: String;
 | |
| begin
 | |
|   if StartPos<=0 then exit;
 | |
|   SetDataPos(StartPos);
 | |
|   if ReadEntry<>ibloadunit then exit;
 | |
|   while not EndOfEntry do begin
 | |
|     AUnitName:=ReadEntryShortstring;
 | |
|     if List=nil then
 | |
|       List:=TStringList.Create;
 | |
|     if List.IndexOf(AUnitName)<0 then
 | |
|       List.Add(AUnitName);
 | |
|     ReadEntryDWord; // CRC
 | |
|     ReadEntryDWord; // IntfCRC
 | |
|     if FVersion>=107 then ReadEntryDWord;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.SetDataPos(NewPos: integer);
 | |
| begin
 | |
|   FillByte(FEntry,SizeOf(FEntry),0);
 | |
|   FEntryPos:=0;
 | |
|   FDataPos:=NewPos;
 | |
| end;
 | |
| 
 | |
| function TPPU.GetProcMangledName(ProcDefPos: integer): string;
 | |
| var
 | |
|   calloption: tproccalloption;
 | |
|   procoptions: tprocoptions;
 | |
|   proctypeoption: tproctypeoption;
 | |
| begin
 | |
|   Result:='';
 | |
|   if ProcDefPos<=0 then exit;
 | |
|   SetDataPos(ProcDefPos);
 | |
|   if ReadEntry<>ibprocdef then exit;
 | |
|   ReadCommonDefinition;
 | |
|   ReadAbstractProcDef(calloption,procoptions,proctypeoption);
 | |
|   if (po_has_mangledname in procoptions) then
 | |
|     Result:=ReadEntryShortstring;
 | |
| end;
 | |
| 
 | |
| constructor TPPU.Create(TheOwner: TObject);
 | |
| begin
 | |
|   FOwner:=TheOwner;
 | |
| end;
 | |
| 
 | |
| destructor TPPU.Destroy;
 | |
| begin
 | |
|   Clear;
 | |
|   inherited Destroy;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.Clear;
 | |
| begin
 | |
|   FillByte(FHeader,SizeOf(FHeader),0);
 | |
|   FillByte(FEntry,SizeOf(FEntry),0);
 | |
|   FEntryPos:=0;
 | |
|   
 | |
|   ReAllocMem(FEntryBuf,0);
 | |
|   FEntryBufSize:=0;
 | |
|   
 | |
|   ReAllocMem(FDerefData,0);
 | |
|   FDerefDataSize:=0;
 | |
|   
 | |
|   ReAllocMem(FData,0);
 | |
|   FDataSize:=0;
 | |
|   FDataPos:=0;
 | |
| 
 | |
|   FInterfaceHeaderPos:=0;
 | |
|   FMainUsesSectionPos:=0;
 | |
|   FImplementationHeaderPos:=0;
 | |
|   FImplementationUsesSectionPos:=0;
 | |
|   FInitProcPos:=0;
 | |
|   FFinalProcPos:=0;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.LoadFromStream(s: TStream; const Parts: TPPUParts);
 | |
| begin
 | |
|   Clear;
 | |
|   ReadDataFromStream(s);
 | |
|   ReadPPU(Parts);
 | |
| end;
 | |
| 
 | |
| procedure TPPU.LoadFromFile(const Filename: string; const Parts: TPPUParts);
 | |
| var
 | |
|   ms: TMemoryStream;
 | |
|   fs: TFileStreamUTF8;
 | |
| begin
 | |
|   fs:=TFileStreamUTF8.Create(Filename,fmOpenRead or fmShareDenyWrite);
 | |
|   ms:=TMemoryStream.Create;
 | |
|   try
 | |
|     ms.Size:=fs.Size;
 | |
|     ms.CopyFrom(fs,fs.Size);
 | |
|     ms.Position:=0;
 | |
|     LoadFromStream(ms,Parts);
 | |
|   finally
 | |
|     ms.Free;
 | |
|     fs.Free;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TPPU.Dump(const Prefix: string);
 | |
| begin
 | |
|   DebugLn([Prefix+'TPPU.Dump ']);
 | |
|   DumpHeader(Prefix+'  ');
 | |
| end;
 | |
| 
 | |
| procedure TPPU.DumpHeader(const Prefix: string);
 | |
| begin
 | |
|   DebugLn([Prefix,'Header']);
 | |
|   DebugLn([Prefix,'  ID=',String(FHeader.ID)]);
 | |
|   DebugLn([Prefix,'  Ver=',StrToIntDef(String(FHeader.ver),0)]);
 | |
|   DebugLn([Prefix,'  Compiler=',FHeader.compiler shr 14,'.',
 | |
|                             (FHeader.compiler shr 7) and $7f,'.',
 | |
|                             FHeader.compiler and $7f]);
 | |
|   DebugLn([Prefix,'  Target CPU=',PPUCpuToStr(FHeader.cpu)]);
 | |
|   DebugLn([Prefix,'  Target OS=',PPUTargetToStr(FHeader.target)]);
 | |
|   DebugLn([Prefix,'  Unit Flags=',PPUFlagsToStr(FHeader.flags)]);
 | |
|   DebugLn([Prefix,'  Filesize (w/o header)=',FHeader.size]);
 | |
|   DebugLn([Prefix,'  Checksum=',HexStr(cardinal(FHeader.checksum),8)]);
 | |
|   DebugLn([Prefix,'  Interface CheckSum=',HexStr(cardinal(FHeader.interface_checksum),8)]);
 | |
|   DebugLn([Prefix,'  Number of Definitions=',FHeader.deflistsize]);
 | |
|   DebugLn([Prefix,'  Number of Symbols=',FHeader.symlistsize]);
 | |
|   DebugLn([Prefix,'  Indirect Checksum=',HexStr(cardinal(FHeader.indirect_checksum),8)]);
 | |
|   DebugLn([Prefix,'  sizeof(aint)=',FSizeOfAInt]);
 | |
| end;
 | |
| 
 | |
| procedure TPPU.GetMainUsesSectionNames(var List: TStrings);
 | |
| begin
 | |
|   GetUsesSection(FMainUsesSectionPos,List);
 | |
| end;
 | |
| 
 | |
| procedure TPPU.GetImplementationUsesSectionNames(var List: TStrings);
 | |
| begin
 | |
|   GetUsesSection(FImplementationUsesSectionPos,List);
 | |
| end;
 | |
| 
 | |
| procedure TPPU.GetLinkedFiles(var ListOfTPPULinkedFile: TObjectList);
 | |
| var
 | |
|   EntryNr: Byte;
 | |
|   Item: TPPULinkedFile;
 | |
|   Filename: String;
 | |
|   Flags: LongInt;
 | |
| begin
 | |
|   if FInterfaceHeaderPos=0 then exit;
 | |
|   SetDataPos(FInterfaceHeaderPos);
 | |
|   repeat
 | |
|     EntryNr:=ReadEntry;
 | |
|     case EntryNr of
 | |
|     iblinkunitofiles,iblinkunitstaticlibs,iblinkunitsharedlibs,
 | |
|     iblinkotherofiles,iblinkotherstaticlibs,iblinkothersharedlibs,
 | |
|     iblinkotherframeworks:
 | |
|       begin
 | |
|         while not EndOfEntry do begin
 | |
|           Filename:=ReadEntryShortstring;
 | |
|           Flags:=ReadEntryLongint;
 | |
|           //debugln(['TPPU.GetLinkedFiles ',PPUEntryName(EntryNr),' ',Filename]);
 | |
|           if ListOfTPPULinkedFile=nil then
 | |
|             ListOfTPPULinkedFile:=TObjectList.Create(true);
 | |
|           Item:=TPPULinkedFile.Create;
 | |
|           Item.ID:=EntryNr;
 | |
|           Item.Filename:=Filename;
 | |
|           Item.Flags:=Flags;
 | |
|           ListOfTPPULinkedFile.Add(Item);
 | |
|         end;
 | |
|       end;
 | |
| 
 | |
|     ibendinterface:
 | |
|       break;
 | |
| 
 | |
|     else
 | |
|       FEntryPos:=FEntry.size;
 | |
|     end;
 | |
|   until false;
 | |
| end;
 | |
| 
 | |
| function TPPU.GetInitProcName: string;
 | |
| begin
 | |
|   Result:=GetProcMangledName(FInitProcPos);
 | |
| end;
 | |
| 
 | |
| function TPPU.GetFinalProcName: string;
 | |
| begin
 | |
|   Result:=GetProcMangledName(FFinalProcPos);
 | |
| end;
 | |
| 
 | |
| end.
 | |
| 
 | 
