[pypy-commit] creflect default: Change to group all CREFLECT sections inside a single function

arigo noreply at buildbot.pypy.org
Thu Nov 27 16:29:49 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r94:aee2e5e2ec38
Date: 2014-11-27 16:30 +0100
http://bitbucket.org/cffi/creflect/changeset/aee2e5e2ec38/

Log:	Change to group all CREFLECT sections inside a single function at
	the end, called by default '_creflect_main()'.

diff --git a/creflect/cmdline.py b/creflect/cmdline.py
--- a/creflect/cmdline.py
+++ b/creflect/cmdline.py
@@ -9,7 +9,8 @@
  from stdin and/or write to stdout.
 
 Options:
-    -m, --main      for debugging, include a main() function that
+    -m/--main=NAME  name of main exported function, default '_creflect_main'
+    -d, --debug     for debugging, include a main() function that
                       prints the recorded reflection information
     -n, --no-copy   output only the translated creflect sections,
                       without copying the text around them
@@ -28,13 +29,14 @@
 
 def main(argv):
     try:
-        options, args = getopt.gnu_getopt(argv, "mnih",
-            ["main", "no-copy", "include", "help", "version"])
+        options, args = getopt.gnu_getopt(argv, "m:dnih",
+            ["main=", "debug", "no-copy", "include", "help", "version"])
     except getopt.GetoptError, e:
         return error(e)
     #
     from . import __version__
-    include_main = False
+    main_name = '_creflect_main'
+    include_debug = False
     include_text_outside_creflect = True
     include_includes = False
     for option, value in options:
@@ -44,7 +46,9 @@
             include_text_outside_creflect = False
             include_includes = True
         elif option == '-m' or option == '--main':
-            include_main = True
+            main_name = value
+        elif option == '-d' or option == '--debug':
+            include_debug = True
         elif option == '-h' or option == '--help':
             print __doc__
             return 0
@@ -73,10 +77,10 @@
     try:
         if include_includes:
             outputf.write('#include "%s"\n' % (inputfile,))
-        blocks = driver.copy_file_and_expand(inputf, outputf,
+        driver.copy_file_and_expand(inputf, outputf, main_name,
             include_text_outside_creflect = include_text_outside_creflect)
-        if include_main:
-            outputf.write(driver.get_debug_code(blocks))
+        if include_debug:
+            outputf.write(driver.get_debug_code())
     except driver.CDefError, e:
         print >> sys.stderr, 'FAILED:', e
         return 1
diff --git a/creflect/codegen.py b/creflect/codegen.py
--- a/creflect/codegen.py
+++ b/creflect/codegen.py
@@ -54,7 +54,7 @@
         return d1
 
 
-def transform_cdef(csource, crx_func_name):
+def transform_cdef(csource, crx_func_name, static=False):
     outerblock = CodeBlock(parent=None)
     outerblock.writeline('#include "creflect.h"')
     outerblock.crx_func_name = crx_func_name
@@ -70,7 +70,11 @@
     for d1 in funcblock.crx_field_vars:
         funcblock.writedecl("crx_field_t %s;" % d1)
 
-    outerblock.writeline('void %s(crx_builder_t *cb)' % (crx_func_name,))
+    static_decl = ""
+    if static:
+        static_decl = "static "
+    outerblock.writeline('%svoid %s(crx_builder_t *cb)' % (static_decl,
+                                                           crx_func_name))
     outerblock.write_subblock(funcblock)
     outerblock.writeline('')     # for the final \n below
     return '\n'.join(outerblock.codelines)
diff --git a/creflect/driver.py b/creflect/driver.py
--- a/creflect/driver.py
+++ b/creflect/driver.py
@@ -5,39 +5,35 @@
 
 def expand_cdef(input, reflection_func_name, first_lineno=1):
     csource = CSource(input, first_lineno)
-    return transform_cdef(csource, reflection_func_name)
+    return transform_cdef(csource, reflection_func_name, static=True)
 
 
-r_comment1 = re.compile(r'\s*/[*/]\s*CREFLECT\s*:\s*([A-Za-z_][A-Za-z0-9_]*)'
-                        r'\s*[(]\s*[)]')
-r_comment2 = re.compile(r'\s*/[*/]\s*CREFLECT\s*:\s*[Ee][Nn][Dd]\b')
-END = object()
+r_directive = re.compile(r'\s*/[*/]\s*CREFLECT\s*:\s*([A-Za-z_][A-Za-z0-9_]*)')
 
-def get_creflect_comment(line):
-    match = r_comment1.match(line)
+def get_creflect_directive(line, expected, lineno):
+    match = r_directive.match(line)
     if match:
-        return match.group(1)
-    if r_comment2.match(line):
-        return END
-    return None
+        if match.group(1).lower() != expected:
+            raise CDefError("line %d: 'CREFLECT: %s' expected, "
+                            "got 'CREFLECT: %s'" % (lineno, expected,
+                                                    match.group(1)))
+        return True
+    return False
 
-def copy_file_and_expand(inputf, outputf, include_text_outside_creflect=True):
+def copy_file_and_expand(inputf, outputf, export_func_name='_creflect_main',
+                         include_text_outside_creflect=True):
     lineno = 0
     blocks = []
     while True:
         # outside 'CREFLECT:' sections
         for line in inputf:
             lineno += 1
-            funcname = get_creflect_comment(line)
-            if funcname is not None:
+            if get_creflect_directive(line, 'start', lineno):
                 break
             if include_text_outside_creflect:
                 outputf.write(line)
         else:
             break    # end of file
-        if funcname is END:
-            raise CDefError("line %d: 'CREFLECT: end' without "
-                            "'CREFLECT: funcname()' before" % lineno)
         if not include_text_outside_creflect:
             outputf.write("\n")
         #
@@ -46,46 +42,52 @@
         first_lineno = lineno + 1
         for line in inputf:
             lineno += 1
-            end = get_creflect_comment(line)
-            if end is not None:
+            if get_creflect_directive(line, 'end', lineno):
                 break
             csource.append(line)
         else:
             raise CDefError("missing 'CREFLECT: end' in the input file")
-        if end is not END:
-            raise CDefError("line %d: 'CREFLECT: funcname()' without "
-                            "'CREFLECT: end' before" % lineno)
         #
         if include_text_outside_creflect:
             outputf.write("/***** CREFLECT block start, "
                           "source line %d *****/\n\n" % (first_lineno - 1,))
+        blocknum = len(blocks)
+        funcname = '_creflect_block%d' % blocknum
         output = expand_cdef(''.join(csource), funcname, first_lineno)
         outputf.write(output)
+        outputf.write('#define _CREFLECT_BLOCK%(blocknum)d\n' % {
+            'blocknum': blocknum})
         if include_text_outside_creflect:
             outputf.write("\n/***** CREFLECT block end, "
                           "source line %d *****/\n" % (lineno,))
-        blocks.append(funcname)
+        blocks.append(CALL_TEMPLATE2 % {'funcname': funcname,
+                                        'blocknum': blocknum})
     #
     if len(blocks) == 0:
         raise CDefError("no 'CREFLECT' block found in the input file")
-    return blocks
+    outputf.write(CALL_TEMPLATE1 % (export_func_name, ''.join(blocks)))
 
 
-_DEBUG_TEMPLATE1 = '''
+CALL_TEMPLATE1 = '''
+/***** CREFLECT main entry point *****/
+
+void %s(crx_builder_t *cb) {
+%s}
+'''
+CALL_TEMPLATE2 = '''\
+#ifdef _CREFLECT_BLOCK%(blocknum)d
+    %(funcname)s(cb);
+#endif
+'''
+
+DEBUG_TEMPLATE = '''\
 /***** CREFLECT debug code *****/
 #include "creflect_print.h"
 int main(void) {
-%s    return 0;
+    %s(&maincb);
+    return 0;
 }
 '''
-_DEBUG_TEMPLATE2 = '''\
-    %(funcname)s(&maincb);
-'''
 
-def get_debug_code(reflection_func_name):
-    if not isinstance(reflection_func_name, list):
-        reflection_func_name = [reflection_func_name]
-    parts = []
-    for funcname in reflection_func_name:
-        parts.append(_DEBUG_TEMPLATE2 % {'funcname': funcname})
-    return _DEBUG_TEMPLATE1 % (''.join(parts),)
+def get_debug_code(export_func_name='_creflect_main'):
+    return DEBUG_TEMPLATE % (export_func_name,)
diff --git a/test/test_driver.py b/test/test_driver.py
--- a/test/test_driver.py
+++ b/test/test_driver.py
@@ -3,10 +3,10 @@
 from creflect.driver import expand_cdef, get_debug_code, copy_file_and_expand
 from .udir import udir
 
-def compile_and_run(code, funcname):
+def compile_and_run(code, funcname, export_func_name='_creflect_main'):
     f = open(str(udir.join(funcname + '.c')), 'w')
     print >> f, code
-    print >> f, get_debug_code(funcname)
+    print >> f, get_debug_code(export_func_name)
     f.close()
     #
     from creflect.driver import __file__
@@ -27,7 +27,7 @@
     real_code = "typedef short a_t[42];\n"
     gen = expand_cdef("typedef long a_t[20];", "test_expand_cdef")
     code = '/* real code */\n%s\n/* generated code */\n%s' % (real_code, gen)
-    data = compile_and_run(code, "test_expand_cdef")
+    data = compile_and_run(code, "test_expand_cdef", "test_expand_cdef")
     assert data == "TYPEDEF a_t = ARRAY[42] short\n"
 
 
@@ -35,7 +35,7 @@
     f = StringIO("""
 typedef unsigned short a_t[5];
 
-/* CREFLECT: inspect1() */
+/* CREFLECT: start */
 typedef int a_t[20];
 /* CREFLECT: end */
 """)
@@ -44,3 +44,23 @@
     #
     data = compile_and_run(g.getvalue(), "inspect1")
     assert data == "TYPEDEF a_t = ARRAY[5] unsigned short\n"
+
+def test_copy_file_and_expand_ifdefs():
+    f = StringIO("""
+typedef unsigned short a_t[5];
+
+#ifdef FOOBARBAZ_NONEXISTENT
+// CREFLECT: start
+typedef int nonexistent_t[20];
+// CREFLECT: end
+#else
+// CREFLECT: start
+typedef int a_t[20];
+// CREFLECT: end
+#endif
+""")
+    g = StringIO()
+    copy_file_and_expand(f, g)
+    #
+    data = compile_and_run(g.getvalue(), "inspect2")
+    assert data == "TYPEDEF a_t = ARRAY[5] unsigned short\n"


More information about the pypy-commit mailing list