|
|
@@ -25,15 +25,27 @@
|
|
|
*/
|
|
|
|
|
|
#include "Python.h"
|
|
|
-#include "stdarg.h"
|
|
|
+
|
|
|
+#include <stdarg.h>
|
|
|
#include <stdio.h>
|
|
|
+#include <string.h>
|
|
|
|
|
|
#define likely(x) __builtin_expect((x),1)
|
|
|
#define unlikely(x) __builtin_expect((x),0)
|
|
|
|
|
|
+static PyObject *py_callback_hook_handler_name;
|
|
|
+static PyObject *py_callback_hook_read_after_name;
|
|
|
+static PyObject *py_callback_hook_read_before_name;
|
|
|
+
|
|
|
static PyObject *py_callback_handle_name;
|
|
|
-static PyObject *py_callback_hook_name;
|
|
|
+static PyObject *py_callback_read_name;
|
|
|
|
|
|
+// Construct attribute names (only the first time)
|
|
|
+// TODO: where do we Py_DECREF(handle_name) ??
|
|
|
+#define INIT_ATTR(variable, name) \
|
|
|
+ if (unlikely(!variable)) { \
|
|
|
+ variable = PyString_FromString(name); \
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
|
* Callback function which is invoked by target handlers within the C yyparse()
|
|
|
@@ -66,24 +78,16 @@ PyObject* py_callback(PyObject *parser, char *target, int option, int nargs,
|
|
|
|
|
|
va_end(ap);
|
|
|
|
|
|
- // Construct attribute names (only the first time)
|
|
|
- if (unlikely(!py_callback_handle_name)) {
|
|
|
- py_callback_handle_name = PyString_FromString("_handle");
|
|
|
- // TODO: where do we Py_DECREF(handle_name) ??
|
|
|
- }
|
|
|
-
|
|
|
- if (unlikely(!py_callback_hook_name)) {
|
|
|
- py_callback_hook_name = PyString_FromString("hook_handler");
|
|
|
- // TODO: where do we Py_DECREF(hook_name) ??
|
|
|
- }
|
|
|
+ INIT_ATTR(py_callback_handle_name, "_handle");
|
|
|
+ INIT_ATTR(py_callback_hook_handler_name, "hook_handler");
|
|
|
|
|
|
// Call the handler with the arguments
|
|
|
PyObject *handle = PyObject_GetAttr(parser, py_callback_handle_name);
|
|
|
|
|
|
- if (unlikely(!handle)) return res;
|
|
|
+ if (unlikely(!handle)) return NULL;
|
|
|
|
|
|
PyObject *arglist = Py_BuildValue("(siOO)", target, option, names, values);
|
|
|
- if (unlikely(!arglist)) { Py_DECREF(handle); return res; }
|
|
|
+ if (unlikely(!arglist)) { Py_DECREF(handle); return NULL; }
|
|
|
|
|
|
res = PyObject_CallObject(handle, arglist);
|
|
|
|
|
|
@@ -93,10 +97,10 @@ PyObject* py_callback(PyObject *parser, char *target, int option, int nargs,
|
|
|
if (unlikely(!res)) return res;
|
|
|
|
|
|
// Check if the "hook_handler" callback exists
|
|
|
- if (unlikely(!PyObject_HasAttr(parser, py_callback_hook_name)))
|
|
|
+ if (unlikely(!PyObject_HasAttr(parser, py_callback_hook_handler_name)))
|
|
|
return res;
|
|
|
|
|
|
- handle = PyObject_GetAttr(parser, py_callback_hook_name);
|
|
|
+ handle = PyObject_GetAttr(parser, py_callback_hook_handler_name);
|
|
|
|
|
|
if (unlikely(!handle)) {
|
|
|
Py_DECREF(res);
|
|
|
@@ -114,3 +118,78 @@ PyObject* py_callback(PyObject *parser, char *target, int option, int nargs,
|
|
|
|
|
|
return res;
|
|
|
}
|
|
|
+
|
|
|
+void py_input(PyObject *parser, char *buf, int *result, int max_size)
|
|
|
+{
|
|
|
+ PyObject *handle, *arglist, *res;
|
|
|
+ char *bufstr;
|
|
|
+
|
|
|
+ INIT_ATTR(py_callback_hook_read_after_name, "hook_read_after");
|
|
|
+ INIT_ATTR(py_callback_hook_read_before_name, "hook_read_before");
|
|
|
+ INIT_ATTR(py_callback_read_name, "read");
|
|
|
+
|
|
|
+ // Check if the "hook_READ_BEFORE" callback exists
|
|
|
+ if (unlikely(!PyObject_HasAttr(parser, py_callback_hook_read_before_name)))
|
|
|
+ {
|
|
|
+ handle = PyObject_GetAttr(parser, py_callback_hook_read_before_name);
|
|
|
+ if (unlikely(!handle)) return;
|
|
|
+
|
|
|
+ // Call the "hook_READ_BEFORE" callback
|
|
|
+ arglist = PyTuple_New(0);
|
|
|
+ if (unlikely(!arglist)) { Py_DECREF(handle); return; }
|
|
|
+
|
|
|
+ res = PyObject_CallObject(handle, arglist);
|
|
|
+
|
|
|
+ Py_DECREF(handle);
|
|
|
+ Py_DECREF(arglist);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Read the input string and catch keyboard interrupt exceptions.
|
|
|
+ handle = PyObject_GetAttr(parser, py_callback_read_name);
|
|
|
+ if (unlikely(!handle)) {
|
|
|
+ // TODO: set exception message for missing attribute error
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ arglist = Py_BuildValue("(i)", max_size);
|
|
|
+ if (unlikely(!arglist)) { Py_DECREF(handle); return; }
|
|
|
+
|
|
|
+ res = PyObject_CallObject(handle, arglist);
|
|
|
+
|
|
|
+ Py_DECREF(handle);
|
|
|
+ Py_DECREF(arglist);
|
|
|
+
|
|
|
+ if (unlikely(!res)) { return; }
|
|
|
+
|
|
|
+ // Check if the "hook_read_after" callback exists
|
|
|
+ if (unlikely(!PyObject_HasAttr(parser, py_callback_hook_read_after_name)))
|
|
|
+ goto finish_input;
|
|
|
+
|
|
|
+ handle = PyObject_GetAttr(parser, py_callback_hook_read_after_name);
|
|
|
+ if (unlikely(!handle)) return;
|
|
|
+
|
|
|
+ // Call the "hook_READ_AFTER" callback
|
|
|
+ arglist = Py_BuildValue("(O)", res);
|
|
|
+ if (unlikely(!arglist)) { Py_DECREF(handle); return; }
|
|
|
+
|
|
|
+ res = PyObject_CallObject(handle, arglist);
|
|
|
+
|
|
|
+ Py_DECREF(handle);
|
|
|
+ Py_DECREF(arglist);
|
|
|
+
|
|
|
+ if (unlikely(!res)) return;
|
|
|
+
|
|
|
+finish_input:
|
|
|
+
|
|
|
+ // Copy the read python input string to the buffer
|
|
|
+ bufstr = PyString_AsString(res);
|
|
|
+ *result = strlen(bufstr);
|
|
|
+ memcpy(buf, bufstr, *result);
|
|
|
+
|
|
|
+ // TODO: translate the following code snippet to the Python C aPI
|
|
|
+ //if buflen == 0 and parser.file:
|
|
|
+ // # Marks the Python file object as being closed from Python's point of
|
|
|
+ // # view. This does not close the associated C stream (which is not
|
|
|
+ // # necessary here, otherwise use "os.close(0)").
|
|
|
+ // parser.file.close()
|
|
|
+}
|