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