[pypy-commit] creflect default: Adapt the driver's code

arigo noreply at buildbot.pypy.org
Fri Sep 19 15:15:59 CEST 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r49:70c5769aca75
Date: 2014-09-19 15:16 +0200
http://bitbucket.org/cffi/creflect/changeset/70c5769aca75/

Log:	Adapt the driver's code

diff --git a/creflect/cmdline.py b/creflect/cmdline.py
--- a/creflect/cmdline.py
+++ b/creflect/cmdline.py
@@ -1,21 +1,21 @@
 """Usage:
 
-    creflect [options] input.rfl [output.c]
+    creflect [options] input.rfl.c [output.c]
 
-Read the 'input.rfl' file and expand the #creflect...#end sections in it
+Read the 'input.rfl.c' file and expand the CREFLECT sections in it
 into regular C code.  Write the result to 'output.c'.
 
 The default output file name is built from the input file name, by
-replacing the extension with '.c'.  The input and/or output file names
+removing the '.rfl' part.  The input and/or output file names
 can be specified as '-' to read from stdin and/or write to stdout.
 
 Options:
-    -n, --name=NAME   name of the reflection function to create
-                      (default: "_creflect")
-    -m, --main        for debugging, include a main() function that
+    -m, --main      for debugging, include a main() function that
                       prints the recorded reflection information
-    -h, --help        display this help and exit
-    --version         output version information and exit
+    -n, --no-copy   output only the translated creflect sections,
+                      without copying the text around them
+    -h, --help      display this help and exit
+    --version       output version information and exit
 """
 import sys, os, getopt
 
@@ -28,24 +28,24 @@
 
 def main(argv):
     try:
-        options, args = getopt.gnu_getopt(argv, "nmh",
-            ["name", "main", "help", "version"])
+        options, args = getopt.gnu_getopt(argv, "mnh",
+            ["main", "no-copy", "help", "version"])
     except getopt.GetoptError, e:
         return error(e)
     #
     from . import __version__
-    reflection_func_name = "_creflect"
     include_main = False
+    include_text_outside_creflect = True
     for option, value in options:
-        if option == '-n' or option == '--name':
-            reflection_func_name = value
+        if option == '-n' or option == '--no-copy':
+            include_text_outside_creflect = False
         elif option == '-m' or option == '--main':
             include_main = True
         elif option == '-h' or option == '--help':
             print __doc__
             return 0
         elif option == '--version':
-            print 'CReflect %d.%d' % __version__
+            print 'CReflect %s' % __version__
             return 0
     #
     if len(args) == 0:
@@ -58,14 +58,17 @@
     else:
         if inputfile == '-':
             return error("destination file must be specified if input is '-'")
-        outputfile, _ = os.path.splitext(inputfile)
-        outputfile += '.c'
+        i = inputfile.lower().rfind('.rfl')
+        if i < 0:
+            return error("cannot find '.rfl' in the input file name: specify "
+                         "the output file name explicitly")
+        outputfile = inputfile[:i] + inputfile[i+4:]
     if inputfile != '-' and inputfile == outputfile:
         return error("not overwriting the file %r" % (inputfile,))
     #
     from . import driver
-    print >> sys.stderr, 'CReflect %d.%d converting %r to %r...' % (
-        __version__[0], __version__[1], inputfile, outputfile)
+    print >> sys.stderr, 'CReflect %s converting %r to %r...' % (
+        __version__, inputfile, outputfile)
     if inputfile == '-':
         inputf = sys.stdin
     else:
@@ -76,9 +79,10 @@
         outputf = open(outputfile, 'w')
     #
     try:
-        driver.driver(inputf, outputf, reflection_func_name)
+        blocks = driver.copy_file_and_expand(inputf, outputf,
+            include_text_outside_creflect = include_text_outside_creflect)
         if include_main:
-            driver.output_main(outputf)
+            outputf.write(driver.get_debug_code(blocks))
     except driver.CDefError, e:
         print >> sys.stderr, 'FAILED:', e
         return 1
diff --git a/creflect/driver.py b/creflect/driver.py
--- a/creflect/driver.py
+++ b/creflect/driver.py
@@ -1,3 +1,4 @@
+import re
 from codegen import transform_cdef
 from cparser import CSource, CDefError
 
@@ -7,68 +8,91 @@
     return transform_cdef(csource, reflection_func_name)
 
 
-def get_preprocessor_directive(line):
-    if line.startswith('#'):
-        line = line[1:].split()
-        if line:
-            return line[0]
+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()
+
+def get_creflect_comment(line):
+    match = r_comment1.match(line)
+    if match:
+        return match.group(1)
+    if r_comment2.match(line):
+        return END
     return None
 
-def driver(inputf, outputf, reflection_func_name):
-    func_num = 0
+def copy_file_and_expand(inputf, outputf, include_text_outside_creflect=True):
     lineno = 0
+    blocks = []
     while True:
-        # outside '#creflect' sections
+        # outside 'CREFLECT:' sections
         for line in inputf:
             lineno += 1
-            if get_preprocessor_directive(line) == 'creflect':
+            funcname = get_creflect_comment(line)
+            if funcname is not None:
                 break
-            outputf.write(line)
+            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)
         #
-        # inside a '#creflect' section
+        # inside a 'CREFLECT:' section
         csource = []
         first_lineno = lineno + 1
         for line in inputf:
             lineno += 1
-            if get_preprocessor_directive(line) == 'end':
+            end = get_creflect_comment(line)
+            if end is not None:
                 break
             csource.append(line)
         else:
-            raise CDefError("missing '#end' directive after '#creflect'")
-        csource = CSource(''.join(csource), first_lineno)
-        func_num += 1
-        outputf.write("/***** '#creflect' block start, "
-                      "source line %d *****/\n\n" % (first_lineno - 1,))
-        output = transform_cdef(csource, func_num)
+            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,))
+        output = expand_cdef(''.join(csource), funcname, first_lineno)
         outputf.write(output)
-        outputf.write("\n/***** '#creflect' block end, "
-                      "source line %d *****/\n" % (lineno,))
-    if func_num == 0:
-        raise CDefError("no '#creflect' found")
-    outputf.write('''
-/* main entry point for getting the reflection function */
-void %s(void r(char *, void**, int))
-{
-    __CREFLECT_PREV(r);
-}
-''' % (reflection_func_name,))
+        if include_text_outside_creflect:
+            outputf.write("\n/***** CREFLECT block end, "
+                          "source line %d *****/\n" % (lineno,))
+        blocks.append(funcname)
+    #
+    if len(blocks) == 0:
+        raise CDefError("no 'CREFLECT' block found in the input file")
+    return blocks
 
 
-DEBUG_TEMPLATE = r'''
-/* debugging only */
+_DEBUG_TEMPLATE1 = '''
+/***** CREFLECT debug code *****/
 #include <stdio.h>
 #include <stdlib.h>
-#define _CREFLECT_MAIN  %s
 int main(void) {
-    int size = _CREFLECT_MAIN((char *)0);
-    char *result = malloc(size);
-    int err = _CREFLECT_MAIN(result);
-    printf("%%s", result);
-    return (err != 0);
+%s    return 0;
 }
 '''
+_DEBUG_TEMPLATE2 = '''\
+    {
+        int size = %(funcname)s((char *)0);
+        char *result = malloc(size);
+        int err = %(funcname)s(result);
+        printf("%%s", result);
+        free(result);
+        if (err != 0)
+            return 1;
+    }
+'''
 
 def get_debug_code(reflection_func_name):
-    return DEBUG_TEMPLATE % (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),)
diff --git a/test/test_driver.py b/test/test_driver.py
--- a/test/test_driver.py
+++ b/test/test_driver.py
@@ -1,14 +1,11 @@
 import os
 from StringIO import StringIO
-from creflect.driver import expand_cdef, get_debug_code
+from creflect.driver import expand_cdef, get_debug_code, copy_file_and_expand
 from .udir import udir
 
-def compile_and_run(real_code, generated_code, funcname):
+def compile_and_run(code, funcname):
     f = open(str(udir.join(funcname + '.c')), 'w')
-    print >> f, '/* real code */'
-    print >> f, real_code
-    print >> f, '/* generated code */'
-    print >> f, generated_code
+    print >> f, code
     print >> f, get_debug_code(funcname)
     f.close()
     #
@@ -27,47 +24,21 @@
 def test_expand_cdef():
     real_code = "typedef short a_t[42];\n"
     gen = expand_cdef("typedef long a_t[20];", "test_expand_cdef")
-    data = compile_and_run(real_code, gen, "test_expand_cdef")
+    code = '/* real code */\n%s\n/* generated code */\n%s' % (real_code, gen)
+    data = compile_and_run(code, "test_expand_cdef")
     assert data == real_code
 
 
-def XXXtest_driver():
+def test_copy_file_and_expand():
     f = StringIO("""
-typedef unsigned int a_t[5];
+typedef unsigned short a_t[5];
 
-#creflect
-typedef long a_t[20];
-#end
-
-typedef unsigned short b_t;
-# creflect
-typedef int b_t;
-# end
+/* CREFLECT: inspect1() */
+typedef int a_t[20];
+/* CREFLECT: end */
 """)
     g = StringIO()
-    driver.driver(f, g, "foobar_func")
+    copy_file_and_expand(f, g)
     #
-    f = open(str(udir.join('foobar.c')), 'w')
-    f.write(g.getvalue())
-    f.close()
-    #
-    err = os.system(
-        "cd '%s' && gcc -fPIC -Werror -Wall -shared foobar.c -o foobar.so"
-        % (str(udir),))
-    assert err == 0
-    #
-    import ctypes
-    cdll = ctypes.CDLL(str(udir.join('foobar.so')))
-    RFUNC = ctypes.CFUNCTYPE(None,
-                             ctypes.c_char_p,
-                             ctypes.POINTER(ctypes.c_void_p),
-                             ctypes.c_int)
-    seen = []
-    def rfunc(cmd, args, nargs):
-        print cmd
-        seen.append((cmd, [args[i] for i in range(nargs)]))
-    callback = RFUNC(rfunc)
-    cdll.foobar_func(callback)
-    assert seen == [
-        ('=a_t:int?[?]', [4, 5]),
-        ('=b_t:int?', [2])]
+    data = compile_and_run(g.getvalue(), "inspect1")
+    assert data == "typedef unsigned short a_t[5];\n"


More information about the pypy-commit mailing list