source: neercs/trunk/src/interpreter.c @ 4037

Last change on this file since 4037 was 4037, checked in by Jean-Yves Lamoureux, 11 years ago
  • Added error checking on PyObject?->char*
  • Different handling for errors/results
File size: 8.7 KB
Line 
1/*
2 *  neercs        console-based window manager
3 *  Copyright (c) 2009 Jean-Yves Lamoureux <jylam@lnxscene.org>
4 *                All Rights Reserved
5 *
6 *  $Id: interpreter.c 3996 2009-11-22 12:41:45Z jylam $
7 *
8 *  This program is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15#include "config.h"
16
17#ifdef USE_PYTHON
18
19#include <Python.h>
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <unistd.h>
25
26#include <fcntl.h>
27#include <signal.h>
28#include <sys/ioctl.h>
29#include <sys/socket.h>
30#include <sys/time.h>
31#include <time.h>
32#include <sys/wait.h>
33#include <sys/types.h>
34
35#include <caca.h>
36
37#include "neercs.h"
38#include "py_module.h"
39
40static void add_char(struct screen_list *sl, unsigned int c);
41static void del_char(struct screen_list *sl);
42static int python_execute(struct screen_list *sl);
43static char *getStringFromPyObject(PyObject * p);
44static char *getPythonError(void);
45
46static void add_char(struct screen_list *sl, unsigned int c)
47{
48    /* FIXME handle return values */
49    if (!sl->interpreter_props.command)
50    {
51        sl->interpreter_props.size = 1;
52        sl->interpreter_props.x = 0;
53        sl->interpreter_props.command = (char *)malloc(2);
54        sl->interpreter_props.command[0] = 0;
55    }
56    else
57    {
58        sl->interpreter_props.command =
59            (char *)realloc(sl->interpreter_props.command,
60                            sl->interpreter_props.size + 1);
61    }
62    memmove(&sl->interpreter_props.command[sl->interpreter_props.x + 1],
63            &sl->interpreter_props.command[sl->interpreter_props.x],
64            (sl->interpreter_props.size - sl->interpreter_props.x));
65
66    sl->interpreter_props.command[sl->interpreter_props.x] = c;
67    sl->interpreter_props.x++;
68    sl->interpreter_props.size++;
69}
70
71static void del_char(struct screen_list *sl)
72{
73    if (sl->interpreter_props.x < 1)
74        return;
75    if (sl->interpreter_props.size > 1)
76        sl->interpreter_props.size--;
77    else
78        return;
79
80    memcpy(&sl->interpreter_props.command[sl->interpreter_props.x - 1],
81           &sl->interpreter_props.command[sl->interpreter_props.x],
82           sl->interpreter_props.size - sl->interpreter_props.x);
83
84    sl->interpreter_props.command =
85        (char *)realloc(sl->interpreter_props.command,
86                        sl->interpreter_props.size);
87
88    if (sl->interpreter_props.x)
89        sl->interpreter_props.x--;
90    sl->interpreter_props.command[sl->interpreter_props.size - 1] = 0;
91}
92
93
94int python_command_handle_key(struct screen_list *screen_list, unsigned int c)
95{
96    if (c == CACA_KEY_ESCAPE)
97    {
98        if (screen_list->interpreter_props.command)
99        {
100            free(screen_list->interpreter_props.command);
101            screen_list->interpreter_props.command = NULL;
102        }
103        screen_list->python_command = 0;
104        screen_list->changed = 1;
105        return 1;
106    }
107    else if (c == CACA_KEY_LEFT)
108    {
109        if (screen_list->interpreter_props.x)
110            screen_list->interpreter_props.x--;
111    }
112    else if (c == CACA_KEY_RIGHT)
113    {
114        if (screen_list->interpreter_props.x <
115            screen_list->interpreter_props.size - 1)
116            screen_list->interpreter_props.x++;
117    }
118    else if (c == CACA_KEY_RETURN)
119    {
120        python_execute(screen_list);
121    }
122    else
123    {
124        if (c >= ' ' && c < 127)
125            add_char(screen_list, c);
126        else if (c == 8)
127        {
128            del_char(screen_list);
129        }
130        screen_list->changed = 1;
131        return 0;
132    }
133    return 0;
134}
135
136void draw_python_command(struct screen_list *screen_list)
137{
138    int w = 65, h = 6;
139    int x = (caca_get_canvas_width(screen_list->cv) - w) / 2;
140    int y = (caca_get_canvas_height(screen_list->cv) - h) / 2;
141
142    caca_set_color_ansi(screen_list->cv, CACA_BLUE, CACA_BLUE);
143    caca_fill_box(screen_list->cv, x, y, w, h, '#');
144    caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_BLUE);
145    caca_draw_cp437_box(screen_list->cv, x, y, w, h);
146    caca_printf(screen_list->cv, x, y, "Execute command");
147
148    caca_printf(screen_list->cv, x + 2, y + 2,
149                "[___________________________________________________________]");
150
151    if (screen_list->interpreter_props.command)
152    {
153        caca_printf(screen_list->cv, x + 3, y + 2,
154                    "%s", screen_list->interpreter_props.command);
155        caca_gotoxy(screen_list->cv,
156                    x + 3 + screen_list->interpreter_props.x, y + 2);
157    }
158    else
159    {
160        caca_gotoxy(screen_list->cv, x + 3, y + 2);
161    }
162
163    if (screen_list->interpreter_props.output_err)
164    {
165        caca_set_color_ansi(screen_list->cv, CACA_RED, CACA_BLUE);
166        caca_printf(screen_list->cv, x + 2, y + 4,
167                    screen_list->interpreter_props.output_err);
168    }
169    if (screen_list->interpreter_props.output_res)
170    {
171        caca_set_color_ansi(screen_list->cv, CACA_LIGHTGREEN, CACA_BLUE);
172        caca_printf(screen_list->cv, x + 2, y + 4,
173                    screen_list->interpreter_props.output_res);
174    }
175}
176
177/* Actual Python interpreter stuff */
178int python_init(struct screen_list *sl)
179{
180    sl->interpreter_props.output_err = NULL;
181    sl->interpreter_props.output_res = NULL;
182    Py_Initialize();
183   
184    PyInit_neercs();
185   
186    return 0;
187}
188
189int python_close(struct screen_list *sl)
190{
191    if (sl->interpreter_props.output_err)
192        free(sl->interpreter_props.output_err);
193    if (sl->interpreter_props.output_res)
194        free(sl->interpreter_props.output_res);
195    sl->interpreter_props.output_err = NULL;
196    sl->interpreter_props.output_res = NULL;
197    Py_Finalize();
198    return 0;
199}
200
201
202static int python_execute(struct screen_list *sl)
203{
204    if (!sl->interpreter_props.command || sl->interpreter_props.size < 1)
205        return -1;
206    int err = 0;
207
208    debug("py Executing '%s'\n", sl->interpreter_props.command);
209
210    if (sl->interpreter_props.output_err)
211    {
212        free(sl->interpreter_props.output_err);
213        sl->interpreter_props.output_err = NULL;
214    }
215    if (sl->interpreter_props.output_res)
216    {
217        free(sl->interpreter_props.output_res);
218        sl->interpreter_props.output_res = NULL;
219    }
220   
221    PyObject *pModule, *pName, *pFunc, *pValue;
222
223    /* Module from which to call the function */
224    pName = PyUnicode_FromString("neercs");
225    if (!pName)
226    {
227        sl->interpreter_props.output_err = getPythonError();
228        err = 1;
229        debug("py Error 1\n");
230        goto end;
231    }
232
233
234    pModule = PyImport_Import(pName);
235    Py_DECREF(pName);
236    if (pModule != NULL)
237    {
238        pFunc = PyObject_GetAttrString(pModule, sl->interpreter_props.command);
239        if (pFunc && PyCallable_Check(pFunc))
240        {
241            pValue = PyObject_CallObject(pFunc, NULL);
242            if (pValue != NULL) {
243                char *res = getStringFromPyObject(pValue);
244                sl->interpreter_props.output_res = res;
245                debug("py Result of call: %s\n", res);
246                Py_DECREF(pValue);
247                err = 2;
248            }
249            else {
250                Py_DECREF(pFunc);
251                Py_DECREF(pModule);
252                sl->interpreter_props.output_err = getPythonError();
253                err = 1;
254                debug("py Call failed\n");
255                goto end;
256                return 1;
257            }
258        }
259        else
260        {
261            sl->interpreter_props.output_err = getPythonError();
262            err = 1;
263            debug("py Error 2\n");
264            goto end;
265        }
266    }
267    else
268    {
269        sl->interpreter_props.output_err = getPythonError();
270        err = 1;
271        debug("py: %s\n", sl->interpreter_props.output_err);
272        goto end;
273    }
274
275  end:
276   
277    Py_XDECREF(pFunc);
278    Py_DECREF(pModule);
279   
280    if (!err)
281    {
282        free(sl->interpreter_props.command);
283        sl->interpreter_props.command = NULL;
284        sl->interpreter_props.size = 0;
285        sl->interpreter_props.x = 0;
286        sl->python_command = 0;
287    }
288    sl->changed = 1;
289
290    return 0;
291}
292
293
294
295static char *getPythonError(void)
296{
297    char *err;
298    PyObject *type, *value, *traceback;
299    PyErr_Fetch(&type, &value, &traceback);
300
301    char *etype = getStringFromPyObject(type);
302    char *evalue = getStringFromPyObject(value);
303
304    int r = asprintf(&err, "%s", evalue);
305        (void)r;
306    return err;
307}
308
309static char *getStringFromPyObject(PyObject * p)
310{
311    PyObject *str = PyObject_Repr(p);
312    char *err = PyBytes_AS_STRING(PyUnicode_AsEncodedString(str, "utf-8",
313                                                            "Error ~"));
314   
315    char *ret = strdup(err);
316    return ret;
317}
318
319
320#endif
Note: See TracBrowser for help on using the repository browser.