1 /*
2  * pythonopcodes.c
3  *
4  * Copyright (C) 2002 Maurizio Umberto Puxeddu
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this software; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20 
21 #ifdef _DEBUG
22 # undef _DEBUG
23 #  include <Python.h>
24 # define _DEBUG
25 #else
26 # include <Python.h>
27 #endif
28 #include <sysdep.h>
29 #include "csdl.h"
30 #include "pythonopcodes.h"
31 #include "pythonhelper.h"
32 
33 /* HELPERS */
34 
create_private_namespace_if_needed(OPDS * o)35 static CS_NOINLINE void create_private_namespace_if_needed(OPDS *o)
36 {
37     if (GETPYLOCAL(o->insdshead) == 0) {
38       SETPYLOCAL(o->insdshead, PyDict_New());
39 #ifdef DEBUG_PY_NAMESPACES
40       printf("Creating private namespace %p for %p\n",
41              (void*) GETPYLOCAL(o->insdshead), (void*) o->insdshead);
42 #endif
43     }
44 #ifdef DEBUG_PY_NAMESPACES
45     else {
46       printf("Private namespace for %p already allocated at %p\n",
47              (void*) o->insdshead, (void*) GETPYLOCAL(o->insdshead));
48     }
49 #endif
50 }
51 
format_call_statement2(char * statement,char * callable,int argc,MYFLT * argv[],long skip)52 static void format_call_statement2(char *statement, char *callable,
53                                   int argc, MYFLT *argv[], long skip)
54 {
55     int       i;
56 
57     statement[0] = '\0';
58     if (argc-skip > 0) {
59       snprintf(statement, 1024, "%s(%0.6f", callable, *(argv[skip]));
60       for (i = skip+1; i < argc; ++i) {
61         snprintf(statement + strlen(statement), 1024 - strlen(statement),
62                 ", %f", *(argv[i]));
63       }
64       // MKG 2014 Jan 29: No linkage for strlcat in py.dll on MinGW.
65       //strlcat(statement, ")", 1024);
66       strncat(statement, ")", 1023 - strlen(statement)); statement[1023] = '\0';
67     }
68     else {
69       snprintf(statement, 1024, "%s()", callable);
70     }
71 
72 }
73 
format_call_statement(char * statement,char * callable,int argc,MYFLT * argv[],int skip)74 static void format_call_statement(char *statement, char *callable,
75                                   int argc, MYFLT *argv[], int skip)
76 {
77     int       i;
78 
79     statement[0] = '\0';
80     if (argc > 0) {
81       snprintf(statement, 1024, "%s(%0.6f", callable, *(argv[0]));
82       for (i = 1; i < argc - skip; ++i) {
83         snprintf(statement + strlen(statement), 1024-strlen(statement),
84                  ", %f", *(argv[i]));
85       }
86       // MKG 2014 Jan 29: No linkage for strlcat in py.dll on MinGW.
87       //strlcat(statement, ")", 1024);
88       strncat(statement, ")", 1023-strlen(statement)); statement[1023] = '\0';
89     }
90     else {
91       snprintf(statement, 1024, "%s()", callable);
92     }
93 }
94 
95 
96 static PyObject *
run_statement_in_given_context(char * string,PyObject * private)97 run_statement_in_given_context(char *string, PyObject *private)
98 {
99     PyObject  *module, *public;
100 
101     module = PyImport_AddModule("__main__");
102     if (module == NULL) {
103       PyErr_SetString(PyExc_RuntimeError, "couldn't find module __main__");
104       return NULL;
105     }
106     public = PyModule_GetDict(module);
107     return PyRun_String(string, Py_file_input,
108                         public, private ? private : public);
109 }
110 
111 static PyObject *
eval_string_in_given_context(char * string,PyObject * private)112 eval_string_in_given_context(char *string, PyObject *private)
113 {
114     PyObject  *module, *public;
115 
116     module = PyImport_AddModule("__main__");
117     if (module == NULL) {
118       PyErr_SetString(PyExc_RuntimeError, "couldn't find module __main__");
119       return NULL;
120     }
121     public = PyModule_GetDict(module);
122     return PyRun_String(string, Py_eval_input,
123                         public, private ? private : public);
124 }
125 
126 static PyObject *
exec_file_in_given_context(CSOUND * cs,char * filename,PyObject * private)127 exec_file_in_given_context(CSOUND* cs, char *filename, PyObject *private)
128 {
129     PyObject  *result, *module, *public, *pyFileObj;
130     char      *fullpath;
131 
132     fullpath = cs->FindInputFile(cs, filename, NULL);
133 
134     module = PyImport_AddModule("__main__");
135     if (module == NULL) {
136       PyErr_SetString(PyExc_RuntimeError, "couldn't find module __main__");
137       return NULL;
138     }
139     public = PyModule_GetDict(module);
140     pyFileObj = PyFile_FromString(fullpath, "r");
141     if (pyFileObj == NULL) {
142       PyErr_Format(PyExc_RuntimeError,
143                    "couldn't open script file %s", filename);
144       return NULL;
145     }
146     result = PyRun_File(PyFile_AsFile(pyFileObj), fullpath, Py_file_input,
147                     public, private ? private : public);
148     return result;
149 }
150 
151 /* ------ OPCODES ------ */
152 
errMsg(void * p,const char * msg)153 static CS_NOINLINE int errMsg(void *p, const char *msg)
154 {
155     CSOUND      *csound = ((OPDS*) p)->insdshead->csound;
156     const char  *opname = csound->GetOpcodeName(p);
157     csound->ErrorMsg(csound, "%s: %s", opname, msg);
158 
159     return NOTOK;
160 }
161 
pyErrMsg(void * p,const char * msg)162 static CS_NOINLINE int pyErrMsg(void *p, const char *msg)
163 {
164     CSOUND      *csound = ((OPDS*) p)->insdshead->csound;
165     const char  *opname = csound->GetOpcodeName(p);
166     csound->ErrorMsg(csound, "%s: %s", opname, msg);
167     PyErr_Print();
168 
169     return NOTOK;
170 }
171 
pyinit(CSOUND * csound,PYINIT * p)172 static int pyinit(CSOUND *csound, PYINIT *p)
173 {
174     (void) csound;
175     (void) p;
176     int *py_initialize_done;
177 
178     if((py_initialize_done = csound->QueryGlobalVariable(csound,
179                                                          "PY_INITIALIZE")) == NULL){
180     csound->CreateGlobalVariable(csound, "PY_INITIALIZE", sizeof(int));
181     py_initialize_done = csound->QueryGlobalVariable(csound,"PY_INITIALIZE");
182     *py_initialize_done = 0;
183     }
184 
185     if (*py_initialize_done == 0) {
186       Py_Initialize();
187       *py_initialize_done = 1;
188     }
189 
190     PyObject *module = PyImport_AddModule("__main__");
191     if (module == NULL) {
192       PyErr_SetString(PyExc_RuntimeError, "couldn't find module __main__");
193       return NOTOK;
194     }
195     PyObject *public = PyModule_GetDict(module);
196     PyObject *csobj = Py_BuildValue("l", (uintptr_t) csound);
197     PyDict_SetItemString(public, "_CSOUND_", csobj);
198     return OK;
199 }
200 
201 #include "pyx.auto.c"
202 #include "pycall.auto.c"
203 
pycalln_krate(CSOUND * csound,PYCALLN * p)204 static int pycalln_krate(CSOUND *csound, PYCALLN *p)
205 {
206     IGN(csound);
207     int       i;
208     char      command[1024];
209     PyObject  *result;
210 
211 
212     format_call_statement2(command,  p->function->data,
213                           p->INOCOUNT-2, p->args, *p->nresult);
214     result = eval_string_in_given_context(command, 0);
215     if (result != NULL && PyTuple_Check(result) &&
216         PyTuple_Size(result) == (int) *p->nresult) {
217       for (i = 0; i < *p->nresult; ++i)
218         *p->args[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(result, i));
219       Py_DECREF(result);
220     }
221     else {
222       return pyErrMsg(p, "ERROR");
223     }
224     return OK;
225 }
226 
pylcalln_irate(CSOUND * csound,PYCALLN * p)227 static int pylcalln_irate(CSOUND *csound, PYCALLN *p)
228 {
229      IGN(csound);
230     create_private_namespace_if_needed(&p->h);
231     return OK;
232 }
233 
pylcalln_krate(CSOUND * csound,PYCALLN * p)234 static int pylcalln_krate(CSOUND *csound, PYCALLN *p)
235 {
236      IGN(csound);
237     int       i;
238     char      command[1024];
239     PyObject  *result;
240 
241     format_call_statement2(command,  p->function->data,
242                           p->INOCOUNT-2, p->args, *p->nresult);
243     result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead));
244     if (result != NULL && PyTuple_Check(result) &&
245         PyTuple_Size(result) == (int) *p->nresult) {
246       for (i = 0; i < *p->nresult; ++i)
247         *p->args[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(result, i));
248       Py_DECREF(result);
249     }
250     else {
251       return pyErrMsg(p, "ERROR");
252     }
253     return OK;
254 }
255 
pylcallni_irate(CSOUND * csound,PYCALLN * p)256 static int pylcallni_irate(CSOUND *csound, PYCALLN *p)
257 {
258      IGN(csound);
259     int       i;
260     char      command[1024];
261     PyObject  *result;
262 
263     create_private_namespace_if_needed(&p->h);
264     format_call_statement2(command,  p->function->data,
265                           p->INOCOUNT-2, p->args, *p->nresult);
266     result = eval_string_in_given_context(command, GETPYLOCAL(p->h.insdshead));
267     if (result != NULL && PyTuple_Check(result) &&
268         PyTuple_Size(result) == (int) *p->nresult) {
269       for (i = 0; i < *p->nresult; ++i)
270         *p->args[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(result, i));
271       Py_DECREF(result);
272     }
273     else {
274       return pyErrMsg(p, "ERROR");
275     }
276     return OK;
277 }
278 
279   /* PYTHON OPCODES */
280 
281 OENTRY python_localops[] = {
282 
283   /* INITIALIZATION */
284 
285 { "pyinit",   sizeof(PYINIT),   0, 1,  "",     "",     (SUBR)pyinit, NULL      },
286 
287   /* RUN GROUP */
288 { "pyrun",    sizeof(PYRUN),    0, 2,  "",     "S",    NULL, (SUBR)pyrun_krate },
289 { "pyruni",   sizeof(PYRUN),    0, 1,  "",     "S",    (SUBR)pyruni_irate      },
290 { "pylrun",   sizeof(PYRUN),    0, 3,  "",     "S",
291               (SUBR)pylrun_irate, (SUBR)pylrun_krate },
292 { "pylruni",  sizeof(PYRUN),    0, 1,  "",     "S",    (SUBR)pylruni_irate     },
293 
294 { "pyrunt",   sizeof(PYRUNT),   0, 2,  "",     "kS",   NULL, (SUBR)pyrunt_krate },
295 { "pylrunt",  sizeof(PYRUNT),   0, 3,  "",     "kS",
296               (SUBR)pylrunt_irate, (SUBR)pylrunt_krate },
297 
298   /* EXEC GROUP */
299 
300 { "pyexec",   sizeof(PYEXEC),   0, 2,  "",     "S",    NULL, (SUBR)pyexec_krate },
301 { "pyexeci",  sizeof(PYEXEC),   0, 1,  "",     "S",    (SUBR)pyexec_krate      },
302 { "pylexec",  sizeof(PYEXEC),   0, 3,  "",     "S",
303               (SUBR)pylexec_irate, (SUBR)pylexec_krate },
304 { "pylexeci", sizeof(PYEXEC),   0, 1,  "",     "S",    (SUBR)pylexeci_irate    },
305 
306 { "pyexect",  sizeof(PYEXECT),  0, 2,  "",     "kS",   NULL, (SUBR)pyexect_krate },
307 { "pylexect", sizeof(PYEXECT),  0, 3,  "",     "kS",
308               (SUBR)pylexect_irate, (SUBR)pylexect_krate },
309 
310   /* CALL GROUP */
311 
312 { "pycall",   sizeof(PYCALL0),  0, 2,  "" ,    "Sz",   NULL, (SUBR)pycall0_krate },
313 { "pycall1",  sizeof(PYCALL1),  0, 2,  "k",    "Sz",   NULL, (SUBR)pycall1_krate },
314 { "pycall2",  sizeof(PYCALL2),  0, 2,  "kk",   "Sz",   NULL, (SUBR)pycall2_krate },
315 { "pycall3",  sizeof(PYCALL3),  0, 2,  "kkk",  "Sz",   NULL, (SUBR)pycall3_krate },
316 { "pycall4",  sizeof(PYCALL4),  0, 2,  "kkkk", "Sz",   NULL, (SUBR)pycall4_krate },
317 { "pycall5",  sizeof(PYCALL5),  0, 2,  "kkkkk", "Sz",  NULL, (SUBR)pycall5_krate },
318 { "pycall6",  sizeof(PYCALL6),  0, 2,  "kkkkkk", "Sz", NULL, (SUBR)pycall6_krate },
319 { "pycall7",  sizeof(PYCALL7),  0, 2,  "kkkkkkk", "Sz", NULL, (SUBR)pycall7_krate },
320 { "pycall8",  sizeof(PYCALL8), 0,  2,  "kkkkkkkk", "Sz", NULL,(SUBR)pycall8_krate },
321 
322 { "pycalln",  sizeof(PYCALLN),  0, 2,  "",     "Siz",  NULL, (SUBR)pycalln_krate },
323 
324 { "pycallt",  sizeof(PYCALL0T), 0, 2,  "" ,    "kSz",  NULL, (SUBR)pycall0t_krate },
325 { "pycall1t", sizeof(PYCALL1T), 0, 2,  "k",    "kSz",  NULL, (SUBR)pycall1t_krate },
326 { "pycall2t", sizeof(PYCALL2T), 0, 2,  "kk",   "kSz",  NULL, (SUBR)pycall2t_krate },
327 { "pycall3t", sizeof(PYCALL3T),0,  2,  "kkk",  "kSz",  NULL, (SUBR)pycall3t_krate },
328 { "pycall4t", sizeof(PYCALL4T), 0, 2,  "kkkk", "kSz",  NULL, (SUBR)pycall4t_krate },
329 { "pycall5t", sizeof(PYCALL5T), 0, 2,  "kkkkk", "kSz", NULL, (SUBR)pycall5t_krate },
330 { "pycall6t", sizeof(PYCALL6T), 0, 2,  "kkkkkk", "kSz", NULL,(SUBR)pycall6t_krate },
331 { "pycall7t", sizeof(PYCALL7T), 0, 2,  "kkkkkkk","kSz", NULL,(SUBR)pycall7t_krate },
332 { "pycall8t", sizeof(PYCALL8T), 0, 2,  "kkkkkkkk","kSz",NULL,(SUBR)pycall8t_krate },
333 
334 #if 0
335 { "pycallnt", sizeof(PYCALLNT), 0, 2,  "",  "Siz",  NULL, (SUBR)pycallnt_krate },
336 #endif
337 
338 { "pycalli",  sizeof(PYCALL0),  0, 1,  "",         "Sm",   (SUBR)pycall0_krate },
339 { "pycall1i", sizeof(PYCALL1),  0, 1,  "i",        "Sm",   (SUBR)pycall1_krate },
340 { "pycall2i", sizeof(PYCALL2),  0, 1,  "ii",       "Sm",   (SUBR)pycall2_krate },
341 { "pycall3i", sizeof(PYCALL3),  0, 1,  "iii",      "Sm",   (SUBR)pycall3_krate },
342 { "pycall4i", sizeof(PYCALL4),  0, 1,  "iiii",     "Sm",   (SUBR)pycall4_krate },
343 { "pycall5i", sizeof(PYCALL5),  0, 1,  "iiiii",    "Sm",   (SUBR)pycall5_krate },
344 { "pycall6i", sizeof(PYCALL6),  0, 1,  "iiiiii",   "Sm",   (SUBR)pycall6_krate },
345 { "pycall7i", sizeof(PYCALL7),  0, 1,  "iiiiiii",  "Sm",   (SUBR)pycall7_krate },
346 { "pycall8i", sizeof(PYCALL8),  0, 1,  "iiiiiiii", "Sm",   (SUBR)pycall8_krate },
347 
348 { "pycallni", sizeof(PYCALLN),  0, 1,  "",         "Sim",  (SUBR)pycalln_krate },
349 
350 { "pylcall",  sizeof(PYCALL0),  0, 3,  "" ,        "Sz",
351               (SUBR)pylcall0_irate, (SUBR)pylcall0_krate },
352 { "pylcall1", sizeof(PYCALL1),  0, 3,  "k",        "Sz",
353               (SUBR)pylcall1_irate, (SUBR)pylcall1_krate },
354 { "pylcall2", sizeof(PYCALL2),  0, 3,  "kk",       "Sz",
355               (SUBR)pylcall2_irate, (SUBR)pylcall2_krate },
356 { "pylcall3", sizeof(PYCALL3),  0, 3,  "kkk",      "Sz",
357               (SUBR)pylcall3_irate, (SUBR)pylcall3_krate },
358 { "pylcall4", sizeof(PYCALL4),  0, 3,  "kkkk",     "Sz",
359               (SUBR)pylcall4_irate, (SUBR)pylcall4_krate },
360 { "pylcall5", sizeof(PYCALL5),  0, 3,  "kkkkk",    "Sz",
361               (SUBR)pylcall5_irate, (SUBR)pylcall5_krate },
362 { "pylcall6", sizeof(PYCALL6),  0, 3,  "kkkkkk",   "Sz",
363               (SUBR)pylcall6_irate, (SUBR)pylcall6_krate },
364 { "pylcall7", sizeof(PYCALL7),  0, 3,  "kkkkkkk",  "Sz",
365               (SUBR)pylcall7_irate, (SUBR)pylcall7_krate },
366 { "pylcall8", sizeof(PYCALL8),  0, 3,  "kkkkkkkk", "Sz",
367               (SUBR)pylcall8_irate, (SUBR)pylcall8_krate },
368 
369 { "pylcalln", sizeof(PYCALLN),  0, 3,  "",         "Siz",
370               (SUBR)pylcalln_irate, (SUBR)pylcalln_krate },
371 
372 { "pylcallt", sizeof(PYCALL0T), 0, 3,  "" ,        "kSz",
373               (SUBR)pylcall0t_irate, (SUBR)pylcall0t_krate },
374 { "pylcall1t", sizeof(PYCALL1T), 0, 3, "k",        "kSz",
375                (SUBR)pylcall1t_irate, (SUBR)pylcall1t_krate },
376 { "pylcall2t", sizeof(PYCALL2T), 0, 3, "kk",       "kSz",
377                (SUBR)pylcall2t_irate, (SUBR)pylcall2t_krate },
378 { "pylcall3t", sizeof(PYCALL3T), 0, 3, "kkk",      "kSz",
379                (SUBR)pylcall3t_irate, (SUBR)pylcall3t_krate },
380 { "pylcall4t", sizeof(PYCALL4T), 0, 3, "kkkk",     "kSz",
381                (SUBR)pylcall4t_irate, (SUBR)pylcall4t_krate },
382 { "pylcall5t", sizeof(PYCALL5T), 0, 3, "kkkkk",    "kSz",
383                (SUBR)pylcall5t_irate, (SUBR)pylcall5t_krate },
384 { "pylcall6t", sizeof(PYCALL6T), 0, 3, "kkkkkk",   "kSz",
385                (SUBR)pylcall6t_irate, (SUBR)pylcall6t_krate },
386 { "pylcall7t", sizeof(PYCALL7T), 0, 3, "kkkkkkk",  "kSz",
387                (SUBR)pylcall7t_irate, (SUBR)pylcall7t_krate },
388 { "pylcall8t", sizeof(PYCALL8T), 0, 3, "kkkkkkkk", "kSz",
389                (SUBR)pylcall8t_irate, (SUBR)pylcall8t_krate },
390 
391 #if 0
392 { "pylcallnt", sizeof(PYCALLNT), 0, 3, "",         "Siz",
393                (SUBR)pylcalln_irate, (SUBR)pylcallnt_krate },
394 #endif
395 
396 { "pylcalli", sizeof(PYCALL0),  0, 1,  "",         "Sm",   (SUBR)pylcall0i_irate },
397 { "pylcall1i", sizeof(PYCALL1), 0, 1,  "i",        "Sm",   (SUBR)pylcall1i_irate },
398 { "pylcall2i", sizeof(PYCALL2), 0, 1,  "ii",       "Sm",   (SUBR)pylcall2i_irate },
399 { "pylcall3i", sizeof(PYCALL3), 0, 1,  "iii",      "Sm",   (SUBR)pylcall3i_irate },
400 { "pylcall4i", sizeof(PYCALL4), 0, 1,  "iiii",     "Sm",   (SUBR)pylcall4i_irate },
401 { "pylcall5i", sizeof(PYCALL5), 0, 1,  "iiiii",    "Sm",   (SUBR)pylcall5i_irate },
402 { "pylcall6i", sizeof(PYCALL6), 0, 1,  "iiiiii",   "Sm",   (SUBR)pylcall6i_irate },
403 { "pylcall7i", sizeof(PYCALL7), 0, 1,  "iiiiiii",  "Sm",   (SUBR)pylcall7i_irate },
404 { "pylcall8i", sizeof(PYCALL8), 0, 1,  "iiiiiiii", "Sm",   (SUBR)pylcall8i_irate },
405 
406 { "pylcallni", sizeof(PYCALLN), 0, 1,  "",         "Sim",  (SUBR)pylcallni_irate },
407 
408   /* EVAL GROUP */
409 
410 { "pyeval",   sizeof(PYEVAL),   0, 2,  "k",    "S",    NULL, (SUBR)pyeval_krate },
411 { "pyevali",  sizeof(PYEVAL),   0, 1,  "i",    "S",    (SUBR)pyeval_krate },
412 { "pyleval",  sizeof(PYEVAL),   0, 3,  "k",    "S",
413               (SUBR)pyleval_irate, (SUBR)pyleval_krate },
414 { "pylevali", sizeof(PYEVAL),   0, 1,  "i",    "S",    (SUBR)pylevali_irate },
415 
416 { "pyevalt",  sizeof(PYEVALT),  0, 2,  "k",    "S",    NULL, (SUBR)pyevalt_krate },
417 { "pylevalt", sizeof(PYEVALT),  0, 3,  "k",    "S",
418               (SUBR)pylevalt_irate, (SUBR)pylevalt_krate },
419 
420   /* ASSIGN GROUP */
421 
422 { "pyassign", sizeof(PYASSIGN), 0, 2,  "",     "Sz",   NULL, (SUBR)pyassign_krate },
423 { "pyassigni", sizeof(PYASSIGN), 0, 1, "",     "Sz",   (SUBR)pyassign_krate },
424 { "pylassign", sizeof(PYASSIGN), 0, 3, "",     "Sz",
425                (SUBR)pylassign_irate, (SUBR)pylassign_krate },
426 { "pylassigni", sizeof(PYASSIGN), 0, 1, "",    "Sz",   (SUBR)pylassigni_irate },
427 
428 { "pyassignt", sizeof(PYASSIGNT), 0, 2, "",    "Sz", NULL, (SUBR)pyassignt_krate },
429 { "pylassignt", sizeof(PYASSIGNT), 0, 3, "",   "Sz",
430                 (SUBR)pylassignt_irate, (SUBR)pylassignt_krate },
431 
432 };
433 
434 LINKAGE_BUILTIN(python_localops)
435