1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Cyril Concolato
5  *			Copyright (c) Telecom ParisTech 2004-2012
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / SVG Scene Graph Generator sub-project
9  *
10  *  GPAC is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU Lesser General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  GPAC is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 #include <gpac/tools.h>
27 #include <gpac/list.h>
28 
start_ctx(char * ctx_name,FILE ** ifce_c,FILE ** fun_c)29 static void start_ctx(char *ctx_name, FILE **ifce_c, FILE **fun_c)
30 {
31 	char szFile[GF_MAX_PATH];
32 	sprintf(szFile, "../../../src/jsmods/%s.c", ctx_name);
33 	FILE *res = gf_fopen(szFile, "wt");
34 	*ifce_c = res;
35 	*fun_c = gf_file_temp(NULL);
36 
37 	fprintf(res, "/* !! AUTOGENERATED FILE - DO NOT MODIFY !! \n");
38 	fprintf(res, "\n%s implementation for QJS\n*/\n\n", ctx_name);
39 }
40 
41 
end_ctx(FILE * ifce_c,FILE * func_c,char * ctx_name)42 static void end_ctx(FILE *ifce_c, FILE *func_c, char *ctx_name)
43 {
44 
45 	fprintf(ifce_c, "static const JSCFunctionListEntry %s_funcs[] =\n\{\n", ctx_name);
46 	gf_fseek(func_c, 0, SEEK_SET);
47 	while (!feof(func_c)) {
48 		char szLine[4001];
49 		szLine[0] = 0;
50 		gf_fgets(szLine, 4000, func_c);
51 		gf_fputs(szLine, ifce_c);
52 	}
53 	gf_fclose(func_c);
54 	fprintf(ifce_c, "};\n");
55 	gf_fclose(ifce_c);
56 	gf_free(ctx_name);
57 
58 }
59 
put_const(FILE * fun_defs,char * c_name,char * c_val)60 static void put_const(FILE *fun_defs, char *c_name, char *c_val)
61 {
62 	fprintf(fun_defs, "\tJS_PROP_INT32_DEF(\"%s\", %s, JS_PROP_CONFIGURABLE),\n", c_name, c_val);
63 }
put_fun(FILE * fun_defs,char * f_name)64 static void put_fun(FILE *fun_defs, char *f_name)
65 {
66 	fprintf(fun_defs, "\tJS_CFUNC_DEF(\"%s\", 0, wgl_%s),\n", f_name, f_name);
67 }
put_prop(FILE * fun_defs,char * ctx_name,char * pname,Bool is_readonly)68 static void put_prop(FILE *fun_defs, char *ctx_name, char *pname, Bool is_readonly)
69 {
70 	if (is_readonly) {
71 		fprintf(fun_defs, "\tJS_CGETSET_MAGIC_DEF(\"%s\", %s_getProperty, NULL, %s_PROP_%s),\n", pname, ctx_name, ctx_name, pname);
72 	} else {
73 		fprintf(fun_defs, "\tJS_CGETSET_MAGIC_DEF(\"%s\", %s_getProperty, %s_setProperty, %s_PROP_%s),\n", pname, ctx_name, ctx_name, ctx_name, pname);
74 	}
75 }
76 
get_arg_type(char * arg_type,Bool * is_array)77 static const char *get_arg_type(char *arg_type, Bool *is_array)
78 {
79 	*is_array = GF_FALSE;
80 	if (!strcmp(arg_type, "GLenum")) return "u32";
81 	if (!strcmp(arg_type, "DOMString"))  return "const char *";
82 	if (!strcmp(arg_type, "DOMString?"))  return "const char *";
83 	if (!strcmp(arg_type, "GLuint"))  return "u32";
84 	if (!strcmp(arg_type, "GLint"))  return "s32";
85 	if (!strcmp(arg_type, "GLuint"))  return "u32";
86 	if (!strcmp(arg_type, "GLclampf"))  return "Float";
87 	if (!strcmp(arg_type, "GLfloat"))  return "Float";
88 	if (!strcmp(arg_type, "GLboolean"))  return "Bool";
89 	if (!strcmp(arg_type, "boolean"))  return "Bool";
90 	if (!strcmp(arg_type, "GLsizei"))  return "u32";
91 	if (!strcmp(arg_type, "GLbitfield"))  return "u32";
92 	if (!strcmp(arg_type, "GLshort"))  return "s16";
93 	if (!strcmp(arg_type, "GLushort"))  return "u16";
94 	if (!strcmp(arg_type, "GLsizeiptr"))  return "u64";
95 	if (!strcmp(arg_type, "GLintptr"))  return "u64";
96 	if (!strcmp(arg_type, "GLbyte"))  return "s8";
97 	if (!strcmp(arg_type, "GLubyte"))  return "u8";
98 	if (!strcmp(arg_type, "WebGLProgram?")) return "WebGLProgram";
99 	if (!strcmp(arg_type, "WebGLShader?")) return "WebGLShader";
100 	if (!strcmp(arg_type, "WebGLBuffer?")) return "WebGLBuffer";
101 	if (!strcmp(arg_type, "WebGLFramebuffer?")) return "WebGLFramebuffer";
102 	if (!strcmp(arg_type, "WebGLRenderbuffer?")) return "WebGLRenderbuffer";
103 	if (!strcmp(arg_type, "WebGLTexture?")) return "WebGLTexture";
104 	if (!strcmp(arg_type, "WebGLUniformLocation?")) return "WebGLUniformLocation";
105 	if (!strcmp(arg_type, "TexImageSource?")) return "TexImageSource";
106 	if (!strcmp(arg_type, "WebGLContextAttributes?")) return "WebGLContextAttributes";
107 	if (!strcmp(arg_type, "boolean?")) return "Bool";
108 	if (!strcmp(arg_type, "WebGLActiveInfo?")) return "JSValue";
109 
110 	if (!strcmp(arg_type, "Float32Array")) {
111 		*is_array = GF_TRUE;
112 		return "Float *";
113 	}
114 	if (!strcmp(arg_type, "Int32Array")) {
115 		*is_array = GF_TRUE;
116 		return "s32 *";
117 	}
118 	if (!strcmp(arg_type, "sequence<DOMString>?")) {
119 		return "JSValue";
120 	}
121 	if (!strcmp(arg_type, "sequence<WebGLShader>?")) {
122 		return "JSValue";
123 	}
124 	if (!strcmp(arg_type, "ArrayBufferView")
125 		|| !strcmp(arg_type, "ArrayBufferView?")
126 		|| !strcmp(arg_type, "BufferDataSource?")
127 	) {
128 		*is_array = GF_TRUE;
129 		return "u8 *";
130 	}
131 
132 	if (!strcmp(arg_type, "object?")
133 		|| !strcmp(arg_type, "WebGLShaderPrecisionFormat?")
134 		|| !strcmp(arg_type, "any")
135 		) {
136 		return NULL;
137 	}
138 
139 	fprintf(stderr, "arg type %s not supported\n", arg_type);
140 	return "JSValue";
141 }
142 
put_arg_get(FILE * ifce_c,char * fname,int idx,char * arg_type,char * arg_name)143 static void put_arg_get(FILE *ifce_c, char *fname, int idx, char *arg_type, char *arg_name)
144 {
145 	Bool is_array;
146 	const char *native_type = get_arg_type(arg_type, &is_array);
147 	if (!native_type) return;
148 
149 	if (!strcmp(native_type, "Bool")) {
150 		fprintf(ifce_c, "\tWGL_GET_BOOL(%s, argv[%d]);\n", arg_name, idx);
151 	}
152 	else if (!strcmp(native_type, "s32")) {
153 		fprintf(ifce_c, "\tWGL_GET_S32(%s, argv[%d]);\n", arg_name, idx);
154 	}
155 	else if (!strcmp(native_type, "u32")) {
156 		fprintf(ifce_c, "\tWGL_GET_U32(%s, argv[%d]);\n", arg_name, idx);
157 	}
158 	else if (!strcmp(native_type, "u64")) {
159 		fprintf(ifce_c, "\tWGL_GET_U64(%s, argv[%d]);\n", arg_name, idx);
160 	}
161 	else if (!strcmp(native_type, "s64")) {
162 		fprintf(ifce_c, "\tWGL_GET_S64(%s, argv[%d]);\n", arg_name, idx);
163 	}
164 	else if (!strcmp(native_type, "s16")) {
165 		fprintf(ifce_c, "\tWGL_GET_S16(%s, argv[%d]);\n", arg_name, idx);
166 	}
167 	else if (!strcmp(native_type, "u16")) {
168 		fprintf(ifce_c, "\tWGL_GET_U16(%s, argv[%d]);\n", arg_name, idx);
169 	}
170 	else if (!strcmp(arg_type, "GLclampf")) {
171 		fprintf(ifce_c, "\tWGL_GET_FLOAT_CLAMP(%s, argv[%d]);\n", arg_name, idx);
172 	}
173 	else if (!strcmp(native_type, "Float")) {
174 		fprintf(ifce_c, "\tWGL_GET_FLOAT(%s, argv[%d]);\n", arg_name, idx);
175 	}
176 	else if (!strcmp(native_type, "const char *")) {
177 		fprintf(ifce_c, "\tWGL_GET_STRING(%s, argv[%d]);\n", arg_name, idx);
178 	}
179 	else if (!strcmp(native_type, "WebGLProgram")
180 	 	|| !strcmp(native_type, "WebGLShader")
181 	 	|| !strcmp(native_type, "WebGLBuffer")
182 	 	|| !strcmp(native_type, "WebGLFramebuffer")
183 	 	|| !strcmp(native_type, "WebGLRenderbuffer")
184 	 	|| !strcmp(native_type, "WebGLTexture")
185 	 	|| !strcmp(native_type, "WebGLUniformLocation")
186 	) {
187 		fprintf(ifce_c, "\tWGL_GET_GLID(%s, argv[%d], %s_class_id);\n", arg_name, idx, native_type);
188 	}
189 
190 	else if (!strcmp(arg_type, "BufferDataSource?")) {
191 		fprintf(ifce_c, "\tif(!JS_IsObject(argv[%d])) {\n", idx);
192 		fprintf(ifce_c, "\t\tWGL_GET_U32(%s_size, argv[%d]);\n", arg_name, idx);
193 		fprintf(ifce_c, "\t} else {\n");
194 		fprintf(ifce_c, "\t\t%s = wgl_GetArrayBuffer(ctx, &%s_size, argv[%d]);\n", arg_name, arg_name, idx);
195 		fprintf(ifce_c, "\t}\n");
196 	}
197 	else if (is_array && !strcmp(native_type, "u8 *")) {
198 		fprintf(ifce_c, "\tif(!JS_IsArray(ctx, argv[%d])) return js_throw_err(ctx, WGL_INVALID_VALUE);\n", idx);
199 		fprintf(ifce_c, "\t%s = wgl_GetArrayBuffer(ctx, &%s_size, argv[%d]);\n", arg_name, arg_name, idx);
200 	}
201 	else if (is_array && (!strcmp(native_type, "Float *") || !strcmp(native_type, "s32 *")) ) {
202 		u32 vlen = 1;
203 		if (strstr(fname, "2fv")) vlen = 2;
204 		else if (strstr(fname, "3fv")) vlen = 3;
205 		else if (strstr(fname, "4fv")) vlen = 4;
206 
207 		if (!strcmp(native_type, "s32 *"))
208 			fprintf(ifce_c, "\tif (!WGL_LOAD_INT32_VEC(ctx, argv[%d], (s32 **) &%s, &%s_size, %d)) return js_throw_err(ctx, WGL_INVALID_VALUE);;\n", idx, arg_name, arg_name, vlen);
209 		else {
210 			Bool is_matrix = GF_FALSE;
211 			if (strstr(fname, "Matrix")) is_matrix = GF_TRUE;
212 			if (strstr(fname, "vertexAttrib")) {
213 				fprintf(ifce_c, "\tif (!WGL_LOAD_FLOAT_VEC(ctx, argv[%d], (Float **) &%s, NULL, %d, %d)) return js_throw_err(ctx, WGL_INVALID_VALUE);\n", idx, arg_name, vlen, is_matrix);
214 			} else {
215 				fprintf(ifce_c, "\tif (!WGL_LOAD_FLOAT_VEC(ctx, argv[%d], (Float **) &%s, &%s_size, %d, %d)) return js_throw_err(ctx, WGL_INVALID_VALUE);\n", idx, arg_name, arg_name, vlen, is_matrix);
216 			}
217 		}
218 	}
219 	else {
220 		fprintf(stderr, "arg type %s not supported\n", arg_type);
221 	}
222 
223 }
224 
put_arg_decl(FILE * ifce_c,char * fname,char * arg_type,char * arg_name)225 static void put_arg_decl(FILE *ifce_c, char *fname, char *arg_type, char *arg_name)
226 {
227 	Bool is_array = GF_FALSE;
228 	const char *native_type = get_arg_type(arg_type, &is_array);
229 	if (!native_type)
230 		return;
231 
232 	if (is_array) {
233 		if (strstr(fname, "vertexAttrib1fv")) {
234 			fprintf(ifce_c, "\tFloat %s[1];\n", arg_name);
235 		} else if (strstr(fname, "vertexAttrib2fv")) {
236 			fprintf(ifce_c, "\tFloat %s[2];\n", arg_name);
237 		} else if (strstr(fname, "vertexAttrib3fv")) {
238 			fprintf(ifce_c, "\tFloat %s[3];\n", arg_name);
239 		} else if (strstr(fname, "vertexAttrib4fv")) {
240 			fprintf(ifce_c, "\tFloat %s[4];\n", arg_name);
241 		} else {
242 			fprintf(ifce_c, "\t%s %s = NULL;\n", native_type, arg_name);
243 			fprintf(ifce_c, "\tu32 %s_size = 0;\n", arg_name);
244 		}
245 	} else {
246 		if (strstr(arg_name, " *"))
247 			fprintf(ifce_c, "\t%s %s = NULL;\n", native_type, arg_name);
248 		else if (!strcmp(native_type, "JSValue"))
249 			fprintf(ifce_c, "\t%s %s = JS_UNDEFINED;\n", native_type, arg_name);
250 		else if (!strncmp(native_type, "WebGL", 5))
251 			fprintf(ifce_c, "\tGLuint %s = 0;\n", arg_name);
252 		else
253 			fprintf(ifce_c, "\t%s %s = 0;\n", native_type, arg_name);
254 	}
255 }
256 /*all functions that cannot be mapped directly due to to heavy syntax pacthing or our own hacking*/
257 static const char *not_autogen_funcs = "getContextAttributes,isContextLost,getSupportedExtensions,getExtension,getBufferParameter,getParameter,getFramebufferAttachmentParameter,getProgramParameter,getRenderbufferParameter,getShaderParameter,getShaderPrecisionFormat,getProgramInfoLog,getShaderParameter,getShaderInfoLog,getShaderSource,getTexParameter,getUniform,getVertexAttrib,getVertexAttribOffset,readPixels,shaderSource,texImage2D,texSubImage2D,useProgram,activeTexture,bindTexture,getUniformLocation,createTexture,bindFramebuffer";
258 
wrap_func(FILE * ifce_c,char * fname,char * fun_def)259 static void wrap_func(FILE *ifce_c, char *fname, char *fun_def)
260 {
261 	char *sep, *nsep;
262 	u32 len, i, nb_args;
263 	u32 first_char;
264 	u32 ret_type=0;
265 	Bool is_create=GF_FALSE;
266 	Bool is_delete_fun=GF_FALSE;
267 	char *ret_val=NULL, *exc_value=NULL, *arg_type[50], *arg_name[50];
268 
269 	if (strstr(not_autogen_funcs, fname)) {
270 		fprintf(ifce_c, "\nstatic JSValue wgl_%s(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);\n", fname);
271 		return;
272 	}
273 
274 	fprintf(ifce_c, "\nstatic JSValue wgl_%s(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)\n{\n", fname);
275 
276 	nb_args = 0;
277 	memset(arg_type, 0, sizeof(char *)*50);
278 	memset(arg_name, 0, sizeof(char *)*50);
279 
280 	sep = fun_def;
281 	while (sep[0]==' ') sep++;
282 	/*parse exception*/
283 	if (sep[0]=='[') {
284 		nsep = strchr(sep, ']');
285 		assert(nsep);
286 		nsep[0]=0;
287 		exc_value = gf_strdup(sep);
288 		nsep[0]=']';
289 		sep = nsep+1;
290 		while (sep[0]==' ') sep++;
291 	}
292 	/*parse return value*/
293 	nsep = strchr(sep, ' ');
294 	assert(nsep);
295 	nsep[0] = 0;
296 	ret_val = strdup(sep);
297 	sep = nsep+1;
298 	len = strlen(fname);
299 	assert(!strncmp(sep, fname, len) );
300 	sep += len+1;
301 	while (sep) {
302 		char *next_arg;
303 		nsep = strchr(sep, ',');
304 		if (!nsep) {
305 			nsep = strchr(sep, ')');
306 			if (!nsep) break;
307 		}
308 		nsep[0]=0;
309 		next_arg = nsep+1;
310 
311 		if (nb_args>=50) {
312 			assert(0);
313 		}
314 		nsep = strchr(sep, ' ');
315 		if (!nsep)
316 			break;
317 		assert(nsep);
318 		nsep[0] = 0;
319 		arg_type[nb_args] = gf_strdup(sep);
320 		arg_name[nb_args] = gf_strdup(nsep+1);
321 		nb_args++;
322 		sep = next_arg;
323 		while (sep[0]==' ') sep++;
324 	}
325 
326 	fprintf(ifce_c, "\tJSValue ret_val_js = JS_UNDEFINED;\n");
327 
328 	for (i=0; i<nb_args; i++) {
329 		put_arg_decl(ifce_c, fname, arg_type[i], arg_name[i]);
330 	}
331 	fprintf(ifce_c, "\tWGL_CHECK_CONTEXT\n");
332 
333 	if (nb_args) {
334 		fprintf(ifce_c, "\tif (argc<%d) return js_throw_err(ctx, WGL_INVALID_VALUE);\n", nb_args);
335 		for (i=0; i<nb_args; i++) {
336 			put_arg_get(ifce_c, fname, i, arg_type[i], arg_name[i]);
337 		}
338 	}
339 
340 	/*hack a few funcs with different signatures*/
341 	if (!strcmp(fname, "getActiveAttrib")) {
342 		fprintf(ifce_c, "\tret_val_js = webgl_getActiveAttrib(ctx, program, index);\n\treturn ret_val_js;\n");
343 		goto fun_done;
344 	}
345 	if (!strcmp(fname, "getActiveUniform")) {
346 		fprintf(ifce_c, "\tret_val_js = webgl_getActiveUniform(ctx, program, index);\n\treturn ret_val_js;\n");
347 		goto fun_done;
348 	}
349 	if (!strcmp(fname, "getAttachedShaders")) {
350 		fprintf(ifce_c, "\tret_val_js = webgl_getAttachedShaders(ctx, JS_GetOpaque(this_val, WebGLRenderingContextBase_class_id), program);\n\treturn ret_val_js;\n");
351 		goto fun_done;
352 	}
353 	if (!strcmp(fname, "getBufferParameter")) {
354 		fprintf(ifce_c, "\tret_val_js = webgl_getBufferParameter(ctx, target, pname);\n\treturn ret_val_js;\n");
355 		goto fun_done;
356 	}
357 
358 	if (ret_val && strcmp(ret_val, "void")) {
359 		if (!strcmp(fname, "createBuffer") || !strcmp(fname, "createFramebuffer") || !strcmp(fname, "createTexture") || !strcmp(fname, "createRenderbuffer")) {
360 			fprintf(ifce_c, "\tGF_WebGLObject *wglo;\n");
361 			is_create = GF_TRUE;
362 			ret_type = 2;
363 
364 		} else if (!strcmp(fname, "createProgram") || !strcmp(fname, "createShader")) {
365 			fprintf(ifce_c, "\tGF_WebGLObject *wglo;\n");
366 			ret_type = 2;
367 		} else {
368 			put_arg_decl(ifce_c, fname, ret_val, "ret_val");
369 			ret_type = 1;
370 		}
371 	}
372 
373 	first_char = fname[0];
374 	if ((first_char < 'A') || (first_char > 'Z')) {
375 		first_char += 'A' - 'a';
376 	}
377 
378 	if (is_create) {
379 		fprintf(ifce_c, "\tGF_SAFEALLOC(wglo, GF_WebGLObject);\n");
380 		fprintf(ifce_c, "\tif (!wglo) return js_throw_err(ctx, WGL_OUT_OF_MEMORY);\n");
381 		fprintf(ifce_c, "\twglo->par_ctx = JS_GetOpaque(this_val, WebGLRenderingContextBase_class_id);\n");
382 		fprintf(ifce_c, "\tglGen%ss(1, &wglo->gl_id", fname+6);
383 	} else {
384 		if (!strcmp(fname, "deleteShader") || !strcmp(fname, "deleteProgram")) {
385 			is_delete_fun=GF_TRUE;
386 		}
387 		if (!strcmp(fname, "deleteBuffer") || !strcmp(fname, "deleteTexture") || !strcmp(fname, "deleteFramebuffer") || !strcmp(fname, "deleteRenderbuffer")) {
388 			fprintf(ifce_c, "\tgl%c%ss(1, &", first_char, fname+1);
389 			is_delete_fun=GF_TRUE;
390 		}
391 		else if (!strcmp(fname, "createProgram") || !strcmp(fname, "createShader")) {
392 			fprintf(ifce_c, "\tGF_SAFEALLOC(wglo, GF_WebGLObject);\n");
393 			fprintf(ifce_c, "\tif (!wglo) return js_throw_err(ctx, WGL_OUT_OF_MEMORY);\n");
394 			fprintf(ifce_c, "\twglo->par_ctx = JS_GetOpaque(this_val, WebGLRenderingContextBase_class_id);\n");
395 			fprintf(ifce_c, "\twglo->gl_id = gl%c%s(", first_char, fname+1);
396 		} else if (!strcmp(fname, "clearDepth") || !strcmp(fname, "depthRange")) {
397 			fprintf(ifce_c, "#if defined(GPAC_USE_GLES2)\n");
398 			fprintf(ifce_c, "\tgl%c%sf(\n", first_char, fname+1);
399 			fprintf(ifce_c, "#else\n");
400 			fprintf(ifce_c, "\tgl%c%s(\n", first_char, fname+1);
401 			fprintf(ifce_c, "#endif\n\t\t");
402 		} else {
403 			fprintf(ifce_c, "\t");
404 			if (ret_type==1) {
405 				fprintf(ifce_c, "ret_val = ");
406 			}
407 			if (!strncmp(fname, "uniform", 7)) {
408 
409 				fprintf(ifce_c, "/*hack for GPAC textures, we create uniforms with loc -2 for such textures*/\n\tif ((s32) location>=0)\n\t\t");
410 			}
411 			fprintf(ifce_c, "gl%c%s(", first_char, fname+1);
412 		}
413 	}
414 
415 	Bool prev_is_transpose = GF_FALSE;
416 	for (i=0; i<nb_args; i++) {
417 		Bool is_array;
418 		get_arg_type(arg_type[i], &is_array);
419 
420 		if (!strcmp(arg_name[i], "transpose")) {
421 			fprintf(ifce_c, "%s_size, ", arg_name[i+1]);
422 			prev_is_transpose = GF_TRUE;
423 		}
424 		else if (prev_is_transpose) {
425 			is_array = GF_FALSE;
426 		}
427 
428 		if (is_array && (
429 			!strcmp(fname, "bufferData") || !strcmp(fname, "bufferSubData")
430 			|| !strcmp(fname, "compressedTexImage2D") || !strcmp(fname, "compressedTexSubImage2D")
431 			|| !strncmp(fname, "uniform", 7)
432 
433 		)) {
434 			is_array = GF_FALSE;
435 			fprintf(ifce_c, "%s_size, ", arg_name[i]);
436 		}
437 		if (!strcmp(arg_type[i], "GLintptr") && (!strcmp(fname, "vertexAttribPointer") || !strcmp(fname, "drawElements")) ) {
438 			fprintf(ifce_c, "(void *)");
439 		}
440 
441 		fprintf(ifce_c, "%s", arg_name[i]);
442 
443 		if (is_array) {
444 			if (strstr(fname, "vertexAttrib1fv")) {}
445 			else if (strstr(fname, "vertexAttrib2fv")) {}
446 			else if (strstr(fname, "vertexAttrib3fv")) {}
447 			else if (strstr(fname, "vertexAttrib4fv")) {}
448 			else {
449 				fprintf(ifce_c, ", %s_size", arg_name[i]);
450 			}
451 		}
452 		if (i+1<nb_args)
453 			fprintf(ifce_c, ", ");
454 	}
455 
456 	fprintf(ifce_c, ");\n");
457 	if (is_delete_fun) {
458 		Bool is_array;
459 		const char *nat_type = get_arg_type(arg_type[0], &is_array);
460 		fprintf(ifce_c, "\t{\n\tGF_WebGLObject *glo = JS_GetOpaque(argv[0], %s_class_id);\n\tif (glo) {\n\tglo->gl_id=0;\n", nat_type);
461 		fprintf(ifce_c, "\tJS_FreeValue(ctx, glo->obj);\n\tglo->obj = JS_UNDEFINED;\n\tgf_list_del_item(glo->par_ctx->all_objects, glo);\n");
462 		fprintf(ifce_c, "\t}\n\t}\n");
463 	}
464 
465 	if (ret_type==1) {
466 
467 		if (!strcmp(ret_val, "GLenum") || !strcmp(ret_val, "GLint")) {
468 			fprintf(ifce_c, "\tret_val_js = JS_NewInt32(ctx, ret_val);\n");
469 		} else if (!strcmp(ret_val, "GLboolean") ) {
470 			fprintf(ifce_c, "\tret_val_js = JS_NewBool(ctx, ret_val);\n");
471 		} else if (!strcmp(ret_val, "WebGLProgram") ) {
472 			fprintf(ifce_c, "\tret_val_js = JS_NewObjectClass(ctx, WebGLProgram_class_id);\n");
473 			fprintf(ifce_c, "\tJS_SetOpaque(ret_val_js, wglo);\n");
474 		} else {
475 			fprintf(stderr, "retval %s not supported in %s\n", ret_val, fname);
476 		}
477 	} else if (ret_type==2) {
478 		Bool is_array;
479 		const char *native_type = get_arg_type(ret_val, &is_array);
480 		fprintf(ifce_c, "\tret_val_js = JS_NewObjectClass(ctx, %s_class_id);\n", native_type);
481 		fprintf(ifce_c, "\tJS_SetOpaque(ret_val_js, wglo);\n");
482 		fprintf(ifce_c, "\twglo->obj = JS_DupValue(ctx, ret_val_js);\n");
483 		fprintf(ifce_c, "\twglo->class_id = %s_class_id;\n", native_type);
484 		fprintf(ifce_c, "\tgf_list_add(wglo->par_ctx->all_objects, wglo);\n");
485 	}
486 
487 	for (i=0; i<nb_args; i++) {
488 		Bool is_array;
489 		const char *native_type = get_arg_type(arg_type[i], &is_array);
490 		if (!native_type) continue;
491 		if (!strcmp(native_type, "const char *")) {
492 			fprintf(ifce_c, "\tJS_FreeCString(ctx, %s);\n", arg_name[i]);
493 		}
494 
495 		if (is_array && strcmp(native_type, "u8 *")) {
496 			if (strstr(fname, "vertexAttrib1fv")) {
497 			} else if (strstr(fname, "vertexAttrib2fv")) {
498 			} else if (strstr(fname, "vertexAttrib3fv")) {
499 			} else if (strstr(fname, "vertexAttrib4fv")) {
500 			} else {
501 				fprintf(ifce_c, "\tif (%s) gf_free(%s);\n", arg_name[i], arg_name[i]);
502 			}
503 		}
504 	}
505 
506 	fprintf(ifce_c, "\treturn ret_val_js;\n");
507 
508 fun_done:
509 	while (nb_args>1) {
510 		gf_free(arg_type[nb_args-1]);
511 		gf_free(arg_name[nb_args-1]);
512 		nb_args--;
513 	}
514 	gf_free(ret_val);
515 	fprintf(ifce_c, "}\n");
516 }
517 
518 
load_idl(const char * file)519 static void load_idl(const char *file)
520 {
521 	Bool in_ctxbase = GF_FALSE;
522 	char szLine[4001], *sep;
523 	char *curCtx = NULL;
524 	u32 len;
525 	FILE * idl = gf_fopen(file, "rt");
526 	FILE *ifce_c=NULL;
527 	FILE *fun_defs=NULL;
528 
529 	while (!feof(idl)) {
530 		gf_fgets(szLine, 4000, idl);
531 		if (strstr(szLine, "implements"))
532 			continue;
533 		len = strlen(szLine);
534 		while (len && strchr(" \n", szLine[len])) {
535 			szLine[len] = 0;
536 			len--;
537 		}
538 		if (!len) continue;
539 
540 		if (!in_ctxbase) {
541 			if (!strstr(szLine, "RenderingContextBase"))
542 				continue;
543 			in_ctxbase = GF_TRUE;
544 			sep = strchr(szLine, ' ');
545 			assert(sep);
546 			curCtx = gf_strdup(sep+1);
547 			start_ctx(curCtx, &ifce_c, &fun_defs);
548 			continue;
549 		} else {
550 			if (strstr(szLine, "};")){
551 				in_ctxbase = GF_FALSE;
552 				end_ctx(ifce_c, fun_defs, curCtx);
553 				ifce_c = NULL;
554 				continue;
555 			}
556 		}
557 
558 		if (strstr(szLine, "/*")) continue;
559 		sep = strstr(szLine, "const ");
560 		if (sep) {
561 			char *cname, *nsep;
562 			sep = strchr(sep+7, ' ');
563 			assert(sep);
564 			sep++;
565 			nsep = strchr(sep, ' ');
566 			assert(nsep);
567 			nsep[0] = 0;
568 			cname = gf_strdup(sep);
569 			sep = strchr(nsep+1, '=');
570 			assert(sep);
571 			sep++;
572 			while (sep[0]==' ') sep++;
573 			nsep = strchr(sep, ';');
574 			assert(nsep);
575 			nsep[0]=0;
576 			put_const(fun_defs, cname, sep);
577 			gf_free(cname);
578 			continue;
579 		}
580 		sep = strstr(szLine, "typedef");
581 		if (sep) continue;
582 
583 		sep = strstr(szLine, "attribute");
584 		if (sep) {
585 			char *nsep;
586 			Bool is_readonly = GF_FALSE;
587 			sep = szLine;
588 			while (sep[0]==' ') sep++;
589 			if (!strncmp(sep, "readonly", 8)) {
590 				is_readonly = GF_TRUE;
591 				sep+=9;
592 			}
593 			sep += 10;
594 			sep = strchr(sep, ' ');
595 			assert(sep);
596 			sep+=1;
597 			nsep = strchr(sep, ';');
598 			assert(nsep);
599 			nsep[0] = 0;
600 			put_prop(fun_defs, curCtx, sep, is_readonly);
601 			continue;
602 		}
603 		/*double type declaration for glXXXifv*/
604 		if (strstr(szLine, ", sequence<"))
605 			continue;
606 		/*double type declaration for bufferData*/
607 		if (strstr(szLine, ", GLsizeiptr size"))
608 			continue;
609 		/*double type declaration for texImage2D and texSubImage2D*/
610 		if (strstr(szLine, ", TexImageSource"))
611 			continue;
612 
613 		sep = strstr(szLine, "(");
614 		/*this is a function*/
615 		if (sep) {
616 			char *nsep, *fname;
617 			sep = strchr(szLine, ']');
618 			if (sep) sep+=1;
619 			else sep = szLine;
620 			while (sep[0] == ' ') sep++;
621 			sep = strchr(sep, ' ');
622 			assert(sep);
623 			sep++;
624 			nsep = strchr(sep, '(');
625 			assert(nsep);
626 			nsep[0] = 0;
627 			fname = gf_strdup(sep);
628 			put_fun(fun_defs, sep);
629 			nsep[0] = '(';
630 
631 			wrap_func(ifce_c, fname, szLine);
632 			gf_free(fname);
633 			continue;
634 		}
635 		fprintf(stderr, "instruction %s not handled\n", szLine);
636 	}
637 
638 
639 	gf_fclose(idl);
640 }
641 
main(int argc,char ** argv)642 int main(int argc, char **argv)
643 {
644 	u32 i=0;
645 	for (i=1; i<argc; i++) {
646 		load_idl(argv[i]);
647 	}
648 
649 	return 0;
650 }
651 
652 
653