37
37
-> $define macroname
38
38
#define macroname constant
39
39
-> const macroname = constant
40
simplifies conditional directives (e.g. deletes #ifdef nonexisting)
42
44
add comments for skipped items
43
45
insert auto generated types in front of current node
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
51
A basic record type definition in C is
53
struct structname { <struct_definition> };
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:
57
typedef struct structname aliasname;
59
You can combine both statements into one:
61
typedef struct structname { <struct_definition> } aliasname;
63
You can also create multiple type aliases using a single typedef statement:
65
typedef struct structname aliasname, anotheraliasname;
66
typedef struct structname { <struct_definition> } aliasname, anotheraliasname; // same as line above
68
You can also create pointer type names at the same time:
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
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).
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
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:
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"
52
90
{$mode objfpc}{$H+}
760
807
DebugLn(['TH2PasTool.ConvertTypedef Typedef name="',CurName,'"']);
761
808
ChildNode:=CNode.FirstChild;
762
809
case ChildNode.Desc of
764
ccnVariable: // typedef variable
811
ccnName: // typedef simple-type name
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;
775
820
if SimpleType<>'' then begin
776
821
CurCName:=CurName;
777
822
H2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnTypeDefinition,
778
SimpleType,nil,true);
779
824
DebugLn(['TH2PasTool.ConvertTypedef added: ',H2PNode.DescAsString(CTool)]);
826
CurType:=CTool.ExtractDefinitionType(ChildNode);
781
827
DebugLn(['TH2PasTool.ConvertTypedef SKIPPING Typedef Variable Name="',CurName,'" Type="',CurType,'"']);
785
831
ccnStruct: // typedef struct
787
ChildNode:=CNode.FirstChild.FirstChild;
789
and (ChildNode.Desc=ccnStructAlias) then begin
790
// this is a struct alias
791
CurType:=GetIdentifier(@CTool.Src[ChildNode.StartPos]);
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
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)]);
849
BuildH2PTree(TypeH2PNode,SubChildNode.FirstChild);
850
// create an alias b=a
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;
860
TypeH2PNode:=CreateH2PNode(CurName,CurCName,ChildNode,ctnRecordType,'');
861
DebugLn(['TH2PasTool.ConvertTypedef added record: ',TypeH2PNode.DescAsString(CTool)]);
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]);
871
TypeH2PNode:=CreateH2PNode(CurName,CurCName,CNode,
872
ctnTypeDefinition,SubTypeName);
873
DebugLn(['TH2PasTool.ConvertTypedef added type alias: ',TypeH2PNode.DescAsString(CTool)]);
796
// this is a new struct
798
TypeH2PNode:=CreateH2PNode(CurName,CurCName,CNode,ctnRecordType,'');
799
DebugLn(['TH2PasTool.ConvertTypedef added record: ',TypeH2PNode.DescAsString(CTool)]);
801
if ChildNode<>nil then
802
BuildH2PTree(TypeH2PNode,ChildNode);
875
raise Exception.Create('TH2PasTool.ConvertTypedef inconsistency: unknown format of typedef struct');
2378
2467
ConstantNumber: int64;
2379
2468
BracketOpenPos: LongInt;
2380
2469
NeedH2PNode: Boolean;
2470
SubCNode: TCodeTreeNode;
2383
if (CNode.Desc=ccnVariable)
2384
and (CNode.FirstChild<>nil)
2385
and (CNode.FirstChild.Desc=ccnUnion) then begin
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)
2398
DebugLn(['TH2PasTool.GetH2PNodeForComplexType CCode="',CCode,'"']);
2399
{ int[][3] -> array of array[0..2] of cint
2401
int *[15] -> array[0..14] of pcint
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;
2418
if BaseCType='' then begin
2419
DebugLn(['TH2PasTool.GetH2PNodeForComplexType no base type in c declaration: CCode="',dbgstr(CCode),'"']);
2422
BasePascalType:=ConvertSimpleCTypeToPascalType(BaseCType,true);
2423
if (BasePascalType='') then begin
2424
DebugLn(['TH2PasTool.GetH2PNodeForComplexType unknown c type: "',BaseCType,'"']);
2427
DebugLn(['TH2PasTool.GetH2PNodeForComplexType BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']);
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
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;
2446
BasePascalType:=NewBasePascalType;
2447
DebugLn(['TH2PasTool.GetH2PNodeForComplexType using pointer type: BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']);
2448
end else if (CurAtom='const') then begin
2453
ReadRawNextCAtom(CCode,p,AtomStart);
2456
PascalName:=BasePascalType;
2457
PascalCode:=PascalName;
2461
while (AtomStart<=length(CCode)) do begin
2462
CurAtom:=copy(CCode,AtomStart,p-AtomStart);
2463
if CurAtom='[' then begin
2465
BracketOpenPos:=AtomStart;
2466
ReadRawNextCAtom(CCode,p,AtomStart);
2467
if AtomStart>length(CCode) then begin
2468
DebugLn(['TH2PasTool.GetH2PNodeForComplexType untranslatable (missing ]): CCode="',dbgstr(CCode),'"']);
2471
CurAtom:=copy(CCode,AtomStart,p-AtomStart);
2472
if CurAtom=']' then begin
2474
PascalCode:='array of '+PascalCode;
2475
PascalName:='ArrayOf'+PascalName;
2476
//DebugLn(['TH2PasTool.GetTypeForVarType open array: ',PascalCode]);
2478
// [constant] -> array[0..constant-1]
2479
ConstantStartPos:=AtomStart;
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
2490
ConstantCode:=IntToStr(ConstantNumber);
2492
ConstantCode:=ConstantCode+'-1';
2494
PascalCode:='array[0..'+ConstantCode+'] of '+PascalCode;
2495
PascalName:='Array0to'+CreatePascalNameFromCCode(ConstantCode)+'Of'+PascalName;
2496
//DebugLn(['TH2PasTool.GetTypeForVarType fixed array: ',PascalCode]);
2500
ReadRawNextCAtom(CCode,p,AtomStart);
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);
2509
// check if the whole declaration was translated
2510
if AtomStart<=length(CCode) then begin
2512
DebugLn(['TH2PasTool.GetTypeForVarType untranslatable: CCode="',dbgstr(CCode),'"']);
2516
DebugLn(['TH2PasTool.GetTypeForVarType CCode="',dbgstr(CCode),'" PascalName="',PascalName,'"']);
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);
2482
if (SubCNode.Desc=ccnStruct) then begin
2483
Result:=ConvertStruct(SubCNode,nil);
2486
if SubCNode.Desc<>ccnConstant then begin
2487
debugln(['TH2PasTool.GetH2PNodeForComplexType TODO: ',CCNodeDescAsString(CNode.Desc),' of ',CCNodeDescAsString(SubCNode.Desc)]);
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)
2504
debugln(['TH2PasTool.GetH2PNodeForComplexType not supported: CNode=',CCNodeDescAsString(CNode.Desc)]);
2508
DebugLn(['TH2PasTool.GetH2PNodeForComplexType CCode="',CCode,'"']);
2509
{ int[][3] -> array of array[0..2] of cint
2511
int *[15] -> array[0..14] of pcint
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;
2528
if BaseCType='' then begin
2529
DebugLn(['TH2PasTool.GetH2PNodeForComplexType no base type in c declaration: CCode="',dbgstr(CCode),'"']);
2532
BasePascalType:=ConvertSimpleCTypeToPascalType(BaseCType,true);
2533
if (BasePascalType='') then begin
2534
DebugLn(['TH2PasTool.GetH2PNodeForComplexType unknown c type: "',BaseCType,'"']);
2537
DebugLn(['TH2PasTool.GetH2PNodeForComplexType BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']);
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
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;
2556
BasePascalType:=NewBasePascalType;
2557
DebugLn(['TH2PasTool.GetH2PNodeForComplexType using pointer type: BasePascalType="',BasePascalType,'" BaseCType="',BaseCType,'"']);
2558
end else if (CurAtom='const') then begin
2563
ReadRawNextCAtom(CCode,p,AtomStart);
2566
PascalName:=BasePascalType;
2567
PascalCode:=PascalName;
2571
while (AtomStart<=length(CCode)) do begin
2572
CurAtom:=copy(CCode,AtomStart,p-AtomStart);
2573
if CurAtom='[' then begin
2575
BracketOpenPos:=AtomStart;
2576
ReadRawNextCAtom(CCode,p,AtomStart);
2577
if AtomStart>length(CCode) then begin
2578
DebugLn(['TH2PasTool.GetH2PNodeForComplexType untranslatable (missing ]): CCode="',dbgstr(CCode),'"']);
2581
CurAtom:=copy(CCode,AtomStart,p-AtomStart);
2582
if CurAtom=']' then begin
2584
PascalCode:='array of '+PascalCode;
2585
PascalName:='ArrayOf'+PascalName;
2586
//DebugLn(['TH2PasTool.GetTypeForVarType open array: ',PascalCode]);
2588
// [constant] -> array[0..constant-1]
2589
ConstantStartPos:=AtomStart;
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
2600
ConstantCode:=IntToStr(ConstantNumber);
2602
ConstantCode:=ConstantCode+'-1';
2604
PascalCode:='array[0..'+ConstantCode+'] of '+PascalCode;
2605
PascalName:='Array0to'+CreatePascalNameFromCCode(ConstantCode)+'Of'+PascalName;
2606
//DebugLn(['TH2PasTool.GetTypeForVarType fixed array: ',PascalCode]);
2610
ReadRawNextCAtom(CCode,p,AtomStart);
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);
2619
// check if the whole declaration was translated
2620
if AtomStart<=length(CCode) then begin
2622
DebugLn(['TH2PasTool.GetTypeForVarType untranslatable: CCode="',dbgstr(CCode),'"']);
2626
DebugLn(['TH2PasTool.GetTypeForVarType CCode="',dbgstr(CCode),'" PascalName="',PascalName,'"']);
2521
2630
function TH2PasTool.CreatePascalNameFromCCode(const CCode: string;