aboutsummaryrefslogtreecommitdiffstats
path: root/lib/wx/api_gen/gl_gen.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/wx/api_gen/gl_gen.erl')
-rw-r--r--lib/wx/api_gen/gl_gen.erl687
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.