Repository: brendanzab/gl-rs (language: rust)

Issue:
Make the generator work properly for GLX



Discussion / hints:
The problem with GLX is this:
- https://github.com/capnm/Khronos_XML_API/blob/31765e5b0d656812d4f700cbedaa09baf10a7c5a/glx.xml#L204
- https://github.com/capnm/Khronos_XML_API/blob/31765e5b0d656812d4f700cbedaa09baf10a7c5a/glx.xml#L1412

`GLX_EXTENSION_NAME` is of type `GLenum` but its value is `"GLX"`.
This is a dirty hack in the khronos API, and I don't really know how we can fix this properly except by adding `if name == "GLX_EXTENSION_NAME" { ... change type ... }`.


Fix patch:
diff --git a/src/gl_generator/lib.rs b/src/gl_generator/lib.rs
index 1ba20e9f..aae2da43 100644
--- a/src/gl_generator/lib.rs
+++ b/src/gl_generator/lib.rs
@@ -34,7 +34,7 @@
 //!
 //! ## Parameters
 //!
-//! * API: Can be `gl`, `wgl`, `glx`, `egl`. `glx` and `egl` are not supported for the moment.
+//! * API: Can be `gl`, `wgl`, `glx`, `egl`.
 //! * Profile: Can be `core` or `compatibility`. `core` will only include all functions supported
 //!    by the requested version it self, while `compatibility` will include all the functions from
 //!    previous versions as well.
@@ -74,7 +74,11 @@
 #[phase(plugin, link)]
 extern crate log;
 
+#[phase(plugin)]
+extern crate regex_macros;
+
 extern crate khronos_api;
+extern crate regex;
 extern crate rustc;
 extern crate syntax;
 
@@ -127,15 +131,9 @@ fn macro_handler(ecx: &mut ExtCtxt, span: Span, token_tree: &[TokenTree]) -> Box
 
     let (ns, source) = match api.as_slice() {
         "gl"  => (Gl, khronos_api::GL_XML),
-        "glx" => {
-            ecx.span_err(span, "glx generation unimplemented");
-            return DummyResult::any(span)
-        },
+        "glx" => (Glx, khronos_api::GLX_XML),
         "wgl" => (Wgl, khronos_api::WGL_XML),
-        "egl" => {
-            ecx.span_err(span, "egl generation unimplemented");
-            return DummyResult::any(span)
-        },
+        "egl" => (Egl, khronos_api::EGL_XML),
         ns => {
             ecx.span_err(span, format!("Unexpected opengl namespace '{}'", ns).as_slice());
             return DummyResult::any(span)
diff --git a/src/gl_generator/static_gen.rs b/src/gl_generator/static_gen.rs
index b7623cce..5ddd1e76 100644
--- a/src/gl_generator/static_gen.rs
+++ b/src/gl_generator/static_gen.rs
@@ -71,17 +71,44 @@ impl<'a, W: Writer> StaticGenerator<'a, W> {
             enm.ident.clone()
         };
 
-        let ty = match ident.as_slice() {
-            "TRUE" | "FALSE" => "types::GLboolean",
-            _ => match enm.ty {
-                Some(ref s) if s.as_slice() == "ull" => "types::GLuint64",
-                _ => "types::GLenum"
+        let ty = {
+            let regex = regex!(r"\(\((\w+)\).+\)");
+
+            if (regex).is_match(enm.value.as_slice()) {
+                // if the value is ((Type)value), then the type is types::Type
+                regex.replace(enm.value.as_slice(), "types::$1")
+
+            } else if enm.value.as_slice().starts_with("\"") {
+                "&'static str".to_string()
+
+            } else {
+                match ident.as_slice() {
+                    "TRUE" | "FALSE" => "types::GLboolean",
+                    _ => match enm.ty {
+                        Some(ref s) if s.as_slice() == "ull" => "types::GLuint64",
+                        _ => "types::GLenum"
+                    }
+                }.to_string()
             }
         };
 
+        let value = {
+            let ref value = enm.value;
+
+            // replacing "((EGLType)0)" by "0 as types::EGLType"
+            let regex = regex!(r"\(\((EGL\w+)\)0\)");
+            let value = regex.replace(value.as_slice(), "0 as types::$1");
+
+            // replacing "((Type)value)" by "value"
+            let regex = regex!(r"\(\(\w+\)(.+)\)");
+            let value = regex.replace(value.as_slice(), "$1");
+
+            value
+        };
+
         self.write_line("#[stable]");
         self.write_line("#[allow(dead_code)]");
-        self.write_line(format!("pub static {}: {} = {};", ident, ty, enm.value).as_slice())
+        self.write_line(format!("pub static {}: {} = {};", ident, ty, value).as_slice())
     }
 
     fn write_enums(&mut self) {
diff --git a/src/gl_generator/struct_gen.rs b/src/gl_generator/struct_gen.rs
index c3fec6d3..86e7a9af 100644
--- a/src/gl_generator/struct_gen.rs
+++ b/src/gl_generator/struct_gen.rs
@@ -71,17 +71,44 @@ impl<'a, W: Writer> StructGenerator<'a, W> {
             enm.ident.clone()
         };
 
-        let ty = match ident.as_slice() {
-            "TRUE" | "FALSE" => "types::GLboolean",
-            _ => match enm.ty {
-                Some(ref s) if s.as_slice() == "ull" => "types::GLuint64",
-                _ => "types::GLenum"
+        let ty = {
+            let regex = regex!(r"\(\((\w+)\).+\)");
+
+            if (regex).is_match(enm.value.as_slice()) {
+                // if the value is ((Type)value), then the type is types::Type
+                regex.replace(enm.value.as_slice(), "types::$1")
+
+            } else if enm.value.as_slice().starts_with("\"") {
+                "&'static str".to_string()
+
+            } else {
+                match ident.as_slice() {
+                    "TRUE" | "FALSE" => "types::GLboolean",
+                    _ => match enm.ty {
+                        Some(ref s) if s.as_slice() == "ull" => "types::GLuint64",
+                        _ => "types::GLenum"
+                    }
+                }.to_string()
             }
         };
 
+        let value = {
+            let ref value = enm.value;
+
+            // replacing "((EGLType)0)" by "0 as types::EGLType"
+            let regex = regex!(r"\(\((EGL\w+)\)0\)");
+            let value = regex.replace(value.as_slice(), "0 as types::$1");
+
+            // replacing "((Type)value)" by "value"
+            let regex = regex!(r"\(\(\w+\)(.+)\)");
+            let value = regex.replace(value.as_slice(), "$1");
+
+            value
+        };
+
         self.write_line("#[stable]");
         self.write_line("#[allow(dead_code)]");
-        self.write_line(format!("pub static {}: {} = {};", ident, ty, enm.value).as_slice())
+        self.write_line(format!("pub static {}: {} = {};", ident, ty, value).as_slice())
     }
 
     fn write_enums(&mut self) {
diff --git a/src/gl_generator/ty.rs b/src/gl_generator/ty.rs
index f03b91bc..5b50c3b9 100644
--- a/src/gl_generator/ty.rs
+++ b/src/gl_generator/ty.rs
@@ -641,16 +641,16 @@ pub static EGL_ALIASES: Src = &[
     // platform-specific aliases are unknown
     // IMPORTANT: these are alises to the same level of the bindings
     // the values must be defined by the user
-    "pub type khronos_utime_nanoseconds_t = super::super::khronos_utime_nanoseconds_t;",
-    "pub type khronos_uint64_t = super::super::khronos_uint64_t;",
-    "pub type khronos_ssize_t = super::super::khronos_ssize_t;",
-    "pub type EGLNativeDisplayType = super::super::EGLNativeDisplayType;",
-    "pub type EGLNativePixmapType = super::super::EGLNativePixmapType;",
-    "pub type EGLNativeWindowType = super::super::EGLNativeWindowType;",
-    "pub type EGLint = super::super::EGLint;",
-    "pub type NativeDisplayType = super::super::NativeDisplayType;",
-    "pub type NativePixmapType = super::super::NativePixmapType;",
-    "pub type NativeWindowType = super::super::NativeWindowType;",
+    "pub type khronos_utime_nanoseconds_t = super::khronos_utime_nanoseconds_t;",
+    "pub type khronos_uint64_t = super::khronos_uint64_t;",
+    "pub type khronos_ssize_t = super::khronos_ssize_t;",
+    "pub type EGLNativeDisplayType = super::EGLNativeDisplayType;",
+    "pub type EGLNativePixmapType = super::EGLNativePixmapType;",
+    "pub type EGLNativeWindowType = super::EGLNativeWindowType;",
+    "pub type EGLint = super::EGLint;",
+    "pub type NativeDisplayType = super::NativeDisplayType;",
+    "pub type NativePixmapType = super::NativePixmapType;",
+    "pub type NativeWindowType = super::NativeWindowType;",
 
     // EGL alises
     "pub type Bool = EGLBoolean;",  // TODO: not sure
@@ -678,8 +678,8 @@ pub static EGL_ALIASES: Src = &[
     "pub type EGLuint64KHR = khronos_uint64_t;",
     "pub type EGLNativeFileDescriptorKHR = super::__gl_imports::libc::c_int;",
     "pub type EGLsizeiANDROID = khronos_ssize_t;",
-    "pub type __eglMustCastToProperFunctionPointerType = extern \"system\" fn(*const super::__gl_imports::libc::c_void, EGLsizeiANDROID, *const super::__gl_imports::libc::c_void, EGLsizeiANDROID) -> ();",
-    "pub type __eglMustCastToProperFunctionPointerType = extern \"system\" fn(*const super::__gl_imports::libc::c_void, EGLsizeiANDROID, *mut super::__gl_imports::libc::c_void, EGLsizeiANDROID) -> EGLsizeiANDROID;",
+    "pub type EGLSetBlobFuncANDROID = extern \"system\" fn(*const super::__gl_imports::libc::c_void, EGLsizeiANDROID, *const super::__gl_imports::libc::c_void, EGLsizeiANDROID) -> ();",
+    "pub type EGLGetBlobFuncANDROID = extern \"system\" fn(*const super::__gl_imports::libc::c_void, EGLsizeiANDROID, *mut super::__gl_imports::libc::c_void, EGLsizeiANDROID) -> EGLsizeiANDROID;",
 
     "#[repr(C)]
     pub struct EGLClientPixmapHI {


Test patch:
diff --git a/tests/egl.rs b/tests/egl.rs
index 32339ca3..e102a049 100644
--- a/tests/egl.rs
+++ b/tests/egl.rs
@@ -1,13 +1,14 @@
 #![feature(phase)]
+#![allow(non_camel_case_types)]
 
 #[phase(plugin)]
 extern crate gl_generator;
 
 extern crate libc;
 
-// TODO: egl not yet implemented
+mod egl_static {
+    use libc;
 
-/*mod egl_static {
     pub type khronos_utime_nanoseconds_t = libc::c_int;
     pub type khronos_uint64_t = libc::uint64_t;
     pub type khronos_ssize_t = libc::ssize_t;
@@ -23,6 +24,8 @@ extern crate libc;
 }
 
 mod egl_struct {
+    use libc;
+
     pub type khronos_utime_nanoseconds_t = libc::c_int;
     pub type khronos_uint64_t = libc::uint64_t;
     pub type khronos_ssize_t = libc::ssize_t;
@@ -35,4 +38,4 @@ mod egl_struct {
     pub type NativeWindowType = *const libc::c_void;
 
     generate_gl_bindings!("egl", "core", "1.5", "struct")
-}*/
+}
diff --git a/tests/glx.rs b/tests/glx.rs
new file mode 100644
index 00000000..43834574
--- /dev/null
+++ b/tests/glx.rs
@@ -0,0 +1,12 @@
+#![feature(phase)]
+
+#[phase(plugin)]
+extern crate gl_generator;
+
+mod glx_static {
+    generate_gl_bindings!("glx", "core", "1.4", "static")
+}
+
+mod glx_struct {
+    generate_gl_bindings!("glx", "core", "1.4", "struct")
+}
diff --git a/tests/no_warning.rs b/tests/no_warning.rs
index 90299cda..78279df0 100644
--- a/tests/no_warning.rs
+++ b/tests/no_warning.rs
@@ -8,6 +8,8 @@
 #[phase(plugin)]
 extern crate gl_generator;
 
+extern crate libc;
+
 mod gl_static {
     generate_gl_bindings!("gl", "core", "4.5", "static")
 }
@@ -16,6 +18,14 @@ mod gl_struct {
     generate_gl_bindings!("gl", "core", "4.5", "struct")
 }
 
+mod glx_static {
+    generate_gl_bindings!("glx", "core", "1.4", "static")
+}
+
+mod glx_struct {
+    generate_gl_bindings!("glx", "core", "1.4", "struct")
+}
+
 mod wgl_static {
     generate_gl_bindings!("wgl", "core", "1.0", "static")
 }
@@ -23,3 +33,43 @@ mod wgl_static {
 mod wgl_struct {
     generate_gl_bindings!("wgl", "core", "1.0", "struct")
 }
+
+mod egl_static {
+    use libc;
+
+    #[allow(non_camel_case_types)]
+    pub type khronos_utime_nanoseconds_t = libc::c_int;
+    #[allow(non_camel_case_types)]
+    pub type khronos_uint64_t = libc::uint64_t;
+    #[allow(non_camel_case_types)]
+    pub type khronos_ssize_t = libc::ssize_t;
+    pub type EGLNativeDisplayType = *const libc::c_void;
+    pub type EGLNativePixmapType = *const libc::c_void;
+    pub type EGLNativeWindowType = *const libc::c_void;
+    pub type EGLint = libc::c_int;
+    pub type NativeDisplayType = *const libc::c_void;
+    pub type NativePixmapType = *const libc::c_void;
+    pub type NativeWindowType = *const libc::c_void;
+
+    generate_gl_bindings!("egl", "core", "1.5", "static")
+}
+
+mod egl_struct {
+    use libc;
+
+    #[allow(non_camel_case_types)]
+    pub type khronos_utime_nanoseconds_t = libc::c_int;
+    #[allow(non_camel_case_types)]
+    pub type khronos_uint64_t = libc::uint64_t;
+    #[allow(non_camel_case_types)]
+    pub type khronos_ssize_t = libc::ssize_t;
+    pub type EGLNativeDisplayType = *const libc::c_void;
+    pub type EGLNativePixmapType = *const libc::c_void;
+    pub type EGLNativeWindowType = *const libc::c_void;
+    pub type EGLint = libc::c_int;
+    pub type NativeDisplayType = *const libc::c_void;
+    pub type NativePixmapType = *const libc::c_void;
+    pub type NativeWindowType = *const libc::c_void;
+
+    generate_gl_bindings!("egl", "core", "1.5", "struct")
+}