Embedding to C++: hooking up GNU readline
Alex Farber
farber at cpan.org
Fri Mar 3 17:09:19 EST 2000
Hi,
Alex Farber wrote:
> Now the bad thing is, that I can not say if Py_CompileString() failed
> because of "not enough data" or because of "syntax error". That's why
in tradition of replying to my own messages, here is another method -
using Py_CompileString() and PyEval_EvalCode(). It looks cleaner to me,
because only Python.h have to be included and the _PyParser_Grammar is
not used. I am not sure if there any bugs.
Regards
Alex
/* Q: How to distinguish between "syntax error" and "not enough input"? */
/* A: Py_CompileString() + PyEval_EvalCode() */
/* gcc -I/usr/include/python -I/usr/include/readline -lpython1.5 -lreadline -o compile compile.c */
#include <stdio.h>
#include <readline.h>
#include <Python.h>
int main (int argc, char* argv[])
{
int i, j, done = 0; /* lengths of line, code */
char ps1[] = ">>> ";
char ps2[] = "... ";
char *prompt = ps1;
char *msg, *line, *code = NULL;
PyObject *src, *glb, *loc;
PyObject *exc, *val, *trb, *obj;
Py_Initialize ();
loc = PyDict_New ();
glb = PyDict_New ();
PyDict_SetItemString (glb, "__builtins__", PyEval_GetBuiltins ());
while (!done)
{
line = readline (prompt);
if (NULL == line || /* CTRL-D pressed */
0 == strcmp (line, "quit") ||
0 == strcmp (line, "exit"))
{
done = 1;
}
else
{
i = strlen (line);
if (i > 0)
add_history (line); /* save non-empty lines */
if (NULL == code) /* nothing in code yet */
j = 0;
else
j = strlen (code);
code = realloc (code, i + j + 2);
if (NULL == code) /* out of memory */
exit (1);
if (0 == j) /* code was empty, so */
code[0] = '\0'; /* keep strcat happy */
strcat (code, line); /* append line to code */
code[i + j] = '\n'; /* append '\n' to code */
code[i + j + 1] = '\0';
src = Py_CompileString (code, "<stdin>", Py_file_input); /* or Py_single_input? */
if (NULL != src) /* compiled just fine - */
{
if (ps1 == prompt || /* ">>> " or */
'\n' == code[i + j - 1]) /* "... " and double '\n' */
{
PyEval_EvalCode (src, glb, loc); /* so execute it */
Py_XDECREF(src);
free (code);
code = NULL;
if (PyErr_Occurred ())
PyErr_Print ();
prompt = ps1;
}
}
else if (PyErr_ExceptionMatches (PyExc_SyntaxError)) /* syntax error or E_EOF? */
{
PyErr_Fetch (&exc, &val, &trb); /* clears exception! */
if (PyArg_ParseTuple (val, "sO", &msg, &obj) && /* string + object */
!strcmp (msg, "unexpected EOF while parsing")) /* not enough input */
{
Py_XDECREF (exc);
Py_XDECREF (val);
Py_XDECREF (trb);
prompt = ps2;
}
else /* some other syntax error */
{
PyErr_Restore (exc, val, trb);
PyErr_Print ();
free (code);
code = NULL;
prompt = ps1;
}
}
else /* some non-syntax error */
{
PyErr_Print ();
free (code);
code = NULL;
prompt = ps1;
}
}
free (line);
}
Py_XDECREF(glb);
Py_XDECREF(loc);
Py_Finalize();
exit(0);
}
More information about the Python-list
mailing list