~ubuntu-branches/ubuntu/saucy/lazarus/saucy

« back to all changes in this revision

Viewing changes to components/codetools/h2pastool.pas

  • Committer: Package Import Robot
  • Author(s): Paul Gevers, Abou Al Montacir, Bart Martens, Paul Gevers
  • Date: 2013-06-08 14:12:17 UTC
  • mfrom: (1.1.9)
  • Revision ID: package-import@ubuntu.com-20130608141217-7k0cy9id8ifcnutc
Tags: 1.0.8+dfsg-1
[ Abou Al Montacir ]
* New upstream major release and multiple maintenace release offering many
  fixes and new features marking a new milestone for the Lazarus development
  and its stability level.
  - The detailed list of changes can be found here:
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_release_notes
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_fixes_branch
* LCL changes:
  - LCL is now a normal package.
      + Platform independent parts of the LCL are now in the package LCLBase
      + LCL is automatically recompiled when switching the target platform,
        unless pre-compiled binaries for this target are already installed.
      + No impact on existing projects.
      + Linker options needed by LCL are no more added to projects that do
        not use the LCL package.
  - Minor changes in LCL basic classes behaviour
      + TCustomForm.Create raises an exception if a form resource is not
        found.
      + TNotebook and TPage: a new implementation of these classes was added.
      + TDBNavigator: It is now possible to have focusable buttons by setting
        Options = [navFocusableButtons] and TabStop = True, useful for
        accessibility and for devices with neither mouse nor touch screen.
      + Names of TControlBorderSpacing.GetSideSpace and GetSpace were swapped
        and are now consistent. GetSideSpace = Around + GetSpace.
      + TForm.WindowState=wsFullscreen was added
      + TCanvas.TextFitInfo was added to calculate how many characters will
        fit into a specified Width. Useful for word-wrapping calculations.
      + TControl.GetColorResolvingParent and
        TControl.GetRGBColorResolvingParent were added, simplifying the work
        to obtain the final color of the control while resolving clDefault
        and the ParentColor.
      + LCLIntf.GetTextExtentExPoint now has a good default implementation
        which works in any platform not providing a specific implementation.
        However, Widgetset specific implementation is better, when available.
      + TTabControl was reorganized. Now it has the correct class hierarchy
        and inherits from TCustomTabControl as it should.
  - New unit in the LCL:
      + lazdialogs.pas: adds non-native versions of various native dialogs,
        for example TLazOpenDialog, TLazSaveDialog, TLazSelectDirectoryDialog.
        It is used by widgetsets which either do not have a native dialog, or
        do not wish to use it because it is limited. These dialogs can also be
        used by user applications directly.
      + lazdeviceapis.pas: offers an interface to more hardware devices such
        as the accelerometer, GPS, etc. See LazDeviceAPIs
      + lazcanvas.pas: provides a TFPImageCanvas descendent implementing
        drawing in a LCL-compatible way, but 100% in Pascal.
      + lazregions.pas. LazRegions is a wholly Pascal implementation of
        regions for canvas clipping, event clipping, finding in which control
        of a region tree one an event should reach, for drawing polygons, etc.
      + customdrawncontrols.pas, customdrawndrawers.pas,
        customdrawn_common.pas, customdrawn_android.pas and
        customdrawn_winxp.pas: are the Lazarus Custom Drawn Controls -controls
        which imitate the standard LCL ones, but with the difference that they
        are non-native and support skinning.
  - New APIs added to the LCL to improve support of accessibility software
    such as screen readers.
* IDE changes:
  - Many improvments.
  - The detailed list of changes can be found here:
    http://wiki.lazarus.freepascal.org/New_IDE_features_since#v1.0_.282012-08-29.29
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_release_notes#IDE_Changes
* Debugger / Editor changes:
  - Added pascal sources and breakpoints to the disassembler
  - Added threads dialog.
* Components changes:
  - TAChart: many fixes and new features
  - CodeTool: support Delphi style generics and new syntax extensions.
  - AggPas: removed to honor free licencing. (Closes: Bug#708695)
[Bart Martens]
* New debian/watch file fixing issues with upstream RC release.
[Abou Al Montacir]
* Avoid changing files in .pc hidden directory, these are used by quilt for
  internal purpose and could lead to surprises during build.
[Paul Gevers]
* Updated get-orig-source target and it compinion script orig-tar.sh so that they
  repack the source file, allowing bug 708695 to be fixed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
                    -> $define macroname
38
38
    #define macroname constant
39
39
                    -> const macroname = constant
40
 
 
 
40
    simplifies conditional directives (e.g. deletes #ifdef nonexisting)
 
41
}
 
42
(*
41
43
  ToDos:
42
44
    add comments for skipped items
43
45
    insert auto generated types in front of current node
44
46
    c comments
45
47
    const char a; -> const a: char;
46
 
    simplify conditional directives (e.g. #ifdef)
47
48
    #define name value  ->  alias  (const, var, type, proc)
48
49
    more complex expressions and statements
49
 
}
 
50
 
 
51
A basic record type definition in C is
 
52
 
 
53
  struct structname { <struct_definition> };
 
54
 
 
55
The full name of this type is "struct structname". If you want to avoid typing the extra "struct" everywhere, you can create an alias for the type name using typedef:
 
56
 
 
57
  typedef struct structname aliasname;
 
58
 
 
59
You can combine both statements into one:
 
60
 
 
61
  typedef struct structname { <struct_definition> } aliasname;
 
62
 
 
63
You can also create multiple type aliases using a single typedef statement:
 
64
 
 
65
  typedef struct structname aliasname, anotheraliasname;
 
66
  typedef struct structname { <struct_definition> } aliasname, anotheraliasname; // same as line above
 
67
 
 
68
You can also create pointer type names at the same time:
 
69
 
 
70
  typedef struct structname aliasname, anotheraliasname, *pointeraliasname;
 
71
  typedef struct structname { <struct_definition> } aliasname, anotheraliasname, *pointeraliasname; // same as line above
 
72
  typedef struct structname aliasname, anotheraliasname; typedef aliasname *pointeraliasname; // same as line above
 
73
 
 
74
If you want to declare a variable whose type is a struct, it works the same as with any other C type: the type definition/name followed by the variable name (and in case of multiple variables, those are in turn separated by commas).
 
75
 
 
76
  struct structname structvar1, *structvar2;
 
77
  aliasname structvar1, *strucvar2; // same as line above
 
78
  aliasname structvar1; pointeraliasname structvar2; // same as line above
 
79
  struct structname { <struct_definition> } structvar1, *structvar2; // same as line above
 
80
 
 
81
It is also possible to define anonymous structs (without any identifier following the "struct" keyword). In that case it should either be used in a variable definition, or in a typedef declaration. Otherwise the statement has no meaning, since there is no way to refer to that struct definition later on:
 
82
 
 
83
struct { <struct_definition> }; // no meaning: does not define a variable, and no name to refer to the type again in later declarations; gcc will warn
 
84
struct { <struct_definition> } structvar; // same as "var structvar: record <struct_definition> end;"
 
85
typedef struct { <struct_definition> } aliasname; // same as *** above, except that you can only use "aliasname" to refer to this type, rather than also "struct structname"
 
86
 
 
87
*)
50
88
unit H2PasTool;
51
89
 
52
90
{$mode objfpc}{$H+}
190
228
    FSimplifyExpressions: boolean;
191
229
    FSourceName: string;
192
230
    FUndefines: TStringToStringTree;
 
231
    FUseExternal: boolean;
193
232
    // converting C nodes to H2P nodes
194
 
    procedure ConvertStruct(CNode: TCodeTreeNode; ParentNode: TH2PNode);
 
233
    function ConvertStruct(CNode: TCodeTreeNode; ParentNode: TH2PNode): TH2PNode;
195
234
    procedure ConvertVariable(CNode: TCodeTreeNode; ParentNode: TH2PNode);
196
 
    procedure ConvertEnumBlock(CNode: TCodeTreeNode; ParentNode: TH2PNode);
 
235
    function ConvertEnumBlock(CNode: TCodeTreeNode; ParentNode: TH2PNode): TH2PNode;
197
236
    procedure ConvertFunction(CNode: TCodeTreeNode; ParentNode: TH2PNode);
198
237
    procedure ConvertFuncParameter(CNode: TCodeTreeNode; ParentNode: TH2PNode);
199
238
    procedure ConvertTypedef(CNode: TCodeTreeNode; ParentNode: TH2PNode);
254
293
    
255
294
    function GetSimplePascalTypeOfCVar(CVarNode: TCodeTreeNode): string;
256
295
    function GetSimplePascalTypeOfCParameter(CParamNode: TCodeTreeNode): string;
 
296
    function GetSimplePascalTypeOfTypeDef(TypeDefNode: TCodeTreeNode): string;
257
297
    function GetSimplePascalResultTypeOfCFunction(CFuncNode: TCodeTreeNode): string;
258
298
    function ConvertSimpleCTypeToPascalType(CType: string;
259
299
                  UseSingleIdentifierAsDefault: boolean): string;
267
307
       PascalDesc: TCodeTreeNodeDesc; const PascalCode: string;
268
308
       ParentNode: TH2PNode; IsGlobal: boolean;
269
309
       InsertAsPreLast: boolean): TH2PNode;
270
 
    function GetH2PNodeForComplexType(CNode: TCodeTreeNode;
 
310
    function CreateH2PNodeForComplexType(CNode: TCodeTreeNode;
271
311
                               CreateIfNotExists: boolean;
272
312
                               InsertAsPreLast: boolean): TH2PNode;
273
313
    function CreatePascalNameFromCCode(const CCode: string;
289
329
    property PredefinedCTypes: TStringToStringTree read FPredefinedCTypes;
290
330
    property IgnoreCParts: TIgnoreCSourceParts read FIgnoreCParts write FIgnoreCParts;
291
331
    property SourceName: string read FSourceName write FSourceName;
 
332
    property UseExternal: boolean read FUseExternal write FUseExternal;// use external instad of public
292
333
 
293
334
    // directives
294
335
    property SimplifyExpressions: boolean read FSimplifyExpressions
316
357
    function MarkMacroAsRead(const MacroName: string;
317
358
                             Node: TH2PNode): TH2PMacroStats;// use Undefines instead
318
359
  end;
319
 
  
320
 
  
 
360
 
321
361
function DefaultPredefinedCTypes: TStringToStringTree;// types in unit ctypes
322
362
 
323
363
function CompareH2PNodePascalNames(Data1, Data2: Pointer): integer;
512
552
 
513
553
{ TH2PasTool }
514
554
 
515
 
procedure TH2PasTool.ConvertStruct(CNode: TCodeTreeNode; ParentNode: TH2PNode);
 
555
function TH2PasTool.ConvertStruct(CNode: TCodeTreeNode; ParentNode: TH2PNode
 
556
  ): TH2PNode;
516
557
var
517
558
  CurName: String;
518
 
  TypeH2PNode: TH2PNode;
519
559
  CurCName: String;
 
560
  ChildCNode: TCodeTreeNode;
520
561
begin
 
562
  Result:=nil;
521
563
  CurName:=CTool.ExtractStructName(CNode);
522
564
  if CurName='' then begin
523
565
    // this is an anonymous struct -> ignore
526
568
    // this struct has a name
527
569
    // create a type
528
570
    CurCName:=CurName;
529
 
    TypeH2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnRecordType,'',
 
571
    Result:=CreateH2PNode(CurName,CurCName,CNode,ctnRecordType,'',
530
572
                               nil,ParentNode=nil);
531
 
    DebugLn(['TH2PasTool.ConvertStruct ADDED ',TypeH2PNode.DescAsString(CTool)]);
 
573
    DebugLn(['TH2PasTool.ConvertStruct ADDED ',Result.DescAsString(CTool)]);
532
574
    // build recursively
533
 
    BuildH2PTree(TypeH2PNode);
 
575
    ChildCNode:=CNode.FirstChild;
 
576
    while (ChildCNode<>nil) do begin
 
577
      if (ChildCNode.Desc=ccnSubDefs) and (ChildCNode.FirstChild<>nil) then
 
578
        BuildH2PTree(Result,ChildCNode.FirstChild);
 
579
      ChildCNode:=ChildCNode.NextBrother;
 
580
    end;
534
581
  end;
535
582
end;
536
583
 
537
 
procedure TH2PasTool.ConvertVariable(CNode: TCodeTreeNode; ParentNode: TH2PNode
538
 
  );
 
584
procedure TH2PasTool.ConvertVariable(CNode: TCodeTreeNode; ParentNode: TH2PNode);
539
585
var
540
586
  CurName: String;
541
587
  TypeH2PNode: TH2PNode;
547
593
begin
548
594
  if (CNode.FirstChild<>nil) and (CNode.FirstChild.Desc=ccnUnion)
549
595
  then begin
550
 
    CurName:=CTool.ExtractVariableName(CNode);
 
596
    CurName:=CTool.ExtractDefinitionName(CNode);
551
597
    if (ParentNode<>nil) and (ParentNode.PascalDesc=ctnRecordType)
552
598
    then begin
553
599
      // create a pascal 'record case'
579
625
      DebugLn(['TH2PasTool.ConvertVariable SKIPPING union variable at ',CTool.CleanPosToStr(CNode.StartPos)]);
580
626
    end;
581
627
  end else begin
582
 
    CurName:=CTool.ExtractVariableName(CNode);
583
 
    CurType:=CTool.ExtractVariableType(CNode);
 
628
    CurName:=CTool.ExtractDefinitionName(CNode);
584
629
    SimpleType:=GetSimplePascalTypeOfCVar(CNode);
585
630
    if SimpleType='' then begin
586
631
      // this variable has a complex type
587
 
      TypeH2PNode:=GetH2PNodeForComplexType(CNode,true,ParentNode<>nil);
 
632
      TypeH2PNode:=CreateH2PNodeForComplexType(CNode,true,ParentNode<>nil);
588
633
      if TypeH2PNode<>nil then
589
634
        SimpleType:=TypeH2PNode.PascalName;
590
635
    end;
591
 
    if SimpleType<>'' then begin
592
 
      CurCName:=CurName;
593
 
      H2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnVarDefinition,SimpleType,
594
 
                             ParentNode,ParentNode=nil);
595
 
      DebugLn(['TH2PasTool.ConvertVariable CurName=',CurName,' ',H2PNode.PascalName]);
596
 
      DebugLn(['TH2PasTool.ConvertVariable added: ',H2PNode.DescAsString(CTool)]);
597
 
    end else begin
598
 
      DebugLn(['TH2PasTool.ConvertVariable SKIPPING Variable Name="',CurName,'" Type="',CurType,'"']);
 
636
    if CurName<>'' then begin
 
637
      if SimpleType<>'' then begin
 
638
        CurCName:=CurName;
 
639
        H2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnVarDefinition,SimpleType,
 
640
                               ParentNode,ParentNode=nil);
 
641
        DebugLn(['TH2PasTool.ConvertVariable CurName=',CurName,' ',H2PNode.PascalName]);
 
642
        DebugLn(['TH2PasTool.ConvertVariable added: ',H2PNode.DescAsString(CTool)]);
 
643
      end else begin
 
644
        CurType:=CTool.ExtractDefinitionType(CNode);
 
645
        DebugLn(['TH2PasTool.ConvertVariable SKIPPING Variable Name="',CurName,'" Type="',CurType,'"']);
 
646
      end;
599
647
    end;
600
648
  end;
601
649
end;
602
650
 
603
 
procedure TH2PasTool.ConvertEnumBlock(CNode: TCodeTreeNode;
604
 
  ParentNode: TH2PNode);
 
651
function TH2PasTool.ConvertEnumBlock(CNode: TCodeTreeNode; ParentNode: TH2PNode
 
652
  ): TH2PNode;
605
653
var
606
654
  CurName: String;
607
 
  TypeH2PNode: TH2PNode;
608
655
  CurValue: String;
609
656
  H2PNode: TH2PNode;
610
657
  CurCName: String;
613
660
  if CurName='' then begin
614
661
    // this is an anonymous enum block => auto generate a name
615
662
    CurName:=CreatePascalNameFromCCode(CTool.Src,CNode.StartPos,CNode.EndPos);
616
 
    TypeH2PNode:=CreateAutoGeneratedH2PNode(CurName,CNode,ctnEnumerationType,'',
 
663
    Result:=CreateAutoGeneratedH2PNode(CurName,CNode,ctnEnumerationType,'',
617
664
                                            nil,true,ParentNode<>nil);
618
665
  end else begin
619
666
    // this enum block has a name
620
667
    CurCName:=CurName;
621
 
    TypeH2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnEnumerationType,'',
 
668
    Result:=CreateH2PNode(CurName,CurCName,CNode,ctnEnumerationType,'',
622
669
                               nil,true);
623
670
  end;
624
 
  DebugLn(['TH2PasTool.ConvertEnumBlock added: ',TypeH2PNode.DescAsString(CTool)]);
 
671
  DebugLn(['TH2PasTool.ConvertEnumBlock added: ',Result.DescAsString(CTool)]);
625
672
 
626
673
  CNode:=CNode.FirstChild;
627
674
  while CNode<>nil do begin
630
677
      CurValue:=CTool.ExtractEnumIDValue(CNode);
631
678
      CurCName:=CurName;
632
679
      H2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnEnumIdentifier,CurValue,
633
 
                             TypeH2PNode,true);
 
680
                             Result,true);
634
681
      DebugLn(['TH2PasTool.ConvertEnumBlock added: ',H2PNode.DescAsString(CTool)]);
635
682
    end;
636
683
    CNode:=CNode.NextBrother;
637
684
  end;
638
685
end;
639
686
 
640
 
procedure TH2PasTool.ConvertFunction(CNode: TCodeTreeNode; ParentNode: TH2PNode
641
 
  );
 
687
procedure TH2PasTool.ConvertFunction(CNode: TCodeTreeNode; ParentNode: TH2PNode);
642
688
var
643
689
  CurName: String;
644
690
  CurType: String;
667
713
  end;
668
714
  if Ok and (SimpleType='') then begin
669
715
    // this function has a complex result type
670
 
    TypeH2PNode:=GetH2PNodeForComplexType(CNode,true,ParentNode<>nil);
 
716
    TypeH2PNode:=CreateH2PNodeForComplexType(CNode,true,ParentNode<>nil);
671
717
    if TypeH2PNode<>nil then begin
672
718
      SimpleType:=TypeH2PNode.PascalName;
673
719
    end else
725
771
  DebugLn(['TH2PasTool.ConvertFuncParameter Parameter: Name="',CurName,'" Type="',CurType,'" SimpleType="',SimpleType,'"']);
726
772
  if SimpleType='' then begin
727
773
    // this variable has a complex type
728
 
    TypeH2PNode:=GetH2PNodeForComplexType(CNode,true,true);
 
774
    TypeH2PNode:=CreateH2PNodeForComplexType(CNode,true,true);
729
775
    if TypeH2PNode<>nil then
730
776
      SimpleType:=TypeH2PNode.PascalName;
731
777
  end;
739
785
  end;
740
786
end;
741
787
 
742
 
procedure TH2PasTool.ConvertTypedef(CNode: TCodeTreeNode; ParentNode: TH2PNode
743
 
  );
 
788
procedure TH2PasTool.ConvertTypedef(CNode: TCodeTreeNode; ParentNode: TH2PNode);
744
789
var
745
790
  CurName: String;
746
791
  ChildNode: TCodeTreeNode;
752
797
  CurCName: String;
753
798
  CurValue: String;
754
799
  SubChildNode: TCodeTreeNode;
 
800
  TypeNode: TCodeTreeNode;
 
801
  SubTypeName: String;
755
802
begin
756
803
  if CNode.FirstChild=nil then begin
757
804
    exit;
760
807
  DebugLn(['TH2PasTool.ConvertTypedef Typedef name="',CurName,'"']);
761
808
  ChildNode:=CNode.FirstChild;
762
809
  case ChildNode.Desc of
763
 
  
764
 
  ccnVariable: // typedef variable
 
810
 
 
811
  ccnName: // typedef simple-type name
765
812
    begin
766
 
      CurName:=CTool.ExtractVariableName(ChildNode);
767
 
      CurType:=CTool.ExtractVariableType(ChildNode);
768
 
      SimpleType:=GetSimplePascalTypeOfCVar(ChildNode);
 
813
      SimpleType:=GetSimplePascalTypeOfTypeDef(CNode);
769
814
      if SimpleType='' then begin
770
815
        // this variable has a complex type
771
 
        TypeH2PNode:=GetH2PNodeForComplexType(ChildNode,true,ParentNode<>nil);
 
816
        TypeH2PNode:=CreateH2PNodeForComplexType(CNode,true,ParentNode<>nil);
772
817
        if TypeH2PNode<>nil then
773
818
          SimpleType:=TypeH2PNode.PascalName;
774
819
      end;
775
820
      if SimpleType<>'' then begin
776
821
        CurCName:=CurName;
777
822
        H2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnTypeDefinition,
778
 
                               SimpleType,nil,true);
 
823
                               SimpleType);
779
824
        DebugLn(['TH2PasTool.ConvertTypedef added: ',H2PNode.DescAsString(CTool)]);
780
825
      end else begin
 
826
        CurType:=CTool.ExtractDefinitionType(ChildNode);
781
827
        DebugLn(['TH2PasTool.ConvertTypedef SKIPPING Typedef Variable Name="',CurName,'" Type="',CurType,'"']);
782
828
      end;
783
829
    end;
784
830
 
785
831
  ccnStruct: // typedef struct
786
832
    begin
787
 
      ChildNode:=CNode.FirstChild.FirstChild;
788
 
      if (ChildNode<>nil)
789
 
      and (ChildNode.Desc=ccnStructAlias) then begin
790
 
        // this is a struct alias
791
 
        CurType:=GetIdentifier(@CTool.Src[ChildNode.StartPos]);
792
 
        CurCName:=CurName;
793
 
        TypeH2PNode:=CreateH2PNode(CurName,CurCName,CNode,
794
 
                                   ctnTypeDefinition,CurType);
 
833
      (* typedef struct a b;     =>  alias b = a
 
834
        typedef struct a {} b;  =>  a = record + alias b = a
 
835
        typedef struct {} b;    =>  b = record
 
836
      *)
 
837
      if (ChildNode.FirstChild.Desc=ccnTypeName)
 
838
      and (ChildNode.LastChild.Desc=ccnSubDefs) then begin
 
839
        // for example: typedef struct a {} b;
 
840
        // => create a new record type a and an alias b = a
 
841
        TypeNode:=ChildNode.FirstChild;
 
842
        SubChildNode:=ChildNode.LastChild;
 
843
        // create a new record
 
844
        CurCName:=GetIdentifier(@CTool.Src[TypeNode.StartPos]);
 
845
        SubTypeName:=CurCName;
 
846
        TypeH2PNode:=CreateH2PNode(SubTypeName,CurCName,TypeNode,ctnRecordType,'');
 
847
        DebugLn(['TH2PasTool.ConvertTypedef added record: ',TypeH2PNode.DescAsString(CTool)]);
 
848
        // build recursively
 
849
        BuildH2PTree(TypeH2PNode,SubChildNode.FirstChild);
 
850
        // create an alias  b=a
 
851
        CurCName:=CurName;
 
852
        TypeH2PNode:=CreateH2PNode(CurName,CurCName,CNode,
 
853
                                   ctnTypeDefinition,SubTypeName);
 
854
        DebugLn(['TH2PasTool.ConvertTypedef added type alias: ',TypeH2PNode.DescAsString(CTool)]);
 
855
      end else if ChildNode.FirstChild.Desc=ccnSubDefs then begin
 
856
        // for example: typedef struct {} b;  => b = record
 
857
        // => create a new record type b
 
858
        SubChildNode:=ChildNode.LastChild;
 
859
        CurCName:=CurName;
 
860
        TypeH2PNode:=CreateH2PNode(CurName,CurCName,ChildNode,ctnRecordType,'');
 
861
        DebugLn(['TH2PasTool.ConvertTypedef added record: ',TypeH2PNode.DescAsString(CTool)]);
 
862
        // build recursively
 
863
        BuildH2PTree(TypeH2PNode,SubChildNode.FirstChild);
 
864
      end else if (ChildNode.FirstChild.Desc=ccnTypeName)
 
865
      and (ChildNode.FirstChild.NextBrother=nil) then begin
 
866
        // for example: typedef struct a b;
 
867
        // => create a type alias b = a
 
868
        TypeNode:=ChildNode.FirstChild;
 
869
        SubTypeName:=GetIdentifier(@CTool.Src[TypeNode.StartPos]);
 
870
        CurCName:=CurName;
 
871
        TypeH2PNode:=CreateH2PNode(CurName,CurCName,CNode,
 
872
                                   ctnTypeDefinition,SubTypeName);
 
873
        DebugLn(['TH2PasTool.ConvertTypedef added type alias: ',TypeH2PNode.DescAsString(CTool)]);
795
874
      end else begin
796
 
        // this is a new struct
797
 
        CurCName:=CurName;
798
 
        TypeH2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnRecordType,'');
799
 
        DebugLn(['TH2PasTool.ConvertTypedef added record: ',TypeH2PNode.DescAsString(CTool)]);
800
 
        // build recursively
801
 
        if ChildNode<>nil then
802
 
          BuildH2PTree(TypeH2PNode,ChildNode);
 
875
        raise Exception.Create('TH2PasTool.ConvertTypedef inconsistency: unknown format of typedef struct');
803
876
      end;
804
877
    end;
805
878
 
811
884
      SimpleType:=GetSimplePascalResultTypeOfCFunction(ChildNode);
812
885
      if IsPointerToFunction and (SimpleType='') then begin
813
886
        // this function has a complex result type
814
 
        TypeH2PNode:=GetH2PNodeForComplexType(ChildNode,true,ParentNode<>nil);
 
887
        TypeH2PNode:=CreateH2PNodeForComplexType(ChildNode,true,ParentNode<>nil);
815
888
        if TypeH2PNode<>nil then
816
889
          SimpleType:=TypeH2PNode.PascalName;
817
890
      end;
857
930
  end;
858
931
end;
859
932
 
860
 
procedure TH2PasTool.ConvertDirective(CNode: TCodeTreeNode; ParentNode: TH2PNode
861
 
  );
 
933
procedure TH2PasTool.ConvertDirective(CNode: TCodeTreeNode; ParentNode: TH2PNode);
862
934
var
863
935
  Directive: String;
864
936
  H2PNode: TH2PNode;
1255
1327
  SetPasSection(ctnVarSection);
1256
1328
  PascalCode:=H2PNode.PascalCode+';';
1257
1329
  if H2PNode.CName<>'' then begin
1258
 
    PascalCode:=PascalCode+' cvar; public';
 
1330
    PascalCode:=PascalCode+' cvar; ';
 
1331
    if UseExternal then
 
1332
      PascalCode:=PascalCode+'external'
 
1333
    else
 
1334
      PascalCode:=PascalCode+'public';
1259
1335
    if H2PNode.PascalName<>H2PNode.CName then begin
1260
1336
      PascalCode:=PascalCode+' name '''+H2PNode.CName+'''';
1261
1337
    end;
1985
2061
  CNode: TCodeTreeNode;
1986
2062
  NextCNode: TCodeTreeNode;
1987
2063
begin
1988
 
  //DebugLn(['TH2PasTool.BuildH2PTree ParentNode=',ParentNode.DescAsString(CTool)]);
 
2064
  if ParentNode<>nil then
 
2065
    DebugLn(['TH2PasTool.BuildH2PTree ParentNode=',ParentNode.DescAsString(CTool)])
 
2066
  else
 
2067
    debugln(['TH2PasTool.BuildH2PTree START']);
1989
2068
  if ParentNode<>nil then begin
1990
2069
    if StartNode=nil then
1991
2070
      StartNode:=ParentNode.CNode.FirstChild;
2000
2079
  end;
2001
2080
  CNode:=StartNode;
2002
2081
  while CNode<>nil do begin
2003
 
    //DebugLn(['TH2PasTool.BuildH2PTree Current ParentNode=',ParentNode.DescAsString(CTool),' CNode=',CCNodeDescAsString(CNode.Desc)]);
 
2082
    if ParentNode<>nil then
 
2083
      DebugLn(['TH2PasTool.BuildH2PTree Current ParentNode=',ParentNode.DescAsString(CTool),' CNode=',CCNodeDescAsString(CNode.Desc)])
 
2084
    else
 
2085
      DebugLn(['TH2PasTool.BuildH2PTree Current ParentNode=nil CNode=',CCNodeDescAsString(CNode.Desc)]);
2004
2086
    NextCNode:=CNode.NextSkipChilds;
2005
2087
    case CNode.Desc of
2006
 
    ccnRoot, ccnExtern:
 
2088
    ccnRoot, ccnExternBlock:
2007
2089
      NextCNode:=CNode.Next;
2008
2090
      
2009
2091
    ccnTypedef:
2010
2092
      ConvertTypedef(CNode,ParentNode);
2011
2093
 
2012
 
    ccnVariable:
 
2094
    ccnDefinition:
2013
2095
      ConvertVariable(CNode,ParentNode);
2014
2096
 
2015
2097
    ccnFunction:
2223
2305
 
2224
2306
function TH2PasTool.GetSimplePascalTypeOfCVar(CVarNode: TCodeTreeNode): string;
2225
2307
begin
2226
 
  Result:=CTool.ExtractVariableType(CVarNode);
 
2308
  Result:=CTool.ExtractDefinitionType(CVarNode);
2227
2309
  if Result='' then exit;
2228
2310
  Result:=ConvertSimpleCTypeToPascalType(Result,true);
2229
2311
end;
2239
2321
    Result:=ConvertSimpleCTypeToPascalType(Result,true);
2240
2322
end;
2241
2323
 
 
2324
function TH2PasTool.GetSimplePascalTypeOfTypeDef(TypeDefNode: TCodeTreeNode
 
2325
  ): string;
 
2326
begin
 
2327
  Result:=CTool.ExtractTypeDefType(TypeDefNode,false);
 
2328
  if Result='' then exit;
 
2329
  Result:=ConvertSimpleCTypeToPascalType(Result,true);
 
2330
end;
 
2331
 
2242
2332
function TH2PasTool.GetSimplePascalResultTypeOfCFunction(
2243
2333
  CFuncNode: TCodeTreeNode): string;
2244
2334
begin
2282
2372
    ReadRawNextCAtom(CType,p,CurAtomStart);
2283
2373
    if CurAtomStart>length(CType) then break;
2284
2374
    //DebugLn(['TH2PasTool.ConvertSimpleCTypeToPascalType Atom=',copy(CType,CurAtomStart,p-CurAtomStart)]);
2285
 
    if (not TestIsAtomAndRemove('const'))
2286
 
    and (not TestIsAtomAndRemove('struct')) then ;
 
2375
    TestIsAtomAndRemove('const');
2287
2376
  until false;
2288
2377
  // seach in predefined ctypes
2289
2378
  Result:=PredefinedCTypes[CType];
2359
2448
    inc(i);
2360
2449
end;
2361
2450
 
2362
 
function TH2PasTool.GetH2PNodeForComplexType(CNode: TCodeTreeNode;
 
2451
function TH2PasTool.CreateH2PNodeForComplexType(CNode: TCodeTreeNode;
2363
2452
  CreateIfNotExists: boolean; InsertAsPreLast: boolean): TH2PNode;
2364
2453
var
2365
2454
  CCode: String;
2378
2467
  ConstantNumber: int64;
2379
2468
  BracketOpenPos: LongInt;
2380
2469
  NeedH2PNode: Boolean;
 
2470
  SubCNode: TCodeTreeNode;
2381
2471
begin
2382
2472
  Result:=nil;
2383
 
  if (CNode.Desc=ccnVariable)
2384
 
  and (CNode.FirstChild<>nil)
2385
 
  and (CNode.FirstChild.Desc=ccnUnion) then begin
2386
 
    // ToDo: union
2387
 
  end else begin
2388
 
    SubH2PNode:=nil;
2389
 
    if CNode.Desc=ccnVariable then
2390
 
      CCode:=CTool.ExtractVariableType(CNode)
2391
 
    else if CNode.Desc=ccnFunction then
2392
 
      CCode:=CTool.ExtractFunctionResultType(CNode)
2393
 
    else if CNode.Desc=ccnFuncParameter then
2394
 
      CCode:=CTool.ExtractParameterType(CNode)
2395
 
    else
2396
 
      exit;
2397
 
      
2398
 
    DebugLn(['TH2PasTool.GetH2PNodeForComplexType CCode="',CCode,'"']);
2399
 
    { int[][3]  -> array of array[0..2] of cint
2400
 
      char**    -> PPchar
2401
 
      int *[15] -> array[0..14] of pcint
2402
 
      
2403
 
    }
2404
 
    // read identifiers
2405
 
    p:=1;
2406
 
    BaseCType:='';
2407
 
    repeat
2408
 
      ReadRawNextCAtom(CCode,p,AtomStart);
2409
 
      if AtomStart>length(CCode) then break;
2410
 
      if IsIdentStartChar[CCode[AtomStart]] then begin
2411
 
        CurAtom:=copy(CCode,AtomStart,p-AtomStart);
2412
 
        if BaseCType<>'' then
2413
 
          BaseCType:=BaseCType+' ';
2414
 
        BaseCType:=BaseCType+CurAtom;
2415
 
      end else
2416
 
        break;
2417
 
    until false;
2418
 
    if BaseCType='' then begin
2419
 
      DebugLn(['TH2PasTool.GetH2PNodeForComplexType no base type in c declaration: CCode="',dbgstr(CCode),'"']);
2420
 
      exit;
2421
 
    end;
2422
 
    BasePascalType:=ConvertSimpleCTypeToPascalType(BaseCType,true);
2423
 
    if (BasePascalType='') then begin
2424
 
      DebugLn(['TH2PasTool.GetH2PNodeForComplexType unknown c type: "',BaseCType,'"']);
2425
 
      exit;
2426
 
    end;
2427
 
    DebugLn(['TH2PasTool.GetH2PNodeForComplexType BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']);
2428
 
    
2429
 
    // read pointer(s)
2430
 
    while (AtomStart<=length(CCode)) do begin
2431
 
      CurAtom:=copy(CCode,AtomStart,p-AtomStart);
2432
 
      if (CurAtom='*') then begin
2433
 
        BaseCType:=BaseCType+'*';
2434
 
        NewBasePascalType:=ConvertSimpleCTypeToPascalType(BaseCType,true);
2435
 
        if NewBasePascalType<>'' then begin
2436
 
          // for this pointer type exists already a predefined simple type
2437
 
        end else begin
2438
 
          // a new pointer type is needed
2439
 
          NewBasePascalType:='P'+BasePascalType;
2440
 
          SubH2PNode:=CreateAutoGeneratedH2PNode(NewBasePascalType,nil,
2441
 
                                    ctnTypeDefinition,'^'+BasePascalType,
2442
 
                                    nil,true,InsertAsPreLast);
2443
 
          DebugLn(['TH2PasTool.GetH2PNodeForComplexType added new pointer type: ',SubH2PNode.DescAsString(CTool)]);
2444
 
          NewBasePascalType:=SubH2PNode.PascalName;
2445
 
        end;
2446
 
        BasePascalType:=NewBasePascalType;
2447
 
        DebugLn(['TH2PasTool.GetH2PNodeForComplexType using pointer type: BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']);
2448
 
      end else if (CurAtom='const') then begin
2449
 
        // skip 'const'
2450
 
      end else begin
2451
 
        break;
2452
 
      end;
2453
 
      ReadRawNextCAtom(CCode,p,AtomStart);
2454
 
    end;
2455
 
    
2456
 
    PascalName:=BasePascalType;
2457
 
    PascalCode:=PascalName;
2458
 
    
2459
 
    // read arrays
2460
 
    NeedH2PNode:=false;
2461
 
    while (AtomStart<=length(CCode)) do begin
2462
 
      CurAtom:=copy(CCode,AtomStart,p-AtomStart);
2463
 
      if CurAtom='[' then begin
2464
 
        NeedH2PNode:=true;
2465
 
        BracketOpenPos:=AtomStart;
2466
 
        ReadRawNextCAtom(CCode,p,AtomStart);
2467
 
        if AtomStart>length(CCode) then begin
2468
 
          DebugLn(['TH2PasTool.GetH2PNodeForComplexType untranslatable (missing ]): CCode="',dbgstr(CCode),'"']);
2469
 
          exit;
2470
 
        end;
2471
 
        CurAtom:=copy(CCode,AtomStart,p-AtomStart);
2472
 
        if CurAtom=']' then begin
2473
 
          // [] -> open array
2474
 
          PascalCode:='array of '+PascalCode;
2475
 
          PascalName:='ArrayOf'+PascalName;
2476
 
          //DebugLn(['TH2PasTool.GetTypeForVarType open array: ',PascalCode]);
2477
 
        end else begin
2478
 
          // [constant] -> array[0..constant-1]
2479
 
          ConstantStartPos:=AtomStart;
2480
 
          p:=BracketOpenPos;
2481
 
          ReadTilCBracketClose(CCode,p);
2482
 
          ConstantEndPos:=p-1;
2483
 
          ConstantCode:=copy(CCode,ConstantStartPos,ConstantEndPos-ConstantStartPos);
2484
 
          //DebugLn(['TH2PasTool.GetTypeForVarType ConstantCode="',ConstantCode,'"']);
2485
 
          if CConstantToInt64(ConstantCode,ConstantNumber) then begin
2486
 
            if ConstantNumber>0 then
2487
 
              dec(ConstantNumber)
2488
 
            else
2489
 
              ConstantNumber:=0;
2490
 
            ConstantCode:=IntToStr(ConstantNumber);
2491
 
          end else begin
2492
 
            ConstantCode:=ConstantCode+'-1';
2493
 
          end;
2494
 
          PascalCode:='array[0..'+ConstantCode+'] of '+PascalCode;
2495
 
          PascalName:='Array0to'+CreatePascalNameFromCCode(ConstantCode)+'Of'+PascalName;
2496
 
          //DebugLn(['TH2PasTool.GetTypeForVarType fixed array: ',PascalCode]);
2497
 
        end;
2498
 
      end else
2499
 
        break;
2500
 
      ReadRawNextCAtom(CCode,p,AtomStart);
2501
 
    end;
2502
 
    if NeedH2PNode then begin
2503
 
      PascalName:='T'+PascalName;
2504
 
      PascalName:=copy(PascalName,1,DefaultMaxPascalIdentLen);
2505
 
      SubH2PNode:=CreateAutoGeneratedH2PNode(PascalName,nil,ctnTypeDefinition,
2506
 
        PascalCode,nil,true,InsertAsPreLast);
2507
 
    end;
2508
 
    
2509
 
    // check if the whole declaration was translated
2510
 
    if AtomStart<=length(CCode) then begin
2511
 
      // unknown C type
2512
 
      DebugLn(['TH2PasTool.GetTypeForVarType untranslatable: CCode="',dbgstr(CCode),'"']);
2513
 
      exit;
2514
 
    end;
2515
 
    
2516
 
    DebugLn(['TH2PasTool.GetTypeForVarType CCode="',dbgstr(CCode),'" PascalName="',PascalName,'"']);
2517
 
    Result:=SubH2PNode;
2518
 
  end;
 
2473
  if (CNode.Desc=ccnDefinition) and (CNode.FirstChild<>nil) then begin
 
2474
    SubCNode:=CNode.FirstChild;
 
2475
    if SubCNode.Desc=ccnName then
 
2476
      SubCNode:=SubCNode.NextBrother;
 
2477
    if (SubCNode<>nil) then begin
 
2478
      if (SubCNode.Desc=ccnEnumBlock) then begin
 
2479
        Result:=ConvertEnumBlock(SubCNode,nil);
 
2480
        exit;
 
2481
      end;
 
2482
      if (SubCNode.Desc=ccnStruct) then begin
 
2483
        Result:=ConvertStruct(SubCNode,nil);
 
2484
        exit;
 
2485
      end;
 
2486
      if SubCNode.Desc<>ccnConstant then begin
 
2487
        debugln(['TH2PasTool.GetH2PNodeForComplexType TODO: ',CCNodeDescAsString(CNode.Desc),' of ',CCNodeDescAsString(SubCNode.Desc)]);
 
2488
        exit;
 
2489
      end;
 
2490
    end;
 
2491
  end;
 
2492
 
 
2493
  SubH2PNode:=nil;
 
2494
  debugln(['TH2PasTool.GetH2PNodeForComplexType CNode=',CCNodeDescAsString(CNode.Desc)]);
 
2495
  if CNode.Desc=ccnDefinition then
 
2496
    CCode:=CTool.ExtractDefinitionType(CNode)
 
2497
  else if CNode.Desc=ccnFunction then
 
2498
    CCode:=CTool.ExtractFunctionResultType(CNode)
 
2499
  else if CNode.Desc=ccnFuncParameter then
 
2500
    CCode:=CTool.ExtractParameterType(CNode)
 
2501
  else if CNode.Desc=ccnTypedef then
 
2502
    CCode:=CTool.ExtractTypeDefType(CNode)
 
2503
  else begin
 
2504
    debugln(['TH2PasTool.GetH2PNodeForComplexType not supported: CNode=',CCNodeDescAsString(CNode.Desc)]);
 
2505
    exit;
 
2506
  end;
 
2507
 
 
2508
  DebugLn(['TH2PasTool.GetH2PNodeForComplexType CCode="',CCode,'"']);
 
2509
  { int[][3]  -> array of array[0..2] of cint
 
2510
    char**    -> PPchar
 
2511
    int *[15] -> array[0..14] of pcint
 
2512
 
 
2513
  }
 
2514
  // read identifiers
 
2515
  p:=1;
 
2516
  BaseCType:='';
 
2517
  repeat
 
2518
    ReadRawNextCAtom(CCode,p,AtomStart);
 
2519
    if AtomStart>length(CCode) then break;
 
2520
    if IsIdentStartChar[CCode[AtomStart]] then begin
 
2521
      CurAtom:=copy(CCode,AtomStart,p-AtomStart);
 
2522
      if BaseCType<>'' then
 
2523
        BaseCType:=BaseCType+' ';
 
2524
      BaseCType:=BaseCType+CurAtom;
 
2525
    end else
 
2526
      break;
 
2527
  until false;
 
2528
  if BaseCType='' then begin
 
2529
    DebugLn(['TH2PasTool.GetH2PNodeForComplexType no base type in c declaration: CCode="',dbgstr(CCode),'"']);
 
2530
    exit;
 
2531
  end;
 
2532
  BasePascalType:=ConvertSimpleCTypeToPascalType(BaseCType,true);
 
2533
  if (BasePascalType='') then begin
 
2534
    DebugLn(['TH2PasTool.GetH2PNodeForComplexType unknown c type: "',BaseCType,'"']);
 
2535
    exit;
 
2536
  end;
 
2537
  DebugLn(['TH2PasTool.GetH2PNodeForComplexType BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']);
 
2538
 
 
2539
  // read pointer(s)
 
2540
  while (AtomStart<=length(CCode)) do begin
 
2541
    CurAtom:=copy(CCode,AtomStart,p-AtomStart);
 
2542
    if (CurAtom='*') then begin
 
2543
      BaseCType:=BaseCType+'*';
 
2544
      NewBasePascalType:=ConvertSimpleCTypeToPascalType(BaseCType,true);
 
2545
      if NewBasePascalType<>'' then begin
 
2546
        // for this pointer type exists already a predefined simple type
 
2547
      end else begin
 
2548
        // a new pointer type is needed
 
2549
        NewBasePascalType:='P'+BasePascalType;
 
2550
        SubH2PNode:=CreateAutoGeneratedH2PNode(NewBasePascalType,nil,
 
2551
                                  ctnTypeDefinition,'^'+BasePascalType,
 
2552
                                  nil,true,InsertAsPreLast);
 
2553
        DebugLn(['TH2PasTool.GetH2PNodeForComplexType added new pointer type: ',SubH2PNode.DescAsString(CTool)]);
 
2554
        NewBasePascalType:=SubH2PNode.PascalName;
 
2555
      end;
 
2556
      BasePascalType:=NewBasePascalType;
 
2557
      DebugLn(['TH2PasTool.GetH2PNodeForComplexType using pointer type: BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']);
 
2558
    end else if (CurAtom='const') then begin
 
2559
      // skip 'const'
 
2560
    end else begin
 
2561
      break;
 
2562
    end;
 
2563
    ReadRawNextCAtom(CCode,p,AtomStart);
 
2564
  end;
 
2565
 
 
2566
  PascalName:=BasePascalType;
 
2567
  PascalCode:=PascalName;
 
2568
 
 
2569
  // read arrays
 
2570
  NeedH2PNode:=false;
 
2571
  while (AtomStart<=length(CCode)) do begin
 
2572
    CurAtom:=copy(CCode,AtomStart,p-AtomStart);
 
2573
    if CurAtom='[' then begin
 
2574
      NeedH2PNode:=true;
 
2575
      BracketOpenPos:=AtomStart;
 
2576
      ReadRawNextCAtom(CCode,p,AtomStart);
 
2577
      if AtomStart>length(CCode) then begin
 
2578
        DebugLn(['TH2PasTool.GetH2PNodeForComplexType untranslatable (missing ]): CCode="',dbgstr(CCode),'"']);
 
2579
        exit;
 
2580
      end;
 
2581
      CurAtom:=copy(CCode,AtomStart,p-AtomStart);
 
2582
      if CurAtom=']' then begin
 
2583
        // [] -> open array
 
2584
        PascalCode:='array of '+PascalCode;
 
2585
        PascalName:='ArrayOf'+PascalName;
 
2586
        //DebugLn(['TH2PasTool.GetTypeForVarType open array: ',PascalCode]);
 
2587
      end else begin
 
2588
        // [constant] -> array[0..constant-1]
 
2589
        ConstantStartPos:=AtomStart;
 
2590
        p:=BracketOpenPos;
 
2591
        ReadTilCBracketClose(CCode,p);
 
2592
        ConstantEndPos:=p-1;
 
2593
        ConstantCode:=copy(CCode,ConstantStartPos,ConstantEndPos-ConstantStartPos);
 
2594
        //DebugLn(['TH2PasTool.GetTypeForVarType ConstantCode="',ConstantCode,'"']);
 
2595
        if CConstantToInt64(ConstantCode,ConstantNumber) then begin
 
2596
          if ConstantNumber>0 then
 
2597
            dec(ConstantNumber)
 
2598
          else
 
2599
            ConstantNumber:=0;
 
2600
          ConstantCode:=IntToStr(ConstantNumber);
 
2601
        end else begin
 
2602
          ConstantCode:=ConstantCode+'-1';
 
2603
        end;
 
2604
        PascalCode:='array[0..'+ConstantCode+'] of '+PascalCode;
 
2605
        PascalName:='Array0to'+CreatePascalNameFromCCode(ConstantCode)+'Of'+PascalName;
 
2606
        //DebugLn(['TH2PasTool.GetTypeForVarType fixed array: ',PascalCode]);
 
2607
      end;
 
2608
    end else
 
2609
      break;
 
2610
    ReadRawNextCAtom(CCode,p,AtomStart);
 
2611
  end;
 
2612
  if NeedH2PNode then begin
 
2613
    PascalName:='T'+PascalName;
 
2614
    PascalName:=copy(PascalName,1,DefaultMaxPascalIdentLen);
 
2615
    SubH2PNode:=CreateAutoGeneratedH2PNode(PascalName,nil,ctnTypeDefinition,
 
2616
      PascalCode,nil,true,InsertAsPreLast);
 
2617
  end;
 
2618
 
 
2619
  // check if the whole declaration was translated
 
2620
  if AtomStart<=length(CCode) then begin
 
2621
    // unknown C type
 
2622
    DebugLn(['TH2PasTool.GetTypeForVarType untranslatable: CCode="',dbgstr(CCode),'"']);
 
2623
    exit;
 
2624
  end;
 
2625
 
 
2626
  DebugLn(['TH2PasTool.GetTypeForVarType CCode="',dbgstr(CCode),'" PascalName="',PascalName,'"']);
 
2627
  Result:=SubH2PNode;
2519
2628
end;
2520
2629
 
2521
2630
function TH2PasTool.CreatePascalNameFromCCode(const CCode: string;
2634
2743
  end else if (Tree.Root=nil) then begin
2635
2744
    DebugLn(['TH2PasTool.WriteH2PNodeReport Tree.Root=nil']);
2636
2745
  end else begin
 
2746
    //debugln(['TH2PasTool.WriteH2PNodeReport ']);
2637
2747
    Node:=Tree.Root;
2638
2748
    while Node<>nil do begin
2639
2749
      DebugLn([GetIndentStr(Node.GetLevel*2),Node.DescAsString(CTool)]);
2669
2779
  FIgnoreCParts:=[icspInclude];
2670
2780
  FDefines:=TStringToStringTree.Create(true);
2671
2781
  FUndefines:=TStringToStringTree.Create(true);
 
2782
  UseExternal:=true;
2672
2783
  AddCommonCDefines;
2673
2784
end;
2674
2785