diff options
Diffstat (limited to 'lib/wx/api_gen/gl_gen.erl')
-rw-r--r-- | lib/wx/api_gen/gl_gen.erl | 687 |
1 files changed, 687 insertions, 0 deletions
diff --git a/lib/wx/api_gen/gl_gen.erl b/lib/wx/api_gen/gl_gen.erl new file mode 100644 index 0000000000..91a6a1adbf --- /dev/null +++ b/lib/wx/api_gen/gl_gen.erl @@ -0,0 +1,687 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%%%------------------------------------------------------------------- +%%% File : gl_gen.erl +%%% Author : Dan Gudmundsson <[email protected]> +%%% Description : +%%% +%%% Created : 16 Apr 2007 by Dan Gudmundsson <[email protected]> +%%%------------------------------------------------------------------- +-module(gl_gen). + +-export([code/0]). + +-include_lib("xmerl/include/xmerl.hrl"). +-include("gl_gen.hrl"). + +-import(lists, [foldl/3,foldr/3,reverse/1,reverse/2,keysearch/3,map/2,filter/2]). +-import(proplists, [get_value/2,get_value/3]). + +-import(gen_util,[uppercase_all/1]). + +-compile(export_all). + +code() -> safe(fun gen_code/0,true). + +devcode() -> spawn(fun() -> safe(fun gen_code/0,false) end). + +safe(What, QuitOnErr) -> + try + What(), + io:format("Completed succesfully~n~n", []), + QuitOnErr andalso gen_util:halt(0) + catch Err:Reason -> + catch gen_util:close(), + io:format("Error ~p: ~p:~p~n ~p~n", + [get(current_func),Err,Reason,erlang:get_stacktrace()]), + timer:sleep(1999), + QuitOnErr andalso gen_util:halt(1) + end. + +gen_code() -> + {ok, Opts0} = file:consult("glapi.conf"), + erase(func_id), + Opts = init_defs(Opts0), + GLUDefs = parse_glu_defs(Opts), + GLDefs = parse_gl_defs(Opts), + {GLUDefines,GLUFuncs} = setup(GLUDefs, Opts), + {GLDefines,GLFuncs} = setup(GLDefs, Opts), + gl_gen_erl:glu_defines(GLUDefines), + gl_gen_erl:glu_api(GLUFuncs), + + gl_gen_erl:gl_defines(GLDefines), + gl_gen_erl:gl_api(GLFuncs), + gl_gen_erl:gen_debug(GLFuncs,GLUFuncs), + gl_gen_c:gen(GLFuncs,GLUFuncs), + ok. + +init_defs(Opts0) -> + Opts0. + +parse_glu_defs(Opts0) -> + All = foldl(fun(File, Acc) -> load_file(File,Opts0,Acc) end, [], ["glu"]), + reverse(All). + +parse_gl_defs(Opts0) -> + All = foldl(fun(File, Acc) -> load_file(File,Opts0,Acc) end, [], ["gl","glext"]), + reverse(All). + +load_file(FileName, Opts, Acc) -> + File = filename:join(["gl_xml",FileName ++ "_8h.xml"]), + put({loaded, FileName}, true), + case xmerl_scan:file(File, [{space, normalize}]) of + {error, enoent} -> + io:format("Skipped File not found ~p ~n", [File]), + Acc; + {Doc, _} -> + io:format("Scanning ~p ~n", [File]), + %% It's duplicated in xml get sectiondef only once. + Content = find_data(Doc#xmlElement.content), + lists:foreach(fun(D) -> extract_argnames(D) end, Content), + foldl(fun(Data,Acc0) -> parse_file(Data, Opts, Acc0) end, + Acc, Content) + end. + +extract_argnames(#xmlElement{name=memberdef,attributes=Attr,content=C}) -> + case keysearch(kind, #xmlAttribute.name, Attr) of + {value, #xmlAttribute{value = "typedef"}} -> + parse_typedef(C,undefined); + _ -> + ok + end; +extract_argnames(_) -> ok. + +parse_typedef([#xmlElement{name=argsstring,content=[#xmlText{value=AS}]}|R],_) -> + parse_typedef(R,AS); +parse_typedef([#xmlElement{name=name}|_],undefined) -> + skip; +parse_typedef([#xmlElement{name=name,content=[#xmlText{value=N}]}|_],AS) -> + Args0 = string:tokens(AS," ,()*[]"), + try + Args = get_arg_names(Args0), + put({typedef,string:strip(N)},Args) + catch _:Where -> + io:format("Error ~p: ~p ~p~n", [N,Args0,Where]), + ?error(arg_names) + end; +parse_typedef([_|R],AS) -> + parse_typedef(R,AS); +parse_typedef([],_) -> skip. + +get_arg_names(As0) -> + Args = lists:filter(fun("const") -> false; (_) -> true end, As0), + get_arg_names(Args, []). + +get_arg_names([_Type,Name|R],Acc) -> + get_arg_names(R, [Name|Acc]); +get_arg_names([],Acc) -> reverse(Acc); +get_arg_names(["void"],[]) -> []; +get_arg_names(Error,_Acc) -> exit(Error). + +%% Avoid bugs in (old) doxygen..the new one doesn't have 'em +find_data([#xmlElement{name=compounddef, content=C}|_]) -> find_data(C); +find_data([#xmlElement{name=sectiondef, attributes=Attr, content=C}|R]) -> + case keysearch(kind, #xmlAttribute.name, Attr) of + {value, _} -> %% The new one have func define typedef + find_data(R) ++ C; + false -> + C + end; +find_data([_Hmm|R]) -> +%% case _Hmm of +%% #xmlElement{} -> +%% io:format("0 ~p ~n",[_Hmm#xmlElement.name]); +%% _ -> +%% ok +%% end, + find_data(R); +find_data([]) -> []. + +parse_file(#xmlElement{name=memberdef,attributes=Attr, content=C}, Opts, Acc) -> + case keysearch(kind, #xmlAttribute.name, Attr) of + {value, #xmlAttribute{value = "function"}} -> + try + Def = parse_func(C, Opts), + [Def|Acc] + catch throw:skip -> Acc + after erase(current_func) + end; + {value, #xmlAttribute{value = "define"}} -> + try + Def = parse_define(C, #def{}, Opts), + [Def|Acc] + catch throw:skip -> Acc + end; + {value, #xmlAttribute{value = "typedef"}} -> + Acc; + _W -> + io:format("Hmm ~p~n",[_W]), + Acc + end; +parse_file(_Hmm,_,Acc) -> + Acc. + +parse_define([#xmlElement{name=name,content=[#xmlText{value="API" ++ _}]}|_],_Def,_Os) -> + throw(skip); +parse_define([#xmlElement{name=name,content=[#xmlText{value="GLAPI"++_}]}|_],_Def,_Os) -> + throw(skip); +parse_define([#xmlElement{name=name,content=[#xmlText{value="WINGDIAPI"++_}]}|_],_Def,_Os) -> + throw(skip); +parse_define([#xmlElement{name=name,content=[#xmlText{value=Name}]}|R], Def, Os) -> + parse_define(R, Def#def{name=Name}, Os); +parse_define([#xmlElement{name=initializer,content=[#xmlText{value=V}]}|_],Def,_Os) -> + Val0 = string:strip(V), + try + case Val0 of + "0x" ++ Val1 -> + Val = http_util:hexlist_to_integer(Val1), + Def#def{val=Val, type=hex}; + _ -> + Val = list_to_integer(Val0), + Def#def{val=Val, type=int} + end + catch _:_ -> + Def#def{val=Val0, type=string} + end; +parse_define([_|R], D, Opts) -> + parse_define(R, D, Opts); +parse_define([], D, _Opts) -> + D. + +parse_func(Xml, Opts) -> + {Func,_} = foldl(fun(X,Acc) -> parse_func(X,Acc,Opts) end, {#func{},1}, Xml), + #func{params=Args0,type=Type0} = Func, + Args = filter(fun(#arg{type=void}) -> false; (_) -> true end, Args0), + #arg{type=Type} = + patch_param(Func#func.name,#arg{name="result",type=Type0},Opts), + Func#func{params=reverse(Args), type=Type}. + +parse_func(#xmlElement{name=type, content=C}, {F,AC}, Os) -> + Type = parse_type(drop_empty(C), Os), + {F#func{type=Type},AC}; +parse_func(#xmlElement{name=name, content=[#xmlText{value=C}]},{F,AC},Os) -> + Func = string:strip(C), + put(current_func, Func), + {F#func{name=name(Func,Os)},AC}; +parse_func(#xmlElement{name=param, content=C},{F,AC},Os) -> + Parse = fun(Con, Ac) -> parse_param(Con, Ac, Os) end, + Param0 = foldl(Parse, #arg{}, drop_empty(C)), + Param = fix_param_name(Param0, F, AC), + {add_param(Param, Os, F),AC+1}; +parse_func(_, F,_) -> + F. + +fix_param_name(A=#arg{name=undefined,type=T},#func{name=Func},Count) -> + TDName = "PFN" ++ uppercase_all(Func) ++ "PROC", + case get({typedef,TDName}) of + undefined when T == void -> + A; + undefined -> + io:format("Didn't find typedef for: ~s~n", [TDName]), + exit(aargh); + AS -> + try A#arg{name = lists:nth(Count, AS)} + catch _:_ -> A + end + end; +fix_param_name(A,_,_) -> A. + +parse_param(#xmlElement{name=type,content=C}, Arg, Os) -> + Arg#arg{type=parse_type(drop_empty(C),Os)}; +parse_param(#xmlElement{name=declname,content=[C]},Arg,_Os) -> + #xmlText{value=Name} = C, + Arg#arg{name=Name}; +parse_param(#xmlElement{name=array,content=[#xmlText{value=C}]}, + Arg=#arg{type=Type0},_Os) -> + try + [Int] = string:tokens(C, "[] "), + Val = list_to_integer(Int), + Arg#arg{type=Type0#type{single={tuple,Val}, by_val=true}} + catch _:_ -> + ?warning("Undefined Array size ~p in ~p ~p~n", + [Arg, get(current_func), C]), + Arg#arg{type=Type0#type{single={tuple,undefined}, by_val=true}} + end; + +%% Skip these +parse_param(#xmlElement{name=definition}, Arg, _) -> Arg; +parse_param(#xmlElement{name=argsstring}, Arg,_) -> Arg; +parse_param(#xmlElement{name=briefdescription}, Arg,_) -> Arg; +parse_param(#xmlElement{name=detaileddescription}, Arg,_) -> Arg; +parse_param(#xmlElement{name=inbodydescription}, Arg,_) -> Arg; +parse_param(#xmlElement{name=location}, Arg,_) -> Arg; +parse_param(Other, Arg,_) -> + io:format("Unhandled Param ~p ~n in ~p~n", [Other,Arg]), + ?error(unhandled_param). + +add_param(Arg0=#arg{type=T0}, Opts, F=#func{name=Name,params=Args}) -> + Arg = case T0 of +%% #type{mod=[const],ref={pointer,1},name="GLubyte"} -> +%% Arg0#arg{type=T0#type{base=binary}}; + #type{mod=[const]} -> Arg0; %% In is true default + #type{ref={pointer,_}} -> Arg0#arg{in=false, + type=T0#type{single=undefined}}; + _ -> Arg0 + end, + Patched = patch_param(Name,Arg,Opts), + F#func{params=[Patched|Args]}. + +patch_param(Method,P = #arg{name=ArgName},AllOpts) -> + %%io:format("~p ~n", [Method]), + case lookup(Method,AllOpts,undefined) of + undefined -> P; + What -> + %% io:format("~p ~p => ~p~n", [Method, ArgName, What]), + case What of + {ArgName,Fopt} when is_list(Fopt) -> + foldl(fun handle_arg_opt/2,P,Fopt); + {ArgName,Fopt} -> + handle_arg_opt(Fopt,P); + {_,_} -> P; + Opts when is_list(Opts) -> + case get_value(ArgName, Opts, undefined) of + undefined -> P; + List when is_list(List) -> + foldl(fun handle_arg_opt/2,P,List); + Val -> + handle_arg_opt(Val,P) + end + end + end. + +handle_arg_opt(skip, P) -> P#arg{where=c}; +%%handle_arg_opt(nowhere, P) -> P#arg{where=nowhere}; +%%handle_arg_opt(skip_member, _P) -> throw(skip_member); +handle_arg_opt(in, P) -> P#arg{in=true}; +handle_arg_opt(out, P) -> P#arg{in=false}; +handle_arg_opt(both, P) -> P#arg{in=both}; +handle_arg_opt(binary, P=#arg{type=T}) -> + P#arg{type=T#type{size=undefined,base=binary}}; +handle_arg_opt({binary,Sz}, P=#arg{type=T}) -> + P#arg{type=T#type{size=Sz,base=binary}}; +handle_arg_opt({type,Type}, P=#arg{type=T}) -> P#arg{type=T#type{name=Type}}; +handle_arg_opt({single,Opt},P=#arg{type=T}) -> P#arg{type=T#type{single=Opt}}; +handle_arg_opt({base,Opt}, P=#arg{type=T}) -> P#arg{type=T#type{base=Opt}}; +handle_arg_opt({c_only,Opt},P) -> P#arg{where=c, alt=Opt}. + +parse_type([], _Os) -> void; +parse_type(C, Os) -> + {Type,_Info} = foldl(fun extract_type_info/2,{[],undefined},C), + Empty = #type{}, + case parse_type2(reverse(Type),Empty,Os) of + Empty -> ?error({strange_type, Type}); + Assert -> Assert + end. + +extract_type_info(#xmlText{value=Value}, {Acc, Info}) -> + {reverse(foldl(fun extract_type_info2/2, [], + string:tokens(Value, " "))) ++ Acc, Info}; +extract_type_info(#xmlElement{name=ref,attributes=As, + content=[#xmlText{value=V}]}, + {Acc,undefined}) -> + {value, #xmlAttribute{value = Refid}} = + keysearch(refid,#xmlAttribute.name,As), + {value, #xmlAttribute{value = Kind}} = + keysearch(kindref,#xmlAttribute.name,As), + {reverse(foldl(fun extract_type_info2/2, [], + string:tokens(V, " "))) ++ Acc, + {Kind,Refid}}; +extract_type_info(What,Acc) -> + ?error({parse_error,What,Acc}). + +extract_type_info2("const",Acc) -> [const|Acc]; +extract_type_info2("*", [{by_ref,{pointer,N}}|Acc]) -> + [{by_ref,{pointer,N+1}}|Acc]; +extract_type_info2("*", Acc) -> [{by_ref,{pointer,1}}|Acc]; +extract_type_info2("**", Acc) -> [{by_ref,{pointer,2}}|Acc]; +extract_type_info2(Type, Acc) -> [Type|Acc]. + +parse_type2(["void"], _T, _Opts) -> void; +parse_type2([N="void"|R], T, Opts) -> + parse_type2(R,T#type{name=N},Opts); +parse_type2([const|R],T=#type{mod=Mod},Opts) -> + parse_type2(R,T#type{mod=[const|Mod]},Opts); +parse_type2(["unsigned"|R],T=#type{mod=Mod},Opts) -> + parse_type2(R,T#type{mod=[unsigned|Mod]},Opts); +parse_type2([N="GLenum"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=4, base=int},Opts); +parse_type2([N="GLboolean"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=1, base=bool},Opts); +parse_type2([N="GLbitfield"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=4, base=int},Opts); +parse_type2([N="GLvoid"|R],T,Opts) -> + parse_type2(R,T#type{name=N, base=idx_binary},Opts); + +parse_type2([N="GLbyte"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=1, base=int},Opts); +parse_type2([N="GLubyte"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=1, base=int},Opts); +parse_type2([N="GLshort"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=2, base=int},Opts); +parse_type2([N="GLushort"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=2, base=int},Opts); +parse_type2([N="GLint"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=4, base=int},Opts); +parse_type2([N="GLuint"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=4, base=int},Opts); +parse_type2([N="GLsizei"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=4, base=int},Opts); + +parse_type2([N="GLfloat"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=4,base=float},Opts); +parse_type2([N="GLdouble"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=8,base=float},Opts); +parse_type2([N="GLclampf"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=4,base=float},Opts); +parse_type2([N="GLclampd"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=8,base=float},Opts); +parse_type2([N="GLhandleARB"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=8,base=int},Opts); +parse_type2(["GLchar" ++ _ARB|R],T,Opts) -> + parse_type2(R,T#type{name="GLchar",size=1,base=string},Opts); +parse_type2(["GLUquadric"|R],T,Opts) -> + parse_type2(R,T#type{name="GLUquadric",size=8,base=int},Opts); +parse_type2(["GLintptr" ++ _ARB|R],T,Opts) -> + parse_type2(R,T#type{name="GLintptr",size=8,base=int},Opts); +parse_type2(["GLsizeiptr" ++ _ARB|R],T,Opts) -> + parse_type2(R,T#type{name="GLsizeiptr",size=8,base=int},Opts); + +parse_type2([{by_ref,Ref}|R],T,Opts) -> + parse_type2(R,T#type{ref=Ref,by_val=false},Opts); + +%% Let type errors be seen later because we don't know if these unhandled types +%% will be used. +parse_type2(_A = [Name|R],T,Opts) -> +%% io:format("unhandled ~p ~p ~n",[_A,T]), + New = T#type{name={unhandled,Name,get(current_func)}}, + parse_type2(R,New,Opts); +parse_type2([], T, _) -> T. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Function mangling %% + +setup(Defs,Opts) -> + {Fs0,Ds0} = + foldr(fun(F=#func{name=N},{Fs,Ds}) -> + case put(N,F) of + undefined -> + {[N|Fs],Ds}; + _ -> %% Duplicate + {Fs,Ds} + end; + (D=#def{}, {Fs,Ds}) -> + {Fs,[D|Ds]} + end, {[],[]}, Defs), + Fs = setup_functions(Fs0,Opts,[]), + erase(current_func), + %% Remove duplicates but keep order + {Ds,_} = foldl(fun(D=#def{name=Name},{Keep,Defined}) -> + case gb_sets:is_member(Name,Defined) of + true -> {Keep,Defined}; + false -> {[D|Keep],gb_sets:add(Name,Defined)} + end + end, {[],gb_sets:empty()}, Ds0), + {reverse(Ds),Fs}. + +setup_functions([F0|Defs],Opts,Acc) -> + put(current_func, F0), + {Name, Ext} = get_extension(F0,Opts), + %%io:format("~p = ~p + ~p~n", [F0, Name, Ext]), + Skip = (not keep(F0,Opts)) andalso (skip(F0,Opts) orelse skip(Ext,Opts)), + case Skip of + true -> + setup_functions(Defs,Opts,Acc); + false -> + case setup_extension(Name,Ext,Opts) of + skip -> + setup_functions(Defs,Opts,Acc); + New -> + setup_functions(Defs,Opts,[New|Acc]) + end + end; +setup_functions([],_, Acc) -> reverse(Acc). + +setup_extension(Name,"",Opts) -> + setup_vector_variant(Name,"",Opts); +setup_extension(Name,Ext,Opts) -> + case get(Name) of + undefined -> + setup_vector_variant(Name,Ext,Opts); + OrigF = #func{} -> + F = get(Name++Ext), + case is_equal(F,OrigF) of + true -> + put(Name, OrigF#func{ext={ext,Ext}}), + skip; + _ -> + setup_vector_variant(Name,Ext,Opts) + end + end. + +setup_vector_variant(Name,Ext,Opts) -> + case reverse(Name) of + [$v|NoVec] -> %% Hmm might be a vector version + RealName = reverse(NoVec,Ext), + case get(RealName) of + undefined -> + setup_idx_binary(Name,Ext,Opts); + Real = #func{} -> + verify_args(Name,Ext,Real,RealName,Opts) + end; + _ -> + setup_idx_binary(Name,Ext,Opts) + end. + +verify_args(Name,Ext,Real = #func{params=RAs},RealName,Opts) -> + FuncName = Name ++ Ext, + Vector = #func{params=Args} = get(FuncName), + case is_vector(Name,Opts) of + false -> + Check = fun(#arg{type=#type{name=Type}},Acc) -> + if Type =:= Acc -> Acc; + Acc =:= undefined -> Type; + true -> different + end + end, + case foldl(Check,undefined,RAs) of + different -> + setup_idx_binary(Name,Ext,Opts); + undefined -> + setup_idx_binary(Name,Ext,Opts); + _ when length(Args) =/= 1 -> + setup_idx_binary(Name,Ext,Opts); + _Type -> + put(FuncName,Vector#func{where=erl,alt={vector,0,RealName}}), + put(RealName,Real#func{alt={has_vector,0,FuncName}}), + Name++Ext + end; + VecPos -> + put(FuncName,Vector#func{where=erl,alt={vector,VecPos,RealName}}), + put(RealName,Real#func{alt={has_vector,VecPos,FuncName}}), + Name++Ext + end. + +is_vector(Name, Opts) -> + Vecs = get_value(vector, Opts, []), + lookup(Name, Vecs, false). + +lookup(Name,[{Vector, VecPos}|R],Def) when is_list(Vector) -> + case lists:prefix(Vector,Name) of + true -> + %% VecPos; + %%io:format("~s ~s => ~p ~n", [Vector,Name,VecPos]), + case Vector == Name of + true -> + VecPos; + false -> %% Look for exactly the correct Name + case lookup(Name,R,Def) of + Def -> VecPos; + Other -> Other + end + end; + false -> lookup(Name,R, Def) + end; +lookup(Name,[_|R],Def) -> + lookup(Name,R,Def); +lookup(_,[], Def) -> Def. + +setup_idx_binary(Name,Ext,_Opts) -> + FuncName = Name ++ Ext, + Func = #func{params=Args} = get(FuncName), + Id = next_id(function), + + %% Ok warn if single is undefined + lists:foreach(fun(#arg{type=#type{base=memory}}) -> ok; + (#arg{type=#type{base=idx_binary}}) -> ok; + (#arg{type=#type{name="GLUquadric"}}) -> ok; + (A=#arg{type=#type{single=undefined}}) -> + ?warning("~p Unknown size of~n ~p~n", + [get(current_func),A]), + io:format("{~p, {~p, }}.~n", + [get(current_func),A#arg.name]), + ok; + (_) -> ok + end, Args), + + case setup_idx_binary(Args, []) of + ignore -> + put(FuncName, Func#func{id=Id}), + Name++Ext; + {bin, A1,A2} -> + put(FuncName, Func#func{id=Id,params=A1}), + Extra = FuncName++"Bin", + put(Extra, Func#func{params=A2, id=next_id(function)}), + [FuncName,Extra]; + {matrix, A1,A2} -> + put(FuncName, Func#func{id=Id,params=A2}), + Extra = FuncName++"Matrix", + put(Extra, Func#func{where=erl, params=A1, id=Id}), + [FuncName,Extra] + end. + +setup_idx_binary([A=#arg{in=true,type=T=#type{base=idx_binary}}|R], Acc) -> + A1 = A#arg{type=T#type{base=guard_int,size=4}}, + A2 = A#arg{type=T#type{base=binary}}, + Head = reverse(Acc), + case setup_idx_binary(R, []) of + ignore -> + {bin, Head ++ [A1|R], Head ++ [A2|R]}; + {bin, R1,R2} -> + {bin, Head ++ [A1|R1], Head ++ [A2|R2]} + end; +setup_idx_binary([A=#arg{in=true,type=T=#type{single={tuple,matrix}}}|R], Acc) -> + A1 = A#arg{type=T#type{single={tuple, matrix12}}}, + A2 = A#arg{type=T#type{single={tuple, 16}}}, + Head = reverse(Acc), + case setup_idx_binary(R, []) of + ignore -> + {matrix, Head ++ [A1|R], Head ++ [A2|R]}; + {matrix, R1,R2} -> + {matrix, Head ++ [A1|R1], Head ++ [A2|R2]} + end; +setup_idx_binary([H|R],Acc) -> + setup_idx_binary(R,[H|Acc]); +setup_idx_binary([],_) -> ignore. + +is_equal(F1=#func{type=T1,params=A1},F2=#func{type=T2,params=A2}) -> + Equal = is_equal_type(T1,T2) andalso is_equal_args(A1,A2), + case Equal of + true -> ok; + false -> + %% io:format("A1: ~p~nA2: ~p~n",[A1,A2]), + ?warning("Skipped Ext Not Equal ~p ~p~n", + [F1#func.name,F2#func.name]) + end, + Equal. + +is_equal_args([],[]) -> true; +is_equal_args([_A1=#arg{type=T1}|A1s],[_A2=#arg{type=T2}|A2s]) -> + case is_equal_type(T1,T2) of + true -> is_equal_args(A1s,A2s); + false -> + %%io:format("Diff~n ~p~n ~p ~n~n", [_A1,_A2]), + false + end. + +is_equal_type(T,T) -> true; +is_equal_type(#type{name="GLcharARB"},#type{name="GLchar"}) -> true; +%%is_equal_type(#type{name="GLhandleARB"},#type{name="GLuint"}) -> true; +is_equal_type(#type{name="GLenum"},#type{name="GLuint"}) -> true; +is_equal_type(#type{name="GLenum"},#type{name="GLint"}) -> true; +is_equal_type(#type{base=idx_binary},#type{base=guard_int}) -> true; +is_equal_type(#type{base=idx_binary},#type{base=memory}) -> true; +is_equal_type(#type{single={tuple,matrix}},#type{single={tuple,matrix12}}) -> true; +is_equal_type(#type{base=B,single=S,name=N,size=Sz}, + #type{base=B,single=S,name=N,size=Sz}) -> true; +is_equal_type(_,_) -> false. + +skip(Name,Opts) -> + Skip = get_value(skip, Opts, []), + lists:any(fun(Prefix) -> lists:prefix(Prefix,Name) end, Skip). + +keep(Name,Opts) -> + Skip = get_value(keep, Opts, []), + lists:any(fun(Prefix) -> lists:prefix(Prefix,Name) end, Skip). + +get_extension(ExtName,_Opts) -> + case reverse(ExtName) of + "BRA" ++ Name -> {reverse(Name),"ARB"}; + "TXE" ++ Name -> {reverse(Name),"EXT"}; + "ASEM" ++ Name -> {reverse(Name),"MESA"}; + "ITA" ++ Name -> {reverse(Name),"ATI"}; + "DMA" ++ Name -> {reverse(Name),"AMD"}; + "VN" ++ Name -> {reverse(Name),"NV"}; %Nvidia + "ELPPA"++ Name -> {reverse(Name),"APPLE"}; + "LETNI"++ Name -> {reverse(Name),"INTEL"}; + "NUS" ++ Name -> {reverse(Name),"SUN"}; + "XNUS" ++ Name -> {reverse(Name),"SUNX"}; + "IGS" ++ Name -> {reverse(Name),"SGI"}; + "SIGS" ++ Name -> {reverse(Name),"SGIS"}; + "XIGS" ++ Name -> {reverse(Name),"SGIX"}; + "XFD3" ++ Name -> {reverse(Name),"3DFX"}; + "MBI" ++ Name -> {reverse(Name),"IBM"}; + "RGNI" ++ Name -> {reverse(Name),"INGR"}; + "IGP" ++ Name -> {reverse(Name),"PGI"}; + "PH" ++ Name -> {reverse(Name),"HP"}; + "YDEMERG" ++ Name -> {reverse(Name),"GREMEDY"}; + %%["" ++ Name] -> {Name; %% + _ -> {ExtName, ""} + end. + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +drop_empty(List) -> + filter(fun(#xmlText { value = Text}) -> + string:strip(Text) =/= ""; + (_)-> + true + end, List). + +name(Name, _Opts) -> Name. + +next_id(What) -> + Next = case get(What) of + undefined -> 5010; %% Opengl + N -> N+1 + end, + put(What, Next), + Next. |