Fixed segfault caused by variadic function py_callback.

parent 9c01c2ce
#@+leo-ver=4
#@+node:@file src/pyrex/bison_.pyx
"""
Pyrex-generated portion of pybison
"""
#@+others
#@+node:python
cdef extern from "Python.h":
object PyString_FromStringAndSize(char *, int)
object PyString_FromString(char *)
......@@ -25,8 +22,6 @@ cdef extern from "Python.h":
object PyObject_CallObject(object callable_object, object args)
int PyObject_SetAttrString(object o, char *attr_name, object v)
#@-node:python
#@+node:libdl
# use libdl for now - easy and simple - maybe switch to
# glib or libtool if a keen windows dev sends in a patch
......@@ -43,18 +38,12 @@ cdef extern from "Python.h":
# RTLD_NOLOAD
# RTLD_GLOBAL
#@-node:libdl
#@+node:stdio.h
cdef extern from "stdio.h":
int printf(char *format,...)
#@-node:stdio.h
#@+node:string.h
cdef extern from "string.h":
void *memcpy(void *dest, void *src, long n)
#@-node:string.h
#@+node:bisondynlib.h
cdef extern from "../c/bisondynlib.h":
void *bisondynlib_open(char *filename)
int bisondynlib_close(void *handle)
......@@ -65,62 +54,74 @@ cdef extern from "../c/bisondynlib.h":
#int bisondynlib_build(char *libName, char *includedir)
cdef extern from "stdarg.h":
ctypedef struct va_list:
pass
ctypedef struct fake_type:
pass
void va_start(va_list, void* arg)
void* va_arg(va_list, fake_type)
void va_end(va_list)
fake_type void_type "void *"
fake_type str_type "char *"
#@-node:bisondynlib.h
#@+node:py_callback
# Callback function which is invoked by target handlers
# within the C yyparse() function.
cdef public object py_callback(object parser, char *target, int option, \
int nargs, void *args):
#cdef int *pargs
#pargs = <int *>(&args)
int nargs, ...):
cdef int i
cdef va_list ap
va_start(ap, <void*>nargs)
cdef void *objptr
cdef object obj
cdef int i
cdef object valobj
cdef void *val
cdef char *tokval
cdef char *termname
if parser.verbose:
print 'py_callback: called with nargs=%d' % nargs
#if parser.verbose:
# print 'py_callback: called with nargs=%d' % nargs
try:
names = PyList_New(0)
values = PyList_New(0)
#names = PyList_New(nargs)
#values = PyList_New(nargs)
names = PyList_New(nargs)
values = PyList_New(nargs)
Py_INCREF(names)
Py_INCREF(values)
#for i in range(nargs):
# print 'i:', i
# print 'i=%d' % i , <char*>va_arg(ap, str_type), \
# hex(<int>va_arg(ap, str_type))
# termname = <char *>(pargs[i*2])
# Py_INCREF(termname)
# print 'termname:', termname
# PyList_SetItem(names, i, termname)
for i in range(nargs):
termname = <char*>va_arg(ap, str_type)
Py_INCREF(termname)
PyList_SetItem(names, i, termname)
# val = <void *>(pargs[i*2+1])
# valobj = <object>val
# Py_INCREF(valobj)
# print 'valobj:', valobj
# PyList_SetItem(values, i, valobj)
val = <void *>va_arg(ap, void_type)
valobj = <object>val
Py_INCREF(valobj)
PyList_SetItem(values, i, valobj)
if parser.verbose:
print 'py_callback: calling handler for target "%s"' % target
print 'py_callback: with args:', (target, option, names, values)
#if parser.verbose:
# print 'py_callback: calling handler:', \
# (target, option, names, values)
res = parser._handle(target, option, names, values)
if parser.verbose:
print 'py_callback: handler returned:', res
return res
#if parser.verbose:
# print 'py_callback: handler returned:', res
except:
traceback.print_exc()
return None
res = None
va_end(ap)
return res
#@-node:py_callback
#@+node:py_input
# callback routine for reading input
cdef public void py_input(object parser, char *buf, int *result, int max_size):
cdef char *buf1
......@@ -138,28 +139,22 @@ cdef public void py_input(object parser, char *buf, int *result, int max_size):
print "\npy_input: got %s bytes" % buflen
#@-node:py_input
#@+node:Python imports
import sys, os, sha, re, imp, traceback
import shutil
import distutils.sysconfig
import distutils.ccompiler
#@-node:Python imports
#@+node:Python Globals
reSpaces = re.compile("\\s+")
#unquoted = r"""^|[^'"]%s[^'"]?"""
unquoted = "[^'\"]%s[^'\"]?"
#@-node:Python Globals
#@+node:cdef class ParserEngine
cdef class ParserEngine:
"""
Wraps the interface to the binary bison/lex-generated
parser engine dynamic library.
Wraps the interface to the binary bison/lex-generated parser engine dynamic
library.
You shouldn't need to deal with this at all.
Takes care of:
......@@ -171,61 +166,53 @@ cdef class ParserEngine:
Makes direct calls to the platform-dependent routines in
bisondynlib-[linux|windows].c
"""
#@ @+others
#@+node:C attribs
cdef object parser
cdef object parserHash # hash of current python parser object
cdef object libFilename_py
cdef void *libHandle
# rules hash str embedded in bison parser lib
cdef char *libHash
#@-node:C attribs
#@+node:__init__
def __init__(self, parser, **kw):
"""
Creates a ParserEngine wrapper, and builds/loads the library
Creates a ParserEngine wrapper, and builds/loads the library.
Arguments:
- parser - an instance of a subclass of Parser
In the course of initialisation, we check the library
against the parser object's rules. If the lib doesn't
exist, or can't be loaded, or doesn't match, we build
a new library.
Either way, we end up with a binary parser engine which
matches the current rules in the parser object
In the course of initialisation, we check the library against the
parser object's rules. If the lib doesn't exist, or can't be loaded, or
doesn't match, we build a new library.
Either way, we end up with a binary parser engine which matches the
current rules in the parser object.
"""
self.parser = parser
self.libFilename_py = parser.buildDirectory \
+ parser.bisonEngineLibName \
+ imp.get_suffixes()[0][0]
self.parserHash = hashParserObject(self.parser)
self.openCurrentLib()
#@-node:__init__
#@+node:openCurrentLib
def openCurrentLib(self):
"""
Tests if library exists and is current.
If not, builds a fresh one
Opens the library and imports the parser entry point
Tests if library exists and is current. If not, builds a fresh one.
Opens the library and imports the parser entry point.
"""
parser = self.parser
verbose = parser.verbose
if not os.path.isfile(self.libFilename_py):
self.buildLib()
self.openLib()
# hash our parser spec, compare to hash val stored in lib
libHash = PyString_FromString(self.libHash)
if self.parserHash != libHash:
......@@ -239,19 +226,18 @@ cdef class ParserEngine:
else:
if verbose:
print "Hashes match, no need to rebuild bison engine lib"
#@-node:openCurrentLib
#@+node:openLib
def openLib(self):
"""
Loads the parser engine's dynamic library,
and extracts the following symbols:
Loads the parser engine's dynamic library, and extracts the following
symbols:
- void *do_parse() (runs parser)
- char *parserHash (contains hash of python parser rules)
Returns lib handle, plus pointer to do_parse() function, as long ints
(which later need to be cast to pointers)
Important note -this is totally linux-specific.
If you want windows support, you'll have to modify these funcs to
use glib instead (or create windows equivalents), in which case I'd
......@@ -341,7 +327,7 @@ cdef class ParserEngine:
"extern char *yytext;",
"#define YYSTYPE void*",
#'extern void *py_callback(void *, char *, int, void*, ...);',
'void *(*py_callback)(void *, char *, int, int, void *, ...);',
'void *(*py_callback)(void *, char *, int, int, ...);',
'void (*py_input)(void *, char *, int *, int);',
'void *py_parser;',
'char *rules_hash = "%s";' % self.parserHash,
......
......@@ -243,7 +243,7 @@ class BisonParser(object):
flexCFile1 = "tmp.lex.c" # c output file from lex gets renamed to this
cflags_pre = ['-fPIC'] # = CFLAGS added before all arguments.
cflags_post = ['-O0','-g'] # = CFLAGS added after all arguments.
cflags_post = ['-O3','-g'] # = CFLAGS added after all arguments.
buildDirectory = './' # Directory used to store the generated / compiled files.
debugSymbols = 1 # Add debugging symbols to the binary files.
......@@ -338,7 +338,6 @@ class BisonParser(object):
print '_handle: invoking handler at line %s for "%s"' \
% (hdlrline, targetname)
print handler
self.last = handler(target=targetname, option=option, names=names,
values=values)
#if self.verbose:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment