Code archives/Miscellaneous/itoh

This code has been declared by its author to be Public Domain code.

Download source code

itoh by skidracer2007
Only of interest to C/C++ programmers this code will scan the .i files of the specified module build - in this case win32 x86 release (good for Windows usage) and builds an interface for all the types, consts and globals it finds for use by C/C++ code.

Method table descriptions not yet implemented sorry.

WARNING: this program generates many files in currentdir so make sure you save it in it's own folder before running, the path $blitzmax/include might be a good choice.



<edit>

sry,

MingW not quite compatible, usable code coming soon...
' itoh.bmx

' converts blitzmax .i interface files to c/c++ .h files

' WARNING: this program generates many files in currentdir

Local modpath$=RequestDir("Please select your blitzmax/mod directory as source path",CurrentDir())

MakeHeaders modpath,".release.win32.x86","bb"

' "C:/blitzmax/mod",".release.win32.x86","bb"

Function MakeHeaders(modpath$,suffix$,prefix$)
	Local suffixi$=suffix+".i"
	Local suffixa$=suffix+".a"
	For Local d$=EachIn LoadDir(modpath)
		If d[d.length-4..]<>".mod" Continue
		For Local m$=EachIn LoadDir(modpath+"/"+d)
			If m[m.length-4..]<>".mod" Continue
			Local id$=d[..d.length-4]+"_"+m[..m.length-4]
			For Local f$=EachIn LoadDir(modpath+"/"+d+"/"+m)
Rem
uncomment to archive single super mods.a
				If f[f.length-suffixa.length..]=suffixa
					Local ar$="ar -vrus mods.a "+modpath+"/"+d+"/"+m+"/"+f
					DebugLog ar
					system_ ar
					Continue
				EndIf
EndRem				
				If f[f.length-suffixi.length..]<>suffixi Continue
				Local hpath$=d[..d.length-4]+"_"+f[..f.length-suffixi.length]+".h"
				Local ipath$=modpath+"/"+d+"/"+m+"/"+f
				CreateHeader hpath,ipath,id,prefix
			Next
		Next	
	Next
	Local b$=modpath+"/brl.mod/blitz.mod/"
	CopyFile b+"blitz_types.h","blitz_types.h"
	CopyFile b+"blitz_object.h","blitz_object.h"
	CopyFile b+"blitz_array.h","blitz_array.h"
	CopyFile b+"blitz_string.h","blitz_string.h"
	CopyFile b+"blitz_debug.h","blitz_debug.h"
	CopyFile b+"blitz_handle.h","blitz_handle.h"
End Function

Function CreateHeader( hpath$,ipath$,id$,prefix$ )
	Local f:TStream
	Local l$,sname$,ssuper$,p,q
	Local struct$
	Local hdrs$,structs$,defs$,funcs$

	If id="brl_blitz"
		hdrs:+"#include ~qblitz_types.h~q~n"
		hdrs:+"#include ~qblitz_debug.h~q~n"
		hdrs:+"#include ~qblitz_object.h~q~n"
		hdrs:+"#include ~qblitz_string.h~q~n"
		hdrs:+"#include ~qblitz_array.h~q~n"
		hdrs:+"#include ~qblitz_handle.h~q~n"
	EndIf

	f=ReadStream(ipath)
	If Not f Return
	While Not Eof(f)
		l=f.ReadLine()
		If l[..10]="ModuleInfo" Continue
		
		If l[..7]="import "
			l=l[7..]	
			If l[..1]="~q" Continue 'ignore misc import directives
			p=l.findlast(".")
			If p=-1
				DebugStop
			EndIf
			l=l.Replace(".","_")
'			l=l[p+1..]
			hdrs:+"#include ~q"+l+".h~q~n"
			Continue
		EndIf
		If l[l.length-1..]="{"
			p=l.find("^")
			If p<>-1
				sname=l[..p]
				ssuper=l[p+1..l.length-1]
				p=ssuper.findlast(".")
				ssuper=":"+ssuper[p+1..]
				If ssuper=":Null" ssuper=""	
				ssuper=ssuper.Replace(":Object",":BBObject")		
				struct$="struct "+sname+ssuper+"{~n"
'				DebugLog struct
			EndIf
			Continue
		EndIf
		If struct
			If l[..2]="}=" Or l[..3]="}A=" Or l[..3]="}E="
				struct:+"};~n~n"			
'				DebugLog struct
				structs:+struct
				struct=""
				Continue
			EndIf		
			If l[..1]="."
				l=l[1..l.length-1]
				struct:+"~t"+bb2c(l)+";~n"
		
			EndIf
			Continue
		EndIf
		p=l.findlast("=")
		If p<>-1
			Select l[p-1..p]
				Case ")"
					Local bbname$,args$,ftype$
					bbname=l[p+1..]
					l=l[..p]
					p=l.find("(")
					args=l[p+1..l.length-1]
					l=l[..p]
					funcs:+funcbb2c(l,bbname,args,prefix)
'					DebugLog "FUNCTION:l="+l+" bbname="+bbname+" args="+args
				Case "%"
					defs:+"#define "+l[..p-1]+" "+l[p+1..]+"~n"
				Case "$"
					defs:+"#define "+l[..p-1]+" "+l[p+2..]+"~n"
				Case "&"
'					DebugLog "Ptr= ??? "+l
				Case "S"
'					DebugLog "STDCALL Function= ??? "+l
				Default
					DebugStop
			End Select
			Continue
		EndIf
	Wend
	CloseFile f
	
	id=id.ToUpper()+"_H"


	Local h$=hdrs+"~n"+defs+"~n"+structs+funcs
	
	h="#ifndef "+id+"~n#define "+id+"~n~n"+h+"#endif~n"
		
	SaveText h,hpath

End Function


Function funcbb2c$(l$,bbname$,args$,prefix$)
	Local h$,a$
	bbname=bbname[1..bbname.length-1]
	h=bb2c(l)+"("	'strips l and returns c decl
	h=h.Replace(l+"(",bbname+"(")
	While True
		a=getarg(args)
		If Not a Exit
		h:+bb2c(a)
		If args h:+","	
	Wend
	h:+");~n"
	l=prefix+l
	If l<>bbname
		h:+"#define "+l+" "+bbname+"~n~n"
	EndIf
'	DebugLog h
	Return h
End Function


Function bb2c$(bb$ Var)	'on return strips input string to friendly name
	Local p,t$,eq$,fn$,ar$,std$

	Local o$=bb
	
	p=bb.find("=")
	If p<>-1
		eq$=bb[p..]
		bb=bb[..p]
		If eq[..2]="=~q"
			eq=eq[2..eq.length-1]
			If eq[..2]="bb" 
				eq="&"+eq
			EndIf
			eq="="+eq
		EndIf
		If eq[..2]="=$"
			If eq="=$~q~q"
				eq="=&bbEmptyString"
			Else
				DebugLog "&&&&&&&&"+eq
				eq=""
			EndIf
		EndIf
		Select eq[eq.length-1..]
			Case "!","#"
				eq=eq[..eq.length-1]
				If eq.find(".")=-1 eq=eq+".0"
				eq=eq+"f"
		End Select
	EndIf

	While bb.length
		If bb[bb.length-4..]=" Var"
			t="&"+t
			bb=bb[..bb.length-4]
			Continue		
		EndIf

		If bb[bb.length-2..]=")S"
			bb=bb[..bb.length-1]
			std="__stdcall "
		EndIf

		
		Select bb[bb.length-1..]
			Case ")"
				p=bb.find("(")
				fn=bb[p..bb.length]
				bb=bb[..p]
				
				Local args$=fn[1..fn.length-1]
				If args
					fn=""
					While True
						Local a$=getarg(args)
						If Not a Exit
						fn:+bb2c(a)
						If args fn:+","	
					Wend
					fn="("+fn+")"
				EndIf

				Continue				
			Case "%"
				If bb[bb.length-2..]="%%"
					t="BBInt64"+t
					bb=bb[..bb.length-2]
					Continue
				EndIf
				t="int"+t
			Case "#"
				t="float"+t
			Case "!"
				t="double"+t
			Case "$"
				t="BBString*"+t
			Case "z"
				If bb[bb.length-2..]="$z"
					t="const char *"+t
					bb=bb[..bb.length-2]
					Continue
				EndIf
			Case "@"
				If bb[bb.length-2..]="@@"
					t="BBSHORT"+t
					bb=bb[..bb.length-2]
					Continue
				EndIf
				t="BBBYTE"+t
			Case "*"
				t="*"+t
'Function LoadDir$[]( dir$,skip_dots=True )
'	Object&[]* _datas;
			Case "]"
				p=bb.find("&[")
'				If bb[bb.length-3..]="&[]"
				If p<>-1
					ar="BBArray*"+t
					bb=bb[..p]
					Continue
				EndIf			
				DebugStop
			Default

				p=bb.find(":")
				If p<>-1
			
					If t DebugStop
					
					o=bb[p+1..]
					bb=bb[..p]
					p=o.findlast(".")	'typedef
					o=o[p+1..]
					
					If o="Object" 
						o="BBObject"
					Else
						If eq
							eq="=("+o+"*)"+eq[1..]
						EndIf
					EndIf
					
'					If bb="_datas" DebugStop
			
					If ar Return ar+" "+bb

'					DebugLog"default:"+o+" *"+bb
					
					Return o+" *"+bb+eq
				EndIf

				If bb="char" bb="c"
				If ar t=ar	'ignore type of array for now
				If fn					
'					DebugLog "FN:"+t+"("+bb+")"+fn+eq
					Return t+"("+std+bb+")"+fn+eq
				EndIf
				If t="Object&[]*" DebugStop
				
				Return t$+" "+bb+eq
		End Select			
		bb=bb[..bb.length-1]
	Wend
End Function

Function getarg$(arg$ Var)
	Local p=arg.find(",")
	Local q=arg.find("(")
	If q<>-1 And q<p	'needs to handle nest
		q=arg.find(")",q)
		p=arg.find(",",q)
	EndIf
	If p=-1 p=arg.length
	Local a$=arg[..p]
	arg=arg[p+1..]
	Return a
End Function

Comments

N2007
Slightly modified, included in comments my changes. This produces working code at times, from what I can see, the only issue is that of referencing stuff that has not yet been declared (structures, specifically, absolutely need to be declared in prototype form before they get really defined -- may write my own parser to handle this, since this is kind of messy at the moment).



Aside from what I noted, the code this produces now seems to work for me.


skidracer2007
Thanks Noel.

Just been trying to build interfaces for an application not just modules. Unfortunately the main .bmx build file does not generate a .i so you need to declare a single line .bmx file that imports yourapp.bmx, build the single line version in release mode and then run the following selecting yourapp.bmx (not the stub) as the application source in the second requester. This could be easily automated with a few calls to bmk once some other issues get ironed out.

My new initialization code now looks like this:

Strict

Const BUILD$=".release.win32.x86"
Const PREFIX$="bb" 

Local cd$=CurrentDir()

Local modpath$=RequestDir("Please select your blitzmax/mod directory as source path",cd)

MakeHeaders modpath,BUILD,PREFIX

Local app$=RequestFile("Please select your application.bmx","BlitzMax Source:bmx",False,cd)
Local path$=app[..app.length-4]
Local dir$=ExtractDir(path)
Local ifile$=dir+"/.bmx/"+StripDir(app)+BUILD+".i"

CreateHeader( path+".h",ifile,"",prefix$ )

End



Code Archives Forum