{$A+,B-,F-,G+,I-,P-,Q-,R-,S-,T-,V-,X+,Y+} Program H2Pas; { Program: H2PAS Version: 1.21 Purpose: convert C header files to some kind of Pascal units Developer: Peter Sawatzki (ps) (c) 1993 Buchenhof 3, 58091 Hagen, Germany CompuServe: 100031,3002 revision history: date version author modification 11/03/93 1.00 ps written 05/10/94 1.10 ps add EXEHDR import support 06/29/94 1.2x ps minor modifications } Uses Objects, Strings; Const Version = 'H2Pas v.1.21'; H2PasIni= 'H2Pas.Ini'; CRLF = #13#10; StdUses: pChar = 'Uses'+CRLF+ ' WinTypes,'+CRLF+ ' WinProcs;'; HasImports: Boolean = False; WhichBlock: (Undefd, InConst, InType, InVar, InFunc) = Undefd; Var DstName, Imports: String[67]; Function WordCount(aStr, Delims: pChar): Integer; Var Count: Integer; EndStr: pChar; Begin EndStr:= StrEnd(aStr); Count:= 0; While aStr<=EndStr Do Begin While (aStr<=EndStr) And (StrScan(Delims, aStr[0])<>Nil) Do Inc(aStr); If aStr<=EndStr Then Inc(Count); While (aStr<=EndStr) And (StrScan(Delims, aStr[0])=Nil) Do Inc(aStr) End; WordCount:= Count End; Function WordPosition (aStr, Delims: pChar; No: Integer): pChar; Var Count: Integer; EndStr: pChar; Begin EndStr:= StrEnd(aStr); Count:= 0; WordPosition:= Nil; While (aStr<=EndStr) And (Count<>No) Do Begin While (aStr<=EndStr) And (StrScan(Delims, aStr[0])<>Nil) Do Inc(aStr); If aStr<=EndStr Then Inc(Count); If Count<>No Then While (aStr<=EndStr) And (StrScan(Delims, aStr[0])=Nil) Do Inc(aStr) Else WordPosition:= aStr End End; Function ExtractWord (aDst, aStr, Delims: pChar; No: Integer): pChar; Var EndStr: pChar; Begin ExtractWord:= aDst; aStr:= WordPosition(aStr, Delims, No); If Assigned(aStr) Then Begin EndStr:= StrEnd(aStr); While (aStr<=EndStr) And (StrScan(Delims, aStr[0])=Nil) Do Begin aDst[0]:= aStr[0]; Inc(aStr); Inc(aDst) End End; aDst[0]:= #0 End; Function Trim (aDst, aSrc: pChar): pChar; Var EndStr: pChar; Begin Trim:= aDst; If Not Assigned(aSrc) Or (aSrc[0]=#0) Then aDst[0]:= #0 Else Begin EndStr:= StrEnd(aSrc); While (aSrcaDst) And (EndStr[0]<=' ') Do Begin EndStr[0]:= #0; Dec(EndStr) End End End; Function Pad (aDst, aSrc: pChar; Count: Integer): pChar; Begin Pad:= aDst; If aDst<>aSrc Then StrCopy(aDst, aSrc); Count:= Count-StrLen(aDst); aDst:= StrEnd(aDst); While Count>0 Do Begin aDst[0]:= ' '; Inc(aDst); Dec(Count) End; aDst[0]:= #0 End; Function StrIPos(Str1, Str2: PChar): PChar; Var EndStr: pChar; Len: Integer; Begin StrIPos:= Nil; EndStr:= StrEnd(Str1); Len:= StrLen(Str2); Repeat Str1:= StrScan(Str1, Str2[0]); If Str1=Nil Then Exit; If StrLIComp(Str1, Str2, Len)=0 Then Begin StrIPos:= Str1; Exit End; Inc(Str1) Until Str1>EndStr End; Function JustFilename(PathName : string) : string; {-Return just the filename of a pathname} Var I: Word; Begin I:= Succ(Word(Length(PathName))); Repeat Dec(I); Until (PathName[I] in ['\', ':', #0]) or (I = 0); JustFilename := Copy(PathName, Succ(I), 64); End; function JustName(PathName : string) : string; {-Return just the name (no extension, no path) of a pathname} var DotPos : Byte; begin PathName := JustFileName(PathName); DotPos := Pos('.', PathName); if DotPos > 0 then PathName := Copy(PathName, 1, DotPos-1); JustName := PathName; end; Function JustPath(aName: string): string; {-Return just the path of a filename} Var I: Word; Begin I:= Succ(Word(Length(aName))); Repeat Dec(I); Until (aName[I] in ['\', ':', #0]) or (I = 0); JustPath:= Copy(aName, 1, I) End; Procedure Fatal (aMsg: pChar); Begin WriteLn(aMsg); Halt(255) End; Function GetLine (aDst: pChar; Var aFile: Text): pChar; Var aString: String; p,i: Integer; Begin {$i-} ReadLn(aFile, aString); If IoResult<>0 Then Fatal('Read error.'); p:= Pos('//', aString); If p>0 Then Begin aString[p+1]:= '*'; aString:= aString+' */' End; p:= Pos(#9, aString); While p>0 Do Begin aString[p]:= ' '; For i:= 1 To 7-((p-1) Mod 8) Do Insert(' ', aString, p); p:= Pos(#9, aString) End; GetLine:= StrPCopy(aDst, aString) End; Procedure OutLn (Var aFile: Text; OutStr: pChar); Var oc: Char; Begin While OutStr[0]<>#0 Do Begin oc:= OutStr[0]; Case oc Of '/': If OutStr[1]='*' Then Begin oc:= '{'; Inc(OutStr,1) End; '*': If OutStr[1]='/' Then Begin oc:= '}'; Inc(OutStr) End End; Write(aFile, oc); If IoResult<>0 Then Fatal('Write error.'); Inc(OutStr) End; Write(aFile,CRLF); If IoResult<>0 Then Fatal('Write error.') End; Procedure HeaderInfo (Var aFile: Text); Var aLine: Array[0..100] Of Char; Begin WriteLn(aFile, '{ Unit: ',DstName); WriteLn(aFile, ' Version: 1.00'); WriteLn(aFile, ' translated from file ',DstName,'.H'); WriteLn(aFile, ' raw translation using '+Version+', (c) Peter Sawatzki'); WriteLn(aFile, ' fine tuned by:'); WriteLn(aFile, ' (fill in)'); WriteLn(aFile, ' '); WriteLn(aFile, ' revision history:'); WriteLn(aFile, ' Date: Ver: Author: Mod:'); WriteLn(aFile, ' xx/xx/94 1.00 '); WriteLn(aFile, '}'); WriteLn(aFile, 'Unit ',DstName,';'); WriteLn(aFile, 'Interface'); If StrLen(StdUses)<>0 Then WriteLn(aFile, StdUses); End; {-the collection part} Type pImportEntry = ^tImportEntry; tImportEntry = Record TheName, TheDLL, TheOrd: pChar End; pImportCollection = ^tImportCollection; tImportCollection = Object(tSortedCollection) Function KeyOf(Item: Pointer): Pointer; Virtual; Function Compare(Key1, Key2: Pointer): Integer; Virtual; Procedure FreeItem(Item: Pointer); Virtual; End; pTypeMap = ^tTypeMap; tTypeMap = Record F, T: pChar; End; pTypeMapCollection = ^tTypeMapCollection; tTypeMapCollection = Object(tSortedCollection) Function KeyOf(Item: Pointer): Pointer; Virtual; Function Compare(Key1, Key2: Pointer): Integer; Virtual; Procedure FreeItem(Item: Pointer); Virtual; End; Function tImportCollection.KeyOf(Item: Pointer): Pointer; Begin KeyOf:= pImportEntry(Item)^.TheName End; Function tImportCollection.Compare(Key1, Key2: Pointer): Integer; Begin Compare:= StrIComp(Key1, Key2) End; Procedure TImportCollection.FreeItem(Item: Pointer); Begin StrDispose(pImportEntry(Item)^.TheName); StrDispose(pImportEntry(Item)^.TheDLL); StrDispose(pImportEntry(Item)^.TheOrd); Dispose(pImportEntry(Item)) End; Function tTypeMapCollection.KeyOf(Item: Pointer): Pointer; Begin KeyOf:= pTypeMap(Item)^.F End; Function tTypeMapCollection.Compare(Key1, Key2: Pointer): Integer; Begin Compare:= StrIComp(Key1, Key2) End; Procedure tTypeMapCollection.FreeItem(Item: Pointer); Begin StrDispose(pTypeMap(Item)^.F); StrDispose(pTypeMap(Item)^.T); Dispose(pTypeMap(Item)) End; Const TheImports: pImportCollection = Nil; TheFuncs: pStrCollection = Nil; TheStructs: pStrCollection = Nil; TheTypeMap: pTypeMapCollection = Nil; TheModMap: pStrCollection = Nil; Procedure CreateCollections; Begin TheImports:= New(pImportCollection, Init(100, 50)); TheFuncs:= New(pStrCollection, Init(10, 20)); TheStructs:= New(pStrCollection, Init(10, 20)); TheTypeMap:= New(pTypeMapCollection, Init(10, 10)); TheModMap:= New(pStrCollection, Init(10, 10)); End; Procedure DestroyCollections; Begin If Assigned(TheImports) Then Dispose(TheImports, Done); If Assigned(TheFuncs) Then Dispose(TheFuncs, Done); If Assigned(TheStructs) Then Dispose(TheStructs, Done); If Assigned(TheTypeMap) Then Dispose(TheTypeMap, Done); If Assigned(TheModMap) Then Dispose(TheModMap, Done); End; Procedure AddImport (aName, aDLL, anOrd: pChar); Var anEntry: pImportEntry; Begin anEntry:= New(pImportEntry); anEntry^.TheName:= StrNew(aName); anEntry^.TheDLL:= StrNew(aDLL); anEntry^.TheOrd:= StrNew(anOrd); TheImports^.Insert(anEntry) End; Procedure AddFunc (aName: pChar); Begin TheFuncs^.Insert(StrNew(aName)) End; Procedure AddStruct (aName: pChar); Begin TheStructs^.Insert(StrNew(aName)) End; Procedure AddType (aSrc, aDst: pChar); Var anEntry: pTypeMap; Begin anEntry:= New(pTypeMap); anEntry^.F:= StrNew(aSrc); anEntry^.T:= StrNew(aDst); TheTypeMap^.Insert(anEntry) End; Procedure AddMod (aName: pChar); Begin TheModMap^.Insert(StrNew(aName)) End; Function GetOrdDLL (aName, RetDLL, RetOrd: pChar): Boolean; Var Index: Integer; Begin If TheImports^.Search(aName, Index) Then With pImportEntry(TheImports^.At(Index))^ Do Begin GetOrdDLL:= True; StrCopy(RetDLL, TheDLL); StrCopy(RetOrd, TheOrd) End Else GetOrdDLL:= False End; Procedure ReadImports (aFileName: String); Var aFile: Text; aLine: Array[0..500] Of Char; aName, aDLL, anOrd: Array[0..60] Of Char; aWord: Array[0..60] Of Char; Begin {$i-} Assign(aFile, aFileName); Reset(aFile); If IoResult<>0 Then Exit; HasImports:= True; StrCopy(aDLL, '?'); While Not Eof(aFile) Do Begin GetLine(aLine, aFile); If StrComp(ExtractWord(aWord, aLine, ' ', 1),'Library:')=0 Then ExtractWord(aDLL, aLine, ' ', 2) Else If StrComp(ExtractWord(aWord, aLine, ' ', 5),'exported,')=0 Then Begin ExtractWord(anOrd, aLine, ' ', 1); ExtractWord(aName, aLine, ' ', 4); AddImport(aName, aDLL, anOrd) End End; Close(aFile) End; Procedure ReadIni; Var IniFile: Text; aStr: String; aLine, Word1, Word2: Array[0..255] Of Char; rm: (rmNone, rmTypeMap, rmModMap); p: Integer; Begin {$i-} Assign(IniFile, H2PasIni); Reset(IniFile); If IoResult<>0 Then Begin Assign(IniFile, JustPath(ParamStr(0))+'\'+H2PasIni); Reset(IniFile); If IoResult<>0 Then Exit End; rm:= rmNone; While Not Eof(IniFile) Do Begin ReadLn(IniFile, aStr); p:= Pos(';', aStr); If (p>0) Then aStr[0]:= Chr(p-1); StrPCopy(aLine, aStr); Trim(aLine, aLine); If StrLen(aLine)=0 Then Continue; If aLine[0]='[' Then Begin If StrIComp(aLine, '[TypeMap]')=0 Then rm:= rmTypeMap Else If StrIComp(aLine, '[ModMap]')=0 Then rm:= rmModMap Else rm:= rmNone; Continue End; Case rm Of rmTypeMap: AddType(Trim(Word1, ExtractWord(Word1, aLine, '=', 1)), Trim(Word2, ExtractWord(Word2, aLine, '=', 2))); rmModMap: AddMod(aLine); End End; Close(IniFile) End; Function Modifier (aPart: pChar): Boolean; Var Index: Integer; Begin Modifier:= TheModMap^.Search(aPart, Index) End; Function TypeConvert (aDst, aSrc: pChar): pChar; Var aWord, ToParse: Array[0..79] Of Char; i, anInt, anError: Integer; aTemp: Array[0..79] Of Char; Index: Integer; Begin TypeConvert:= aDst; aDst[0]:= #0; ExtractWord(aTemp, aSrc, '[]', 2); If StrLen(aTemp)>0 Then Begin Val(aTemp, anInt, anError); If anError=0 Then Begin Str(anInt-1:0, aTemp); StrCat(StrCat(StrCat(aDst,'Array[0..'), aTemp),'] Of '); End Else StrCat(StrCat(StrCat(aDst,'?'), aTemp),'?') End; ExtractWord(ToParse, aSrc, '[]', 1); aTemp[0]:= #0; For i:= 1 To WordCount(ToParse, ' ') Do Begin ExtractWord(aWord, ToParse, ' ', i); If aWord[0]='*' Then Begin StrCat(aTemp,'* '); aWord[0]:= ' '; Trim(aWord, aWord) End; If (aWord[0]<>#0) And Not Modifier(aWord) Then StrCat(StrCat(aTemp, aWord),' '); End; Trim(aTemp, aTemp); If TheTypeMap^.Search(@aTemp, Index) Then With pTypeMap(TheTypeMap^.At(Index))^ Do StrCopy(aTemp, T); StrCat(aDst, aTemp) End; Const IdMax = 50; Type tIdTable = Array[1..IdMax] Of Record TheId, TheType: Array[0..79] Of Char; TheComment: Array[0..300] Of Char End; Var IdCnt: Integer; IdTable: tIdTable; Procedure InitId; Begin IdCnt:= 0 End; Procedure AddId (anId, aType, aComment: pChar); Begin If IdCnt=IdMax Then Begin WriteLn('Error: Id Table full. HALT.'); Halt(1) End; Inc(IdCnt); With IdTable[IdCnt] Do Begin Trim(TheId, anId); TypeConvert(TheType, aType); Trim(TheComment, aComment) End End; Function ParseComment(Var Inf: Text; InStr, OutStr: pChar): Boolean; Var aWord: Array[0..40] Of Char; Begin ParseComment:= False; If StrPos(StrLCopy(aWord, InStr, 5),'/*')=Nil Then Exit; While StrPos(InStr, '*/')=Nil Do Begin StrCat(OutStr, InStr); GetLine(InStr, Inf) End; StrCat(OutStr, InStr); ParseComment:= True End; Function ParseDefine(InStr, OutStr: pChar): Boolean; Const DefineDelim = ' '; Var aWord: Array[0..512] Of Char; Rest, p: pChar; isConst: Boolean; i: Integer; Begin ParseDefine:= False; If WordCount(InStr, DefineDelim)<3 Then Exit; If (ExtractWord(aWord, InStr, DefineDelim, 1)<>Nil) And (StrIComp(aWord, '#define')=0) Then Begin isConst:= False; If WhichBlock<>InConst Then StrCopy(OutStr,CRLF+'Const'+CRLF+' ') Else StrCopy(OutStr,' '); ExtractWord(StrEnd(OutStr), InStr, DefineDelim, 2); StrCat(Pad(OutStr, OutStr, 35), '= '); Rest:= WordPosition(InStr, DefineDelim, 3); StrCopy(aWord, Rest); p:= StrPos(aWord,'/*'); If Assigned(p) Then p^:= #0; Trim(aWord, aWord); If StrLen(aWord)>15 Then Exit; p:= StrPos(aWord, '0x'); While Assigned(p) Do Begin isConst:= True; p[0]:= ' '; p[1]:= '$'; p:= StrPos(p, '0x') End; p:= StrScan(aWord, 'L'); {get rid of the f*cking 'L'} While Assigned(p) Do Begin If (p>aWord) Then Begin Dec(p); If p^ In ['0'..'9','A'..'F','a'..'f'] Then Begin p[1]:= ' '; IsConst:= True End; Inc(p) End; p:= StrScan(p+1, 'L') End; If Not IsConst Then For i:= 0 To StrLen(aWord)-1 Do If aWord[i] In ['0'..'9'] Then Begin IsConst:= True; Break End; If Not IsConst Then Exit; Trim(aWord, aWord); StrCat(StrCat(OutStr, aWord), ';'); p:= StrPos(Rest,'/*'); If Assigned(p) Then StrCat(Pad(OutStr,OutStr, 60), p); WhichBlock:= InConst; ParseDefine:= True End End; Function ParseStruct(Var Inf: Text; InStr, OutStr: pChar): Boolean; Var aWord, aComment, RecComment, RecName, anId, aType, Rest: Array[0..300] Of Char; possibleArray: Array[0..60] Of Char; p, cp: pChar; i: Integer; Begin ParseStruct:= False; If (StrIComp(ExtractWord(aWord, Instr, ' ', 1), 'struct')<>0) And (StrIComp(ExtractWord(aWord, Instr, ' ', 2), 'struct')<>0) Then Exit; p:= Instr; Instr:= StrScan(InStr, '{'); If Not Assigned(InStr) Then Exit; {-try to parse the structure} InStr^:= #0; ExtractWord(RecName, p, ' ', WordCount(p,' ')); Inc(InStr); Trim(InStr, InStr); If (InStr[0]='/') And (InStr[1]='*') Then StrCopy(RecComment, InStr) Else RecComment[0]:= #0; InStr:= StrEnd(InStr); cp:= InStr; Repeat GetLine(cp, Inf); p:= StrScan(cp, '}'); cp:= StrEnd(cp); cp^:= ' '; Inc(cp); cp^:= #0 Until Assigned(p); If WordCount(p+1,' ;')>0 Then ExtractWord(RecName, p+1, ' ;', 1); pChar(p-1)^:= #0; InitId; p:= InStr; Repeat cp:= p; p:= StrScan(p, ';'); If Assigned(p) Then Begin Trim(aWord, ExtractWord(aWord, cp, ';', 1)); {extract possible comment} cp:= StrPos(aWord, '/*'); If Assigned(cp) Then Begin StrCopy(aComment, cp); cp^:= #0 End Else aComment[0]:= #0; {-extract id and type} cp:= WordPosition(aWord, ' *', WordCount(aWord, ' *')); {last word} StrCopy(anId, cp); ExtractWord(possibleArray, anId,'[]',2); ExtractWord(anId, anId, '[]', 1); cp^:= #0; StrCopy(aType, aWord); If StrLen(possibleArray)>0 Then StrCat(StrCat(StrCat(aType,'['),possibleArray),']'); {-extract comment if after ';'} Inc(p); While p^=' ' Do Inc(p); While (p[0]='/') And (p[1]='*') Do Begin {append comment} cp:= StrEnd(aComment); Repeat cp^:= p^; Inc(p); Inc(cp) Until (p[0]=#0) Or ((p[0]='*') And (p[1]='/')); cp[0]:= #0; StrCat(Trim(aComment, aComment),' */'); If p[0]<>#0 Then Inc(p,2); While p^=' ' Do Inc(p) End; AddId(anId, aType, aComment) End Until Not Assigned(p); {-output the structure} If WhichBlock<>InType Then Begin StrCopy(OutStr,CRLF+'Type'+CRLF); OutStr:= StrEnd(OutStr) End; StrCopy(OutStr,' '); StrCat(OutStr, RecName); StrCat(OutStr,' = Record'); If RecComment[0]<>#0 Then StrCat(Pad(OutStr, OutStr, 40), RecComment); StrCat(OutStr,CRLF); For i:= 1 To IdCnt Do Begin OutStr:= StrEnd(OutStr); With IdTable[i] Do Begin StrCopy(OutStr,' '); {If StrIComp(TheId, TheType)=0 Then StrCat(OutStr, '_');} {it works as is} StrCat(OutStr, TheId); If (i#0 Then Begin Pad(OutStr, OutStr, 40); StrCat(OutStr, TheComment) End; StrCat(OutStr,CRLF) End End; StrCat(OutStr,' End;'); AddStruct(RecName); WhichBlock:= InType; ParseStruct:= True End; Function ParseAPI(Var Inf: Text; InStr, OutStr: pChar): Boolean; Var FHead, aWord, Res, FuncComment, FuncName, anId, aType, aComment: Array[0..200] Of Char; p, cp, cp2, pStart: pChar; i, Indent: Integer; IsFunc: Boolean; Unknown: Integer; Function ParseWordAndComment (aComment, aWord, Src: pChar; Delim: Char): pChar; {parse Src, search for delim. append comments to aComment, source to aWord} Var cp: pChar; Begin Repeat While Src^=' ' Do Inc(Src); While (Src[0]='/') And (Src[1]='*') Do Begin {append comment} cp:= StrEnd(aComment); Repeat cp^:= Src^; Inc(Src); Inc(cp) Until (Src[0]=#0) Or ((Src[0]='*') And (Src[1]='/')); cp[0]:= #0; StrCat(Trim(aComment, aComment),' */'); If Src[0]<>#0 Then Inc(Src,2); While Src^=' ' Do Inc(Src) End; cp:= StrEnd(aWord); While Not(Src^ In [#0,',','/']) Do Begin cp^:= Src^; Inc(Src); Inc(cp) End; cp^:= #0; If Src^=#0 Then Begin ParseWordAndComment:= Src; Exit End Until Src^=','; Inc(Src); While Src^=' ' Do Inc(Src); While (Src[0]='/') And (Src[1]='*') Do Begin {append comment} cp:= StrEnd(aComment); Repeat cp^:= Src^; Inc(Src); Inc(cp) Until (Src[0]=#0) Or ((Src[0]='*') And (Src[1]='/')); cp[0]:= #0; StrCat(Trim(aComment, aComment),' */'); If Src[0]<>#0 Then Inc(Src,2); While Src^=' ' Do Inc(Src) End; ParseWordAndComment:= Src End; Begin ParseAPI:= False; IsFunc:= False; FuncName[0]:= #0; Res[0]:= #0; If (StrPos(InStr,'typedef')<>Nil) Or (StrPos(InStr,'#define')<>Nil) Or (StrPos(InStr,'#if')<>Nil) Or (StrPos(InStr,'#el')<>Nil) Then Exit; pStart:= StrScan(InStr, '('); If Not Assigned(pStart) Then Exit; pStart^:= #0; Trim(FuncName, ExtractWord(FuncName, InStr, ' ', WordCount(InStr, ' '))); cp:= WordPosition(InStr, ' ', WordCount(InStr, ' ')); If Assigned(cp) Then Begin cp[0]:= #0; Trim(Res, TypeConvert(Res, InStr)) End Else StrCopy(Res, '?????'); InStr:= pStart+1; cp:= InStr; p:= StrScan(cp, ';'); While Not Assigned(p) Do Begin cp:= StrEnd(cp); cp^:= ' '; Inc(cp); GetLine(cp, Inf); p:= StrScan(cp, ';') End; StrCopy(FuncComment, p+1); Repeat Dec(p) Until (p<=InStr) Or (p^=')'); p^:= #0; InitId; Unknown:= 0; p:= InStr; While p^<>#0 Do Begin aComment[0]:= #0; aWord[0]:= #0; p:= ParseWordAndComment(aComment, aWord, p, ','); Trim(aWord, aWord); TypeConvert(aType, aWord); anId[0]:= #0; cp:= WordPosition(aWord, ' *', WordCount(aWord, ' *')); {last word} If (WordCount(aWord,' *')=1) Or (Assigned(cp) And (StrIComp(cp, TypeConvert(aType, cp))<>0)) Then Begin {non-Ansi declaration} Inc(Unknown); Str(Unknown, anId); Move(anId[0], anId[3], StrLen(anId)+1); anId[0]:= 'P'; anId[1]:= 'a'; anId[2]:= 'r'; End Else Begin If Assigned(cp) Then Begin StrCopy(anId, cp); cp^:= #0 End; TypeConvert(aType, aWord) End; AddId(anId, aType, aComment) End; StrCopy(OutStr, ' Function '); StrCat(OutStr, FuncName); StrCat(OutStr, ' ('); Indent:= StrLen(OutStr); OutStr:= StrEnd(OutStr); aWord[0]:= #0; For i:= 1 To IdCnt Do With IdTable[i] Do Begin StrCat(aWord, TheId); If (i#0 Then StrCat(Pad(aWord, aWord, 60-Indent), TheComment); If (Indent+StrLen(aWord)>90) Or (TheComment[0]<>#0) Then Begin StrCopy(OutStr, aWord); OutStr:= StrEnd(OutStr); If i'+CRLF+ '#include "'+DstName+'.h"'+CRLF+ 'void veri (char *aStr, int aSize)'+CRLF+ '{ printf("Size of %s= %5i\n",aStr,aSize); }'+CRLF); WriteLn(Out,'void main (void)'+CRLF+ '{ printf("verification of '+DstName+' for C:\n");'); TheStructs^.ForEach(@VeriC); WriteLn(Out,'}'); End; Const LineBufSize = 5000; IoBufSize = 32*1024; Type IoBuf = Array[0..IoBufSize-1] Of Char; pIoBuf = ^IoBuf; Var Inf, Out: Text; InStr, OutStr: pChar; Begin WriteLn(Version,', written 1993 by P. Sawatzki'); If Not (ParamCount In [2,3]) Then Begin WriteLn('Usage: H2Pas InFile OutFile [ImportList]'); Halt End; CreateCollections; ReadIni; If ParamStr(3)<>'' Then Imports:= ParamStr(3) Else Imports:= JustName(ParamStr(1))+'.Imp'; {$i-} Assign(Inf, ParamStr(1)); Reset(Inf); If IoResult<>0 Then Fatal('Input file not found'); Assign(Out, ParamStr(2)); ReWrite(Out); If IoResult<>0 Then Fatal('Unable to create output file'); DstName:= JustName(ParamStr(2)); GetMem(InStr, LineBufSize); GetMem(OutStr, LineBufSize); Write('Processing files...'); HeaderInfo(Out); While Not Eof(Inf) Do Begin GetLine(InStr, Inf); OutStr[0]:= #0; If ParseComment(Inf, InStr, OutStr) Or ParseDefine(InStr, OutStr) Or ParseStruct(Inf, InStr, OutStr) Or ParseAPI(Inf, InStr, OutStr) Then OutLn(Out, OutStr) Else OutLn(Out, InStr) End; WriteLn('Done.'); Write('Reading import file ',Imports,'...'); ReadImports(Imports); If HasImports Then WriteLn('Done.') Else WriteLn('Not found.'+CRLF+ '(generate an import file using "EXEHDR File.DLL >'+JustName(ParamStr(1))+ '.Imp")'); Write('Appending report...'); GenerateReport(Out); WriteLn('Done.'); DestroyCollections; FreeMem(InStr, LineBufSize); FreeMem(OutStr, LineBufSize); Close(Inf); Close(Out) End. { ------------- INFO ON THIS PROGRAM ------------------ } ReadMe.Txt for H2Pas ==================== H2Pas is a quick and dirty hack to convert C-Header files to Pascal units. If you make modifications, please drop me a copy at Peter Sawatzki, CompuServe 100031,3002 In it's current implementation (1.20) H2Pas does the following: - convert structs - convert constant defines - convert procedure/function headers - 'convert' comments of style /* xxxx */ to { xxxx } and comments of style // yyyy to { yyy } - make use of IMPort files to resolve DLL index entries - output C and Pascal code to verify correctness of C and Pascal structure sizes How to use and generate import files: ------------------------------------- if a EXEHDR type .IMP file is present for the DLL with information about the entry points of a function, H2Pas outputs an unit implementation section with entries of the form: Function Ctl3DEnabled; External 'CTL3D' Index 5; where the appropriate indices are resolved from information gathered from the .IMP file. To generate the .IMP file for a DLL -say CTL3D.DLL- one must do the following: EXEHDR CTL3D.DLL >CTL3D.IMP How to execute H2Pas -------------------- Usage: H2Pas Ctl3D.H Ctl3D.Pas [Ctl3D.Imp] where Ctl3D.H is the source C header file, Ctl3D.Pas is the destination pascal unit to be generated and Ctl3D.Imp is an optional import file generated from EXEHDR H2Pas.Ini --------- currently H2Pas.Ini has two areas for customization: [TypeMap] C-Type = Pascal-Type maps a certain C-type to a Pascal type (see sample H2Pas.Ini) [ModMap] modifier a list of modifiers that H2Pas should ignore (see sample H2Pas.Ini) written by Peter Sawatzki Buchenhof 3 58091 Hagen / Germany CompuServe: 100031,3002 { ------------------ SAMPLE INI FILE NEED FOR THIS UNIT ---------- } { CUT and Save as H2PAS.INI } [TypeMap] unsigned = Word unsigned int = Word char = Char unsigned long = LongInt int = Integer char far * = pChar unsigned char = Byte byte = Byte char * = pChar long = LongInt WORD = Word DWORD = LongInt ULONG = LongInt BOOL = Bool UINT = Word void * = Pointer ; Windows stuff BITMAPINFO = tBitmapInfo HANDLE = tHandle HWINDOW = hWindow COLORREF = tColorRef [ModMap] WINAPI WINGAPI APIENTRY EXPENTRY EXPORT EXTERN PASCAL FAR _FAR const