Add weak functions
[ocl-icd] / icd_generator.rb
1 =begin
2 Copyright (c) 2012, Brice Videau <brice.videau@imag.fr>
3 All rights reserved.
4       
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7     
8 1. Redistributions of source code must retain the above copyright notice, this
9    list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11    this list of conditions and the following disclaimer in the documentation
12    and/or other materials provided with the distribution.
13         
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 =end
25
26 require 'yaml'
27
28 class Hash
29     def to_yaml( opts = {} )
30         YAML::quick_emit( self, opts ) do |out|
31             out.map( taguri, to_yaml_style ) do |map|
32                 sort.each do |k, v|
33                     map.add( k, v )
34                 end
35             end
36         end
37     end
38 end
39
40
41 module IcdGenerator
42   $api_entries = {}
43   $api_entries_array = []
44   $cl_objects = ["platform_id", "device_id", "context", "command_queue", "mem", "program", "kernel", "event", "sampler"]
45   $known_entries= { 1 => "clGetPlatformInfo", 0 => "clGetPlatformIDs" }
46   $forbidden_funcs = ["clGetPlatformInfo", "clUnloadCompiler", "clGetExtensionFunctionAddress","clGetPlatformIDs" ]
47   $noweak_funcs = ["clWaitForEvents", "clCreateContextFromType", "clCreateContext" ]
48   $header_files = ["/usr/include/CL/cl.h", "/usr/include/CL/cl_gl.h", "/usr/include/CL/cl_ext.h", "/usr/include/CL/cl_gl_ext.h"]
49 #  $header_files = ["./cl.h", "./cl_gl.h", "./cl_ext.h", "./cl_gl_ext.h"]
50   $buff=20
51   $license = <<EOF
52 Copyright (c) 2012, Brice Videau <brice.videau@imag.fr>
53 All rights reserved.
54       
55 Redistribution and use in source and binary forms, with or without
56 modification, are permitted provided that the following conditions are met:
57     
58 1. Redistributions of source code must retain the above copyright notice, this
59    list of conditions and the following disclaimer.
60 2. Redistributions in binary form must reproduce the above copyright notice,
61    this list of conditions and the following disclaimer in the documentation
62    and/or other materials provided with the distribution.
63         
64 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
65 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
66 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
67 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
68 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
69 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
70 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
71 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
72 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
73 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
74
75 Do not edit this file. It is automatically generated.
76 EOF
77
78   def self.parse_headers
79     api_entries = []
80     $header_files.each{ |fname|
81       f = File::open(fname)
82       doc = f.read
83       api_entries += doc.scan(/CL_API_ENTRY.*?;/m).reject {|item| item.match("KHR")}
84       f.close
85     }
86     api_entries.each{ |entry|
87 #      puts entry
88       begin 
89         entry_name = entry.match(/CL_API_CALL(.*?)\(/m)[1].strip
90         next if entry_name.match('\*')
91         next if entry_name.match("INTEL")
92         next if entry_name.match("APPLE")
93         $api_entries[entry_name] = entry
94        
95       rescue
96         entry_name = entry.match(/(\S*?)\(/m)[1].strip
97         next if entry_name.match('\*')
98         next if entry_name.match("INTEL")
99         next if entry_name.match("APPLE")
100         $api_entries[entry_name] = entry
101       end
102     }
103 #    $api_entries.each{ |key, value|
104 #      puts "#{key}: #{value}"
105 #    }
106   end
107
108   def self.include_headers
109     headers =""
110     $header_files.each { |h|
111       headers += "#include \"#{h}\"\n"
112     }
113     return headers
114   end
115   def self.generate_ocl_icd_header
116     ocl_icd_header = "/**\n#{$license}\n*/\n"
117     ocl_icd_header +=  "#include <CL/opencl.h>\n"
118     ocl_icd_header += self.include_headers
119     ocl_icd_header +=  "struct _cl_icd_dispatch {\n"
120     $api_entries.each_value { |entry|
121       ocl_icd_header += entry.sub(/CL_API_CALL(.*?)\(/m,'(CL_API_CALL*\1)(').gsub("\r","") + "\n"
122     }
123     $buff.times {|i|
124       ocl_icd_header += "void (* dummyFunc#{i})(void) ;\n"
125     }
126     return ocl_icd_header += "};\n"
127   end
128
129   def self.generate_ocl_icd_header_final
130     ocl_icd_header = "/**\n#{$license}\n*/\n"
131     ocl_icd_header += "#define CL_USE_DEPRECATED_OPENCL_1_0_APIS\n"
132     ocl_icd_header += "#define CL_USE_DEPRECATED_OPENCL_1_1_APIS\n"
133     ocl_icd_header += "#include <CL/opencl.h>\n"
134     ocl_icd_header += self.include_headers
135     ocl_icd_header += "struct _cl_icd_dispatch {\n"
136     $api_entries_array.each { |entry|
137       ocl_icd_header += entry.sub(/CL_API_CALL(.*?)\(/m,'(CL_API_CALL*\1)(').gsub("\r","") + "\n"
138     }
139     ocl_icd_header += "};\n"
140     ocl_icd_header += "extern struct _cl_icd_dispatch master_dispatch;\n"
141     $cl_objects.each { |o|
142       ocl_icd_header += "struct _cl_#{o} { struct _cl_icd_dispatch *dispatch; };\n"
143     }
144     return ocl_icd_header
145   end
146
147   def self.generate_ocl_icd_source
148     ocl_icd_source = "/**\n#{$license}\n*/\n"
149     ocl_icd_source += "#include \"ocl_icd.h\"\n"
150     ocl_icd_source += "struct _cl_icd_dispatch master_dispatch = {\n"
151     ($api_entries.length+$buff-1).times { |i|
152       if( $known_entries[i] ) then 
153         ocl_icd_source += "  #{$known_entries[i]},\n"
154       else
155         ocl_icd_source += "  (void *) NULL,\n"
156       end
157     }
158     if( $known_entries[$api_entries.length+$buff-1] ) then
159       ocl_icd_source += "  #{$known_entries[i]}\n"
160     else
161       ocl_icd_source += "  (void *) NULL\n"
162     end
163     ocl_icd_source += "};\n"
164     ocl_icd_source += <<EOF
165
166 CL_API_ENTRY cl_int CL_API_CALL clIcdGetPlatformIDsKHR(  
167              cl_uint num_entries, 
168              cl_platform_id *platforms,
169              cl_uint *num_platforms) {
170   if( platforms == NULL && num_platforms == NULL )
171     return CL_INVALID_VALUE;
172   if( num_entries == 0 && platforms != NULL )
173     return CL_INVALID_VALUE;
174 #error You have to fill the commented lines with corresponding variables from your library
175 //  if( your_number_of_platforms == 0)
176 //    return CL_PLATFORM_NOT_FOUND_KHR;
177 //  if( num_platforms != NULL )
178 //    *num_platforms = your_number_of_platforms;
179   if( platforms != NULL ) {
180     cl_uint i;
181 //    for( i=0; i<(your_number_of_platforms<num_entries?your_number_of_platforms:num_entries); i++)
182 //      platforms[i] = &your_platforms[i];
183   }
184   return CL_SUCCESS;
185 }
186
187 CL_API_ENTRY void * CL_API_CALL clGetExtensionFunctionAddress(
188              const char *   func_name) CL_API_SUFFIX__VERSION_1_0 {
189 #error You have to fill this function with your extensions of incorporate these lines in your version
190   if( func_name != NULL &&  strcmp("clIcdGetPlatformIDsKHR", func_name) == 0 )
191     return (void *)clIcdGetPlatformIDsKHR;
192   return NULL;
193 }
194 CL_API_ENTRY cl_int CL_API_CALL clGetPlatformInfo(
195              cl_platform_id   platform, 
196              cl_platform_info param_name,
197              size_t           param_value_size, 
198              void *           param_value,
199              size_t *         param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 {
200 #error You ahve to fill this function with your information or assert that your version responds to CL_PLATFORM_ICD_SUFFIX_KHR
201 //  char cl_platform_profile[] = "FULL_PROFILE";
202 //  char cl_platform_version[] = "OpenCL 1.1";
203 //  char cl_platform_name[] = "DummyCL";
204 //  char cl_platform_vendor[] = "LIG";
205 //  char cl_platform_extensions[] = "cl_khr_icd";
206 //  char cl_platform_icd_suffix_khr[] = "DUMMY";
207   size_t size_string;
208   char * string_p;
209   if( platform != NULL ) {
210     int found = 0;
211     int i;
212     for(i=0; i<num_master_platforms; i++) {
213       if( platform == &master_platforms[i] )
214         found = 1;
215     }
216     if(!found)
217       return CL_INVALID_PLATFORM;
218   }
219   switch ( param_name ) {
220     case CL_PLATFORM_PROFILE:
221       string_p = cl_platform_profile;
222       size_string = sizeof(cl_platform_profile);
223       break;
224     case CL_PLATFORM_VERSION:
225       string_p = cl_platform_version;
226       size_string = sizeof(cl_platform_version);
227       break;
228     case CL_PLATFORM_NAME:
229       string_p = cl_platform_name;
230       size_string = sizeof(cl_platform_name);
231       break;
232     case CL_PLATFORM_VENDOR:
233       string_p = cl_platform_vendor;
234       size_string = sizeof(cl_platform_vendor);
235       break;
236     case CL_PLATFORM_EXTENSIONS:
237       string_p = cl_platform_extensions;
238       size_string = sizeof(cl_platform_extensions);
239       break;
240     case CL_PLATFORM_ICD_SUFFIX_KHR:
241       string_p = cl_platform_icd_suffix_khr;
242       size_string = sizeof(cl_platform_icd_suffix_khr);
243       break;
244     default:
245       return CL_INVALID_VALUE;
246       break;
247   }
248   if( param_value != NULL ) {
249     if( size_string > param_value_size )
250       return CL_INVALID_VALUE;
251     memcpy(param_value, string_p, size_string);
252   }
253   if( param_value_size_ret != NULL )
254     *param_value_size_ret = size_string;
255   return CL_SUCCESS;
256 }
257 EOF
258     return ocl_icd_source
259   end
260  
261   def self.generate_ocl_icd_dummy_header
262     ocl_icd_dummy_header = "/**\n#{$license}\n*/\n"
263     ocl_icd_dummy_header += "#include <CL/opencl.h>\n"
264     ocl_icd_dummy_header += "#include \"ocl_icd_h_dummy.h\"\n"
265     ($api_entries.length+$buff).times { |i|
266       ocl_icd_dummy_header += "void dummyFunc#{i}(void);\n"
267     }
268     ocl_icd_dummy_header += "struct _cl_icd_dispatch master_dispatch = {\n"
269     ($api_entries.length+$buff-1).times { |i|
270       if( $known_entries[i] ) then 
271         ocl_icd_dummy_header += "  (void *)& #{$known_entries[i]},\n"
272       else
273         ocl_icd_dummy_header += "  (void *)& dummyFunc#{i},\n"
274       end
275     }
276     if( $known_entries[$api_entries.length+$buff-1] ) then
277       cl_icd_dummy_header += "  (void *)& #{$known_entries[$api_entries.length+$buff-1]}\n"
278     else
279       ocl_icd_dummy_header += "  (void *)& dummyFunc#{$api_entries.length+$buff-1}\n"
280     end
281     ocl_icd_dummy_header += "};\n"
282     $cl_objects.each { |o|
283       ocl_icd_dummy_header += "struct _cl_#{o} { struct _cl_icd_dispatch *dispatch; };\n"
284       ocl_icd_dummy_header += "struct _cl_#{o} master_#{o} = { &master_dispatch };\n"
285     }
286     return ocl_icd_dummy_header
287   end
288  
289   def self.generate_ocl_icd_lib_source
290     forbidden_funcs = $forbidden_funcs[2..-1]
291     ocl_icd_lib_source = "/**\n#{$license}\n*/\n"
292     ocl_icd_lib_source += "#include \"ocl_icd.h\"\n"
293     ocl_icd_lib_source += ""
294     $api_entries.each { |func_name, entry|
295       next if forbidden_funcs.include?(func_name)
296       clean_entry = entry.sub(/(.*\)).*/m,'\1').gsub("/*","").gsub("*/","").gsub("\r","") + "{\n"
297       parameters = clean_entry.match(/\(.*\)/m)[0][1..-2]
298       parameters.gsub!(/\[.*?\]/,"")
299       parameters.sub!(/\(.*?\*\s*(.*?)\)\s*\(.*?\)/,'\1')
300       ocl_icd_lib_source += clean_entry.gsub(/\[.*?\]/,"")
301       if func_name == "clCreateContext" then
302         ocl_icd_lib_source += <<EOF
303   cl_uint i=0;
304   if( properties != NULL){
305     while( properties[i] != 0 ) {
306       if( properties[i] == CL_CONTEXT_PLATFORM )
307         return ((struct _cl_platform_id *) properties[i+1])->dispatch->clCreateContext(properties, num_devices, devices, pfn_notify, user_data, errcode_ret);
308       i += 2;
309     }
310   }
311   if(devices == NULL || num_devices == 0) {
312     *errcode_ret = CL_INVALID_VALUE;
313     return NULL;
314   }
315   return ((struct _cl_device_id *)devices[0])->dispatch->clCreateContext(properties, num_devices, devices, pfn_notify, user_data, errcode_ret);
316 EOF
317       elsif func_name == "clCreateContextFromType" then
318         ocl_icd_lib_source += <<EOF
319   cl_uint i=0;
320   if( properties != NULL){
321     while( properties[i] != 0 ) {
322       if( properties[i] == CL_CONTEXT_PLATFORM )
323         return ((struct _cl_platform_id *) properties[i+1])->dispatch->clCreateContextFromType(properties, device_type, pfn_notify, user_data, errcode_ret);
324       i += 2;
325     }
326   }
327   *errcode_ret = CL_INVALID_PLATFORM;
328   return NULL;
329 EOF
330       elsif func_name == "clWaitForEvents" then
331         ocl_icd_lib_source += <<EOF
332   if( num_events == 0 || event_list == NULL )
333     return CL_INVALID_VALUE;
334   return ((struct _cl_event *)event_list[0])->dispatch->clWaitForEvents(num_events, event_list);
335 EOF
336       elsif func_name == "clUnloadCompiler" then
337         ocl_icd_lib_source += <<EOF
338   return CL_SUCCESS;
339 EOF
340       else
341         first_parameter = parameters.match(/.*?\,/m)
342         if not first_parameter then
343           first_parameter =  parameters.match(/.*/m)[0]
344         else
345           first_parameter = first_parameter[0][0..-2]
346         end
347         fps = first_parameter.split
348         ocl_icd_lib_source += "return ((struct _#{fps[0]} *)#{fps[1]})->dispatch->#{func_name}("
349         ps = parameters.split(",")
350         ps = ps.collect { |p|
351           p = p.split
352           p = p[-1].gsub("*","")
353         }
354         ocl_icd_lib_source += ps.join(", ")
355         ocl_icd_lib_source += ");\n"
356       end
357       ocl_icd_lib_source += "}\n\n"
358     }
359
360     return ocl_icd_lib_source;
361   end
362   
363   def self.generate_ocl_icd_dummy_source
364     ocl_icd_dummy_source = "/**\n#{$license}\n*/\n"
365     ocl_icd_dummy_source += "#include \"ocl_icd_dummy.h\"\n"
366     ocl_icd_dummy_source += "#include <stdio.h>\n"
367     ocl_icd_dummy_source += "#include <string.h>\n"
368     ocl_icd_dummy_source += <<EOF
369 #define NUM_PLATFORMS 1
370 #define DEBUG 0
371 cl_uint const num_master_platforms = NUM_PLATFORMS;
372 struct _cl_platform_id master_platforms[NUM_PLATFORMS] = { {&master_dispatch} };
373 CL_API_ENTRY cl_int CL_API_CALL clGetPlatformIDs(  
374              cl_uint num_entries, 
375              cl_platform_id *platforms,
376              cl_uint *num_platforms) {
377   return clIcdGetPlatformIDsKHR(num_entries, platforms, num_platforms);
378 }
379 CL_API_ENTRY cl_int CL_API_CALL clIcdGetPlatformIDsKHR(  
380              cl_uint num_entries, 
381              cl_platform_id *platforms,
382              cl_uint *num_platforms) {
383 #if DEBUG
384   printf("In clIcdGetPlatformIDsKHR...\\n");
385 #endif
386   if( platforms == NULL && num_platforms == NULL )
387     return CL_INVALID_VALUE;
388   if( num_entries == 0 && platforms != NULL )
389     return CL_INVALID_VALUE;
390   if( num_master_platforms == 0)
391     return CL_PLATFORM_NOT_FOUND_KHR;
392   if( num_platforms != NULL ){
393 #if DEBUG
394   printf("  asked num_platforms\\n");
395 #endif
396     *num_platforms = num_master_platforms; }
397   if( platforms != NULL ) {
398 #if DEBUG
399   printf("  asked platforms\\n");
400 #endif
401     cl_uint i;
402     for( i=0; i<(num_master_platforms<num_entries?num_master_platforms:num_entries); i++)
403       platforms[i] = &master_platforms[i];
404   }
405   return CL_SUCCESS;
406 }
407
408 /*CL_API_ENTRY void * CL_API_CALL clGetExtensionFunctionAddressForPlatform(
409              cl_platform_id platform,
410              const char *   func_name) CL_API_SUFFIX__VERSION_1_2 {
411 }*/
412
413 CL_API_ENTRY void * CL_API_CALL clGetExtensionFunctionAddress(
414              const char *   func_name) CL_API_SUFFIX__VERSION_1_0 {
415 #if DEBUG
416   printf("In clGetExtensionFunctionAddress... asked %s\\n", func_name);
417 #endif
418   if( func_name != NULL &&  strcmp("clIcdGetPlatformIDsKHR", func_name) == 0 )
419     return (void *)clIcdGetPlatformIDsKHR;
420   return NULL;
421 }
422 CL_API_ENTRY cl_int CL_API_CALL clGetPlatformInfo(
423              cl_platform_id   platform, 
424              cl_platform_info param_name,
425              size_t           param_value_size, 
426              void *           param_value,
427              size_t *         param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 {
428 #if DEBUG
429   printf("In clGetPlatformInfo...\\n");
430 #endif
431
432   char cl_platform_profile[] = "FULL_PROFILE";
433   char cl_platform_version[] = "OpenCL 1.1";
434   char cl_platform_name[] = "DummyCL";
435   char cl_platform_vendor[] = "LIG";
436   char cl_platform_extensions[] = "cl_khr_icd";
437   char cl_platform_icd_suffix_khr[] = "dummy";
438   size_t size_string;
439   char * string_p;
440   if( platform != NULL ) {
441     int found = 0;
442     int i;
443     for(i=0; i<num_master_platforms; i++) {
444       if( platform == &master_platforms[i] )
445         found = 1;
446     }
447     if(!found)
448       return CL_INVALID_PLATFORM;
449   }
450   switch ( param_name ) {
451     case CL_PLATFORM_PROFILE:
452       string_p = cl_platform_profile;
453       size_string = sizeof(cl_platform_profile);
454       break;
455     case CL_PLATFORM_VERSION:
456       string_p = cl_platform_version;
457       size_string = sizeof(cl_platform_version);
458       break;
459     case CL_PLATFORM_NAME:
460       string_p = cl_platform_name;
461       size_string = sizeof(cl_platform_name);
462       break;
463     case CL_PLATFORM_VENDOR:
464       string_p = cl_platform_vendor;
465       size_string = sizeof(cl_platform_vendor);
466       break;
467     case CL_PLATFORM_EXTENSIONS:
468       string_p = cl_platform_extensions;
469       size_string = sizeof(cl_platform_extensions);
470       break;
471     case CL_PLATFORM_ICD_SUFFIX_KHR:
472       string_p = cl_platform_icd_suffix_khr;
473       size_string = sizeof(cl_platform_icd_suffix_khr);
474       break;
475     default:
476       return CL_INVALID_VALUE;
477       break;
478   }
479   if( param_value != NULL ) {
480     if( size_string > param_value_size )
481       return CL_INVALID_VALUE;
482     memcpy(param_value, string_p, size_string);
483   }
484   if( param_value_size_ret != NULL )
485     *param_value_size_ret = size_string;
486   return CL_SUCCESS;
487 }
488 EOF
489     (0...$api_entries.length+$buff).each { |i|
490       ocl_icd_dummy_source += "void dummyFunc#{i}(void){ printf(\"#{i}  : \"); fflush(NULL); }\n"
491     }
492     return ocl_icd_dummy_source
493   end
494   
495   def self.generate_ocl_icd_dummy_test_weak_source
496     ocl_icd_dummy_test_weak = "/**\n#{$license}\n*/\n"
497     ocl_icd_dummy_test_weak += <<EOF
498 #define _GNU_SOURCE 1
499 #include <stdio.h>
500 #include <dlfcn.h>
501
502 #define F(f) \\
503 __attribute__((weak)) int f (void* arg) { \\
504   void (* p)(void*)=NULL; \\
505   p=dlsym(RTLD_NEXT, #f); \\
506   if (p) { \\
507     (*p)(arg); \\
508   } else { \\
509     printf("-1 : "); \\
510   } \\
511   return 0; \\
512
513 EOF
514     $api_entries.each_key { |func_name|
515        next if $forbidden_funcs.include?(func_name)
516        next if $noweak_funcs.include?(func_name)
517        ocl_icd_dummy_test_weak += "F(#{func_name})\n"
518     }
519     return ocl_icd_dummy_test_weak
520   end
521   def self.generate_ocl_icd_dummy_test_source
522     ocl_icd_dummy_test = "/**\n#{$license}\n*/\n"
523     ocl_icd_dummy_test += "#include <stdlib.h>\n"
524     ocl_icd_dummy_test += "#include <stdio.h>\n"
525     ocl_icd_dummy_test += "#define CL_USE_DEPRECATED_OPENCL_1_0_APIS\n"
526     ocl_icd_dummy_test += "#define CL_USE_DEPRECATED_OPENCL_1_1_APIS\n"
527     ocl_icd_dummy_test += "#include <CL/opencl.h>\n"
528     ocl_icd_dummy_test += self.include_headers
529     ocl_icd_dummy_test += "#include <string.h>\n"
530     ocl_icd_dummy_test += <<EOF
531
532 int main(void) {
533   int i;
534   cl_uint num_platforms;
535   clGetPlatformIDs( 0, NULL, &num_platforms);
536   cl_platform_id *platforms = malloc(sizeof(cl_platform_id) * num_platforms);
537   clGetPlatformIDs(num_platforms, platforms, NULL);
538 #ifdef DEBUG
539   fprintf(stderr, "Found %d platforms.\\n", num_platforms);
540 #endif
541   cl_platform_id chosen_platform=NULL;
542   CL_API_ENTRY cl_int (CL_API_CALL* oclFuncPtr)(cl_platform_id platform);
543   typedef CL_API_ENTRY cl_int (CL_API_CALL* oclFuncPtr_fn)(cl_platform_id platform);
544
545    for(i=0; i<num_platforms; i++){
546      char *platform_vendor;
547      size_t param_value_size_ret;
548
549      clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, 0, NULL, &param_value_size_ret );
550      platform_vendor = (char *)malloc(param_value_size_ret);
551      clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, param_value_size_ret, platform_vendor, NULL );
552
553 #ifdef DEBUG
554      fprintf(stderr, "%s\\n",platform_vendor);
555 #endif
556      if( strcmp(platform_vendor, "LIG") == 0)
557        chosen_platform = platforms[i];
558      free(platform_vendor);
559   }
560   if( chosen_platform == NULL ) {
561     fprintf(stderr,"Error LIG platform not found!\\n");
562     return -1;
563   }
564
565   cl_context_properties properties[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)chosen_platform, 0 };
566   printf("---\\n");
567   fflush(NULL);
568 EOF
569     $api_entries.each_key { |func_name|
570        next if $forbidden_funcs.include?(func_name)
571        if func_name == "clCreateContext" then
572          ocl_icd_dummy_test += "  #{func_name}(properties,1,(cl_device_id*)&chosen_platform,NULL,NULL,NULL);\n"
573        elsif func_name == "clCreateContextFromType" then
574          ocl_icd_dummy_test += "  #{func_name}(properties,CL_DEVICE_TYPE_CPU,NULL,NULL,NULL);\n"
575        elsif func_name == "clWaitForEvents" then
576          ocl_icd_dummy_test += "  #{func_name}(1,(cl_event*)&chosen_platform);\n"
577        else
578          ocl_icd_dummy_test += "  oclFuncPtr = (oclFuncPtr_fn)" + func_name + ";\n"
579          ocl_icd_dummy_test += "  oclFuncPtr(chosen_platform);\n"
580        end
581        ocl_icd_dummy_test += "  printf(\"%s\\n\", \"#{func_name}\");"
582        ocl_icd_dummy_test += "  fflush(NULL);\n"
583     }
584     ocl_icd_dummy_test += "  return 0;\n}\n"
585     return ocl_icd_dummy_test
586   end
587
588   def self.generate_sources
589     parse_headers
590     File.open('ocl_icd_h_dummy.h','w') { |f|
591       f.puts generate_ocl_icd_header
592     }
593     File.open('ocl_icd_dummy.h','w') { |f|
594       f.puts generate_ocl_icd_dummy_header
595     }
596     File.open('ocl_icd_dummy.c','w') { |f|
597       f.puts generate_ocl_icd_dummy_source
598     }
599     File.open('ocl_icd_dummy_test.c','w') { |f|
600       f.puts generate_ocl_icd_dummy_test_source
601     }
602     File.open('ocl_icd_dummy_test_weak.c','w') { |f|
603       f.puts generate_ocl_icd_dummy_test_weak_source
604     }
605   end
606
607   def self.savedb
608     api_db = {}
609     begin
610       File::open("ocl_interface.yaml","r") { |f|
611         api_db = YAML::load(f.read)
612 #        puts api_db.inspect
613       }
614     rescue
615       api_db = {}
616     end
617     $known_entries.each_key {|i|
618       next if api_db[i]
619       api_db[i] = $api_entries[$known_entries[i]].gsub("\r","")
620     }
621     File::open("ocl_interface.yaml","w") { |f|
622       f.write($license.gsub(/^/,"# "))
623       f.write(YAML::dump(api_db))
624     }
625   end
626
627   def self.finalize
628     parse_headers
629     doc = YAML::load(`./ocl_icd_dummy_test`)
630     doc.delete(-1)
631     $known_entries.merge!(doc)
632     self.savedb
633     unknown=0
634     $api_entries_array = []
635     ($known_entries.length+$buff).times { |i|
636       #puts $known_entries[i]
637       if $known_entries[i] then
638         $api_entries_array.push( $api_entries[$known_entries[i]] )
639       else
640         $api_entries_array.push( "CL_API_ENTRY cl_int CL_API_CALL clUnknown#{unknown}(void);" )
641         unknown += 1
642       end
643     }
644     File.open('ocl_icd.h','w') { |f|
645       f.puts generate_ocl_icd_header_final
646     }
647     File.open('ocl_icd_bindings.c','w') { |f|
648       f.puts generate_ocl_icd_source
649     }
650     File.open('ocl_icd_lib.c','w') { |f|
651       f.puts generate_ocl_icd_lib_source
652     }
653   end
654   
655   def self.generate_from_database
656     doc={}
657     File::open('./ocl_interface.yaml') { |f|
658       doc = YAML:: load(f.read)
659     }
660     $known_entries = {}
661     $api_entries = {}
662     entry_name = ""
663     doc.each { |key, value|
664       begin
665         entry_name = value.match(/CL_API_CALL(.*?)\(/m)[1].strip
666       rescue
667         entry_name = value.match(/(\S*?)\(/m)[1].strip
668       end
669       $known_entries[key] = entry_name
670       $api_entries[entry_name] = value
671     }
672     $api_entries_array = []
673     unknown=0
674     ($known_entries.length+$buff).times { |i|
675       #puts $known_entries[i]
676       if $known_entries[i] then
677         $api_entries_array.push( $api_entries[$known_entries[i]] )
678       else
679         $api_entries_array.push( "CL_API_ENTRY cl_int CL_API_CALL clUnknown#{unknown}(void);" )
680         unknown += 1
681       end
682     }
683     File.open('ocl_icd.h','w') { |f|
684       f.puts generate_ocl_icd_header_final
685     }
686     File.open('ocl_icd_bindings.c','w') { |f|
687       f.puts generate_ocl_icd_source
688     }
689     File.open('ocl_icd_lib.c','w') { |f|
690       f.puts generate_ocl_icd_lib_source
691     }
692   end
693 end
694
695 if ARGV[0] == "--generate"
696   IcdGenerator.generate_sources
697 elsif ARGV[0] == "--finalize"
698   IcdGenerator.finalize
699 elsif ARGV[0] == "--database"
700   IcdGenerator.generate_from_database
701 else
702   raise "Argument must be one of --generate or --finalize" 
703 end