Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: py_interface.cc | |
4 | // Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
5 | // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
6 | // | |
7 | // The above named program is free software; you can redistribute it and/or | |
8 | // modify it under the terms of the GNU General Public | |
9 | // License version 2 as published by the Free Software Foundation. | |
10 | // | |
11 | // The above named program is distributed in the hope that it will be | |
12 | // useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | // General Public License for more details. | |
15 | // | |
16 | // You should have received a copy of the GNU General Public | |
17 | // License along with this work; if not, write to the Free Software | |
18 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
19 | // | |
20 | // ========== Copyright Header End ============================================ | |
21 | ///////////////////////////////////////////////////////////////////////// | |
22 | // | |
23 | // Copyright (C) 2006 Sun Microsystems, Inc. | |
24 | // All rights reserved. | |
25 | // | |
26 | ||
27 | // py_interface.cc | |
28 | // | |
29 | // implementation file for python user interface | |
30 | ||
31 | /* standard C includes */ | |
32 | ||
33 | ||
34 | // must be before other includes | |
35 | #include "Python.h" | |
36 | #include "abstract.h" | |
37 | ||
38 | #include <stdio.h> | |
39 | #include <thread.h> | |
40 | #include <stdlib.h> | |
41 | #include <string.h> | |
42 | #include <assert.h> | |
43 | #include <stdio.h> | |
44 | #include <unistd.h> | |
45 | #include <ctype.h> | |
46 | #include <libgen.h> | |
47 | ||
48 | /* solaris includes */ | |
49 | #include <signal.h> | |
50 | #include <sys/types.h> | |
51 | #include <sys/exec.h> | |
52 | #include <sys/stat.h> | |
53 | #include <sys/time.h> | |
54 | #include <sys/resource.h> | |
55 | #include <sys/procfs.h> | |
56 | #include <sys/socket.h> | |
57 | #include <netinet/in.h> | |
58 | #include <arpa/inet.h> | |
59 | #include <fcntl.h> | |
60 | #include <netdb.h> | |
61 | #include <stropts.h> | |
62 | ||
63 | #include <dlfcn.h> | |
64 | #include <map> | |
65 | ||
66 | #include "types.h" | |
67 | #include "blaze_globals.h" | |
68 | #include "system.h" | |
69 | #include "mem.h" | |
70 | ||
71 | #include "ui.h" | |
72 | #include "ui_cmd_struct.h" | |
73 | ||
74 | ||
75 | // declarations from ui_cmds.cc | |
76 | extern Ui_cmd ui_cmd_list[]; | |
77 | extern void UI_register_cmd_2 (char * name, char *help, int (*efn)(void *, int, char **), int (*hfn)()); | |
78 | extern void UI_invalidate_cmd (char * name); | |
79 | extern int sstep_cmd (int vcpu_id); | |
80 | extern uint32_t BLAZE_restore_from_checkpoint(); | |
81 | extern int exec_cmd(char *s); | |
82 | ||
83 | // ui does not accept command which length exceeds | |
84 | // max_cmd_length param defined in ui_cmds.cc | |
85 | const int max_cmd_line_size = 2048; | |
86 | ||
87 | ||
88 | // globals | |
89 | static void *py_lib_handle = NULL; | |
90 | char *sam_dir = NULL; | |
91 | ||
92 | // map for new command registered from py module | |
93 | std::map<std::string,PyObject*> *py_cmd_map = NULL; | |
94 | ||
95 | ||
96 | static PyObject * pyCBdelfn = 0; | |
97 | static PyObject * pyCBaddfn = 0; | |
98 | ||
99 | // the externally callable interface function from SAM UI | |
100 | typedef void (*Py_Intf_fn)(const char *); | |
101 | extern Py_Intf_fn addPycmd; | |
102 | extern Py_Intf_fn delPycmd; | |
103 | ||
104 | void delPyUI(const char * n){ | |
105 | PyObject * rslt; | |
106 | PyObject * args = Py_BuildValue((char*)"(s)",n); | |
107 | if(pyCBdelfn) | |
108 | rslt = PyEval_CallObject(pyCBdelfn,args); | |
109 | Py_DECREF(args); | |
110 | ||
111 | if(rslt) | |
112 | Py_DECREF(rslt); | |
113 | else | |
114 | printf("ERROR: could not delete %s\n",n); | |
115 | return; | |
116 | } | |
117 | ||
118 | void addPyUI(const char * n){ | |
119 | Ui_cmd * next = &ui_cmd_list[0]; | |
120 | ||
121 | while(next){ | |
122 | if(!strcmp(n,next->name)) | |
123 | break; | |
124 | next = next->next; | |
125 | } | |
126 | ||
127 | if(!next) | |
128 | assert(0); | |
129 | ||
130 | PyObject * arg = Py_BuildValue((char*)"(ss)",next->help,n); | |
131 | PyObject * rslt = 0; | |
132 | if(pyCBaddfn) | |
133 | rslt = PyEval_CallObject(pyCBaddfn,arg); | |
134 | ||
135 | Py_DECREF(arg); | |
136 | if (rslt) | |
137 | Py_DECREF(rslt); | |
138 | else | |
139 | printf("ERROR: could not add %s\n",n); | |
140 | ||
141 | return; | |
142 | } | |
143 | ||
144 | // send command string to build-in ui interpreter | |
145 | extern "C" PyObject* sam_exec( PyObject* self, PyObject* args ) | |
146 | { | |
147 | char *cmd; | |
148 | char rsp[2]; | |
149 | ||
150 | if (!PyArg_ParseTuple(args,(char*)"s",&cmd)) | |
151 | return 0; | |
152 | ||
153 | // Don't need to mutex exec_cmd() here as python can only be | |
154 | // executed from the ui which means we should already hold | |
155 | // the mutex ui_thread_lock (see ui_cmds.cc) | |
156 | ||
157 | exec_cmd( cmd ); | |
158 | ||
159 | return Py_BuildValue(""); | |
160 | } | |
161 | ||
162 | // add string s2 to s1 | |
163 | static inline char *stradd(char *s1, char *s2, int len=0) | |
164 | { | |
165 | if (!len) len = strlen(s2); | |
166 | strncpy(s1,s2,len); | |
167 | return s1+len; | |
168 | } | |
169 | ||
170 | // send command to py interpreter | |
171 | int exec_py_cmd(void * /* usrdata */, int argc, char **argv) | |
172 | { | |
173 | if (!IN_STOP_STATE (blaze_run_state)) | |
174 | { | |
175 | fprintf(stderr, "ERROR: not in stop state, use stop command first\n"); | |
176 | return 0; | |
177 | } | |
178 | ||
179 | // check if command was registered before | |
180 | PyObject *py_cmd_fn = py_cmd_map->find(argv[0])->second; | |
181 | ||
182 | if(!py_cmd_fn) | |
183 | { | |
184 | fprintf(stderr, "unknown py command %s\n", argv[0]); | |
185 | return 0; | |
186 | } | |
187 | ||
188 | // build arguments | |
189 | PyObject * arg = PyTuple_New(argc); | |
190 | for (int i=0; i<argc; i++) | |
191 | PyTuple_SetItem(arg, i, PyString_FromString(argv[i])); | |
192 | ||
193 | // call py routine | |
194 | PyObject * rslt = PyEval_CallObject(py_cmd_fn,arg); | |
195 | ||
196 | Py_DECREF(arg); | |
197 | if (rslt) | |
198 | Py_DECREF(rslt); | |
199 | ||
200 | return 1; | |
201 | } | |
202 | ||
203 | // register a new py command with ui | |
204 | extern "C" PyObject* sam_register( PyObject* self, PyObject* args ) | |
205 | { | |
206 | char *cmd_name, *help_str; | |
207 | PyObject *py_command_fn; | |
208 | ||
209 | // get command name, help string and a pointer to py command routine | |
210 | if (!PyArg_ParseTuple(args,(char*)"ssO:sam_register",&cmd_name, &help_str,&py_command_fn)) | |
211 | return 0; | |
212 | ||
213 | if (!PyCallable_Check(py_command_fn)) | |
214 | { | |
215 | PyErr_SetString(PyExc_TypeError, "parameter must be callable"); | |
216 | return 0; | |
217 | } | |
218 | ||
219 | Py_XINCREF(py_command_fn); | |
220 | ||
221 | ||
222 | // register new command | |
223 | if (!py_cmd_map) // keep map for new py commands | |
224 | { | |
225 | py_cmd_map = new std::map<std::string,PyObject*>; | |
226 | } | |
227 | if (py_cmd_map->find(cmd_name) == py_cmd_map->end()) | |
228 | { | |
229 | py_cmd_map->insert(std::pair<std::string,PyObject *>(cmd_name,py_command_fn)); | |
230 | UI_register_cmd_2(cmd_name, help_str, exec_py_cmd, NULL); | |
231 | } | |
232 | else | |
233 | { | |
234 | fprintf(stderr, "ERROR: cannot register a new command, %s command exist already \n",cmd_name); | |
235 | } | |
236 | ||
237 | ||
238 | return Py_BuildValue(""); | |
239 | } | |
240 | ||
241 | ||
242 | // unregister ui command | |
243 | extern "C" PyObject* sam_unregister( PyObject* self, PyObject* args ) | |
244 | { | |
245 | char *cmd_name; | |
246 | ||
247 | // get command name | |
248 | if (!PyArg_ParseTuple(args,(char*)"s",&cmd_name)) | |
249 | return 0; | |
250 | ||
251 | if (py_cmd_map && cmd_name) // check new py commands | |
252 | { | |
253 | if (py_cmd_map->erase(cmd_name)) | |
254 | { | |
255 | // unregister the command | |
256 | UI_invalidate_cmd (cmd_name); | |
257 | ui->verbose("command %s, was removed\n", cmd_name); | |
258 | } | |
259 | else | |
260 | { | |
261 | fprintf(stderr, "ERROR: cannot unregister command %s \n", cmd_name); | |
262 | } | |
263 | } | |
264 | ||
265 | return Py_BuildValue(""); | |
266 | } | |
267 | ||
268 | ||
269 | extern "C" uint_t vcpu_get_sys_type(); | |
270 | extern "C" uint_t vcpu_get_sys_size(); | |
271 | extern "C" void* vcpu_get_sys_pntr( uint_t i ); | |
272 | ||
273 | ||
274 | extern "C" PyObject* vcpu_sys_type( PyObject* self, PyObject* args ) | |
275 | { | |
276 | uint_t type; | |
277 | ||
278 | type = vcpu_get_sys_type(); | |
279 | ||
280 | return Py_BuildValue((char*)"i", type); | |
281 | } | |
282 | ||
283 | ||
284 | extern "C" PyObject* vcpu_sys_size( PyObject* self, PyObject* args ) | |
285 | { | |
286 | uint_t size; | |
287 | ||
288 | size = vcpu_get_sys_size(); | |
289 | ||
290 | return Py_BuildValue((char*)"i", size); | |
291 | } | |
292 | ||
293 | ||
294 | ||
295 | extern "C" PyObject* set_cmd_del_fn( PyObject* self, PyObject* args ) | |
296 | { | |
297 | PyObject *result = 0; | |
298 | if(PyArg_ParseTuple(args,"O:set_cmd_del_fn",&pyCBdelfn)){ | |
299 | if (!PyCallable_Check(pyCBdelfn)){ | |
300 | PyErr_SetString(PyExc_TypeError, "parameter must be callable"); | |
301 | return 0; | |
302 | } | |
303 | Py_XINCREF(pyCBdelfn); | |
304 | Py_INCREF(Py_None); | |
305 | result = Py_None; | |
306 | delPycmd = delPyUI; | |
307 | } | |
308 | ||
309 | return result; | |
310 | } | |
311 | ||
312 | extern "C" PyObject* set_cmd_add_fn( PyObject* self, PyObject* args ) | |
313 | { | |
314 | PyObject *result = 0; | |
315 | if(PyArg_ParseTuple(args,"O:set_cmd_add_fn",&pyCBaddfn)){ | |
316 | if (!PyCallable_Check(pyCBaddfn)){ | |
317 | PyErr_SetString(PyExc_TypeError, "parameter must be callable"); | |
318 | return 0; | |
319 | } | |
320 | Py_XINCREF(pyCBaddfn); | |
321 | Py_INCREF(Py_None); | |
322 | result = Py_None; | |
323 | addPycmd = addPyUI; | |
324 | } | |
325 | return result; | |
326 | } | |
327 | ||
328 | ||
329 | extern "C" PyObject* vcpu_sys_pntr( PyObject* self, PyObject* args ) | |
330 | { | |
331 | uint_t i; | |
332 | uint64_t sysp; | |
333 | ||
334 | if (!PyArg_ParseTuple(args,(char*)"i",&i)) | |
335 | return 0; | |
336 | ||
337 | sysp = (uint64_t)vcpu_get_sys_pntr(i); | |
338 | ||
339 | return Py_BuildValue((char*)"l", sysp); | |
340 | } | |
341 | ||
342 | extern "C" PyObject* mem_ld64( PyObject* self, PyObject* args ) | |
343 | { | |
344 | uint64_t addr, data; | |
345 | if (!PyArg_ParseTuple(args,(char*)"l",&addr)) | |
346 | return 0; | |
347 | addr &= ~uint64_t(7); // align | |
348 | data = mm1->ld64(addr); | |
349 | return PyLong_FromUnsignedLong(data); | |
350 | } | |
351 | ||
352 | ||
353 | extern "C" PyObject* mem_st64( PyObject* self, PyObject* args ) | |
354 | { | |
355 | uint64_t addr, data; | |
356 | if (!PyArg_ParseTuple(args,(char*)"ll",&addr,&data)) | |
357 | return 0; | |
358 | addr &= ~uint64_t(7); // align | |
359 | mm1->st64(addr,data); | |
360 | return Py_BuildValue((char*)""); | |
361 | } | |
362 | ||
363 | extern "C" PyObject* mem_ld32( PyObject* self, PyObject* args ) | |
364 | { | |
365 | uint64_t addr, data; | |
366 | if (!PyArg_ParseTuple(args,(char*)"l",&addr)) | |
367 | return 0; | |
368 | addr &= ~uint64_t(3); // align | |
369 | data = mm1->ld32u(addr); | |
370 | return Py_BuildValue((char*)"l",data); | |
371 | } | |
372 | ||
373 | ||
374 | extern "C" PyObject* mem_st32( PyObject* self, PyObject* args ) | |
375 | { | |
376 | uint64_t addr, data; | |
377 | if (!PyArg_ParseTuple(args,(char*)"ll",&addr,&data)) | |
378 | return 0; | |
379 | addr &= ~uint64_t(3); // align | |
380 | mm1->st32(addr,data); | |
381 | return Py_BuildValue((char*)""); | |
382 | } | |
383 | ||
384 | extern "C" PyObject* mem_ld16( PyObject* self, PyObject* args ) | |
385 | { | |
386 | uint64_t addr, data; | |
387 | if (!PyArg_ParseTuple(args,(char*)"l",&addr)) | |
388 | return 0; | |
389 | addr &= ~uint64_t(1); // align | |
390 | data = mm1->ld16u(addr); | |
391 | return Py_BuildValue((char*)"l",data); | |
392 | } | |
393 | ||
394 | ||
395 | extern "C" PyObject* mem_st16( PyObject* self, PyObject* args ) | |
396 | { | |
397 | uint64_t addr, data; | |
398 | if (!PyArg_ParseTuple(args,(char*)"ll",&addr,&data)) | |
399 | return 0; | |
400 | addr &= ~uint64_t(1); // align | |
401 | mm1->st16(addr,data); | |
402 | return Py_BuildValue((char*)""); | |
403 | } | |
404 | ||
405 | extern "C" PyObject* mem_ld8( PyObject* self, PyObject* args ) | |
406 | { | |
407 | uint64_t addr, data; | |
408 | if (!PyArg_ParseTuple(args,(char*)"l",&addr)) | |
409 | return 0; | |
410 | data = mm1->ld8u(addr); | |
411 | return Py_BuildValue((char*)"l",data); | |
412 | } | |
413 | ||
414 | ||
415 | extern "C" PyObject* mem_st8( PyObject* self, PyObject* args ) | |
416 | { | |
417 | uint64_t addr, data; | |
418 | if (!PyArg_ParseTuple(args,(char*)"ll",&addr,&data)) | |
419 | return 0; | |
420 | mm1->st8(addr,data); | |
421 | return Py_BuildValue((char*)""); | |
422 | } | |
423 | ||
424 | extern "C" PyObject* is_stopped( PyObject* self, PyObject* args ) | |
425 | { | |
426 | bool_t stop = SYSTEM_is_stopped(); | |
427 | if (!PyArg_ParseTuple(args,(char*)"")) | |
428 | return 0; | |
429 | return Py_BuildValue((char*)"i",stop); | |
430 | } | |
431 | ||
432 | extern "C" PyObject* is_restored_simulation( PyObject* self, PyObject* args ) | |
433 | { | |
434 | bool_t restore = BLAZE_restore_from_checkpoint(); | |
435 | if (!PyArg_ParseTuple(args,(char*)"")) | |
436 | return 0; | |
437 | return Py_BuildValue((char*)"i",restore); | |
438 | } | |
439 | ||
440 | ||
441 | ||
442 | // methods used to run verification diags | |
443 | extern "C" PyObject* s_step( PyObject* self, PyObject* args ) | |
444 | { | |
445 | uint_t vcpu_id; | |
446 | ||
447 | if (!PyArg_ParseTuple(args,(char*)"i",&vcpu_id)) | |
448 | return 0; | |
449 | ||
450 | uint_t done = sstep_cmd(vcpu_id); | |
451 | ||
452 | return Py_BuildValue((char*)"i",done); | |
453 | } | |
454 | ||
455 | ||
456 | extern "C" PyObject* get_cmd_dict( PyObject* self, PyObject* args ) | |
457 | { | |
458 | const int bufSize = 64 * 1024; // largest possible string - no error checks ahead!!! | |
459 | char buf2[bufSize]; | |
460 | ||
461 | buf2[0] = 0; | |
462 | ||
463 | // create a dictionary of {cmd_name:definition} | |
464 | ||
465 | Ui_cmd * next = &ui_cmd_list[0]; | |
466 | // build the python dictionary | |
467 | PyObject* pyDict = Py_BuildValue((char*)"{s:s}","",""); | |
468 | ||
469 | while(next){ | |
470 | // Force use of _ iso - or . for example | |
471 | char * cmd_name = strdup(next->name); | |
472 | for(int i = 0; i < strlen(cmd_name); i++) | |
473 | if(!isalnum(cmd_name[i])) | |
474 | cmd_name[i]='_'; | |
475 | ||
476 | // special case the SAM break command as it is a python keyword | |
477 | if(!strcmp(cmd_name,"break")){ | |
478 | free((void*)cmd_name); | |
479 | cmd_name = strdup("brk"); | |
480 | } | |
481 | ||
482 | sprintf(buf2,"def sam_%s(args=\"\"):\n",cmd_name); | |
483 | sprintf(buf2 + strlen(buf2)," \"\"\"%s\n \"\"\"\n",next->help); | |
484 | sprintf(buf2 + strlen(buf2)," sam.ui_exec(\"%s \" + args)\n\n",next->name); | |
485 | ||
486 | PyObject* pyStr = Py_BuildValue((char*)"s",buf2); | |
487 | PyMapping_SetItemString(pyDict,cmd_name,pyStr); | |
488 | ||
489 | next = next->next; | |
490 | free((void*)cmd_name); | |
491 | } | |
492 | ||
493 | return pyDict; | |
494 | } | |
495 | ||
496 | ||
497 | static PyMethodDef py_methods [] = | |
498 | { | |
499 | {"ui_exec", sam_exec, METH_VARARGS, "ui_exec <cmd>\n"}, | |
500 | {"ui_register", sam_register, METH_VARARGS, "ui_register (cmd_name, help_str,cmd_func)\n"}, | |
501 | {"ui_unregister", sam_unregister, METH_VARARGS, "ui_unregister (cmd_name)\n"}, | |
502 | {"sys_type", vcpu_sys_type, METH_VARARGS, "vcpu_sys_type <>\n"}, | |
503 | {"sys_size", vcpu_sys_size, METH_VARARGS, "vcpu_sys_size <>\n"}, | |
504 | {"sys_pntr", vcpu_sys_pntr, METH_VARARGS, "vcpu_sys_pntr <i>\n"}, | |
505 | {"mem_ld64", mem_ld64, METH_VARARGS, "mem_ld64(addr)\n"}, | |
506 | {"mem_st64", mem_st64, METH_VARARGS, "mem_st64(addr,data)\n"}, | |
507 | {"mem_ld32", mem_ld32, METH_VARARGS, "mem_ld32(addr)\n"}, | |
508 | {"mem_st32", mem_st32, METH_VARARGS, "mem_st32(addr,data)\n"}, | |
509 | {"mem_ld16", mem_ld16, METH_VARARGS, "mem_ld16(addr)\n"}, | |
510 | {"mem_st16", mem_st16, METH_VARARGS, "mem_st16(addr,data)\n"}, | |
511 | {"mem_ld8", mem_ld8, METH_VARARGS, "mem_ld8(addr)\n"}, | |
512 | {"mem_st8", mem_st8, METH_VARARGS, "mem_st8(addr,data)\n"}, | |
513 | {"is_stopped", is_stopped, METH_VARARGS, "is_stopped()\n"}, | |
514 | {"is_restored_simulation", is_restored_simulation, METH_VARARGS, "is_restored_simulation()\n"}, | |
515 | {"sstep", s_step, METH_VARARGS, "sstep(vcpu_id)\n"}, | |
516 | {"get_cmd_dict", get_cmd_dict, METH_VARARGS, "get_cmd_dict()\n"}, | |
517 | {"set_cmd_del_fn", set_cmd_del_fn, METH_VARARGS, "set_cmd_del_fn(Fn)\n"}, | |
518 | {"set_cmd_add_fn", set_cmd_add_fn, METH_VARARGS, "set_cmd_add_fn(Fn)\n"}, | |
519 | {0, 0, 0, 0} // end of the list | |
520 | }; | |
521 | ||
522 | ||
523 | //////////////////////////////////////////////////////////////// | |
524 | // | |
525 | // py source command | |
526 | // | |
527 | ||
528 | extern int (*py_source)( int argc, char** argv ); | |
529 | ||
530 | int py_source_cmd( int argc, char **argv ) | |
531 | { | |
532 | assert (argc > 0); | |
533 | ||
534 | ui->verbose("loading py module %s...\n", argv[0]); | |
535 | char cmd[max_cmd_line_size]; | |
536 | char *s=cmd; | |
537 | s=stradd(s,"execfile(\""); | |
538 | char* filename = argv[0]; | |
539 | if (strncmp(filename,"$SAM/",5) == 0) | |
540 | { | |
541 | // replace $SAM with dir path | |
542 | char *fname = s; | |
543 | s=stradd(s,sam_dir); | |
544 | s=stradd(s,&filename[4]); | |
545 | filename = fname; | |
546 | } | |
547 | else // file name | |
548 | s=stradd(s,filename); | |
549 | ||
550 | stradd(s,"\0",1); | |
551 | ||
552 | // check if file exist | |
553 | struct stat sfile; | |
554 | if (stat(filename, &sfile)) | |
555 | { | |
556 | fprintf(stderr, "ERROR: %s : No such file or directory\n", filename); | |
557 | return 0; | |
558 | } | |
559 | if ((sfile.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0) | |
560 | { | |
561 | fprintf(stderr, "ERROR: %s : file is not readable \n", filename); | |
562 | return 0; | |
563 | } | |
564 | ||
565 | stradd(s,"\")\0",3); | |
566 | ||
567 | ui->verbose("%s\n", cmd); | |
568 | ||
569 | // set pythons sys.argv to arguments of py_source | |
570 | PySys_SetArgv(argc,argv); | |
571 | PyRun_SimpleString(cmd); | |
572 | ||
573 | return 1; | |
574 | } | |
575 | ||
576 | ///////////////////////////////////////////////////////////////// | |
577 | // | |
578 | // start py user interface | |
579 | // | |
580 | ||
581 | extern void setenv_pythonhome(); // Defined in pythonhome.cc | |
582 | ||
583 | extern "C" int init_py_interface(char* fname, char* modname, void* lib_handle) | |
584 | { | |
585 | if (py_lib_handle != NULL) | |
586 | { | |
587 | ui->error("py lib was loaded already. \n" ); | |
588 | return 0; | |
589 | } | |
590 | ||
591 | py_lib_handle = lib_handle; | |
592 | ||
593 | if(py_lib_handle==NULL) | |
594 | { | |
595 | fprintf (stderr, "cannot obtain py lib handle\n" ); | |
596 | return 0; | |
597 | } | |
598 | ||
599 | extern bool python_UI; | |
600 | python_UI = true; | |
601 | ||
602 | setenv_pythonhome(); | |
603 | ||
604 | // set PYTHONPATH to the known python directories in our | |
605 | // sam releases. | |
606 | ||
607 | const char* env_var = "PYTHONPATH="; | |
608 | const char* pfe_dir = "/pfe"; | |
609 | const char* sam = getexecname(); | |
610 | ||
611 | // Do we expect getexecname() to fail ... geeesh that would be | |
612 | // a disaster if $0 is blank. In case it is just assume sam. | |
613 | ||
614 | if (!sam) sam = "./sam"; | |
615 | ||
616 | // Expect that sam was executed from our release. So expect | |
617 | // $sam_dir/bin/sam and grab $sam_dir. If not then things have | |
618 | // been moved around ... well though. | |
619 | ||
620 | char* origin = dirname(strdup(sam)); | |
621 | sam_dir = dirname(strdup(origin)); | |
622 | ||
623 | char* str; | |
624 | size_t len = strlen(env_var) + strlen(sam_dir) + strlen(pfe_dir); | |
625 | ||
626 | // Before setting PYTHONPATH, check if one is set already and prepend | |
627 | // our paths to it. Otherwise assume PYTHONPATH was '.' | |
628 | ||
629 | char* pythonpath = getenv(env_var); | |
630 | if (pythonpath == 0) | |
631 | pythonpath = "."; | |
632 | ||
633 | str = (char*)malloc(len + strlen(pythonpath) + 2); | |
634 | sprintf(str,"%s%s%s:%s",env_var,sam_dir,pfe_dir,pythonpath); | |
635 | ||
636 | ui->verbose("%s\n",str); | |
637 | putenv(str); | |
638 | ||
639 | if ( !Py_IsInitialized() ) | |
640 | { | |
641 | Py_Initialize(); | |
642 | Py_InitModule((char*)"sam", py_methods); | |
643 | PyEval_InitThreads(); | |
644 | } | |
645 | ||
646 | // The "run-python-file" ui command needs this py_source | |
647 | py_source = py_source_cmd; | |
648 | ||
649 | return 1; | |
650 | } | |
651 | ||
652 | extern "C" int close_py_interface() | |
653 | { | |
654 | // when return back to sam ui don't call this method | |
655 | // during the session otherwise sam ui hangs; | |
656 | if ( Py_IsInitialized() ) | |
657 | { | |
658 | Py_Finalize(); | |
659 | } | |
660 | ||
661 | pyCBdelfn = 0; | |
662 | pyCBaddfn = 0; | |
663 | ||
664 | if(py_cmd_map) | |
665 | { | |
666 | delete py_cmd_map; | |
667 | py_cmd_map = NULL; | |
668 | } | |
669 | ||
670 | return 0; | |
671 | } |