diff options
author | Graeme Geldenhuys <graemeg@gmail.com> | 2009-10-24 01:12:50 +0200 |
---|---|---|
committer | Graeme Geldenhuys <graemeg@gmail.com> | 2009-10-24 01:12:50 +0200 |
commit | ff350d99fff38a3f1f2bfe3a230448cc991d4ac6 (patch) | |
tree | 88c6f45a9a3e651f99b2db09752fa7ed668f13a8 /src/docdump | |
parent | 1b0638852d202a17b264b02911341d44a0a81cc2 (diff) | |
download | fpGUI-ff350d99fff38a3f1f2bfe3a230448cc991d4ac6.tar.xz |
New debug project: docdump which dumps the file structure of INF files
out to a more human readable form. Hopefully this will help me debug
and reading problems in docview. And also help with implementation
of a custom ipfc compiler (one day).
Signed-off-by: Graeme Geldenhuys <graemeg@gmail.com>
Diffstat (limited to 'src/docdump')
-rw-r--r-- | src/docdump/docdump.lpi | 65 | ||||
-rw-r--r-- | src/docdump/docdump.lpr | 87 | ||||
-rw-r--r-- | src/docdump/filestreamhelper.pas | 35 | ||||
-rw-r--r-- | src/docdump/readheader.pas | 114 |
4 files changed, 301 insertions, 0 deletions
diff --git a/src/docdump/docdump.lpi b/src/docdump/docdump.lpi new file mode 100644 index 00000000..182a9da4 --- /dev/null +++ b/src/docdump/docdump.lpi @@ -0,0 +1,65 @@ +<?xml version="1.0"?> +<CONFIG> + <ProjectOptions> + <Version Value="7"/> + <General> + <SessionStorage Value="InIDEConfig"/> + <MainUnit Value="0"/> + <TargetFileExt Value=""/> + <UseAppBundle Value="False"/> + </General> + <VersionInfo> + <ProjectVersion Value=""/> + </VersionInfo> + <PublishOptions> + <Version Value="2"/> + <IgnoreBinaries Value="False"/> + <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/> + <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/> + </PublishOptions> + <RunParams> + <local> + <FormatVersion Value="1"/> + <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/> + </local> + </RunParams> + <Units Count="5"> + <Unit0> + <Filename Value="docdump.lpr"/> + <IsPartOfProject Value="True"/> + <UnitName Value="docdump"/> + </Unit0> + <Unit1> + <Filename Value="../IPFEscapeCodes.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="IPFEscapeCodes"/> + </Unit1> + <Unit2> + <Filename Value="../IPFFileFormatUnit.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="IPFFileFormatUnit"/> + </Unit2> + <Unit3> + <Filename Value="readheader.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="readheader"/> + </Unit3> + <Unit4> + <Filename Value="filestreamhelper.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="filestreamhelper"/> + </Unit4> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="8"/> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)/"/> + <OtherUnitFiles Value="../"/> + <UnitOutputDirectory Value="units"/> + </SearchPaths> + <Other> + <CompilerPath Value="$(CompPath)"/> + </Other> + </CompilerOptions> +</CONFIG> diff --git a/src/docdump/docdump.lpr b/src/docdump/docdump.lpr new file mode 100644 index 00000000..4415a0a8 --- /dev/null +++ b/src/docdump/docdump.lpr @@ -0,0 +1,87 @@ +program docdump; + +{$mode objfpc}{$H+} + +uses + {$IFDEF UNIX}{$IFDEF UseCThreads} + cthreads, + {$ENDIF}{$ENDIF} + Classes, SysUtils, IPFFileFormatUnit, IPFEscapeCodes, CustApp, readheader, + filestreamhelper; + +type + + { TDocDump } + + TDocDump = class(TCustomApplication) + private + FIn: TFileStream; + FOut: TFileTextStream; + protected + procedure DoRun; override; + public + constructor Create(TheOwner: TComponent); override; + destructor Destroy; override; + procedure WriteHelp; virtual; + end; + +{ TDocDump } + +procedure TDocDump.DoRun; +var + ErrorMsg: String; +begin + // quick check parameters + ErrorMsg:=CheckOptions('h','help'); + if ErrorMsg<>'' then begin + ShowException(Exception.Create(ErrorMsg)); + Terminate; + Exit; + end; + + // parse parameters + if HasOption('h','help') then begin + WriteHelp; + Terminate; + Exit; + end; + + FIn := TFileStream.Create(ParamStr(1), fmOpenRead); + FOut := TFileTextStream.Create(ExtractFileName(ParamStr(1))+'.txt', fmCreate); + try + FOut.WriteLn(Format('File name: %s (%d bytes)', [ExtractFileName(ParamStr(1)), FIn.Size])); + ProcessHeader(FIn, FOut); + finally + FIn.Free; + FOut.Free; + end; + // stop program loop + Terminate; +end; + +constructor TDocDump.Create(TheOwner: TComponent); +begin + inherited Create(TheOwner); + StopOnException:=True; +end; + +destructor TDocDump.Destroy; +begin + inherited Destroy; +end; + +procedure TDocDump.WriteHelp; +begin + { add your help code here } + writeln('Usage: ',ExeName,' -h'); +end; + +var + Application: TDocDump; + +begin + Application:=TDocDump.Create(nil); + Application.Run; + Application.Free; +end. + diff --git a/src/docdump/filestreamhelper.pas b/src/docdump/filestreamhelper.pas new file mode 100644 index 00000000..ff831a91 --- /dev/null +++ b/src/docdump/filestreamhelper.pas @@ -0,0 +1,35 @@ +unit filestreamhelper; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils; + +type + TFileTextStream = class(TFileStream) + public + procedure WriteLn(const fmt: String; const args: array of const); + procedure WriteLn(const s: String); + end; + +implementation + +{ TFileTextStream } + +procedure TFileTextStream.WriteLn(const fmt: String; const args: array of const); +var + temp: String; +begin + temp := Format(fmt, args) + LineEnding; + Write(temp[1], Length(temp)); +end; + +procedure TFileTextStream.WriteLn(const s: String); +begin + self.WriteLn('%s', [s]); +end; + +end. + diff --git a/src/docdump/readheader.pas b/src/docdump/readheader.pas new file mode 100644 index 00000000..0c5f7bc8 --- /dev/null +++ b/src/docdump/readheader.pas @@ -0,0 +1,114 @@ +unit readheader; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, filestreamhelper; + +procedure ProcessHeader(AIn: TFileStream; AOut: TFileTextStream); + +implementation + +uses + IPFFileFormatUnit; + +type + TWord = record + b1: AnsiChar; + b2: AnsiChar; + end; + + Unsigned_31 = 0 .. (1 shl 31) - 1; // 31 bit type + + TOverlayID = packed record + b1: Byte; + b2: Byte; + b3: Byte; + end; + + TOverlaySearchStart = bitpacked record + SearchOffset: Unsigned_31; + IsRec16bitSize: boolean; + end; + + +procedure ProcessHeader(AIn: TFileStream; AOut: TFileTextStream); +var + hdr: TPHelpFileHeader; + bytes: integer; + s: string; + w: TWord; + i: uint32; + t0: TOverlayID; + t1: TOverlaySearchStart; +begin + New(hdr); + try + AIn.Seek(0, soBeginning); + bytes := AIn.Read(hdr^, SizeOf(THelpFileHeader)); + if bytes <> SizeOf(THelpFileHeader) then + raise Exception.Create('Failed to read complete file header'); + + if hdr^.ID <> INF_HEADER_ID then + raise Exception.Create('This is not an OS/2 help file'); + + AOut.WriteLn('Header Section'); + t0 := TOverlayID(hdr^.ID); + s := hdr^.ID; + AOut.WriteLn(Format(' hdr.id: %4.2x %2x %2x ("%s") : Magic word' ,[Byte(hdr^.id[0]), Byte(hdr^.id[1]), Byte(hdr^.id[2]), s])); + if (hdr^.flags and $01) > 0 then + s := 'INF' + else + s := 'HLP'; + AOut.WriteLn(Format(' hdr.flags: %8.2x (%s format) : File format' ,[hdr^.flags, s])); + AOut.WriteLn(Format(' hdr.size: %8.4x (%0:7d bytes) : Size of this header structure', [hdr^.hdrsize])); + AOut.WriteLn(Format(' hdr.version: %6d.%d : version of file format?', [hdr^.version_hi, hdr^.version_lo])); + AOut.WriteLn(Format(' hdr.ntoc: %8.4x (%0:13d) : No of TOC entries', [hdr^.ntoc])); + AOut.WriteLn(Format(' hdr.tocstart: %8.8x (%0:7d bytes) : 32bit file offset to start of TOC', [hdr^.tocstart])); + AOut.WriteLn(Format(' hdr.toclen: %8.8x (%0:7d bytes) : bytes occupied by TOC entries', [hdr^.toclen])); + AOut.WriteLn(Format(' hdr.tocoffsetsstart: %8.8x (%0:7d bytes) : file offset to array of TOC offsets', [hdr^.tocoffsetsstart])); + AOut.WriteLn(Format(' hdr.nres: %8.4x (%0:13d) : number of panels with resource numbers', [hdr^.nres])); + AOut.WriteLn(Format(' hdr.resstart: %8.8x (%0:7d bytes) : 32bit file offset of ressource number table', [hdr^.resstart])); + AOut.WriteLn(Format(' hdr.nname: %8.4x (%0:13d) : number of panels with textual name', [hdr^.nname])); + AOut.WriteLn(Format(' hdr.namestart: %8.8x (%0:7d bytes) : 32bit file offset to panel name table', [hdr^.namestart])); + AOut.WriteLn(Format(' hdr.nindex: %8.4x (%0:13d) : number of index entries', [hdr^.nindex])); + AOut.WriteLn(Format(' hdr.indexstart: %8.8x (%0:7d bytes) : 32bit file offset to index table', [hdr^.indexstart])); + AOut.WriteLn(Format(' hdr.indexlen: %8.8x (%0:7d bytes) : size of index table', [hdr^.indexlen])); + AOut.WriteLn(Format(' hdr.icmdCount: %8.4x (%0:13d) : number of icmd index items', [hdr^.icmdCount])); + AOut.WriteLn(Format(' hdr.icmdOffset: %8.8x (%0:7d bytes) : file offset to icmd index items', [hdr^.icmdOffset])); + AOut.WriteLn(Format(' hdr.icmdSize: %8.8x (%0:7d bytes) : size of icmd index table', [hdr^.icmdSize])); + t1 := TOverlaySearchStart(hdr^.searchstart); + i := t1.SearchOffset; + AOut.WriteLn(Format(' hdr.searchstart :31 %8.8x (%0:7d bytes) : 31 bit file offset of full text search table', [i, i])); + if t1.IsRec16bitSize then + s := 'search rec is 16bit size' + else + s := 'search rec is 8bit size'; + AOut.WriteLn(Format(' hdr.recSize :1 %s (%s) : if high bit set, search record size is 16bit', [BoolToStr(t1.IsRec16bitSize, True), s])); + AOut.WriteLn(Format(' hdr.searchlen: %8.8x (%0:7d bytes) : size of full text search table', [hdr^.searchlen])); + AOut.WriteLn(Format(' hdr.nslots: %8.4x (%0:13d) : number of "slots"', [hdr^.nslots])); + AOut.WriteLn(Format(' hdr.slotsstart: %8.8x (%0:7d bytes) : 32bit file offset of the slots array', [hdr^.slotsstart])); + AOut.WriteLn(Format(' hdr.dictlen: %8.8x (%0:7d bytes) : bytes occupied by the "dictionary"', [hdr^.dictlen])); + AOut.WriteLn(Format(' hdr.ndict: %8.4x (%0:13d) : number of entries in the dictionary', [hdr^.ndict])); + AOut.WriteLn(Format(' hdr.dictstart: %8.8x (%0:7d bytes) : 32bit file offset to start of dictionary', [hdr^.dictstart])); + AOut.WriteLn(Format(' hdr.imgstart: %8.8x (%0:7d bytes) : 32bit file offset to image data', [hdr^.imgstart])); + AOut.WriteLn(Format(' hdr.maxCVTIndex: %8.2x (%0:13d) : highest index inside panel''s local dictionary', [hdr^.maxCVTIndex])); + AOut.WriteLn(Format(' hdr.nlsstart: %8.8x (%0:7d bytes) : 32bit file offset of NLS table', [hdr^.nlsstart, hdr^.nlsstart])); + AOut.WriteLn(Format(' hdr.nlslen: %8.8x (%0:7d bytes) : size of NLS table', [hdr^.nlslen])); + AOut.WriteLn(Format(' hdr.extstart: %8.8x (%0:7d bytes) : 32bit file offset of extended data block', [hdr^.extstart])); + AOut.WriteLn(Format(' hdr.reserved: %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x : for future use. set to zero.', + [hdr^.reserved[0], hdr^.reserved[1], hdr^.reserved[2], hdr^.reserved[3], hdr^.reserved[4], hdr^.reserved[5], + hdr^.reserved[6], hdr^.reserved[7], hdr^.reserved[8], hdr^.reserved[9], hdr^.reserved[10], hdr^.reserved[11] ])); + AOut.WriteLn(Format(' hdr.title: "%s" : ASCII title of database', [hdr^.title])); + +{ title: array[ 0..47 ] of char; // ASCII title of database +} + finally + Dispose(hdr); + end; +end; + +end. + |