[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