summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Fonseca <jose.r.fonseca@gmail.com>2011-12-01 09:00:50 +0000
committerJosé Fonseca <jose.r.fonseca@gmail.com>2011-12-01 09:01:38 +0000
commit27ced2422a87714c5c2afea10b946cea977a512c (patch)
treee64c565de8411943371561ec81571ad0d8e0f903
parentc7cc272ddcf5dbde3361f2a9a54427a77976da89 (diff)
Minor cleanups and better documentation for the spec generation scripts.
-rw-r--r--common/os_win32.cpp1
-rw-r--r--specs/scripts/README12
-rw-r--r--specs/scripts/README.markdown54
-rwxr-xr-xspecs/scripts/cdecl.py17
-rwxr-xr-xspecs/scripts/gltxt.py63
5 files changed, 118 insertions, 29 deletions
diff --git a/common/os_win32.cpp b/common/os_win32.cpp
index 13dd4f8..0b72433 100644
--- a/common/os_win32.cpp
+++ b/common/os_win32.cpp
@@ -196,6 +196,7 @@ int execute(char * const * args)
&processInformation
)) {
log("error: failed to execute %s\n", arg0);
+ return -1;
}
WaitForSingleObject(processInformation.hProcess, INFINITE);
diff --git a/specs/scripts/README b/specs/scripts/README
deleted file mode 100644
index 6df2a3d..0000000
--- a/specs/scripts/README
+++ /dev/null
@@ -1,12 +0,0 @@
-This directory contains several helper scripts that facilitate the generation
-of the API descriptions from specs and/or header files.
-
-The specs/headers are not expressive enough, which is why we can't just code
-generate everything from them.
-
-For GL the typical procedure is to run
-
- make -B
-
-and then manually crossport new functions / enums to the files in the top dir
-via a side-by-side diff tool, such as gvimdiff.
diff --git a/specs/scripts/README.markdown b/specs/scripts/README.markdown
new file mode 100644
index 0000000..66f9faa
--- /dev/null
+++ b/specs/scripts/README.markdown
@@ -0,0 +1,54 @@
+This directory contains several helper scripts that facilitate the generation
+of the API descriptions from specs and/or header files.
+
+The specs/headers are not expressive enough, which is why we can't just code
+generate everything from them directly. However the scripts in this directory
+usually get 90% of the work done automatically.
+
+
+OpenGL
+======
+
+For OpenGL the typical procedure is to run
+
+ make -B
+
+which will generate several python scripts with prototypes and defines from the
+Khronos `.spec` files:
+
+* glapi.py
+
+* glparams.py
+
+* glxapi.py
+
+* wglapi.py
+
+* wglenum.py
+
+and then manually crossport new functions / enums to the identically named
+files in the parent dir via a side-by-side diff tool, such as gvimdiff.
+
+
+OpenGL ES
+=========
+
+Khronos doesn't provide `.spec` files for OpenGL ES. But the `gltxt.py` script
+can extract and convert prototypes for the `.txt` extension specifications:
+
+ $ ./gltxt.py http://www.khronos.org/registry/gles/extensions/OES/OES_mapbuffer.txt
+ # GL_OES_mapbuffer
+ GlFunction(Void, "glGetBufferPointervOES", [(GLenum, "target"), (GLenum, "pname"), (OpaquePointer(OpaquePointer(Void)), "params")], sideeffects=False),
+ GlFunction(OpaquePointer(Void), "glMapBufferOES", [(GLenum, "target"), (GLenum, "access")]),
+ GlFunction(GLboolean, "glUnmapBufferOES", [(GLenum, "target")]),
+
+
+Generic
+=======
+
+When the domain specific scripts don't work the fallback solution is `cdecl.py`, which can parse most C declarations:
+
+ $ echo 'void *memcpy(void *dest, const void *src, size_t n);' | ./cdecl.py
+ Function(OpaquePointer(Void), "memcpy", [(OpaquePointer(Void), "dest"), (OpaquePointer(Const(Void)), "src"), (size_t, "n")]),
+
+
diff --git a/specs/scripts/cdecl.py b/specs/scripts/cdecl.py
index 613561c..d6ee058 100755
--- a/specs/scripts/cdecl.py
+++ b/specs/scripts/cdecl.py
@@ -34,7 +34,7 @@ import re
import optparse
-class Parser:
+class DeclParser:
token_re = re.compile(r'(\d[x0-9a-fA-F.UL]*|\w+|\s+|.)')
@@ -354,14 +354,15 @@ class Parser:
return type
-
-
-
-
def main():
- parser = Parser()
- for arg in sys.argv[1:]:
- parser.parse(open(arg, 'rt').read())
+ args = sys.argv[1:]
+
+ parser = DeclParser()
+ if args:
+ for arg in args:
+ parser.parse(open(arg, 'rt').read())
+ else:
+ parser.parse(sys.stdin.read())
if __name__ == '__main__':
diff --git a/specs/scripts/gltxt.py b/specs/scripts/gltxt.py
index 7fc62f5..4ce9232 100755
--- a/specs/scripts/gltxt.py
+++ b/specs/scripts/gltxt.py
@@ -31,6 +31,7 @@
import sys
import re
import optparse
+from urllib2 import urlopen
def stderr(x):
@@ -91,6 +92,8 @@ class LineParser:
class TxtParser(LineParser):
+ section_re = re.compile(r'^([A-Z]\w+)( \w+)*$')
+
property_re = re.compile(r'^\w+:')
prototype_re = re.compile(r'^(\w+)\((.*)\)$')
@@ -99,22 +102,51 @@ class TxtParser(LineParser):
self.prefix = prefix
def parse(self):
- line = self.consume()
- while not line.startswith("New Procedures and Functions"):
+ while not self.eof():
+ while not self.eof():
+ line = self.lookahead()
+ if self.eof():
+ return
+ mo = self.section_re.match(line)
+ if mo:
+ break
+ self.consume()
line = self.consume()
- self.parse_procs()
+ self.parse_section(line)
+ print
+
+ def parse_section(self, name):
+ if name == 'Name Strings':
+ self.parse_strings()
+ if name == 'New Procedures and Functions':
+ self.parse_procs()
+
+ def parse_strings(self):
+ while not self.eof():
+ line = self.lookahead()
+ if not line.strip():
+ self.consume()
+ continue
+ if not line.startswith(' '):
+ break
+ self.consume()
+ name = line.strip()
+ print ' # %s' % name
def parse_procs(self):
lines = []
- while True:
- line = self.consume()
+ while not self.eof():
+ line = self.lookahead()
if not line.strip():
+ self.consume()
continue
if not line.startswith(' '):
break
+ self.consume()
lines.append(line.strip())
- if line.endswith(';'):
- self.parse_proc(' '.join(lines))
+ if line[-1] in (';', ')'):
+ prototype = ' '.join(lines)
+ self.parse_proc(prototype)
lines = []
token_re = re.compile(r'(\w+|\s+|.)')
@@ -163,8 +195,21 @@ class TxtParser(LineParser):
def main():
- for arg in sys.argv[1:]:
- parser = TxtParser(open(arg, 'rt'), prefix='gl')
+ optparser = optparse.OptionParser(
+ usage="\n\t%prog [options] [SPEC] ")
+ optparser.add_option(
+ '-p', '--prefix', metavar='STRING',
+ type="string", dest="prefix", default='gl',
+ help="function prefix [default: %default]")
+
+ (options, args) = optparser.parse_args(sys.argv[1:])
+
+ for arg in args:
+ if arg.startswith('http://'):
+ stream = urlopen(arg, 'rt')
+ else:
+ stream = open(arg, 'rt')
+ parser = TxtParser(stream, prefix = options.prefix)
parser.parse()