~ubuntu-branches/debian/squeeze/erlang/squeeze

« back to all changes in this revision

Viewing changes to lib/wx/api_gen/gl_gen.erl

  • Committer: Bazaar Package Importer
  • Author(s): Sergei Golovan
  • Date: 2009-05-07 15:07:37 UTC
  • mfrom: (1.2.1 upstream) (5.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20090507150737-i4yb5elwinm7r0hc
Tags: 1:13.b-dfsg1-1
* Removed another bunch of non-free RFCs from original tarball
  (closes: #527053).
* Fixed build-dependencies list by adding missing comma. This requires
  libsctp-dev again. Also, added libsctp1 dependency to erlang-base and
  erlang-base-hipe packages because the shared library is loaded via
  dlopen now and cannot be added using dh_slibdeps (closes: #526682).
* Weakened dependency of erlang-webtool on erlang-observer to recommends
  to avoid circular dependencies (closes: #526627).
* Added solaris-i386 to HiPE enabled architectures.
* Made script sources in /usr/lib/erlang/erts-*/bin directory executable,
  which is more convenient if a user wants to create a target Erlang system.
* Shortened extended description line for erlang-dev package to make it
  fit 80x25 terminals.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
%%
 
2
%% %CopyrightBegin%
 
3
%% 
 
4
%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
 
5
%% 
 
6
%% The contents of this file are subject to the Erlang Public License,
 
7
%% Version 1.1, (the "License"); you may not use this file except in
 
8
%% compliance with the License. You should have received a copy of the
 
9
%% Erlang Public License along with this software. If not, it can be
 
10
%% retrieved online at http://www.erlang.org/.
 
11
%% 
 
12
%% Software distributed under the License is distributed on an "AS IS"
 
13
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 
14
%% the License for the specific language governing rights and limitations
 
15
%% under the License.
 
16
%% 
 
17
%% %CopyrightEnd%
 
18
%%
 
19
%%%-------------------------------------------------------------------
 
20
%%% File    : gl_gen.erl
 
21
%%% Author  : Dan Gudmundsson <dgud@erix.ericsson.se>
 
22
%%% Description : 
 
23
%%%
 
24
%%% Created : 16 Apr 2007 by Dan Gudmundsson <dgud@erix.ericsson.se>
 
25
%%%-------------------------------------------------------------------
 
26
-module(gl_gen).
 
27
 
 
28
-export([code/0]).
 
29
 
 
30
-include_lib("xmerl/include/xmerl.hrl").
 
31
-include("gl_gen.hrl").
 
32
 
 
33
-import(lists, [foldl/3,foldr/3,reverse/1,reverse/2,keysearch/3,map/2,filter/2]).
 
34
-import(proplists, [get_value/2,get_value/3]).
 
35
 
 
36
-import(gen_util,[uppercase_all/1]).
 
37
 
 
38
-compile(export_all).
 
39
 
 
40
code() ->  safe(fun gen_code/0,true).
 
41
 
 
42
devcode() -> spawn(fun() -> safe(fun gen_code/0,false) end).
 
43
 
 
44
safe(What, QuitOnErr) ->
 
45
    try 
 
46
        What(),
 
47
        io:format("Completed succesfully~n~n", []),
 
48
        QuitOnErr andalso gen_util:halt(0)
 
49
    catch Err:Reason ->
 
50
            catch gen_util:close(),
 
51
            io:format("Error ~p: ~p:~p~n  ~p~n", 
 
52
                      [get(current_func),Err,Reason,erlang:get_stacktrace()]),
 
53
            timer:sleep(1999),
 
54
            QuitOnErr andalso gen_util:halt(1)
 
55
    end.
 
56
 
 
57
gen_code() ->
 
58
    {ok, Opts0} = file:consult("glapi.conf"),
 
59
    erase(func_id),
 
60
    Opts = init_defs(Opts0),
 
61
    GLUDefs = parse_glu_defs(Opts),   
 
62
    GLDefs  = parse_gl_defs(Opts),    
 
63
    {GLUDefines,GLUFuncs} = setup(GLUDefs, Opts),
 
64
    {GLDefines,GLFuncs}   = setup(GLDefs, Opts),
 
65
    gl_gen_erl:glu_defines(GLUDefines),
 
66
    gl_gen_erl:glu_api(GLUFuncs),
 
67
 
 
68
    gl_gen_erl:gl_defines(GLDefines),
 
69
    gl_gen_erl:gl_api(GLFuncs),
 
70
    gl_gen_erl:gen_debug(GLFuncs,GLUFuncs),
 
71
    gl_gen_c:gen(GLFuncs,GLUFuncs),
 
72
    ok.
 
73
 
 
74
init_defs(Opts0) ->
 
75
    Opts0.
 
76
 
 
77
parse_glu_defs(Opts0) ->
 
78
    All = foldl(fun(File, Acc) -> load_file(File,Opts0,Acc) end, [], ["glu"]),
 
79
    reverse(All).
 
80
 
 
81
parse_gl_defs(Opts0) ->
 
82
    All = foldl(fun(File, Acc) -> load_file(File,Opts0,Acc) end, [], ["gl","glext"]),
 
83
    reverse(All).
 
84
 
 
85
load_file(FileName, Opts, Acc) ->
 
86
    File = filename:join(["gl_xml",FileName ++ "_8h.xml"]),
 
87
    put({loaded, FileName}, true),
 
88
    case xmerl_scan:file(File, [{space, normalize}]) of 
 
89
        {error, enoent} ->
 
90
            io:format("Skipped File not found ~p ~n", [File]),
 
91
            Acc;
 
92
        {Doc, _} ->
 
93
            io:format("Scanning ~p ~n", [File]),
 
94
            %% It's duplicated in xml get sectiondef only once.
 
95
            Content = find_data(Doc#xmlElement.content),
 
96
            lists:foreach(fun(D) -> extract_argnames(D) end, Content),
 
97
            foldl(fun(Data,Acc0) -> parse_file(Data, Opts, Acc0) end, 
 
98
                  Acc, Content)
 
99
    end.
 
100
 
 
101
extract_argnames(#xmlElement{name=memberdef,attributes=Attr,content=C}) ->
 
102
    case keysearch(kind, #xmlAttribute.name, Attr) of
 
103
        {value, #xmlAttribute{value = "typedef"}} -> 
 
104
            parse_typedef(C,undefined);
 
105
        _ ->
 
106
            ok
 
107
    end;
 
108
extract_argnames(_) -> ok.
 
109
    
 
110
parse_typedef([#xmlElement{name=argsstring,content=[#xmlText{value=AS}]}|R],_) -> 
 
111
    parse_typedef(R,AS);
 
112
parse_typedef([#xmlElement{name=name}|_],undefined) ->
 
113
    skip;
 
114
parse_typedef([#xmlElement{name=name,content=[#xmlText{value=N}]}|_],AS) ->
 
115
    Args0 = string:tokens(AS," ,()*[]"),
 
116
    try 
 
117
        Args = get_arg_names(Args0),
 
118
        put({typedef,string:strip(N)},Args)
 
119
    catch _:Where ->
 
120
            io:format("Error ~p: ~p ~p~n", [N,Args0,Where]),
 
121
            ?error(arg_names)
 
122
    end;
 
123
parse_typedef([_|R],AS) ->
 
124
    parse_typedef(R,AS);
 
125
parse_typedef([],_) -> skip.
 
126
 
 
127
get_arg_names(As0) ->
 
128
    Args = lists:filter(fun("const") -> false; (_) -> true end, As0),
 
129
    get_arg_names(Args, []).
 
130
 
 
131
get_arg_names([_Type,Name|R],Acc) ->
 
132
    get_arg_names(R, [Name|Acc]);
 
133
get_arg_names([],Acc) -> reverse(Acc);
 
134
get_arg_names(["void"],[]) -> [];
 
135
get_arg_names(Error,_Acc) -> exit(Error).
 
136
    
 
137
%% Avoid bugs in (old) doxygen..the new one doesn't have 'em
 
138
find_data([#xmlElement{name=compounddef, content=C}|_]) -> find_data(C);
 
139
find_data([#xmlElement{name=sectiondef, attributes=Attr, content=C}|R]) ->  
 
140
    case keysearch(kind, #xmlAttribute.name, Attr) of
 
141
        {value, _} -> %% The new one have func define typedef
 
142
            find_data(R) ++ C;
 
143
        false ->
 
144
            C
 
145
    end;
 
146
find_data([_Hmm|R]) -> 
 
147
%%     case _Hmm of 
 
148
%%      #xmlElement{} -> 
 
149
%%          io:format("0 ~p ~n",[_Hmm#xmlElement.name]);
 
150
%%      _ ->
 
151
%%          ok
 
152
%%     end,
 
153
    find_data(R);
 
154
find_data([]) -> [].
 
155
 
 
156
parse_file(#xmlElement{name=memberdef,attributes=Attr, content=C}, Opts, Acc) ->
 
157
    case keysearch(kind, #xmlAttribute.name, Attr) of
 
158
        {value, #xmlAttribute{value = "function"}} -> 
 
159
            try 
 
160
                Def = parse_func(C, Opts),
 
161
                [Def|Acc]
 
162
            catch throw:skip -> Acc
 
163
            after erase(current_func)
 
164
            end;
 
165
        {value, #xmlAttribute{value = "define"}} -> 
 
166
            try 
 
167
                Def = parse_define(C, #def{}, Opts),
 
168
                [Def|Acc]
 
169
            catch throw:skip -> Acc
 
170
            end;
 
171
        {value, #xmlAttribute{value = "typedef"}} -> 
 
172
            Acc;
 
173
        _W ->
 
174
            io:format("Hmm ~p~n",[_W]),
 
175
            Acc
 
176
    end;
 
177
parse_file(_Hmm,_,Acc) ->
 
178
    Acc.
 
179
 
 
180
parse_define([#xmlElement{name=name,content=[#xmlText{value="API" ++ _}]}|_],_Def,_Os) ->
 
181
    throw(skip);
 
182
parse_define([#xmlElement{name=name,content=[#xmlText{value="GLAPI"++_}]}|_],_Def,_Os) ->
 
183
    throw(skip);
 
184
parse_define([#xmlElement{name=name,content=[#xmlText{value="WINGDIAPI"++_}]}|_],_Def,_Os) ->
 
185
    throw(skip);
 
186
parse_define([#xmlElement{name=name,content=[#xmlText{value=Name}]}|R], Def, Os) ->
 
187
    parse_define(R, Def#def{name=Name}, Os);
 
188
parse_define([#xmlElement{name=initializer,content=[#xmlText{value=V}]}|_],Def,_Os) ->
 
189
    Val0 = string:strip(V),
 
190
    try 
 
191
        case Val0 of
 
192
            "0x" ++ Val1 -> 
 
193
                Val = http_util:hexlist_to_integer(Val1),
 
194
                Def#def{val=Val, type=hex};
 
195
            _ ->
 
196
                Val = list_to_integer(Val0),
 
197
                Def#def{val=Val, type=int}
 
198
        end
 
199
    catch _:_ -> 
 
200
            Def#def{val=Val0, type=string}
 
201
    end;
 
202
parse_define([_|R], D, Opts) ->
 
203
    parse_define(R, D, Opts);
 
204
parse_define([], D, _Opts) ->
 
205
    D.
 
206
 
 
207
parse_func(Xml, Opts) ->
 
208
    {Func,_} = foldl(fun(X,Acc) -> parse_func(X,Acc,Opts) end, {#func{},1}, Xml),
 
209
    #func{params=Args0,type=Type0} = Func,
 
210
    Args = filter(fun(#arg{type=void}) -> false; (_) -> true end, Args0),
 
211
    #arg{type=Type} = 
 
212
        patch_param(Func#func.name,#arg{name="result",type=Type0},Opts),
 
213
    Func#func{params=reverse(Args), type=Type}.
 
214
 
 
215
parse_func(#xmlElement{name=type, content=C}, {F,AC}, Os) ->
 
216
    Type = parse_type(drop_empty(C), Os),
 
217
    {F#func{type=Type},AC};
 
218
parse_func(#xmlElement{name=name, content=[#xmlText{value=C}]},{F,AC},Os) ->
 
219
    Func = string:strip(C),
 
220
    put(current_func, Func),
 
221
    {F#func{name=name(Func,Os)},AC};
 
222
parse_func(#xmlElement{name=param, content=C},{F,AC},Os) -> 
 
223
    Parse  = fun(Con, Ac) -> parse_param(Con, Ac, Os) end,
 
224
    Param0 = foldl(Parse, #arg{}, drop_empty(C)),
 
225
    Param = fix_param_name(Param0, F, AC),
 
226
    {add_param(Param, Os, F),AC+1};
 
227
parse_func(_, F,_) ->
 
228
    F.
 
229
 
 
230
fix_param_name(A=#arg{name=undefined,type=T},#func{name=Func},Count) ->
 
231
    TDName = "PFN" ++ uppercase_all(Func) ++ "PROC",
 
232
    case get({typedef,TDName}) of
 
233
        undefined when T == void ->
 
234
            A;
 
235
        undefined ->
 
236
            io:format("Didn't find typedef for: ~s~n", [TDName]),
 
237
            exit(aargh);
 
238
        AS ->
 
239
            try A#arg{name = lists:nth(Count, AS)} 
 
240
            catch _:_ -> A
 
241
            end
 
242
    end;
 
243
fix_param_name(A,_,_) -> A.
 
244
 
 
245
parse_param(#xmlElement{name=type,content=C}, Arg, Os) ->
 
246
    Arg#arg{type=parse_type(drop_empty(C),Os)};
 
247
parse_param(#xmlElement{name=declname,content=[C]},Arg,_Os) -> 
 
248
    #xmlText{value=Name} = C,
 
249
    Arg#arg{name=Name};
 
250
parse_param(#xmlElement{name=array,content=[#xmlText{value=C}]},
 
251
            Arg=#arg{type=Type0},_Os) ->
 
252
    try 
 
253
        [Int] = string:tokens(C, "[] "),
 
254
        Val = list_to_integer(Int),
 
255
        Arg#arg{type=Type0#type{single={tuple,Val}, by_val=true}}
 
256
    catch _:_ ->
 
257
            ?warning("Undefined Array size ~p in ~p ~p~n", 
 
258
                     [Arg, get(current_func), C]),
 
259
            Arg#arg{type=Type0#type{single={tuple,undefined}, by_val=true}}
 
260
    end;
 
261
            
 
262
%% Skip these
 
263
parse_param(#xmlElement{name=definition}, Arg, _) ->    Arg;
 
264
parse_param(#xmlElement{name=argsstring}, Arg,_) ->     Arg;
 
265
parse_param(#xmlElement{name=briefdescription}, Arg,_) ->     Arg;
 
266
parse_param(#xmlElement{name=detaileddescription}, Arg,_) ->  Arg;
 
267
parse_param(#xmlElement{name=inbodydescription}, Arg,_) ->    Arg;
 
268
parse_param(#xmlElement{name=location}, Arg,_) ->             Arg;
 
269
parse_param(Other, Arg,_) ->
 
270
    io:format("Unhandled Param ~p ~n in ~p~n", [Other,Arg]),
 
271
    ?error(unhandled_param).
 
272
 
 
273
add_param(Arg0=#arg{type=T0}, Opts, F=#func{name=Name,params=Args}) ->
 
274
    Arg = case T0 of 
 
275
%%            #type{mod=[const],ref={pointer,1},name="GLubyte"} -> 
 
276
%%                Arg0#arg{type=T0#type{base=binary}};
 
277
              #type{mod=[const]}     -> Arg0;   %% In is true default
 
278
              #type{ref={pointer,_}} -> Arg0#arg{in=false,
 
279
                                                 type=T0#type{single=undefined}};
 
280
              _ -> Arg0
 
281
          end,
 
282
    Patched = patch_param(Name,Arg,Opts),
 
283
    F#func{params=[Patched|Args]}.
 
284
 
 
285
patch_param(Method,P = #arg{name=ArgName},AllOpts) ->    
 
286
    case lookup(Method,AllOpts,undefined) of
 
287
        undefined -> P;
 
288
        What -> 
 
289
            %%io:format("~p ~p => ~p", [Method, ArgName, What]),
 
290
            case What of
 
291
                {ArgName,Fopt} when is_list(Fopt) ->
 
292
                    foldl(fun handle_arg_opt/2,P,Fopt);
 
293
                {ArgName,Fopt}  ->
 
294
                    handle_arg_opt(Fopt,P);
 
295
                {_,_} -> P;
 
296
                Opts when is_list(Opts) ->
 
297
                    case get_value(ArgName, Opts, undefined) of
 
298
                        undefined -> P;
 
299
                        List when is_list(List) -> 
 
300
                            foldl(fun handle_arg_opt/2,P,List);
 
301
                        Val -> 
 
302
                            handle_arg_opt(Val,P)
 
303
                    end
 
304
            end
 
305
    end.
 
306
 
 
307
handle_arg_opt(skip, P) -> P#arg{where=c};
 
308
%%handle_arg_opt(nowhere, P) -> P#arg{where=nowhere};
 
309
%%handle_arg_opt(skip_member, _P) -> throw(skip_member);
 
310
handle_arg_opt(in, P) -> P#arg{in=true};
 
311
handle_arg_opt(out, P) -> P#arg{in=false};
 
312
handle_arg_opt(both, P) -> P#arg{in=both};
 
313
handle_arg_opt(binary, P=#arg{type=T}) -> 
 
314
    P#arg{type=T#type{size=undefined,base=binary}};
 
315
handle_arg_opt({binary,Sz}, P=#arg{type=T}) -> 
 
316
    P#arg{type=T#type{size=Sz,base=binary}};
 
317
handle_arg_opt({type,Type}, P=#arg{type=T}) -> P#arg{type=T#type{name=Type}};
 
318
handle_arg_opt({single,Opt},P=#arg{type=T}) -> P#arg{type=T#type{single=Opt}};
 
319
handle_arg_opt({base,Opt},  P=#arg{type=T}) -> P#arg{type=T#type{base=Opt}};
 
320
handle_arg_opt({c_only,Opt},P) -> P#arg{where=c, alt=Opt}.
 
321
 
 
322
parse_type([], _Os) -> void;
 
323
parse_type(C, Os) -> 
 
324
    {Type,_Info} = foldl(fun extract_type_info/2,{[],undefined},C),
 
325
    Empty = #type{},
 
326
    case parse_type2(reverse(Type),Empty,Os) of
 
327
        Empty ->  ?error({strange_type, Type});
 
328
        Assert -> Assert
 
329
    end.
 
330
 
 
331
extract_type_info(#xmlText{value=Value}, {Acc, Info}) -> 
 
332
    {reverse(foldl(fun extract_type_info2/2, [], 
 
333
                   string:tokens(Value, " "))) ++ Acc, Info};
 
334
extract_type_info(#xmlElement{name=ref,attributes=As,
 
335
                              content=[#xmlText{value=V}]},
 
336
                  {Acc,undefined}) ->
 
337
    {value, #xmlAttribute{value = Refid}} = 
 
338
        keysearch(refid,#xmlAttribute.name,As),
 
339
    {value, #xmlAttribute{value = Kind}} = 
 
340
        keysearch(kindref,#xmlAttribute.name,As),
 
341
    {reverse(foldl(fun extract_type_info2/2, [], 
 
342
                   string:tokens(V, " "))) ++ Acc,
 
343
     {Kind,Refid}};
 
344
extract_type_info(What,Acc) ->
 
345
    ?error({parse_error,What,Acc}).
 
346
 
 
347
extract_type_info2("const",Acc) -> [const|Acc];
 
348
extract_type_info2("*", [{by_ref,{pointer,N}}|Acc]) -> 
 
349
    [{by_ref,{pointer,N+1}}|Acc];
 
350
extract_type_info2("*",   Acc) -> [{by_ref,{pointer,1}}|Acc];
 
351
extract_type_info2("**",  Acc) -> [{by_ref,{pointer,2}}|Acc];
 
352
extract_type_info2(Type,  Acc) -> [Type|Acc].
 
353
 
 
354
parse_type2(["void"],  _T, _Opts) ->  void;
 
355
parse_type2([N="void"|R],  T, Opts) ->  
 
356
    parse_type2(R,T#type{name=N},Opts);
 
357
parse_type2([const|R],T=#type{mod=Mod},Opts) -> 
 
358
    parse_type2(R,T#type{mod=[const|Mod]},Opts);
 
359
parse_type2(["unsigned"|R],T=#type{mod=Mod},Opts) -> 
 
360
    parse_type2(R,T#type{mod=[unsigned|Mod]},Opts);
 
361
parse_type2([N="GLenum"|R],T,Opts) -> 
 
362
    parse_type2(R,T#type{name=N, size=4, base=int},Opts);
 
363
parse_type2([N="GLboolean"|R],T,Opts) -> 
 
364
    parse_type2(R,T#type{name=N, size=1, base=bool},Opts);
 
365
parse_type2([N="GLbitfield"|R],T,Opts) -> 
 
366
    parse_type2(R,T#type{name=N, size=4, base=int},Opts);
 
367
parse_type2([N="GLvoid"|R],T,Opts) -> 
 
368
    parse_type2(R,T#type{name=N, base=idx_binary},Opts);
 
369
 
 
370
parse_type2([N="GLbyte"|R],T,Opts) -> 
 
371
    parse_type2(R,T#type{name=N, size=1, base=int},Opts);
 
372
parse_type2([N="GLubyte"|R],T,Opts) -> 
 
373
    parse_type2(R,T#type{name=N, size=1, base=int},Opts);
 
374
parse_type2([N="GLshort"|R],T,Opts) -> 
 
375
    parse_type2(R,T#type{name=N, size=2, base=int},Opts);
 
376
parse_type2([N="GLushort"|R],T,Opts) -> 
 
377
    parse_type2(R,T#type{name=N, size=2, base=int},Opts);
 
378
parse_type2([N="GLint"|R],T,Opts) -> 
 
379
    parse_type2(R,T#type{name=N, size=4, base=int},Opts);
 
380
parse_type2([N="GLuint"|R],T,Opts) -> 
 
381
    parse_type2(R,T#type{name=N, size=4, base=int},Opts);
 
382
parse_type2([N="GLsizei"|R],T,Opts) -> 
 
383
    parse_type2(R,T#type{name=N, size=4, base=int},Opts);
 
384
 
 
385
parse_type2([N="GLfloat"|R],T,Opts) -> 
 
386
    parse_type2(R,T#type{name=N, size=4,base=float},Opts);
 
387
parse_type2([N="GLdouble"|R],T,Opts) -> 
 
388
    parse_type2(R,T#type{name=N, size=8,base=float},Opts);
 
389
parse_type2([N="GLclampf"|R],T,Opts) -> 
 
390
    parse_type2(R,T#type{name=N, size=4,base=float},Opts);
 
391
parse_type2([N="GLclampd"|R],T,Opts) -> 
 
392
    parse_type2(R,T#type{name=N, size=8,base=float},Opts);
 
393
parse_type2([N="GLhandleARB"|R],T,Opts) -> %% unsigned int normally (in glext.h) but 
 
394
    parse_type2(R,T#type{name=N, size=4,base=int},Opts); %% is void * on Mac!! FIXME
 
395
parse_type2(["GLchar" ++ _ARB|R],T,Opts) -> 
 
396
    parse_type2(R,T#type{name="GLchar",size=1,base=string},Opts);
 
397
parse_type2(["GLintptr" ++ _ARB|R],T,Opts) -> 
 
398
    parse_type2(R,T#type{name="GLintptr",size=8,base=int},Opts);
 
399
parse_type2(["GLsizeiptr" ++ _ARB|R],T,Opts) -> 
 
400
    parse_type2(R,T#type{name="GLsizeiptr",size=8,base=int},Opts);
 
401
 
 
402
parse_type2([{by_ref,Ref}|R],T,Opts) -> 
 
403
    parse_type2(R,T#type{ref=Ref,by_val=false},Opts);
 
404
 
 
405
%% Let type errors be seen later because we don't know if these unhandled types
 
406
%% will be used.
 
407
parse_type2(_A = [Name|R],T,Opts) ->
 
408
%%    io:format("unhandled ~p ~p ~n",[_A,T]),
 
409
    New = T#type{name={unhandled,Name,get(current_func)}},
 
410
    parse_type2(R,New,Opts);
 
411
parse_type2([], T, _) -> T.
 
412
 
 
413
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
414
%% Function mangling                         %%
 
415
 
 
416
setup(Defs,Opts) ->
 
417
    {Fs0,Ds0} = 
 
418
        foldr(fun(F=#func{name=N},{Fs,Ds}) ->  
 
419
                      case put(N,F) of
 
420
                          undefined ->
 
421
                              {[N|Fs],Ds};
 
422
                          _ ->  %% Duplicate
 
423
                              {Fs,Ds}
 
424
                      end;
 
425
                 (D=#def{}, {Fs,Ds}) ->
 
426
                      {Fs,[D|Ds]}
 
427
              end, {[],[]}, Defs),
 
428
    Fs = setup_functions(Fs0,Opts,[]),
 
429
    erase(current_func),
 
430
    %% Remove duplicates but keep order
 
431
    {Ds,_} = foldl(fun(D=#def{name=Name},{Keep,Defined}) ->
 
432
                           case gb_sets:is_member(Name,Defined) of
 
433
                               true -> {Keep,Defined};
 
434
                               false -> {[D|Keep],gb_sets:add(Name,Defined)}
 
435
                           end
 
436
                   end, {[],gb_sets:empty()}, Ds0),
 
437
    {reverse(Ds),Fs}.
 
438
 
 
439
setup_functions([F0|Defs],Opts,Acc) ->
 
440
    put(current_func, F0),
 
441
    {Name, Ext} = get_extension(F0,Opts),
 
442
    %%io:format("~p = ~p + ~p~n", [F0, Name, Ext]),
 
443
    Skip = (not keep(F0,Opts)) andalso (skip(F0,Opts) orelse skip(Ext,Opts)),
 
444
    case Skip of
 
445
        true ->
 
446
            setup_functions(Defs,Opts,Acc);
 
447
        false -> 
 
448
            case setup_extension(Name,Ext,Opts) of
 
449
                skip -> 
 
450
                    setup_functions(Defs,Opts,Acc);
 
451
                New  -> 
 
452
                    setup_functions(Defs,Opts,[New|Acc])
 
453
            end
 
454
    end;
 
455
setup_functions([],_, Acc) -> reverse(Acc).
 
456
 
 
457
setup_extension(Name,"",Opts) ->
 
458
    setup_vector_variant(Name,"",Opts);
 
459
setup_extension(Name,Ext,Opts) ->
 
460
    case get(Name) of
 
461
        undefined ->
 
462
            setup_vector_variant(Name,Ext,Opts);
 
463
        OrigF = #func{} ->
 
464
            F = get(Name++Ext),
 
465
            case is_equal(F,OrigF) of
 
466
                true ->
 
467
                    put(Name, OrigF#func{ext={ext,Ext}}),
 
468
                    skip;
 
469
                _ -> 
 
470
                    setup_vector_variant(Name,"",Opts)
 
471
            end
 
472
    end.
 
473
 
 
474
setup_vector_variant(Name,Ext,Opts) ->
 
475
    case reverse(Name) of
 
476
        [$v|NoVec] -> %% Hmm might be a vector version
 
477
            RealName = reverse(NoVec,Ext),
 
478
            case get(RealName) of
 
479
                undefined -> 
 
480
                    setup_idx_binary(Name,Ext,Opts);
 
481
                Real = #func{} -> 
 
482
                    verify_args(Name,Ext,Real,RealName,Opts)
 
483
            end;
 
484
        _ ->
 
485
            setup_idx_binary(Name,Ext,Opts)
 
486
    end.
 
487
 
 
488
verify_args(Name,Ext,Real = #func{params=RAs},RealName,Opts) ->
 
489
    FuncName = Name ++ Ext,
 
490
    Vector = #func{params=Args} = get(FuncName),
 
491
    case is_vector(Name,Opts) of
 
492
        false ->
 
493
            Check = fun(#arg{type=#type{name=Type}},Acc) ->
 
494
                            if Type =:= Acc -> Acc;
 
495
                               Acc =:= undefined -> Type;
 
496
                               true -> different
 
497
                            end
 
498
                    end,
 
499
            case foldl(Check,undefined,RAs) of
 
500
                different ->
 
501
                    setup_idx_binary(Name,Ext,Opts);
 
502
                undefined ->
 
503
                    setup_idx_binary(Name,Ext,Opts);
 
504
                _ when length(Args) =/= 1 -> 
 
505
                    setup_idx_binary(Name,Ext,Opts);
 
506
                _Type ->
 
507
                    put(FuncName,Vector#func{where=erl,alt={vector,0,RealName}}),
 
508
                    put(RealName,Real#func{alt={has_vector,0,FuncName}}),
 
509
                    Name++Ext
 
510
            end;
 
511
        VecPos ->
 
512
            put(FuncName,Vector#func{where=erl,alt={vector,VecPos,RealName}}),
 
513
            put(RealName,Real#func{alt={has_vector,VecPos,FuncName}}),
 
514
            Name++Ext
 
515
    end.
 
516
 
 
517
is_vector(Name, Opts) ->
 
518
    Vecs = get_value(vector, Opts, []),
 
519
    lookup(Name, Vecs, false).
 
520
 
 
521
lookup(Name,[{Vector, VecPos}|R],Def) when is_list(Vector) ->
 
522
    case lists:prefix(Vector,Name) of
 
523
        true -> 
 
524
            %%io:format("~s ~s => ~p ~n", [Vector,Name,VecPos]),
 
525
            VecPos;
 
526
        false -> lookup(Name,R, Def)
 
527
    end;
 
528
lookup(Name,[_|R],Def) ->
 
529
    lookup(Name,R,Def);
 
530
lookup(_,[], Def) -> Def.
 
531
    
 
532
setup_idx_binary(Name,Ext,_Opts) ->
 
533
    FuncName = Name ++ Ext,
 
534
    Func = #func{params=Args} = get(FuncName),
 
535
    Id = next_id(function),
 
536
 
 
537
    %% Ok warn if single is undefined
 
538
    lists:foreach(fun(#arg{type=#type{base=memory}}) -> ok;
 
539
                     (#arg{type=#type{base=idx_binary}}) -> ok;
 
540
                     (A=#arg{type=#type{single=undefined}}) -> 
 
541
                          ?warning("~p Unknown size of~n ~p~n",
 
542
                                   [get(current_func),A]),
 
543
                          io:format("{~p, {~p, }}.~n",
 
544
                                    [get(current_func),A#arg.name]),
 
545
                          ok;
 
546
                     (_) -> ok
 
547
                  end, Args),
 
548
 
 
549
    case setup_idx_binary(Args, []) of
 
550
        ignore -> 
 
551
            put(FuncName, Func#func{id=Id}),
 
552
            Name++Ext;
 
553
        {A1,A2} ->
 
554
            put(FuncName, Func#func{id=Id,params=A1}),
 
555
            Extra = FuncName++"Bin",
 
556
            put(Extra, Func#func{params=A2, id=next_id(function)}),
 
557
            [FuncName,Extra]
 
558
    end.
 
559
 
 
560
setup_idx_binary([A=#arg{in=true,type=T=#type{base=idx_binary}}|R], Acc) ->
 
561
    A1 = A#arg{type=T#type{base=guard_int,size=4}},
 
562
    A2 = A#arg{type=T#type{base=binary}},
 
563
    Head = reverse(Acc),
 
564
    case setup_idx_binary(R, []) of
 
565
        ignore -> 
 
566
            {Head ++ [A1|R], Head ++ [A2|R]};
 
567
        {R1,R2} ->
 
568
            {Head ++ [A1|R1], Head ++ [A2|R2]}
 
569
    end;
 
570
setup_idx_binary([H|R],Acc) -> 
 
571
    setup_idx_binary(R,[H|Acc]);
 
572
setup_idx_binary([],_) -> ignore.
 
573
    
 
574
is_equal(F1=#func{type=T1,params=A1},F2=#func{type=T2,params=A2}) ->
 
575
    Equal = is_equal_type(T1,T2) andalso is_equal_args(A1,A2),
 
576
    case Equal of
 
577
        true -> ok;
 
578
        false ->
 
579
            ?warning("Skipped Ext Not Equal ~p ~p~n", 
 
580
                     [F1#func.name,F2#func.name])
 
581
    end,
 
582
    Equal.
 
583
 
 
584
is_equal_args([],[]) -> true;
 
585
is_equal_args([_A1=#arg{type=T1}|A1s],[_A2=#arg{type=T2}|A2s]) -> 
 
586
    case is_equal_type(T1,T2) of
 
587
        true -> is_equal_args(A1s,A2s);
 
588
        false ->
 
589
            io:format("Diff~n ~p~n ~p ~n~n", [_A1,_A2]),
 
590
            false
 
591
    end.
 
592
 
 
593
is_equal_type(T,T) -> true;
 
594
is_equal_type(#type{name="GLcharARB"},#type{name="GLchar"}) -> true;
 
595
is_equal_type(#type{name="GLhandleARB"},#type{name="GLuint"}) -> true;
 
596
is_equal_type(#type{name="GLenum"},#type{name="GLuint"}) -> true;
 
597
is_equal_type(#type{name="GLenum"},#type{name="GLint"}) -> true;
 
598
is_equal_type(#type{base=idx_binary},#type{base=guard_int}) -> true;
 
599
is_equal_type(#type{base=idx_binary},#type{base=memory}) -> true;
 
600
is_equal_type(#type{base=B,single=S,name=N,size=Sz},
 
601
              #type{base=B,single=S,name=N,size=Sz}) -> true;
 
602
is_equal_type(_,_) -> false.
 
603
 
 
604
skip(Name,Opts) ->
 
605
    Skip = get_value(skip, Opts, []),
 
606
    lists:any(fun(Prefix) -> lists:prefix(Prefix,Name) end, Skip).
 
607
 
 
608
keep(Name,Opts) ->
 
609
    Skip = get_value(keep, Opts, []),
 
610
    lists:any(fun(Prefix) -> lists:prefix(Prefix,Name) end, Skip).
 
611
 
 
612
get_extension(ExtName,_Opts) ->
 
613
    case reverse(ExtName) of
 
614
        "BRA"  ++ Name -> {reverse(Name),"ARB"};
 
615
        "TXE"  ++ Name -> {reverse(Name),"EXT"};
 
616
        "ASEM" ++ Name -> {reverse(Name),"MESA"};
 
617
        "ITA"  ++ Name -> {reverse(Name),"ATI"};
 
618
        "VN"   ++ Name -> {reverse(Name),"NV"}; %Nvidia
 
619
        "ELPPA"++ Name -> {reverse(Name),"APPLE"};
 
620
        "LETNI"++ Name -> {reverse(Name),"INTEL"};
 
621
        "NUS"  ++ Name -> {reverse(Name),"SUN"};
 
622
        "XNUS" ++ Name -> {reverse(Name),"SUNX"};
 
623
        "IGS"  ++ Name -> {reverse(Name),"SGI"};
 
624
        "SIGS" ++ Name -> {reverse(Name),"SGIS"};
 
625
        "XIGS" ++ Name -> {reverse(Name),"SGIX"};
 
626
        "XFD3" ++ Name -> {reverse(Name),"3DFX"};
 
627
        "MBI"  ++ Name -> {reverse(Name),"IBM"};
 
628
        "RGNI" ++ Name -> {reverse(Name),"INGR"};
 
629
        "IGP"  ++ Name -> {reverse(Name),"PGI"};
 
630
        "PH"   ++ Name -> {reverse(Name),"HP"};
 
631
        "YDEMERG" ++ Name -> {reverse(Name),"GREMEDY"};
 
632
        %%["" ++ Name] ->     {Name;  %%
 
633
        _ -> {ExtName, ""}
 
634
    end.
 
635
                    
 
636
 
 
637
 
 
638
 
 
639
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
640
 
 
641
drop_empty(List) ->
 
642
    filter(fun(#xmlText { value = Text}) ->                
 
643
                   string:strip(Text) =/= "";
 
644
              (_)->
 
645
                   true
 
646
           end, List).
 
647
 
 
648
name(Name, _Opts) -> Name.
 
649
 
 
650
next_id(What) ->
 
651
    Next = case get(What) of
 
652
               undefined -> 5001;  %% Opengl 
 
653
               N -> N+1
 
654
           end,
 
655
    put(What, Next),
 
656
    Next.