(* Copyright (c) 1998-2000 by Florian Klaempfl This program 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 program 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ****************************************************************************) unit h2pbase; {$modeswitch result} {$message TODO: warning Unit types is only needed due to issue 7910} interface uses SysUtils, classes, h2poptions,scan,h2pconst,h2plexlib,h2pyacclib, scanbase,h2pout,h2ptypes; type YYSTYPE = presobject; var s,TN,PN : String; (* $ define yydebug compile with -dYYDEBUG to get debugging info *) procedure yymsg(const msg : string); function ellipsisarg : presobject; function HandleErrorDecl(e1,e2 : presobject) : presobject; Function HandleDeclarationStatement(decl,type_spec,modifier_spec,decllist_spec,block_spec : presobject) : presobject; Function HandleDeclarationSysTrap(decl,type_spec,modifier_spec,decllist_spec,sys_trap : presobject) : presobject; function HandleSpecialType(aType: presobject) : presobject; function HandleTypedef(type_spec,dec_modifier,declarator,arg_decl_list: presobject) : presobject; function HandleTypedefList(type_spec,dec_modifier,declarator_list: presobject) : presobject; function HandleStructDef(dname1,dname2 : presobject) : presobject; function HandleSimpleTypeDef(tname : presobject) : presobject; function HandleDeclarator(aTyp : ttyp; aright: presobject): presobject; function HandleDeclarator2(aTyp : ttyp; aleft,aright: presobject): presobject; function HandleSizedDeclarator(psym,psize : presobject) : presobject; function HandleSizedPointerDeclarator(psym,psize : presobject) : presobject; function HandleSizeOverrideDeclarator(psize,psym : presobject) : presobject; function HandleDefaultDeclarator(psym,pdefault : presobject) : presobject; function HandleArgList(aEl,aList : PResObject) : PResObject; function HandlePointerArgDeclarator(ptype, psym : presobject): presobject; function HandlePointerAbstractDeclarator(psym : presobject): presobject; function HandlePointerAbstractListDeclarator(psym,plist : presobject): presobject; function HandleDeclarationList(plist,pelem : presobject) : presobject; function handleSpecialSignedType(aType : presobject) : presobject; function handleSpecialUnSignedType(aType : presobject) : presobject; function handleArrayDecl(aType : presobject) : presobject; function handleSizedArrayDecl(aType,aSizeExpr: presobject): presobject; function handleFuncNoArg(aType: presobject): presobject; function handleFuncExpr(aType,aList: presobject): presobject; function handlePointerType(aType,aPointer,aSize : presobject): presobject; function HandleUnaryDefExpr(aExpr : presobject) : presobject; function HandleTernary(expr,colonexpr : presobject) : presobject; // Macros function HandleDefineMacro(dname,enum_list,para_def_expr: presobject) : presobject; function HandleDefineConst(dname,def_expr: presobject) : presobject; function HandleDefine(dname : presobject) : presobject; Function CheckWideString(S : String) : presobject; function CheckUnderScore(pdecl : presobject) : presobject; Function NewCType(aCType,aPascalType : String) : PresObject; Implementation function HandleTernary(expr,colonexpr : presobject) : presobject; begin colonexpr^.p1:=expr; Result:=colonexpr; inc(if_nb); result^.p:=strpnew('if_local'+str(if_nb)); end; Function NewCType(aCType,aPascalType : String) : PresObject; begin if UseCTypesUnit then Result:=NewID(aCType) else result:=NewIntID(aPascalType); end; function HandleUnaryDefExpr(aExpr : presobject) : presobject; begin if aExpr^.typ=t_funexprlist then Result:=aExpr else Result:=NewType2(t_exprlist,aExpr,nil); (* if here is a type specifier we know the return type *) if (aExpr^.typ=t_typespec) then Result^.p3:=aExpr^.p1^.get_copy; end; function handleSpecialSignedType(aType : presobject) : presobject; var hp : presobject; tc,tp : string; begin tp:=''; Result:=aType; hp:=result; if not Assigned(HP) then exit; tc:=strpas(hp^.p); if UseCTypesUnit then Case tc of cint_STR: tp:=csint_STR; cshort_STR: tp:=csshort_STR; cchar_STR: tp:=cschar_STR; clong_STR: tp:=cslong_STR; clonglong_STR: tp:=cslonglong_STR; cint8_STR: tp:=cint8_STR; cint16_STR: tp:=cint16_STR; cint32_STR: tp:=cint32_STR; cint64_STR: tp:=cint64_STR; else tp:=''; end else case tc of UINT_STR: tp:=INT_STR; USHORT_STR: tp:=SHORT_STR; USMALL_STR: tp:=SMALL_STR; // UCHAR_STR: tp:=CHAR_STR; identical to USHORT_STR.... QWORD_STR: tp:=INT64_STR; else tp:=''; end; if tp<>'' then hp^.setstr(tp); end; function handleSpecialUnSignedType(aType : presobject) : presobject; var hp : presobject; tc,tp : string; begin hp:=aType; Result:=hp; if Not assigned(hp) then exit; tp:=''; tc:=strpas(hp^.p); if UseCTypesUnit then case tc of cint_STR: tp:=cuint_STR; cshort_STR: tp:=cushort_STR; cchar_STR : tp:=cuchar_STR; clong_STR : tp:=culong_STR; clonglong_STR : tp:=culonglong_STR; cint8_STR : tp:=cuint8_STR; cint16_STR : tp:=cuint16_STR; cint32_STR : tp:=cuint32_STR; cint64_STR : tp:=cuint64_STR; else tp:=''; end else case tc of INT_STR : tp:=UINT_STR; SHORT_STR : tp:=USHORT_STR; SMALL_STR : tp:=USMALL_STR; CHAR_STR : tp:=UCHAR_STR; INT64_STR : tp:=QWORD_STR; else tp:=''; end; if tp<>'' then hp^.setstr(tp); end; function handleSizedArrayDecl(aType,aSizeExpr: presobject): presobject; var hp : presobject; begin hp:=aType; result:=hp; while assigned(hp^.p1) do hp:=hp^.p1; hp^.p1:=NewType2(t_arraydef,nil,aSizeExpr); end; function handleFuncNoArg(aType: presobject): presobject; var hp : presobject; begin hp:=aType; Result:=hp; while assigned(hp^.p1) do hp:=hp^.p1; hp^.p1:=NewType2(t_procdef,nil,nil); end; function handleFuncExpr(aType, aList: presobject): presobject; var hp : presobject; begin hp:=NewType1(t_exprlist,aType); Result:=NewType3(t_funexprlist,hp,aList,nil); end; function handlePointerType(aType, aPointer, aSize: presobject): presobject; var hp : presobject; begin if assigned(aSize) then begin if not stripinfo then emitignore(aSize); dispose(aSize,done); write_type_specifier(outfile,aType); emitwriteln(' ignored *)'); end; hp:=NewType1(t_pointerdef,aType); Result:=NewType2(t_typespec,hp,aPointer); end; function handleArrayDecl(aType: presobject): presobject; var hp : presobject; begin (* this is translated into a pointer *) hp:=aType; Result:=hp; while assigned(hp^.p1) do hp:=hp^.p1; hp^.p1:=NewType1(t_pointerdef,nil); end; function HandlePointerAbstractDeclarator(psym: presobject): presobject; var hp : presobject; begin hp:=psym; Result:=hp; while assigned(hp^.p1) do hp:=hp^.p1; hp^.p1:=NewType1(t_pointerdef,nil); end; function HandlePointerAbstractListDeclarator(psym, plist: presobject ): presobject; var hp : presobject; begin hp:=psym; result:=hp; while assigned(hp^.p1) do hp:=hp^.p1; hp^.p1:=NewType2(t_procdef,nil,plist); end; function HandleDeclarationList(plist,pelem : presobject) : presobject; var hp : presobject; begin hp:=plist; result:=hp; while assigned(hp^.next) do hp:=hp^.next; hp^.next:=NewType1(t_declist,pelem); end; function HandleSizedDeclarator(psym,psize : presobject) : presobject; var hp : presobject; begin hp:=NewType1(t_size_specifier,psize); Result:=NewType3(t_dec,nil,psym,hp); end; function HandleDefaultDeclarator(psym,pdefault : presobject) : presobject; var hp : presobject; begin EmitIgnoreDefault(psym); hp:=NewType1(t_default_value,pdefault); HandleDefaultDeclarator:=NewType3(t_dec,nil,psym,hp); end; function HandleArgList(aEl, aList: PResObject): PResObject; begin Result:=NewType2(t_arglist,aEl,nil); Result^.next:=aList; end; function HandlePointerArgDeclarator(ptype, psym : presobject): presobject; var hp : presobject; begin (* type_specifier STAR declarator *) hp:=NewType1(t_pointerdef,ptype); Result:=NewType2(t_arg,hp,psym); end; function HandleSizedPointerDeclarator(psym, psize: presobject): presobject; var hp : presobject; begin emitignore(psize); dispose(psize,done); hp:=psym; Result:=hp; while assigned(hp^.p1) do hp:=hp^.p1; hp^.p1:=NewType1(t_pointerdef,nil); end; function HandleSizeOverrideDeclarator(psize,psym : presobject) : presobject; var hp : presobject; begin EmitIgnore(psize); dispose(psize,done); hp:=psym; HandleSizeOverrideDeclarator:=hp; while assigned(hp^.p1) do hp:=hp^.p1; hp^.p1:=NewType1(t_pointerdef,nil); end; function HandleDeclarator2(aTyp : ttyp; aleft,aright: presobject): presobject; var hp : presobject; begin hp:=aLeft; result:=hp; while assigned(hp^.p1) do hp:=hp^.p1; hp^.p1:=NewType2(aTyp,nil,aRight); end; function HandleDeclarator(aTyp : ttyp; aright: presobject): presobject; var hp : presobject; begin hp:=aright; Result:=hp; while assigned(hp^.p1) do hp:=hp^.p1; hp^.p1:=NewType1(atyp,nil); end; function CheckWideString(S: String): presobject; begin if Win32headers and (s[1]='L') then delete(s,1,1); CheckWideString:=NewID(''''+copy(s,2,length(s)-2)+''''); end; function CheckUnderScore(pdecl: presobject): presobject; var tn : string; len : integer; begin Result:=pdecl; tn:=result^.str; len:=length(tn); if removeunderscore and (len>1) and (tn[1]='_') then result^.setstr(Copy(tn,2,len-1)); end; function yylex : Integer; begin yylex:=scan.yylex; line_no:=yylineno; end; (* writes an argument list, where p is t_arglist *) procedure yymsg(const msg : string); begin writeln('line ',line_no,': ',msg); end; function ellipsisarg : presobject; begin ellipsisarg:=new(presobject,init_two(t_arg,nil,nil)); end; function HandleDeclarationStatement(decl, type_spec, modifier_spec, decllist_spec, block_spec: presobject): presobject; var hp : presobject; IsExtern : boolean; begin HandleDeclarationStatement:=Nil; IsExtern:=false; (* by default we must pop the args pushed on stack *) no_pop:=false; if (assigned(decllist_spec)and assigned(decllist_spec^.p1)and assigned(decllist_spec^.p1^.p1)) and (decllist_spec^.p1^.p1^.typ=t_procdef) then begin repeat If UseLib then IsExtern:=true else IsExtern:=assigned(decl)and(decl^.str='extern'); no_pop:=assigned(modifier_spec) and (modifier_spec^.str='no_pop'); if (block_type<>bt_func) and not(createdynlib) then begin writeln(outfile); block_type:=bt_func; end; (* dyn. procedures must be put into a var block *) if createdynlib then begin if (block_type<>bt_var) then begin if not(compactmode) then writeln(outfile); writeln(outfile,aktspace,'var'); block_type:=bt_var; end; shift(2); end; if not CompactMode then begin write(outfile,aktspace); if not IsExtern then write(implemfile,aktspace); end; (* distinguish between procedure and function *) if assigned(type_spec) then if (type_spec^.typ=t_void) and (decllist_spec^.p1^.p1^.p1=nil) then begin if createdynlib then begin write(outfile,decllist_spec^.p1^.p2^.p,' : procedure'); end else begin shift(10); write(outfile,'procedure ',decllist_spec^.p1^.p2^.p); end; if assigned(decllist_spec^.p1^.p1^.p2) then write_args(outfile,decllist_spec^.p1^.p1^.p2); if createdynlib then begin loaddynlibproc.add('pointer('+decllist_spec^.p1^.p2^.p+'):=GetProcAddress(hlib,'''+decllist_spec^.p1^.p2^.p+''');'); freedynlibproc.add(decllist_spec^.p1^.p2^.p+':=nil;'); end else if not IsExtern then begin write(implemfile,'procedure ',decllist_spec^.p1^.p2^.p); if assigned(decllist_spec^.p1^.p1^.p2) then write_args(implemfile,decllist_spec^.p1^.p1^.p2); end; end else begin if createdynlib then begin write(outfile,decllist_spec^.p1^.p2^.p,' : function'); end else begin shift(9); write(outfile,'function ',decllist_spec^.p1^.p2^.p); end; if assigned(decllist_spec^.p1^.p1^.p2) then write_args(outfile,decllist_spec^.p1^.p1^.p2); write(outfile,':'); old_in_args:=in_args; (* write pointers as P.... instead of ^.... *) in_args:=true; write_p_a_def(outfile,decllist_spec^.p1^.p1^.p1,type_spec); in_args:=old_in_args; if createdynlib then begin loaddynlibproc.add('pointer('+decllist_spec^.p1^.p2^.p+'):=GetProcAddress(hlib,'''+decllist_spec^.p1^.p2^.p+''');'); freedynlibproc.add(decllist_spec^.p1^.p2^.p+':=nil;'); end else if not IsExtern then begin write(implemfile,'function ',decllist_spec^.p1^.p2^.p); if assigned(decllist_spec^.p1^.p1^.p2) then write_args(implemfile,decllist_spec^.p1^.p1^.p2); write(implemfile,':'); old_in_args:=in_args; (* write pointers as P.... instead of ^.... *) in_args:=true; write_p_a_def(implemfile,decllist_spec^.p1^.p1^.p1,type_spec); in_args:=old_in_args; end; end; (* No CDECL in interface for Uselib *) if IsExtern and (not no_pop) then write(outfile,';cdecl'); popshift; if createdynlib then begin writeln(outfile,';'); end else if UseLib then begin if IsExtern then begin write (outfile,';external'); If UseName then Write(outfile,' External_library name ''',decllist_spec^.p1^.p2^.p,''''); end; writeln(outfile,';'); end else begin writeln(outfile,';'); if not IsExtern then begin writeln(implemfile,';'); shift(2); if block_spec^.typ=t_statement_list then write_statement_block(implemfile,block_spec); popshift; end; end; IsExtern:=false; if not(compactmode) and not(createdynlib) then writeln(outfile); until not NeedEllipsisOverload; end else (* decllist_spec^.p1^.p1^.typ=t_procdef *) if assigned(decllist_spec)and assigned(decllist_spec^.p1) then begin shift(2); if block_type<>bt_var then begin if not(compactmode) then writeln(outfile); writeln(outfile,aktspace,'var'); end; block_type:=bt_var; shift(2); IsExtern:=assigned(decl)and(decl^.str='extern'); (* walk through all declarations *) hp:=decllist_spec; while assigned(hp) and assigned(hp^.p1) do begin (* write new var name *) if assigned(hp^.p1^.p2) and assigned(hp^.p1^.p2^.p) then write(outfile,aktspace,hp^.p1^.p2^.p); write(outfile,' : '); shift(2); (* write its type *) write_p_a_def(outfile,hp^.p1^.p1,type_spec); if assigned(hp^.p1^.p2)and assigned(hp^.p1^.p2^.p)then begin if isExtern then write(outfile,';cvar;external') else write(outfile,';cvar;public'); end; writeln(outfile,';'); popshift; hp:=hp^.p2; end; popshift; popshift; end; if assigned(decl) then dispose(decl,done); if assigned(type_spec) then dispose(type_spec,done); if assigned(modifier_spec) then dispose(modifier_spec,done); if assigned(decllist_spec) then dispose(decllist_spec,done); if assigned(block_spec) then dispose(block_spec,done); end; function HandleDeclarationSysTrap(decl, type_spec, modifier_spec, decllist_spec, sys_trap: presobject): presobject; var hp : presobject; IsExtern : boolean; begin HandleDeclarationSysTrap:=Nil; IsExtern:=false; (* by default we must pop the args pushed on stack *) no_pop:=false; if (assigned(decllist_spec)and assigned(decllist_spec^.p1)and assigned(decllist_spec^.p1^.p1)) and (decllist_spec^.p1^.p1^.typ=t_procdef) then begin repeat If UseLib then IsExtern:=true else IsExtern:=assigned(decl)and(decl^.str='extern'); no_pop:=assigned(modifier_spec) and (modifier_spec^.str='no_pop'); if (block_type<>bt_func) and not(createdynlib) then begin writeln(outfile); block_type:=bt_func; end; (* dyn. procedures must be put into a var block *) if createdynlib then begin if (block_type<>bt_var) then begin if not(compactmode) then writeln(outfile); writeln(outfile,aktspace,'var'); block_type:=bt_var; end; shift(2); end; if not CompactMode then begin write(outfile,aktspace); if not IsExtern then write(implemfile,aktspace); end; (* distinguish between procedure and function *) if assigned(type_spec) then if (type_spec^.typ=t_void) and (decllist_spec^.p1^.p1^.p1=nil) then begin if createdynlib then begin write(outfile,decllist_spec^.p1^.p2^.p,' : procedure'); end else begin shift(10); write(outfile,'procedure ',decllist_spec^.p1^.p2^.p); end; if assigned(decllist_spec^.p1^.p1^.p2) then write_args(outfile,decllist_spec^.p1^.p1^.p2); if createdynlib then begin loaddynlibproc.add('pointer('+decllist_spec^.p1^.p2^.p+'):=GetProcAddress(hlib,'''+decllist_spec^.p1^.p2^.p+''');'); freedynlibproc.add(decllist_spec^.p1^.p2^.p+':=nil;'); end else if not IsExtern then begin write(implemfile,'procedure ',decllist_spec^.p1^.p2^.p); if assigned(decllist_spec^.p1^.p1^.p2) then write_args(implemfile,decllist_spec^.p1^.p1^.p2); end; end else begin if createdynlib then begin write(outfile,decllist_spec^.p1^.p2^.p,' : function'); end else begin shift(9); write(outfile,'function ',decllist_spec^.p1^.p2^.p); end; if assigned(decllist_spec^.p1^.p1^.p2) then write_args(outfile,decllist_spec^.p1^.p1^.p2); write(outfile,':'); write_p_a_def(outfile,decllist_spec^.p1^.p1^.p1,type_spec); if createdynlib then begin loaddynlibproc.add('pointer('+decllist_spec^.p1^.p2^.p+'):=GetProcAddress(hlib,'''+decllist_spec^.p1^.p2^.p+''');'); freedynlibproc.add(decllist_spec^.p1^.p2^.p+':=nil;'); end else if not IsExtern then begin write(implemfile,'function ',decllist_spec^.p1^.p2^.p); if assigned(decllist_spec^.p1^.p1^.p2) then write_args(implemfile,decllist_spec^.p1^.p1^.p2); write(implemfile,':'); old_in_args:=in_args; (* write pointers as P.... instead of ^.... *) in_args:=true; write_p_a_def(implemfile,decllist_spec^.p1^.p1^.p1,type_spec); in_args:=old_in_args; end; end; if assigned(sys_trap) then write(outfile,';systrap ',sys_trap^.p); (* No CDECL in interface for Uselib *) if IsExtern and (not no_pop) then write(outfile,';cdecl'); popshift; if createdynlib then begin writeln(outfile,';'); end else if UseLib then begin if IsExtern then begin write (outfile,';external'); If UseName then Write(outfile,' External_library name ''',decllist_spec^.p1^.p2^.p,''''); end; writeln(outfile,';'); end else begin writeln(outfile,';'); if not IsExtern then begin writeln(implemfile,';'); writeln(implemfile,aktspace,'begin'); writeln(implemfile,aktspace,' { You must implement this function }'); writeln(implemfile,aktspace,'end;'); end; end; IsExtern:=false; if not(compactmode) and not(createdynlib) then writeln(outfile); until not NeedEllipsisOverload; end else (* decllist_spec^.p1^.p1^.typ=t_procdef *) if assigned(decllist_spec)and assigned(decllist_spec^.p1) then begin shift(2); if block_type<>bt_var then begin if not(compactmode) then writeln(outfile); writeln(outfile,aktspace,'var'); end; block_type:=bt_var; shift(2); IsExtern:=assigned(decl)and(decl^.str='extern'); (* walk through all declarations *) hp:=decllist_spec; while assigned(hp) and assigned(hp^.p1) do begin (* write new var name *) if assigned(hp^.p1^.p2) and assigned(hp^.p1^.p2^.p) then write(outfile,aktspace,hp^.p1^.p2^.p); write(outfile,' : '); shift(2); (* write its type *) write_p_a_def(outfile,hp^.p1^.p1,type_spec); if assigned(hp^.p1^.p2)and assigned(hp^.p1^.p2^.p)then begin if isExtern then write(outfile,';cvar;external') else write(outfile,';cvar;public'); end; writeln(outfile,';'); popshift; hp:=hp^.p2; end; popshift; popshift; end; if assigned(decl)then dispose(decl,done); if assigned(type_spec)then dispose(type_spec,done); if assigned(decllist_spec)then dispose(decllist_spec,done); end; function HandleSpecialType(aType: presobject) : presobject; var hp : presobject; begin HandleSpecialType:=Nil; if block_type<>bt_type then begin if not(compactmode) then writeln(outfile); writeln(outfile,aktspace,'type'); block_type:=bt_type; end; shift(2); if ( aType^.p2 <> nil ) then begin (* write new type name *) TN:=TypeName(aType^.p2^.p); PN:=PointerName(aType^.p2^.p); (* define a Pointer type also for structs *) if UsePPointers and (Uppercase(tn)<>Uppercase(pn)) and assigned(aType) and (aType^.typ in [t_uniondef,t_structdef]) then writeln(outfile,aktspace,PN,' = ^',TN,';'); write(outfile,aktspace,TN,' = '); shift(2); hp:=aType; write_type_specifier(outfile,hp); popshift; (* enum_to_const can make a switch to const *) if block_type=bt_type then writeln(outfile,';'); writeln(outfile); flush(outfile); popshift; if must_write_packed_field then write_packed_fields_info(outfile,hp,TN); if assigned(hp) then dispose(hp,done) end else begin TN:=TypeName(aType^.str); PN:=PointerName(aType^.str); if UsePPointers then writeln(outfile,aktspace,PN,' = ^',TN,';'); if PackRecords then writeln(outfile, aktspace, TN, ' = packed record') else writeln(outfile, aktspace, TN, ' = record'); writeln(outfile, aktspace, ' {undefined structure}'); writeln(outfile, aktspace, ' end;'); writeln(outfile); popshift; end; end; function HandleTypedef(type_spec,dec_modifier,declarator,arg_decl_list: presobject) : presobject; var hp : presobject; begin hp:=nil; HandleTypedef:=nil; (* TYPEDEF type_specifier LKLAMMER dec_modifier declarator RKLAMMER maybe_space LKLAMMER argument_declaration_list RKLAMMER SEMICOLON *) if block_type<>bt_type then begin if not(compactmode) then writeln(outfile); writeln(outfile,aktspace,'type'); block_type:=bt_type; end; no_pop:=assigned(dec_modifier) and (dec_modifier^.str='no_pop'); shift(2); (* walk through all declarations *) hp:=declarator; if assigned(hp) then begin hp:=declarator; while assigned(hp^.p1) do hp:=hp^.p1; hp^.p1:=new(presobject,init_two(t_procdef,nil,arg_decl_list)); hp:=declarator; if assigned(hp^.p1) and assigned(hp^.p1^.p1) then begin writeln(outfile); (* write new type name *) write(outfile,aktspace,TypeName(hp^.p2^.p),' = '); shift(2); write_p_a_def(outfile,hp^.p1,type_spec); popshift; (* if no_pop it is normal fpc calling convention *) if is_procvar and (not no_pop) then write(outfile,';cdecl'); writeln(outfile,';'); flush(outfile); end; end; popshift; if assigned(type_spec)then dispose(type_spec,done); if assigned(dec_modifier)then dispose(dec_modifier,done); if assigned(declarator)then (* disposes also arg_decl_list *) dispose(declarator,done); end; function HandleTypedefList(type_spec,dec_modifier,declarator_list: presobject) : presobject; (* TYPEDEF type_specifier dec_modifier declarator_list SEMICOLON *) var hp,ph : presobject; begin HandleTypedefList:=Nil; ph:=nil; if block_type<>bt_type then begin if not(compactmode) then writeln(outfile); writeln(outfile,aktspace,'type'); block_type:=bt_type; end else writeln(outfile); no_pop:=assigned(dec_modifier) and (dec_modifier^.str='no_pop'); shift(2); (* Get the name to write the type definition for, try to use the tag name first *) if assigned(type_spec^.p2) then begin ph:=type_spec^.p2; end else begin if not assigned(declarator_list) then internalerror(5555); if not assigned(declarator_list^.p1) then internalerror(666); if not assigned(declarator_list^.p1^.p2) then internalerror(4444); ph:=declarator_list^.p1^.p2; end; (* write type definition *) is_procvar:=false; TN:=TypeName(ph^.p); PN:=PointerName(ph^.p); if UsePPointers and (Uppercase(tn)<>Uppercase(pn)) and assigned(type_spec) and (type_spec^.typ<>t_procdef) then WritePointerTypeDef(outfile,PN,TN); (* write new type name *) write(outfile,aktspace,TN,' = '); shift(2); write_p_a_def(outfile,declarator_list^.p1^.p1,type_spec); popshift; (* if no_pop it is normal fpc calling convention *) if is_procvar and (not no_pop) then write(outfile,';cdecl'); writeln(outfile,';'); flush(outfile); (* write alias names, ph points to the name already used *) hp:=declarator_list; while assigned(hp) do begin if (hp<>ph) and assigned(hp^.p1^.p2) then begin PN:=TypeName(ph^.p); TN:=TypeName(hp^.p1^.p2^.p); if Uppercase(TN)<>Uppercase(PN) then begin write(outfile,aktspace,TN,' = '); write_p_a_def(outfile,hp^.p1^.p1,ph); writeln(outfile,';'); PN:=PointerName(hp^.p1^.p2^.p); if UsePPointers and (Uppercase(tn)<>Uppercase(pn)) and assigned(type_spec) and (type_spec^.typ<>t_procdef) then writeln(outfile,aktspace,PN,' = ^',TN,';'); end; end; hp:=hp^.next; end; popshift; if must_write_packed_field then if assigned(ph) then write_packed_fields_info(outfile,type_spec,ph^.str) else if assigned(type_spec^.p2) then write_packed_fields_info(outfile,type_spec,type_spec^.p2^.str); if assigned(type_spec)then dispose(type_spec,done); if assigned(dec_modifier)then dispose(dec_modifier,done); if assigned(declarator_list)then dispose(declarator_list,done); end; function HandleStructDef(dname1,dname2 : presobject) : presobject; begin HandleStructDef:=nil; (* TYPEDEF STRUCT dname dname SEMICOLON *) if block_type<>bt_type then begin if not(compactmode) then writeln(outfile); writeln(outfile,aktspace,'type'); block_type:=bt_type; end; PN:=TypeName(dname1^.p); TN:=TypeName(dname2^.p); if Uppercase(tn)<>Uppercase(pn) then begin shift(2); writeln(outfile,aktspace,PN,' = ',TN,';'); popshift; end; if assigned(dname1) then dispose(dname1,done); if assigned(dname2) then dispose(dname2,done); end; function HandleSimpleTypeDef(tname : presobject) : presobject; begin HandleSimpleTypeDef:=Nil; if block_type<>bt_type then begin if not(compactmode) then writeln(outfile); writeln(outfile,aktspace,'type'); block_type:=bt_type; end else writeln(outfile); shift(2); (* write as pointer *) writeln(outfile,'(* generic typedef *)'); writeln(outfile,aktspace,tname^.p,' = pointer;'); flush(outfile); popshift; if assigned(tname) then dispose(tname,done); end; function HandleErrorDecl(e1,e2 : presobject) : presobject; begin HandleErrorDecl:=Nil; writeln(outfile,'in declaration at line ',line_no,' *)'); aktspace:=''; in_space_define:=0; in_define:=false; arglevel:=0; if_nb:=0; aktspace:=' '; resetshift; yyerrok; end; function HandleDefine(dname : presobject) : presobject; begin HandleDefine:=Nil; writeln(outfile,'{$define ',dname^.p,'}',aktspace,commentstr); flush(outfile); if assigned(dname)then dispose(dname,done); end; function HandleDefineConst(dname,def_expr: presobject) : presobject; var hp : presobject; begin HandleDefineConst:=Nil; (* DEFINE dname SPACE_DEFINE def_expr NEW_LINE *) if (def_expr^.typ=t_exprlist) and def_expr^.p1^.is_const and not assigned(def_expr^.next) then begin if block_type<>bt_const then begin if block_type<>bt_func then writeln(outfile); writeln(outfile,aktspace,'const'); end; block_type:=bt_const; shift(2); write(outfile,aktspace,dname^.p); write(outfile,' = '); flush(outfile); write_expr(outfile,def_expr^.p1); writeln(outfile,';',aktspace,commentstr); popshift; if assigned(dname) then dispose(dname,done); if assigned(def_expr) then dispose(def_expr,done); end else begin if block_type<>bt_func then writeln(outfile); if not stripinfo then begin writeln (outfile,aktspace,'{ was #define dname def_expr }'); writeln (implemfile,aktspace,'{ was #define dname def_expr }'); end; block_type:=bt_func; write(outfile,aktspace,'function ',dname^.p); write(implemfile,aktspace,'function ',dname^.p); shift(2); if not assigned(def_expr^.p3) then begin writeln(outfile,' : longint; { return type might be wrong }'); flush(outfile); writeln(implemfile,' : longint; { return type might be wrong }'); end else begin write(outfile,' : '); write_type_specifier(outfile,def_expr^.p3); writeln(outfile,';',aktspace,commentstr); flush(outfile); write(implemfile,' : '); write_type_specifier(implemfile,def_expr^.p3); writeln(implemfile,';'); end; writeln(outfile); flush(outfile); hp:=new(presobject,init_two(t_funcname,dname,def_expr)); write_funexpr(implemfile,hp); popshift; dispose(hp,done); writeln(implemfile); flush(implemfile); end; end; function HandleDefineMacro(dname,enum_list,para_def_expr: presobject) : presobject; var hp,ph : presobject; begin HandleDefineMacro:=Nil; hp:=nil; ph:=nil; (* DEFINE dname LKLAMMER enum_list RKLAMMER para_def_expr NEW_LINE *) if not stripinfo then begin writeln (outfile,aktspace,'{ was #define dname(params) para_def_expr }'); writeln (implemfile,aktspace,'{ was #define dname(params) para_def_expr }'); if assigned(enum_list) then begin writeln (outfile,aktspace,'{ argument types are unknown }'); writeln (implemfile,aktspace,'{ argument types are unknown }'); end; if not assigned(para_def_expr^.p3) then begin writeln(outfile,aktspace,'{ return type might be wrong } '); writeln(implemfile,aktspace,'{ return type might be wrong } '); end; end; if block_type<>bt_func then writeln(outfile); block_type:=bt_func; write(outfile,aktspace,'function ',dname^.p); write(implemfile,aktspace,'function ',dname^.p); if assigned(enum_list) then begin write(outfile,'('); write(implemfile,'('); ph:=new(presobject,init_one(t_enumdef,enum_list)); write_def_params(outfile,ph); write_def_params(implemfile,ph); if assigned(ph) then dispose(ph,done); ph:=nil; (* types are unknown *) write(outfile,' : longint)'); write(implemfile,' : longint)'); end; if not assigned(para_def_expr^.p3) then begin writeln(outfile,' : longint;',aktspace,commentstr); writeln(implemfile,' : longint;'); flush(outfile); end else begin write(outfile,' : '); write_type_specifier(outfile,para_def_expr^.p3); writeln(outfile,';',aktspace,commentstr); flush(outfile); write(implemfile,' : '); write_type_specifier(implemfile,para_def_expr^.p3); writeln(implemfile,';'); end; writeln(outfile); flush(outfile); hp:=new(presobject,init_two(t_funcname,dname,para_def_expr)); write_funexpr(implemfile,hp); writeln(implemfile); flush(implemfile); if assigned(hp)then dispose(hp,done); end; end.